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 /*-
    2  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
    3  * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved.
    4  * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions are met:
    8  *
    9  * a) Redistributions of source code must retain the above copyright notice,
   10  *   this list of conditions and the following disclaimer.
   11  *
   12  * b) Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in
   14  *   the documentation and/or other materials provided with the distribution.
   15  *
   16  * c) Neither the name of Cisco Systems, Inc. nor the names of its
   17  *    contributors may be used to endorse or promote products derived
   18  *    from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
   22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   30  * THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 /* $KAME: sctp_asconf.c,v 1.24 2005/03/06 16:04:16 itojun Exp $  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/9.0/sys/netinet/sctp_asconf.c 225584 2011-09-15 12:20:52Z tuexen $");
   37 #include <netinet/sctp_os.h>
   38 #include <netinet/sctp_var.h>
   39 #include <netinet/sctp_sysctl.h>
   40 #include <netinet/sctp_pcb.h>
   41 #include <netinet/sctp_header.h>
   42 #include <netinet/sctputil.h>
   43 #include <netinet/sctp_output.h>
   44 #include <netinet/sctp_asconf.h>
   45 #include <netinet/sctp_timer.h>
   46 
   47 /*
   48  * debug flags:
   49  * SCTP_DEBUG_ASCONF1: protocol info, general info and errors
   50  * SCTP_DEBUG_ASCONF2: detailed info
   51  */
   52 #ifdef SCTP_DEBUG
   53 #endif                          /* SCTP_DEBUG */
   54 
   55 
   56 static void
   57 sctp_asconf_get_source_ip(struct mbuf *m, struct sockaddr *sa)
   58 {
   59         struct ip *iph;
   60 
   61 #ifdef INET
   62         struct sockaddr_in *sin;
   63 
   64 #endif
   65 #ifdef INET6
   66         struct sockaddr_in6 *sin6;
   67 
   68 #endif
   69 
   70         iph = mtod(m, struct ip *);
   71         switch (iph->ip_v) {
   72 #ifdef INET
   73         case IPVERSION:
   74                 {
   75                         /* IPv4 source */
   76                         sin = (struct sockaddr_in *)sa;
   77                         bzero(sin, sizeof(*sin));
   78                         sin->sin_family = AF_INET;
   79                         sin->sin_len = sizeof(struct sockaddr_in);
   80                         sin->sin_port = 0;
   81                         sin->sin_addr.s_addr = iph->ip_src.s_addr;
   82                         break;
   83                 }
   84 #endif
   85 #ifdef INET6
   86         case (IPV6_VERSION >> 4):
   87                 {
   88                         /* IPv6 source */
   89                         struct ip6_hdr *ip6;
   90 
   91                         sin6 = (struct sockaddr_in6 *)sa;
   92                         bzero(sin6, sizeof(*sin6));
   93                         sin6->sin6_family = AF_INET6;
   94                         sin6->sin6_len = sizeof(struct sockaddr_in6);
   95                         sin6->sin6_port = 0;
   96                         ip6 = mtod(m, struct ip6_hdr *);
   97                         sin6->sin6_addr = ip6->ip6_src;
   98                         break;
   99                 }
  100 #endif                          /* INET6 */
  101         default:
  102                 break;
  103         }
  104         return;
  105 }
  106 
  107 /*
  108  * draft-ietf-tsvwg-addip-sctp
  109  *
  110  * An ASCONF parameter queue exists per asoc which holds the pending address
  111  * operations.  Lists are updated upon receipt of ASCONF-ACK.
  112  *
  113  * A restricted_addrs list exists per assoc to hold local addresses that are
  114  * not (yet) usable by the assoc as a source address.  These addresses are
  115  * either pending an ASCONF operation (and exist on the ASCONF parameter
  116  * queue), or they are permanently restricted (the peer has returned an
  117  * ERROR indication to an ASCONF(ADD), or the peer does not support ASCONF).
  118  *
  119  * Deleted addresses are always immediately removed from the lists as they will
  120  * (shortly) no longer exist in the kernel.  We send ASCONFs as a courtesy,
  121  * only if allowed.
  122  */
  123 
  124 /*
  125  * ASCONF parameter processing.
  126  * response_required: set if a reply is required (eg. SUCCESS_REPORT).
  127  * returns a mbuf to an "error" response parameter or NULL/"success" if ok.
  128  * FIX: allocating this many mbufs on the fly is pretty inefficient...
  129  */
  130 static struct mbuf *
  131 sctp_asconf_success_response(uint32_t id)
  132 {
  133         struct mbuf *m_reply = NULL;
  134         struct sctp_asconf_paramhdr *aph;
  135 
  136         m_reply = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_paramhdr),
  137             0, M_DONTWAIT, 1, MT_DATA);
  138         if (m_reply == NULL) {
  139                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  140                     "asconf_success_response: couldn't get mbuf!\n");
  141                 return NULL;
  142         }
  143         aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
  144         aph->correlation_id = id;
  145         aph->ph.param_type = htons(SCTP_SUCCESS_REPORT);
  146         aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr);
  147         SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
  148         aph->ph.param_length = htons(aph->ph.param_length);
  149 
  150         return m_reply;
  151 }
  152 
  153 static struct mbuf *
  154 sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv,
  155     uint16_t tlv_length)
  156 {
  157         struct mbuf *m_reply = NULL;
  158         struct sctp_asconf_paramhdr *aph;
  159         struct sctp_error_cause *error;
  160         uint8_t *tlv;
  161 
  162         m_reply = sctp_get_mbuf_for_msg((sizeof(struct sctp_asconf_paramhdr) +
  163             tlv_length +
  164             sizeof(struct sctp_error_cause)),
  165             0, M_DONTWAIT, 1, MT_DATA);
  166         if (m_reply == NULL) {
  167                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  168                     "asconf_error_response: couldn't get mbuf!\n");
  169                 return NULL;
  170         }
  171         aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
  172         error = (struct sctp_error_cause *)(aph + 1);
  173 
  174         aph->correlation_id = id;
  175         aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND);
  176         error->code = htons(cause);
  177         error->length = tlv_length + sizeof(struct sctp_error_cause);
  178         aph->ph.param_length = error->length +
  179             sizeof(struct sctp_asconf_paramhdr);
  180 
  181         if (aph->ph.param_length > MLEN) {
  182                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  183                     "asconf_error_response: tlv_length (%xh) too big\n",
  184                     tlv_length);
  185                 sctp_m_freem(m_reply);  /* discard */
  186                 return NULL;
  187         }
  188         if (error_tlv != NULL) {
  189                 tlv = (uint8_t *) (error + 1);
  190                 memcpy(tlv, error_tlv, tlv_length);
  191         }
  192         SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
  193         error->length = htons(error->length);
  194         aph->ph.param_length = htons(aph->ph.param_length);
  195 
  196         return m_reply;
  197 }
  198 
  199 static struct mbuf *
  200 sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
  201     struct sctp_tcb *stcb, int send_hb, int response_required)
  202 {
  203         struct sctp_nets *net;
  204         struct mbuf *m_reply = NULL;
  205         struct sockaddr_storage sa_source, sa_store;
  206         struct sctp_paramhdr *ph;
  207         uint16_t param_type, param_length, aparam_length;
  208         struct sockaddr *sa;
  209         int zero_address = 0;
  210         int bad_address = 0;
  211 
  212 #ifdef INET
  213         struct sockaddr_in *sin;
  214         struct sctp_ipv4addr_param *v4addr;
  215 
  216 #endif
  217 #ifdef INET6
  218         struct sockaddr_in6 *sin6;
  219         struct sctp_ipv6addr_param *v6addr;
  220 
  221 #endif
  222 
  223         aparam_length = ntohs(aph->ph.param_length);
  224         ph = (struct sctp_paramhdr *)(aph + 1);
  225         param_type = ntohs(ph->param_type);
  226         param_length = ntohs(ph->param_length);
  227 
  228         sa = (struct sockaddr *)&sa_store;
  229         switch (param_type) {
  230 #ifdef INET
  231         case SCTP_IPV4_ADDRESS:
  232                 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
  233                         /* invalid param size */
  234                         return NULL;
  235                 }
  236                 v4addr = (struct sctp_ipv4addr_param *)ph;
  237                 sin = (struct sockaddr_in *)&sa_store;
  238                 bzero(sin, sizeof(*sin));
  239                 sin->sin_family = AF_INET;
  240                 sin->sin_len = sizeof(struct sockaddr_in);
  241                 sin->sin_port = stcb->rport;
  242                 sin->sin_addr.s_addr = v4addr->addr;
  243                 if ((sin->sin_addr.s_addr == INADDR_BROADCAST) ||
  244                     IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
  245                         bad_address = 1;
  246                 }
  247                 if (sin->sin_addr.s_addr == INADDR_ANY)
  248                         zero_address = 1;
  249                 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
  250                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
  251                 break;
  252 #endif
  253 #ifdef INET6
  254         case SCTP_IPV6_ADDRESS:
  255                 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
  256                         /* invalid param size */
  257                         return NULL;
  258                 }
  259                 v6addr = (struct sctp_ipv6addr_param *)ph;
  260                 sin6 = (struct sockaddr_in6 *)&sa_store;
  261                 bzero(sin6, sizeof(*sin6));
  262                 sin6->sin6_family = AF_INET6;
  263                 sin6->sin6_len = sizeof(struct sockaddr_in6);
  264                 sin6->sin6_port = stcb->rport;
  265                 memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
  266                     sizeof(struct in6_addr));
  267                 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
  268                         bad_address = 1;
  269                 }
  270                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
  271                         zero_address = 1;
  272                 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
  273                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
  274                 break;
  275 #endif
  276         default:
  277                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  278                     SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
  279                     aparam_length);
  280                 return m_reply;
  281         }                       /* end switch */
  282 
  283         /* if 0.0.0.0/::0, add the source address instead */
  284         if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
  285                 sa = (struct sockaddr *)&sa_source;
  286                 sctp_asconf_get_source_ip(m, sa);
  287                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  288                     "process_asconf_add_ip: using source addr ");
  289                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
  290         }
  291         /* add the address */
  292         if (bad_address) {
  293                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  294                     SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
  295                     aparam_length);
  296         } else if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE,
  297             SCTP_ADDR_DYNAMIC_ADDED) != 0) {
  298                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  299                     "process_asconf_add_ip: error adding address\n");
  300                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  301                     SCTP_CAUSE_RESOURCE_SHORTAGE, (uint8_t *) aph,
  302                     aparam_length);
  303         } else {
  304                 /* notify upper layer */
  305                 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
  306                 if (response_required) {
  307                         m_reply =
  308                             sctp_asconf_success_response(aph->correlation_id);
  309                 }
  310                 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net);
  311                 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
  312                     stcb, net);
  313                 if (send_hb) {
  314                         sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
  315                 }
  316         }
  317         return m_reply;
  318 }
  319 
  320 static int
  321 sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src)
  322 {
  323         struct sctp_nets *src_net, *net;
  324 
  325         /* make sure the source address exists as a destination net */
  326         src_net = sctp_findnet(stcb, src);
  327         if (src_net == NULL) {
  328                 /* not found */
  329                 return -1;
  330         }
  331         /* delete all destination addresses except the source */
  332         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
  333                 if (net != src_net) {
  334                         /* delete this address */
  335                         sctp_remove_net(stcb, net);
  336                         SCTPDBG(SCTP_DEBUG_ASCONF1,
  337                             "asconf_del_remote_addrs_except: deleting ");
  338                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1,
  339                             (struct sockaddr *)&net->ro._l_addr);
  340                         /* notify upper layer */
  341                         sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0,
  342                             (struct sockaddr *)&net->ro._l_addr, SCTP_SO_NOT_LOCKED);
  343                 }
  344         }
  345         return 0;
  346 }
  347 
  348 static struct mbuf *
  349 sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
  350     struct sctp_tcb *stcb, int response_required)
  351 {
  352         struct mbuf *m_reply = NULL;
  353         struct sockaddr_storage sa_source, sa_store;
  354         struct sctp_paramhdr *ph;
  355         uint16_t param_type, param_length, aparam_length;
  356         struct sockaddr *sa;
  357         int zero_address = 0;
  358         int result;
  359 
  360 #ifdef INET
  361         struct sockaddr_in *sin;
  362         struct sctp_ipv4addr_param *v4addr;
  363 
  364 #endif
  365 #ifdef INET6
  366         struct sockaddr_in6 *sin6;
  367         struct sctp_ipv6addr_param *v6addr;
  368 
  369 #endif
  370 
  371         /* get the source IP address for src and 0.0.0.0/::0 delete checks */
  372         sctp_asconf_get_source_ip(m, (struct sockaddr *)&sa_source);
  373 
  374         aparam_length = ntohs(aph->ph.param_length);
  375         ph = (struct sctp_paramhdr *)(aph + 1);
  376         param_type = ntohs(ph->param_type);
  377         param_length = ntohs(ph->param_length);
  378 
  379         sa = (struct sockaddr *)&sa_store;
  380         switch (param_type) {
  381 #ifdef INET
  382         case SCTP_IPV4_ADDRESS:
  383                 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
  384                         /* invalid param size */
  385                         return NULL;
  386                 }
  387                 v4addr = (struct sctp_ipv4addr_param *)ph;
  388                 sin = (struct sockaddr_in *)&sa_store;
  389                 bzero(sin, sizeof(*sin));
  390                 sin->sin_family = AF_INET;
  391                 sin->sin_len = sizeof(struct sockaddr_in);
  392                 sin->sin_port = stcb->rport;
  393                 sin->sin_addr.s_addr = v4addr->addr;
  394                 if (sin->sin_addr.s_addr == INADDR_ANY)
  395                         zero_address = 1;
  396                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  397                     "process_asconf_delete_ip: deleting ");
  398                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
  399                 break;
  400 #endif
  401 #ifdef INET6
  402         case SCTP_IPV6_ADDRESS:
  403                 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
  404                         /* invalid param size */
  405                         return NULL;
  406                 }
  407                 v6addr = (struct sctp_ipv6addr_param *)ph;
  408                 sin6 = (struct sockaddr_in6 *)&sa_store;
  409                 bzero(sin6, sizeof(*sin6));
  410                 sin6->sin6_family = AF_INET6;
  411                 sin6->sin6_len = sizeof(struct sockaddr_in6);
  412                 sin6->sin6_port = stcb->rport;
  413                 memcpy(&sin6->sin6_addr, v6addr->addr,
  414                     sizeof(struct in6_addr));
  415                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
  416                         zero_address = 1;
  417                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  418                     "process_asconf_delete_ip: deleting ");
  419                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
  420                 break;
  421 #endif
  422         default:
  423                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  424                     SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
  425                     aparam_length);
  426                 return m_reply;
  427         }
  428 
  429         /* make sure the source address is not being deleted */
  430         if (sctp_cmpaddr(sa, (struct sockaddr *)&sa_source)) {
  431                 /* trying to delete the source address! */
  432                 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete source addr\n");
  433                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  434                     SCTP_CAUSE_DELETING_SRC_ADDR, (uint8_t *) aph,
  435                     aparam_length);
  436                 return m_reply;
  437         }
  438         /* if deleting 0.0.0.0/::0, delete all addresses except src addr */
  439         if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
  440                 result = sctp_asconf_del_remote_addrs_except(stcb,
  441                     (struct sockaddr *)&sa_source);
  442 
  443                 if (result) {
  444                         /* src address did not exist? */
  445                         SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: src addr does not exist?\n");
  446                         /* what error to reply with?? */
  447                         m_reply =
  448                             sctp_asconf_error_response(aph->correlation_id,
  449                             SCTP_CAUSE_REQUEST_REFUSED, (uint8_t *) aph,
  450                             aparam_length);
  451                 } else if (response_required) {
  452                         m_reply =
  453                             sctp_asconf_success_response(aph->correlation_id);
  454                 }
  455                 return m_reply;
  456         }
  457         /* delete the address */
  458         result = sctp_del_remote_addr(stcb, sa);
  459         /*
  460          * note if result == -2, the address doesn't exist in the asoc but
  461          * since it's being deleted anyways, we just ack the delete -- but
  462          * this probably means something has already gone awry
  463          */
  464         if (result == -1) {
  465                 /* only one address in the asoc */
  466                 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete last IP addr!\n");
  467                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  468                     SCTP_CAUSE_DELETING_LAST_ADDR, (uint8_t *) aph,
  469                     aparam_length);
  470         } else {
  471                 if (response_required) {
  472                         m_reply = sctp_asconf_success_response(aph->correlation_id);
  473                 }
  474                 /* notify upper layer */
  475                 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
  476         }
  477         return m_reply;
  478 }
  479 
  480 static struct mbuf *
  481 sctp_process_asconf_set_primary(struct mbuf *m,
  482     struct sctp_asconf_paramhdr *aph,
  483     struct sctp_tcb *stcb, int response_required)
  484 {
  485         struct mbuf *m_reply = NULL;
  486         struct sockaddr_storage sa_source, sa_store;
  487         struct sctp_paramhdr *ph;
  488         uint16_t param_type, param_length, aparam_length;
  489         struct sockaddr *sa;
  490         int zero_address = 0;
  491 
  492 #ifdef INET
  493         struct sockaddr_in *sin;
  494         struct sctp_ipv4addr_param *v4addr;
  495 
  496 #endif
  497 #ifdef INET6
  498         struct sockaddr_in6 *sin6;
  499         struct sctp_ipv6addr_param *v6addr;
  500 
  501 #endif
  502 
  503         aparam_length = ntohs(aph->ph.param_length);
  504         ph = (struct sctp_paramhdr *)(aph + 1);
  505         param_type = ntohs(ph->param_type);
  506         param_length = ntohs(ph->param_length);
  507 
  508         sa = (struct sockaddr *)&sa_store;
  509         switch (param_type) {
  510 #ifdef INET
  511         case SCTP_IPV4_ADDRESS:
  512                 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
  513                         /* invalid param size */
  514                         return NULL;
  515                 }
  516                 v4addr = (struct sctp_ipv4addr_param *)ph;
  517                 sin = (struct sockaddr_in *)&sa_store;
  518                 bzero(sin, sizeof(*sin));
  519                 sin->sin_family = AF_INET;
  520                 sin->sin_len = sizeof(struct sockaddr_in);
  521                 sin->sin_addr.s_addr = v4addr->addr;
  522                 if (sin->sin_addr.s_addr == INADDR_ANY)
  523                         zero_address = 1;
  524                 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: ");
  525                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
  526                 break;
  527 #endif
  528 #ifdef INET6
  529         case SCTP_IPV6_ADDRESS:
  530                 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
  531                         /* invalid param size */
  532                         return NULL;
  533                 }
  534                 v6addr = (struct sctp_ipv6addr_param *)ph;
  535                 sin6 = (struct sockaddr_in6 *)&sa_store;
  536                 bzero(sin6, sizeof(*sin6));
  537                 sin6->sin6_family = AF_INET6;
  538                 sin6->sin6_len = sizeof(struct sockaddr_in6);
  539                 memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
  540                     sizeof(struct in6_addr));
  541                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
  542                         zero_address = 1;
  543                 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: ");
  544                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
  545                 break;
  546 #endif
  547         default:
  548                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  549                     SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
  550                     aparam_length);
  551                 return m_reply;
  552         }
  553 
  554         /* if 0.0.0.0/::0, use the source address instead */
  555         if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
  556                 sa = (struct sockaddr *)&sa_source;
  557                 sctp_asconf_get_source_ip(m, sa);
  558                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  559                     "process_asconf_set_primary: using source addr ");
  560                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
  561         }
  562         /* set the primary address */
  563         if (sctp_set_primary_addr(stcb, sa, NULL) == 0) {
  564                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  565                     "process_asconf_set_primary: primary address set\n");
  566                 /* notify upper layer */
  567                 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
  568                 if ((stcb->asoc.primary_destination->dest_state & SCTP_ADDR_REACHABLE) &&
  569                     (!(stcb->asoc.primary_destination->dest_state & SCTP_ADDR_PF)) &&
  570                     (stcb->asoc.alternate)) {
  571                         sctp_free_remote_addr(stcb->asoc.alternate);
  572                         stcb->asoc.alternate = NULL;
  573                 }
  574                 if (response_required) {
  575                         m_reply = sctp_asconf_success_response(aph->correlation_id);
  576                 }
  577                 /*
  578                  * Mobility adaptation. Ideally, when the reception of SET
  579                  * PRIMARY with DELETE IP ADDRESS of the previous primary
  580                  * destination, unacknowledged DATA are retransmitted
  581                  * immediately to the new primary destination for seamless
  582                  * handover. If the destination is UNCONFIRMED and marked to
  583                  * REQ_PRIM, The retransmission occur when reception of the
  584                  * HEARTBEAT-ACK.  (See sctp_handle_heartbeat_ack in
  585                  * sctp_input.c) Also, when change of the primary
  586                  * destination, it is better that all subsequent new DATA
  587                  * containing already queued DATA are transmitted to the new
  588                  * primary destination. (by micchie)
  589                  */
  590                 if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
  591                     SCTP_MOBILITY_BASE) ||
  592                     sctp_is_mobility_feature_on(stcb->sctp_ep,
  593                     SCTP_MOBILITY_FASTHANDOFF)) &&
  594                     sctp_is_mobility_feature_on(stcb->sctp_ep,
  595                     SCTP_MOBILITY_PRIM_DELETED) &&
  596                     (stcb->asoc.primary_destination->dest_state &
  597                     SCTP_ADDR_UNCONFIRMED) == 0) {
  598 
  599                         sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7);
  600                         if (sctp_is_mobility_feature_on(stcb->sctp_ep,
  601                             SCTP_MOBILITY_FASTHANDOFF)) {
  602                                 sctp_assoc_immediate_retrans(stcb,
  603                                     stcb->asoc.primary_destination);
  604                         }
  605                         if (sctp_is_mobility_feature_on(stcb->sctp_ep,
  606                             SCTP_MOBILITY_BASE)) {
  607                                 sctp_move_chunks_from_net(stcb,
  608                                     stcb->asoc.deleted_primary);
  609                         }
  610                         sctp_delete_prim_timer(stcb->sctp_ep, stcb,
  611                             stcb->asoc.deleted_primary);
  612                 }
  613         } else {
  614                 /* couldn't set the requested primary address! */
  615                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  616                     "process_asconf_set_primary: set primary failed!\n");
  617                 /* must have been an invalid address, so report */
  618                 m_reply = sctp_asconf_error_response(aph->correlation_id,
  619                     SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
  620                     aparam_length);
  621         }
  622 
  623         return m_reply;
  624 }
  625 
  626 /*
  627  * handles an ASCONF chunk.
  628  * if all parameters are processed ok, send a plain (empty) ASCONF-ACK
  629  */
  630 void
  631 sctp_handle_asconf(struct mbuf *m, unsigned int offset,
  632     struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb,
  633     int first)
  634 {
  635         struct sctp_association *asoc;
  636         uint32_t serial_num;
  637         struct mbuf *n, *m_ack, *m_result, *m_tail;
  638         struct sctp_asconf_ack_chunk *ack_cp;
  639         struct sctp_asconf_paramhdr *aph, *ack_aph;
  640         struct sctp_ipv6addr_param *p_addr;
  641         unsigned int asconf_limit, cnt;
  642         int error = 0;          /* did an error occur? */
  643 
  644         /* asconf param buffer */
  645         uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
  646         struct sctp_asconf_ack *ack, *ack_next;
  647 
  648         /* verify minimum length */
  649         if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) {
  650                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  651                     "handle_asconf: chunk too small = %xh\n",
  652                     ntohs(cp->ch.chunk_length));
  653                 return;
  654         }
  655         asoc = &stcb->asoc;
  656         serial_num = ntohl(cp->serial_number);
  657 
  658         if (SCTP_TSN_GE(asoc->asconf_seq_in, serial_num)) {
  659                 /* got a duplicate ASCONF */
  660                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  661                     "handle_asconf: got duplicate serial number = %xh\n",
  662                     serial_num);
  663                 return;
  664         } else if (serial_num != (asoc->asconf_seq_in + 1)) {
  665                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: incorrect serial number = %xh (expected next = %xh)\n",
  666                     serial_num, asoc->asconf_seq_in + 1);
  667                 return;
  668         }
  669         /* it's the expected "next" sequence number, so process it */
  670         asoc->asconf_seq_in = serial_num;       /* update sequence */
  671         /* get length of all the param's in the ASCONF */
  672         asconf_limit = offset + ntohs(cp->ch.chunk_length);
  673         SCTPDBG(SCTP_DEBUG_ASCONF1,
  674             "handle_asconf: asconf_limit=%u, sequence=%xh\n",
  675             asconf_limit, serial_num);
  676 
  677         if (first) {
  678                 /* delete old cache */
  679                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: Now processing first ASCONF. Try to delete old cache\n");
  680 
  681                 TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) {
  682                         if (ack->serial_number == serial_num)
  683                                 break;
  684                         SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: delete old(%u) < first(%u)\n",
  685                             ack->serial_number, serial_num);
  686                         TAILQ_REMOVE(&asoc->asconf_ack_sent, ack, next);
  687                         if (ack->data != NULL) {
  688                                 sctp_m_freem(ack->data);
  689                         }
  690                         SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack);
  691                 }
  692         }
  693         m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0,
  694             M_DONTWAIT, 1, MT_DATA);
  695         if (m_ack == NULL) {
  696                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  697                     "handle_asconf: couldn't get mbuf!\n");
  698                 return;
  699         }
  700         m_tail = m_ack;         /* current reply chain's tail */
  701 
  702         /* fill in ASCONF-ACK header */
  703         ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *);
  704         ack_cp->ch.chunk_type = SCTP_ASCONF_ACK;
  705         ack_cp->ch.chunk_flags = 0;
  706         ack_cp->serial_number = htonl(serial_num);
  707         /* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */
  708         SCTP_BUF_LEN(m_ack) = sizeof(struct sctp_asconf_ack_chunk);
  709         ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk);
  710 
  711         /* skip the lookup address parameter */
  712         offset += sizeof(struct sctp_asconf_chunk);
  713         p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *) & aparam_buf);
  714         if (p_addr == NULL) {
  715                 SCTPDBG(SCTP_DEBUG_ASCONF1,
  716                     "handle_asconf: couldn't get lookup addr!\n");
  717                 /* respond with a missing/invalid mandatory parameter error */
  718                 return;
  719         }
  720         /* param_length is already validated in process_control... */
  721         offset += ntohs(p_addr->ph.param_length);       /* skip lookup addr */
  722 
  723         /* get pointer to first asconf param in ASCONF-ACK */
  724         ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t)+sizeof(struct sctp_asconf_ack_chunk));
  725         if (ack_aph == NULL) {
  726                 SCTPDBG(SCTP_DEBUG_ASCONF1, "Gak in asconf2\n");
  727                 return;
  728         }
  729         /* get pointer to first asconf param in ASCONF */
  730         aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *) & aparam_buf);
  731         if (aph == NULL) {
  732                 SCTPDBG(SCTP_DEBUG_ASCONF1, "Empty ASCONF received?\n");
  733                 goto send_reply;
  734         }
  735         /* process through all parameters */
  736         cnt = 0;
  737         while (aph != NULL) {
  738                 unsigned int param_length, param_type;
  739 
  740                 param_type = ntohs(aph->ph.param_type);
  741                 param_length = ntohs(aph->ph.param_length);
  742                 if (offset + param_length > asconf_limit) {
  743                         /* parameter goes beyond end of chunk! */
  744                         sctp_m_freem(m_ack);
  745                         return;
  746                 }
  747                 m_result = NULL;
  748 
  749                 if (param_length > sizeof(aparam_buf)) {
  750                         SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) larger than buffer size!\n", param_length);
  751                         sctp_m_freem(m_ack);
  752                         return;
  753                 }
  754                 if (param_length <= sizeof(struct sctp_paramhdr)) {
  755                         SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) too short\n", param_length);
  756                         sctp_m_freem(m_ack);
  757                 }
  758                 /* get the entire parameter */
  759                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
  760                 if (aph == NULL) {
  761                         SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: couldn't get entire param\n");
  762                         sctp_m_freem(m_ack);
  763                         return;
  764                 }
  765                 switch (param_type) {
  766                 case SCTP_ADD_IP_ADDRESS:
  767                         asoc->peer_supports_asconf = 1;
  768                         m_result = sctp_process_asconf_add_ip(m, aph, stcb,
  769                             (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error);
  770                         cnt++;
  771                         break;
  772                 case SCTP_DEL_IP_ADDRESS:
  773                         asoc->peer_supports_asconf = 1;
  774                         m_result = sctp_process_asconf_delete_ip(m, aph, stcb,
  775                             error);
  776                         break;
  777                 case SCTP_ERROR_CAUSE_IND:
  778                         /* not valid in an ASCONF chunk */
  779                         break;
  780                 case SCTP_SET_PRIM_ADDR:
  781                         asoc->peer_supports_asconf = 1;
  782                         m_result = sctp_process_asconf_set_primary(m, aph,
  783                             stcb, error);
  784                         break;
  785                 case SCTP_NAT_VTAGS:
  786                         SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: sees a NAT VTAG state parameter\n");
  787                         break;
  788                 case SCTP_SUCCESS_REPORT:
  789                         /* not valid in an ASCONF chunk */
  790                         break;
  791                 case SCTP_ULP_ADAPTATION:
  792                         /* FIX */
  793                         break;
  794                 default:
  795                         if ((param_type & 0x8000) == 0) {
  796                                 /* Been told to STOP at this param */
  797                                 asconf_limit = offset;
  798                                 /*
  799                                  * FIX FIX - We need to call
  800                                  * sctp_arethere_unrecognized_parameters()
  801                                  * to get a operr and send it for any
  802                                  * param's with the 0x4000 bit set OR do it
  803                                  * here ourselves... note we still must STOP
  804                                  * if the 0x8000 bit is clear.
  805                                  */
  806                         }
  807                         /* unknown/invalid param type */
  808                         break;
  809                 }               /* switch */
  810 
  811                 /* add any (error) result to the reply mbuf chain */
  812                 if (m_result != NULL) {
  813                         SCTP_BUF_NEXT(m_tail) = m_result;
  814                         m_tail = m_result;
  815                         /* update lengths, make sure it's aligned too */
  816                         SCTP_BUF_LEN(m_result) = SCTP_SIZE32(SCTP_BUF_LEN(m_result));
  817                         ack_cp->ch.chunk_length += SCTP_BUF_LEN(m_result);
  818                         /* set flag to force success reports */
  819                         error = 1;
  820                 }
  821                 offset += SCTP_SIZE32(param_length);
  822                 /* update remaining ASCONF message length to process */
  823                 if (offset >= asconf_limit) {
  824                         /* no more data in the mbuf chain */
  825                         break;
  826                 }
  827                 /* get pointer to next asconf param */
  828                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
  829                     sizeof(struct sctp_asconf_paramhdr),
  830                     (uint8_t *) & aparam_buf);
  831                 if (aph == NULL) {
  832                         /* can't get an asconf paramhdr */
  833                         SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: can't get asconf param hdr!\n");
  834                         /* FIX ME - add error here... */
  835                 }
  836         }
  837 
  838 send_reply:
  839         ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length);
  840         /* save the ASCONF-ACK reply */
  841         ack = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_asconf_ack),
  842             struct sctp_asconf_ack);
  843         if (ack == NULL) {
  844                 sctp_m_freem(m_ack);
  845                 return;
  846         }
  847         ack->serial_number = serial_num;
  848         ack->last_sent_to = NULL;
  849         ack->data = m_ack;
  850         ack->len = 0;
  851         for (n = m_ack; n != NULL; n = SCTP_BUF_NEXT(n)) {
  852                 ack->len += SCTP_BUF_LEN(n);
  853         }
  854         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next);
  855 
  856         /* see if last_control_chunk_from is set properly (use IP src addr) */
  857         if (stcb->asoc.last_control_chunk_from == NULL) {
  858                 /*
  859                  * this could happen if the source address was just newly
  860                  * added
  861                  */
  862                 struct ip *iph;
  863                 struct sctphdr *sh;
  864                 struct sockaddr_storage from_store;
  865                 struct sockaddr *from = (struct sockaddr *)&from_store;
  866 
  867                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n");
  868                 /* pullup already done, IP options already stripped */
  869                 iph = mtod(m, struct ip *);
  870                 switch (iph->ip_v) {
  871 #ifdef INET
  872                 case IPVERSION:
  873                         {
  874                                 struct sockaddr_in *from4;
  875 
  876                                 sh = (struct sctphdr *)((caddr_t)iph + sizeof(*iph));
  877                                 from4 = (struct sockaddr_in *)&from_store;
  878                                 bzero(from4, sizeof(*from4));
  879                                 from4->sin_family = AF_INET;
  880                                 from4->sin_len = sizeof(struct sockaddr_in);
  881                                 from4->sin_addr.s_addr = iph->ip_src.s_addr;
  882                                 from4->sin_port = sh->src_port;
  883                                 break;
  884                         }
  885 #endif
  886 #ifdef INET6
  887                 case IPV6_VERSION >> 4:
  888                         {
  889                                 struct ip6_hdr *ip6;
  890                                 struct sockaddr_in6 *from6;
  891 
  892                                 ip6 = mtod(m, struct ip6_hdr *);
  893                                 sh = (struct sctphdr *)((caddr_t)ip6 + sizeof(*ip6));
  894                                 from6 = (struct sockaddr_in6 *)&from_store;
  895                                 bzero(from6, sizeof(*from6));
  896                                 from6->sin6_family = AF_INET6;
  897                                 from6->sin6_len = sizeof(struct sockaddr_in6);
  898                                 from6->sin6_addr = ip6->ip6_src;
  899                                 from6->sin6_port = sh->src_port;
  900                                 /*
  901                                  * Get the scopes in properly to the sin6
  902                                  * addr's
  903                                  */
  904                                 /* we probably don't need these operations */
  905                                 (void)sa6_recoverscope(from6);
  906                                 sa6_embedscope(from6,
  907                                     MODULE_GLOBAL(ip6_use_defzone));
  908 
  909                                 break;
  910                         }
  911 #endif
  912                 default:
  913                         /* unknown address type */
  914                         from = NULL;
  915                 }
  916                 if (from != NULL) {
  917                         SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: ");
  918                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, from);
  919                         /* look up the from address */
  920                         stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, from);
  921 #ifdef SCTP_DEBUG
  922                         if (stcb->asoc.last_control_chunk_from == NULL)
  923                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n");
  924 #endif
  925                 }
  926         }
  927 }
  928 
  929 /*
  930  * does the address match? returns 0 if not, 1 if so
  931  */
  932 static uint32_t
  933 sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
  934 {
  935         switch (sa->sa_family) {
  936 #ifdef INET6
  937         case AF_INET6:
  938                 {
  939                         /* XXX scopeid */
  940                         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
  941 
  942                         if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) &&
  943                             (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr,
  944                             sizeof(struct in6_addr)) == 0)) {
  945                                 return (1);
  946                         }
  947                         break;
  948                 }
  949 #endif
  950 #ifdef INET
  951         case AF_INET:
  952                 {
  953                         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
  954 
  955                         if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) &&
  956                             (memcmp(&aa->ap.addrp.addr, &sin->sin_addr,
  957                             sizeof(struct in_addr)) == 0)) {
  958                                 return (1);
  959                         }
  960                         break;
  961                 }
  962 #endif
  963         default:
  964                 break;
  965         }
  966         return (0);
  967 }
  968 
  969 /*
  970  * does the address match? returns 0 if not, 1 if so
  971  */
  972 static uint32_t
  973 sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
  974 {
  975         uint16_t param_type, param_length;
  976 
  977         param_type = ntohs(ph->param_type);
  978         param_length = ntohs(ph->param_length);
  979         switch (sa->sa_family) {
  980 #ifdef INET6
  981         case AF_INET6:
  982                 {
  983                         /* XXX scopeid */
  984                         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
  985                         struct sctp_ipv6addr_param *v6addr;
  986 
  987                         v6addr = (struct sctp_ipv6addr_param *)ph;
  988                         if ((param_type == SCTP_IPV6_ADDRESS) &&
  989                             param_length == sizeof(struct sctp_ipv6addr_param) &&
  990                             (memcmp(&v6addr->addr, &sin6->sin6_addr,
  991                             sizeof(struct in6_addr)) == 0)) {
  992                                 return (1);
  993                         }
  994                         break;
  995                 }
  996 #endif
  997 #ifdef INET
  998         case AF_INET:
  999                 {
 1000                         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
 1001                         struct sctp_ipv4addr_param *v4addr;
 1002 
 1003                         v4addr = (struct sctp_ipv4addr_param *)ph;
 1004                         if ((param_type == SCTP_IPV4_ADDRESS) &&
 1005                             param_length == sizeof(struct sctp_ipv4addr_param) &&
 1006                             (memcmp(&v4addr->addr, &sin->sin_addr,
 1007                             sizeof(struct in_addr)) == 0)) {
 1008                                 return (1);
 1009                         }
 1010                         break;
 1011                 }
 1012 #endif
 1013         default:
 1014                 break;
 1015         }
 1016         return (0);
 1017 }
 1018 
 1019 /*
 1020  * Cleanup for non-responded/OP ERR'd ASCONF
 1021  */
 1022 void
 1023 sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
 1024 {
 1025         /* mark peer as ASCONF incapable */
 1026         stcb->asoc.peer_supports_asconf = 0;
 1027         /*
 1028          * clear out any existing asconfs going out
 1029          */
 1030         sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
 1031             SCTP_FROM_SCTP_ASCONF + SCTP_LOC_2);
 1032         stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out;
 1033         /* remove the old ASCONF on our outbound queue */
 1034         sctp_toss_old_asconf(stcb);
 1035 }
 1036 
 1037 /*
 1038  * cleanup any cached source addresses that may be topologically
 1039  * incorrect after a new address has been added to this interface.
 1040  */
 1041 static void
 1042 sctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn)
 1043 {
 1044         struct sctp_nets *net;
 1045 
 1046         /*
 1047          * Ideally, we want to only clear cached routes and source addresses
 1048          * that are topologically incorrect.  But since there is no easy way
 1049          * to know whether the newly added address on the ifn would cause a
 1050          * routing change (i.e. a new egress interface would be chosen)
 1051          * without doing a new routing lookup and source address selection,
 1052          * we will (for now) just flush any cached route using a different
 1053          * ifn (and cached source addrs) and let output re-choose them
 1054          * during the next send on that net.
 1055          */
 1056         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1057                 /*
 1058                  * clear any cached route (and cached source address) if the
 1059                  * route's interface is NOT the same as the address change.
 1060                  * If it's the same interface, just clear the cached source
 1061                  * address.
 1062                  */
 1063                 if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) &&
 1064                     ((ifn == NULL) ||
 1065                     (SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) {
 1066                         /* clear any cached route */
 1067                         RTFREE(net->ro.ro_rt);
 1068                         net->ro.ro_rt = NULL;
 1069                 }
 1070                 /* clear any cached source address */
 1071                 if (net->src_addr_selected) {
 1072                         sctp_free_ifa(net->ro._s_addr);
 1073                         net->ro._s_addr = NULL;
 1074                         net->src_addr_selected = 0;
 1075                 }
 1076         }
 1077 }
 1078 
 1079 
 1080 void
 1081 sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet)
 1082 {
 1083         int error;
 1084 
 1085         if (dstnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
 1086                 return;
 1087         }
 1088         if (stcb->asoc.deleted_primary == NULL) {
 1089                 return;
 1090         }
 1091         if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
 1092                 SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Deleted primary is ");
 1093                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa);
 1094                 SCTPDBG(SCTP_DEBUG_ASCONF1, "Current Primary is ");
 1095                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa);
 1096                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb,
 1097                     stcb->asoc.deleted_primary,
 1098                     SCTP_FROM_SCTP_TIMER + SCTP_LOC_8);
 1099                 stcb->asoc.num_send_timers_up--;
 1100                 if (stcb->asoc.num_send_timers_up < 0) {
 1101                         stcb->asoc.num_send_timers_up = 0;
 1102                 }
 1103                 SCTP_TCB_LOCK_ASSERT(stcb);
 1104                 error = sctp_t3rxt_timer(stcb->sctp_ep, stcb,
 1105                     stcb->asoc.deleted_primary);
 1106                 if (error) {
 1107                         SCTP_INP_DECR_REF(stcb->sctp_ep);
 1108                         return;
 1109                 }
 1110                 SCTP_TCB_LOCK_ASSERT(stcb);
 1111 #ifdef SCTP_AUDITING_ENABLED
 1112                 sctp_auditing(4, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary);
 1113 #endif
 1114                 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
 1115                 if ((stcb->asoc.num_send_timers_up == 0) &&
 1116                     (stcb->asoc.sent_queue_cnt > 0)) {
 1117                         struct sctp_tmit_chunk *chk;
 1118 
 1119                         chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
 1120                         sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
 1121                             stcb, chk->whoTo);
 1122                 }
 1123         }
 1124         return;
 1125 }
 1126 
 1127 static int
 1128     sctp_asconf_queue_mgmt(struct sctp_tcb *, struct sctp_ifa *, uint16_t);
 1129 
 1130 void
 1131 sctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net)
 1132 {
 1133         struct sctp_tmit_chunk *chk;
 1134 
 1135         SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO);
 1136         sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net,
 1137             SCTP_FROM_SCTP_TIMER + SCTP_LOC_5);
 1138         stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
 1139         net->error_count = 0;
 1140         TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
 1141                 if (chk->whoTo == net) {
 1142                         if (chk->sent < SCTP_DATAGRAM_RESEND) {
 1143                                 chk->sent = SCTP_DATAGRAM_RESEND;
 1144                                 sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
 1145                                 sctp_flight_size_decrease(chk);
 1146                                 sctp_total_flight_decrease(stcb, chk);
 1147                                 net->marked_retrans++;
 1148                                 stcb->asoc.marked_retrans++;
 1149                         }
 1150                 }
 1151         }
 1152         if (net->marked_retrans) {
 1153                 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
 1154         }
 1155 }
 1156 
 1157 static void
 1158 sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
 1159 {
 1160         struct sctp_nets *net;
 1161         int addrnum, changed;
 1162 
 1163         /*
 1164          * If number of local valid addresses is 1, the valid address is
 1165          * probably newly added address. Several valid addresses in this
 1166          * association.  A source address may not be changed.  Additionally,
 1167          * they can be configured on a same interface as "alias" addresses.
 1168          * (by micchie)
 1169          */
 1170         addrnum = sctp_local_addr_count(stcb);
 1171         SCTPDBG(SCTP_DEBUG_ASCONF1, "p_check_react(): %d local addresses\n",
 1172             addrnum);
 1173         if (addrnum == 1) {
 1174                 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1175                         /* clear any cached route and source address */
 1176                         if (net->ro.ro_rt) {
 1177                                 RTFREE(net->ro.ro_rt);
 1178                                 net->ro.ro_rt = NULL;
 1179                         }
 1180                         if (net->src_addr_selected) {
 1181                                 sctp_free_ifa(net->ro._s_addr);
 1182                                 net->ro._s_addr = NULL;
 1183                                 net->src_addr_selected = 0;
 1184                         }
 1185                         /* Retransmit unacknowledged DATA chunks immediately */
 1186                         if (sctp_is_mobility_feature_on(stcb->sctp_ep,
 1187                             SCTP_MOBILITY_FASTHANDOFF)) {
 1188                                 sctp_net_immediate_retrans(stcb, net);
 1189                         }
 1190                         /* also, SET PRIMARY is maybe already sent */
 1191                 }
 1192                 return;
 1193         }
 1194         /* Multiple local addresses exsist in the association.  */
 1195         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1196                 /* clear any cached route and source address */
 1197                 if (net->ro.ro_rt) {
 1198                         RTFREE(net->ro.ro_rt);
 1199                         net->ro.ro_rt = NULL;
 1200                 }
 1201                 if (net->src_addr_selected) {
 1202                         sctp_free_ifa(net->ro._s_addr);
 1203                         net->ro._s_addr = NULL;
 1204                         net->src_addr_selected = 0;
 1205                 }
 1206                 /*
 1207                  * Check if the nexthop is corresponding to the new address.
 1208                  * If the new address is corresponding to the current
 1209                  * nexthop, the path will be changed. If the new address is
 1210                  * NOT corresponding to the current nexthop, the path will
 1211                  * not be changed.
 1212                  */
 1213                 SCTP_RTALLOC((sctp_route_t *) & net->ro,
 1214                     stcb->sctp_ep->def_vrf_id);
 1215                 if (net->ro.ro_rt == NULL)
 1216                         continue;
 1217 
 1218                 changed = 0;
 1219                 switch (net->ro._l_addr.sa.sa_family) {
 1220 #ifdef INET
 1221                 case AF_INET:
 1222                         if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *) & net->ro)) {
 1223                                 changed = 1;
 1224                         }
 1225                         break;
 1226 #endif
 1227 #ifdef INET6
 1228                 case AF_INET6:
 1229                         if (sctp_v6src_match_nexthop(
 1230                             &newifa->address.sin6, (sctp_route_t *) & net->ro)) {
 1231                                 changed = 1;
 1232                         }
 1233                         break;
 1234 #endif
 1235                 default:
 1236                         break;
 1237                 }
 1238                 /*
 1239                  * if the newly added address does not relate routing
 1240                  * information, we skip.
 1241                  */
 1242                 if (changed == 0)
 1243                         continue;
 1244                 /* Retransmit unacknowledged DATA chunks immediately */
 1245                 if (sctp_is_mobility_feature_on(stcb->sctp_ep,
 1246                     SCTP_MOBILITY_FASTHANDOFF)) {
 1247                         sctp_net_immediate_retrans(stcb, net);
 1248                 }
 1249                 /* Send SET PRIMARY for this new address */
 1250                 if (net == stcb->asoc.primary_destination) {
 1251                         (void)sctp_asconf_queue_mgmt(stcb, newifa,
 1252                             SCTP_SET_PRIM_ADDR);
 1253                 }
 1254         }
 1255 }
 1256 
 1257 /*
 1258  * process an ADD/DELETE IP ack from peer.
 1259  * addr: corresponding sctp_ifa to the address being added/deleted.
 1260  * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS.
 1261  * flag: 1=success, 0=failure.
 1262  */
 1263 static void
 1264 sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr,
 1265     uint16_t type, uint32_t flag)
 1266 {
 1267         /*
 1268          * do the necessary asoc list work- if we get a failure indication,
 1269          * leave the address on the assoc's restricted list.  If we get a
 1270          * success indication, remove the address from the restricted list.
 1271          */
 1272         /*
 1273          * Note: this will only occur for ADD_IP_ADDRESS, since
 1274          * DEL_IP_ADDRESS is never actually added to the list...
 1275          */
 1276         if (flag) {
 1277                 /* success case, so remove from the restricted list */
 1278                 sctp_del_local_addr_restricted(stcb, addr);
 1279 
 1280                 if (sctp_is_mobility_feature_on(stcb->sctp_ep,
 1281                     SCTP_MOBILITY_BASE) ||
 1282                     sctp_is_mobility_feature_on(stcb->sctp_ep,
 1283                     SCTP_MOBILITY_FASTHANDOFF)) {
 1284                         sctp_path_check_and_react(stcb, addr);
 1285                         return;
 1286                 }
 1287                 /* clear any cached/topologically incorrect source addresses */
 1288                 sctp_asconf_nets_cleanup(stcb, addr->ifn_p);
 1289         }
 1290         /* else, leave it on the list */
 1291 }
 1292 
 1293 /*
 1294  * add an asconf add/delete/set primary IP address parameter to the queue.
 1295  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
 1296  * returns 0 if queued, -1 if not queued/removed.
 1297  * NOTE: if adding, but a delete for the same address is already scheduled
 1298  * (and not yet sent out), simply remove it from queue.  Same for deleting
 1299  * an address already scheduled for add.  If a duplicate operation is found,
 1300  * ignore the new one.
 1301  */
 1302 static int
 1303 sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
 1304     uint16_t type)
 1305 {
 1306         struct sctp_asconf_addr *aa, *aa_next;
 1307         struct sockaddr *sa;
 1308 
 1309         /* make sure the request isn't already in the queue */
 1310         TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
 1311                 /* address match? */
 1312                 if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0)
 1313                         continue;
 1314                 /*
 1315                  * is the request already in queue but not sent? pass the
 1316                  * request already sent in order to resolve the following
 1317                  * case: 1. arrival of ADD, then sent 2. arrival of DEL. we
 1318                  * can't remove the ADD request already sent 3. arrival of
 1319                  * ADD
 1320                  */
 1321                 if (aa->ap.aph.ph.param_type == type && aa->sent == 0) {
 1322                         return (-1);
 1323                 }
 1324                 /* is the negative request already in queue, and not sent */
 1325                 if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) &&
 1326                     (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) {
 1327                         /* add requested, delete already queued */
 1328                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1329                         /* remove the ifa from the restricted list */
 1330                         sctp_del_local_addr_restricted(stcb, ifa);
 1331                         /* free the asconf param */
 1332                         SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1333                         SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n");
 1334                         return (-1);
 1335                 }
 1336                 if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) &&
 1337                     (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) {
 1338                         /* delete requested, add already queued */
 1339                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1340                         /* remove the aa->ifa from the restricted list */
 1341                         sctp_del_local_addr_restricted(stcb, aa->ifa);
 1342                         /* free the asconf param */
 1343                         SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1344                         SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n");
 1345                         return (-1);
 1346                 }
 1347         }                       /* for each aa */
 1348 
 1349         /* adding new request to the queue */
 1350         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 1351             SCTP_M_ASC_ADDR);
 1352         if (aa == NULL) {
 1353                 /* didn't get memory */
 1354                 SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n");
 1355                 return (-1);
 1356         }
 1357         aa->special_del = 0;
 1358         /* fill in asconf address parameter fields */
 1359         /* top level elements are "networked" during send */
 1360         aa->ap.aph.ph.param_type = type;
 1361         aa->ifa = ifa;
 1362         atomic_add_int(&ifa->refcount, 1);
 1363         /* correlation_id filled in during send routine later... */
 1364         switch (ifa->address.sa.sa_family) {
 1365 #ifdef INET6
 1366         case AF_INET6:
 1367                 {
 1368                         struct sockaddr_in6 *sin6;
 1369 
 1370                         sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
 1371                         sa = (struct sockaddr *)sin6;
 1372                         aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 1373                         aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
 1374                         aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
 1375                             sizeof(struct sctp_ipv6addr_param);
 1376                         memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
 1377                             sizeof(struct in6_addr));
 1378                         break;
 1379                 }
 1380 #endif
 1381 #ifdef INET
 1382         case AF_INET:
 1383                 {
 1384                         struct sockaddr_in *sin;
 1385 
 1386                         sin = (struct sockaddr_in *)&ifa->address.sa;
 1387                         sa = (struct sockaddr *)sin;
 1388                         aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 1389                         aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
 1390                         aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
 1391                             sizeof(struct sctp_ipv4addr_param);
 1392                         memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
 1393                             sizeof(struct in_addr));
 1394                         break;
 1395                 }
 1396 #endif
 1397         default:
 1398                 /* invalid family! */
 1399                 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1400                 sctp_free_ifa(ifa);
 1401                 return (-1);
 1402         }
 1403         aa->sent = 0;           /* clear sent flag */
 1404 
 1405         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 1406 #ifdef SCTP_DEBUG
 1407         if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) {
 1408                 if (type == SCTP_ADD_IP_ADDRESS) {
 1409                         SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: ");
 1410                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 1411                 } else if (type == SCTP_DEL_IP_ADDRESS) {
 1412                         SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: ");
 1413                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 1414                 } else {
 1415                         SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: ");
 1416                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 1417                 }
 1418         }
 1419 #endif
 1420 
 1421         return (0);
 1422 }
 1423 
 1424 
 1425 /*
 1426  * add an asconf operation for the given ifa and type.
 1427  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
 1428  * returns 0 if completed, -1 if not completed, 1 if immediate send is
 1429  * advisable.
 1430  */
 1431 static int
 1432 sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
 1433     uint16_t type)
 1434 {
 1435         uint32_t status;
 1436         int pending_delete_queued = 0;
 1437 
 1438         /* see if peer supports ASCONF */
 1439         if (stcb->asoc.peer_supports_asconf == 0) {
 1440                 return (-1);
 1441         }
 1442         /*
 1443          * if this is deleting the last address from the assoc, mark it as
 1444          * pending.
 1445          */
 1446         if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending &&
 1447             (sctp_local_addr_count(stcb) < 2)) {
 1448                 /* set the pending delete info only */
 1449                 stcb->asoc.asconf_del_pending = 1;
 1450                 stcb->asoc.asconf_addr_del_pending = ifa;
 1451                 atomic_add_int(&ifa->refcount, 1);
 1452                 SCTPDBG(SCTP_DEBUG_ASCONF2,
 1453                     "asconf_queue_add: mark delete last address pending\n");
 1454                 return (-1);
 1455         }
 1456         /* queue an asconf parameter */
 1457         status = sctp_asconf_queue_mgmt(stcb, ifa, type);
 1458 
 1459         /*
 1460          * if this is an add, and there is a delete also pending (i.e. the
 1461          * last local address is being changed), queue the pending delete
 1462          * too.
 1463          */
 1464         if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) {
 1465                 /* queue in the pending delete */
 1466                 if (sctp_asconf_queue_mgmt(stcb,
 1467                     stcb->asoc.asconf_addr_del_pending,
 1468                     SCTP_DEL_IP_ADDRESS) == 0) {
 1469                         SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n");
 1470                         pending_delete_queued = 1;
 1471                         /* clear out the pending delete info */
 1472                         stcb->asoc.asconf_del_pending = 0;
 1473                         sctp_free_ifa(stcb->asoc.asconf_addr_del_pending);
 1474                         stcb->asoc.asconf_addr_del_pending = NULL;
 1475                 }
 1476         }
 1477         if (pending_delete_queued) {
 1478                 struct sctp_nets *net;
 1479 
 1480                 /*
 1481                  * since we know that the only/last address is now being
 1482                  * changed in this case, reset the cwnd/rto on all nets to
 1483                  * start as a new address and path.  Also clear the error
 1484                  * counts to give the assoc the best chance to complete the
 1485                  * address change.
 1486                  */
 1487                 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1488                         stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb,
 1489                             net);
 1490                         net->RTO = 0;
 1491                         net->error_count = 0;
 1492                 }
 1493                 stcb->asoc.overall_error_count = 0;
 1494                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
 1495                         sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
 1496                             stcb->asoc.overall_error_count,
 1497                             0,
 1498                             SCTP_FROM_SCTP_ASCONF,
 1499                             __LINE__);
 1500                 }
 1501                 /* queue in an advisory set primary too */
 1502                 (void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR);
 1503                 /* let caller know we should send this out immediately */
 1504                 status = 1;
 1505         }
 1506         return (status);
 1507 }
 1508 
 1509 /*-
 1510  * add an asconf delete IP address parameter to the queue by sockaddr and
 1511  * possibly with no sctp_ifa available.  This is only called by the routine
 1512  * that checks the addresses in an INIT-ACK against the current address list.
 1513  * returns 0 if completed, non-zero if not completed.
 1514  * NOTE: if an add is already scheduled (and not yet sent out), simply
 1515  * remove it from queue.  If a duplicate operation is found, ignore the
 1516  * new one.
 1517  */
 1518 static int
 1519 sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
 1520 {
 1521         struct sctp_ifa *ifa;
 1522         struct sctp_asconf_addr *aa, *aa_next;
 1523         uint32_t vrf_id;
 1524 
 1525         if (stcb == NULL) {
 1526                 return (-1);
 1527         }
 1528         /* see if peer supports ASCONF */
 1529         if (stcb->asoc.peer_supports_asconf == 0) {
 1530                 return (-1);
 1531         }
 1532         /* make sure the request isn't already in the queue */
 1533         TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
 1534                 /* address match? */
 1535                 if (sctp_asconf_addr_match(aa, sa) == 0)
 1536                         continue;
 1537                 /* is the request already in queue (sent or not) */
 1538                 if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
 1539                         return (-1);
 1540                 }
 1541                 /* is the negative request already in queue, and not sent */
 1542                 if (aa->sent == 1)
 1543                         continue;
 1544                 if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) {
 1545                         /* add already queued, so remove existing entry */
 1546                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1547                         sctp_del_local_addr_restricted(stcb, aa->ifa);
 1548                         /* free the entry */
 1549                         SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1550                         return (-1);
 1551                 }
 1552         }                       /* for each aa */
 1553 
 1554         /* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */
 1555         if (stcb) {
 1556                 vrf_id = stcb->asoc.vrf_id;
 1557         } else {
 1558                 vrf_id = SCTP_DEFAULT_VRFID;
 1559         }
 1560         ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 1561 
 1562         /* adding new request to the queue */
 1563         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 1564             SCTP_M_ASC_ADDR);
 1565         if (aa == NULL) {
 1566                 /* didn't get memory */
 1567                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1568                     "sctp_asconf_queue_sa_delete: failed to get memory!\n");
 1569                 return (-1);
 1570         }
 1571         aa->special_del = 0;
 1572         /* fill in asconf address parameter fields */
 1573         /* top level elements are "networked" during send */
 1574         aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
 1575         aa->ifa = ifa;
 1576         if (ifa)
 1577                 atomic_add_int(&ifa->refcount, 1);
 1578         /* correlation_id filled in during send routine later... */
 1579         switch (sa->sa_family) {
 1580 #ifdef INET6
 1581         case AF_INET6:
 1582                 {
 1583                         /* IPv6 address */
 1584                         struct sockaddr_in6 *sin6;
 1585 
 1586                         sin6 = (struct sockaddr_in6 *)sa;
 1587                         aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 1588                         aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
 1589                         aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
 1590                         memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
 1591                             sizeof(struct in6_addr));
 1592                         break;
 1593                 }
 1594 #endif
 1595 #ifdef INET
 1596         case AF_INET:
 1597                 {
 1598                         /* IPv4 address */
 1599                         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
 1600 
 1601                         aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 1602                         aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
 1603                         aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
 1604                         memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
 1605                             sizeof(struct in_addr));
 1606                         break;
 1607                 }
 1608 #endif
 1609         default:
 1610                 /* invalid family! */
 1611                 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1612                 if (ifa)
 1613                         sctp_free_ifa(ifa);
 1614                 return (-1);
 1615         }
 1616         aa->sent = 0;           /* clear sent flag */
 1617 
 1618         /* delete goes to the back of the queue */
 1619         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 1620 
 1621         /* sa_ignore MEMLEAK {memory is put on the tailq} */
 1622         return (0);
 1623 }
 1624 
 1625 /*
 1626  * find a specific asconf param on our "sent" queue
 1627  */
 1628 static struct sctp_asconf_addr *
 1629 sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
 1630 {
 1631         struct sctp_asconf_addr *aa;
 1632 
 1633         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 1634                 if (aa->ap.aph.correlation_id == correlation_id &&
 1635                     aa->sent == 1) {
 1636                         /* found it */
 1637                         return (aa);
 1638                 }
 1639         }
 1640         /* didn't find it */
 1641         return (NULL);
 1642 }
 1643 
 1644 /*
 1645  * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do
 1646  * notifications based on the error response
 1647  */
 1648 static void
 1649 sctp_asconf_process_error(struct sctp_tcb *stcb,
 1650     struct sctp_asconf_paramhdr *aph)
 1651 {
 1652         struct sctp_error_cause *eh;
 1653         struct sctp_paramhdr *ph;
 1654         uint16_t param_type;
 1655         uint16_t error_code;
 1656 
 1657         eh = (struct sctp_error_cause *)(aph + 1);
 1658         ph = (struct sctp_paramhdr *)(eh + 1);
 1659         /* validate lengths */
 1660         if (htons(eh->length) + sizeof(struct sctp_error_cause) >
 1661             htons(aph->ph.param_length)) {
 1662                 /* invalid error cause length */
 1663                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1664                     "asconf_process_error: cause element too long\n");
 1665                 return;
 1666         }
 1667         if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) >
 1668             htons(eh->length)) {
 1669                 /* invalid included TLV length */
 1670                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1671                     "asconf_process_error: included TLV too long\n");
 1672                 return;
 1673         }
 1674         /* which error code ? */
 1675         error_code = ntohs(eh->code);
 1676         param_type = ntohs(aph->ph.param_type);
 1677         /* FIX: this should go back up the REMOTE_ERROR ULP notify */
 1678         switch (error_code) {
 1679         case SCTP_CAUSE_RESOURCE_SHORTAGE:
 1680                 /* we allow ourselves to "try again" for this error */
 1681                 break;
 1682         default:
 1683                 /* peer can't handle it... */
 1684                 switch (param_type) {
 1685                 case SCTP_ADD_IP_ADDRESS:
 1686                 case SCTP_DEL_IP_ADDRESS:
 1687                         stcb->asoc.peer_supports_asconf = 0;
 1688                         break;
 1689                 case SCTP_SET_PRIM_ADDR:
 1690                         stcb->asoc.peer_supports_asconf = 0;
 1691                         break;
 1692                 default:
 1693                         break;
 1694                 }
 1695         }
 1696 }
 1697 
 1698 /*
 1699  * process an asconf queue param.
 1700  * aparam: parameter to process, will be removed from the queue.
 1701  * flag: 1=success case, 0=failure case
 1702  */
 1703 static void
 1704 sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
 1705     struct sctp_asconf_addr *aparam, uint32_t flag)
 1706 {
 1707         uint16_t param_type;
 1708 
 1709         /* process this param */
 1710         param_type = aparam->ap.aph.ph.param_type;
 1711         switch (param_type) {
 1712         case SCTP_ADD_IP_ADDRESS:
 1713                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1714                     "process_param_ack: added IP address\n");
 1715                 sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, param_type, flag);
 1716                 break;
 1717         case SCTP_DEL_IP_ADDRESS:
 1718                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1719                     "process_param_ack: deleted IP address\n");
 1720                 /* nothing really to do... lists already updated */
 1721                 break;
 1722         case SCTP_SET_PRIM_ADDR:
 1723                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1724                     "process_param_ack: set primary IP address\n");
 1725                 /* nothing to do... peer may start using this addr */
 1726                 if (flag == 0)
 1727                         stcb->asoc.peer_supports_asconf = 0;
 1728                 break;
 1729         default:
 1730                 /* should NEVER happen */
 1731                 break;
 1732         }
 1733 
 1734         /* remove the param and free it */
 1735         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
 1736         if (aparam->ifa)
 1737                 sctp_free_ifa(aparam->ifa);
 1738         SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
 1739 }
 1740 
 1741 /*
 1742  * cleanup from a bad asconf ack parameter
 1743  */
 1744 static void
 1745 sctp_asconf_ack_clear(struct sctp_tcb *stcb)
 1746 {
 1747         /* assume peer doesn't really know how to do asconfs */
 1748         stcb->asoc.peer_supports_asconf = 0;
 1749         /* XXX we could free the pending queue here */
 1750 }
 1751 
 1752 void
 1753 sctp_handle_asconf_ack(struct mbuf *m, int offset,
 1754     struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb,
 1755     struct sctp_nets *net, int *abort_no_unlock)
 1756 {
 1757         struct sctp_association *asoc;
 1758         uint32_t serial_num;
 1759         uint16_t ack_length;
 1760         struct sctp_asconf_paramhdr *aph;
 1761         struct sctp_asconf_addr *aa, *aa_next;
 1762         uint32_t last_error_id = 0;     /* last error correlation id */
 1763         uint32_t id;
 1764         struct sctp_asconf_addr *ap;
 1765 
 1766         /* asconf param buffer */
 1767         uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
 1768 
 1769         /* verify minimum length */
 1770         if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) {
 1771                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1772                     "handle_asconf_ack: chunk too small = %xh\n",
 1773                     ntohs(cp->ch.chunk_length));
 1774                 return;
 1775         }
 1776         asoc = &stcb->asoc;
 1777         serial_num = ntohl(cp->serial_number);
 1778 
 1779         /*
 1780          * NOTE: we may want to handle this differently- currently, we will
 1781          * abort when we get an ack for the expected serial number + 1 (eg.
 1782          * we didn't send it), process an ack normally if it is the expected
 1783          * serial number, and re-send the previous ack for *ALL* other
 1784          * serial numbers
 1785          */
 1786 
 1787         /*
 1788          * if the serial number is the next expected, but I didn't send it,
 1789          * abort the asoc, since someone probably just hijacked us...
 1790          */
 1791         if (serial_num == (asoc->asconf_seq_out + 1)) {
 1792                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
 1793                 sctp_abort_an_association(stcb->sctp_ep, stcb,
 1794                     SCTP_CAUSE_ILLEGAL_ASCONF_ACK, NULL, SCTP_SO_NOT_LOCKED);
 1795                 *abort_no_unlock = 1;
 1796                 return;
 1797         }
 1798         if (serial_num != asoc->asconf_seq_out_acked + 1) {
 1799                 /* got a duplicate/unexpected ASCONF-ACK */
 1800                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n",
 1801                     serial_num, asoc->asconf_seq_out_acked + 1);
 1802                 return;
 1803         }
 1804         if (serial_num == asoc->asconf_seq_out - 1) {
 1805                 /* stop our timer */
 1806                 sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
 1807                     SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3);
 1808         }
 1809         /* process the ASCONF-ACK contents */
 1810         ack_length = ntohs(cp->ch.chunk_length) -
 1811             sizeof(struct sctp_asconf_ack_chunk);
 1812         offset += sizeof(struct sctp_asconf_ack_chunk);
 1813         /* process through all parameters */
 1814         while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) {
 1815                 unsigned int param_length, param_type;
 1816 
 1817                 /* get pointer to next asconf parameter */
 1818                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
 1819                     sizeof(struct sctp_asconf_paramhdr), aparam_buf);
 1820                 if (aph == NULL) {
 1821                         /* can't get an asconf paramhdr */
 1822                         sctp_asconf_ack_clear(stcb);
 1823                         return;
 1824                 }
 1825                 param_type = ntohs(aph->ph.param_type);
 1826                 param_length = ntohs(aph->ph.param_length);
 1827                 if (param_length > ack_length) {
 1828                         sctp_asconf_ack_clear(stcb);
 1829                         return;
 1830                 }
 1831                 if (param_length < sizeof(struct sctp_paramhdr)) {
 1832                         sctp_asconf_ack_clear(stcb);
 1833                         return;
 1834                 }
 1835                 /* get the complete parameter... */
 1836                 if (param_length > sizeof(aparam_buf)) {
 1837                         SCTPDBG(SCTP_DEBUG_ASCONF1,
 1838                             "param length (%u) larger than buffer size!\n", param_length);
 1839                         sctp_asconf_ack_clear(stcb);
 1840                         return;
 1841                 }
 1842                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
 1843                 if (aph == NULL) {
 1844                         sctp_asconf_ack_clear(stcb);
 1845                         return;
 1846                 }
 1847                 /* correlation_id is transparent to peer, no ntohl needed */
 1848                 id = aph->correlation_id;
 1849 
 1850                 switch (param_type) {
 1851                 case SCTP_ERROR_CAUSE_IND:
 1852                         last_error_id = id;
 1853                         /* find the corresponding asconf param in our queue */
 1854                         ap = sctp_asconf_find_param(stcb, id);
 1855                         if (ap == NULL) {
 1856                                 /* hmm... can't find this in our queue! */
 1857                                 break;
 1858                         }
 1859                         /* process the parameter, failed flag */
 1860                         sctp_asconf_process_param_ack(stcb, ap, 0);
 1861                         /* process the error response */
 1862                         sctp_asconf_process_error(stcb, aph);
 1863                         break;
 1864                 case SCTP_SUCCESS_REPORT:
 1865                         /* find the corresponding asconf param in our queue */
 1866                         ap = sctp_asconf_find_param(stcb, id);
 1867                         if (ap == NULL) {
 1868                                 /* hmm... can't find this in our queue! */
 1869                                 break;
 1870                         }
 1871                         /* process the parameter, success flag */
 1872                         sctp_asconf_process_param_ack(stcb, ap, 1);
 1873                         break;
 1874                 default:
 1875                         break;
 1876                 }               /* switch */
 1877 
 1878                 /* update remaining ASCONF-ACK message length to process */
 1879                 ack_length -= SCTP_SIZE32(param_length);
 1880                 if (ack_length <= 0) {
 1881                         /* no more data in the mbuf chain */
 1882                         break;
 1883                 }
 1884                 offset += SCTP_SIZE32(param_length);
 1885         }                       /* while */
 1886 
 1887         /*
 1888          * if there are any "sent" params still on the queue, these are
 1889          * implicitly "success", or "failed" (if we got an error back) ...
 1890          * so process these appropriately
 1891          * 
 1892          * we assume that the correlation_id's are monotonically increasing
 1893          * beginning from 1 and that we don't have *that* many outstanding
 1894          * at any given time
 1895          */
 1896         if (last_error_id == 0)
 1897                 last_error_id--;/* set to "max" value */
 1898         TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
 1899                 if (aa->sent == 1) {
 1900                         /*
 1901                          * implicitly successful or failed if correlation_id
 1902                          * < last_error_id, then success else, failure
 1903                          */
 1904                         if (aa->ap.aph.correlation_id < last_error_id)
 1905                                 sctp_asconf_process_param_ack(stcb, aa, 1);
 1906                         else
 1907                                 sctp_asconf_process_param_ack(stcb, aa, 0);
 1908                 } else {
 1909                         /*
 1910                          * since we always process in order (FIFO queue) if
 1911                          * we reach one that hasn't been sent, the rest
 1912                          * should not have been sent either. so, we're
 1913                          * done...
 1914                          */
 1915                         break;
 1916                 }
 1917         }
 1918 
 1919         /* update the next sequence number to use */
 1920         asoc->asconf_seq_out_acked++;
 1921         /* remove the old ASCONF on our outbound queue */
 1922         sctp_toss_old_asconf(stcb);
 1923         if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
 1924 #ifdef SCTP_TIMER_BASED_ASCONF
 1925                 /* we have more params, so restart our timer */
 1926                 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep,
 1927                     stcb, net);
 1928 #else
 1929                 /* we have more params, so send out more */
 1930                 sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
 1931 #endif
 1932         }
 1933 }
 1934 
 1935 #ifdef INET6
 1936 static uint32_t
 1937 sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa)
 1938 {
 1939         struct sockaddr_in6 *sin6, *net6;
 1940         struct sctp_nets *net;
 1941 
 1942         if (sa->sa_family != AF_INET6) {
 1943                 /* wrong family */
 1944                 return (0);
 1945         }
 1946         sin6 = (struct sockaddr_in6 *)sa;
 1947         if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) {
 1948                 /* not link local address */
 1949                 return (0);
 1950         }
 1951         /* hunt through our destination nets list for this scope_id */
 1952         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1953                 if (((struct sockaddr *)(&net->ro._l_addr))->sa_family !=
 1954                     AF_INET6)
 1955                         continue;
 1956                 net6 = (struct sockaddr_in6 *)&net->ro._l_addr;
 1957                 if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0)
 1958                         continue;
 1959                 if (sctp_is_same_scope(sin6, net6)) {
 1960                         /* found one */
 1961                         return (1);
 1962                 }
 1963         }
 1964         /* didn't find one */
 1965         return (0);
 1966 }
 1967 
 1968 #endif
 1969 
 1970 /*
 1971  * address management functions
 1972  */
 1973 static void
 1974 sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
 1975     struct sctp_ifa *ifa, uint16_t type, int addr_locked)
 1976 {
 1977         int status;
 1978 
 1979 
 1980         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 ||
 1981             sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
 1982                 /* subset bound, no ASCONF allowed case, so ignore */
 1983                 return;
 1984         }
 1985         /*
 1986          * note: we know this is not the subset bound, no ASCONF case eg.
 1987          * this is boundall or subset bound w/ASCONF allowed
 1988          */
 1989 
 1990         /* first, make sure it's a good address family */
 1991         switch (ifa->address.sa.sa_family) {
 1992 #ifdef INET6
 1993         case AF_INET6:
 1994                 break;
 1995 #endif
 1996 #ifdef INET
 1997         case AF_INET:
 1998                 break;
 1999 #endif
 2000         default:
 2001                 return;
 2002         }
 2003 #ifdef INET6
 2004         /* make sure we're "allowed" to add this type of addr */
 2005         if (ifa->address.sa.sa_family == AF_INET6) {
 2006                 /* invalid if we're not a v6 endpoint */
 2007                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)
 2008                         return;
 2009                 /* is the v6 addr really valid ? */
 2010                 if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
 2011                         return;
 2012                 }
 2013         }
 2014 #endif
 2015         /* put this address on the "pending/do not use yet" list */
 2016         sctp_add_local_addr_restricted(stcb, ifa);
 2017         /*
 2018          * check address scope if address is out of scope, don't queue
 2019          * anything... note: this would leave the address on both inp and
 2020          * asoc lists
 2021          */
 2022         switch (ifa->address.sa.sa_family) {
 2023 #ifdef INET6
 2024         case AF_INET6:
 2025                 {
 2026                         struct sockaddr_in6 *sin6;
 2027 
 2028                         sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
 2029                         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 2030                                 /* we skip unspecifed addresses */
 2031                                 return;
 2032                         }
 2033                         if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 2034                                 if (stcb->asoc.local_scope == 0) {
 2035                                         return;
 2036                                 }
 2037                                 /* is it the right link local scope? */
 2038                                 if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
 2039                                         return;
 2040                                 }
 2041                         }
 2042                         if (stcb->asoc.site_scope == 0 &&
 2043                             IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
 2044                                 return;
 2045                         }
 2046                         break;
 2047                 }
 2048 #endif
 2049 #ifdef INET
 2050         case AF_INET:
 2051                 {
 2052                         struct sockaddr_in *sin;
 2053                         struct in6pcb *inp6;
 2054 
 2055                         inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 2056                         /* invalid if we are a v6 only endpoint */
 2057                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2058                             SCTP_IPV6_V6ONLY(inp6))
 2059                                 return;
 2060 
 2061                         sin = (struct sockaddr_in *)&ifa->address.sa;
 2062                         if (sin->sin_addr.s_addr == 0) {
 2063                                 /* we skip unspecifed addresses */
 2064                                 return;
 2065                         }
 2066                         if (stcb->asoc.ipv4_local_scope == 0 &&
 2067                             IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
 2068                                 return;
 2069                         }
 2070                         break;
 2071                 }
 2072 #endif
 2073         default:
 2074                 /* else, not AF_INET or AF_INET6, so skip */
 2075                 return;
 2076         }
 2077 
 2078         /* queue an asconf for this address add/delete */
 2079         if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
 2080                 /* does the peer do asconf? */
 2081                 if (stcb->asoc.peer_supports_asconf) {
 2082                         /* queue an asconf for this addr */
 2083                         status = sctp_asconf_queue_add(stcb, ifa, type);
 2084 
 2085                         /*
 2086                          * if queued ok, and in the open state, send out the
 2087                          * ASCONF.  If in the non-open state, these will be
 2088                          * sent when the state goes open.
 2089                          */
 2090                         if (status == 0 &&
 2091                             SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2092 #ifdef SCTP_TIMER_BASED_ASCONF
 2093                                 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
 2094                                     stcb, stcb->asoc.primary_destination);
 2095 #else
 2096                                 sctp_send_asconf(stcb, NULL, addr_locked);
 2097 #endif
 2098                         }
 2099                 }
 2100         }
 2101 }
 2102 
 2103 
 2104 int
 2105 sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val)
 2106 {
 2107         struct sctp_asconf_iterator *asc;
 2108         struct sctp_ifa *ifa;
 2109         struct sctp_laddr *l;
 2110         int cnt_invalid = 0;
 2111 
 2112         asc = (struct sctp_asconf_iterator *)ptr;
 2113         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
 2114                 ifa = l->ifa;
 2115                 switch (ifa->address.sa.sa_family) {
 2116 #ifdef INET6
 2117                 case AF_INET6:
 2118                         /* invalid if we're not a v6 endpoint */
 2119                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
 2120                                 cnt_invalid++;
 2121                                 if (asc->cnt == cnt_invalid)
 2122                                         return (1);
 2123                         }
 2124                         break;
 2125 #endif
 2126 #ifdef INET
 2127                 case AF_INET:
 2128                         {
 2129                                 /* invalid if we are a v6 only endpoint */
 2130                                 struct in6pcb *inp6;
 2131 
 2132                                 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 2133                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2134                                     SCTP_IPV6_V6ONLY(inp6)) {
 2135                                         cnt_invalid++;
 2136                                         if (asc->cnt == cnt_invalid)
 2137                                                 return (1);
 2138                                 }
 2139                                 break;
 2140                         }
 2141 #endif
 2142                 default:
 2143                         /* invalid address family */
 2144                         cnt_invalid++;
 2145                         if (asc->cnt == cnt_invalid)
 2146                                 return (1);
 2147                 }
 2148         }
 2149         return (0);
 2150 }
 2151 
 2152 static int
 2153 sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val)
 2154 {
 2155         struct sctp_ifa *ifa;
 2156         struct sctp_asconf_iterator *asc;
 2157         struct sctp_laddr *laddr, *nladdr, *l;
 2158 
 2159         /* Only for specific case not bound all */
 2160         asc = (struct sctp_asconf_iterator *)ptr;
 2161         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
 2162                 ifa = l->ifa;
 2163                 if (l->action == SCTP_ADD_IP_ADDRESS) {
 2164                         LIST_FOREACH(laddr, &inp->sctp_addr_list,
 2165                             sctp_nxt_addr) {
 2166                                 if (laddr->ifa == ifa) {
 2167                                         laddr->action = 0;
 2168                                         break;
 2169                                 }
 2170                         }
 2171                 } else if (l->action == SCTP_DEL_IP_ADDRESS) {
 2172                         LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
 2173                                 /* remove only after all guys are done */
 2174                                 if (laddr->ifa == ifa) {
 2175                                         sctp_del_local_addr_ep(inp, ifa);
 2176                                 }
 2177                         }
 2178                 }
 2179         }
 2180         return (0);
 2181 }
 2182 
 2183 void
 2184 sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
 2185     void *ptr, uint32_t val)
 2186 {
 2187         struct sctp_asconf_iterator *asc;
 2188         struct sctp_ifa *ifa;
 2189         struct sctp_laddr *l;
 2190         int cnt_invalid = 0;
 2191         int type, status;
 2192         int num_queued = 0;
 2193 
 2194         asc = (struct sctp_asconf_iterator *)ptr;
 2195         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
 2196                 ifa = l->ifa;
 2197                 type = l->action;
 2198 
 2199                 /* address's vrf_id must be the vrf_id of the assoc */
 2200                 if (ifa->vrf_id != stcb->asoc.vrf_id) {
 2201                         continue;
 2202                 }
 2203                 /* Same checks again for assoc */
 2204                 switch (ifa->address.sa.sa_family) {
 2205 #ifdef INET6
 2206                 case AF_INET6:
 2207                         {
 2208                                 /* invalid if we're not a v6 endpoint */
 2209                                 struct sockaddr_in6 *sin6;
 2210 
 2211                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
 2212                                         cnt_invalid++;
 2213                                         if (asc->cnt == cnt_invalid)
 2214                                                 return;
 2215                                         else
 2216                                                 continue;
 2217                                 }
 2218                                 sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
 2219                                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 2220                                         /* we skip unspecifed addresses */
 2221                                         continue;
 2222                                 }
 2223                                 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 2224                                         if (stcb->asoc.local_scope == 0) {
 2225                                                 continue;
 2226                                         }
 2227                                         /* is it the right link local scope? */
 2228                                         if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
 2229                                                 continue;
 2230                                         }
 2231                                 }
 2232                                 break;
 2233                         }
 2234 #endif
 2235 #ifdef INET
 2236                 case AF_INET:
 2237                         {
 2238                                 /* invalid if we are a v6 only endpoint */
 2239                                 struct in6pcb *inp6;
 2240                                 struct sockaddr_in *sin;
 2241 
 2242                                 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 2243                                 /* invalid if we are a v6 only endpoint */
 2244                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2245                                     SCTP_IPV6_V6ONLY(inp6))
 2246                                         continue;
 2247 
 2248                                 sin = (struct sockaddr_in *)&ifa->address.sa;
 2249                                 if (sin->sin_addr.s_addr == 0) {
 2250                                         /* we skip unspecifed addresses */
 2251                                         continue;
 2252                                 }
 2253                                 if (stcb->asoc.ipv4_local_scope == 0 &&
 2254                                     IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
 2255                                         continue;
 2256                                 }
 2257                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2258                                     SCTP_IPV6_V6ONLY(inp6)) {
 2259                                         cnt_invalid++;
 2260                                         if (asc->cnt == cnt_invalid)
 2261                                                 return;
 2262                                         else
 2263                                                 continue;
 2264                                 }
 2265                                 break;
 2266                         }
 2267 #endif
 2268                 default:
 2269                         /* invalid address family */
 2270                         cnt_invalid++;
 2271                         if (asc->cnt == cnt_invalid)
 2272                                 return;
 2273                         else
 2274                                 continue;
 2275                         break;
 2276                 }
 2277 
 2278                 if (type == SCTP_ADD_IP_ADDRESS) {
 2279                         /* prevent this address from being used as a source */
 2280                         sctp_add_local_addr_restricted(stcb, ifa);
 2281                 } else if (type == SCTP_DEL_IP_ADDRESS) {
 2282                         struct sctp_nets *net;
 2283 
 2284                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 2285                                 sctp_rtentry_t *rt;
 2286 
 2287                                 /* delete this address if cached */
 2288                                 if (net->ro._s_addr == ifa) {
 2289                                         sctp_free_ifa(net->ro._s_addr);
 2290                                         net->ro._s_addr = NULL;
 2291                                         net->src_addr_selected = 0;
 2292                                         rt = net->ro.ro_rt;
 2293                                         if (rt) {
 2294                                                 RTFREE(rt);
 2295                                                 net->ro.ro_rt = NULL;
 2296                                         }
 2297                                         /*
 2298                                          * Now we deleted our src address,
 2299                                          * should we not also now reset the
 2300                                          * cwnd/rto to start as if its a new
 2301                                          * address?
 2302                                          */
 2303                                         stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
 2304                                         net->RTO = 0;
 2305 
 2306                                 }
 2307                         }
 2308                 } else if (type == SCTP_SET_PRIM_ADDR) {
 2309                         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
 2310                                 /* must validate the ifa is in the ep */
 2311                                 if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) {
 2312                                         continue;
 2313                                 }
 2314                         } else {
 2315                                 /* Need to check scopes for this guy */
 2316                                 if (sctp_is_address_in_scope(ifa,
 2317                                     stcb->asoc.ipv4_addr_legal,
 2318                                     stcb->asoc.ipv6_addr_legal,
 2319                                     stcb->asoc.loopback_scope,
 2320                                     stcb->asoc.ipv4_local_scope,
 2321                                     stcb->asoc.local_scope,
 2322                                     stcb->asoc.site_scope, 0) == 0) {
 2323                                         continue;
 2324                                 }
 2325                         }
 2326                 }
 2327                 /* queue an asconf for this address add/delete */
 2328                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
 2329                     stcb->asoc.peer_supports_asconf) {
 2330                         /* queue an asconf for this addr */
 2331                         status = sctp_asconf_queue_add(stcb, ifa, type);
 2332                         /*
 2333                          * if queued ok, and in the open state, update the
 2334                          * count of queued params.  If in the non-open
 2335                          * state, these get sent when the assoc goes open.
 2336                          */
 2337                         if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2338                                 if (status >= 0) {
 2339                                         num_queued++;
 2340                                 }
 2341                         }
 2342                 }
 2343         }
 2344         /*
 2345          * If we have queued params in the open state, send out an ASCONF.
 2346          */
 2347         if (num_queued > 0) {
 2348                 sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
 2349         }
 2350 }
 2351 
 2352 void
 2353 sctp_asconf_iterator_end(void *ptr, uint32_t val)
 2354 {
 2355         struct sctp_asconf_iterator *asc;
 2356         struct sctp_ifa *ifa;
 2357         struct sctp_laddr *l, *nl;
 2358 
 2359         asc = (struct sctp_asconf_iterator *)ptr;
 2360         LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) {
 2361                 ifa = l->ifa;
 2362                 if (l->action == SCTP_ADD_IP_ADDRESS) {
 2363                         /* Clear the defer use flag */
 2364                         ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
 2365                 }
 2366                 sctp_free_ifa(ifa);
 2367                 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l);
 2368                 SCTP_DECR_LADDR_COUNT();
 2369         }
 2370         SCTP_FREE(asc, SCTP_M_ASC_IT);
 2371 }
 2372 
 2373 /*
 2374  * sa is the sockaddr to ask the peer to set primary to.
 2375  * returns: 0 = completed, -1 = error
 2376  */
 2377 int32_t
 2378 sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
 2379 {
 2380         uint32_t vrf_id;
 2381         struct sctp_ifa *ifa;
 2382 
 2383         /* find the ifa for the desired set primary */
 2384         vrf_id = stcb->asoc.vrf_id;
 2385         ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 2386         if (ifa == NULL) {
 2387                 /* Invalid address */
 2388                 return (-1);
 2389         }
 2390         /* queue an ASCONF:SET_PRIM_ADDR to be sent */
 2391         if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) {
 2392                 /* set primary queuing succeeded */
 2393                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 2394                     "set_primary_ip_address_sa: queued on tcb=%p, ",
 2395                     stcb);
 2396                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
 2397                 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2398 #ifdef SCTP_TIMER_BASED_ASCONF
 2399                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2400                             stcb->sctp_ep, stcb,
 2401                             stcb->asoc.primary_destination);
 2402 #else
 2403                         sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
 2404 #endif
 2405                 }
 2406         } else {
 2407                 SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ",
 2408                     stcb);
 2409                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
 2410                 return (-1);
 2411         }
 2412         return (0);
 2413 }
 2414 
 2415 void
 2416 sctp_set_primary_ip_address(struct sctp_ifa *ifa)
 2417 {
 2418         struct sctp_inpcb *inp;
 2419 
 2420         /* go through all our PCB's */
 2421         LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
 2422                 struct sctp_tcb *stcb;
 2423 
 2424                 /* process for all associations for this endpoint */
 2425                 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
 2426                         /* queue an ASCONF:SET_PRIM_ADDR to be sent */
 2427                         if (!sctp_asconf_queue_add(stcb, ifa,
 2428                             SCTP_SET_PRIM_ADDR)) {
 2429                                 /* set primary queuing succeeded */
 2430                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
 2431                                     stcb);
 2432                                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
 2433                                 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2434 #ifdef SCTP_TIMER_BASED_ASCONF
 2435                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2436                                             stcb->sctp_ep, stcb,
 2437                                             stcb->asoc.primary_destination);
 2438 #else
 2439                                         sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
 2440 #endif
 2441                                 }
 2442                         }
 2443                 }               /* for each stcb */
 2444         }                       /* for each inp */
 2445 }
 2446 
 2447 int
 2448 sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
 2449 {
 2450         struct sctp_tmit_chunk *chk, *nchk;
 2451         unsigned int offset, asconf_limit;
 2452         struct sctp_asconf_chunk *acp;
 2453         struct sctp_asconf_paramhdr *aph;
 2454         uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
 2455         struct sctp_paramhdr *ph;
 2456         int add_cnt, del_cnt;
 2457         uint16_t last_param_type;
 2458 
 2459         add_cnt = del_cnt = 0;
 2460         last_param_type = 0;
 2461         TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) {
 2462                 if (chk->data == NULL) {
 2463                         SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n");
 2464                         continue;
 2465                 }
 2466                 offset = 0;
 2467                 acp = mtod(chk->data, struct sctp_asconf_chunk *);
 2468                 offset += sizeof(struct sctp_asconf_chunk);
 2469                 asconf_limit = ntohs(acp->ch.chunk_length);
 2470                 ph = (struct sctp_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf);
 2471                 if (ph == NULL) {
 2472                         SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n");
 2473                         continue;
 2474                 }
 2475                 offset += ntohs(ph->param_length);
 2476 
 2477                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
 2478                 if (aph == NULL) {
 2479                         SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: Empty ASCONF will be sent?\n");
 2480                         continue;
 2481                 }
 2482                 while (aph != NULL) {
 2483                         unsigned int param_length, param_type;
 2484 
 2485                         param_type = ntohs(aph->ph.param_type);
 2486                         param_length = ntohs(aph->ph.param_length);
 2487                         if (offset + param_length > asconf_limit) {
 2488                                 /* parameter goes beyond end of chunk! */
 2489                                 break;
 2490                         }
 2491                         if (param_length > sizeof(aparam_buf)) {
 2492                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length (%u) larger than buffer size!\n", param_length);
 2493                                 break;
 2494                         }
 2495                         if (param_length <= sizeof(struct sctp_paramhdr)) {
 2496                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length);
 2497                                 break;
 2498                         }
 2499                         aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf);
 2500                         if (aph == NULL) {
 2501                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n");
 2502                                 break;
 2503                         }
 2504                         ph = (struct sctp_paramhdr *)(aph + 1);
 2505                         if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) {
 2506                                 switch (param_type) {
 2507                                 case SCTP_ADD_IP_ADDRESS:
 2508                                         add_cnt++;
 2509                                         break;
 2510                                 case SCTP_DEL_IP_ADDRESS:
 2511                                         del_cnt++;
 2512                                         break;
 2513                                 default:
 2514                                         break;
 2515                                 }
 2516                                 last_param_type = param_type;
 2517                         }
 2518                         offset += SCTP_SIZE32(param_length);
 2519                         if (offset >= asconf_limit) {
 2520                                 /* no more data in the mbuf chain */
 2521                                 break;
 2522                         }
 2523                         /* get pointer to next asconf param */
 2524                         aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
 2525                 }
 2526         }
 2527 
 2528         /*
 2529          * we want to find the sequences which consist of ADD -> DEL -> ADD
 2530          * or DEL -> ADD
 2531          */
 2532         if (add_cnt > del_cnt ||
 2533             (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) {
 2534                 return 1;
 2535         }
 2536         return 0;
 2537 }
 2538 
 2539 static struct sockaddr *
 2540 sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
 2541 {
 2542         struct sctp_vrf *vrf = NULL;
 2543         struct sctp_ifn *sctp_ifn;
 2544         struct sctp_ifa *sctp_ifa;
 2545 
 2546         if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2547                 SCTP_IPI_ADDR_RLOCK();
 2548         vrf = sctp_find_vrf(stcb->asoc.vrf_id);
 2549         if (vrf == NULL) {
 2550                 if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2551                         SCTP_IPI_ADDR_RUNLOCK();
 2552                 return (NULL);
 2553         }
 2554         LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
 2555                 if (stcb->asoc.loopback_scope == 0 &&
 2556                     SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
 2557                         /* Skip if loopback_scope not set */
 2558                         continue;
 2559                 }
 2560                 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
 2561                         switch (sctp_ifa->address.sa.sa_family) {
 2562 #ifdef INET
 2563                         case AF_INET:
 2564                                 if (stcb->asoc.ipv4_addr_legal) {
 2565                                         struct sockaddr_in *sin;
 2566 
 2567                                         sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
 2568                                         if (sin->sin_addr.s_addr == 0) {
 2569                                                 /* skip unspecifed addresses */
 2570                                                 continue;
 2571                                         }
 2572                                         if (stcb->asoc.ipv4_local_scope == 0 &&
 2573                                             IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
 2574                                                 continue;
 2575 
 2576                                         if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
 2577                                             (!sctp_is_addr_pending(stcb, sctp_ifa)))
 2578                                                 continue;
 2579                                         /*
 2580                                          * found a valid local v4 address to
 2581                                          * use
 2582                                          */
 2583                                         if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2584                                                 SCTP_IPI_ADDR_RUNLOCK();
 2585                                         return (&sctp_ifa->address.sa);
 2586                                 }
 2587                                 break;
 2588 #endif
 2589 #ifdef INET6
 2590                         case AF_INET6:
 2591                                 if (stcb->asoc.ipv6_addr_legal) {
 2592                                         struct sockaddr_in6 *sin6;
 2593 
 2594                                         if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
 2595                                                 continue;
 2596                                         }
 2597                                         sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
 2598                                         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 2599                                                 /*
 2600                                                  * we skip unspecifed
 2601                                                  * addresses
 2602                                                  */
 2603                                                 continue;
 2604                                         }
 2605                                         if (stcb->asoc.local_scope == 0 &&
 2606                                             IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
 2607                                                 continue;
 2608                                         if (stcb->asoc.site_scope == 0 &&
 2609                                             IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
 2610                                                 continue;
 2611 
 2612                                         if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
 2613                                             (!sctp_is_addr_pending(stcb, sctp_ifa)))
 2614                                                 continue;
 2615                                         /*
 2616                                          * found a valid local v6 address to
 2617                                          * use
 2618                                          */
 2619                                         if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2620                                                 SCTP_IPI_ADDR_RUNLOCK();
 2621                                         return (&sctp_ifa->address.sa);
 2622                                 }
 2623                                 break;
 2624 #endif
 2625                         default:
 2626                                 break;
 2627                         }
 2628                 }
 2629         }
 2630         /* no valid addresses found */
 2631         if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2632                 SCTP_IPI_ADDR_RUNLOCK();
 2633         return (NULL);
 2634 }
 2635 
 2636 static struct sockaddr *
 2637 sctp_find_valid_localaddr_ep(struct sctp_tcb *stcb)
 2638 {
 2639         struct sctp_laddr *laddr;
 2640 
 2641         LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 2642                 if (laddr->ifa == NULL) {
 2643                         continue;
 2644                 }
 2645                 /* is the address restricted ? */
 2646                 if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
 2647                     (!sctp_is_addr_pending(stcb, laddr->ifa)))
 2648                         continue;
 2649 
 2650                 /* found a valid local address to use */
 2651                 return (&laddr->ifa->address.sa);
 2652         }
 2653         /* no valid addresses found */
 2654         return (NULL);
 2655 }
 2656 
 2657 /*
 2658  * builds an ASCONF chunk from queued ASCONF params.
 2659  * returns NULL on error (no mbuf, no ASCONF params queued, etc).
 2660  */
 2661 struct mbuf *
 2662 sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
 2663 {
 2664         struct mbuf *m_asconf, *m_asconf_chk;
 2665         struct sctp_asconf_addr *aa;
 2666         struct sctp_asconf_chunk *acp;
 2667         struct sctp_asconf_paramhdr *aph;
 2668         struct sctp_asconf_addr_param *aap;
 2669         uint32_t p_length;
 2670         uint32_t correlation_id = 1;    /* 0 is reserved... */
 2671         caddr_t ptr, lookup_ptr;
 2672         uint8_t lookup_used = 0;
 2673 
 2674         /* are there any asconf params to send? */
 2675         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 2676                 if (aa->sent == 0)
 2677                         break;
 2678         }
 2679         if (aa == NULL)
 2680                 return (NULL);
 2681 
 2682         /*
 2683          * get a chunk header mbuf and a cluster for the asconf params since
 2684          * it's simpler to fill in the asconf chunk header lookup address on
 2685          * the fly
 2686          */
 2687         m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_DONTWAIT, 1, MT_DATA);
 2688         if (m_asconf_chk == NULL) {
 2689                 /* no mbuf's */
 2690                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 2691                     "compose_asconf: couldn't get chunk mbuf!\n");
 2692                 return (NULL);
 2693         }
 2694         m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
 2695         if (m_asconf == NULL) {
 2696                 /* no mbuf's */
 2697                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 2698                     "compose_asconf: couldn't get mbuf!\n");
 2699                 sctp_m_freem(m_asconf_chk);
 2700                 return (NULL);
 2701         }
 2702         SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk);
 2703         SCTP_BUF_LEN(m_asconf) = 0;
 2704         acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *);
 2705         bzero(acp, sizeof(struct sctp_asconf_chunk));
 2706         /* save pointers to lookup address and asconf params */
 2707         lookup_ptr = (caddr_t)(acp + 1);        /* after the header */
 2708         ptr = mtod(m_asconf, caddr_t);  /* beginning of cluster */
 2709 
 2710         /* fill in chunk header info */
 2711         acp->ch.chunk_type = SCTP_ASCONF;
 2712         acp->ch.chunk_flags = 0;
 2713         acp->serial_number = htonl(stcb->asoc.asconf_seq_out);
 2714         stcb->asoc.asconf_seq_out++;
 2715 
 2716         /* add parameters... up to smallest MTU allowed */
 2717         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 2718                 if (aa->sent)
 2719                         continue;
 2720                 /* get the parameter length */
 2721                 p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
 2722                 /* will it fit in current chunk? */
 2723                 if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) {
 2724                         /* won't fit, so we're done with this chunk */
 2725                         break;
 2726                 }
 2727                 /* assign (and store) a correlation id */
 2728                 aa->ap.aph.correlation_id = correlation_id++;
 2729 
 2730                 /*
 2731                  * fill in address if we're doing a delete this is a simple
 2732                  * way for us to fill in the correlation address, which
 2733                  * should only be used by the peer if we're deleting our
 2734                  * source address and adding a new address (e.g. renumbering
 2735                  * case)
 2736                  */
 2737                 if (lookup_used == 0 &&
 2738                     (aa->special_del == 0) &&
 2739                     aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
 2740                         struct sctp_ipv6addr_param *lookup;
 2741                         uint16_t p_size, addr_size;
 2742 
 2743                         lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
 2744                         lookup->ph.param_type =
 2745                             htons(aa->ap.addrp.ph.param_type);
 2746                         if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) {
 2747                                 /* copy IPv6 address */
 2748                                 p_size = sizeof(struct sctp_ipv6addr_param);
 2749                                 addr_size = sizeof(struct in6_addr);
 2750                         } else {
 2751                                 /* copy IPv4 address */
 2752                                 p_size = sizeof(struct sctp_ipv4addr_param);
 2753                                 addr_size = sizeof(struct in_addr);
 2754                         }
 2755                         lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
 2756                         memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size);
 2757                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
 2758                         lookup_used = 1;
 2759                 }
 2760                 /* copy into current space */
 2761                 memcpy(ptr, &aa->ap, p_length);
 2762 
 2763                 /* network elements and update lengths */
 2764                 aph = (struct sctp_asconf_paramhdr *)ptr;
 2765                 aap = (struct sctp_asconf_addr_param *)ptr;
 2766                 /* correlation_id is transparent to peer, no htonl needed */
 2767                 aph->ph.param_type = htons(aph->ph.param_type);
 2768                 aph->ph.param_length = htons(aph->ph.param_length);
 2769                 aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type);
 2770                 aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length);
 2771 
 2772                 SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length);
 2773                 ptr += SCTP_SIZE32(p_length);
 2774 
 2775                 /*
 2776                  * these params are removed off the pending list upon
 2777                  * getting an ASCONF-ACK back from the peer, just set flag
 2778                  */
 2779                 aa->sent = 1;
 2780         }
 2781         /* check to see if the lookup addr has been populated yet */
 2782         if (lookup_used == 0) {
 2783                 /* NOTE: if the address param is optional, can skip this... */
 2784                 /* add any valid (existing) address... */
 2785                 struct sctp_ipv6addr_param *lookup;
 2786                 uint16_t p_size, addr_size;
 2787                 struct sockaddr *found_addr;
 2788                 caddr_t addr_ptr;
 2789 
 2790                 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)
 2791                         found_addr = sctp_find_valid_localaddr(stcb,
 2792                             addr_locked);
 2793                 else
 2794                         found_addr = sctp_find_valid_localaddr_ep(stcb);
 2795 
 2796                 lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
 2797                 if (found_addr != NULL) {
 2798                         switch (found_addr->sa_family) {
 2799 #ifdef INET6
 2800                         case AF_INET6:
 2801                                 /* copy IPv6 address */
 2802                                 lookup->ph.param_type =
 2803                                     htons(SCTP_IPV6_ADDRESS);
 2804                                 p_size = sizeof(struct sctp_ipv6addr_param);
 2805                                 addr_size = sizeof(struct in6_addr);
 2806                                 addr_ptr = (caddr_t)&((struct sockaddr_in6 *)
 2807                                     found_addr)->sin6_addr;
 2808                                 break;
 2809 #endif
 2810 #ifdef INET
 2811                         case AF_INET:
 2812                                 /* copy IPv4 address */
 2813                                 lookup->ph.param_type =
 2814                                     htons(SCTP_IPV4_ADDRESS);
 2815                                 p_size = sizeof(struct sctp_ipv4addr_param);
 2816                                 addr_size = sizeof(struct in_addr);
 2817                                 addr_ptr = (caddr_t)&((struct sockaddr_in *)
 2818                                     found_addr)->sin_addr;
 2819                                 break;
 2820 #endif
 2821                         default:
 2822                                 p_size = 0;
 2823                                 addr_size = 0;
 2824                                 addr_ptr = NULL;
 2825                                 break;
 2826                         }
 2827                         lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
 2828                         memcpy(lookup->addr, addr_ptr, addr_size);
 2829                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
 2830                 } else {
 2831                         /* uh oh... don't have any address?? */
 2832                         SCTPDBG(SCTP_DEBUG_ASCONF1,
 2833                             "compose_asconf: no lookup addr!\n");
 2834                         /* XXX for now, we send a IPv4 address of 0.0.0.0 */
 2835                         lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
 2836                         lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
 2837                         bzero(lookup->addr, sizeof(struct in_addr));
 2838                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
 2839                 }
 2840         }
 2841         /* chain it all together */
 2842         SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
 2843         *retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf);
 2844         acp->ch.chunk_length = ntohs(*retlen);
 2845 
 2846         return (m_asconf_chk);
 2847 }
 2848 
 2849 /*
 2850  * section to handle address changes before an association is up eg. changes
 2851  * during INIT/INIT-ACK/COOKIE-ECHO handshake
 2852  */
 2853 
 2854 /*
 2855  * processes the (local) addresses in the INIT-ACK chunk
 2856  */
 2857 static void
 2858 sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
 2859     unsigned int offset, unsigned int length)
 2860 {
 2861         struct sctp_paramhdr tmp_param, *ph;
 2862         uint16_t plen, ptype;
 2863         struct sctp_ifa *sctp_ifa;
 2864         struct sctp_ipv6addr_param addr_store;
 2865 
 2866 #ifdef INET6
 2867         struct sockaddr_in6 sin6;
 2868 
 2869 #endif
 2870 #ifdef INET
 2871         struct sockaddr_in sin;
 2872 
 2873 #endif
 2874         struct sockaddr *sa;
 2875         uint32_t vrf_id;
 2876 
 2877         SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n");
 2878         if (stcb == NULL)       /* Un-needed check for SA */
 2879                 return;
 2880 
 2881         /* convert to upper bound */
 2882         length += offset;
 2883 
 2884         if ((offset + sizeof(struct sctp_paramhdr)) > length) {
 2885                 return;
 2886         }
 2887         /* init the addresses */
 2888 #ifdef INET6
 2889         bzero(&sin6, sizeof(sin6));
 2890         sin6.sin6_family = AF_INET6;
 2891         sin6.sin6_len = sizeof(sin6);
 2892         sin6.sin6_port = stcb->rport;
 2893 #endif
 2894 
 2895 #ifdef INET
 2896         bzero(&sin, sizeof(sin));
 2897         sin.sin_family = AF_INET;
 2898         sin.sin_len = sizeof(sin);
 2899         sin.sin_port = stcb->rport;
 2900 #endif
 2901 
 2902         /* go through the addresses in the init-ack */
 2903         ph = (struct sctp_paramhdr *)
 2904             sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
 2905             (uint8_t *) & tmp_param);
 2906         while (ph != NULL) {
 2907                 ptype = ntohs(ph->param_type);
 2908                 plen = ntohs(ph->param_length);
 2909                 switch (ptype) {
 2910 #ifdef INET6
 2911                 case SCTP_IPV6_ADDRESS:
 2912                         {
 2913                                 struct sctp_ipv6addr_param *a6p;
 2914 
 2915                                 /* get the entire IPv6 address param */
 2916                                 a6p = (struct sctp_ipv6addr_param *)
 2917                                     sctp_m_getptr(m, offset,
 2918                                     sizeof(struct sctp_ipv6addr_param),
 2919                                     (uint8_t *) & addr_store);
 2920                                 if (plen != sizeof(struct sctp_ipv6addr_param) ||
 2921                                     a6p == NULL) {
 2922                                         return;
 2923                                 }
 2924                                 memcpy(&sin6.sin6_addr, a6p->addr,
 2925                                     sizeof(struct in6_addr));
 2926                                 sa = (struct sockaddr *)&sin6;
 2927                                 break;
 2928                         }
 2929 #endif
 2930 #ifdef INET
 2931                 case SCTP_IPV4_ADDRESS:
 2932                         {
 2933                                 struct sctp_ipv4addr_param *a4p;
 2934 
 2935                                 /* get the entire IPv4 address param */
 2936                                 a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
 2937                                     sizeof(struct sctp_ipv4addr_param),
 2938                                     (uint8_t *) & addr_store);
 2939                                 if (plen != sizeof(struct sctp_ipv4addr_param) ||
 2940                                     a4p == NULL) {
 2941                                         return;
 2942                                 }
 2943                                 sin.sin_addr.s_addr = a4p->addr;
 2944                                 sa = (struct sockaddr *)&sin;
 2945                                 break;
 2946                         }
 2947 #endif
 2948                 default:
 2949                         goto next_addr;
 2950                 }
 2951 
 2952                 /* see if this address really (still) exists */
 2953                 if (stcb) {
 2954                         vrf_id = stcb->asoc.vrf_id;
 2955                 } else {
 2956                         vrf_id = SCTP_DEFAULT_VRFID;
 2957                 }
 2958                 sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id,
 2959                     SCTP_ADDR_NOT_LOCKED);
 2960                 if (sctp_ifa == NULL) {
 2961                         /* address doesn't exist anymore */
 2962                         int status;
 2963 
 2964                         /* are ASCONFs allowed ? */
 2965                         if ((sctp_is_feature_on(stcb->sctp_ep,
 2966                             SCTP_PCB_FLAGS_DO_ASCONF)) &&
 2967                             stcb->asoc.peer_supports_asconf) {
 2968                                 /* queue an ASCONF DEL_IP_ADDRESS */
 2969                                 status = sctp_asconf_queue_sa_delete(stcb, sa);
 2970                                 /*
 2971                                  * if queued ok, and in correct state, send
 2972                                  * out the ASCONF.
 2973                                  */
 2974                                 if (status == 0 &&
 2975                                     SCTP_GET_STATE(&stcb->asoc) ==
 2976                                     SCTP_STATE_OPEN) {
 2977 #ifdef SCTP_TIMER_BASED_ASCONF
 2978                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2979                                             stcb->sctp_ep, stcb,
 2980                                             stcb->asoc.primary_destination);
 2981 #else
 2982                                         sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
 2983 #endif
 2984                                 }
 2985                         }
 2986                 }
 2987 next_addr:
 2988                 /*
 2989                  * Sanity check:  Make sure the length isn't 0, otherwise
 2990                  * we'll be stuck in this loop for a long time...
 2991                  */
 2992                 if (SCTP_SIZE32(plen) == 0) {
 2993                         SCTP_PRINTF("process_initack_addrs: bad len (%d) type=%xh\n",
 2994                             plen, ptype);
 2995                         return;
 2996                 }
 2997                 /* get next parameter */
 2998                 offset += SCTP_SIZE32(plen);
 2999                 if ((offset + sizeof(struct sctp_paramhdr)) > length)
 3000                         return;
 3001                 ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
 3002                     sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
 3003         }                       /* while */
 3004 }
 3005 
 3006 /* FIX ME: need to verify return result for v6 address type if v6 disabled */
 3007 /*
 3008  * checks to see if a specific address is in the initack address list returns
 3009  * 1 if found, 0 if not
 3010  */
 3011 static uint32_t
 3012 sctp_addr_in_initack(struct sctp_tcb *stcb, struct mbuf *m, uint32_t offset,
 3013     uint32_t length, struct sockaddr *sa)
 3014 {
 3015         struct sctp_paramhdr tmp_param, *ph;
 3016         uint16_t plen, ptype;
 3017         struct sctp_ipv6addr_param addr_store;
 3018 
 3019 #ifdef INET
 3020         struct sockaddr_in *sin;
 3021         struct sctp_ipv4addr_param *a4p;
 3022 
 3023 #endif
 3024 #ifdef INET6
 3025         struct sockaddr_in6 *sin6;
 3026         struct sctp_ipv6addr_param *a6p;
 3027         struct sockaddr_in6 sin6_tmp;
 3028 
 3029 #endif
 3030 
 3031         switch (sa->sa_family) {
 3032 #ifdef INET
 3033         case AF_INET:
 3034                 break;
 3035 #endif
 3036 #ifdef INET6
 3037         case AF_INET6:
 3038                 break;
 3039 #endif
 3040         default:
 3041                 return (0);
 3042         }
 3043 
 3044         SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for ");
 3045         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 3046         /* convert to upper bound */
 3047         length += offset;
 3048 
 3049         if ((offset + sizeof(struct sctp_paramhdr)) > length) {
 3050                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3051                     "find_initack_addr: invalid offset?\n");
 3052                 return (0);
 3053         }
 3054         /* go through the addresses in the init-ack */
 3055         ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
 3056             sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
 3057         while (ph != NULL) {
 3058                 ptype = ntohs(ph->param_type);
 3059                 plen = ntohs(ph->param_length);
 3060                 switch (ptype) {
 3061 #ifdef INET6
 3062                 case SCTP_IPV6_ADDRESS:
 3063                         if (sa->sa_family == AF_INET6) {
 3064                                 /* get the entire IPv6 address param */
 3065                                 if (plen != sizeof(struct sctp_ipv6addr_param)) {
 3066                                         break;
 3067                                 }
 3068                                 /* get the entire IPv6 address param */
 3069                                 a6p = (struct sctp_ipv6addr_param *)
 3070                                     sctp_m_getptr(m, offset,
 3071                                     sizeof(struct sctp_ipv6addr_param),
 3072                                     (uint8_t *) & addr_store);
 3073                                 if (a6p == NULL) {
 3074                                         return (0);
 3075                                 }
 3076                                 sin6 = (struct sockaddr_in6 *)sa;
 3077                                 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
 3078                                         /* create a copy and clear scope */
 3079                                         memcpy(&sin6_tmp, sin6,
 3080                                             sizeof(struct sockaddr_in6));
 3081                                         sin6 = &sin6_tmp;
 3082                                         in6_clearscope(&sin6->sin6_addr);
 3083                                 }
 3084                                 if (memcmp(&sin6->sin6_addr, a6p->addr,
 3085                                     sizeof(struct in6_addr)) == 0) {
 3086                                         /* found it */
 3087                                         return (1);
 3088                                 }
 3089                         }
 3090                         break;
 3091 #endif                          /* INET6 */
 3092 #ifdef INET
 3093                 case SCTP_IPV4_ADDRESS:
 3094                         if (sa->sa_family == AF_INET) {
 3095                                 if (plen != sizeof(struct sctp_ipv4addr_param)) {
 3096                                         break;
 3097                                 }
 3098                                 /* get the entire IPv4 address param */
 3099                                 a4p = (struct sctp_ipv4addr_param *)
 3100                                     sctp_m_getptr(m, offset,
 3101                                     sizeof(struct sctp_ipv4addr_param),
 3102                                     (uint8_t *) & addr_store);
 3103                                 if (a4p == NULL) {
 3104                                         return (0);
 3105                                 }
 3106                                 sin = (struct sockaddr_in *)sa;
 3107                                 if (sin->sin_addr.s_addr == a4p->addr) {
 3108                                         /* found it */
 3109                                         return (1);
 3110                                 }
 3111                         }
 3112                         break;
 3113 #endif
 3114                 default:
 3115                         break;
 3116                 }
 3117                 /* get next parameter */
 3118                 offset += SCTP_SIZE32(plen);
 3119                 if (offset + sizeof(struct sctp_paramhdr) > length) {
 3120                         return (0);
 3121                 }
 3122                 ph = (struct sctp_paramhdr *)
 3123                     sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
 3124                     (uint8_t *) & tmp_param);
 3125         }                       /* while */
 3126         /* not found! */
 3127         return (0);
 3128 }
 3129 
 3130 /*
 3131  * makes sure that the current endpoint local addr list is consistent with
 3132  * the new association (eg. subset bound, asconf allowed) adds addresses as
 3133  * necessary
 3134  */
 3135 static void
 3136 sctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 3137     int length, struct sockaddr *init_addr)
 3138 {
 3139         struct sctp_laddr *laddr;
 3140 
 3141         /* go through the endpoint list */
 3142         LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 3143                 /* be paranoid and validate the laddr */
 3144                 if (laddr->ifa == NULL) {
 3145                         SCTPDBG(SCTP_DEBUG_ASCONF1,
 3146                             "check_addr_list_ep: laddr->ifa is NULL");
 3147                         continue;
 3148                 }
 3149                 if (laddr->ifa == NULL) {
 3150                         SCTPDBG(SCTP_DEBUG_ASCONF1, "check_addr_list_ep: laddr->ifa->ifa_addr is NULL");
 3151                         continue;
 3152                 }
 3153                 /* do i have it implicitly? */
 3154                 if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) {
 3155                         continue;
 3156                 }
 3157                 /* check to see if in the init-ack */
 3158                 if (!sctp_addr_in_initack(stcb, m, offset, length,
 3159                     &laddr->ifa->address.sa)) {
 3160                         /* try to add it */
 3161                         sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa,
 3162                             SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED);
 3163                 }
 3164         }
 3165 }
 3166 
 3167 /*
 3168  * makes sure that the current kernel address list is consistent with the new
 3169  * association (with all addrs bound) adds addresses as necessary
 3170  */
 3171 static void
 3172 sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 3173     int length, struct sockaddr *init_addr,
 3174     uint16_t local_scope, uint16_t site_scope,
 3175     uint16_t ipv4_scope, uint16_t loopback_scope)
 3176 {
 3177         struct sctp_vrf *vrf = NULL;
 3178         struct sctp_ifn *sctp_ifn;
 3179         struct sctp_ifa *sctp_ifa;
 3180         uint32_t vrf_id;
 3181 
 3182         if (stcb) {
 3183                 vrf_id = stcb->asoc.vrf_id;
 3184         } else {
 3185                 return;
 3186         }
 3187         SCTP_IPI_ADDR_RLOCK();
 3188         vrf = sctp_find_vrf(vrf_id);
 3189         if (vrf == NULL) {
 3190                 SCTP_IPI_ADDR_RUNLOCK();
 3191                 return;
 3192         }
 3193         /* go through all our known interfaces */
 3194         LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
 3195                 if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
 3196                         /* skip loopback interface */
 3197                         continue;
 3198                 }
 3199                 /* go through each interface address */
 3200                 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
 3201                         /* do i have it implicitly? */
 3202                         if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
 3203                                 continue;
 3204                         }
 3205                         /* check to see if in the init-ack */
 3206                         if (!sctp_addr_in_initack(stcb, m, offset, length,
 3207                             &sctp_ifa->address.sa)) {
 3208                                 /* try to add it */
 3209                                 sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
 3210                                     sctp_ifa, SCTP_ADD_IP_ADDRESS,
 3211                                     SCTP_ADDR_LOCKED);
 3212                         }
 3213                 }               /* end foreach ifa */
 3214         }                       /* end foreach ifn */
 3215         SCTP_IPI_ADDR_RUNLOCK();
 3216 }
 3217 
 3218 /*
 3219  * validates an init-ack chunk (from a cookie-echo) with current addresses
 3220  * adds addresses from the init-ack into our local address list, if needed
 3221  * queues asconf adds/deletes addresses as needed and makes appropriate list
 3222  * changes for source address selection m, offset: points to the start of the
 3223  * address list in an init-ack chunk length: total length of the address
 3224  * params only init_addr: address where my INIT-ACK was sent from
 3225  */
 3226 void
 3227 sctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 3228     int length, struct sockaddr *init_addr,
 3229     uint16_t local_scope, uint16_t site_scope,
 3230     uint16_t ipv4_scope, uint16_t loopback_scope)
 3231 {
 3232         /* process the local addresses in the initack */
 3233         sctp_process_initack_addresses(stcb, m, offset, length);
 3234 
 3235         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
 3236                 /* bound all case */
 3237                 sctp_check_address_list_all(stcb, m, offset, length, init_addr,
 3238                     local_scope, site_scope, ipv4_scope, loopback_scope);
 3239         } else {
 3240                 /* subset bound case */
 3241                 if (sctp_is_feature_on(stcb->sctp_ep,
 3242                     SCTP_PCB_FLAGS_DO_ASCONF)) {
 3243                         /* asconf's allowed */
 3244                         sctp_check_address_list_ep(stcb, m, offset, length,
 3245                             init_addr);
 3246                 }
 3247                 /* else, no asconfs allowed, so what we sent is what we get */
 3248         }
 3249 }
 3250 
 3251 /*
 3252  * sctp_bindx() support
 3253  */
 3254 uint32_t
 3255 sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
 3256     uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap)
 3257 {
 3258         struct sctp_ifa *ifa;
 3259         struct sctp_laddr *laddr, *nladdr;
 3260 
 3261         if (sa->sa_len == 0) {
 3262                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
 3263                 return (EINVAL);
 3264         }
 3265         if (sctp_ifap) {
 3266                 ifa = sctp_ifap;
 3267         } else if (type == SCTP_ADD_IP_ADDRESS) {
 3268                 /* For an add the address MUST be on the system */
 3269                 ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 3270         } else if (type == SCTP_DEL_IP_ADDRESS) {
 3271                 /* For a delete we need to find it in the inp */
 3272                 ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED);
 3273         } else {
 3274                 ifa = NULL;
 3275         }
 3276         if (ifa != NULL) {
 3277                 if (type == SCTP_ADD_IP_ADDRESS) {
 3278                         sctp_add_local_addr_ep(inp, ifa, type);
 3279                 } else if (type == SCTP_DEL_IP_ADDRESS) {
 3280                         if (inp->laddr_count < 2) {
 3281                                 /* can't delete the last local address */
 3282                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
 3283                                 return (EINVAL);
 3284                         }
 3285                         LIST_FOREACH(laddr, &inp->sctp_addr_list,
 3286                             sctp_nxt_addr) {
 3287                                 if (ifa == laddr->ifa) {
 3288                                         /* Mark in the delete */
 3289                                         laddr->action = type;
 3290                                 }
 3291                         }
 3292                 }
 3293                 if (LIST_EMPTY(&inp->sctp_asoc_list)) {
 3294                         /*
 3295                          * There is no need to start the iterator if the inp
 3296                          * has no associations.
 3297                          */
 3298                         if (type == SCTP_DEL_IP_ADDRESS) {
 3299                                 LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
 3300                                         if (laddr->ifa == ifa) {
 3301                                                 sctp_del_local_addr_ep(inp, ifa);
 3302                                         }
 3303                                 }
 3304                         }
 3305                 } else {
 3306                         struct sctp_asconf_iterator *asc;
 3307                         struct sctp_laddr *wi;
 3308 
 3309                         SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
 3310                             sizeof(struct sctp_asconf_iterator),
 3311                             SCTP_M_ASC_IT);
 3312                         if (asc == NULL) {
 3313                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
 3314                                 return (ENOMEM);
 3315                         }
 3316                         wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr);
 3317                         if (wi == NULL) {
 3318                                 SCTP_FREE(asc, SCTP_M_ASC_IT);
 3319                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
 3320                                 return (ENOMEM);
 3321                         }
 3322                         LIST_INIT(&asc->list_of_work);
 3323                         asc->cnt = 1;
 3324                         SCTP_INCR_LADDR_COUNT();
 3325                         wi->ifa = ifa;
 3326                         wi->action = type;
 3327                         atomic_add_int(&ifa->refcount, 1);
 3328                         LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
 3329                         (void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
 3330                             sctp_asconf_iterator_stcb,
 3331                             sctp_asconf_iterator_ep_end,
 3332                             SCTP_PCB_ANY_FLAGS,
 3333                             SCTP_PCB_ANY_FEATURES,
 3334                             SCTP_ASOC_ANY_STATE,
 3335                             (void *)asc, 0,
 3336                             sctp_asconf_iterator_end, inp, 0);
 3337                 }
 3338                 return (0);
 3339         } else {
 3340                 /* invalid address! */
 3341                 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL);
 3342                 return (EADDRNOTAVAIL);
 3343         }
 3344 }
 3345 
 3346 void
 3347 sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
 3348     struct sctp_nets *net)
 3349 {
 3350         struct sctp_asconf_addr *aa;
 3351         struct sctp_ifa *sctp_ifap;
 3352         struct sctp_asconf_tag_param *vtag;
 3353 
 3354 #ifdef INET
 3355         struct sockaddr_in *to;
 3356 
 3357 #endif
 3358 #ifdef INET6
 3359         struct sockaddr_in6 *to6;
 3360 
 3361 #endif
 3362         if (net == NULL) {
 3363                 SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n");
 3364                 return;
 3365         }
 3366         if (stcb == NULL) {
 3367                 SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n");
 3368                 return;
 3369         }
 3370         /*
 3371          * Need to have in the asconf: - vtagparam(my_vtag/peer_vtag) -
 3372          * add(0.0.0.0) - del(0.0.0.0) - Any global addresses add(addr)
 3373          */
 3374         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 3375             SCTP_M_ASC_ADDR);
 3376         if (aa == NULL) {
 3377                 /* didn't get memory */
 3378                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3379                     "sctp_asconf_send_nat_state_update: failed to get memory!\n");
 3380                 return;
 3381         }
 3382         aa->special_del = 0;
 3383         /* fill in asconf address parameter fields */
 3384         /* top level elements are "networked" during send */
 3385         aa->ifa = NULL;
 3386         aa->sent = 0;           /* clear sent flag */
 3387         vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph;
 3388         vtag->aph.ph.param_type = SCTP_NAT_VTAGS;
 3389         vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param);
 3390         vtag->local_vtag = htonl(stcb->asoc.my_vtag);
 3391         vtag->remote_vtag = htonl(stcb->asoc.peer_vtag);
 3392         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3393 
 3394         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 3395             SCTP_M_ASC_ADDR);
 3396         if (aa == NULL) {
 3397                 /* didn't get memory */
 3398                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3399                     "sctp_asconf_send_nat_state_update: failed to get memory!\n");
 3400                 return;
 3401         }
 3402         memset(aa, 0, sizeof(struct sctp_asconf_addr));
 3403         /* fill in asconf address parameter fields */
 3404         /* ADD(0.0.0.0) */
 3405         switch (net->ro._l_addr.sa.sa_family) {
 3406 #ifdef INET
 3407         case AF_INET:
 3408                 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
 3409                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
 3410                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 3411                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param);
 3412                 /* No need to add an address, we are using 0.0.0.0 */
 3413                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3414                 break;
 3415 #endif
 3416 #ifdef INET6
 3417         case AF_INET6:
 3418                 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
 3419                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
 3420                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 3421                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param);
 3422                 /* No need to add an address, we are using 0.0.0.0 */
 3423                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3424                 break;
 3425 #endif
 3426         }
 3427         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 3428             SCTP_M_ASC_ADDR);
 3429         if (aa == NULL) {
 3430                 /* didn't get memory */
 3431                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3432                     "sctp_asconf_send_nat_state_update: failed to get memory!\n");
 3433                 return;
 3434         }
 3435         memset(aa, 0, sizeof(struct sctp_asconf_addr));
 3436         /* fill in asconf address parameter fields */
 3437         /* ADD(0.0.0.0) */
 3438         switch (net->ro._l_addr.sa.sa_family) {
 3439 #ifdef INET
 3440         case AF_INET:
 3441                 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
 3442                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
 3443                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 3444                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param);
 3445                 /* No need to add an address, we are using 0.0.0.0 */
 3446                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3447                 break;
 3448 #endif
 3449 #ifdef INET6
 3450         case AF_INET6:
 3451                 aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
 3452                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
 3453                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 3454                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param);
 3455                 /* No need to add an address, we are using 0.0.0.0 */
 3456                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3457                 break;
 3458 #endif
 3459         }
 3460         /* Now we must hunt the addresses and add all global addresses */
 3461         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
 3462                 struct sctp_vrf *vrf = NULL;
 3463                 struct sctp_ifn *sctp_ifnp;
 3464                 uint32_t vrf_id;
 3465 
 3466                 vrf_id = stcb->sctp_ep->def_vrf_id;
 3467                 vrf = sctp_find_vrf(vrf_id);
 3468                 if (vrf == NULL) {
 3469                         goto skip_rest;
 3470                 }
 3471                 SCTP_IPI_ADDR_RLOCK();
 3472                 LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
 3473                         LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
 3474                                 switch (sctp_ifap->address.sa.sa_family) {
 3475 #ifdef INET
 3476                                 case AF_INET:
 3477                                         to = &sctp_ifap->address.sin;
 3478                                         if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
 3479                                                 continue;
 3480                                         }
 3481                                         if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
 3482                                                 continue;
 3483                                         }
 3484                                         break;
 3485 #endif
 3486 #ifdef INET6
 3487                                 case AF_INET6:
 3488                                         to6 = &sctp_ifap->address.sin6;
 3489                                         if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
 3490                                                 continue;
 3491                                         }
 3492                                         if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
 3493                                                 continue;
 3494                                         }
 3495                                         break;
 3496 #endif
 3497                                 default:
 3498                                         continue;
 3499                                 }
 3500                                 sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
 3501                         }
 3502                 }
 3503                 SCTP_IPI_ADDR_RUNLOCK();
 3504         } else {
 3505                 struct sctp_laddr *laddr;
 3506 
 3507                 LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 3508                         if (laddr->ifa == NULL) {
 3509                                 continue;
 3510                         }
 3511                         if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED)
 3512                                 /*
 3513                                  * Address being deleted by the system, dont
 3514                                  * list.
 3515                                  */
 3516                                 continue;
 3517                         if (laddr->action == SCTP_DEL_IP_ADDRESS) {
 3518                                 /*
 3519                                  * Address being deleted on this ep don't
 3520                                  * list.
 3521                                  */
 3522                                 continue;
 3523                         }
 3524                         sctp_ifap = laddr->ifa;
 3525                         switch (sctp_ifap->address.sa.sa_family) {
 3526 #ifdef INET
 3527                         case AF_INET:
 3528                                 to = &sctp_ifap->address.sin;
 3529                                 if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
 3530                                         continue;
 3531                                 }
 3532                                 if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
 3533                                         continue;
 3534                                 }
 3535                                 break;
 3536 #endif
 3537 #ifdef INET6
 3538                         case AF_INET6:
 3539                                 to6 = &sctp_ifap->address.sin6;
 3540                                 if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
 3541                                         continue;
 3542                                 }
 3543                                 if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
 3544                                         continue;
 3545                                 }
 3546                                 break;
 3547 #endif
 3548                         default:
 3549                                 continue;
 3550                         }
 3551                         sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
 3552                 }
 3553         }
 3554 skip_rest:
 3555         /* Now we must send the asconf into the queue */
 3556         sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
 3557 }

Cache object: c7127f0237b34183878ab8fbd858b9a5


[ 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.