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

Cache object: d89551a241b89583c3f6c34961abb4ab


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