Author: tuexen
Date: Sun May  6 11:02:53 2012
New Revision: 235075
URL: http://svn.freebsd.org/changeset/base/235075

Log:
  Add support for SCTP_SEND_FAILED_EVENT as required by RFC 6458.
  
  MFC after: 3 days

Modified:
  head/sys/netinet/sctp.h
  head/sys/netinet/sctp_uio.h
  head/sys/netinet/sctp_usrreq.c
  head/sys/netinet/sctputil.c

Modified: head/sys/netinet/sctp.h
==============================================================================
--- head/sys/netinet/sctp.h     Sun May  6 08:31:57 2012        (r235074)
+++ head/sys/netinet/sctp.h     Sun May  6 11:02:53 2012        (r235075)
@@ -526,7 +526,7 @@ struct sctp_error_unrecognized_chunk {
 #define SCTP_PCB_FLAGS_RECVASSOCEVNT     0x00000800
 #define SCTP_PCB_FLAGS_RECVPADDREVNT     0x00001000
 #define SCTP_PCB_FLAGS_RECVPEERERR       0x00002000
-#define SCTP_PCB_FLAGS_RECVSENDFAILEVNT  0x00004000
+#define SCTP_PCB_FLAGS_RECVSENDFAILEVNT  0x00004000    /* deprecated */
 #define SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT  0x00008000
 #define SCTP_PCB_FLAGS_ADAPTATIONEVNT    0x00010000
 #define SCTP_PCB_FLAGS_PDAPIEVNT         0x00020000
@@ -542,6 +542,7 @@ struct sctp_error_unrecognized_chunk {
 #define SCTP_PCB_FLAGS_RECVNXTINFO       0x10000000
 #define SCTP_PCB_FLAGS_ASSOC_RESETEVNT   0x20000000
 #define SCTP_PCB_FLAGS_STREAM_CHANGEEVNT 0x40000000
+#define SCTP_PCB_FLAGS_RECVNSENDFAILEVNT 0x80000000
 
 /*-
  * mobility_features parameters (by micchie).Note

Modified: head/sys/netinet/sctp_uio.h
==============================================================================
--- head/sys/netinet/sctp_uio.h Sun May  6 08:31:57 2012        (r235074)
+++ head/sys/netinet/sctp_uio.h Sun May  6 11:02:53 2012        (r235075)
@@ -343,7 +343,7 @@ struct sctp_remote_error {
        uint8_t sre_data[4];
 };
 
-/* data send failure event */
+/* data send failure event (deprecated) */
 struct sctp_send_failed {
        uint16_t ssf_type;
        uint16_t ssf_flags;
@@ -354,6 +354,17 @@ struct sctp_send_failed {
        uint8_t ssf_data[];
 };
 
+/* data send failure event (not deprecated) */
+struct sctp_send_failed_event {
+       uint16_t ssfe_type;
+       uint16_t ssfe_flags;
+       uint32_t ssfe_length;
+       uint32_t ssfe_error;
+       struct sctp_sndinfo ssfe_info;
+       sctp_assoc_t ssfe_assoc_id;
+       uint8_t ssfe_data[];
+};
+
 /* flag that indicates state of data */
 #define SCTP_DATA_UNSENT       0x0001  /* inqueue never on wire */
 #define SCTP_DATA_SENT         0x0002  /* on wire at failure */
@@ -513,22 +524,22 @@ union sctp_notification {
 };
 
 /* notification types */
-#define SCTP_ASSOC_CHANGE                      0x0001
-#define SCTP_PEER_ADDR_CHANGE                  0x0002
-#define SCTP_REMOTE_ERROR                      0x0003
-#define SCTP_SEND_FAILED                       0x0004
-#define SCTP_SHUTDOWN_EVENT                    0x0005
-#define SCTP_ADAPTATION_INDICATION             0x0006
+#define SCTP_ASSOC_CHANGE                       0x0001
+#define SCTP_PEER_ADDR_CHANGE                   0x0002
+#define SCTP_REMOTE_ERROR                       0x0003
+#define SCTP_SEND_FAILED                        0x0004
+#define SCTP_SHUTDOWN_EVENT                     0x0005
+#define SCTP_ADAPTATION_INDICATION              0x0006
 /* same as above */
-#define SCTP_ADAPTION_INDICATION               0x0006
-#define SCTP_PARTIAL_DELIVERY_EVENT            0x0007
-#define SCTP_AUTHENTICATION_EVENT              0x0008
-#define SCTP_STREAM_RESET_EVENT                        0x0009
-#define SCTP_SENDER_DRY_EVENT                  0x000a
-#define SCTP_NOTIFICATIONS_STOPPED_EVENT       0x000b  /* we don't send this */
-#define SCTP_ASSOC_RESET_EVENT                 0x000c
-#define SCTP_STREAM_CHANGE_EVENT               0x000d
-
+#define SCTP_ADAPTION_INDICATION                0x0006
+#define SCTP_PARTIAL_DELIVERY_EVENT             0x0007
+#define SCTP_AUTHENTICATION_EVENT               0x0008
+#define SCTP_STREAM_RESET_EVENT                 0x0009
+#define SCTP_SENDER_DRY_EVENT                   0x000a
+#define SCTP_NOTIFICATIONS_STOPPED_EVENT        0x000b /* we don't send this */
+#define SCTP_ASSOC_RESET_EVENT                  0x000c
+#define SCTP_STREAM_CHANGE_EVENT                0x000d
+#define SCTP_SEND_FAILED_EVENT                  0x000e
 /*
  * socket option structs
  */

Modified: head/sys/netinet/sctp_usrreq.c
==============================================================================
--- head/sys/netinet/sctp_usrreq.c      Sun May  6 08:31:57 2012        
(r235074)
+++ head/sys/netinet/sctp_usrreq.c      Sun May  6 11:02:53 2012        
(r235075)
@@ -2989,6 +2989,9 @@ flags_out:
                        case SCTP_STREAM_CHANGE_EVENT:
                                event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
                                break;
+                       case SCTP_SEND_FAILED_EVENT:
+                               event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
+                               break;
                        default:
                                event_type = 0;
                                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -5412,6 +5415,9 @@ sctp_setopt(struct socket *so, int optna
                        case SCTP_STREAM_CHANGE_EVENT:
                                event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
                                break;
+                       case SCTP_SEND_FAILED_EVENT:
+                               event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
+                               break;
                        default:
                                event_type = 0;
                                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_USRREQ, EINVAL);

Modified: head/sys/netinet/sctputil.c
==============================================================================
--- head/sys/netinet/sctputil.c Sun May  6 08:31:57 2012        (r235074)
+++ head/sys/netinet/sctputil.c Sun May  6 11:02:53 2012        (r235075)
@@ -2798,39 +2798,66 @@ sctp_notify_send_failed(struct sctp_tcb 
 {
        struct mbuf *m_notify;
        struct sctp_send_failed *ssf;
+       struct sctp_send_failed_event *ssfe;
        struct sctp_queued_to_read *control;
        int length;
 
        if ((stcb == NULL) ||
-           sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_RECVSENDFAILEVNT)) {
+           (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
+           sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
                /* event not enabled */
                return;
        }
-       m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_send_failed), 0, 
M_DONTWAIT, 1, MT_DATA);
+       if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
+               length = sizeof(struct sctp_send_failed_event);
+       } else {
+               length = sizeof(struct sctp_send_failed);
+       }
+       m_notify = sctp_get_mbuf_for_msg(length, 0, M_DONTWAIT, 1, MT_DATA);
        if (m_notify == NULL)
                /* no space left */
                return;
-       length = sizeof(struct sctp_send_failed) + chk->send_size;
+       length += chk->send_size;
        length -= sizeof(struct sctp_data_chunk);
        SCTP_BUF_LEN(m_notify) = 0;
-       ssf = mtod(m_notify, struct sctp_send_failed *);
-       ssf->ssf_type = SCTP_SEND_FAILED;
-       if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
-               ssf->ssf_flags = SCTP_DATA_UNSENT;
-       else
-               ssf->ssf_flags = SCTP_DATA_SENT;
-       ssf->ssf_length = length;
-       ssf->ssf_error = error;
-       /* not exactly what the user sent in, but should be close :) */
-       bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
-       ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
-       ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
-       ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
-       ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
-       ssf->ssf_info.sinfo_context = chk->rec.data.context;
-       ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
-       ssf->ssf_assoc_id = sctp_get_associd(stcb);
-
+       if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
+               ssfe = mtod(m_notify, struct sctp_send_failed_event *);
+               ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
+               if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
+                       ssfe->ssfe_flags = SCTP_DATA_UNSENT;
+               else
+                       ssfe->ssfe_flags = SCTP_DATA_SENT;
+               ssfe->ssfe_length = length;
+               ssfe->ssfe_error = error;
+               /* not exactly what the user sent in, but should be close :) */
+               bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info));
+               ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number;
+               ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags;
+               ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype;
+               ssfe->ssfe_info.snd_context = chk->rec.data.context;
+               ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
+               ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
+               SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
+       } else {
+               ssf = mtod(m_notify, struct sctp_send_failed *);
+               ssf->ssf_type = SCTP_SEND_FAILED;
+               if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
+                       ssf->ssf_flags = SCTP_DATA_UNSENT;
+               else
+                       ssf->ssf_flags = SCTP_DATA_SENT;
+               ssf->ssf_length = length;
+               ssf->ssf_error = error;
+               /* not exactly what the user sent in, but should be close :) */
+               bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
+               ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
+               ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
+               ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
+               ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
+               ssf->ssf_info.sinfo_context = chk->rec.data.context;
+               ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
+               ssf->ssf_assoc_id = sctp_get_associd(stcb);
+               SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
+       }
        if (chk->data) {
                /*
                 * trim off the sctp chunk header(it should be there)
@@ -2842,7 +2869,6 @@ sctp_notify_send_failed(struct sctp_tcb 
                }
        }
        SCTP_BUF_NEXT(m_notify) = chk->data;
-       SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
        /* Steal off the mbuf */
        chk->data = NULL;
        /*
@@ -2882,43 +2908,75 @@ sctp_notify_send_failed2(struct sctp_tcb
 {
        struct mbuf *m_notify;
        struct sctp_send_failed *ssf;
+       struct sctp_send_failed_event *ssfe;
        struct sctp_queued_to_read *control;
        int length;
 
        if ((stcb == NULL) ||
-           sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_RECVSENDFAILEVNT)) {
+           (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
+           sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
                /* event not enabled */
                return;
        }
