Author: tuexen
Date: Fri Aug 22 20:22:12 2014
New Revision: 270362
URL: http://svnweb.freebsd.org/changeset/base/270362

Log:
  MFC r269858:
  
  Add support for the SCTP_AUTH_SUPPORTED and SCTP_ASCONF_SUPPORTED
  socket options. Add also a sysctl to control the support of ASCONF.

Modified:
  stable/10/lib/libc/net/sctp_sys_calls.c
  stable/10/sys/netinet/sctp.h
  stable/10/sys/netinet/sctp_asconf.c
  stable/10/sys/netinet/sctp_auth.c
  stable/10/sys/netinet/sctp_auth.h
  stable/10/sys/netinet/sctp_input.c
  stable/10/sys/netinet/sctp_output.c
  stable/10/sys/netinet/sctp_pcb.c
  stable/10/sys/netinet/sctp_pcb.h
  stable/10/sys/netinet/sctp_peeloff.c
  stable/10/sys/netinet/sctp_structs.h
  stable/10/sys/netinet/sctp_sysctl.c
  stable/10/sys/netinet/sctp_sysctl.h
  stable/10/sys/netinet/sctp_usrreq.c
  stable/10/sys/netinet/sctputil.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/net/sctp_sys_calls.c
==============================================================================
--- stable/10/lib/libc/net/sctp_sys_calls.c     Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/lib/libc/net/sctp_sys_calls.c     Fri Aug 22 20:22:12 2014        
(r270362)
@@ -356,6 +356,12 @@ sctp_opt_info(int sd, sctp_assoc_t id, i
        case SCTP_PR_SUPPORTED:
                ((struct sctp_assoc_value *)arg)->assoc_id = id;
                break;
+       case SCTP_AUTH_SUPPORTED:
+               ((struct sctp_assoc_value *)arg)->assoc_id = id;
+               break;
+       case SCTP_ASCONF_SUPPORTED:
+               ((struct sctp_assoc_value *)arg)->assoc_id = id;
+               break;
        case SCTP_RECONFIG_SUPPORTED:
                ((struct sctp_assoc_value *)arg)->assoc_id = id;
                break;
@@ -590,6 +596,7 @@ sctp_sendmsg(int s,
        cmsg->cmsg_type = SCTP_SNDRCV;
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
        sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+       memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo));
        sinfo->sinfo_stream = stream_no;
        sinfo->sinfo_ssn = 0;
        sinfo->sinfo_flags = flags;

