The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/sctp_asconf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: sctp_asconf.c,v 1.12 2019/06/25 15:33:56 rjs Exp $ */
    2 /*      $KAME: sctp_asconf.c,v 1.25 2005/06/16 20:44:24 jinmei Exp $    */
    3 
    4 /*
    5  * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the project nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL CISCO SYSTEMS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: sctp_asconf.c,v 1.12 2019/06/25 15:33:56 rjs Exp $");
   34 
   35 #ifdef _KERNEL_OPT
   36 #include "opt_ipsec.h"
   37 #include "opt_inet.h"
   38 #include "opt_sctp.h"
   39 #endif /* _KERNEL_OPT */
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/malloc.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/socket.h>
   46 #include <sys/socketvar.h>
   47 #include <sys/kernel.h>
   48 #include <sys/sysctl.h>
   49 
   50 #include <net/if.h>
   51 #include <net/if_types.h>
   52 #include <net/route.h>
   53 
   54 #include <netinet/in.h>
   55 #include <netinet/in_systm.h>
   56 #include <netinet/ip.h>
   57 #include <netinet/in_pcb.h>
   58 #include <netinet/in_var.h>
   59 #include <netinet/ip_var.h>
   60 
   61 #ifdef INET6
   62 #include <netinet/ip6.h>
   63 #include <netinet6/ip6_var.h>
   64 #include <netinet6/in6_pcb.h>
   65 #include <netinet/icmp6.h>
   66 #include <netinet6/nd6.h>
   67 #include <netinet6/scope6_var.h>
   68 #include <netinet6/nd6.h>
   69 #endif /* INET6 */
   70 
   71 #include <netinet/in_pcb.h>
   72 
   73 #include <netinet/sctp_var.h>
   74 #include <netinet/sctp_pcb.h>
   75 #include <netinet/sctp_header.h>
   76 #include <netinet/sctputil.h>
   77 #include <netinet/sctp_output.h>
   78 #include <netinet/sctp_asconf.h>
   79 #include <netinet/sctp_route.h>
   80 
   81 /*
   82  * debug flags:
   83  *   SCTP_DEBUG_ASCONF1: protocol info, general info and errors
   84  *   SCTP_DEBUG_ASCONF2: detailed info
   85  */
   86 #ifdef SCTP_DEBUG
   87 extern u_int32_t sctp_debug_on;
   88 #endif /* SCTP_DEBUG */
   89 
   90 /*
   91  * draft-ietf-tsvwg-addip-sctp
   92  *
   93  * Address management only currently supported
   94  * For the bound all case:
   95  *      the asoc local addr list is always a "DO NOT USE" list
   96  * For the subset bound case:
   97  *      If ASCONFs are allowed:
   98  *              the endpoint local addr list is the usable address list
   99  *              the asoc local addr list is the "DO NOT USE" list
  100  *      If ASCONFs are not allowed:
  101  *              the endpoint local addr list is the default usable list
  102  *              the asoc local addr list is the usable address list
  103  *
  104  * An ASCONF parameter queue exists per asoc which holds the pending
  105  * address operations.  Lists are updated upon receipt of ASCONF-ACK.
  106  *
  107  * Deleted addresses are always immediately removed from the lists as
  108  * they will (shortly) no longer exist in the kernel.  We send ASCONFs
  109  * as a courtesy, only if allowed.
  110  */
  111 
  112 /*
  113  * ASCONF parameter processing
  114  * response_required: set if a reply is required (eg. SUCCESS_REPORT)
  115  * returns a mbuf to an "error" response parameter or NULL/"success" if ok
  116  * FIX: allocating this many mbufs on the fly is pretty inefficient...
  117  */
  118 
  119 static struct mbuf *
  120 sctp_asconf_success_response(uint32_t id)
  121 {
  122         struct mbuf *m_reply = NULL;
  123         struct sctp_asconf_paramhdr *aph;
  124 
  125         MGET(m_reply, M_DONTWAIT, MT_DATA);
  126         if (m_reply == NULL) {
  127 #ifdef SCTP_DEBUG
  128                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  129                         printf("asconf_success_response: couldn't get mbuf!\n");
  130                 }
  131 #endif /* SCTP_DEBUG */
  132                 return NULL;
  133         }
  134         aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
  135         aph->correlation_id = id;
  136         aph->ph.param_type = htons(SCTP_SUCCESS_REPORT);
  137         aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr);
  138         m_reply->m_len = aph->ph.param_length;
  139         aph->ph.param_length = htons(aph->ph.param_length);
  140 
  141         return m_reply;
  142 }
  143 
  144 static struct mbuf *
  145 sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t *error_tlv,
  146     uint16_t tlv_length)
  147 {
  148         struct mbuf *m_reply = NULL;
  149         struct sctp_asconf_paramhdr *aph;
  150         struct sctp_error_cause *error;
  151         uint8_t *tlv;
  152 
  153         MGET(m_reply, M_DONTWAIT, MT_DATA);
  154         if (m_reply == NULL) {
  155 #ifdef SCTP_DEBUG
  156                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  157                         printf("asconf_error_response: couldn't get mbuf!\n");
  158                 }
  159 #endif /* SCTP_DEBUG */
  160                 return NULL;
  161         }
  162         aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
  163         error = (struct sctp_error_cause *)(aph + 1);
  164 
  165         aph->correlation_id = id;
  166         aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND);
  167         error->code = htons(cause);
  168         error->length = tlv_length + sizeof(struct sctp_error_cause);
  169         aph->ph.param_length = error->length +
  170             sizeof(struct sctp_asconf_paramhdr);
  171 
  172         if (aph->ph.param_length > MLEN) {
  173 #ifdef SCTP_DEBUG
  174                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  175                         printf("asconf_error_response: tlv_length (%xh) too big\n",
  176                             tlv_length);
  177                 }
  178 #endif /* SCTP_DEBUG */
  179                 sctp_m_freem(m_reply);  /* discard */
  180                 return NULL;
  181         }
  182 
  183         if (error_tlv != NULL) {
  184                 tlv = (uint8_t *)(error + 1);
  185                 memcpy(tlv, error_tlv, tlv_length);
  186         }
  187 
  188         m_reply->m_len = aph->ph.param_length;
  189         error->length = htons(error->length);
  190         aph->ph.param_length = htons(aph->ph.param_length);
  191 
  192         return m_reply;
  193 }
  194 
  195 static struct mbuf *
  196 sctp_process_asconf_add_ip(struct sctp_asconf_paramhdr *aph,
  197     struct sctp_tcb *stcb, int response_required)
  198 {
  199         struct mbuf *m_reply = NULL;
  200         struct sockaddr_storage sa_store;
  201         struct sctp_ipv4addr_param *v4addr;
  202         uint16_t param_type, param_length, aparam_length;
  203         struct sockaddr *sa;
  204         struct sockaddr_in *sin;
  205 #ifdef INET6
  206         struct sockaddr_in6 *sin6;
  207         struct sctp_ipv6addr_param *v6addr;
  208 #endif /* INET6 */
  209 
  210         aparam_length = ntohs(aph->ph.param_length);
  211         v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
  212 #ifdef INET6
  213         v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
  214 #endif /* INET6 */
  215         param_type = ntohs(v4addr->ph.param_type);
  216         param_length = ntohs(v4addr->ph.param_length);
  217 
  218         sa = (struct sockaddr *)&sa_store;
  219         switch (param_type) {
  220         case SCTP_IPV4_ADDRESS:
  221                 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
  222                         /* invalid param size */
  223                         return NULL;
  224                 }
  225                 sin = (struct sockaddr_in *)&sa_store;
  226                 memset(sin, 0, sizeof(*sin));
  227                 sin->sin_family = AF_INET;
  228                 sin->sin_len = sizeof(struct sockaddr_in);
  229                 sin->sin_port = stcb->rport;
  230                 sin->sin_addr.s_addr = v4addr->addr;
  231 #ifdef SCTP_DEBUG
  232                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  233                         printf("process_asconf_add_ip: adding ");
  234                         sctp_print_address(sa);
  235                 }
  236 #endif /* SCTP_DEBUG */
  237                 break;
  238         case SCTP_IPV6_ADDRESS:
  239 #ifdef INET6
  240                 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
  241                         /* invalid param size */
  242                         return NULL;
  243                 }
  244                 sin6 = (struct sockaddr_in6 *)&sa_store;
  245                 memset(sin6, 0, sizeof(*sin6));
  246                 sin6->sin6_family = AF_INET6;
  247                 sin6->sin6_len = sizeof(struct sockaddr_in6);
  248                 sin6->sin6_port = stcb->rport;
  249                 memcpy((void *)&sin6->sin6_addr, v6addr->addr,
  250                     sizeof(struct in6_addr));
  251 #ifdef SCTP_DEBUG
  252                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  253                         printf("process_asconf_add_ip: adding ");
  254                         sctp_print_address(sa);
  255                 }
  256 #endif /* SCTP_DEBUG */
  257 #else
  258                 /* IPv6 not enabled! */
  259                 /* FIX ME: currently sends back an invalid param error */
  260                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  261                     SCTP_ERROR_INVALID_PARAM, (uint8_t *)aph, aparam_length);
  262 #ifdef SCTP_DEBUG
  263                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  264                         printf("process_asconf_add_ip: v6 disabled- skipping ");
  265                         sctp_print_address(sa);
  266                 }
  267 #endif /* SCTP_DEBUG */
  268                 return m_reply;
  269 #endif /* INET6 */
  270                 break;
  271         default:
  272                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  273                     SCTP_ERROR_UNRESOLVABLE_ADDR, (uint8_t *)aph,
  274                     aparam_length);
  275                 return m_reply;
  276         } /* end switch */
  277 
  278         /* add the address */
  279         if (sctp_add_remote_addr(stcb, sa, 0, 6) != 0) {
  280 #ifdef SCTP_DEBUG
  281                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  282                         printf("process_asconf_add_ip: error adding address\n");
  283                 }
  284 #endif /* SCTP_DEBUG */
  285                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  286                     SCTP_ERROR_RESOURCE_SHORTAGE, (uint8_t *)aph,
  287                     aparam_length);
  288         } else {
  289                 /* notify upper layer */
  290                 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa);
  291                 if (response_required) {
  292                         m_reply =
  293                             sctp_asconf_success_response(aph->correlation_id);
  294                 }
  295         }
  296 
  297         return m_reply;
  298 }
  299 
  300 static struct mbuf *
  301 sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
  302     struct sctp_tcb *stcb, int response_required)
  303 {
  304         struct mbuf *m_reply = NULL;
  305         struct sockaddr_storage sa_store, sa_source;
  306         struct sctp_ipv4addr_param *v4addr;
  307         uint16_t param_type, param_length, aparam_length;
  308         struct sockaddr *sa;
  309         struct sockaddr_in *sin;
  310         struct ip *iph;
  311         int result;
  312 #ifdef INET6
  313         struct sockaddr_in6 *sin6;
  314         struct sctp_ipv6addr_param *v6addr;
  315 #endif /* INET6 */
  316 
  317         aparam_length = ntohs(aph->ph.param_length);
  318         v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
  319 #ifdef INET6
  320         v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
  321 #endif /* INET6 */
  322         param_type = ntohs(v4addr->ph.param_type);
  323         param_length = ntohs(v4addr->ph.param_length);
  324 
  325         /* get the source IP address for deletion check */
  326         iph = mtod(m, struct ip *);
  327         if (iph->ip_v == IPVERSION) {
  328                 /* IPv4 source */
  329                 sin = (struct sockaddr_in *)&sa_source;
  330                 memset(sin, 0, sizeof(*sin));
  331                 sin->sin_family = AF_INET;
  332                 sin->sin_len = sizeof(struct sockaddr_in);
  333                 sin->sin_port = stcb->rport;
  334                 sin->sin_addr.s_addr = iph->ip_src.s_addr;
  335         }
  336 #ifdef INET6
  337         else if (iph->ip_v == (IPV6_VERSION >> 4)) {
  338                 /* IPv6 source */
  339                 struct ip6_hdr *ip6;
  340 
  341                 sin6 = (struct sockaddr_in6 *)&sa_source;
  342                 memset(sin6, 0, sizeof(*sin6));
  343                 sin6->sin6_family = AF_INET6;
  344                 sin6->sin6_len = sizeof(struct sockaddr_in6);
  345                 sin6->sin6_port = stcb->rport;
  346                 ip6 = mtod(m, struct ip6_hdr *);
  347                 sin6->sin6_addr = ip6->ip6_src;
  348         }
  349 #endif /* INET6 */
  350         else
  351                 return NULL;
  352 
  353         sa = (struct sockaddr *)&sa_store;
  354         switch (param_type) {
  355         case SCTP_IPV4_ADDRESS:
  356                 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
  357                         /* invalid param size */
  358                         return NULL;
  359                 }
  360                 sin = (struct sockaddr_in *)&sa_store;
  361                 memset(sin, 0, sizeof(*sin));
  362                 sin->sin_family = AF_INET;
  363                 sin->sin_len = sizeof(struct sockaddr_in);
  364                 sin->sin_port = stcb->rport;
  365                 sin->sin_addr.s_addr = v4addr->addr;
  366 #ifdef SCTP_DEBUG
  367                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  368                         printf("process_asconf_delete_ip: deleting ");
  369                         sctp_print_address(sa);
  370                 }
  371 #endif /* SCTP_DEBUG */
  372                 break;
  373         case SCTP_IPV6_ADDRESS:
  374                 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
  375                         /* invalid param size */
  376                         return NULL;
  377                 }
  378 #ifdef INET6
  379                 sin6 = (struct sockaddr_in6 *)&sa_store;
  380                 memset(sin6, 0, sizeof(*sin6));
  381                 sin6->sin6_family = AF_INET6;
  382                 sin6->sin6_len = sizeof(struct sockaddr_in6);
  383                 sin6->sin6_port = stcb->rport;
  384                 memcpy(&sin6->sin6_addr, v6addr->addr,
  385                     sizeof(struct in6_addr));
  386 #ifdef SCTP_DEBUG
  387                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  388                         printf("process_asconf_delete_ip: deleting ");
  389                         sctp_print_address(sa);
  390                 }
  391 #endif /* SCTP_DEBUG */
  392 #else
  393                 /* IPv6 not enabled!  No "action" needed; just ack it */
  394 #ifdef SCTP_DEBUG
  395                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  396                         printf("process_asconf_delete_ip: v6 disabled- ignoring: ");
  397                         sctp_print_address(sa);
  398                 }
  399 #endif /* SCTP_DEBUG */
  400                 /* just respond with a "success" ASCONF-ACK */
  401                 return NULL;
  402 #endif /* INET6 */
  403                 break;
  404         default:
  405                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  406                     SCTP_ERROR_UNRESOLVABLE_ADDR, (uint8_t *)aph,
  407                     aparam_length);
  408                 return m_reply;
  409         } /* end switch */
  410 
  411         /* make sure the source address is not being deleted */
  412         if ((memcmp(sa, &sa_source, sizeof(struct sockaddr_in)) == 0)
  413 #ifdef INET6
  414             || (memcmp(sa, &sa_source, sizeof(struct sockaddr_in6)) == 0)
  415 #endif /* INET6 */
  416                 ) {
  417                 /* trying to delete the source address! */
  418 #ifdef SCTP_DEBUG
  419                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  420                         printf("process_asconf_delete_ip: tried to delete source addr\n");
  421                 }
  422 #endif /* SCTP_DEBUG */
  423                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  424                     SCTP_ERROR_DELETE_SOURCE_ADDR, (uint8_t *)aph,
  425                     aparam_length);
  426                 return m_reply;
  427         }
  428 
  429         /* delete the address */
  430         result = sctp_del_remote_addr(stcb, sa);
  431         /*
  432          * note if result == -2, the address doesn't exist in the asoc
  433          * but since it's being deleted anyways, we just ack the delete
  434          * -- but this probably means something has already gone awry
  435          */
  436         if (result == -1) {
  437                 /* only one address in the asoc */
  438 #ifdef SCTP_DEBUG
  439                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  440                         printf("process_asconf_delete_ip: tried to delete last IP addr!\n");
  441                 }
  442 #endif /* SCTP_DEBUG */
  443                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  444                     SCTP_ERROR_DELETE_LAST_ADDR, (uint8_t *)aph,
  445                     aparam_length);
  446         } else {
  447                 /* notify upper layer */
  448                 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa);
  449         }
  450 
  451         if (response_required) {
  452                 m_reply = sctp_asconf_success_response(aph->correlation_id);
  453         }
  454         return m_reply;
  455 }
  456 
  457 static struct mbuf *
  458 sctp_process_asconf_set_primary(struct sctp_asconf_paramhdr *aph,
  459     struct sctp_tcb *stcb, int response_required)
  460 {
  461         struct mbuf *m_reply = NULL;
  462         struct sockaddr_storage sa_store;
  463         struct sctp_ipv4addr_param *v4addr;
  464         uint16_t param_type, param_length, aparam_length;
  465         struct sockaddr *sa;
  466         struct sockaddr_in *sin;
  467 #ifdef INET6
  468         struct sockaddr_in6 *sin6;
  469         struct sctp_ipv6addr_param *v6addr;
  470 #endif /* INET6 */
  471 
  472         aparam_length = ntohs(aph->ph.param_length);
  473         v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
  474 #ifdef INET6
  475         v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
  476 #endif /* INET6 */
  477         param_type = ntohs(v4addr->ph.param_type);
  478         param_length = ntohs(v4addr->ph.param_length);
  479 
  480         sa = (struct sockaddr *)&sa_store;
  481         switch (param_type) {
  482         case SCTP_IPV4_ADDRESS:
  483                 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
  484                         /* invalid param size */
  485                         return NULL;
  486                 }
  487                 sin = (struct sockaddr_in *)&sa_store;
  488                 memset(sin, 0, sizeof(*sin));
  489                 sin->sin_family = AF_INET;
  490                 sin->sin_len = sizeof(struct sockaddr_in);
  491                 sin->sin_addr.s_addr = v4addr->addr;
  492 #ifdef SCTP_DEBUG
  493                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  494                         printf("process_asconf_set_primary: ");
  495                         sctp_print_address(sa);
  496                 }
  497 #endif /* SCTP_DEBUG */
  498                 break;
  499         case SCTP_IPV6_ADDRESS:
  500                 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
  501                         /* invalid param size */
  502                         return NULL;
  503                 }
  504 #ifdef INET6
  505                 sin6 = (struct sockaddr_in6 *)&sa_store;
  506                 memset(sin6, 0, sizeof(*sin6));
  507                 sin6->sin6_family = AF_INET6;
  508                 sin6->sin6_len = sizeof(struct sockaddr_in6);
  509                 memcpy((void *)&sin6->sin6_addr, v6addr->addr,
  510                     sizeof(struct in6_addr));
  511 #ifdef SCTP_DEBUG
  512                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  513                         printf("process_asconf_set_primary: ");
  514                         sctp_print_address(sa);
  515                 }
  516 #endif /* SCTP_DEBUG */
  517 #else
  518                 /* IPv6 not enabled!  No "action" needed; just ack it */
  519 #ifdef SCTP_DEBUG
  520                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  521                         printf("process_asconf_set_primary: v6 disabled- ignoring: ");
  522                         sctp_print_address(sa);
  523                 }
  524 #endif /* SCTP_DEBUG */
  525                 /* just respond with a "success" ASCONF-ACK */
  526                 return NULL;
  527 #endif /* INET6 */
  528                 break;
  529         default:
  530                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  531                     SCTP_ERROR_UNRESOLVABLE_ADDR, (uint8_t *)aph,
  532                     aparam_length);
  533                 return m_reply;
  534         } /* end switch */
  535 
  536         /* set the primary address */
  537         if (sctp_set_primary_addr(stcb, sa, NULL) == 0) {
  538 #ifdef SCTP_DEBUG
  539                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  540                         printf("process_asconf_set_primary: primary address set\n");
  541                 }
  542 #endif /* SCTP_DEBUG */
  543                 /* notify upper layer */
  544                 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa);
  545 
  546                 if (response_required) {
  547                         m_reply = sctp_asconf_success_response(aph->correlation_id);
  548                 }
  549         } else {
  550                 /* couldn't set the requested primary address! */
  551 #ifdef SCTP_DEBUG
  552                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  553                         printf("process_asconf_set_primary: set primary failed!\n");
  554                 }
  555 #endif /* SCTP_DEBUG */
  556                 /* must have been an invalid address, so report */
  557                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  558                     SCTP_ERROR_UNRESOLVABLE_ADDR, (uint8_t *)aph,
  559                     aparam_length);
  560         }
  561 
  562         return m_reply;
  563 }
  564 
  565 /*
  566  * handles an ASCONF chunk
  567  * if all parameters are processed ok, send a plain (empty) ASCONF-ACK
  568  */
  569 void
  570 sctp_handle_asconf(struct mbuf *m, unsigned int offset, struct sctp_asconf_chunk *cp,
  571     struct sctp_tcb *stcb, struct sctp_nets *net)
  572 {
  573         struct sctp_association *asoc;
  574         uint32_t serial_num;
  575         struct mbuf *m_ack, *m_result, *m_tail;
  576         struct sctp_asconf_ack_chunk *ack_cp;
  577         struct sctp_asconf_paramhdr *aph, *ack_aph;
  578         struct sctp_ipv6addr_param *p_addr;
  579         unsigned int asconf_limit;
  580         int error = 0;          /* did an error occur? */
  581         /* asconf param buffer */
  582         static u_int8_t aparam_buf[DEFAULT_PARAM_BUFFER];
  583 
  584         /* verify minimum length */
  585         if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) {
  586 #ifdef SCTP_DEBUG
  587                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  588                         printf("handle_asconf: chunk too small = %xh\n",
  589                             ntohs(cp->ch.chunk_length));
  590                 }
  591 #endif /* SCTP_DEBUG */
  592                 return;
  593         }
  594 
  595         asoc = &stcb->asoc;
  596         serial_num = ntohl(cp->serial_number);
  597 
  598         if (serial_num == asoc->asconf_seq_in) {
  599                 /* got a duplicate ASCONF */
  600 #ifdef SCTP_DEBUG
  601                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  602                         printf("handle_asconf: got duplicate serial number = %xh\n",
  603                                serial_num);
  604                 }
  605 #endif /* SCTP_DEBUG */
  606                 /* resend last ASCONF-ACK... */
  607                 sctp_send_asconf_ack(stcb, 1);
  608                 return;
  609         } else if (serial_num != (asoc->asconf_seq_in + 1)) {
  610 #ifdef SCTP_DEBUG
  611                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  612                         printf("handle_asconf: incorrect serial number = %xh (expected next = %xh)\n",
  613                             serial_num, asoc->asconf_seq_in+1);
  614                 }
  615 #endif /* SCTP_DEBUG */
  616                 return;
  617         }
  618 
  619         /* it's the expected "next" sequence number, so process it */
  620         asoc->asconf_seq_in = serial_num;       /* update sequence */
  621         /* get length of all the param's in the ASCONF */
  622         asconf_limit = offset + ntohs(cp->ch.chunk_length);
  623 #ifdef SCTP_DEBUG
  624         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  625                 printf("handle_asconf: asconf_limit=%u, sequence=%xh\n",
  626                     asconf_limit, serial_num);
  627         }
  628 #endif /* SCTP_DEBUG */
  629         if (asoc->last_asconf_ack_sent != NULL) {
  630                 /* free last ASCONF-ACK message sent */
  631                 sctp_m_freem(asoc->last_asconf_ack_sent);
  632                 asoc->last_asconf_ack_sent = NULL;
  633         }
  634         MGETHDR(m_ack, M_DONTWAIT, MT_DATA);
  635         if (m_ack == NULL) {
  636 #ifdef SCTP_DEBUG
  637                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  638                         printf("handle_asconf: couldn't get mbuf!\n");
  639                 }
  640 #endif /* SCTP_DEBUG */
  641                 return;
  642         }
  643         m_tail = m_ack;         /* current reply chain's tail */
  644 
  645         /* fill in ASCONF-ACK header */
  646         ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *);
  647         ack_cp->ch.chunk_type = SCTP_ASCONF_ACK;
  648         ack_cp->ch.chunk_flags = 0;
  649         ack_cp->serial_number = htonl(serial_num);
  650         /* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */
  651         m_ack->m_len = sizeof(struct sctp_asconf_ack_chunk);
  652         ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk);
  653         m_ack->m_pkthdr.len = sizeof(struct sctp_asconf_ack_chunk);
  654 
  655         /* skip the lookup address parameter */
  656         offset += sizeof(struct sctp_asconf_chunk);
  657         p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *)&aparam_buf);
  658         if (p_addr == NULL) {
  659 #ifdef SCTP_DEBUG
  660                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  661                         printf("handle_asconf: couldn't get lookup addr!\n");
  662                 }
  663 #endif /* SCTP_DEBUG */
  664 
  665                 /* respond with a missing/invalid mandatory parameter error */
  666                 return;
  667         }
  668         /* param_length is already validated in process_control... */
  669         offset += ntohs(p_addr->ph.param_length);   /* skip lookup addr */
  670 
  671         /* get pointer to first asconf param in ASCONF */
  672         aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *)&aparam_buf);
  673         /* get pointer to first asconf param in ASCONF-ACK */
  674         if (aph == NULL) {
  675                 printf("Gak in asconf\n");
  676                 return;
  677         }
  678         ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, vaddr_t) + sizeof(struct sctp_asconf_ack_chunk));
  679         if (ack_aph == NULL) {
  680                 printf("Gak in asconf2\n");
  681                 return;
  682         }
  683 
  684         /* process through all parameters */
  685         while (aph != NULL) {
  686                 unsigned int param_length, param_type;
  687 
  688                 param_type = ntohs(aph->ph.param_type);
  689                 param_length = ntohs(aph->ph.param_length);
  690                 if (offset + param_length > asconf_limit) {
  691                         /* parameter goes beyond end of chunk! */
  692                         sctp_m_freem(m_ack);
  693                         return;
  694                 }
  695                 m_result = NULL;
  696 
  697                 if (param_length > sizeof(aparam_buf)) {
  698 #ifdef SCTP_DEBUG
  699                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  700                                 printf("handle_asconf: param length (%u) larger than buffer size!\n", param_length);
  701                         }
  702 #endif /* SCTP_DEBUG */
  703                         sctp_m_freem(m_ack);
  704                         return;
  705                 }
  706                 if (param_length <= sizeof(struct sctp_paramhdr)) {
  707 #ifdef SCTP_DEBUG
  708                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  709                                 printf("handle_asconf: param length (%u) too short\n", param_length);
  710                         }
  711 #endif /* SCTP_DEBUG */
  712                         sctp_m_freem(m_ack);
  713                 }
  714 
  715                 /* get the entire parameter */
  716                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
  717                 if (aph == NULL) {
  718                         printf("Gag\n");
  719                         sctp_m_freem(m_ack);
  720                         return;
  721                 }
  722                 switch (param_type) {
  723                 case SCTP_ADD_IP_ADDRESS:
  724                         asoc->peer_supports_asconf = 1;
  725                         m_result = sctp_process_asconf_add_ip(aph, stcb, error);
  726                         break;
  727                 case SCTP_DEL_IP_ADDRESS:
  728                         asoc->peer_supports_asconf = 1;
  729                         m_result = sctp_process_asconf_delete_ip(m, aph, stcb,
  730                             error);
  731                         break;
  732                 case SCTP_ERROR_CAUSE_IND:
  733                         /* not valid in an ASCONF chunk */
  734                         break;
  735                 case SCTP_SET_PRIM_ADDR:
  736                         asoc->peer_supports_asconf_setprim = 1;
  737                         m_result = sctp_process_asconf_set_primary(aph, stcb,
  738                             error);
  739                         break;
  740                 case SCTP_SUCCESS_REPORT:
  741                         /* not valid in an ASCONF chunk */
  742                         break;
  743                 case SCTP_ULP_ADAPTION:
  744                         /* FIX */
  745                         break;
  746                 default:
  747                         if ((param_type & 0x8000) == 0) {
  748                                 /* Been told to STOP at this param */
  749                                 asconf_limit = offset;
  750                                 /* FIX FIX - We need to call sctp_arethere_unrecognized_parameters()
  751                                  * to get a operr and send it for any param's with the
  752                                  * 0x4000 bit set OR do it here ourselves... note we still
  753                                  * must STOP if the 0x8000 bit is clear.
  754                                  */
  755                         }
  756                         /* unknown/invalid param type */
  757                         break;
  758                 } /* switch */
  759 
  760                 /* add any (error) result to the reply mbuf chain */
  761                 if (m_result != NULL) {
  762 #ifdef SCTP_DEBUG
  763                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  764                                 printf("handle_asconf: adding reply...\n");
  765                         }
  766 #endif /* SCTP_DEBUG */
  767                         m_tail->m_next = m_result;
  768                         m_tail = m_result;
  769                         /* update lengths, make sure it's aligned too */
  770                         m_result->m_len = SCTP_SIZE32(m_result->m_len);
  771                         m_ack->m_pkthdr.len += m_result->m_len;
  772                         ack_cp->ch.chunk_length += m_result->m_len;
  773                         /* set flag to force success reports */
  774                         error = 1;
  775                 }
  776 
  777                 offset += SCTP_SIZE32(param_length);
  778                 /* update remaining ASCONF message length to process */
  779                 if (offset >= asconf_limit) {
  780                         /* no more data in the mbuf chain */
  781                         break;
  782                 }
  783                 /* get pointer to next asconf param */
  784                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
  785                     sizeof(struct sctp_asconf_paramhdr),
  786                     (uint8_t *)&aparam_buf);
  787                 if (aph == NULL) {
  788                         /* can't get an asconf paramhdr */
  789 #ifdef SCTP_DEBUG
  790                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  791                                 printf("handle_asconf: can't get asconf param hdr!\n");
  792                         }
  793 #endif /* SCTP_DEBUG */
  794                         /* FIX ME - add error here... */
  795                 }
  796         } /* while */
  797 
  798         ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length);
  799         /* save the ASCONF-ACK reply */
  800         asoc->last_asconf_ack_sent = m_ack;
  801         /* and send (a new one) it out... */
  802         sctp_send_asconf_ack(stcb, 0);
  803 }
  804 
  805 /*
  806  * does the address match?
  807  * returns 0 if not, 1 if so
  808  */
  809 static uint32_t
  810 sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
  811 {
  812 #ifdef INET6
  813         if (sa->sa_family == AF_INET6) {
  814                 /* IPv6 sa address */
  815                 /* XXX scopeid */
  816                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
  817                 if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) &&
  818                     (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr,
  819                             sizeof(struct in6_addr)) == 0)) {
  820                         return (1);
  821                 }
  822         } else
  823 #endif /* INET6 */
  824         if (sa->sa_family == AF_INET) {
  825                 /* IPv4 sa address */
  826                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
  827                 if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) &&
  828                     (memcmp(&aa->ap.addrp.addr, &sin->sin_addr,
  829                             sizeof(struct in_addr)) == 0)) {
  830                         return (1);
  831                 }
  832         }
  833         return (0);
  834 }
  835 
  836 /*
  837  * Cleanup for non-responded/OP ERR'd ASCONF
  838  */
  839 void
  840 sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
  841 {
  842 #ifdef SCTP_DEBUG
  843         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  844                 printf("asconf_cleanup: marking peer ASCONF incapable and cleaning up\n");
  845         }
  846 #endif /* SCTP_DEBUG */
  847         /* mark peer as ASCONF incapable */
  848         stcb->asoc.peer_supports_asconf = 0;
  849         stcb->asoc.peer_supports_asconf_setprim = 0;
  850         /*
  851          * clear out any existing asconfs going out
  852          */
  853         sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net);
  854         stcb->asoc.asconf_seq_out++;
  855         /* remove the old ASCONF on our outbound queue */
  856         sctp_toss_old_asconf(stcb);
  857 }
  858 
  859 /*
  860  * process an ADD/DELETE IP ack from peer
  861  * ifa:  corresponding ifaddr to the address being added/deleted
  862  * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS
  863  * flag: 1=success, 0=failure
  864  */
  865 static void
  866 sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct ifaddr *addr,
  867     uint16_t type, uint32_t flag)
  868 {
  869 
  870         /*
  871          * do the necessary asoc list work-
  872          * if we get a failure indication, leave the address on the
  873          *   "do not use" asoc list
  874          * if we get a success indication, remove the address from
  875          *   the list
  876          */
  877         /*
  878          * Note: this will only occur for ADD_IP_ADDRESS, since
  879          * DEL_IP_ADDRESS is never actually added to the list...
  880          */
  881         if (flag) {
  882                 /* success case, so remove from the list */
  883                 sctp_del_local_addr_assoc(stcb, addr);
  884         }
  885         /* else, leave it on the list */
  886 }
  887 
  888 /*
  889  * add an asconf add/delete IP address parameter to the queue
  890  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR
  891  * returns 0 if completed, non-zero if not completed
  892  * NOTE: if adding, but delete already scheduled (and not yet
  893  *      sent out), simply remove from queue.  Same for deleting
  894  *      an address already scheduled for add.  If a duplicate
  895  *      operation is found, ignore the new one.
  896  */
  897 static uint32_t
  898 sctp_asconf_queue_add(struct sctp_tcb *stcb, struct ifaddr *ifa, uint16_t type)
  899 {
  900         struct sctp_asconf_addr *aa, *aa_next;
  901 #ifdef SCTP_DEBUG
  902         char buf[128];  /* for address in string format */
  903 #endif /* SCTP_DEBUG */
  904 
  905         /* see if peer supports ASCONF */
  906         if (stcb->asoc.peer_supports_asconf == 0) {
  907 #ifdef SCTP_DEBUG
  908                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  909                         printf("asconf_queue_add: peer doesn't support ASCONF\n");
  910                 }
  911 #endif /* SCTP_DEBUG */
  912                 return (-1);
  913         }
  914 
  915         /* make sure the request isn't already in the queue */
  916         for (aa=TAILQ_FIRST(&stcb->asoc.asconf_queue); aa!=NULL; aa=aa_next) {
  917                 aa_next = TAILQ_NEXT(aa, next);
  918                 /* address match? */
  919                 if (sctp_asconf_addr_match(aa, ifa->ifa_addr) == 0)
  920                         continue;
  921                 /* is the request already in queue (sent or not) */
  922                 if (aa->ap.aph.ph.param_type == type) {
  923 #ifdef SCTP_DEBUG
  924                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  925                                 printf("asconf_queue_add: request already exists\n");
  926                         }
  927 #endif /* SCTP_DEBUG */
  928                         return (-1);
  929                 }
  930                 /* is the negative request already in queue, and not sent */
  931                 if (aa->sent == 0 &&
  932                     /* add requested, delete already queued */
  933                     ((type == SCTP_ADD_IP_ADDRESS &&
  934                       aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) ||
  935                      /* delete requested, add already queued */
  936                      (type == SCTP_DEL_IP_ADDRESS &&
  937                       aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS))) {
  938                         /* delete the existing entry in the queue */
  939                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
  940                         /* take the entry off the appropriate list */
  941                         sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1);
  942                         /* free the entry */
  943                         free(aa, M_PCB);
  944 
  945 #ifdef SCTP_DEBUG
  946                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  947                                 printf("asconf_queue_add: removing 'opposite' queued request\n");
  948                         }
  949 #endif /* SCTP_DEBUG */
  950                         return (-1);
  951                 }
  952         } /* for each aa */
  953 
  954         /* adding new request to the queue */
  955         aa = malloc(sizeof(*aa), M_PCB, M_NOWAIT);
  956         if (aa == NULL) {
  957                 /* didn't get memory */
  958 #ifdef SCTP_DEBUG
  959                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
  960                         printf("asconf_queue_add: failed to get memory!\n");
  961                 }
  962 #endif /* SCTP_DEBUG */
  963                 return (-1);
  964         }
  965         /* fill in asconf address parameter fields */
  966         /* top level elements are "networked" during send */
  967         aa->ap.aph.ph.param_type = type;
  968         aa->ifa = ifa;
  969         /* correlation_id filled in during send routine later... */
  970         if (ifa->ifa_addr->sa_family == AF_INET6) {
  971                 /* IPv6 address */
  972 #ifdef SCTP_DEBUG
  973                 char ip6buf[INET6_ADDRSTRLEN];
  974 #endif
  975                 struct sockaddr_in6 *sin6;
  976 
  977                 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
  978                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
  979                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
  980                 aa->ap.aph.ph.param_length =
  981                     sizeof(struct sctp_asconf_paramhdr) +
  982                     sizeof(struct sctp_ipv6addr_param);
  983                 memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
  984                     sizeof(struct in6_addr));
  985 #ifdef SCTP_DEBUG
  986                 strlcpy(buf, IN6_PRINT(ip6buf, &sin6->sin6_addr), sizeof(buf));
  987 #endif /* SCTP_DEBUG */
  988 
  989         } else if (ifa->ifa_addr->sa_family == AF_INET) {
  990                 /* IPv4 address */
  991                 struct sockaddr_in *sin = (struct sockaddr_in *)ifa->ifa_addr;
  992                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
  993                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
  994                 aa->ap.aph.ph.param_length =
  995                     sizeof(struct sctp_asconf_paramhdr) +
  996                     sizeof(struct sctp_ipv4addr_param);
  997                 memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
  998                     sizeof(struct in_addr));
  999 #ifdef SCTP_DEBUG
 1000                 strlcpy(buf, inet_ntoa(sin->sin_addr), sizeof(buf));
 1001 #endif /* SCTP_DEBUG */
 1002         } else {
 1003                 /* invalid family! */
 1004                 return (-1);
 1005         }
 1006         aa->sent = 0;                   /* clear sent flag */
 1007 
 1008         /*
 1009          * if we are deleting an address it should go out last
 1010          * otherwise, add it to front of the pending queue
 1011          */
 1012         if (type == SCTP_ADD_IP_ADDRESS) {
 1013                 /* add goes to the front of the queue */
 1014                 TAILQ_INSERT_HEAD(&stcb->asoc.asconf_queue, aa, next);
 1015 #ifdef SCTP_DEBUG
 1016                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1017                         printf("asconf_queue_add: appended asconf ADD_IP_ADDRESS: %s\n", buf);
 1018                 }
 1019 #endif /* SCTP_DEBUG */
 1020         } else {
 1021                 /* delete and set primary goes to the back of the queue */
 1022                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 1023 #ifdef SCTP_DEBUG
 1024                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1025                         if (type == SCTP_DEL_IP_ADDRESS) {
 1026                                 printf("asconf_queue_add: inserted asconf DEL_IP_ADDRESS: %s\n", buf);
 1027                         } else {
 1028                                 printf("asconf_queue_add: inserted asconf SET_PRIM_ADDR: %s\n", buf);
 1029                         }
 1030                 }
 1031 #endif /* SCTP_DEBUG */
 1032         }
 1033 
 1034         return (0);
 1035 }
 1036 
 1037 /*
 1038  * add an asconf add/delete IP address parameter to the queue by addr
 1039  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR
 1040  * returns 0 if completed, non-zero if not completed
 1041  * NOTE: if adding, but delete already scheduled (and not yet
 1042  *      sent out), simply remove from queue.  Same for deleting
 1043  *      an address already scheduled for add.  If a duplicate
 1044  *      operation is found, ignore the new one.
 1045  */
 1046 static uint32_t
 1047 sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa,
 1048     uint16_t type)
 1049 {
 1050         struct sctp_asconf_addr *aa, *aa_next;
 1051 
 1052         /* see if peer supports ASCONF */
 1053         if (stcb->asoc.peer_supports_asconf == 0) {
 1054 #ifdef SCTP_DEBUG
 1055                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1056                         printf("asconf_queue_add_sa: peer doesn't support ASCONF\n");
 1057                 }
 1058 #endif /* SCTP_DEBUG */
 1059                 return (-1);
 1060         }
 1061 
 1062         /* make sure the request isn't already in the queue */
 1063         for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
 1064             aa = aa_next) {
 1065                 aa_next = TAILQ_NEXT(aa, next);
 1066                 /* address match? */
 1067                 if (sctp_asconf_addr_match(aa, sa) == 0)
 1068                         continue;
 1069                 /* is the request already in queue (sent or not) */
 1070                 if (aa->ap.aph.ph.param_type == type) {
 1071 #ifdef SCTP_DEBUG
 1072                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1073                                 printf("asconf_queue_add_sa: request already exists\n");
 1074                         }
 1075 #endif /* SCTP_DEBUG */
 1076                         return (-1);
 1077                 }
 1078 
 1079                 /* is the negative request already in queue, and not sent */
 1080                 if (aa->sent == 1)
 1081                         continue;
 1082                 if (type == SCTP_ADD_IP_ADDRESS &&
 1083                     aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
 1084                         /* add requested, delete already queued */
 1085 
 1086                         /* delete the existing entry in the queue */
 1087                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1088                         /* free the entry */
 1089                         free(aa, M_PCB);
 1090 #ifdef SCTP_DEBUG
 1091                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1092                                 printf("asconf_queue_add_sa: removing queued delete request\n");
 1093                         }
 1094 #endif /* SCTP_DEBUG */
 1095                         return (-1);
 1096                 } else if (type == SCTP_DEL_IP_ADDRESS &&
 1097                            aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) {
 1098                         /* delete requested, add already queued */
 1099 
 1100                         /* delete the existing entry in the queue */
 1101                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1102                         /* take the entry off the appropriate list */
 1103                         sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1);
 1104                         /* free the entry */
 1105                         free(aa, M_PCB);
 1106 #ifdef SCTP_DEBUG
 1107                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1108                                 printf("asconf_queue_add_sa: removing queued add request\n");
 1109                         }
 1110 #endif /* SCTP_DEBUG */
 1111                         return (-1);
 1112                 }
 1113         } /* for each aa */
 1114 
 1115         /* adding new request to the queue */
 1116         aa = malloc(sizeof(*aa), M_PCB, M_NOWAIT);
 1117         if (aa == NULL) {
 1118                 /* didn't get memory */
 1119 #ifdef SCTP_DEBUG
 1120                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1121                         printf("asconf_queue_add_sa: failed to get memory!\n");
 1122                 }
 1123 #endif /* SCTP_DEBUG */
 1124                 return (-1);
 1125         }
 1126         /* fill in asconf address parameter fields */
 1127         /* top level elements are "networked" during send */
 1128         aa->ap.aph.ph.param_type = type;
 1129         aa->ifa = sctp_find_ifa_by_addr(sa);
 1130         /* correlation_id filled in during send routine later... */
 1131         if (sa->sa_family == AF_INET6) {
 1132                 /* IPv6 address */
 1133                 struct sockaddr_in6 *sin6;
 1134 
 1135                 sin6 = (struct sockaddr_in6 *)sa;
 1136                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 1137                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
 1138                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
 1139                 memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
 1140                     sizeof(struct in6_addr));
 1141         } else if (sa->sa_family == AF_INET) {
 1142                 /* IPv4 address */
 1143                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
 1144                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 1145                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
 1146                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
 1147                 memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
 1148                     sizeof(struct in_addr));
 1149         } else {
 1150                 /* invalid family! */
 1151                 return (-1);
 1152         }
 1153         aa->sent = 0;                   /* clear sent flag */
 1154 
 1155         /*
 1156          * if we are deleting an address it should go out last
 1157          * otherwise, add it to front of the pending queue
 1158          */
 1159         if (type == SCTP_ADD_IP_ADDRESS) {
 1160                 /* add goes to the front of the queue */
 1161                 TAILQ_INSERT_HEAD(&stcb->asoc.asconf_queue, aa, next);
 1162 #ifdef SCTP_DEBUG
 1163                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1164                         printf("asconf_queue_add_sa: appended asconf ADD_IP_ADDRESS\n");
 1165                 }
 1166 #endif /* SCTP_DEBUG */
 1167         } else {
 1168                 /* delete and set primary goes to the back of the queue */
 1169                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 1170 #ifdef SCTP_DEBUG
 1171                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1172                         if (type == SCTP_DEL_IP_ADDRESS) {
 1173                                 printf("asconf_queue_add_sa: inserted asconf DEL_IP_ADDRESS\n");
 1174                         } else {
 1175                                 printf("asconf_queue_add_sa: inserted asconf SET_PRIM_ADDR\n");
 1176                         }
 1177                 }
 1178 #endif /* SCTP_DEBUG */
 1179         }
 1180 
 1181         return (0);
 1182 }
 1183 
 1184 /*
 1185  * find a specific asconf param on our "sent" queue
 1186  */
 1187 static struct sctp_asconf_addr *
 1188 sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
 1189 {
 1190         struct sctp_asconf_addr *aa;
 1191 
 1192         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 1193                 if (aa->ap.aph.correlation_id == correlation_id &&
 1194                     aa->sent == 1) {
 1195                         /* found it */
 1196                         return (aa);
 1197                 }
 1198         }
 1199         /* didn't find it */
 1200         return (NULL);
 1201 }
 1202 
 1203 /*
 1204  * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter
 1205  * and do notifications based on the error response
 1206  */
 1207 static void
 1208 sctp_asconf_process_error(struct sctp_tcb *stcb,
 1209     struct sctp_asconf_paramhdr *aph)
 1210 {
 1211         struct sctp_error_cause *eh;
 1212         struct sctp_paramhdr *ph;
 1213         uint16_t param_type;
 1214         uint16_t error_code;
 1215 
 1216         eh = (struct sctp_error_cause *)(aph + 1);
 1217         ph = (struct sctp_paramhdr *)(eh + 1);
 1218         /* validate lengths */
 1219         if (htons(eh->length) + sizeof(struct sctp_error_cause) >
 1220             htons(aph->ph.param_length)) {
 1221                 /* invalid error cause length */
 1222 #ifdef SCTP_DEBUG
 1223                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1224                         printf("asconf_process_error: cause element too long\n");
 1225                 }
 1226 #endif /* SCTP_DEBUG */
 1227                 return;
 1228         }
 1229         if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) >
 1230             htons(eh->length)) {
 1231                 /* invalid included TLV length */
 1232 #ifdef SCTP_DEBUG
 1233                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1234                         printf("asconf_process_error: included TLV too long\n");
 1235                 }
 1236 #endif /* SCTP_DEBUG */
 1237                 return;
 1238         }
 1239 
 1240         /* which error code ? */
 1241         error_code = ntohs(eh->code);
 1242         param_type = ntohs(aph->ph.param_type);
 1243         /* FIX: this should go back up the REMOTE_ERROR ULP notify */
 1244         switch (error_code) {
 1245         case SCTP_ERROR_RESOURCE_SHORTAGE:
 1246                 /* we allow ourselves to "try again" for this error */
 1247                 break;
 1248         default:
 1249                 /* peer can't handle it... */
 1250                 switch (param_type) {
 1251                 case SCTP_ADD_IP_ADDRESS:
 1252                 case SCTP_DEL_IP_ADDRESS:
 1253                         stcb->asoc.peer_supports_asconf = 0;
 1254                         break;
 1255                 case SCTP_SET_PRIM_ADDR:
 1256                         stcb->asoc.peer_supports_asconf_setprim = 0;
 1257                         break;
 1258                 default:
 1259                         break;
 1260                 }
 1261         }
 1262 }
 1263 
 1264 /*
 1265  * process an asconf queue param
 1266  * aparam: parameter to process, will be removed from the queue
 1267  * flag: 1=success, 0=failure
 1268  */
 1269 static void
 1270 sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
 1271     struct sctp_asconf_addr *aparam, uint32_t flag)
 1272 {
 1273         uint16_t param_type;
 1274 
 1275         /* process this param */
 1276         param_type = aparam->ap.aph.ph.param_type;
 1277 #ifdef SCTP_DEBUG
 1278         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1279                 printf("process_param_ack: handling asconf parameter type=%xh\n", param_type);
 1280         }
 1281 #endif /* SCTP_DEBUG */
 1282         switch (param_type) {
 1283         case SCTP_ADD_IP_ADDRESS:
 1284 #ifdef SCTP_DEBUG
 1285                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1286                         printf("process_param_ack: added IP address\n");
 1287                 }
 1288 #endif /* SCTP_DEBUG */
 1289                 sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, param_type, flag);
 1290                 break;
 1291         case SCTP_DEL_IP_ADDRESS:
 1292 #ifdef SCTP_DEBUG
 1293                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1294                         printf("process_param_ack: deleted IP address\n");
 1295                 }
 1296 #endif /* SCTP_DEBUG */
 1297                 /* nothing really to do... lists already updated */
 1298                 break;
 1299         case SCTP_SET_PRIM_ADDR:
 1300                 /* nothing to do... peer may start using this addr */
 1301                 if (flag == 0)
 1302                         stcb->asoc.peer_supports_asconf_setprim = 0;
 1303                 break;
 1304         default:
 1305                 /* should NEVER happen */
 1306                 break;
 1307         } /* switch */
 1308 
 1309         /* remove the param and free it */
 1310         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
 1311         free(aparam, M_PCB);
 1312 }
 1313 
 1314 /*
 1315  * cleanup from a bad asconf ack parameter
 1316  */
 1317 static void
 1318 sctp_asconf_ack_clear(struct sctp_tcb *stcb)
 1319 {
 1320         /* assume peer doesn't really know how to do asconfs */
 1321         stcb->asoc.peer_supports_asconf = 0;
 1322         stcb->asoc.peer_supports_asconf_setprim = 0;
 1323         /* XXX we could free the pending queue here */
 1324 }
 1325 
 1326 void
 1327 sctp_handle_asconf_ack(struct mbuf *m, int offset,
 1328     struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb,
 1329     struct sctp_nets *net)
 1330 {
 1331         struct sctp_association *asoc;
 1332         uint32_t serial_num;
 1333         uint16_t ack_length;
 1334         struct sctp_asconf_paramhdr *aph;
 1335         struct sctp_asconf_addr *aa, *aa_next;
 1336         uint32_t last_error_id = 0;             /* last error correlation id */
 1337         uint32_t id;
 1338         struct sctp_asconf_addr *ap;
 1339         /* asconf param buffer */
 1340         static u_int8_t aparam_buf[DEFAULT_PARAM_BUFFER];
 1341 
 1342         /* verify minimum length */
 1343         if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) {
 1344 #ifdef SCTP_DEBUG
 1345                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1346                         printf("handle_asconf_ack: chunk too small = %xh\n",
 1347                                ntohs(cp->ch.chunk_length));
 1348                 }
 1349 #endif /* SCTP_DEBUG */
 1350                 return;
 1351         }
 1352 
 1353         asoc = &stcb->asoc;
 1354         serial_num = ntohl(cp->serial_number);
 1355 
 1356         /*
 1357          * NOTE: we may want to handle this differently- currently, we
 1358          * will abort when we get an ack for the expected serial number + 1
 1359          * (eg. we didn't send it), process an ack normally if it is the
 1360          * expected serial number, and re-send the previous ack for *ALL*
 1361          * other serial numbers
 1362          */
 1363 
 1364         /*
 1365          * if the serial number is the next expected, but I didn't send it,
 1366          * abort the asoc, since someone probably just hijacked us...
 1367          */
 1368         if (serial_num == (asoc->asconf_seq_out + 1)) {
 1369                 sctp_abort_an_association(stcb->sctp_ep, stcb,
 1370                     SCTP_ERROR_ILLEGAL_ASCONF_ACK, NULL);
 1371 #ifdef SCTP_DEBUG
 1372                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1373                         printf("handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
 1374                 }
 1375 #endif /* SCTP_DEBUG */
 1376                 return;
 1377         }
 1378 
 1379         if (serial_num != asoc->asconf_seq_out) {
 1380                 /* got a duplicate/unexpected ASCONF-ACK */
 1381 #ifdef SCTP_DEBUG
 1382                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1383                         printf("handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n", serial_num, asoc->asconf_seq_out);
 1384                 }
 1385 #endif /* SCTP_DEBUG */
 1386                 return;
 1387         }
 1388         /* stop our timer */
 1389         sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net);
 1390 
 1391         /* process the ASCONF-ACK contents */
 1392         ack_length = ntohs(cp->ch.chunk_length) -
 1393             sizeof(struct sctp_asconf_ack_chunk);
 1394         offset += sizeof(struct sctp_asconf_ack_chunk);
 1395         /* process through all parameters */
 1396         while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) {
 1397                 unsigned int param_length, param_type;
 1398 
 1399                 /* get pointer to next asconf parameter */
 1400                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
 1401                     sizeof(struct sctp_asconf_paramhdr), aparam_buf);
 1402                 if (aph == NULL) {
 1403                         /* can't get an asconf paramhdr */
 1404                         sctp_asconf_ack_clear(stcb);
 1405                         return;
 1406                 }
 1407                 param_type = ntohs(aph->ph.param_type);
 1408                 param_length = ntohs(aph->ph.param_length);
 1409                 if (param_length > ack_length) {
 1410                         sctp_asconf_ack_clear(stcb);
 1411                         return;
 1412                 }
 1413                 if (param_length < sizeof(struct sctp_paramhdr)) {
 1414                         sctp_asconf_ack_clear(stcb);
 1415                         return;
 1416                 }
 1417 
 1418                 /* get the complete parameter... */
 1419                 if (param_length > sizeof(aparam_buf)) {
 1420 #ifdef SCTP_DEBUG
 1421                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1422                                 printf("param length (%u) larger than buffer size!\n", param_length);
 1423                         }
 1424 #endif /* SCTP_DEBUG */
 1425                         sctp_asconf_ack_clear(stcb);
 1426                         return;
 1427                 }
 1428                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
 1429                 if (aph == NULL) {
 1430                         sctp_asconf_ack_clear(stcb);
 1431                         return;
 1432                 }
 1433                 /* correlation_id is transparent to peer, no ntohl needed */
 1434                 id = aph->correlation_id;
 1435 
 1436                 switch (param_type) {
 1437                 case SCTP_ERROR_CAUSE_IND:
 1438                         last_error_id = id;
 1439                         /* find the corresponding asconf param in our queue */
 1440                         ap = sctp_asconf_find_param(stcb, id);
 1441                         if (ap == NULL) {
 1442                                 /* hmm... can't find this in our queue! */
 1443                                 break;
 1444                         }
 1445                         /* process the parameter, failed flag */
 1446                         sctp_asconf_process_param_ack(stcb, ap, 0);
 1447                         /* process the error response */
 1448                         sctp_asconf_process_error(stcb, aph);
 1449                         break;
 1450                 case SCTP_SUCCESS_REPORT:
 1451                         /* find the corresponding asconf param in our queue */
 1452                         ap = sctp_asconf_find_param(stcb, id);
 1453                         if (ap == NULL) {
 1454                                 /* hmm... can't find this in our queue! */
 1455                                 break;
 1456                         }
 1457                         /* process the parameter, success flag */
 1458                         sctp_asconf_process_param_ack(stcb, ap, 1);
 1459                         break;
 1460                 default:
 1461                         break;
 1462                 } /* switch */
 1463 
 1464                 /* update remaining ASCONF-ACK message length to process */
 1465                 ack_length -= SCTP_SIZE32(param_length);
 1466                 if (ack_length <= 0) {
 1467                         /* no more data in the mbuf chain */
 1468                         break;
 1469                 }
 1470                 offset += SCTP_SIZE32(param_length);
 1471         } /* while */
 1472 
 1473         /*
 1474          * if there are any "sent" params still on the queue, these are
 1475          * implicitly "success", or "failed" (if we got an error back)
 1476          * ... so process these appropriately
 1477          *
 1478          * we assume that the correlation_id's are monotonically increasing
 1479          * beginning from 1 and that we don't have *that* many outstanding
 1480          * at any given time
 1481          */
 1482         if (last_error_id == 0)
 1483                 last_error_id--;        /* set to "max" value */
 1484         for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
 1485             aa = aa_next) {
 1486                 aa_next = TAILQ_NEXT(aa, next);
 1487                 if (aa->sent == 1) {
 1488                         /*
 1489                          * implicitly successful or failed
 1490                          * if correlation_id < last_error_id, then success
 1491                          * else, failure
 1492                          */
 1493                         if (aa->ap.aph.correlation_id < last_error_id)
 1494                                 sctp_asconf_process_param_ack(stcb, aa,
 1495                                     SCTP_SUCCESS_REPORT);
 1496                         else
 1497                                 sctp_asconf_process_param_ack(stcb, aa,
 1498                                     SCTP_ERROR_CAUSE_IND);
 1499                 } else {
 1500                         /*
 1501                          * since we always process in order (FIFO queue)
 1502                          * if we reach one that hasn't been sent, the
 1503                          * rest should not have been sent either.
 1504                          * so, we're done...
 1505                          */
 1506                         break;
 1507                 }
 1508         }
 1509 
 1510         /* update the next sequence number to use */
 1511         asoc->asconf_seq_out++;
 1512         /* remove the old ASCONF on our outbound queue */
 1513         sctp_toss_old_asconf(stcb);
 1514         /* clear the sent flag to allow new ASCONFs */
 1515         asoc->asconf_sent = 0;
 1516         if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
 1517                 /* we have more params, so restart our timer */
 1518                 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep,
 1519                     stcb, net);
 1520         }
 1521 }
 1522 
 1523 /* is this an interface that we care about at all? */
 1524 static uint32_t
 1525 sctp_is_desired_interface_type(struct ifaddr *ifa)
 1526 {
 1527         int result;
 1528 
 1529         /* check the interface type to see if it's one we care about */
 1530         switch (ifa->ifa_ifp->if_type) {
 1531         case IFT_ETHER:
 1532         case IFT_ISO88023:
 1533         case IFT_ISO88025:
 1534         case IFT_STARLAN:
 1535         case IFT_P10:
 1536         case IFT_P80:
 1537         case IFT_HY:
 1538         case IFT_FDDI:
 1539         case IFT_PPP:
 1540         case IFT_XETHER:
 1541         case IFT_SLIP:
 1542         case IFT_GIF:
 1543                 result = 1;
 1544                 break;
 1545         default:
 1546 #ifdef SCTP_DEBUG
 1547                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1548                         printf("ignoring interface type = %u\n",
 1549                                ifa->ifa_ifp->if_type);
 1550                 }
 1551 #endif /* SCTP_DEBUG */
 1552                 result = 0;
 1553         } /* end switch */
 1554 
 1555         return (result);
 1556 }
 1557 
 1558 static uint32_t
 1559 sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa)
 1560 {
 1561         struct sockaddr_in6 *sin6;
 1562         const struct sockaddr_in6 *net6;
 1563         struct sctp_nets *net;
 1564 
 1565         if (sa->sa_family != AF_INET6) {
 1566                 /* wrong family */
 1567                 return (0);
 1568         }
 1569 
 1570         sin6 = (struct sockaddr_in6 *)sa;
 1571         if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) {
 1572                 /* not link local address */
 1573                 return (0);
 1574         }
 1575         /* hunt through our destination nets list for this scope_id */
 1576         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1577                 if ((rtcache_getdst(&net->ro))->sa_family !=
 1578                     AF_INET6)
 1579                         continue;
 1580                 net6 = (const struct sockaddr_in6 *)rtcache_getdst(&net->ro);
 1581                 if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0)
 1582                         continue;
 1583                 if (sctp_is_same_scope(sin6, net6)) {
 1584                         /* found one */
 1585                         return (1);
 1586                 }
 1587         }
 1588         /* didn't find one */
 1589         return (0);
 1590 }
 1591 
 1592 /*
 1593  * address management functions
 1594  */
 1595 static void
 1596 sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
 1597     struct ifaddr *ifa, uint16_t type)
 1598 {
 1599         int status;
 1600 #ifdef SCTP_DEBUG
 1601         char buf[128];  /* for address in string format */
 1602 #endif /* SCTP_DEBUG */
 1603 
 1604         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 &&
 1605             (inp->sctp_flags & SCTP_PCB_FLAGS_DO_ASCONF) == 0) {
 1606                 /* subset bound, no ASCONF allowed case, so ignore */
 1607                 return;
 1608         }
 1609 
 1610         /*
 1611          * note: we know this is not the subset bound, no ASCONF case
 1612          *      eg. this is boundall or subset bound w/ASCONF allowed
 1613          */
 1614 
 1615         /* first, make sure it's a good address family */
 1616         if (ifa->ifa_addr->sa_family != AF_INET6 &&
 1617             ifa->ifa_addr->sa_family != AF_INET) {
 1618                 return;
 1619         }
 1620 
 1621         /* make sure we're "allowed" to add this type of addr */
 1622         if (ifa->ifa_addr->sa_family == AF_INET6) {
 1623                 struct in6_ifaddr *ifa6;
 1624 
 1625                 /* invalid if we're not a v6 endpoint */
 1626                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)
 1627                         return;
 1628                 /* is the v6 addr really valid ? */
 1629                 ifa6 = (struct in6_ifaddr *)ifa;
 1630                 if (IFA6_IS_DEPRECATED(ifa6) ||
 1631                     (ifa6->ia6_flags &
 1632                      (IN6_IFF_DETACHED | IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) {
 1633                         /* can't use an invalid address */
 1634                         return;
 1635                 }
 1636         }
 1637 
 1638         /* put this address on the "pending/do not use yet" list */
 1639         /*
 1640          * Note: we do this primarily for the subset bind case
 1641          * We don't have scoping flags at the EP level, so we must
 1642          * add link local/site local addresses to the EP, then need
 1643          * to "negate" them here.  Recall that this routine is only
 1644          * called for the subset bound w/ASCONF allowed case.
 1645          */
 1646 
 1647         /*
 1648          * do a scope_id check against any link local addresses
 1649          * in the destination nets list to see if we should put
 1650          * this local address on the pending list or not
 1651          * eg. don't put on the list if we have a link local
 1652          * destination with the same scope_id
 1653          */
 1654         if (type == SCTP_ADD_IP_ADDRESS) {
 1655                 if (sctp_is_scopeid_in_nets(stcb, ifa->ifa_addr) == 0) {
 1656                         sctp_add_local_addr_assoc(stcb, ifa);
 1657 #ifdef SCTP_DEBUG
 1658                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1659                                 printf("addr_mgmt_assoc: added to pending list ");
 1660                                 sctp_print_address(ifa->ifa_addr);
 1661                         }
 1662 #endif /* SCTP_DEBUG */
 1663                 }
 1664         }
 1665         /*
 1666          * check address scope
 1667          * if address is out of scope, don't queue anything...
 1668          * note: this would leave the address on both inp and asoc lists
 1669          */
 1670         if (ifa->ifa_addr->sa_family == AF_INET6) {
 1671 #ifdef SCTP_DEBUG
 1672                 char ip6buf[INET6_ADDRSTRLEN];
 1673 #endif /* SCTP_DEBUG */
 1674                 struct sockaddr_in6 *sin6;
 1675 
 1676                 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
 1677 #ifdef SCTP_DEBUG
 1678                 strlcpy(buf, IN6_PRINT(ip6buf, &sin6->sin6_addr), sizeof(buf));
 1679 #endif /* SCTP_DEBUG */
 1680                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 1681                         /* we skip unspecifed addresses */
 1682 #ifdef SCTP_DEBUG
 1683                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1684                                 printf("addr_mgmt_assoc: unspecified IPv6 addr\n");
 1685                         }
 1686 #endif /* SCTP_DEBUG */
 1687                         return;
 1688                 }
 1689                 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 1690                         if (stcb->asoc.local_scope == 0) {
 1691 #ifdef SCTP_DEBUG
 1692                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1693                                         printf("addr_mgmt_assoc: skipping link local IPv6 addr: %s\n", buf);
 1694                                 }
 1695 #endif /* SCTP_DEBUG */
 1696                                 return;
 1697                         }
 1698                         /* is it the right link local scope? */
 1699                         if (sctp_is_scopeid_in_nets(stcb, ifa->ifa_addr) == 0) {
 1700 #ifdef SCTP_DEBUG
 1701                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1702                                         printf("addr_mgmt_assoc: skipping link local IPv6 addr: %s, wrong scope_id\n", buf);
 1703                                 }
 1704 #endif /* SCTP_DEBUG */
 1705                                 return;
 1706                         }
 1707                 }
 1708                 if (stcb->asoc.site_scope == 0 &&
 1709                     IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
 1710 #ifdef SCTP_DEBUG
 1711                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1712                                 printf("addr_mgmt_assoc: skipping site local IPv6 addr: %s\n", buf);
 1713                         }
 1714 #endif /* SCTP_DEBUG */
 1715                         return;
 1716                 }
 1717         } else if (ifa->ifa_addr->sa_family == AF_INET) {
 1718                 struct sockaddr_in *sin;
 1719                 struct in6pcb *inp6;
 1720 
 1721                 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 1722                 /* invalid if we are a v6 only endpoint */
 1723                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 1724                     (inp6->in6p_flags & IN6P_IPV6_V6ONLY)
 1725                         )
 1726                         return;
 1727 
 1728                 sin = (struct sockaddr_in *)ifa->ifa_addr;
 1729 #ifdef SCTP_DEBUG
 1730                 strlcpy(buf, inet_ntoa(sin->sin_addr), sizeof(buf));
 1731 #endif /* SCTP_DEBUG */
 1732                 if (sin->sin_addr.s_addr == 0) {
 1733                         /* we skip unspecifed addresses */
 1734 #ifdef SCTP_DEBUG
 1735                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1736                                 printf("addr_mgmt_assoc: unspecified IPv4 addr\n");
 1737                         }
 1738 #endif /* SCTP_DEBUG */
 1739                         return;
 1740                 }
 1741                 if (stcb->asoc.ipv4_local_scope == 0 &&
 1742                     IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
 1743 #ifdef SCTP_DEBUG
 1744                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1745                                 printf("addr_mgmt_assoc: skipping private IPv4 addr: %s\n", buf);
 1746                         }
 1747 #endif /* SCTP_DEBUG */
 1748                         return;
 1749                 }
 1750         } else {
 1751                 /* else, not AF_INET or AF_INET6, so skip */
 1752 #ifdef SCTP_DEBUG
 1753                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1754                         printf("addr_mgmt_assoc: not AF_INET or AF_INET6\n");
 1755                 }
 1756 #endif /* SCTP_DEBUG */
 1757                 return;
 1758         }
 1759 
 1760         /* queue an asconf for this address add/delete */
 1761         if (inp->sctp_flags & SCTP_PCB_FLAGS_DO_ASCONF) {
 1762                 /* does the peer do asconf? */
 1763                 if (stcb->asoc.peer_supports_asconf) {
 1764                         /* queue an asconf for this addr */
 1765                         status = sctp_asconf_queue_add(stcb, ifa, type);
 1766                         /*
 1767                          * if queued ok, and in correct state, set the
 1768                          * ASCONF timer
 1769                          * if in non-open state, we will set this timer
 1770                          * when the state does go open and do all the
 1771                          * asconf's
 1772                          */
 1773                         if (status == 0 &&
 1774                             SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 1775                                 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
 1776                                     stcb, stcb->asoc.primary_destination);
 1777                         }
 1778                 }
 1779         } else {
 1780                 /* this is the boundall, no ASCONF case */
 1781 #if 0 /* assume kernel will delete this very shortly; add done above */
 1782                 if (type == SCTP_DEL_IP_ADDRESS) {
 1783                         /* if deleting, add this addr to the do not use list */
 1784                         sctp_add_local_addr_assoc(stcb, ifa);
 1785                 }
 1786 #endif
 1787         }
 1788 }
 1789 
 1790 static void
 1791 sctp_addr_mgmt_ep(struct sctp_inpcb *inp, struct ifaddr *ifa, uint16_t type)
 1792 {
 1793         struct sctp_tcb *stcb;
 1794         int s;
 1795 
 1796         SCTP_INP_WLOCK(inp);
 1797         /* make sure we're "allowed" to add this type of addr */
 1798         if (ifa->ifa_addr->sa_family == AF_INET6) {
 1799                 struct in6_ifaddr *ifa6;
 1800 
 1801                 /* invalid if we're not a v6 endpoint */
 1802                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
 1803                         SCTP_INP_WUNLOCK(inp);
 1804                         return;
 1805                 }
 1806                 /* is the v6 addr really valid ? */
 1807                 ifa6 = (struct in6_ifaddr *)ifa;
 1808                 if (IFA6_IS_DEPRECATED(ifa6) ||
 1809                     (ifa6->ia6_flags &
 1810                      (IN6_IFF_DETACHED | IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) {
 1811                         /* can't use an invalid address */
 1812                         SCTP_INP_WUNLOCK(inp);
 1813                         return;
 1814                 }
 1815         } else if (ifa->ifa_addr->sa_family == AF_INET) {
 1816                 /* invalid if we are a v6 only endpoint */
 1817                 struct in6pcb *inp6;
 1818                 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 1819 
 1820                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 1821                     (inp6->in6p_flags & IN6P_IPV6_V6ONLY)
 1822                         ) {
 1823                         SCTP_INP_WUNLOCK(inp);
 1824                         return;
 1825                 }
 1826         } else {
 1827                 /* invalid address family */
 1828                 SCTP_INP_WUNLOCK(inp);
 1829                 return;
 1830         }
 1831         /* is this endpoint subset bound ? */
 1832         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
 1833                 /* subset bound endpoint */
 1834                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_DO_ASCONF) == 0) {
 1835                         /*
 1836                          * subset bound, but ASCONFs not allowed...
 1837                          * if adding, nothing to do, since not allowed
 1838                          * if deleting, remove address from endpoint
 1839                          *      peer will have to "timeout" this addr
 1840                          */
 1841                         if (type == SCTP_DEL_IP_ADDRESS) {
 1842                                 sctp_del_local_addr_ep(inp, ifa);
 1843                         }
 1844                         /* no asconfs to queue for this inp... */
 1845                         SCTP_INP_WUNLOCK(inp);
 1846                         return;
 1847                 } else {
 1848                         /*
 1849                          * subset bound, ASCONFs allowed...
 1850                          * if adding, add address to endpoint list
 1851                          * if deleting, remove address from endpoint
 1852                          */
 1853                         if (type == SCTP_ADD_IP_ADDRESS) {
 1854                                 sctp_add_local_addr_ep(inp, ifa);
 1855                         } else {
 1856                                 sctp_del_local_addr_ep(inp, ifa);
 1857                         }
 1858                         /* drop through and notify all asocs */
 1859                 }
 1860         }
 1861 
 1862         s = splsoftnet();
 1863         /* process for all associations for this endpoint */
 1864         LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
 1865                 SCTP_TCB_LOCK(stcb);
 1866                 sctp_addr_mgmt_assoc(inp, stcb, ifa, type);
 1867                 SCTP_TCB_UNLOCK(stcb);
 1868         } /* for each stcb */
 1869         splx(s);
 1870         SCTP_INP_WUNLOCK(inp);
 1871 }
 1872 
 1873 /*
 1874  * restrict the use of this address
 1875  */
 1876 static void
 1877 sctp_addr_mgmt_restrict_ep(struct sctp_inpcb *inp, struct ifaddr *ifa)
 1878 {
 1879         struct sctp_tcb *stcb;
 1880         int s;
 1881 
 1882         /* is this endpoint bound to all? */
 1883         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
 1884                 /*
 1885                  * Nothing to do for subset bound case.
 1886                  * Allow sctp_bindx() to manage the address lists
 1887                  */
 1888                 return;
 1889         }
 1890 
 1891         s = splsoftnet();
 1892         SCTP_INP_RLOCK(inp);
 1893         /* process for all associations for this endpoint */
 1894         LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
 1895                 /* put this address on the "pending/do not use yet" list */
 1896                 SCTP_TCB_LOCK(stcb);
 1897                 sctp_add_local_addr_assoc(stcb, ifa);
 1898                 SCTP_TCB_UNLOCK(stcb);
 1899 #ifdef SCTP_DEBUG
 1900                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1901                         printf("restrict_ep: added addr to unusable list\n");
 1902                 }
 1903 #endif /* SCTP_DEBUG */
 1904         } /* for each stcb */
 1905         splx(s);
 1906         SCTP_INP_RUNLOCK(inp);
 1907 }
 1908 
 1909 /*
 1910  * this is only called for kernel initiated address changes
 1911  * eg. it will check the PCB_FLAGS_AUTO_ASCONF flag
 1912  */
 1913 static void
 1914 sctp_addr_mgmt(struct ifaddr *ifa, uint16_t type) {
 1915         struct sockaddr *sa;
 1916         struct sctp_inpcb *inp;
 1917 
 1918         /* make sure we care about this interface... */
 1919         if (!sctp_is_desired_interface_type(ifa)) {
 1920 #ifdef SCTP_DEBUG
 1921                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1922                         printf("sctp_addr_mgmt: ignoring this interface\n");
 1923                 }
 1924 #endif /* SCTP_DEBUG */
 1925                 return;
 1926         }
 1927 
 1928         sa = ifa->ifa_addr;
 1929         if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
 1930                 return;
 1931 
 1932 #ifdef SCTP_DEBUG
 1933         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1934                 if (type == SCTP_ADD_IP_ADDRESS)
 1935                         printf("sctp_addr_mgmt: kernel adds ");
 1936                 else
 1937                         printf("sctp_addr_mgmt: kernel deletes ");
 1938                 sctp_print_address(sa);
 1939         }
 1940 #endif /* SCTP_DEBUG */
 1941 
 1942         /* go through all our PCB's */
 1943         LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) {
 1944                 if (inp->sctp_flags & SCTP_PCB_FLAGS_AUTO_ASCONF) {
 1945                         sctp_addr_mgmt_ep(inp, ifa, type);
 1946                 } else {
 1947                         /* this address is going away anyways... */
 1948                         if (type == SCTP_DEL_IP_ADDRESS)
 1949                                 return;
 1950                         /* (temporarily) restrict this address */
 1951                         sctp_addr_mgmt_restrict_ep(inp, ifa);
 1952                 }
 1953                 /* else, not allowing automatic asconf's, so ignore */
 1954         } /* for each inp */
 1955 }
 1956 
 1957 /*
 1958  * add/delete IP address requests from kernel (via routing change)
 1959  * assumed that the address is non-broadcast, non-multicast
 1960  * all addresses are passed from any type of interface-- need to filter
 1961  * duplicate addresses may get requested
 1962  */
 1963 
 1964 void
 1965 sctp_add_ip_address(struct ifaddr *ifa)
 1966 {
 1967         sctp_addr_mgmt(ifa, SCTP_ADD_IP_ADDRESS);
 1968 }
 1969 
 1970 void
 1971 sctp_delete_ip_address(struct ifaddr *ifa)
 1972 {
 1973         struct sctp_inpcb *inp;
 1974 
 1975         /* process the delete */
 1976         sctp_addr_mgmt(ifa, SCTP_DEL_IP_ADDRESS);
 1977 
 1978         /*
 1979          * need to remove this ifaddr from any cached routes
 1980          * and also any from any assoc "restricted/pending" lists
 1981          */
 1982         /* make sure we care about this interface... */
 1983         if (!sctp_is_desired_interface_type(ifa)) {
 1984 #ifdef SCTP_DEBUG
 1985                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 1986                         printf("sctp_delete_ip_address: ignoring this interface\n");
 1987                 }
 1988 #endif /* SCTP_DEBUG */
 1989                 return;
 1990         }
 1991 
 1992         /* go through all our PCB's */
 1993         SCTP_INP_INFO_RLOCK();
 1994         LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) {
 1995                 struct sctp_tcb *stcb;
 1996                 struct sctp_laddr *laddr, *laddr_next;
 1997 
 1998                 /* process for all associations for this endpoint */
 1999                 SCTP_INP_RLOCK(inp);
 2000                 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
 2001                         struct sctp_nets *net;
 2002 
 2003                         /* process through the nets list */
 2004                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 2005                                 rtcache_free(&net->ro); /* XXX - was clear */
 2006                         } /* for each net */
 2007                         /* process through the asoc "pending" list */
 2008                         laddr = LIST_FIRST(&stcb->asoc.sctp_local_addr_list);
 2009                         while (laddr != NULL) {
 2010                                 laddr_next = LIST_NEXT(laddr, sctp_nxt_addr);
 2011                                 /* remove if in use */
 2012                                 if (laddr->ifa == ifa) {
 2013                                         sctp_remove_laddr(laddr);
 2014                                 }
 2015                                 laddr = laddr_next;
 2016                         } /* while */
 2017                 } /* for each stcb */
 2018                 /* process through the inp bound addr list */
 2019                 laddr = LIST_FIRST(&inp->sctp_addr_list);
 2020                 while (laddr != NULL) {
 2021                         laddr_next = LIST_NEXT(laddr, sctp_nxt_addr);
 2022                         /* remove if in use */
 2023                         if (laddr->ifa == ifa) {
 2024                                 sctp_remove_laddr(laddr);
 2025                         }
 2026                         laddr = laddr_next;
 2027                 } /* while */
 2028                 SCTP_INP_RUNLOCK(inp);
 2029         } /* for each inp */
 2030         SCTP_INP_INFO_RUNLOCK();
 2031 }
 2032 
 2033 /*
 2034  * sa is the sockaddr to ask the peer to set primary to
 2035  * returns: 0 = completed, -1 = error
 2036  */
 2037 int32_t
 2038 sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
 2039 {
 2040         /* NOTE: we currently don't check the validity of the address! */
 2041 
 2042         /* queue an ASCONF:SET_PRIM_ADDR to be sent */
 2043         if (!sctp_asconf_queue_add_sa(stcb, sa, SCTP_SET_PRIM_ADDR)) {
 2044                 /* set primary queuing succeeded */
 2045                 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2046                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2047                             stcb->sctp_ep, stcb,
 2048                             stcb->asoc.primary_destination);
 2049                 }
 2050 #ifdef SCTP_DEBUG
 2051                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2052                         printf("set_primary_ip_address_sa: queued on tcb=%p, ",
 2053                             stcb);
 2054                         sctp_print_address(sa);
 2055                 }
 2056 #endif /* SCTP_DEBUG */
 2057         } else {
 2058 #ifdef SCTP_DEBUG
 2059                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2060                         printf("set_primary_ip_address_sa: failed to add to queue on tcb=%p, ",
 2061                             stcb);
 2062                         sctp_print_address(sa);
 2063                 }
 2064 #endif /* SCTP_DEBUG */
 2065                 return (-1);
 2066         }
 2067         return (0);
 2068 }
 2069 
 2070 void
 2071 sctp_set_primary_ip_address(struct ifaddr *ifa)
 2072 {
 2073         struct sctp_inpcb *inp;
 2074 
 2075         /* make sure we care about this interface... */
 2076         if (!sctp_is_desired_interface_type(ifa)) {
 2077 #ifdef SCTP_DEBUG
 2078                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2079                         printf("set_primary_ip_address: ignoring this interface\n");
 2080                 }
 2081 #endif /* SCTP_DEBUG */
 2082                 return;
 2083         }
 2084 
 2085         /* go through all our PCB's */
 2086         LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) {
 2087                 struct sctp_tcb *stcb;
 2088 
 2089                 /* process for all associations for this endpoint */
 2090                 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
 2091                         /* queue an ASCONF:SET_PRIM_ADDR to be sent */
 2092                         if (!sctp_asconf_queue_add(stcb, ifa,
 2093                             SCTP_SET_PRIM_ADDR)) {
 2094                                 /* set primary queuing succeeded */
 2095                                 if (SCTP_GET_STATE(&stcb->asoc) ==
 2096                                     SCTP_STATE_OPEN) {
 2097                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2098                                             stcb->sctp_ep, stcb,
 2099                                             stcb->asoc.primary_destination);
 2100                                 }
 2101 #ifdef SCTP_DEBUG
 2102                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2103                                         printf("set_primary_ip_address: queued on stcb=%p, ",
 2104                                             stcb);
 2105                                         sctp_print_address(ifa->ifa_addr);
 2106                                 }
 2107 #endif /* SCTP_DEBUG */
 2108                         } else {
 2109 #ifdef SCTP_DEBUG
 2110                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2111                                         printf("set_primary_ip_address: failed to add to queue, ");
 2112                                         sctp_print_address(ifa->ifa_addr);
 2113                                 }
 2114 #endif /* SCTP_DEBUG */
 2115                         }
 2116                 } /* for each stcb */
 2117         } /* for each inp */
 2118 }
 2119 
 2120 static struct sockaddr *
 2121 sctp_find_valid_localaddr(struct sctp_tcb *stcb)
 2122 {
 2123         struct ifnet *ifn;
 2124         struct ifaddr *ifa;
 2125         int s;
 2126 
 2127         s = pserialize_read_enter();
 2128         IFNET_READER_FOREACH(ifn) {
 2129                 if (stcb->asoc.loopback_scope == 0 && ifn->if_type == IFT_LOOP) {
 2130                         /* Skip if loopback_scope not set */
 2131                         continue;
 2132                 }
 2133                 IFADDR_READER_FOREACH(ifa, ifn) {
 2134                         if (ifa->ifa_addr->sa_family == AF_INET &&
 2135                             stcb->asoc.ipv4_addr_legal) {
 2136                                 struct sockaddr_in *sin;
 2137 
 2138                                 sin = (struct sockaddr_in *)ifa->ifa_addr;
 2139                                 if (sin->sin_addr.s_addr == 0) {
 2140                                         /* skip unspecifed addresses */
 2141                                         continue;
 2142                                 }
 2143                                 if (stcb->asoc.ipv4_local_scope == 0 &&
 2144                                     IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
 2145                                         continue;
 2146 
 2147                                 if (sctp_is_addr_restricted(stcb,
 2148                                     ifa->ifa_addr))
 2149                                         continue;
 2150                                 pserialize_read_exit(s);
 2151 
 2152                                 /* found a valid local v4 address to use */
 2153                                 return (ifa->ifa_addr);
 2154                         } else if (ifa->ifa_addr->sa_family == AF_INET6 &&
 2155                             stcb->asoc.ipv6_addr_legal) {
 2156                                 struct sockaddr_in6 *sin6;
 2157                                 struct in6_ifaddr *ifa6;
 2158 
 2159                                 ifa6 = (struct in6_ifaddr *)ifa;
 2160                                 if (IFA6_IS_DEPRECATED(ifa6) ||
 2161                                     (ifa6->ia6_flags & (IN6_IFF_DETACHED |
 2162                                      IN6_IFF_ANYCAST | IN6_IFF_NOTREADY)))
 2163                                         continue;
 2164 
 2165                                 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
 2166                                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 2167                                         /* we skip unspecifed addresses */
 2168                                         continue;
 2169                                 }
 2170                                 if (stcb->asoc.local_scope == 0 &&
 2171                                     IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
 2172                                         continue;
 2173                                 if (stcb->asoc.site_scope == 0 &&
 2174                                     IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
 2175                                         continue;
 2176 
 2177                                 pserialize_read_exit(s);
 2178                                 /* found a valid local v6 address to use */
 2179                                 return (ifa->ifa_addr);
 2180                         }
 2181                 }
 2182         }
 2183         pserialize_read_exit(s);
 2184 
 2185         /* no valid addresses found */
 2186         return (NULL);
 2187 }
 2188 
 2189 static struct sockaddr *
 2190 sctp_find_valid_localaddr_ep(struct sctp_tcb *stcb)
 2191 {
 2192         struct sctp_laddr *laddr;
 2193 
 2194         LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 2195                 if (laddr->ifa == NULL) {
 2196 #ifdef SCTP_DEBUG
 2197                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2198                                 printf("find_valid_localaddr_ep: laddr error\n");
 2199                         }
 2200 #endif /* SCTP_DEBUG */
 2201                         continue;
 2202                 }
 2203                 if (laddr->ifa->ifa_addr == NULL) {
 2204 #ifdef SCTP_DEBUG
 2205                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2206                                 printf("find_valid_localaddr_ep: laddr->ifa error\n");
 2207                         }
 2208 #endif /* SCTP_DEBUG */
 2209                         continue;
 2210                 }
 2211                 /* is the address restricted ? */
 2212                 if (sctp_is_addr_restricted(stcb, laddr->ifa->ifa_addr))
 2213                         continue;
 2214 
 2215                 /* found a valid local address to use */
 2216                 return (laddr->ifa->ifa_addr);
 2217         }
 2218         /* no valid addresses found */
 2219         return (NULL);
 2220 }
 2221 
 2222 /*
 2223  * builds an ASCONF chunk from queued ASCONF params
 2224  * returns NULL on error (no mbuf, no ASCONF params queued, etc)
 2225  */
 2226 struct mbuf *
 2227 sctp_compose_asconf(struct sctp_tcb *stcb)
 2228 {
 2229         struct mbuf *m_asconf, *m_asconf_chk;
 2230         struct sctp_asconf_addr *aa;
 2231         struct sctp_asconf_chunk *acp;
 2232         struct sctp_asconf_paramhdr *aph;
 2233         struct sctp_asconf_addr_param *aap;
 2234         uint32_t p_length;
 2235         uint32_t correlation_id = 1;            /* 0 is reserved... */
 2236         vaddr_t ptr, lookup_ptr;
 2237         uint8_t lookup_used = 0;
 2238 
 2239         /* are there any asconf params to send? */
 2240         if (TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
 2241                 return (NULL);
 2242         }
 2243 
 2244         /*
 2245          * get a chunk header mbuf and a cluster for the asconf params
 2246          * since it's simpler to fill in the asconf chunk header lookup
 2247          * address on the fly
 2248          */
 2249         m_asconf_chk = NULL;
 2250         MGETHDR(m_asconf_chk, M_DONTWAIT, MT_DATA);
 2251         if (m_asconf_chk == NULL) {
 2252                 /* no mbuf's */
 2253 #ifdef SCTP_DEBUG
 2254                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1)
 2255                         printf("compose_asconf: couldn't get chunk mbuf!\n");
 2256 #endif /* SCTP_DEBUG */
 2257                 return (NULL);
 2258         }
 2259         m_asconf = NULL;
 2260         MGETHDR(m_asconf, M_DONTWAIT, MT_HEADER);
 2261         if (m_asconf == NULL) {
 2262                 /* no mbuf's */
 2263 #ifdef SCTP_DEBUG
 2264                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1)
 2265                         printf("compose_asconf: couldn't get mbuf!\n");
 2266 #endif /* SCTP_DEBUG */
 2267                 sctp_m_freem(m_asconf_chk);
 2268                 return (NULL);
 2269         }
 2270         MCLGET(m_asconf, M_DONTWAIT);
 2271         if ((m_asconf->m_flags & M_EXT) != M_EXT) {
 2272                 /* failed to get cluster buffer */
 2273 #ifdef SCTP_DEBUG
 2274                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1)
 2275                         printf("compose_asconf: couldn't get cluster!\n");
 2276 #endif /* SCTP_DEBUG */
 2277                 sctp_m_freem(m_asconf_chk);
 2278                 sctp_m_freem(m_asconf);
 2279                 return (NULL);
 2280         }
 2281 
 2282         m_asconf_chk->m_len = sizeof(struct sctp_asconf_chunk);
 2283         m_asconf->m_len = 0;
 2284         acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *);
 2285         memset(acp, 0, sizeof(struct sctp_asconf_chunk));
 2286         /* save pointers to lookup address and asconf params */
 2287         lookup_ptr = (vaddr_t)(acp + 1);        /* after the header */
 2288         ptr = mtod(m_asconf, vaddr_t);          /* beginning of cluster */
 2289 
 2290         /* fill in chunk header info */
 2291         acp->ch.chunk_type = SCTP_ASCONF;
 2292         acp->ch.chunk_flags = 0;
 2293         acp->serial_number = htonl(stcb->asoc.asconf_seq_out);
 2294 
 2295         /* add parameters... up to smallest MTU allowed */
 2296         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 2297                 /* get the parameter length */
 2298                 p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
 2299                 /* will it fit in current chunk? */
 2300                 if (m_asconf->m_len + p_length > stcb->asoc.smallest_mtu) {
 2301                         /* won't fit, so we're done with this chunk */
 2302                         break;
 2303                 }
 2304                 /* assign (and store) a correlation id */
 2305                 aa->ap.aph.correlation_id = correlation_id++;
 2306 
 2307                 /*
 2308                  * fill in address if we're doing a delete
 2309                  * this is a simple way for us to fill in the correlation
 2310                  * address, which should only be used by the peer if we're
 2311                  * deleting our source address and adding a new address
 2312                  * (e.g. renumbering case)
 2313                  */
 2314                 if (lookup_used == 0 &&
 2315                     aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
 2316                         struct sctp_ipv6addr_param *lookup;
 2317                         uint16_t p_size, addr_size;
 2318 
 2319                         lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
 2320                         lookup->ph.param_type =
 2321                             htons(aa->ap.addrp.ph.param_type);
 2322                         if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) {
 2323                                 /* copy IPv6 address */
 2324                                 p_size = sizeof(struct sctp_ipv6addr_param);
 2325                                 addr_size = sizeof(struct in6_addr);
 2326                         } else {
 2327                                 /* copy IPv4 address */
 2328                                 p_size = sizeof(struct sctp_ipv4addr_param);
 2329                                 addr_size = sizeof(struct in_addr);
 2330                         }
 2331                         lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
 2332                         memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size);
 2333                         m_asconf_chk->m_len += SCTP_SIZE32(p_size);
 2334                         lookup_used = 1;
 2335                 }
 2336 
 2337                 /* copy into current space */
 2338                 memcpy((void *)ptr, &aa->ap, p_length);
 2339 
 2340                 /* network elements and update lengths */
 2341                 aph = (struct sctp_asconf_paramhdr *) ptr;
 2342                 aap = (struct sctp_asconf_addr_param *) ptr;
 2343                 /* correlation_id is transparent to peer, no htonl needed */
 2344                 aph->ph.param_type = htons(aph->ph.param_type);
 2345                 aph->ph.param_length = htons(aph->ph.param_length);
 2346                 aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type);
 2347                 aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length);
 2348 
 2349                 m_asconf->m_len += SCTP_SIZE32(p_length);
 2350                 ptr += SCTP_SIZE32(p_length);
 2351 
 2352                 /*
 2353                  * these params are removed off the pending list upon
 2354                  * getting an ASCONF-ACK back from the peer, just set flag
 2355                  */
 2356                 aa->sent = 1;
 2357         }
 2358         /* check to see if the lookup addr has been populated yet */
 2359         if (lookup_used == 0) {
 2360                 /* NOTE: if the address param is optional, can skip this... */
 2361                 /* add any valid (existing) address... */
 2362                 struct sctp_ipv6addr_param *lookup;
 2363                 uint16_t p_size, addr_size;
 2364                 struct sockaddr *found_addr;
 2365                 vaddr_t addr_ptr;
 2366 
 2367                 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)
 2368                         found_addr = sctp_find_valid_localaddr(stcb);
 2369                 else
 2370                         found_addr = sctp_find_valid_localaddr_ep(stcb);
 2371 
 2372                 lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
 2373                 if (found_addr != NULL) {
 2374                         if (found_addr->sa_family == AF_INET6) {
 2375                                 /* copy IPv6 address */
 2376                                 lookup->ph.param_type =
 2377                                     htons(SCTP_IPV6_ADDRESS);
 2378                                 p_size = sizeof(struct sctp_ipv6addr_param);
 2379                                 addr_size = sizeof(struct in6_addr);
 2380                                 addr_ptr = (vaddr_t)&((struct sockaddr_in6 *)
 2381                                     found_addr)->sin6_addr;
 2382                         } else {
 2383                                 /* copy IPv4 address */
 2384                                 lookup->ph.param_type =
 2385                                     htons(SCTP_IPV4_ADDRESS);
 2386                                 p_size = sizeof(struct sctp_ipv4addr_param);
 2387                                 addr_size = sizeof(struct in_addr);
 2388                                 addr_ptr = (vaddr_t)&((struct sockaddr_in *)
 2389                                     found_addr)->sin_addr;
 2390                         }
 2391                         lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
 2392                         memcpy(lookup->addr, (void *)addr_ptr, addr_size);
 2393                         m_asconf_chk->m_len += SCTP_SIZE32(p_size);
 2394                         lookup_used = 1;
 2395                 } else {
 2396                         /* uh oh... don't have any address?? */
 2397 #ifdef SCTP_DEBUG
 2398                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1)
 2399                                 printf("compose_asconf: no lookup addr!\n");
 2400 #endif /* SCTP_DEBUG */
 2401                         /* for now, we send a IPv4 address of 0.0.0.0 */
 2402                         lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
 2403                         lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
 2404                         memset(lookup->addr, 0, sizeof(struct in_addr));
 2405                         m_asconf_chk->m_len += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
 2406                         lookup_used = 1;
 2407                 }
 2408         }
 2409 
 2410         /* chain it all together */
 2411         m_asconf_chk->m_next = m_asconf;
 2412         m_asconf_chk->m_pkthdr.len = m_asconf_chk->m_len + m_asconf->m_len;
 2413         acp->ch.chunk_length = ntohs(m_asconf_chk->m_pkthdr.len);
 2414 
 2415         /* update "sent" flag */
 2416         stcb->asoc.asconf_sent++;
 2417 
 2418         return (m_asconf_chk);
 2419 }
 2420 
 2421 /*
 2422  * section to handle address changes before an association is up
 2423  * eg. changes during INIT/INIT-ACK/COOKIE-ECHO handshake
 2424  */
 2425 
 2426 /*
 2427  * processes the (local) addresses in the INIT-ACK chunk
 2428  */
 2429 static void
 2430 sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
 2431     unsigned int offset, unsigned int length)
 2432 {
 2433         struct sctp_paramhdr tmp_param, *ph;
 2434         uint16_t plen, ptype;
 2435         struct sctp_ipv6addr_param addr_store;
 2436         struct sockaddr_in6 sin6;
 2437         struct sockaddr_in sin;
 2438         struct sockaddr *sa;
 2439         struct ifaddr *ifa;
 2440 
 2441 #ifdef SCTP_DEBUG
 2442         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2443                 printf("processing init-ack addresses\n");
 2444         }
 2445 #endif /* SCTP_DEBUG */
 2446 
 2447         /* convert to upper bound */
 2448         length += offset;
 2449 
 2450         if ((offset + sizeof(struct sctp_paramhdr)) > length) {
 2451 #ifdef SCTP_DEBUG
 2452                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2453                         printf("process_initack_addrs: invalid offset?\n");
 2454                 }
 2455 #endif /* SCTP_DEBUG */
 2456                 return;
 2457         }
 2458 
 2459         /* init the addresses */
 2460         memset(&sin6, 0, sizeof(sin6));
 2461         sin6.sin6_family = AF_INET6;
 2462         sin6.sin6_len = sizeof(sin6);
 2463         sin6.sin6_port = stcb->rport;
 2464 
 2465         memset(&sin, 0, sizeof(sin));
 2466         sin.sin_len = sizeof(sin);
 2467         sin.sin_family = AF_INET;
 2468         sin.sin_port = stcb->rport;
 2469 
 2470         /* go through the addresses in the init-ack */
 2471         ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
 2472             sizeof(struct sctp_paramhdr), (uint8_t *)&tmp_param);
 2473         while (ph != NULL) {
 2474                 ptype = ntohs(ph->param_type);
 2475                 plen = ntohs(ph->param_length);
 2476                 if (ptype == SCTP_IPV6_ADDRESS) {
 2477                         struct sctp_ipv6addr_param *a6p;
 2478                         /* get the entire IPv6 address param */
 2479 #ifdef SCTP_DEBUG
 2480                         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2481                                 printf("process_initack_addrs: checking IPv6 param\n");
 2482                         }
 2483 #endif /* SCTP_DEBUG */
 2484                         a6p = (struct sctp_ipv6addr_param *)
 2485                                 sctp_m_getptr(m, offset,
 2486                                     sizeof(struct sctp_ipv6addr_param),
 2487                                     (uint8_t *)&addr_store);
 2488                         if (plen != sizeof(struct sctp_ipv6addr_param) ||
 2489                             a6p == NULL) {
 2490 #ifdef SCTP_DEBUG
 2491                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2492                                         printf("process_initack_addrs: invalid IPv6 param length\n");
 2493                                 }
 2494 #endif /* SCTP_DEBUG */
 2495                                 return;
 2496                         }
 2497                         memcpy(&sin6.sin6_addr, a6p->addr,
 2498                             sizeof(struct in6_addr));
 2499                         sa = (struct sockaddr *)&sin6;
 2500                 } else if (ptype == SCTP_IPV4_ADDRESS) {
 2501                         struct sctp_ipv4addr_param *a4p;
 2502                         /* get the entire IPv4 address param */
 2503 #ifdef SCTP_DEBUG
 2504                         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2505                                 printf("process_initack_addrs: checking IPv4 param\n");
 2506                         }
 2507 #endif /* SCTP_DEBUG */
 2508                         a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_ipv4addr_param), (uint8_t *)&addr_store);
 2509                         if (plen != sizeof(struct sctp_ipv4addr_param) ||
 2510                             a4p == NULL) {
 2511 #ifdef SCTP_DEBUG
 2512                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2513                                         printf("process_initack_addrs: invalid IPv4 param length\n");
 2514                                 }
 2515 #endif /* SCTP_DEBUG */
 2516                                 return;
 2517                         }
 2518                         sin.sin_addr.s_addr = a4p->addr;
 2519                         sa = (struct sockaddr *)&sin;
 2520                 } else {
 2521 #ifdef SCTP_DEBUG
 2522                         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2523                                 printf("process_initack_addrs: skipping param type=%xh\n", ptype);
 2524                         }
 2525 #endif /* SCTP_DEBUG */
 2526                         goto next_addr;
 2527                 }
 2528 
 2529                 /* see if this address really (still) exists */
 2530                 ifa = sctp_find_ifa_by_addr(sa);
 2531                 if (ifa == NULL) {
 2532                         /* address doesn't exist anymore */
 2533                         int status;
 2534                         /* are ASCONFs allowed ? */
 2535                         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DO_ASCONF) &&
 2536                             stcb->asoc.peer_supports_asconf) {
 2537                                 /* queue an ASCONF DEL_IP_ADDRESS */
 2538                                 status = sctp_asconf_queue_add_sa(stcb, sa,
 2539                                     SCTP_DEL_IP_ADDRESS);
 2540                                 /*
 2541                                  * if queued ok, and in correct state,
 2542                                  * set the ASCONF timer
 2543                                  */
 2544                                 if (status == 0 &&
 2545                                     SCTP_GET_STATE(&stcb->asoc) ==
 2546                                     SCTP_STATE_OPEN) {
 2547                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2548                                             stcb->sctp_ep, stcb,
 2549                                             stcb->asoc.primary_destination);
 2550                                 }
 2551                         }
 2552                 } else {
 2553                         /* address still exists */
 2554                         /*
 2555                          * if subset bound, ep addr's managed by default
 2556                          * if not doing ASCONF, add the address to the assoc
 2557                          */
 2558                         if ((stcb->sctp_ep->sctp_flags &
 2559                              SCTP_PCB_FLAGS_BOUNDALL) == 0 &&
 2560                             (stcb->sctp_ep->sctp_flags &
 2561                              SCTP_PCB_FLAGS_DO_ASCONF) == 0) {
 2562 #ifdef SCTP_DEBUG
 2563                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2564                                         printf("process_initack_addrs: adding local addr to asoc\n");
 2565                                 }
 2566 #endif /* SCTP_DEBUG */
 2567                                 sctp_add_local_addr_assoc(stcb, ifa);
 2568                         }
 2569                 }
 2570 
 2571         next_addr:
 2572                 /* get next parameter */
 2573                 offset += SCTP_SIZE32(plen);
 2574                 if ((offset + sizeof(struct sctp_paramhdr)) > length)
 2575                         return;
 2576                 ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
 2577                     sizeof(struct sctp_paramhdr), (uint8_t *)&tmp_param);
 2578         } /* while */
 2579 }
 2580 
 2581 /* FIX ME: need to verify return result for v6 address type if v6 disabled */
 2582 /*
 2583  * checks to see if a specific address is in the initack address list
 2584  * returns 1 if found, 0 if not
 2585  */
 2586 static uint32_t
 2587 sctp_addr_in_initack(struct sctp_tcb *stcb, struct mbuf *m, unsigned int offset,
 2588     unsigned int length, struct sockaddr *sa)
 2589 {
 2590         struct sctp_paramhdr tmp_param, *ph;
 2591         uint16_t plen, ptype;
 2592         struct sctp_ipv6addr_param addr_store;
 2593         struct sockaddr_in *sin;
 2594         struct sctp_ipv4addr_param *a4p;
 2595 #ifdef INET6
 2596         struct sockaddr_in6 *sin6, sin6_tmp;
 2597         struct sctp_ipv6addr_param *a6p;
 2598 #endif /* INET6 */
 2599 
 2600         if (
 2601 #ifdef INET6
 2602                 (sa->sa_family != AF_INET6) &&
 2603 #endif /* INET6 */
 2604                 (sa->sa_family != AF_INET))
 2605                 return (0);
 2606 
 2607 #ifdef SCTP_DEBUG
 2608         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2609                 printf("find_initack_addr: starting search for ");
 2610                 sctp_print_address(sa);
 2611         }
 2612 #endif /* SCTP_DEBUG */
 2613         /* convert to upper bound */
 2614         length += offset;
 2615 
 2616         if ((offset + sizeof(struct sctp_paramhdr)) > length) {
 2617 #ifdef SCTP_DEBUG
 2618                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2619                         printf("find_initack_addr: invalid offset?\n");
 2620                 }
 2621 #endif /* SCTP_DEBUG */
 2622                 return (0);
 2623         }
 2624 
 2625         /* go through the addresses in the init-ack */
 2626         ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
 2627             sizeof(struct sctp_paramhdr), (uint8_t *)&tmp_param);
 2628         while (ph != NULL) {
 2629                 ptype = ntohs(ph->param_type);
 2630                 plen = ntohs(ph->param_length);
 2631 #ifdef INET6
 2632                 if (ptype == SCTP_IPV6_ADDRESS && sa->sa_family == AF_INET6) {
 2633                         /* get the entire IPv6 address param */
 2634 #ifdef SCTP_DEBUG
 2635                         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2636                                 printf("addr_in_initack: checking IPv6 param\n");
 2637                         }
 2638 #endif /* SCTP_DEBUG */
 2639                         a6p = (struct sctp_ipv6addr_param *)
 2640                                 sctp_m_getptr(m, offset,
 2641                                     sizeof(struct sctp_ipv6addr_param),
 2642                                     (uint8_t *)&addr_store);
 2643                         if (plen != sizeof(struct sctp_ipv6addr_param) ||
 2644                             ph == NULL) {
 2645 #ifdef SCTP_DEBUG
 2646                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2647                                         printf("addr_in_initack: invalid IPv6 param length\n");
 2648                                 }
 2649 #endif /* SCTP_DEBUG */
 2650                                 return (0);
 2651                         }
 2652                         sin6 = (struct sockaddr_in6 *)sa;
 2653                         if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
 2654                                 /* create a copy and clear scope */
 2655                                 memcpy(&sin6_tmp, sin6,
 2656                                     sizeof(struct sockaddr_in6));
 2657                                 sin6 = &sin6_tmp;
 2658                                 in6_clearscope(&sin6->sin6_addr);
 2659                         }
 2660                         if (memcmp(&sin6->sin6_addr, a6p->addr,
 2661                             sizeof(struct in6_addr)) == 0) {
 2662                                 /* found it */
 2663 #ifdef SCTP_DEBUG
 2664                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2665                                         printf("addr_in_initack: found IPv6 addr\n");
 2666                                 }
 2667 #endif /* SCTP_DEBUG */
 2668                                 return (1);
 2669                         }
 2670                 } else
 2671 #endif /* INET6 */
 2672 
 2673                 if (ptype == SCTP_IPV4_ADDRESS &&
 2674                     sa->sa_family == AF_INET) {
 2675                         /* get the entire IPv4 address param */
 2676 #ifdef SCTP_DEBUG
 2677                         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2678                                 printf("addr_in_initack: checking IPv4 param\n");
 2679                         }
 2680 #endif /* SCTP_DEBUG */
 2681                         a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m,
 2682                             offset, sizeof(struct sctp_ipv4addr_param),
 2683                             (uint8_t *)&addr_store);
 2684                         if (plen != sizeof(struct sctp_ipv4addr_param) ||
 2685                             ph == NULL) {
 2686 #ifdef SCTP_DEBUG
 2687                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2688                                         printf("addr_in_initack: invalid IPv4 param length\n");
 2689                                 }
 2690 #endif /* SCTP_DEBUG */
 2691                                 return (0);
 2692                         }
 2693                         sin = (struct sockaddr_in *)sa;
 2694                         if (sin->sin_addr.s_addr == a4p->addr) {
 2695                                 /* found it */
 2696 #ifdef SCTP_DEBUG
 2697                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2698                                         printf("addr_in_initack: found IPv4 addr\n");
 2699                                 }
 2700 #endif /* SCTP_DEBUG */
 2701                                 return (1);
 2702                         }
 2703                 } else {
 2704 #ifdef SCTP_DEBUG
 2705                         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2706                                 printf("addr_in_initack: skipping param type=%xh\n", ptype);
 2707                         }
 2708 #endif /* SCTP_DEBUG */
 2709                 }
 2710                 /* get next parameter */
 2711                 offset += SCTP_SIZE32(plen);
 2712                 if (offset + sizeof(struct sctp_paramhdr) > length)
 2713                         return (0);
 2714                 ph = (struct sctp_paramhdr *)
 2715                         sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
 2716                             (uint8_t *)&tmp_param);
 2717         } /* while */
 2718         /* not found! */
 2719 #ifdef SCTP_DEBUG
 2720         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2721                 printf("addr_in_initack: not found!\n");
 2722         }
 2723 #endif /* SCTP_DEBUG */
 2724         return (0);
 2725 }
 2726 
 2727 /*
 2728  * makes sure that the current endpoint local addr list is consistent
 2729  * with the new association (eg. subset bound, asconf allowed)
 2730  * adds addresses as necessary
 2731  */
 2732 static void
 2733 sctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 2734     int length, struct sockaddr *init_addr)
 2735 {
 2736         struct sctp_laddr *laddr;
 2737 
 2738         /* go through the endpoint list */
 2739         LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 2740                 /* be paranoid and validate the laddr */
 2741                 if (laddr->ifa == NULL) {
 2742 #ifdef SCTP_DEBUG
 2743                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2744                                 printf("check_addr_list_ep: laddr->ifa is NULL");
 2745                         }
 2746 #endif
 2747                         continue;
 2748                 }
 2749                 if (laddr->ifa->ifa_addr == NULL) {
 2750 #ifdef SCTP_DEBUG
 2751                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2752                                 printf("check_addr_list_ep: laddr->ifa->ifa_addr is NULL");
 2753                         }
 2754 #endif
 2755                         continue;
 2756                 }
 2757                 /* do i have it implicitly? */
 2758                 if (sctp_cmpaddr(laddr->ifa->ifa_addr, init_addr)) {
 2759 #ifdef SCTP_DEBUG
 2760                         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2761                                 printf("check_address_list_all: skipping ");
 2762                                 sctp_print_address(laddr->ifa->ifa_addr);
 2763                         }
 2764 #endif /* SCTP_DEBUG */
 2765                         continue;
 2766                 }
 2767                 /* check to see if in the init-ack */
 2768                 if (!sctp_addr_in_initack(stcb, m, offset, length,
 2769                                           laddr->ifa->ifa_addr)) {
 2770                         /* try to add it */
 2771                         sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa,
 2772                             SCTP_ADD_IP_ADDRESS);
 2773                 }
 2774         }
 2775 }
 2776 
 2777 /*
 2778  * makes sure that the current kernel address list is consistent
 2779  * with the new association (with all addrs bound)
 2780  * adds addresses as necessary
 2781  */
 2782 static void
 2783 sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 2784     int length, struct sockaddr *init_addr, uint16_t local_scope,
 2785     uint16_t site_scope, uint16_t ipv4_scope, uint16_t loopback_scope)
 2786 {
 2787         struct ifnet *ifn;
 2788         struct ifaddr *ifa;
 2789         int s;
 2790 
 2791         /* go through all our known interfaces */
 2792         s = pserialize_read_enter();
 2793         IFNET_READER_FOREACH(ifn) {
 2794                 if (loopback_scope == 0 && ifn->if_type == IFT_LOOP) {
 2795                         /* skip loopback interface */
 2796                         continue;
 2797                 }
 2798 
 2799                 /* go through each interface address */
 2800                 IFADDR_READER_FOREACH(ifa, ifn) {
 2801                         /* do i have it implicitly? */
 2802                         if (sctp_cmpaddr(ifa->ifa_addr, init_addr)) {
 2803 #ifdef SCTP_DEBUG
 2804                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
 2805                                         printf("check_address_list_all: skipping ");
 2806                                         sctp_print_address(ifa->ifa_addr);
 2807                                 }
 2808 #endif /* SCTP_DEBUG */
 2809                                 continue;
 2810                         }
 2811                         /* check to see if in the init-ack */
 2812                         if (!sctp_addr_in_initack(stcb, m, offset, length,
 2813                             ifa->ifa_addr)) {
 2814                                 /* try to add it */
 2815                                 sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
 2816                                     ifa, SCTP_ADD_IP_ADDRESS);
 2817                         }
 2818                 } /* end foreach ifa */
 2819         } /* end foreach ifn */
 2820         pserialize_read_exit(s);
 2821 }
 2822 
 2823 /*
 2824  * validates an init-ack chunk (from a cookie-echo) with current addresses
 2825  * adds addresses from the init-ack into our local address list, if needed
 2826  * queues asconf adds/deletes addresses as needed and makes appropriate
 2827  * list changes for source address selection
 2828  * m, offset: points to the start of the address list in an init-ack chunk
 2829  * length: total length of the address params only
 2830  * init_addr: address where my INIT-ACK was sent from
 2831  */
 2832 void
 2833 sctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 2834     int length, struct sockaddr *init_addr, uint16_t local_scope,
 2835     uint16_t site_scope, uint16_t ipv4_scope, uint16_t loopback_scope)
 2836 {
 2837 
 2838         /* process the local addresses in the initack */
 2839         sctp_process_initack_addresses(stcb, m, offset, length);
 2840 
 2841         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
 2842                 /* bound all case */
 2843                 sctp_check_address_list_all(stcb, m, offset, length, init_addr,
 2844                     local_scope, site_scope, ipv4_scope, loopback_scope);
 2845         } else {
 2846                 /* subset bound case */
 2847                 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DO_ASCONF) {
 2848                         /* asconf's allowed */
 2849                         sctp_check_address_list_ep(stcb, m, offset, length,
 2850                             init_addr);
 2851                 }
 2852                 /* else, no asconfs allowed, so what we sent is what we get */
 2853         }
 2854 }
 2855 
 2856 /*
 2857  * sctp_bindx() support
 2858  */
 2859 uint32_t
 2860 sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, uint16_t type)
 2861 {
 2862         struct ifaddr *ifa;
 2863 
 2864         if (sa->sa_len == 0)
 2865                 return (EINVAL);
 2866 
 2867         ifa = sctp_find_ifa_by_addr(sa);
 2868         if (ifa != NULL) {
 2869 #ifdef INET6
 2870                 if (ifa->ifa_addr->sa_family == AF_INET6) {
 2871                         struct in6_ifaddr *ifa6;
 2872                         ifa6 = (struct in6_ifaddr *)ifa;
 2873                         if (IFA6_IS_DEPRECATED(ifa6) ||
 2874                             (ifa6->ia6_flags & (IN6_IFF_DETACHED |
 2875                              IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) {
 2876                                 /* Can't bind a non-existent addr. */
 2877                                 return (EINVAL);
 2878                         }
 2879                 }
 2880 #endif /* INET6 */
 2881                 /* add this address */
 2882                 sctp_addr_mgmt_ep(inp, ifa, type);
 2883         } else {
 2884                 /* invalid address! */
 2885 #ifdef SCTP_DEBUG
 2886                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
 2887                         printf("addr_mgmt_ep_sa: got invalid address!\n");
 2888                 }
 2889 #endif /* SCTP_DEBUG */
 2890                 return (EADDRNOTAVAIL);
 2891         }
 2892         return (0);
 2893 }

Cache object: e4bcbe220722c7fc12e729fe84ed6f67


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.