-       length = sizeof(struct sctp_send_failed) + sp->length;
-       m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_send_failed), 0, 
M_DONTWAIT, 1, MT_DATA);
-       if (m_notify == NULL)
+       if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
+               length = sizeof(struct sctp_send_failed_event);
+       } else {
+               length = sizeof(struct sctp_send_failed);
+       }
+       m_notify = sctp_get_mbuf_for_msg(length, 0, M_DONTWAIT, 1, MT_DATA);
+       if (m_notify == NULL) {
                /* no space left */
                return;
+       }
+       length += sp->length;
        SCTP_BUF_LEN(m_notify) = 0;
-       ssf = mtod(m_notify, struct sctp_send_failed *);
-       ssf->ssf_type = SCTP_SEND_FAILED;
-       if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
-               ssf->ssf_flags = SCTP_DATA_UNSENT;
-       else
-               ssf->ssf_flags = SCTP_DATA_SENT;
-       ssf->ssf_length = length;
-       ssf->ssf_error = error;
-       /* not exactly what the user sent in, but should be close :) */
-       bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
-       ssf->ssf_info.sinfo_stream = sp->stream;
-       ssf->ssf_info.sinfo_ssn = sp->strseq;
-       if (sp->some_taken) {
-               ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG;
+       if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
+               ssfe = mtod(m_notify, struct sctp_send_failed_event *);
+               ssfe->ssfe_type = SCTP_SEND_FAILED;
+               if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
+                       ssfe->ssfe_flags = SCTP_DATA_UNSENT;
+               else
+                       ssfe->ssfe_flags = SCTP_DATA_SENT;
+               ssfe->ssfe_length = length;
+               ssfe->ssfe_error = error;
+               /* not exactly what the user sent in, but should be close :) */
+               bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info));
+               ssfe->ssfe_info.snd_sid = sp->stream;
+               if (sp->some_taken) {
+                       ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG;
+               } else {
+                       ssfe->ssfe_info.snd_flags = SCTP_DATA_NOT_FRAG;
+               }
+               ssfe->ssfe_info.snd_ppid = sp->ppid;
+               ssfe->ssfe_info.snd_context = sp->context;
+               ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
+               ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
+               SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
        } else {
-               ssf->ssf_info.sinfo_flags = SCTP_DATA_NOT_FRAG;
+               ssf = mtod(m_notify, struct sctp_send_failed *);
+               ssf->ssf_type = SCTP_SEND_FAILED;
+               if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
+                       ssf->ssf_flags = SCTP_DATA_UNSENT;
+               else
+                       ssf->ssf_flags = SCTP_DATA_SENT;
+               ssf->ssf_length = length;
+               ssf->ssf_error = error;
+               /* not exactly what the user sent in, but should be close :) */
+               bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
+               ssf->ssf_info.sinfo_stream = sp->stream;
+               ssf->ssf_info.sinfo_ssn = sp->strseq;
+               if (sp->some_taken) {
+                       ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG;
+               } else {
+                       ssf->ssf_info.sinfo_flags = SCTP_DATA_NOT_FRAG;
+               }
+               ssf->ssf_info.sinfo_ppid = sp->ppid;
+               ssf->ssf_info.sinfo_context = sp->context;
+               ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
+               ssf->ssf_assoc_id = sctp_get_associd(stcb);
+               SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
        }
-       ssf->ssf_info.sinfo_ppid = sp->ppid;
-       ssf->ssf_info.sinfo_context = sp->context;
-       ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
-       ssf->ssf_assoc_id = sctp_get_associd(stcb);
        SCTP_BUF_NEXT(m_notify) = sp->data;
-       SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
 
        /* Steal off the mbuf */
        sp->data = NULL;
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to