Modified: stable/10/sys/netinet/sctp.h
==============================================================================
--- stable/10/sys/netinet/sctp.h        Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp.h        Fri Aug 22 20:22:12 2014        
(r270362)
@@ -123,9 +123,11 @@ struct sctp_paramhdr {
 #define SCTP_REMOTE_UDP_ENCAPS_PORT     0x00000024
 #define SCTP_ECN_SUPPORTED              0x00000025
 #define SCTP_PR_SUPPORTED               0x00000026
-#define SCTP_NRSACK_SUPPORTED           0x00000027
-#define SCTP_PKTDROP_SUPPORTED          0x00000028
+#define SCTP_AUTH_SUPPORTED             0x00000027
+#define SCTP_ASCONF_SUPPORTED           0x00000028
 #define SCTP_RECONFIG_SUPPORTED         0x00000029
+#define SCTP_NRSACK_SUPPORTED           0x00000030
+#define SCTP_PKTDROP_SUPPORTED          0x00000031
 
 /*
  * read-only options

Modified: stable/10/sys/netinet/sctp_asconf.c
==============================================================================
--- stable/10/sys/netinet/sctp_asconf.c Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_asconf.c Fri Aug 22 20:22:12 2014        
(r270362)
@@ -724,13 +724,11 @@ sctp_handle_asconf(struct mbuf *m, unsig
                }
                switch (param_type) {
                case SCTP_ADD_IP_ADDRESS:
-                       asoc->peer_supports_asconf = 1;
                        m_result = sctp_process_asconf_add_ip(src, aph, stcb,
                            (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error);
                        cnt++;
                        break;
                case SCTP_DEL_IP_ADDRESS:
-                       asoc->peer_supports_asconf = 1;
                        m_result = sctp_process_asconf_delete_ip(src, aph, stcb,
                            error);
                        break;
@@ -738,7 +736,6 @@ sctp_handle_asconf(struct mbuf *m, unsig
                        /* not valid in an ASCONF chunk */
                        break;
                case SCTP_SET_PRIM_ADDR:
-                       asoc->peer_supports_asconf = 1;
                        m_result = sctp_process_asconf_set_primary(src, aph,
                            stcb, error);
                        break;
@@ -930,8 +927,6 @@ sctp_addr_match(struct sctp_paramhdr *ph
 void
 sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
 {
-       /* mark peer as ASCONF incapable */
-       stcb->asoc.peer_supports_asconf = 0;
        /*
         * clear out any existing asconfs going out
         */
@@ -1340,7 +1335,7 @@ sctp_asconf_queue_add(struct sctp_tcb *s
        int pending_delete_queued = 0;
 
        /* see if peer supports ASCONF */
-       if (stcb->asoc.peer_supports_asconf == 0) {
+       if (stcb->asoc.asconf_supported == 0) {
                return (-1);
        }
        /*
@@ -1430,7 +1425,7 @@ sctp_asconf_queue_sa_delete(struct sctp_
                return (-1);
        }
        /* see if peer supports ASCONF */
-       if (stcb->asoc.peer_supports_asconf == 0) {
+       if (stcb->asoc.asconf_supported == 0) {
                return (-1);
        }
        /* make sure the request isn't already in the queue */
@@ -1550,7 +1545,7 @@ sctp_asconf_find_param(struct sctp_tcb *
  * notifications based on the error response
  */
 static void
-sctp_asconf_process_error(struct sctp_tcb *stcb,
+sctp_asconf_process_error(struct sctp_tcb *stcb SCTP_UNUSED,
     struct sctp_asconf_paramhdr *aph)
 {
        struct sctp_error_cause *eh;
@@ -1588,10 +1583,7 @@ sctp_asconf_process_error(struct sctp_tc
                switch (param_type) {
                case SCTP_ADD_IP_ADDRESS:
                case SCTP_DEL_IP_ADDRESS:
-                       stcb->asoc.peer_supports_asconf = 0;
-                       break;
                case SCTP_SET_PRIM_ADDR:
-                       stcb->asoc.peer_supports_asconf = 0;
                        break;
                default:
                        break;
@@ -1627,8 +1619,6 @@ sctp_asconf_process_param_ack(struct sct
                SCTPDBG(SCTP_DEBUG_ASCONF1,
                    "process_param_ack: set primary IP address\n");
                /* nothing to do... peer may start using this addr */
-               if (flag == 0)
-                       stcb->asoc.peer_supports_asconf = 0;
                break;
        default:
                /* should NEVER happen */
@@ -1646,11 +1636,11 @@ sctp_asconf_process_param_ack(struct sct
  * cleanup from a bad asconf ack parameter
  */
 static void
-sctp_asconf_ack_clear(struct sctp_tcb *stcb)
+sctp_asconf_ack_clear(struct sctp_tcb *stcb SCTP_UNUSED)
 {
        /* assume peer doesn't really know how to do asconfs */
-       stcb->asoc.peer_supports_asconf = 0;
        /* XXX we could free the pending queue here */
+
 }
 
 void
@@ -1988,7 +1978,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *
        /* queue an asconf for this address add/delete */
        if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
                /* does the peer do asconf? */
-               if (stcb->asoc.peer_supports_asconf) {
+               if (stcb->asoc.asconf_supported) {
                        /* queue an asconf for this addr */
                        status = sctp_asconf_queue_add(stcb, ifa, type);
 
@@ -2238,7 +2228,7 @@ sctp_asconf_iterator_stcb(struct sctp_in
                }
                /* queue an asconf for this address add/delete */
                if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
-                   stcb->asoc.peer_supports_asconf) {
+                   stcb->asoc.asconf_supported == 1) {
                        /* queue an asconf for this addr */
                        status = sctp_asconf_queue_add(stcb, ifa, type);
                        /*
@@ -2886,7 +2876,7 @@ sctp_process_initack_addresses(struct sc
                        /* are ASCONFs allowed ? */
                        if ((sctp_is_feature_on(stcb->sctp_ep,
                            SCTP_PCB_FLAGS_DO_ASCONF)) &&
-                           stcb->asoc.peer_supports_asconf) {
+                           stcb->asoc.asconf_supported) {
                                /* queue an ASCONF DEL_IP_ADDRESS */
                                status = sctp_asconf_queue_sa_delete(stcb, sa);
                                /*

Modified: stable/10/sys/netinet/sctp_auth.c
==============================================================================
--- stable/10/sys/netinet/sctp_auth.c   Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_auth.c   Fri Aug 22 20:22:12 2014        
(r270362)
@@ -133,11 +133,6 @@ sctp_auth_delete_chunk(uint8_t chunk, sc
        if (list == NULL)
                return (-1);
 
-       /* is chunk restricted? */
-       if ((chunk == SCTP_ASCONF) ||
-           (chunk == SCTP_ASCONF_ACK)) {
-               return (-1);
-       }
        if (list->chunks[chunk] == 1) {
                list->chunks[chunk] = 0;
                list->num_chunks--;
@@ -158,16 +153,6 @@ sctp_auth_get_chklist_size(const sctp_au
 }
 
 /*
- * set the default list of chunks requiring AUTH
- */
-void
-sctp_auth_set_default_chunks(sctp_auth_chklist_t * list)
-{
-       (void)sctp_auth_add_chunk(SCTP_ASCONF, list);
-       (void)sctp_auth_add_chunk(SCTP_ASCONF_ACK, list);
-}
-
-/*
  * return the current number and list of required chunks caller must
  * guarantee ptr has space for up to 256 bytes
  */

Modified: stable/10/sys/netinet/sctp_auth.h
==============================================================================
--- stable/10/sys/netinet/sctp_auth.h   Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_auth.h   Fri Aug 22 20:22:12 2014        
(r270362)
@@ -112,7 +112,6 @@ extern sctp_auth_chklist_t *sctp_copy_ch
 extern int sctp_auth_add_chunk(uint8_t chunk, sctp_auth_chklist_t * list);
 extern int sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t * list);
 extern size_t sctp_auth_get_chklist_size(const sctp_auth_chklist_t * list);
-extern void sctp_auth_set_default_chunks(sctp_auth_chklist_t * list);
 extern int 
 sctp_serialize_auth_chunks(const sctp_auth_chklist_t * list,
     uint8_t * ptr);

Modified: stable/10/sys/netinet/sctp_input.c
==============================================================================
--- stable/10/sys/netinet/sctp_input.c  Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_input.c  Fri Aug 22 20:22:12 2014        
(r270362)
@@ -480,7 +480,7 @@ sctp_process_init_ack(struct mbuf *m, in
                return (-1);
        }
        /* if the peer doesn't support asconf, flush the asconf queue */
-       if (asoc->peer_supports_asconf == 0) {
+       if (asoc->asconf_supported == 0) {
                struct sctp_asconf_addr *param, *nparam;
 
                TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) {
@@ -756,7 +756,7 @@ sctp_handle_nat_missing_state(struct sct
         * return 0 means we want you to proceed with the abort non-zero
         * means no abort processing
         */
-       if (stcb->asoc.peer_supports_auth == 0) {
+       if (stcb->asoc.auth_supported == 0) {
                SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer 
does not support AUTH, cannot send an asconf\n");
                return (0);
        }
@@ -1096,6 +1096,7 @@ sctp_process_unrecog_chunk(struct sctp_t
  * Skip past the param header and then we will find the param that caused the
  * problem.  There are a number of param's in a ASCONF OR the prsctp param
  * these will turn of specific features.
+ * XXX: Is this the right thing to do?
  */
 static void
 sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr)
@@ -1117,14 +1118,14 @@ sctp_process_unrecog_param(struct sctp_t
        case SCTP_ADD_IP_ADDRESS:
        case SCTP_DEL_IP_ADDRESS:
        case SCTP_SET_PRIM_ADDR:
-               stcb->asoc.peer_supports_asconf = 0;
+               stcb->asoc.asconf_supported = 0;
                break;
        case SCTP_SUCCESS_REPORT:
        case SCTP_ERROR_CAUSE_IND:
                SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support 
success? or error cause?\n");
                SCTPDBG(SCTP_DEBUG_INPUT2,
                    "Turning off ASCONF to this strange peer\n");
-               stcb->asoc.peer_supports_asconf = 0;
+               stcb->asoc.asconf_supported = 0;
                break;
        default:
                SCTPDBG(SCTP_DEBUG_INPUT2,
@@ -2787,6 +2788,8 @@ sctp_handle_cookie_echo(struct mbuf *m, 
                        inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
                        inp->ecn_supported = (*inp_p)->ecn_supported;
                        inp->prsctp_supported = (*inp_p)->prsctp_supported;
+                       inp->auth_supported = (*inp_p)->auth_supported;
+                       inp->asconf_supported = (*inp_p)->asconf_supported;
                        inp->reconfig_supported = (*inp_p)->reconfig_supported;
                        inp->nrsack_supported = (*inp_p)->nrsack_supported;
                        inp->pktdrop_supported = (*inp_p)->pktdrop_supported;
@@ -2966,7 +2969,7 @@ sctp_handle_cookie_ack(struct sctp_cooki
                 * in flight)
                 */
                if ((sctp_is_feature_on(stcb->sctp_ep, 
SCTP_PCB_FLAGS_DO_ASCONF)) &&
-                   (stcb->asoc.peer_supports_asconf) &&
+                   (stcb->asoc.asconf_supported == 1) &&
                    (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) {
 #ifdef SCTP_TIMER_BASED_ASCONF
                        sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
@@ -4439,7 +4442,7 @@ __attribute__((noinline))
                 */
                if ((ch->chunk_type == SCTP_AUTHENTICATION) &&
                    (stcb == NULL) &&
-                   !SCTP_BASE_SYSCTL(sctp_auth_disable)) {
+                   (inp->auth_supported == 1)) {
                        /* save this chunk for later processing */
                        auth_skipped = 1;
                        auth_offset = *offset;
@@ -4706,7 +4709,7 @@ process_control_chunks:
 
                /* check to see if this chunk required auth, but isn't */
                if ((stcb != NULL) &&
-                   !SCTP_BASE_SYSCTL(sctp_auth_disable) &&
+                   (stcb->asoc.auth_supported == 1) &&
                    sctp_auth_is_required_chunk(ch->chunk_type, 
stcb->asoc.local_auth_chunks) &&
                    !stcb->asoc.authenticated) {
                        /* "silently" ignore */
@@ -5225,6 +5228,9 @@ process_control_chunks:
                                return (NULL);
                        }
                        if (stcb) {
+                               if (stcb->asoc.ecn_supported == 0) {
+                                       goto unknown_chunk;
+                               }
                                if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_THRESHOLD_LOGGING) {
                                        sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
                                            stcb->asoc.overall_error_count,
@@ -5250,6 +5256,9 @@ process_control_chunks:
                                return (NULL);
                        }
                        if (stcb) {
+                               if (stcb->asoc.ecn_supported == 0) {
+                                       goto unknown_chunk;
+                               }
                                if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_THRESHOLD_LOGGING) {
                                        sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
                                            stcb->asoc.overall_error_count,
@@ -5283,6 +5292,9 @@ process_control_chunks:
                        SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n");
                        /* He's alive so give him credit */
                        if (stcb) {
+                               if (stcb->asoc.asconf_supported == 0) {
+                                       goto unknown_chunk;
+                               }
                                if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_THRESHOLD_LOGGING) {
                                        sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
                                            stcb->asoc.overall_error_count,
@@ -5307,6 +5319,9 @@ process_control_chunks:
                                return (NULL);
                        }
                        if ((stcb) && netp && *netp) {
+                               if (stcb->asoc.asconf_supported == 0) {
+                                       goto unknown_chunk;
+                               }
                                /* He's alive so give him credit */
                                if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_THRESHOLD_LOGGING) {
                                        sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
@@ -5336,6 +5351,9 @@ process_control_chunks:
                        if (stcb) {
                                int abort_flag = 0;
 
+                               if (stcb->asoc.prsctp_supported == 0) {
+                                       goto unknown_chunk;
+                               }
                                stcb->asoc.overall_error_count = 0;
                                if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_THRESHOLD_LOGGING) {
                                        sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
@@ -5391,12 +5409,7 @@ process_control_chunks:
                                return (NULL);
                        }
                        if (stcb->asoc.reconfig_supported == 0) {
-                               /*
-                                * hmm, peer should have announced this, but
-                                * we will turn it on since he is sending us
-                                * a stream reset.
-                                */
-                               stcb->asoc.reconfig_supported = 1;
+                               goto unknown_chunk;
                        }
                        if (sctp_handle_stream_reset(stcb, m, *offset, ch)) {
                                /* stop processing */
@@ -5416,18 +5429,17 @@ process_control_chunks:
                                return (NULL);
                        }
                        if (ch && (stcb) && netp && (*netp)) {
+                               if (stcb->asoc.pktdrop_supported == 0) {
+                                       goto unknown_chunk;
+                               }
                                sctp_handle_packet_dropped((struct 
sctp_pktdrop_chunk *)ch,
                                    stcb, *netp,
                                    min(chk_length, (sizeof(chunk_buf) - 4)));
 
                        }
                        break;
-
                case SCTP_AUTHENTICATION:
                        SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n");
-                       if (SCTP_BASE_SYSCTL(sctp_auth_disable))
-                               goto unknown_chunk;
-
                        if (stcb == NULL) {
                                /* save the first AUTH for later processing */
                                if (auth_skipped == 0) {
@@ -5438,6 +5450,9 @@ process_control_chunks:
                                /* skip this chunk (temporarily) */
                                goto next_chunk;
                        }
+                       if (stcb->asoc.auth_supported == 0) {
+                               goto unknown_chunk;
+                       }
                        if ((chk_length < (sizeof(struct sctp_auth_chunk))) ||
                            (chk_length > (sizeof(struct sctp_auth_chunk) +
                            SCTP_AUTH_DIGEST_LEN_MAX))) {
@@ -5778,7 +5793,7 @@ sctp_common_input_processing(struct mbuf
                 * chunks
                 */
                if ((stcb != NULL) &&
-                   !SCTP_BASE_SYSCTL(sctp_auth_disable) &&
+                   (stcb->asoc.auth_supported == 1) &&
                    sctp_auth_is_required_chunk(SCTP_DATA, 
stcb->asoc.local_auth_chunks)) {
                        /* "silently" ignore */
                        SCTP_STAT_INCR(sctps_recvauthmissing);
@@ -5820,7 +5835,7 @@ sctp_common_input_processing(struct mbuf
         */
        if ((length > offset) &&
            (stcb != NULL) &&
-           !SCTP_BASE_SYSCTL(sctp_auth_disable) &&
+           (stcb->asoc.auth_supported == 1) &&
            sctp_auth_is_required_chunk(SCTP_DATA, 
stcb->asoc.local_auth_chunks) &&
            !stcb->asoc.authenticated) {
                /* "silently" ignore */

Modified: stable/10/sys/netinet/sctp_output.c
==============================================================================
--- stable/10/sys/netinet/sctp_output.c Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_output.c Fri Aug 22 20:22:12 2014        
(r270362)
@@ -4753,12 +4753,6 @@ sctp_send_initiate(struct sctp_inpcb *in
        }
        chunk_len = (uint16_t) sizeof(struct sctp_init_chunk);
        padding_len = 0;
-       /*
-        * assume peer supports asconf in order to be able to queue local
-        * address changes while an INIT is in flight and before the assoc
-        * is established.
-        */
-       stcb->asoc.peer_supports_asconf = 1;
        /* Now lets put the chunk header in place */
        init = mtod(m, struct sctp_init_chunk *);
        /* now the chunk header */
@@ -4811,31 +4805,34 @@ sctp_send_initiate(struct sctp_inpcb *in
        /* And now tell the peer which extensions we support */
        num_ext = 0;
        pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, 
caddr_t)+chunk_len);
-       pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
-       pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
-       pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
        if (stcb->asoc.prsctp_supported == 1) {
                pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
        }
-       if (stcb->asoc.pktdrop_supported == 1) {
-               pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+       if (stcb->asoc.auth_supported == 1) {
+               pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
+       }
+       if (stcb->asoc.asconf_supported == 1) {
+               pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
+               pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
        }
        if (stcb->asoc.reconfig_supported == 1) {
                pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
        }
-       if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
-               pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
-       }
        if (stcb->asoc.nrsack_supported == 1) {
                pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
        }
-       parameter_len = (uint16_t) sizeof(struct 
sctp_supported_chunk_types_param) + num_ext;
-       pr_supported->ph.param_length = htons(parameter_len);
-       padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
-       chunk_len += parameter_len;
-
+       if (stcb->asoc.pktdrop_supported == 1) {
+               pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+       }
+       if (num_ext > 0) {
+               parameter_len = (uint16_t) sizeof(struct 
sctp_supported_chunk_types_param) + num_ext;
+               pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
+               pr_supported->ph.param_length = htons(parameter_len);
+               padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+               chunk_len += parameter_len;
+       }
        /* add authentication parameters */
-       if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
+       if (stcb->asoc.auth_supported) {
                /* attach RANDOM parameter, if available */
                if (stcb->asoc.authinfo.random != NULL) {
                        struct sctp_auth_random *randp;
@@ -4853,8 +4850,7 @@ sctp_send_initiate(struct sctp_inpcb *in
                        chunk_len += parameter_len;
                }
                /* add HMAC_ALGO parameter */
-               if ((stcb->asoc.local_hmacs != NULL) &&
-                   (stcb->asoc.local_hmacs->num_algo > 0)) {
+               if (stcb->asoc.local_hmacs != NULL) {
                        struct sctp_auth_hmac_algo *hmacs;
 
                        if (padding_len > 0) {
@@ -4872,7 +4868,7 @@ sctp_send_initiate(struct sctp_inpcb *in
                        chunk_len += parameter_len;
                }
                /* add CHUNKS parameter */
-               if (sctp_auth_get_chklist_size(stcb->asoc.local_auth_chunks) > 
0) {
+               if (stcb->asoc.local_auth_chunks != NULL) {
                        struct sctp_auth_chunk_list *chunks;
 
                        if (padding_len > 0) {
@@ -5917,35 +5913,41 @@ do_a_abort:
        /* And now tell the peer which extensions we support */
        num_ext = 0;
        pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, 
caddr_t)+chunk_len);
-       pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
-       pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
-       pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
        if (((asoc != NULL) && (asoc->prsctp_supported == 1)) ||
            ((asoc == NULL) && (inp->prsctp_supported == 1))) {
                pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
        }
-       if (((asoc != NULL) && (asoc->pktdrop_supported == 1)) ||
-           ((asoc == NULL) && (inp->pktdrop_supported == 1))) {
-               pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+       if (((asoc != NULL) && (asoc->auth_supported == 1)) ||
+           ((asoc == NULL) && (inp->auth_supported == 1))) {
+               pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
+       }
+       if (((asoc != NULL) && (asoc->asconf_supported == 1)) ||
+           ((asoc == NULL) && (inp->asconf_supported == 1))) {
+               pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
+               pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
        }
        if (((asoc != NULL) && (asoc->reconfig_supported == 1)) ||
            ((asoc == NULL) && (inp->reconfig_supported == 1))) {
                pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
        }
-       if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
-               pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
-       }
        if (((asoc != NULL) && (asoc->nrsack_supported == 1)) ||
            ((asoc == NULL) && (inp->nrsack_supported == 1))) {
                pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
        }
-       parameter_len = (uint16_t) sizeof(struct 
sctp_supported_chunk_types_param) + num_ext;
-       pr_supported->ph.param_length = htons(parameter_len);
-       padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
-       chunk_len += parameter_len;
-
+       if (((asoc != NULL) && (asoc->pktdrop_supported == 1)) ||
+           ((asoc == NULL) && (inp->pktdrop_supported == 1))) {
+               pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+       }
+       if (num_ext > 0) {
+               parameter_len = (uint16_t) sizeof(struct 
sctp_supported_chunk_types_param) + num_ext;
+               pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
+               pr_supported->ph.param_length = htons(parameter_len);
+               padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+               chunk_len += parameter_len;
+       }
        /* add authentication parameters */
-       if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
+       if (((asoc != NULL) && (asoc->auth_supported == 1)) ||
+           ((asoc == NULL) && (inp->auth_supported == 1))) {
                struct sctp_auth_random *randp;
                struct sctp_auth_hmac_algo *hmacs;
                struct sctp_auth_chunk_list *chunks;
@@ -7806,7 +7808,6 @@ sctp_med_chunk_output(struct sctp_inpcb 
 
        *num_out = 0;
        auth_keyid = stcb->asoc.authinfo.active_keyid;
-
        if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
            (asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED) ||
            (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) {
@@ -13417,12 +13418,7 @@ sctp_add_auth_chunk(struct mbuf *m, stru
            (stcb == NULL))
                return (m);
 
-       /* sysctl disabled auth? */
-       if (SCTP_BASE_SYSCTL(sctp_auth_disable))
-               return (m);
-
-       /* peer doesn't do auth... */
-       if (!stcb->asoc.peer_supports_auth) {
+       if (stcb->asoc.auth_supported == 0) {
                return (m);
        }
        /* does the requested chunk require auth? */

Modified: stable/10/sys/netinet/sctp_pcb.c
==============================================================================
--- stable/10/sys/netinet/sctp_pcb.c    Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_pcb.c    Fri Aug 22 20:22:12 2014        
(r270362)
@@ -2485,6 +2485,12 @@ sctp_inpcb_alloc(struct socket *so, uint
        inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off);
        inp->ecn_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_ecn_enable);
        inp->prsctp_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pr_enable);
+       if (SCTP_BASE_SYSCTL(sctp_auth_disable)) {
+               inp->auth_supported = 0;
+       } else {
+               inp->auth_supported = 1;
+       }
+       inp->asconf_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_asconf_enable);
        inp->reconfig_supported = (uint8_t) 
SCTP_BASE_SYSCTL(sctp_reconfig_enable);
        inp->nrsack_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_nrsack_enable);
        inp->pktdrop_supported = (uint8_t) 
SCTP_BASE_SYSCTL(sctp_pktdrop_enable);
@@ -2651,12 +2657,15 @@ sctp_inpcb_alloc(struct socket *so, uint
         */
        m->local_hmacs = sctp_default_supported_hmaclist();
        m->local_auth_chunks = sctp_alloc_chunklist();
+       if (inp->asconf_supported) {
+               sctp_auth_add_chunk(SCTP_ASCONF, m->local_auth_chunks);
+               sctp_auth_add_chunk(SCTP_ASCONF_ACK, m->local_auth_chunks);
+       }
        m->default_dscp = 0;
 #ifdef INET6
        m->default_flowlabel = 0;
 #endif
        m->port = 0;            /* encapsulation disabled by default */
-       sctp_auth_set_default_chunks(m->local_auth_chunks);
        LIST_INIT(&m->shared_keys);
        /* add default NULL key as key id 0 */
        null_key = sctp_alloc_sharedkey();
@@ -6085,11 +6094,14 @@ sctp_load_addresses_from_init(struct sct
        sctp_key_t *new_key;
        uint32_t keylen;
        int got_random = 0, got_hmacs = 0, got_chklist = 0;
-       uint8_t ecn_supported;
-       uint8_t prsctp_supported;
-       uint8_t reconfig_supported;
-       uint8_t nrsack_supported;
-       uint8_t pktdrop_supported;
+       uint8_t peer_supports_ecn;
+       uint8_t peer_supports_prsctp;
+       uint8_t peer_supports_auth;
+       uint8_t peer_supports_asconf;
+       uint8_t peer_supports_asconf_ack;
+       uint8_t peer_supports_reconfig;
+       uint8_t peer_supports_nrsack;
+       uint8_t peer_supports_pktdrop;
 
 #ifdef INET
        struct sockaddr_in sin;
@@ -6118,11 +6130,14 @@ sctp_load_addresses_from_init(struct sct
        } else {
                sa = src;
        }
-       ecn_supported = 0;
-       prsctp_supported = 0;
-       reconfig_supported = 0;
-       nrsack_supported = 0;
-       pktdrop_supported = 0;
+       peer_supports_ecn = 0;
+       peer_supports_prsctp = 0;
+       peer_supports_auth = 0;
+       peer_supports_asconf = 0;
+       peer_supports_asconf = 0;
+       peer_supports_reconfig = 0;
+       peer_supports_nrsack = 0;
+       peer_supports_pktdrop = 0;
        TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
                /* mark all addresses that we have currently on the list */
                net->dest_state |= SCTP_ADDR_NOT_IN_ASSOC;
@@ -6172,12 +6187,6 @@ sctp_load_addresses_from_init(struct sct
                /* the assoc was freed? */
                return (-4);
        }
-       /*
-        * peer must explicitly turn this on. This may have been initialized
-        * to be "on" in order to allow local addr changes while INIT's are
-        * in flight.
-        */
-       stcb->asoc.peer_supports_asconf = 0;
        /* now we must go through each of the params. */
        phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
        while (phdr) {
@@ -6371,7 +6380,7 @@ sctp_load_addresses_from_init(struct sct
                } else
 #endif
                if (ptype == SCTP_ECN_CAPABLE) {
-                       ecn_supported = 1;
+                       peer_supports_ecn = 1;
                } else if (ptype == SCTP_ULP_ADAPTATION) {
                        if (stcb->asoc.state != SCTP_STATE_OPEN) {
                                struct sctp_adaptation_layer_indication ai,
@@ -6395,7 +6404,9 @@ sctp_load_addresses_from_init(struct sct
 
 #endif
 
-                       stcb->asoc.peer_supports_asconf = 1;
+                       if (stcb->asoc.asconf_supported == 0) {
+                               return (-100);
+                       }
                        if (plen > sizeof(lstore)) {
                                return (-23);
                        }
@@ -6447,7 +6458,7 @@ sctp_load_addresses_from_init(struct sct
                        stcb->asoc.peer_supports_nat = 1;
                } else if (ptype == SCTP_PRSCTP_SUPPORTED) {
                        /* Peer supports pr-sctp */
-                       prsctp_supported = 1;
+                       peer_supports_prsctp = 1;
                } else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
                        /* A supported extension chunk */
                        struct sctp_supported_chunk_types_param *pr_supported;
@@ -6459,30 +6470,29 @@ sctp_load_addresses_from_init(struct sct
                        if (phdr == NULL) {
                                return (-25);
                        }
-                       stcb->asoc.peer_supports_asconf = 0;
-                       stcb->asoc.peer_supports_auth = 0;
                        pr_supported = (struct sctp_supported_chunk_types_param 
*)phdr;
                        num_ent = plen - sizeof(struct sctp_paramhdr);
                        for (i = 0; i < num_ent; i++) {
                                switch (pr_supported->chunk_types[i]) {
                                case SCTP_ASCONF:
+                                       peer_supports_asconf = 1;
                                case SCTP_ASCONF_ACK:
-                                       stcb->asoc.peer_supports_asconf = 1;
+                                       peer_supports_asconf_ack = 1;
                                        break;
                                case SCTP_FORWARD_CUM_TSN:
-                                       prsctp_supported = 1;
+                                       peer_supports_prsctp = 1;
                                        break;
                                case SCTP_PACKET_DROPPED:
-                                       pktdrop_supported = 1;
+                                       peer_supports_pktdrop = 1;
                                        break;
                                case SCTP_NR_SELECTIVE_ACK:
-                                       nrsack_supported = 1;
+                                       peer_supports_nrsack = 1;
                                        break;
                                case SCTP_STREAM_RESET:
-                                       reconfig_supported = 1;
+                                       peer_supports_reconfig = 1;
                                        break;
                                case SCTP_AUTHENTICATION:
-                                       stcb->asoc.peer_supports_auth = 1;
+                                       peer_supports_auth = 1;
                                        break;
                                default:
                                        /* one I have not learned yet */
@@ -6619,25 +6629,47 @@ next_param:
                        }
                }
        }
-       stcb->asoc.ecn_supported &= ecn_supported;
-       stcb->asoc.prsctp_supported &= prsctp_supported;
-       stcb->asoc.reconfig_supported &= reconfig_supported;
-       stcb->asoc.nrsack_supported &= nrsack_supported;
-       stcb->asoc.pktdrop_supported &= pktdrop_supported;
-       /* validate authentication required parameters */
-       if (got_random && got_hmacs) {
-               stcb->asoc.peer_supports_auth = 1;
-       } else {
-               stcb->asoc.peer_supports_auth = 0;
+       if ((stcb->asoc.ecn_supported == 1) &&
+           (peer_supports_ecn == 0)) {
+               stcb->asoc.ecn_supported = 0;
+       }
+       if ((stcb->asoc.prsctp_supported == 1) &&
+           (peer_supports_prsctp == 0)) {
+               stcb->asoc.prsctp_supported = 0;
+       }
+       if ((stcb->asoc.auth_supported == 1) &&
+           ((peer_supports_auth == 0) ||
+           (got_random == 0) || (got_hmacs == 0))) {
+               stcb->asoc.auth_supported = 0;
+       }
+       if ((stcb->asoc.asconf_supported == 1) &&
+           ((peer_supports_asconf == 0) || (peer_supports_asconf_ack == 0) ||
+           (stcb->asoc.auth_supported == 0) ||
+           (saw_asconf == 0) || (saw_asconf_ack == 0))) {
+               stcb->asoc.asconf_supported = 0;
+       }
+       if ((stcb->asoc.reconfig_supported == 1) &&
+           (peer_supports_reconfig == 0)) {
+               stcb->asoc.reconfig_supported = 0;
+       }
+       if ((stcb->asoc.nrsack_supported == 1) &&
+           (peer_supports_nrsack == 0)) {
+               stcb->asoc.nrsack_supported = 0;
+       }
+       if ((stcb->asoc.pktdrop_supported == 1) &&
+           (peer_supports_pktdrop == 0)) {
+               stcb->asoc.pktdrop_supported = 0;
        }
-       if (!stcb->asoc.peer_supports_auth && got_chklist) {
+       /* validate authentication required parameters */
+       if ((peer_supports_auth == 0) && (got_chklist == 1)) {
                /* peer does not support auth but sent a chunks list? */
                return (-31);
        }
-       if (stcb->asoc.peer_supports_asconf && !stcb->asoc.peer_supports_auth) {
+       if ((peer_supports_asconf == 1) && (peer_supports_auth == 0)) {
                /* peer supports asconf but not auth? */
                return (-32);
-       } else if ((stcb->asoc.peer_supports_asconf) && 
(stcb->asoc.peer_supports_auth) &&
+       } else if ((peer_supports_asconf == 1) &&
+                   (peer_supports_auth == 1) &&
            ((saw_asconf == 0) || (saw_asconf_ack == 0))) {
                return (-33);
        }

Modified: stable/10/sys/netinet/sctp_pcb.h
==============================================================================
--- stable/10/sys/netinet/sctp_pcb.h    Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_pcb.h    Fri Aug 22 20:22:12 2014        
(r270362)
@@ -408,6 +408,8 @@ struct sctp_inpcb {
        uint32_t sctp_cmt_on_off;
        uint8_t ecn_supported;
        uint8_t prsctp_supported;
+       uint8_t auth_supported;
+       uint8_t asconf_supported;
        uint8_t reconfig_supported;
        uint8_t nrsack_supported;
        uint8_t pktdrop_supported;

Modified: stable/10/sys/netinet/sctp_peeloff.c
==============================================================================
--- stable/10/sys/netinet/sctp_peeloff.c        Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_peeloff.c        Fri Aug 22 20:22:12 2014        
(r270362)
@@ -120,6 +120,8 @@ sctp_do_peeloff(struct socket *head, str
        n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
        n_inp->ecn_supported = inp->ecn_supported;
        n_inp->prsctp_supported = inp->prsctp_supported;
+       n_inp->auth_supported = inp->auth_supported;
+       n_inp->asconf_supported = inp->asconf_supported;
        n_inp->reconfig_supported = inp->reconfig_supported;
        n_inp->nrsack_supported = inp->nrsack_supported;
        n_inp->pktdrop_supported = inp->pktdrop_supported;

Modified: stable/10/sys/netinet/sctp_structs.h
==============================================================================
--- stable/10/sys/netinet/sctp_structs.h        Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_structs.h        Fri Aug 22 20:22:12 2014        
(r270362)
@@ -1153,6 +1153,8 @@ struct sctp_association {
        /* Flags whether an extension is supported or not */
        uint8_t ecn_supported;
        uint8_t prsctp_supported;
+       uint8_t auth_supported;
+       uint8_t asconf_supported;
        uint8_t reconfig_supported;
        uint8_t nrsack_supported;
        uint8_t pktdrop_supported;
@@ -1160,10 +1162,6 @@ struct sctp_association {
        /* Did the peer make the stream config (add out) request */
        uint8_t peer_req_out;
 
-       /* flag to indicate if peer can do asconf */
-       uint8_t peer_supports_asconf;
-       /* peer authentication support flag */
-       uint8_t peer_supports_auth;
        uint8_t local_strreset_support;
 
        uint8_t peer_supports_nat;

Modified: stable/10/sys/netinet/sctp_sysctl.c
==============================================================================
--- stable/10/sys/netinet/sctp_sysctl.c Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_sysctl.c Fri Aug 22 20:22:12 2014        
(r270362)
@@ -56,6 +56,8 @@ sctp_init_sysctls()
        SCTP_BASE_SYSCTL(sctp_multiple_asconfs) = 
SCTPCTL_MULTIPLEASCONFS_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_ecn_enable) = SCTPCTL_ECN_ENABLE_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_pr_enable) = SCTPCTL_PR_ENABLE_DEFAULT;
+       SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT;
+       SCTP_BASE_SYSCTL(sctp_asconf_enable) = SCTPCTL_ASCONF_ENABLE_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_reconfig_enable) = 
SCTPCTL_RECONFIG_ENABLE_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_nrsack_enable) = SCTPCTL_NRSACK_ENABLE_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_pktdrop_enable) = SCTPCTL_PKTDROP_ENABLE_DEFAULT;
@@ -91,7 +93,6 @@ sctp_init_sysctls()
        SCTP_BASE_SYSCTL(sctp_cmt_on_off) = SCTPCTL_CMT_ON_OFF_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_cmt_use_dac) = SCTPCTL_CMT_USE_DAC_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) = 
SCTPCTL_CWND_MAXBURST_DEFAULT;
-       SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_nat_friendly) = SCTPCTL_NAT_FRIENDLY_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_L2_abc_variable) = SCTPCTL_ABC_L_VAR_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count) = 
SCTPCTL_MAX_CHAINED_MBUFS_DEFAULT;
@@ -640,7 +641,6 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
                RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_on_off), 
SCTPCTL_CMT_ON_OFF_MIN, SCTPCTL_CMT_ON_OFF_MAX);
                RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_use_dac), 
SCTPCTL_CMT_USE_DAC_MIN, SCTPCTL_CMT_USE_DAC_MAX);
                RANGECHK(SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), 
SCTPCTL_CWND_MAXBURST_MIN, SCTPCTL_CWND_MAXBURST_MAX);
-               RANGECHK(SCTP_BASE_SYSCTL(sctp_auth_disable), 
SCTPCTL_AUTH_DISABLE_MIN, SCTPCTL_AUTH_DISABLE_MAX);
                RANGECHK(SCTP_BASE_SYSCTL(sctp_nat_friendly), 
SCTPCTL_NAT_FRIENDLY_MIN, SCTPCTL_NAT_FRIENDLY_MAX);
                RANGECHK(SCTP_BASE_SYSCTL(sctp_L2_abc_variable), 
SCTPCTL_ABC_L_VAR_MIN, SCTPCTL_ABC_L_VAR_MAX);
                RANGECHK(SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), 
SCTPCTL_MAX_CHAINED_MBUFS_MIN, SCTPCTL_MAX_CHAINED_MBUFS_MAX);
@@ -679,6 +679,56 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
        return (error);
 }
 
+static int
+sysctl_sctp_auth_check(SYSCTL_HANDLER_ARGS)
+{
+       int error;
+
+       error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+       if (error == 0) {
+               if (SCTP_BASE_SYSCTL(sctp_auth_disable) < 
SCTPCTL_AUTH_DISABLE_MIN) {
+                       SCTP_BASE_SYSCTL(sctp_auth_disable) = 
SCTPCTL_AUTH_DISABLE_MIN;
+               }
+               if (SCTP_BASE_SYSCTL(sctp_auth_disable) > 
SCTPCTL_AUTH_DISABLE_MAX) {
+                       SCTP_BASE_SYSCTL(sctp_auth_disable) = 
SCTPCTL_AUTH_DISABLE_MAX;
+               }
+               if ((SCTP_BASE_SYSCTL(sctp_auth_disable) == 1) &&
+                   (SCTP_BASE_SYSCTL(sctp_asconf_enable) == 1)) {
+                       /*
+                        * You can't disable AUTH with disabling ASCONF
+                        * first
+                        */
+                       SCTP_BASE_SYSCTL(sctp_auth_disable) = 0;
+               }
+       }
+       return (error);
+}
+
+static int
+sysctl_sctp_asconf_check(SYSCTL_HANDLER_ARGS)
+{
+       int error;
+
+       error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+       if (error == 0) {
+               if (SCTP_BASE_SYSCTL(sctp_asconf_enable) < 
SCTPCTL_ASCONF_ENABLE_MIN) {
+                       SCTP_BASE_SYSCTL(sctp_asconf_enable) = 
SCTPCTL_ASCONF_ENABLE_MIN;
+               }
+               if (SCTP_BASE_SYSCTL(sctp_asconf_enable) > 
SCTPCTL_ASCONF_ENABLE_MAX) {
+                       SCTP_BASE_SYSCTL(sctp_asconf_enable) = 
SCTPCTL_ASCONF_ENABLE_MAX;
+               }
+               if ((SCTP_BASE_SYSCTL(sctp_asconf_enable) == 1) &&
+                   (SCTP_BASE_SYSCTL(sctp_auth_disable) == 1)) {
+                       /*
+                        * You can't enable ASCONF without enabling AUTH
+                        * first
+                        */
+                       SCTP_BASE_SYSCTL(sctp_asconf_enable) = 0;
+               }
+       }
+       return (error);
+}
+
 #if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
 static int
 sysctl_stat_get(SYSCTL_HANDLER_ARGS)
@@ -871,6 +921,14 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUT
     &SCTP_BASE_SYSCTL(sctp_pr_enable), 0, sysctl_sctp_check, "IU",
     SCTPCTL_PR_ENABLE_DESC);
 
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_UINT | 
CTLFLAG_RW,
+    &SCTP_BASE_SYSCTL(sctp_auth_disable), 0, sysctl_sctp_auth_check, "IU",
+    SCTPCTL_AUTH_DISABLE_DESC);
+
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, asconf_enable, CTLTYPE_UINT | 
CTLFLAG_RW,
+    &SCTP_BASE_SYSCTL(sctp_asconf_enable), 0, sysctl_sctp_asconf_check, "IU",
+    SCTPCTL_ASCONF_ENABLE_DESC);
+
 SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, reconfig_enable, CTLTYPE_UINT | 
CTLFLAG_RW,
     &SCTP_BASE_SYSCTL(sctp_reconfig_enable), 0, sysctl_sctp_check, "IU",
     SCTPCTL_RECONFIG_ENABLE_DESC);
@@ -1012,10 +1070,6 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUT
     &SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), 0, sysctl_sctp_check, 
"IU",
     SCTPCTL_CWND_MAXBURST_DESC);
 
-SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_UINT | 
CTLFLAG_RW,
-    &SCTP_BASE_SYSCTL(sctp_auth_disable), 0, sysctl_sctp_check, "IU",
-    SCTPCTL_AUTH_DISABLE_DESC);
-
 SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nat_friendly, CTLTYPE_UINT | 
CTLFLAG_RW,
     &SCTP_BASE_SYSCTL(sctp_nat_friendly), 0, sysctl_sctp_check, "IU",
     SCTPCTL_NAT_FRIENDLY_DESC);

Modified: stable/10/sys/netinet/sctp_sysctl.h
==============================================================================
--- stable/10/sys/netinet/sctp_sysctl.h Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_sysctl.h Fri Aug 22 20:22:12 2014        
(r270362)
@@ -46,6 +46,8 @@ struct sctp_sysctl {
        uint32_t sctp_multiple_asconfs;
        uint32_t sctp_ecn_enable;
        uint32_t sctp_pr_enable;
+       uint32_t sctp_auth_disable;
+       uint32_t sctp_asconf_enable;
        uint32_t sctp_reconfig_enable;
        uint32_t sctp_nrsack_enable;
        uint32_t sctp_pktdrop_enable;
@@ -81,7 +83,6 @@ struct sctp_sysctl {
        uint32_t sctp_cmt_on_off;
        uint32_t sctp_cmt_use_dac;
        uint32_t sctp_use_cwnd_based_maxburst;
-       uint32_t sctp_auth_disable;
        uint32_t sctp_nat_friendly;
        uint32_t sctp_L2_abc_variable;
        uint32_t sctp_mbuf_threshold_count;
@@ -162,6 +163,18 @@ struct sctp_sysctl {
 #define SCTPCTL_PR_ENABLE_MAX          1
 #define SCTPCTL_PR_ENABLE_DEFAULT      1
 
+/* auth_disable: Disable SCTP AUTH function */
+#define SCTPCTL_AUTH_DISABLE_DESC      "Disable SCTP AUTH function"
+#define SCTPCTL_AUTH_DISABLE_MIN       0
+#define SCTPCTL_AUTH_DISABLE_MAX       1
+#define SCTPCTL_AUTH_DISABLE_DEFAULT   0
+
+/* asconf_enable: Enable SCTP ASCONF */
+#define SCTPCTL_ASCONF_ENABLE_DESC     "Enable SCTP ASCONF"
+#define SCTPCTL_ASCONF_ENABLE_MIN      0
+#define SCTPCTL_ASCONF_ENABLE_MAX      1
+#define SCTPCTL_ASCONF_ENABLE_DEFAULT  1
+
 /* reconfig_enable: Enable SCTP RE-CONFIG */
 #define SCTPCTL_RECONFIG_ENABLE_DESC   "Enable SCTP RE-CONFIG"
 #define SCTPCTL_RECONFIG_ENABLE_MIN    0
@@ -379,12 +392,6 @@ struct sctp_sysctl {
 #define SCTPCTL_CWND_MAXBURST_MAX      1
 #define SCTPCTL_CWND_MAXBURST_DEFAULT  1
 
-/* auth_disable: Disable SCTP AUTH function */
-#define SCTPCTL_AUTH_DISABLE_DESC      "Disable SCTP AUTH function"
-#define SCTPCTL_AUTH_DISABLE_MIN       0
-#define SCTPCTL_AUTH_DISABLE_MAX       1
-#define SCTPCTL_AUTH_DISABLE_DEFAULT   0
-
 /* nat_friendly: SCTP NAT friendly operation */
 #define SCTPCTL_NAT_FRIENDLY_DESC      "SCTP NAT friendly operation"
 #define SCTPCTL_NAT_FRIENDLY_MIN       0

Modified: stable/10/sys/netinet/sctp_usrreq.c
==============================================================================
--- stable/10/sys/netinet/sctp_usrreq.c Fri Aug 22 20:16:26 2014        
(r270361)
+++ stable/10/sys/netinet/sctp_usrreq.c Fri Aug 22 20:22:12 2014        
(r270362)
@@ -3348,6 +3348,60 @@ flags_out:
                        }
                        break;
                }
+       case SCTP_AUTH_SUPPORTED:
+               {
+                       struct sctp_assoc_value *av;
+
+                       SCTP_CHECK_AND_CAST(av, optval, struct 
sctp_assoc_value, *optsize);
+                       SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+                       if (stcb) {
+                               av->assoc_value = stcb->asoc.auth_supported;
+                               SCTP_TCB_UNLOCK(stcb);
+                       } else {
+                               if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) 
||
+                                   (inp->sctp_flags & 
SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                                   (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                                       SCTP_INP_RLOCK(inp);
+                                       av->assoc_value = inp->auth_supported;
+                                       SCTP_INP_RUNLOCK(inp);
+                               } else {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
[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