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

Cache object: 01046aa2bb3a8a5dca7be4d2a411877a


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