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

Cache object: 4011679c9f3c7104434a75069ebf6da1


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