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  -  FREEBSD11  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 742bdd18c3d68ce3b965b99e4ceeb83b


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