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/8.3/sys/netinet/sctp_asconf.c 231492 2012-02-11 00:57:08Z 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, uint32_t flag)
 1265 {
 1266         /*
 1267          * do the necessary asoc list work- if we get a failure indication,
 1268          * leave the address on the assoc's restricted list.  If we get a
 1269          * success indication, remove the address from the restricted list.
 1270          */
 1271         /*
 1272          * Note: this will only occur for ADD_IP_ADDRESS, since
 1273          * DEL_IP_ADDRESS is never actually added to the list...
 1274          */
 1275         if (flag) {
 1276                 /* success case, so remove from the restricted list */
 1277                 sctp_del_local_addr_restricted(stcb, addr);
 1278 
 1279                 if (sctp_is_mobility_feature_on(stcb->sctp_ep,
 1280                     SCTP_MOBILITY_BASE) ||
 1281                     sctp_is_mobility_feature_on(stcb->sctp_ep,
 1282                     SCTP_MOBILITY_FASTHANDOFF)) {
 1283                         sctp_path_check_and_react(stcb, addr);
 1284                         return;
 1285                 }
 1286                 /* clear any cached/topologically incorrect source addresses */
 1287                 sctp_asconf_nets_cleanup(stcb, addr->ifn_p);
 1288         }
 1289         /* else, leave it on the list */
 1290 }
 1291 
 1292 /*
 1293  * add an asconf add/delete/set primary IP address parameter to the queue.
 1294  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
 1295  * returns 0 if queued, -1 if not queued/removed.
 1296  * NOTE: if adding, but a delete for the same address is already scheduled
 1297  * (and not yet sent out), simply remove it from queue.  Same for deleting
 1298  * an address already scheduled for add.  If a duplicate operation is found,
 1299  * ignore the new one.
 1300  */
 1301 static int
 1302 sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
 1303     uint16_t type)
 1304 {
 1305         struct sctp_asconf_addr *aa, *aa_next;
 1306         struct sockaddr *sa;
 1307 
 1308         /* make sure the request isn't already in the queue */
 1309         TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
 1310                 /* address match? */
 1311                 if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0)
 1312                         continue;
 1313                 /*
 1314                  * is the request already in queue but not sent? pass the
 1315                  * request already sent in order to resolve the following
 1316                  * case: 1. arrival of ADD, then sent 2. arrival of DEL. we
 1317                  * can't remove the ADD request already sent 3. arrival of
 1318                  * ADD
 1319                  */
 1320                 if (aa->ap.aph.ph.param_type == type && aa->sent == 0) {
 1321                         return (-1);
 1322                 }
 1323                 /* is the negative request already in queue, and not sent */
 1324                 if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) &&
 1325                     (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) {
 1326                         /* add requested, delete already queued */
 1327                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1328                         /* remove the ifa from the restricted list */
 1329                         sctp_del_local_addr_restricted(stcb, ifa);
 1330                         /* free the asconf param */
 1331                         SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1332                         SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n");
 1333                         return (-1);
 1334                 }
 1335                 if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) &&
 1336                     (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) {
 1337                         /* delete requested, add already queued */
 1338                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1339                         /* remove the aa->ifa from the restricted list */
 1340                         sctp_del_local_addr_restricted(stcb, aa->ifa);
 1341                         /* free the asconf param */
 1342                         SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1343                         SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n");
 1344                         return (-1);
 1345                 }
 1346         }                       /* for each aa */
 1347 
 1348         /* adding new request to the queue */
 1349         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 1350             SCTP_M_ASC_ADDR);
 1351         if (aa == NULL) {
 1352                 /* didn't get memory */
 1353                 SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n");
 1354                 return (-1);
 1355         }
 1356         aa->special_del = 0;
 1357         /* fill in asconf address parameter fields */
 1358         /* top level elements are "networked" during send */
 1359         aa->ap.aph.ph.param_type = type;
 1360         aa->ifa = ifa;
 1361         atomic_add_int(&ifa->refcount, 1);
 1362         /* correlation_id filled in during send routine later... */
 1363         switch (ifa->address.sa.sa_family) {
 1364 #ifdef INET6
 1365         case AF_INET6:
 1366                 {
 1367                         struct sockaddr_in6 *sin6;
 1368 
 1369                         sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
 1370                         sa = (struct sockaddr *)sin6;
 1371                         aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 1372                         aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
 1373                         aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
 1374                             sizeof(struct sctp_ipv6addr_param);
 1375                         memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
 1376                             sizeof(struct in6_addr));
 1377                         break;
 1378                 }
 1379 #endif
 1380 #ifdef INET
 1381         case AF_INET:
 1382                 {
 1383                         struct sockaddr_in *sin;
 1384 
 1385                         sin = (struct sockaddr_in *)&ifa->address.sa;
 1386                         sa = (struct sockaddr *)sin;
 1387                         aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 1388                         aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
 1389                         aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
 1390                             sizeof(struct sctp_ipv4addr_param);
 1391                         memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
 1392                             sizeof(struct in_addr));
 1393                         break;
 1394                 }
 1395 #endif
 1396         default:
 1397                 /* invalid family! */
 1398                 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1399                 sctp_free_ifa(ifa);
 1400                 return (-1);
 1401         }
 1402         aa->sent = 0;           /* clear sent flag */
 1403 
 1404         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 1405 #ifdef SCTP_DEBUG
 1406         if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) {
 1407                 if (type == SCTP_ADD_IP_ADDRESS) {
 1408                         SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: ");
 1409                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 1410                 } else if (type == SCTP_DEL_IP_ADDRESS) {
 1411                         SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: ");
 1412                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 1413                 } else {
 1414                         SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: ");
 1415                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 1416                 }
 1417         }
 1418 #endif
 1419 
 1420         return (0);
 1421 }
 1422 
 1423 
 1424 /*
 1425  * add an asconf operation for the given ifa and type.
 1426  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
 1427  * returns 0 if completed, -1 if not completed, 1 if immediate send is
 1428  * advisable.
 1429  */
 1430 static int
 1431 sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
 1432     uint16_t type)
 1433 {
 1434         uint32_t status;
 1435         int pending_delete_queued = 0;
 1436 
 1437         /* see if peer supports ASCONF */
 1438         if (stcb->asoc.peer_supports_asconf == 0) {
 1439                 return (-1);
 1440         }
 1441         /*
 1442          * if this is deleting the last address from the assoc, mark it as
 1443          * pending.
 1444          */
 1445         if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending &&
 1446             (sctp_local_addr_count(stcb) < 2)) {
 1447                 /* set the pending delete info only */
 1448                 stcb->asoc.asconf_del_pending = 1;
 1449                 stcb->asoc.asconf_addr_del_pending = ifa;
 1450                 atomic_add_int(&ifa->refcount, 1);
 1451                 SCTPDBG(SCTP_DEBUG_ASCONF2,
 1452                     "asconf_queue_add: mark delete last address pending\n");
 1453                 return (-1);
 1454         }
 1455         /* queue an asconf parameter */
 1456         status = sctp_asconf_queue_mgmt(stcb, ifa, type);
 1457 
 1458         /*
 1459          * if this is an add, and there is a delete also pending (i.e. the
 1460          * last local address is being changed), queue the pending delete
 1461          * too.
 1462          */
 1463         if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) {
 1464                 /* queue in the pending delete */
 1465                 if (sctp_asconf_queue_mgmt(stcb,
 1466                     stcb->asoc.asconf_addr_del_pending,
 1467                     SCTP_DEL_IP_ADDRESS) == 0) {
 1468                         SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n");
 1469                         pending_delete_queued = 1;
 1470                         /* clear out the pending delete info */
 1471                         stcb->asoc.asconf_del_pending = 0;
 1472                         sctp_free_ifa(stcb->asoc.asconf_addr_del_pending);
 1473                         stcb->asoc.asconf_addr_del_pending = NULL;
 1474                 }
 1475         }
 1476         if (pending_delete_queued) {
 1477                 struct sctp_nets *net;
 1478 
 1479                 /*
 1480                  * since we know that the only/last address is now being
 1481                  * changed in this case, reset the cwnd/rto on all nets to
 1482                  * start as a new address and path.  Also clear the error
 1483                  * counts to give the assoc the best chance to complete the
 1484                  * address change.
 1485                  */
 1486                 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1487                         stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb,
 1488                             net);
 1489                         net->RTO = 0;
 1490                         net->error_count = 0;
 1491                 }
 1492                 stcb->asoc.overall_error_count = 0;
 1493                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
 1494                         sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
 1495                             stcb->asoc.overall_error_count,
 1496                             0,
 1497                             SCTP_FROM_SCTP_ASCONF,
 1498                             __LINE__);
 1499                 }
 1500                 /* queue in an advisory set primary too */
 1501                 (void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR);
 1502                 /* let caller know we should send this out immediately */
 1503                 status = 1;
 1504         }
 1505         return (status);
 1506 }
 1507 
 1508 /*-
 1509  * add an asconf delete IP address parameter to the queue by sockaddr and
 1510  * possibly with no sctp_ifa available.  This is only called by the routine
 1511  * that checks the addresses in an INIT-ACK against the current address list.
 1512  * returns 0 if completed, non-zero if not completed.
 1513  * NOTE: if an add is already scheduled (and not yet sent out), simply
 1514  * remove it from queue.  If a duplicate operation is found, ignore the
 1515  * new one.
 1516  */
 1517 static int
 1518 sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
 1519 {
 1520         struct sctp_ifa *ifa;
 1521         struct sctp_asconf_addr *aa, *aa_next;
 1522         uint32_t vrf_id;
 1523 
 1524         if (stcb == NULL) {
 1525                 return (-1);
 1526         }
 1527         /* see if peer supports ASCONF */
 1528         if (stcb->asoc.peer_supports_asconf == 0) {
 1529                 return (-1);
 1530         }
 1531         /* make sure the request isn't already in the queue */
 1532         TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
 1533                 /* address match? */
 1534                 if (sctp_asconf_addr_match(aa, sa) == 0)
 1535                         continue;
 1536                 /* is the request already in queue (sent or not) */
 1537                 if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
 1538                         return (-1);
 1539                 }
 1540                 /* is the negative request already in queue, and not sent */
 1541                 if (aa->sent == 1)
 1542                         continue;
 1543                 if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) {
 1544                         /* add already queued, so remove existing entry */
 1545                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1546                         sctp_del_local_addr_restricted(stcb, aa->ifa);
 1547                         /* free the entry */
 1548                         SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1549                         return (-1);
 1550                 }
 1551         }                       /* for each aa */
 1552 
 1553         /* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */
 1554         if (stcb) {
 1555                 vrf_id = stcb->asoc.vrf_id;
 1556         } else {
 1557                 vrf_id = SCTP_DEFAULT_VRFID;
 1558         }
 1559         ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 1560 
 1561         /* adding new request to the queue */
 1562         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 1563             SCTP_M_ASC_ADDR);
 1564         if (aa == NULL) {
 1565                 /* didn't get memory */
 1566                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1567                     "sctp_asconf_queue_sa_delete: failed to get memory!\n");
 1568                 return (-1);
 1569         }
 1570         aa->special_del = 0;
 1571         /* fill in asconf address parameter fields */
 1572         /* top level elements are "networked" during send */
 1573         aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
 1574         aa->ifa = ifa;
 1575         if (ifa)
 1576                 atomic_add_int(&ifa->refcount, 1);
 1577         /* correlation_id filled in during send routine later... */
 1578         switch (sa->sa_family) {
 1579 #ifdef INET6
 1580         case AF_INET6:
 1581                 {
 1582                         /* IPv6 address */
 1583                         struct sockaddr_in6 *sin6;
 1584 
 1585                         sin6 = (struct sockaddr_in6 *)sa;
 1586                         aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 1587                         aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
 1588                         aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
 1589                         memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
 1590                             sizeof(struct in6_addr));
 1591                         break;
 1592                 }
 1593 #endif
 1594 #ifdef INET
 1595         case AF_INET:
 1596                 {
 1597                         /* IPv4 address */
 1598                         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
 1599 
 1600                         aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 1601                         aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
 1602                         aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
 1603                         memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
 1604                             sizeof(struct in_addr));
 1605                         break;
 1606                 }
 1607 #endif
 1608         default:
 1609                 /* invalid family! */
 1610                 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1611                 if (ifa)
 1612                         sctp_free_ifa(ifa);
 1613                 return (-1);
 1614         }
 1615         aa->sent = 0;           /* clear sent flag */
 1616 
 1617         /* delete goes to the back of the queue */
 1618         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 1619 
 1620         /* sa_ignore MEMLEAK {memory is put on the tailq} */
 1621         return (0);
 1622 }
 1623 
 1624 /*
 1625  * find a specific asconf param on our "sent" queue
 1626  */
 1627 static struct sctp_asconf_addr *
 1628 sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
 1629 {
 1630         struct sctp_asconf_addr *aa;
 1631 
 1632         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 1633                 if (aa->ap.aph.correlation_id == correlation_id &&
 1634                     aa->sent == 1) {
 1635                         /* found it */
 1636                         return (aa);
 1637                 }
 1638         }
 1639         /* didn't find it */
 1640         return (NULL);
 1641 }
 1642 
 1643 /*
 1644  * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do
 1645  * notifications based on the error response
 1646  */
 1647 static void
 1648 sctp_asconf_process_error(struct sctp_tcb *stcb,
 1649     struct sctp_asconf_paramhdr *aph)
 1650 {
 1651         struct sctp_error_cause *eh;
 1652         struct sctp_paramhdr *ph;
 1653         uint16_t param_type;
 1654         uint16_t error_code;
 1655 
 1656         eh = (struct sctp_error_cause *)(aph + 1);
 1657         ph = (struct sctp_paramhdr *)(eh + 1);
 1658         /* validate lengths */
 1659         if (htons(eh->length) + sizeof(struct sctp_error_cause) >
 1660             htons(aph->ph.param_length)) {
 1661                 /* invalid error cause length */
 1662                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1663                     "asconf_process_error: cause element too long\n");
 1664                 return;
 1665         }
 1666         if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) >
 1667             htons(eh->length)) {
 1668                 /* invalid included TLV length */
 1669                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1670                     "asconf_process_error: included TLV too long\n");
 1671                 return;
 1672         }
 1673         /* which error code ? */
 1674         error_code = ntohs(eh->code);
 1675         param_type = ntohs(aph->ph.param_type);
 1676         /* FIX: this should go back up the REMOTE_ERROR ULP notify */
 1677         switch (error_code) {
 1678         case SCTP_CAUSE_RESOURCE_SHORTAGE:
 1679                 /* we allow ourselves to "try again" for this error */
 1680                 break;
 1681         default:
 1682                 /* peer can't handle it... */
 1683                 switch (param_type) {
 1684                 case SCTP_ADD_IP_ADDRESS:
 1685                 case SCTP_DEL_IP_ADDRESS:
 1686                         stcb->asoc.peer_supports_asconf = 0;
 1687                         break;
 1688                 case SCTP_SET_PRIM_ADDR:
 1689                         stcb->asoc.peer_supports_asconf = 0;
 1690                         break;
 1691                 default:
 1692                         break;
 1693                 }
 1694         }
 1695 }
 1696 
 1697 /*
 1698  * process an asconf queue param.
 1699  * aparam: parameter to process, will be removed from the queue.
 1700  * flag: 1=success case, 0=failure case
 1701  */
 1702 static void
 1703 sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
 1704     struct sctp_asconf_addr *aparam, uint32_t flag)
 1705 {
 1706         uint16_t param_type;
 1707 
 1708         /* process this param */
 1709         param_type = aparam->ap.aph.ph.param_type;
 1710         switch (param_type) {
 1711         case SCTP_ADD_IP_ADDRESS:
 1712                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1713                     "process_param_ack: added IP address\n");
 1714                 sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, flag);
 1715                 break;
 1716         case SCTP_DEL_IP_ADDRESS:
 1717                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1718                     "process_param_ack: deleted IP address\n");
 1719                 /* nothing really to do... lists already updated */
 1720                 break;
 1721         case SCTP_SET_PRIM_ADDR:
 1722                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1723                     "process_param_ack: set primary IP address\n");
 1724                 /* nothing to do... peer may start using this addr */
 1725                 if (flag == 0)
 1726                         stcb->asoc.peer_supports_asconf = 0;
 1727                 break;
 1728         default:
 1729                 /* should NEVER happen */
 1730                 break;
 1731         }
 1732 
 1733         /* remove the param and free it */
 1734         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
 1735         if (aparam->ifa)
 1736                 sctp_free_ifa(aparam->ifa);
 1737         SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
 1738 }
 1739 
 1740 /*
 1741  * cleanup from a bad asconf ack parameter
 1742  */
 1743 static void
 1744 sctp_asconf_ack_clear(struct sctp_tcb *stcb)
 1745 {
 1746         /* assume peer doesn't really know how to do asconfs */
 1747         stcb->asoc.peer_supports_asconf = 0;
 1748         /* XXX we could free the pending queue here */
 1749 }
 1750 
 1751 void
 1752 sctp_handle_asconf_ack(struct mbuf *m, int offset,
 1753     struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb,
 1754     struct sctp_nets *net, int *abort_no_unlock)
 1755 {
 1756         struct sctp_association *asoc;
 1757         uint32_t serial_num;
 1758         uint16_t ack_length;
 1759         struct sctp_asconf_paramhdr *aph;
 1760         struct sctp_asconf_addr *aa, *aa_next;
 1761         uint32_t last_error_id = 0;     /* last error correlation id */
 1762         uint32_t id;
 1763         struct sctp_asconf_addr *ap;
 1764 
 1765         /* asconf param buffer */
 1766         uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
 1767 
 1768         /* verify minimum length */
 1769         if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) {
 1770                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1771                     "handle_asconf_ack: chunk too small = %xh\n",
 1772                     ntohs(cp->ch.chunk_length));
 1773                 return;
 1774         }
 1775         asoc = &stcb->asoc;
 1776         serial_num = ntohl(cp->serial_number);
 1777 
 1778         /*
 1779          * NOTE: we may want to handle this differently- currently, we will
 1780          * abort when we get an ack for the expected serial number + 1 (eg.
 1781          * we didn't send it), process an ack normally if it is the expected
 1782          * serial number, and re-send the previous ack for *ALL* other
 1783          * serial numbers
 1784          */
 1785 
 1786         /*
 1787          * if the serial number is the next expected, but I didn't send it,
 1788          * abort the asoc, since someone probably just hijacked us...
 1789          */
 1790         if (serial_num == (asoc->asconf_seq_out + 1)) {
 1791                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
 1792                 sctp_abort_an_association(stcb->sctp_ep, stcb,
 1793                     SCTP_CAUSE_ILLEGAL_ASCONF_ACK, NULL, SCTP_SO_NOT_LOCKED);
 1794                 *abort_no_unlock = 1;
 1795                 return;
 1796         }
 1797         if (serial_num != asoc->asconf_seq_out_acked + 1) {
 1798                 /* got a duplicate/unexpected ASCONF-ACK */
 1799                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n",
 1800                     serial_num, asoc->asconf_seq_out_acked + 1);
 1801                 return;
 1802         }
 1803         if (serial_num == asoc->asconf_seq_out - 1) {
 1804                 /* stop our timer */
 1805                 sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
 1806                     SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3);
 1807         }
 1808         /* process the ASCONF-ACK contents */
 1809         ack_length = ntohs(cp->ch.chunk_length) -
 1810             sizeof(struct sctp_asconf_ack_chunk);
 1811         offset += sizeof(struct sctp_asconf_ack_chunk);
 1812         /* process through all parameters */
 1813         while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) {
 1814                 unsigned int param_length, param_type;
 1815 
 1816                 /* get pointer to next asconf parameter */
 1817                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
 1818                     sizeof(struct sctp_asconf_paramhdr), aparam_buf);
 1819                 if (aph == NULL) {
 1820                         /* can't get an asconf paramhdr */
 1821                         sctp_asconf_ack_clear(stcb);
 1822                         return;
 1823                 }
 1824                 param_type = ntohs(aph->ph.param_type);
 1825                 param_length = ntohs(aph->ph.param_length);
 1826                 if (param_length > ack_length) {
 1827                         sctp_asconf_ack_clear(stcb);
 1828                         return;
 1829                 }
 1830                 if (param_length < sizeof(struct sctp_paramhdr)) {
 1831                         sctp_asconf_ack_clear(stcb);
 1832                         return;
 1833                 }
 1834                 /* get the complete parameter... */
 1835                 if (param_length > sizeof(aparam_buf)) {
 1836                         SCTPDBG(SCTP_DEBUG_ASCONF1,
 1837                             "param length (%u) larger than buffer size!\n", param_length);
 1838                         sctp_asconf_ack_clear(stcb);
 1839                         return;
 1840                 }
 1841                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
 1842                 if (aph == NULL) {
 1843                         sctp_asconf_ack_clear(stcb);
 1844                         return;
 1845                 }
 1846                 /* correlation_id is transparent to peer, no ntohl needed */
 1847                 id = aph->correlation_id;
 1848 
 1849                 switch (param_type) {
 1850                 case SCTP_ERROR_CAUSE_IND:
 1851                         last_error_id = id;
 1852                         /* find the corresponding asconf param in our queue */
 1853                         ap = sctp_asconf_find_param(stcb, id);
 1854                         if (ap == NULL) {
 1855                                 /* hmm... can't find this in our queue! */
 1856                                 break;
 1857                         }
 1858                         /* process the parameter, failed flag */
 1859                         sctp_asconf_process_param_ack(stcb, ap, 0);
 1860                         /* process the error response */
 1861                         sctp_asconf_process_error(stcb, aph);
 1862                         break;
 1863                 case SCTP_SUCCESS_REPORT:
 1864                         /* find the corresponding asconf param in our queue */
 1865                         ap = sctp_asconf_find_param(stcb, id);
 1866                         if (ap == NULL) {
 1867                                 /* hmm... can't find this in our queue! */
 1868                                 break;
 1869                         }
 1870                         /* process the parameter, success flag */
 1871                         sctp_asconf_process_param_ack(stcb, ap, 1);
 1872                         break;
 1873                 default:
 1874                         break;
 1875                 }               /* switch */
 1876 
 1877                 /* update remaining ASCONF-ACK message length to process */
 1878                 ack_length -= SCTP_SIZE32(param_length);
 1879                 if (ack_length <= 0) {
 1880                         /* no more data in the mbuf chain */
 1881                         break;
 1882                 }
 1883                 offset += SCTP_SIZE32(param_length);
 1884         }                       /* while */
 1885 
 1886         /*
 1887          * if there are any "sent" params still on the queue, these are
 1888          * implicitly "success", or "failed" (if we got an error back) ...
 1889          * so process these appropriately
 1890          * 
 1891          * we assume that the correlation_id's are monotonically increasing
 1892          * beginning from 1 and that we don't have *that* many outstanding
 1893          * at any given time
 1894          */
 1895         if (last_error_id == 0)
 1896                 last_error_id--;/* set to "max" value */
 1897         TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
 1898                 if (aa->sent == 1) {
 1899                         /*
 1900                          * implicitly successful or failed if correlation_id
 1901                          * < last_error_id, then success else, failure
 1902                          */
 1903                         if (aa->ap.aph.correlation_id < last_error_id)
 1904                                 sctp_asconf_process_param_ack(stcb, aa, 1);
 1905                         else
 1906                                 sctp_asconf_process_param_ack(stcb, aa, 0);
 1907                 } else {
 1908                         /*
 1909                          * since we always process in order (FIFO queue) if
 1910                          * we reach one that hasn't been sent, the rest
 1911                          * should not have been sent either. so, we're
 1912                          * done...
 1913                          */
 1914                         break;
 1915                 }
 1916         }
 1917 
 1918         /* update the next sequence number to use */
 1919         asoc->asconf_seq_out_acked++;
 1920         /* remove the old ASCONF on our outbound queue */
 1921         sctp_toss_old_asconf(stcb);
 1922         if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
 1923 #ifdef SCTP_TIMER_BASED_ASCONF
 1924                 /* we have more params, so restart our timer */
 1925                 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep,
 1926                     stcb, net);
 1927 #else
 1928                 /* we have more params, so send out more */
 1929                 sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
 1930 #endif
 1931         }
 1932 }
 1933 
 1934 #ifdef INET6
 1935 static uint32_t
 1936 sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa)
 1937 {
 1938         struct sockaddr_in6 *sin6, *net6;
 1939         struct sctp_nets *net;
 1940 
 1941         if (sa->sa_family != AF_INET6) {
 1942                 /* wrong family */
 1943                 return (0);
 1944         }
 1945         sin6 = (struct sockaddr_in6 *)sa;
 1946         if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) {
 1947                 /* not link local address */
 1948                 return (0);
 1949         }
 1950         /* hunt through our destination nets list for this scope_id */
 1951         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1952                 if (((struct sockaddr *)(&net->ro._l_addr))->sa_family !=
 1953                     AF_INET6)
 1954                         continue;
 1955                 net6 = (struct sockaddr_in6 *)&net->ro._l_addr;
 1956                 if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0)
 1957                         continue;
 1958                 if (sctp_is_same_scope(sin6, net6)) {
 1959                         /* found one */
 1960                         return (1);
 1961                 }
 1962         }
 1963         /* didn't find one */
 1964         return (0);
 1965 }
 1966 
 1967 #endif
 1968 
 1969 /*
 1970  * address management functions
 1971  */
 1972 static void
 1973 sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
 1974     struct sctp_ifa *ifa, uint16_t type, int addr_locked)
 1975 {
 1976         int status;
 1977 
 1978 
 1979         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 ||
 1980             sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
 1981                 /* subset bound, no ASCONF allowed case, so ignore */
 1982                 return;
 1983         }
 1984         /*
 1985          * note: we know this is not the subset bound, no ASCONF case eg.
 1986          * this is boundall or subset bound w/ASCONF allowed
 1987          */
 1988 
 1989         /* first, make sure it's a good address family */
 1990         switch (ifa->address.sa.sa_family) {
 1991 #ifdef INET6
 1992         case AF_INET6:
 1993                 break;
 1994 #endif
 1995 #ifdef INET
 1996         case AF_INET:
 1997                 break;
 1998 #endif
 1999         default:
 2000                 return;
 2001         }
 2002 #ifdef INET6
 2003         /* make sure we're "allowed" to add this type of addr */
 2004         if (ifa->address.sa.sa_family == AF_INET6) {
 2005                 /* invalid if we're not a v6 endpoint */
 2006                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)
 2007                         return;
 2008                 /* is the v6 addr really valid ? */
 2009                 if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
 2010                         return;
 2011                 }
 2012         }
 2013 #endif
 2014         /* put this address on the "pending/do not use yet" list */
 2015         sctp_add_local_addr_restricted(stcb, ifa);
 2016         /*
 2017          * check address scope if address is out of scope, don't queue
 2018          * anything... note: this would leave the address on both inp and
 2019          * asoc lists
 2020          */
 2021         switch (ifa->address.sa.sa_family) {
 2022 #ifdef INET6
 2023         case AF_INET6:
 2024                 {
 2025                         struct sockaddr_in6 *sin6;
 2026 
 2027                         sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
 2028                         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 2029                                 /* we skip unspecifed addresses */
 2030                                 return;
 2031                         }
 2032                         if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 2033                                 if (stcb->asoc.local_scope == 0) {
 2034                                         return;
 2035                                 }
 2036                                 /* is it the right link local scope? */
 2037                                 if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
 2038                                         return;
 2039                                 }
 2040                         }
 2041                         if (stcb->asoc.site_scope == 0 &&
 2042                             IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
 2043                                 return;
 2044                         }
 2045                         break;
 2046                 }
 2047 #endif
 2048 #ifdef INET
 2049         case AF_INET:
 2050                 {
 2051                         struct sockaddr_in *sin;
 2052                         struct in6pcb *inp6;
 2053 
 2054                         inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 2055                         /* invalid if we are a v6 only endpoint */
 2056                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2057                             SCTP_IPV6_V6ONLY(inp6))
 2058                                 return;
 2059 
 2060                         sin = (struct sockaddr_in *)&ifa->address.sa;
 2061                         if (sin->sin_addr.s_addr == 0) {
 2062                                 /* we skip unspecifed addresses */
 2063                                 return;
 2064                         }
 2065                         if (stcb->asoc.ipv4_local_scope == 0 &&
 2066                             IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
 2067                                 return;
 2068                         }
 2069                         break;
 2070                 }
 2071 #endif
 2072         default:
 2073                 /* else, not AF_INET or AF_INET6, so skip */
 2074                 return;
 2075         }
 2076 
 2077         /* queue an asconf for this address add/delete */
 2078         if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
 2079                 /* does the peer do asconf? */
 2080                 if (stcb->asoc.peer_supports_asconf) {
 2081                         /* queue an asconf for this addr */
 2082                         status = sctp_asconf_queue_add(stcb, ifa, type);
 2083 
 2084                         /*
 2085                          * if queued ok, and in the open state, send out the
 2086                          * ASCONF.  If in the non-open state, these will be
 2087                          * sent when the state goes open.
 2088                          */
 2089                         if (status == 0 &&
 2090                             SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2091 #ifdef SCTP_TIMER_BASED_ASCONF
 2092                                 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
 2093                                     stcb, stcb->asoc.primary_destination);
 2094 #else
 2095                                 sctp_send_asconf(stcb, NULL, addr_locked);
 2096 #endif
 2097                         }
 2098                 }
 2099         }
 2100 }
 2101 
 2102 
 2103 int
 2104 sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED)
 2105 {
 2106         struct sctp_asconf_iterator *asc;
 2107         struct sctp_ifa *ifa;
 2108         struct sctp_laddr *l;
 2109         int cnt_invalid = 0;
 2110 
 2111         asc = (struct sctp_asconf_iterator *)ptr;
 2112         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
 2113                 ifa = l->ifa;
 2114                 switch (ifa->address.sa.sa_family) {
 2115 #ifdef INET6
 2116                 case AF_INET6:
 2117                         /* invalid if we're not a v6 endpoint */
 2118                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
 2119                                 cnt_invalid++;
 2120                                 if (asc->cnt == cnt_invalid)
 2121                                         return (1);
 2122                         }
 2123                         break;
 2124 #endif
 2125 #ifdef INET
 2126                 case AF_INET:
 2127                         {
 2128                                 /* invalid if we are a v6 only endpoint */
 2129                                 struct in6pcb *inp6;
 2130 
 2131                                 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 2132                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2133                                     SCTP_IPV6_V6ONLY(inp6)) {
 2134                                         cnt_invalid++;
 2135                                         if (asc->cnt == cnt_invalid)
 2136                                                 return (1);
 2137                                 }
 2138                                 break;
 2139                         }
 2140 #endif
 2141                 default:
 2142                         /* invalid address family */
 2143                         cnt_invalid++;
 2144                         if (asc->cnt == cnt_invalid)
 2145                                 return (1);
 2146                 }
 2147         }
 2148         return (0);
 2149 }
 2150 
 2151 static int
 2152 sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED)
 2153 {
 2154         struct sctp_ifa *ifa;
 2155         struct sctp_asconf_iterator *asc;
 2156         struct sctp_laddr *laddr, *nladdr, *l;
 2157 
 2158         /* Only for specific case not bound all */
 2159         asc = (struct sctp_asconf_iterator *)ptr;
 2160         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
 2161                 ifa = l->ifa;
 2162                 if (l->action == SCTP_ADD_IP_ADDRESS) {
 2163                         LIST_FOREACH(laddr, &inp->sctp_addr_list,
 2164                             sctp_nxt_addr) {
 2165                                 if (laddr->ifa == ifa) {
 2166                                         laddr->action = 0;
 2167                                         break;
 2168                                 }
 2169                         }
 2170                 } else if (l->action == SCTP_DEL_IP_ADDRESS) {
 2171                         LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
 2172                                 /* remove only after all guys are done */
 2173                                 if (laddr->ifa == ifa) {
 2174                                         sctp_del_local_addr_ep(inp, ifa);
 2175                                 }
 2176                         }
 2177                 }
 2178         }
 2179         return (0);
 2180 }
 2181 
 2182 void
 2183 sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
 2184     void *ptr, uint32_t val SCTP_UNUSED)
 2185 {
 2186         struct sctp_asconf_iterator *asc;
 2187         struct sctp_ifa *ifa;
 2188         struct sctp_laddr *l;
 2189         int cnt_invalid = 0;
 2190         int type, status;
 2191         int num_queued = 0;
 2192 
 2193         asc = (struct sctp_asconf_iterator *)ptr;
 2194         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
 2195                 ifa = l->ifa;
 2196                 type = l->action;
 2197 
 2198                 /* address's vrf_id must be the vrf_id of the assoc */
 2199                 if (ifa->vrf_id != stcb->asoc.vrf_id) {
 2200                         continue;
 2201                 }
 2202                 /* Same checks again for assoc */
 2203                 switch (ifa->address.sa.sa_family) {
 2204 #ifdef INET6
 2205                 case AF_INET6:
 2206                         {
 2207                                 /* invalid if we're not a v6 endpoint */
 2208                                 struct sockaddr_in6 *sin6;
 2209 
 2210                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
 2211                                         cnt_invalid++;
 2212                                         if (asc->cnt == cnt_invalid)
 2213                                                 return;
 2214                                         else
 2215                                                 continue;
 2216                                 }
 2217                                 sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
 2218                                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 2219                                         /* we skip unspecifed addresses */
 2220                                         continue;
 2221                                 }
 2222                                 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 2223                                         if (stcb->asoc.local_scope == 0) {
 2224                                                 continue;
 2225                                         }
 2226                                         /* is it the right link local scope? */
 2227                                         if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
 2228                                                 continue;
 2229                                         }
 2230                                 }
 2231                                 break;
 2232                         }
 2233 #endif
 2234 #ifdef INET
 2235                 case AF_INET:
 2236                         {
 2237                                 /* invalid if we are a v6 only endpoint */
 2238                                 struct in6pcb *inp6;
 2239                                 struct sockaddr_in *sin;
 2240 
 2241                                 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 2242                                 /* invalid if we are a v6 only endpoint */
 2243                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2244                                     SCTP_IPV6_V6ONLY(inp6))
 2245                                         continue;
 2246 
 2247                                 sin = (struct sockaddr_in *)&ifa->address.sa;
 2248                                 if (sin->sin_addr.s_addr == 0) {
 2249                                         /* we skip unspecifed addresses */
 2250                                         continue;
 2251                                 }
 2252                                 if (stcb->asoc.ipv4_local_scope == 0 &&
 2253                                     IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
 2254                                         continue;
 2255                                 }
 2256                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2257                                     SCTP_IPV6_V6ONLY(inp6)) {
 2258                                         cnt_invalid++;
 2259                                         if (asc->cnt == cnt_invalid)
 2260                                                 return;
 2261                                         else
 2262                                                 continue;
 2263                                 }
 2264                                 break;
 2265                         }
 2266 #endif
 2267                 default:
 2268                         /* invalid address family */
 2269                         cnt_invalid++;
 2270                         if (asc->cnt == cnt_invalid)
 2271                                 return;
 2272                         else
 2273                                 continue;
 2274                         break;
 2275                 }
 2276 
 2277                 if (type == SCTP_ADD_IP_ADDRESS) {
 2278                         /* prevent this address from being used as a source */
 2279                         sctp_add_local_addr_restricted(stcb, ifa);
 2280                 } else if (type == SCTP_DEL_IP_ADDRESS) {
 2281                         struct sctp_nets *net;
 2282 
 2283                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 2284                                 sctp_rtentry_t *rt;
 2285 
 2286                                 /* delete this address if cached */
 2287                                 if (net->ro._s_addr == ifa) {
 2288                                         sctp_free_ifa(net->ro._s_addr);
 2289                                         net->ro._s_addr = NULL;
 2290                                         net->src_addr_selected = 0;
 2291                                         rt = net->ro.ro_rt;
 2292                                         if (rt) {
 2293                                                 RTFREE(rt);
 2294                                                 net->ro.ro_rt = NULL;
 2295                                         }
 2296                                         /*
 2297                                          * Now we deleted our src address,
 2298                                          * should we not also now reset the
 2299                                          * cwnd/rto to start as if its a new
 2300                                          * address?
 2301                                          */
 2302                                         stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
 2303                                         net->RTO = 0;
 2304 
 2305                                 }
 2306                         }
 2307                 } else if (type == SCTP_SET_PRIM_ADDR) {
 2308                         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
 2309                                 /* must validate the ifa is in the ep */
 2310                                 if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) {
 2311                                         continue;
 2312                                 }
 2313                         } else {
 2314                                 /* Need to check scopes for this guy */
 2315                                 if (sctp_is_address_in_scope(ifa,
 2316                                     stcb->asoc.ipv4_addr_legal,
 2317                                     stcb->asoc.ipv6_addr_legal,
 2318                                     stcb->asoc.loopback_scope,
 2319                                     stcb->asoc.ipv4_local_scope,
 2320                                     stcb->asoc.local_scope,
 2321                                     stcb->asoc.site_scope, 0) == 0) {
 2322                                         continue;
 2323                                 }
 2324                         }
 2325                 }
 2326                 /* queue an asconf for this address add/delete */
 2327                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
 2328                     stcb->asoc.peer_supports_asconf) {
 2329                         /* queue an asconf for this addr */
 2330                         status = sctp_asconf_queue_add(stcb, ifa, type);
 2331                         /*
 2332                          * if queued ok, and in the open state, update the
 2333                          * count of queued params.  If in the non-open
 2334                          * state, these get sent when the assoc goes open.
 2335                          */
 2336                         if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2337                                 if (status >= 0) {
 2338                                         num_queued++;
 2339                                 }
 2340                         }
 2341                 }
 2342         }
 2343         /*
 2344          * If we have queued params in the open state, send out an ASCONF.
 2345          */
 2346         if (num_queued > 0) {
 2347                 sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
 2348         }
 2349 }
 2350 
 2351 void
 2352 sctp_asconf_iterator_end(void *ptr, uint32_t val SCTP_UNUSED)
 2353 {
 2354         struct sctp_asconf_iterator *asc;
 2355         struct sctp_ifa *ifa;
 2356         struct sctp_laddr *l, *nl;
 2357 
 2358         asc = (struct sctp_asconf_iterator *)ptr;
 2359         LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) {
 2360                 ifa = l->ifa;
 2361                 if (l->action == SCTP_ADD_IP_ADDRESS) {
 2362                         /* Clear the defer use flag */
 2363                         ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
 2364                 }
 2365                 sctp_free_ifa(ifa);
 2366                 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l);
 2367                 SCTP_DECR_LADDR_COUNT();
 2368         }
 2369         SCTP_FREE(asc, SCTP_M_ASC_IT);
 2370 }
 2371 
 2372 /*
 2373  * sa is the sockaddr to ask the peer to set primary to.
 2374  * returns: 0 = completed, -1 = error
 2375  */
 2376 int32_t
 2377 sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
 2378 {
 2379         uint32_t vrf_id;
 2380         struct sctp_ifa *ifa;
 2381 
 2382         /* find the ifa for the desired set primary */
 2383         vrf_id = stcb->asoc.vrf_id;
 2384         ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 2385         if (ifa == NULL) {
 2386                 /* Invalid address */
 2387                 return (-1);
 2388         }
 2389         /* queue an ASCONF:SET_PRIM_ADDR to be sent */
 2390         if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) {
 2391                 /* set primary queuing succeeded */
 2392                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 2393                     "set_primary_ip_address_sa: queued on tcb=%p, ",
 2394                     stcb);
 2395                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
 2396                 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2397 #ifdef SCTP_TIMER_BASED_ASCONF
 2398                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2399                             stcb->sctp_ep, stcb,
 2400                             stcb->asoc.primary_destination);
 2401 #else
 2402                         sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
 2403 #endif
 2404                 }
 2405         } else {
 2406                 SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ",
 2407                     stcb);
 2408                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
 2409                 return (-1);
 2410         }
 2411         return (0);
 2412 }
 2413 
 2414 void
 2415 sctp_set_primary_ip_address(struct sctp_ifa *ifa)
 2416 {
 2417         struct sctp_inpcb *inp;
 2418 
 2419         /* go through all our PCB's */
 2420         LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
 2421                 struct sctp_tcb *stcb;
 2422 
 2423                 /* process for all associations for this endpoint */
 2424                 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
 2425                         /* queue an ASCONF:SET_PRIM_ADDR to be sent */
 2426                         if (!sctp_asconf_queue_add(stcb, ifa,
 2427                             SCTP_SET_PRIM_ADDR)) {
 2428                                 /* set primary queuing succeeded */
 2429                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
 2430                                     stcb);
 2431                                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
 2432                                 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2433 #ifdef SCTP_TIMER_BASED_ASCONF
 2434                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2435                                             stcb->sctp_ep, stcb,
 2436                                             stcb->asoc.primary_destination);
 2437 #else
 2438                                         sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
 2439 #endif
 2440                                 }
 2441                         }
 2442                 }               /* for each stcb */
 2443         }                       /* for each inp */
 2444 }
 2445 
 2446 int
 2447 sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
 2448 {
 2449         struct sctp_tmit_chunk *chk, *nchk;
 2450         unsigned int offset, asconf_limit;
 2451         struct sctp_asconf_chunk *acp;
 2452         struct sctp_asconf_paramhdr *aph;
 2453         uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
 2454         struct sctp_paramhdr *ph;
 2455         int add_cnt, del_cnt;
 2456         uint16_t last_param_type;
 2457 
 2458         add_cnt = del_cnt = 0;
 2459         last_param_type = 0;
 2460         TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) {
 2461                 if (chk->data == NULL) {
 2462                         SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n");
 2463                         continue;
 2464                 }
 2465                 offset = 0;
 2466                 acp = mtod(chk->data, struct sctp_asconf_chunk *);
 2467                 offset += sizeof(struct sctp_asconf_chunk);
 2468                 asconf_limit = ntohs(acp->ch.chunk_length);
 2469                 ph = (struct sctp_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf);
 2470                 if (ph == NULL) {
 2471                         SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n");
 2472                         continue;
 2473                 }
 2474                 offset += ntohs(ph->param_length);
 2475 
 2476                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
 2477                 if (aph == NULL) {
 2478                         SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: Empty ASCONF will be sent?\n");
 2479                         continue;
 2480                 }
 2481                 while (aph != NULL) {
 2482                         unsigned int param_length, param_type;
 2483 
 2484                         param_type = ntohs(aph->ph.param_type);
 2485                         param_length = ntohs(aph->ph.param_length);
 2486                         if (offset + param_length > asconf_limit) {
 2487                                 /* parameter goes beyond end of chunk! */
 2488                                 break;
 2489                         }
 2490                         if (param_length > sizeof(aparam_buf)) {
 2491                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length (%u) larger than buffer size!\n", param_length);
 2492                                 break;
 2493                         }
 2494                         if (param_length <= sizeof(struct sctp_paramhdr)) {
 2495                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length);
 2496                                 break;
 2497                         }
 2498                         aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf);
 2499                         if (aph == NULL) {
 2500                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n");
 2501                                 break;
 2502                         }
 2503                         ph = (struct sctp_paramhdr *)(aph + 1);
 2504                         if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) {
 2505                                 switch (param_type) {
 2506                                 case SCTP_ADD_IP_ADDRESS:
 2507                                         add_cnt++;
 2508                                         break;
 2509                                 case SCTP_DEL_IP_ADDRESS:
 2510                                         del_cnt++;
 2511                                         break;
 2512                                 default:
 2513                                         break;
 2514                                 }
 2515                                 last_param_type = param_type;
 2516                         }
 2517                         offset += SCTP_SIZE32(param_length);
 2518                         if (offset >= asconf_limit) {
 2519                                 /* no more data in the mbuf chain */
 2520                                 break;
 2521                         }
 2522                         /* get pointer to next asconf param */
 2523                         aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
 2524                 }
 2525         }
 2526 
 2527         /*
 2528          * we want to find the sequences which consist of ADD -> DEL -> ADD
 2529          * or DEL -> ADD
 2530          */
 2531         if (add_cnt > del_cnt ||
 2532             (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) {
 2533                 return (1);
 2534         }
 2535         return (0);
 2536 }
 2537 
 2538 static struct sockaddr *
 2539 sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
 2540 {
 2541         struct sctp_vrf *vrf = NULL;
 2542         struct sctp_ifn *sctp_ifn;
 2543         struct sctp_ifa *sctp_ifa;
 2544 
 2545         if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2546                 SCTP_IPI_ADDR_RLOCK();
 2547         vrf = sctp_find_vrf(stcb->asoc.vrf_id);
 2548         if (vrf == NULL) {
 2549                 if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2550                         SCTP_IPI_ADDR_RUNLOCK();
 2551                 return (NULL);
 2552         }
 2553         LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
 2554                 if (stcb->asoc.loopback_scope == 0 &&
 2555                     SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
 2556                         /* Skip if loopback_scope not set */
 2557                         continue;
 2558                 }
 2559                 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
 2560                         switch (sctp_ifa->address.sa.sa_family) {
 2561 #ifdef INET
 2562                         case AF_INET:
 2563                                 if (stcb->asoc.ipv4_addr_legal) {
 2564                                         struct sockaddr_in *sin;
 2565 
 2566                                         sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
 2567                                         if (sin->sin_addr.s_addr == 0) {
 2568                                                 /* skip unspecifed addresses */
 2569                                                 continue;
 2570                                         }
 2571                                         if (stcb->asoc.ipv4_local_scope == 0 &&
 2572                                             IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
 2573                                                 continue;
 2574 
 2575                                         if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
 2576                                             (!sctp_is_addr_pending(stcb, sctp_ifa)))
 2577                                                 continue;
 2578                                         /*
 2579                                          * found a valid local v4 address to
 2580                                          * use
 2581                                          */
 2582                                         if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2583                                                 SCTP_IPI_ADDR_RUNLOCK();
 2584                                         return (&sctp_ifa->address.sa);
 2585                                 }
 2586                                 break;
 2587 #endif
 2588 #ifdef INET6
 2589                         case AF_INET6:
 2590                                 if (stcb->asoc.ipv6_addr_legal) {
 2591                                         struct sockaddr_in6 *sin6;
 2592 
 2593                                         if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
 2594                                                 continue;
 2595                                         }
 2596                                         sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
 2597                                         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 2598                                                 /*
 2599                                                  * we skip unspecifed
 2600                                                  * addresses
 2601                                                  */
 2602                                                 continue;
 2603                                         }
 2604                                         if (stcb->asoc.local_scope == 0 &&
 2605                                             IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
 2606                                                 continue;
 2607                                         if (stcb->asoc.site_scope == 0 &&
 2608                                             IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
 2609                                                 continue;
 2610 
 2611                                         if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
 2612                                             (!sctp_is_addr_pending(stcb, sctp_ifa)))
 2613                                                 continue;
 2614                                         /*
 2615                                          * found a valid local v6 address to
 2616                                          * use
 2617                                          */
 2618                                         if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2619                                                 SCTP_IPI_ADDR_RUNLOCK();
 2620                                         return (&sctp_ifa->address.sa);
 2621                                 }
 2622                                 break;
 2623 #endif
 2624                         default:
 2625                                 break;
 2626                         }
 2627                 }
 2628         }
 2629         /* no valid addresses found */
 2630         if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2631                 SCTP_IPI_ADDR_RUNLOCK();
 2632         return (NULL);
 2633 }
 2634 
 2635 static struct sockaddr *
 2636 sctp_find_valid_localaddr_ep(struct sctp_tcb *stcb)
 2637 {
 2638         struct sctp_laddr *laddr;
 2639 
 2640         LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 2641                 if (laddr->ifa == NULL) {
 2642                         continue;
 2643                 }
 2644                 /* is the address restricted ? */
 2645                 if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
 2646                     (!sctp_is_addr_pending(stcb, laddr->ifa)))
 2647                         continue;
 2648 
 2649                 /* found a valid local address to use */
 2650                 return (&laddr->ifa->address.sa);
 2651         }
 2652         /* no valid addresses found */
 2653         return (NULL);
 2654 }
 2655 
 2656 /*
 2657  * builds an ASCONF chunk from queued ASCONF params.
 2658  * returns NULL on error (no mbuf, no ASCONF params queued, etc).
 2659  */
 2660 struct mbuf *
 2661 sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
 2662 {
 2663         struct mbuf *m_asconf, *m_asconf_chk;
 2664         struct sctp_asconf_addr *aa;
 2665         struct sctp_asconf_chunk *acp;
 2666         struct sctp_asconf_paramhdr *aph;
 2667         struct sctp_asconf_addr_param *aap;
 2668         uint32_t p_length;
 2669         uint32_t correlation_id = 1;    /* 0 is reserved... */
 2670         caddr_t ptr, lookup_ptr;
 2671         uint8_t lookup_used = 0;
 2672 
 2673         /* are there any asconf params to send? */
 2674         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 2675                 if (aa->sent == 0)
 2676                         break;
 2677         }
 2678         if (aa == NULL)
 2679                 return (NULL);
 2680 
 2681         /*
 2682          * get a chunk header mbuf and a cluster for the asconf params since
 2683          * it's simpler to fill in the asconf chunk header lookup address on
 2684          * the fly
 2685          */
 2686         m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_DONTWAIT, 1, MT_DATA);
 2687         if (m_asconf_chk == NULL) {
 2688                 /* no mbuf's */
 2689                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 2690                     "compose_asconf: couldn't get chunk mbuf!\n");
 2691                 return (NULL);
 2692         }
 2693         m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
 2694         if (m_asconf == NULL) {
 2695                 /* no mbuf's */
 2696                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 2697                     "compose_asconf: couldn't get mbuf!\n");
 2698                 sctp_m_freem(m_asconf_chk);
 2699                 return (NULL);
 2700         }
 2701         SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk);
 2702         SCTP_BUF_LEN(m_asconf) = 0;
 2703         acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *);
 2704         bzero(acp, sizeof(struct sctp_asconf_chunk));
 2705         /* save pointers to lookup address and asconf params */
 2706         lookup_ptr = (caddr_t)(acp + 1);        /* after the header */
 2707         ptr = mtod(m_asconf, caddr_t);  /* beginning of cluster */
 2708 
 2709         /* fill in chunk header info */
 2710         acp->ch.chunk_type = SCTP_ASCONF;
 2711         acp->ch.chunk_flags = 0;
 2712         acp->serial_number = htonl(stcb->asoc.asconf_seq_out);
 2713         stcb->asoc.asconf_seq_out++;
 2714 
 2715         /* add parameters... up to smallest MTU allowed */
 2716         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 2717                 if (aa->sent)
 2718                         continue;
 2719                 /* get the parameter length */
 2720                 p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
 2721                 /* will it fit in current chunk? */
 2722                 if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) {
 2723                         /* won't fit, so we're done with this chunk */
 2724                         break;
 2725                 }
 2726                 /* assign (and store) a correlation id */
 2727                 aa->ap.aph.correlation_id = correlation_id++;
 2728 
 2729                 /*
 2730                  * fill in address if we're doing a delete this is a simple
 2731                  * way for us to fill in the correlation address, which
 2732                  * should only be used by the peer if we're deleting our
 2733                  * source address and adding a new address (e.g. renumbering
 2734                  * case)
 2735                  */
 2736                 if (lookup_used == 0 &&
 2737                     (aa->special_del == 0) &&
 2738                     aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
 2739                         struct sctp_ipv6addr_param *lookup;
 2740                         uint16_t p_size, addr_size;
 2741 
 2742                         lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
 2743                         lookup->ph.param_type =
 2744                             htons(aa->ap.addrp.ph.param_type);
 2745                         if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) {
 2746                                 /* copy IPv6 address */
 2747                                 p_size = sizeof(struct sctp_ipv6addr_param);
 2748                                 addr_size = sizeof(struct in6_addr);
 2749                         } else {
 2750                                 /* copy IPv4 address */
 2751                                 p_size = sizeof(struct sctp_ipv4addr_param);
 2752                                 addr_size = sizeof(struct in_addr);
 2753                         }
 2754                         lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
 2755                         memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size);
 2756                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
 2757                         lookup_used = 1;
 2758                 }
 2759                 /* copy into current space */
 2760                 memcpy(ptr, &aa->ap, p_length);
 2761 
 2762                 /* network elements and update lengths */
 2763                 aph = (struct sctp_asconf_paramhdr *)ptr;
 2764                 aap = (struct sctp_asconf_addr_param *)ptr;
 2765                 /* correlation_id is transparent to peer, no htonl needed */
 2766                 aph->ph.param_type = htons(aph->ph.param_type);
 2767                 aph->ph.param_length = htons(aph->ph.param_length);
 2768                 aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type);
 2769                 aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length);
 2770 
 2771                 SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length);
 2772                 ptr += SCTP_SIZE32(p_length);
 2773 
 2774                 /*
 2775                  * these params are removed off the pending list upon
 2776                  * getting an ASCONF-ACK back from the peer, just set flag
 2777                  */
 2778                 aa->sent = 1;
 2779         }
 2780         /* check to see if the lookup addr has been populated yet */
 2781         if (lookup_used == 0) {
 2782                 /* NOTE: if the address param is optional, can skip this... */
 2783                 /* add any valid (existing) address... */
 2784                 struct sctp_ipv6addr_param *lookup;
 2785                 uint16_t p_size, addr_size;
 2786                 struct sockaddr *found_addr;
 2787                 caddr_t addr_ptr;
 2788 
 2789                 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)
 2790                         found_addr = sctp_find_valid_localaddr(stcb,
 2791                             addr_locked);
 2792                 else
 2793                         found_addr = sctp_find_valid_localaddr_ep(stcb);
 2794 
 2795                 lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
 2796                 if (found_addr != NULL) {
 2797                         switch (found_addr->sa_family) {
 2798 #ifdef INET6
 2799                         case AF_INET6:
 2800                                 /* copy IPv6 address */
 2801                                 lookup->ph.param_type =
 2802                                     htons(SCTP_IPV6_ADDRESS);
 2803                                 p_size = sizeof(struct sctp_ipv6addr_param);
 2804                                 addr_size = sizeof(struct in6_addr);
 2805                                 addr_ptr = (caddr_t)&((struct sockaddr_in6 *)
 2806                                     found_addr)->sin6_addr;
 2807                                 break;
 2808 #endif
 2809 #ifdef INET
 2810                         case AF_INET:
 2811                                 /* copy IPv4 address */
 2812                                 lookup->ph.param_type =
 2813                                     htons(SCTP_IPV4_ADDRESS);
 2814                                 p_size = sizeof(struct sctp_ipv4addr_param);
 2815                                 addr_size = sizeof(struct in_addr);
 2816                                 addr_ptr = (caddr_t)&((struct sockaddr_in *)
 2817                                     found_addr)->sin_addr;
 2818                                 break;
 2819 #endif
 2820                         default:
 2821                                 p_size = 0;
 2822                                 addr_size = 0;
 2823                                 addr_ptr = NULL;
 2824                                 break;
 2825                         }
 2826                         lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
 2827                         memcpy(lookup->addr, addr_ptr, addr_size);
 2828                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
 2829                 } else {
 2830                         /* uh oh... don't have any address?? */
 2831                         SCTPDBG(SCTP_DEBUG_ASCONF1,
 2832                             "compose_asconf: no lookup addr!\n");
 2833                         /* XXX for now, we send a IPv4 address of 0.0.0.0 */
 2834                         lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
 2835                         lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
 2836                         bzero(lookup->addr, sizeof(struct in_addr));
 2837                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
 2838                 }
 2839         }
 2840         /* chain it all together */
 2841         SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
 2842         *retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf);
 2843         acp->ch.chunk_length = ntohs(*retlen);
 2844 
 2845         return (m_asconf_chk);
 2846 }
 2847 
 2848 /*
 2849  * section to handle address changes before an association is up eg. changes
 2850  * during INIT/INIT-ACK/COOKIE-ECHO handshake
 2851  */
 2852 
 2853 /*
 2854  * processes the (local) addresses in the INIT-ACK chunk
 2855  */
 2856 static void
 2857 sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
 2858     unsigned int offset, unsigned int length)
 2859 {
 2860         struct sctp_paramhdr tmp_param, *ph;
 2861         uint16_t plen, ptype;
 2862         struct sctp_ifa *sctp_ifa;
 2863         struct sctp_ipv6addr_param addr_store;
 2864 
 2865 #ifdef INET6
 2866         struct sockaddr_in6 sin6;
 2867 
 2868 #endif
 2869 #ifdef INET
 2870         struct sockaddr_in sin;
 2871 
 2872 #endif
 2873         struct sockaddr *sa;
 2874         uint32_t vrf_id;
 2875 
 2876         SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n");
 2877         if (stcb == NULL)       /* Un-needed check for SA */
 2878                 return;
 2879 
 2880         /* convert to upper bound */
 2881         length += offset;
 2882 
 2883         if ((offset + sizeof(struct sctp_paramhdr)) > length) {
 2884                 return;
 2885         }
 2886         /* init the addresses */
 2887 #ifdef INET6
 2888         bzero(&sin6, sizeof(sin6));
 2889         sin6.sin6_family = AF_INET6;
 2890         sin6.sin6_len = sizeof(sin6);
 2891         sin6.sin6_port = stcb->rport;
 2892 #endif
 2893 
 2894 #ifdef INET
 2895         bzero(&sin, sizeof(sin));
 2896         sin.sin_family = AF_INET;
 2897         sin.sin_len = sizeof(sin);
 2898         sin.sin_port = stcb->rport;
 2899 #endif
 2900 
 2901         /* go through the addresses in the init-ack */
 2902         ph = (struct sctp_paramhdr *)
 2903             sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
 2904             (uint8_t *) & tmp_param);
 2905         while (ph != NULL) {
 2906                 ptype = ntohs(ph->param_type);
 2907                 plen = ntohs(ph->param_length);
 2908                 switch (ptype) {
 2909 #ifdef INET6
 2910                 case SCTP_IPV6_ADDRESS:
 2911                         {
 2912                                 struct sctp_ipv6addr_param *a6p;
 2913 
 2914                                 /* get the entire IPv6 address param */
 2915                                 a6p = (struct sctp_ipv6addr_param *)
 2916                                     sctp_m_getptr(m, offset,
 2917                                     sizeof(struct sctp_ipv6addr_param),
 2918                                     (uint8_t *) & addr_store);
 2919                                 if (plen != sizeof(struct sctp_ipv6addr_param) ||
 2920                                     a6p == NULL) {
 2921                                         return;
 2922                                 }
 2923                                 memcpy(&sin6.sin6_addr, a6p->addr,
 2924                                     sizeof(struct in6_addr));
 2925                                 sa = (struct sockaddr *)&sin6;
 2926                                 break;
 2927                         }
 2928 #endif
 2929 #ifdef INET
 2930                 case SCTP_IPV4_ADDRESS:
 2931                         {
 2932                                 struct sctp_ipv4addr_param *a4p;
 2933 
 2934                                 /* get the entire IPv4 address param */
 2935                                 a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
 2936                                     sizeof(struct sctp_ipv4addr_param),
 2937                                     (uint8_t *) & addr_store);
 2938                                 if (plen != sizeof(struct sctp_ipv4addr_param) ||
 2939                                     a4p == NULL) {
 2940                                         return;
 2941                                 }
 2942                                 sin.sin_addr.s_addr = a4p->addr;
 2943                                 sa = (struct sockaddr *)&sin;
 2944                                 break;
 2945                         }
 2946 #endif
 2947                 default:
 2948                         goto next_addr;
 2949                 }
 2950 
 2951                 /* see if this address really (still) exists */
 2952                 if (stcb) {
 2953                         vrf_id = stcb->asoc.vrf_id;
 2954                 } else {
 2955                         vrf_id = SCTP_DEFAULT_VRFID;
 2956                 }
 2957                 sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id,
 2958                     SCTP_ADDR_NOT_LOCKED);
 2959                 if (sctp_ifa == NULL) {
 2960                         /* address doesn't exist anymore */
 2961                         int status;
 2962 
 2963                         /* are ASCONFs allowed ? */
 2964                         if ((sctp_is_feature_on(stcb->sctp_ep,
 2965                             SCTP_PCB_FLAGS_DO_ASCONF)) &&
 2966                             stcb->asoc.peer_supports_asconf) {
 2967                                 /* queue an ASCONF DEL_IP_ADDRESS */
 2968                                 status = sctp_asconf_queue_sa_delete(stcb, sa);
 2969                                 /*
 2970                                  * if queued ok, and in correct state, send
 2971                                  * out the ASCONF.
 2972                                  */
 2973                                 if (status == 0 &&
 2974                                     SCTP_GET_STATE(&stcb->asoc) ==
 2975                                     SCTP_STATE_OPEN) {
 2976 #ifdef SCTP_TIMER_BASED_ASCONF
 2977                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2978                                             stcb->sctp_ep, stcb,
 2979                                             stcb->asoc.primary_destination);
 2980 #else
 2981                                         sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
 2982 #endif
 2983                                 }
 2984                         }
 2985                 }
 2986 next_addr:
 2987                 /*
 2988                  * Sanity check:  Make sure the length isn't 0, otherwise
 2989                  * we'll be stuck in this loop for a long time...
 2990                  */
 2991                 if (SCTP_SIZE32(plen) == 0) {
 2992                         SCTP_PRINTF("process_initack_addrs: bad len (%d) type=%xh\n",
 2993                             plen, ptype);
 2994                         return;
 2995                 }
 2996                 /* get next parameter */
 2997                 offset += SCTP_SIZE32(plen);
 2998                 if ((offset + sizeof(struct sctp_paramhdr)) > length)
 2999                         return;
 3000                 ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
 3001                     sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
 3002         }                       /* while */
 3003 }
 3004 
 3005 /* FIX ME: need to verify return result for v6 address type if v6 disabled */
 3006 /*
 3007  * checks to see if a specific address is in the initack address list returns
 3008  * 1 if found, 0 if not
 3009  */
 3010 static uint32_t
 3011 sctp_addr_in_initack(struct mbuf *m, uint32_t offset, uint32_t length, struct sockaddr *sa)
 3012 {
 3013         struct sctp_paramhdr tmp_param, *ph;
 3014         uint16_t plen, ptype;
 3015         struct sctp_ipv6addr_param addr_store;
 3016 
 3017 #ifdef INET
 3018         struct sockaddr_in *sin;
 3019         struct sctp_ipv4addr_param *a4p;
 3020 
 3021 #endif
 3022 #ifdef INET6
 3023         struct sockaddr_in6 *sin6;
 3024         struct sctp_ipv6addr_param *a6p;
 3025         struct sockaddr_in6 sin6_tmp;
 3026 
 3027 #endif
 3028 
 3029         switch (sa->sa_family) {
 3030 #ifdef INET
 3031         case AF_INET:
 3032                 break;
 3033 #endif
 3034 #ifdef INET6
 3035         case AF_INET6:
 3036                 break;
 3037 #endif
 3038         default:
 3039                 return (0);
 3040         }
 3041 
 3042         SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for ");
 3043         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 3044         /* convert to upper bound */
 3045         length += offset;
 3046 
 3047         if ((offset + sizeof(struct sctp_paramhdr)) > length) {
 3048                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3049                     "find_initack_addr: invalid offset?\n");
 3050                 return (0);
 3051         }
 3052         /* go through the addresses in the init-ack */
 3053         ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
 3054             sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
 3055         while (ph != NULL) {
 3056                 ptype = ntohs(ph->param_type);
 3057                 plen = ntohs(ph->param_length);
 3058                 switch (ptype) {
 3059 #ifdef INET6
 3060                 case SCTP_IPV6_ADDRESS:
 3061                         if (sa->sa_family == AF_INET6) {
 3062                                 /* get the entire IPv6 address param */
 3063                                 if (plen != sizeof(struct sctp_ipv6addr_param)) {
 3064                                         break;
 3065                                 }
 3066                                 /* get the entire IPv6 address param */
 3067                                 a6p = (struct sctp_ipv6addr_param *)
 3068                                     sctp_m_getptr(m, offset,
 3069                                     sizeof(struct sctp_ipv6addr_param),
 3070                                     (uint8_t *) & addr_store);
 3071                                 if (a6p == NULL) {
 3072                                         return (0);
 3073                                 }
 3074                                 sin6 = (struct sockaddr_in6 *)sa;
 3075                                 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
 3076                                         /* create a copy and clear scope */
 3077                                         memcpy(&sin6_tmp, sin6,
 3078                                             sizeof(struct sockaddr_in6));
 3079                                         sin6 = &sin6_tmp;
 3080                                         in6_clearscope(&sin6->sin6_addr);
 3081                                 }
 3082                                 if (memcmp(&sin6->sin6_addr, a6p->addr,
 3083                                     sizeof(struct in6_addr)) == 0) {
 3084                                         /* found it */
 3085                                         return (1);
 3086                                 }
 3087                         }
 3088                         break;
 3089 #endif                          /* INET6 */
 3090 #ifdef INET
 3091                 case SCTP_IPV4_ADDRESS:
 3092                         if (sa->sa_family == AF_INET) {
 3093                                 if (plen != sizeof(struct sctp_ipv4addr_param)) {
 3094                                         break;
 3095                                 }
 3096                                 /* get the entire IPv4 address param */
 3097                                 a4p = (struct sctp_ipv4addr_param *)
 3098                                     sctp_m_getptr(m, offset,
 3099                                     sizeof(struct sctp_ipv4addr_param),
 3100                                     (uint8_t *) & addr_store);
 3101                                 if (a4p == NULL) {
 3102                                         return (0);
 3103                                 }
 3104                                 sin = (struct sockaddr_in *)sa;
 3105                                 if (sin->sin_addr.s_addr == a4p->addr) {
 3106                                         /* found it */
 3107                                         return (1);
 3108                                 }
 3109                         }
 3110                         break;
 3111 #endif
 3112                 default:
 3113                         break;
 3114                 }
 3115                 /* get next parameter */
 3116                 offset += SCTP_SIZE32(plen);
 3117                 if (offset + sizeof(struct sctp_paramhdr) > length) {
 3118                         return (0);
 3119                 }
 3120                 ph = (struct sctp_paramhdr *)
 3121                     sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
 3122                     (uint8_t *) & tmp_param);
 3123         }                       /* while */
 3124         /* not found! */
 3125         return (0);
 3126 }
 3127 
 3128 /*
 3129  * makes sure that the current endpoint local addr list is consistent with
 3130  * the new association (eg. subset bound, asconf allowed) adds addresses as
 3131  * necessary
 3132  */
 3133 static void
 3134 sctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 3135     int length, struct sockaddr *init_addr)
 3136 {
 3137         struct sctp_laddr *laddr;
 3138 
 3139         /* go through the endpoint list */
 3140         LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 3141                 /* be paranoid and validate the laddr */
 3142                 if (laddr->ifa == NULL) {
 3143                         SCTPDBG(SCTP_DEBUG_ASCONF1,
 3144                             "check_addr_list_ep: laddr->ifa is NULL");
 3145                         continue;
 3146                 }
 3147                 if (laddr->ifa == NULL) {
 3148                         SCTPDBG(SCTP_DEBUG_ASCONF1, "check_addr_list_ep: laddr->ifa->ifa_addr is NULL");
 3149                         continue;
 3150                 }
 3151                 /* do i have it implicitly? */
 3152                 if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) {
 3153                         continue;
 3154                 }
 3155                 /* check to see if in the init-ack */
 3156                 if (!sctp_addr_in_initack(m, offset, length, &laddr->ifa->address.sa)) {
 3157                         /* try to add it */
 3158                         sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa,
 3159                             SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED);
 3160                 }
 3161         }
 3162 }
 3163 
 3164 /*
 3165  * makes sure that the current kernel address list is consistent with the new
 3166  * association (with all addrs bound) adds addresses as necessary
 3167  */
 3168 static void
 3169 sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 3170     int length, struct sockaddr *init_addr,
 3171     uint16_t local_scope, uint16_t site_scope,
 3172     uint16_t ipv4_scope, uint16_t loopback_scope)
 3173 {
 3174         struct sctp_vrf *vrf = NULL;
 3175         struct sctp_ifn *sctp_ifn;
 3176         struct sctp_ifa *sctp_ifa;
 3177         uint32_t vrf_id;
 3178 
 3179 #ifdef INET
 3180         struct sockaddr_in *sin;
 3181 
 3182 #endif
 3183 #ifdef INET6
 3184         struct sockaddr_in6 *sin6;
 3185 
 3186 #endif
 3187 
 3188         if (stcb) {
 3189                 vrf_id = stcb->asoc.vrf_id;
 3190         } else {
 3191                 return;
 3192         }
 3193         SCTP_IPI_ADDR_RLOCK();
 3194         vrf = sctp_find_vrf(vrf_id);
 3195         if (vrf == NULL) {
 3196                 SCTP_IPI_ADDR_RUNLOCK();
 3197                 return;
 3198         }
 3199         /* go through all our known interfaces */
 3200         LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
 3201                 if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
 3202                         /* skip loopback interface */
 3203                         continue;
 3204                 }
 3205                 /* go through each interface address */
 3206                 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
 3207                         /* do i have it implicitly? */
 3208                         if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
 3209                                 continue;
 3210                         }
 3211                         switch (sctp_ifa->address.sa.sa_family) {
 3212 #ifdef INET
 3213                         case AF_INET:
 3214                                 sin = (struct sockaddr_in *)&sctp_ifa->address.sin;
 3215                                 if ((ipv4_scope == 0) &&
 3216                                     (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
 3217                                         /* private address not in scope */
 3218                                         continue;
 3219                                 }
 3220                                 break;
 3221 #endif
 3222 #ifdef INET6
 3223                         case AF_INET6:
 3224                                 sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6;
 3225                                 if ((local_scope == 0) &&
 3226                                     (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
 3227                                         continue;
 3228                                 }
 3229                                 if ((site_scope == 0) &&
 3230                                     (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
 3231                                         continue;
 3232                                 }
 3233                                 break;
 3234 #endif
 3235                         default:
 3236                                 break;
 3237                         }
 3238                         /* check to see if in the init-ack */
 3239                         if (!sctp_addr_in_initack(m, offset, length, &sctp_ifa->address.sa)) {
 3240                                 /* try to add it */
 3241                                 sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
 3242                                     sctp_ifa, SCTP_ADD_IP_ADDRESS,
 3243                                     SCTP_ADDR_LOCKED);
 3244                         }
 3245                 }               /* end foreach ifa */
 3246         }                       /* end foreach ifn */
 3247         SCTP_IPI_ADDR_RUNLOCK();
 3248 }
 3249 
 3250 /*
 3251  * validates an init-ack chunk (from a cookie-echo) with current addresses
 3252  * adds addresses from the init-ack into our local address list, if needed
 3253  * queues asconf adds/deletes addresses as needed and makes appropriate list
 3254  * changes for source address selection m, offset: points to the start of the
 3255  * address list in an init-ack chunk length: total length of the address
 3256  * params only init_addr: address where my INIT-ACK was sent from
 3257  */
 3258 void
 3259 sctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 3260     int length, struct sockaddr *init_addr,
 3261     uint16_t local_scope, uint16_t site_scope,
 3262     uint16_t ipv4_scope, uint16_t loopback_scope)
 3263 {
 3264         /* process the local addresses in the initack */
 3265         sctp_process_initack_addresses(stcb, m, offset, length);
 3266 
 3267         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
 3268                 /* bound all case */
 3269                 sctp_check_address_list_all(stcb, m, offset, length, init_addr,
 3270                     local_scope, site_scope, ipv4_scope, loopback_scope);
 3271         } else {
 3272                 /* subset bound case */
 3273                 if (sctp_is_feature_on(stcb->sctp_ep,
 3274                     SCTP_PCB_FLAGS_DO_ASCONF)) {
 3275                         /* asconf's allowed */
 3276                         sctp_check_address_list_ep(stcb, m, offset, length,
 3277                             init_addr);
 3278                 }
 3279                 /* else, no asconfs allowed, so what we sent is what we get */
 3280         }
 3281 }
 3282 
 3283 /*
 3284  * sctp_bindx() support
 3285  */
 3286 uint32_t
 3287 sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
 3288     uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap)
 3289 {
 3290         struct sctp_ifa *ifa;
 3291         struct sctp_laddr *laddr, *nladdr;
 3292 
 3293         if (sa->sa_len == 0) {
 3294                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
 3295                 return (EINVAL);
 3296         }
 3297         if (sctp_ifap) {
 3298                 ifa = sctp_ifap;
 3299         } else if (type == SCTP_ADD_IP_ADDRESS) {
 3300                 /* For an add the address MUST be on the system */
 3301                 ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 3302         } else if (type == SCTP_DEL_IP_ADDRESS) {
 3303                 /* For a delete we need to find it in the inp */
 3304                 ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED);
 3305         } else {
 3306                 ifa = NULL;
 3307         }
 3308         if (ifa != NULL) {
 3309                 if (type == SCTP_ADD_IP_ADDRESS) {
 3310                         sctp_add_local_addr_ep(inp, ifa, type);
 3311                 } else if (type == SCTP_DEL_IP_ADDRESS) {
 3312                         if (inp->laddr_count < 2) {
 3313                                 /* can't delete the last local address */
 3314                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
 3315                                 return (EINVAL);
 3316                         }
 3317                         LIST_FOREACH(laddr, &inp->sctp_addr_list,
 3318                             sctp_nxt_addr) {
 3319                                 if (ifa == laddr->ifa) {
 3320                                         /* Mark in the delete */
 3321                                         laddr->action = type;
 3322                                 }
 3323                         }
 3324                 }
 3325                 if (LIST_EMPTY(&inp->sctp_asoc_list)) {
 3326                         /*
 3327                          * There is no need to start the iterator if the inp
 3328                          * has no associations.
 3329                          */
 3330                         if (type == SCTP_DEL_IP_ADDRESS) {
 3331                                 LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
 3332                                         if (laddr->ifa == ifa) {
 3333                                                 sctp_del_local_addr_ep(inp, ifa);
 3334                                         }
 3335                                 }
 3336                         }
 3337                 } else {
 3338                         struct sctp_asconf_iterator *asc;
 3339                         struct sctp_laddr *wi;
 3340 
 3341                         SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
 3342                             sizeof(struct sctp_asconf_iterator),
 3343                             SCTP_M_ASC_IT);
 3344                         if (asc == NULL) {
 3345                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
 3346                                 return (ENOMEM);
 3347                         }
 3348                         wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr);
 3349                         if (wi == NULL) {
 3350                                 SCTP_FREE(asc, SCTP_M_ASC_IT);
 3351                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
 3352                                 return (ENOMEM);
 3353                         }
 3354                         LIST_INIT(&asc->list_of_work);
 3355                         asc->cnt = 1;
 3356                         SCTP_INCR_LADDR_COUNT();
 3357                         wi->ifa = ifa;
 3358                         wi->action = type;
 3359                         atomic_add_int(&ifa->refcount, 1);
 3360                         LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
 3361                         (void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
 3362                             sctp_asconf_iterator_stcb,
 3363                             sctp_asconf_iterator_ep_end,
 3364                             SCTP_PCB_ANY_FLAGS,
 3365                             SCTP_PCB_ANY_FEATURES,
 3366                             SCTP_ASOC_ANY_STATE,
 3367                             (void *)asc, 0,
 3368                             sctp_asconf_iterator_end, inp, 0);
 3369                 }
 3370                 return (0);
 3371         } else {
 3372                 /* invalid address! */
 3373                 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL);
 3374                 return (EADDRNOTAVAIL);
 3375         }
 3376 }
 3377 
 3378 void
 3379 sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
 3380     struct sctp_nets *net)
 3381 {
 3382         struct sctp_asconf_addr *aa;
 3383         struct sctp_ifa *sctp_ifap;
 3384         struct sctp_asconf_tag_param *vtag;
 3385 
 3386 #ifdef INET
 3387         struct sockaddr_in *to;
 3388 
 3389 #endif
 3390 #ifdef INET6
 3391         struct sockaddr_in6 *to6;
 3392 
 3393 #endif
 3394         if (net == NULL) {
 3395                 SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n");
 3396                 return;
 3397         }
 3398         if (stcb == NULL) {
 3399                 SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n");
 3400                 return;
 3401         }
 3402         /*
 3403          * Need to have in the asconf: - vtagparam(my_vtag/peer_vtag) -
 3404          * add(0.0.0.0) - del(0.0.0.0) - Any global addresses add(addr)
 3405          */
 3406         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 3407             SCTP_M_ASC_ADDR);
 3408         if (aa == NULL) {
 3409                 /* didn't get memory */
 3410                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3411                     "sctp_asconf_send_nat_state_update: failed to get memory!\n");
 3412                 return;
 3413         }
 3414         aa->special_del = 0;
 3415         /* fill in asconf address parameter fields */
 3416         /* top level elements are "networked" during send */
 3417         aa->ifa = NULL;
 3418         aa->sent = 0;           /* clear sent flag */
 3419         vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph;
 3420         vtag->aph.ph.param_type = SCTP_NAT_VTAGS;
 3421         vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param);
 3422         vtag->local_vtag = htonl(stcb->asoc.my_vtag);
 3423         vtag->remote_vtag = htonl(stcb->asoc.peer_vtag);
 3424         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3425 
 3426         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 3427             SCTP_M_ASC_ADDR);
 3428         if (aa == NULL) {
 3429                 /* didn't get memory */
 3430                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3431                     "sctp_asconf_send_nat_state_update: failed to get memory!\n");
 3432                 return;
 3433         }
 3434         memset(aa, 0, sizeof(struct sctp_asconf_addr));
 3435         /* fill in asconf address parameter fields */
 3436         /* ADD(0.0.0.0) */
 3437         switch (net->ro._l_addr.sa.sa_family) {
 3438 #ifdef INET
 3439         case AF_INET:
 3440                 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
 3441                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
 3442                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 3443                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param);
 3444                 /* No need to add an address, we are using 0.0.0.0 */
 3445                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3446                 break;
 3447 #endif
 3448 #ifdef INET6
 3449         case AF_INET6:
 3450                 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
 3451                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
 3452                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 3453                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param);
 3454                 /* No need to add an address, we are using 0.0.0.0 */
 3455                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3456                 break;
 3457 #endif
 3458         }
 3459         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 3460             SCTP_M_ASC_ADDR);
 3461         if (aa == NULL) {
 3462                 /* didn't get memory */
 3463                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3464                     "sctp_asconf_send_nat_state_update: failed to get memory!\n");
 3465                 return;
 3466         }
 3467         memset(aa, 0, sizeof(struct sctp_asconf_addr));
 3468         /* fill in asconf address parameter fields */
 3469         /* ADD(0.0.0.0) */
 3470         switch (net->ro._l_addr.sa.sa_family) {
 3471 #ifdef INET
 3472         case AF_INET:
 3473                 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
 3474                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
 3475                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 3476                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param);
 3477                 /* No need to add an address, we are using 0.0.0.0 */
 3478                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3479                 break;
 3480 #endif
 3481 #ifdef INET6
 3482         case AF_INET6:
 3483                 aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
 3484                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
 3485                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 3486                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param);
 3487                 /* No need to add an address, we are using 0.0.0.0 */
 3488                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3489                 break;
 3490 #endif
 3491         }
 3492         /* Now we must hunt the addresses and add all global addresses */
 3493         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
 3494                 struct sctp_vrf *vrf = NULL;
 3495                 struct sctp_ifn *sctp_ifnp;
 3496                 uint32_t vrf_id;
 3497 
 3498                 vrf_id = stcb->sctp_ep->def_vrf_id;
 3499                 vrf = sctp_find_vrf(vrf_id);
 3500                 if (vrf == NULL) {
 3501                         goto skip_rest;
 3502                 }
 3503                 SCTP_IPI_ADDR_RLOCK();
 3504                 LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
 3505                         LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
 3506                                 switch (sctp_ifap->address.sa.sa_family) {
 3507 #ifdef INET
 3508                                 case AF_INET:
 3509                                         to = &sctp_ifap->address.sin;
 3510                                         if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
 3511                                                 continue;
 3512                                         }
 3513                                         if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
 3514                                                 continue;
 3515                                         }
 3516                                         break;
 3517 #endif
 3518 #ifdef INET6
 3519                                 case AF_INET6:
 3520                                         to6 = &sctp_ifap->address.sin6;
 3521                                         if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
 3522                                                 continue;
 3523                                         }
 3524                                         if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
 3525                                                 continue;
 3526                                         }
 3527                                         break;
 3528 #endif
 3529                                 default:
 3530                                         continue;
 3531                                 }
 3532                                 sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
 3533                         }
 3534                 }
 3535                 SCTP_IPI_ADDR_RUNLOCK();
 3536         } else {
 3537                 struct sctp_laddr *laddr;
 3538 
 3539                 LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 3540                         if (laddr->ifa == NULL) {
 3541                                 continue;
 3542                         }
 3543                         if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED)
 3544                                 /*
 3545                                  * Address being deleted by the system, dont
 3546                                  * list.
 3547                                  */
 3548                                 continue;
 3549                         if (laddr->action == SCTP_DEL_IP_ADDRESS) {
 3550                                 /*
 3551                                  * Address being deleted on this ep don't
 3552                                  * list.
 3553                                  */
 3554                                 continue;
 3555                         }
 3556                         sctp_ifap = laddr->ifa;
 3557                         switch (sctp_ifap->address.sa.sa_family) {
 3558 #ifdef INET
 3559                         case AF_INET:
 3560                                 to = &sctp_ifap->address.sin;
 3561                                 if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
 3562                                         continue;
 3563                                 }
 3564                                 if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
 3565                                         continue;
 3566                                 }
 3567                                 break;
 3568 #endif
 3569 #ifdef INET6
 3570                         case AF_INET6:
 3571                                 to6 = &sctp_ifap->address.sin6;
 3572                                 if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
 3573                                         continue;
 3574                                 }
 3575                                 if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
 3576                                         continue;
 3577                                 }
 3578                                 break;
 3579 #endif
 3580                         default:
 3581                                 continue;
 3582                         }
 3583                         sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
 3584                 }
 3585         }
 3586 skip_rest:
 3587         /* Now we must send the asconf into the queue */
 3588         sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
 3589 }

Cache object: cd885a35b03d4807259ecf5e2b6381da


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