The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/sctp_asconf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
    3  *
    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/8.2/sys/netinet/sctp_asconf.c 214477 2010-10-28 19:05:21Z 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 to
  560                  * REQ_PRIM, The retransmission occur when reception of the
  561                  * 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_net(stcb,
  585                                     stcb->asoc.deleted_primary);
  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         ack->len = 0;
  830         n = m_ack;
  831         while (n) {
  832                 ack->len += SCTP_BUF_LEN(n);
  833                 n = SCTP_BUF_NEXT(n);
  834         }
  835         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next);
  836 
  837         /* see if last_control_chunk_from is set properly (use IP src addr) */
  838         if (stcb->asoc.last_control_chunk_from == NULL) {
  839                 /*
  840                  * this could happen if the source address was just newly
  841                  * added
  842                  */
  843                 struct ip *iph;
  844                 struct sctphdr *sh;
  845                 struct sockaddr_storage from_store;
  846                 struct sockaddr *from = (struct sockaddr *)&from_store;
  847 
  848                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n");
  849                 /* pullup already done, IP options already stripped */
  850                 iph = mtod(m, struct ip *);
  851                 sh = (struct sctphdr *)((caddr_t)iph + sizeof(*iph));
  852                 switch (iph->ip_v) {
  853                 case IPVERSION:
  854                         {
  855                                 struct sockaddr_in *from4;
  856 
  857                                 from4 = (struct sockaddr_in *)&from_store;
  858                                 bzero(from4, sizeof(*from4));
  859                                 from4->sin_family = AF_INET;
  860                                 from4->sin_len = sizeof(struct sockaddr_in);
  861                                 from4->sin_addr.s_addr = iph->ip_src.s_addr;
  862                                 from4->sin_port = sh->src_port;
  863                                 break;
  864                         }
  865 #ifdef INET6
  866                 case IPV6_VERSION >> 4:
  867                         {
  868                                 struct ip6_hdr *ip6;
  869                                 struct sockaddr_in6 *from6;
  870 
  871                                 ip6 = mtod(m, struct ip6_hdr *);
  872                                 from6 = (struct sockaddr_in6 *)&from_store;
  873                                 bzero(from6, sizeof(*from6));
  874                                 from6->sin6_family = AF_INET6;
  875                                 from6->sin6_len = sizeof(struct sockaddr_in6);
  876                                 from6->sin6_addr = ip6->ip6_src;
  877                                 from6->sin6_port = sh->src_port;
  878                                 /*
  879                                  * Get the scopes in properly to the sin6
  880                                  * addr's
  881                                  */
  882                                 /* we probably don't need these operations */
  883                                 (void)sa6_recoverscope(from6);
  884                                 sa6_embedscope(from6,
  885                                     MODULE_GLOBAL(ip6_use_defzone));
  886 
  887                                 break;
  888                         }
  889 #endif
  890                 default:
  891                         /* unknown address type */
  892                         from = NULL;
  893                 }
  894                 if (from != NULL) {
  895                         SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: ");
  896                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, from);
  897                         /* look up the from address */
  898                         stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, from);
  899 #ifdef SCTP_DEBUG
  900                         if (stcb->asoc.last_control_chunk_from == NULL)
  901                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n");
  902 #endif
  903                 }
  904         }
  905 }
  906 
  907 /*
  908  * does the address match? returns 0 if not, 1 if so
  909  */
  910 static uint32_t
  911 sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
  912 {
  913 #ifdef INET6
  914         if (sa->sa_family == AF_INET6) {
  915                 /* IPv6 sa address */
  916                 /* XXX scopeid */
  917                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
  918 
  919                 if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) &&
  920                     (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr,
  921                     sizeof(struct in6_addr)) == 0)) {
  922                         return (1);
  923                 }
  924         } else
  925 #endif                          /* INET6 */
  926         if (sa->sa_family == AF_INET) {
  927                 /* IPv4 sa address */
  928                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
  929 
  930                 if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) &&
  931                     (memcmp(&aa->ap.addrp.addr, &sin->sin_addr,
  932                     sizeof(struct in_addr)) == 0)) {
  933                         return (1);
  934                 }
  935         }
  936         return (0);
  937 }
  938 
  939 /*
  940  * does the address match? returns 0 if not, 1 if so
  941  */
  942 static uint32_t
  943 sctp_addr_match(
  944     struct sctp_ipv6addr_param *v6addr,
  945     struct sockaddr *sa)
  946 {
  947         uint16_t param_type, param_length;
  948         struct sctp_ipv4addr_param *v4addr = (struct sctp_ipv4addr_param *)v6addr;
  949 
  950 #ifdef INET6
  951         if (sa->sa_family == AF_INET6) {
  952                 /* IPv6 sa address */
  953                 /* XXX scopeid */
  954                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
  955 
  956                 param_type = ntohs(v6addr->ph.param_type);
  957                 param_length = ntohs(v6addr->ph.param_length);
  958 
  959                 if ((param_type == SCTP_IPV6_ADDRESS) &&
  960                     param_length == sizeof(struct sctp_ipv6addr_param) &&
  961                     (memcmp(&v6addr->addr, &sin6->sin6_addr,
  962                     sizeof(struct in6_addr)) == 0)) {
  963                         return (1);
  964                 }
  965         }
  966 #endif
  967         if (sa->sa_family == AF_INET) {
  968                 /* IPv4 sa address */
  969                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
  970 
  971                 param_type = ntohs(v4addr->ph.param_type);
  972                 param_length = ntohs(v4addr->ph.param_length);
  973 
  974                 if ((param_type == SCTP_IPV4_ADDRESS) &&
  975                     param_length == sizeof(struct sctp_ipv4addr_param) &&
  976                     (memcmp(&v4addr->addr, &sin->sin_addr,
  977                     sizeof(struct in_addr)) == 0)) {
  978                         return (1);
  979                 }
  980         }
  981         return (0);
  982 }
  983 
  984 /*
  985  * Cleanup for non-responded/OP ERR'd ASCONF
  986  */
  987 void
  988 sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
  989 {
  990         /* mark peer as ASCONF incapable */
  991         stcb->asoc.peer_supports_asconf = 0;
  992         /*
  993          * clear out any existing asconfs going out
  994          */
  995         sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
  996             SCTP_FROM_SCTP_ASCONF + SCTP_LOC_2);
  997         stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out;
  998         /* remove the old ASCONF on our outbound queue */
  999         sctp_toss_old_asconf(stcb);
 1000 }
 1001 
 1002 /*
 1003  * cleanup any cached source addresses that may be topologically
 1004  * incorrect after a new address has been added to this interface.
 1005  */
 1006 static void
 1007 sctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn)
 1008 {
 1009         struct sctp_nets *net;
 1010 
 1011         /*
 1012          * Ideally, we want to only clear cached routes and source addresses
 1013          * that are topologically incorrect.  But since there is no easy way
 1014          * to know whether the newly added address on the ifn would cause a
 1015          * routing change (i.e. a new egress interface would be chosen)
 1016          * without doing a new routing lookup and source address selection,
 1017          * we will (for now) just flush any cached route using a different
 1018          * ifn (and cached source addrs) and let output re-choose them
 1019          * during the next send on that net.
 1020          */
 1021         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1022                 /*
 1023                  * clear any cached route (and cached source address) if the
 1024                  * route's interface is NOT the same as the address change.
 1025                  * If it's the same interface, just clear the cached source
 1026                  * address.
 1027                  */
 1028                 if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) &&
 1029                     ((ifn == NULL) ||
 1030                     (SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) {
 1031                         /* clear any cached route */
 1032                         RTFREE(net->ro.ro_rt);
 1033                         net->ro.ro_rt = NULL;
 1034                 }
 1035                 /* clear any cached source address */
 1036                 if (net->src_addr_selected) {
 1037                         sctp_free_ifa(net->ro._s_addr);
 1038                         net->ro._s_addr = NULL;
 1039                         net->src_addr_selected = 0;
 1040                 }
 1041         }
 1042 }
 1043 
 1044 
 1045 void
 1046 sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet)
 1047 {
 1048         int error;
 1049 
 1050         if (dstnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
 1051                 return;
 1052         }
 1053         if (stcb->asoc.deleted_primary == NULL) {
 1054                 return;
 1055         }
 1056         if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
 1057                 SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Deleted primary is ");
 1058                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa);
 1059                 SCTPDBG(SCTP_DEBUG_ASCONF1, "Current Primary is ");
 1060                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa);
 1061                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb,
 1062                     stcb->asoc.deleted_primary,
 1063                     SCTP_FROM_SCTP_TIMER + SCTP_LOC_8);
 1064                 stcb->asoc.num_send_timers_up--;
 1065                 if (stcb->asoc.num_send_timers_up < 0) {
 1066                         stcb->asoc.num_send_timers_up = 0;
 1067                 }
 1068                 SCTP_TCB_LOCK_ASSERT(stcb);
 1069                 error = sctp_t3rxt_timer(stcb->sctp_ep, stcb,
 1070                     stcb->asoc.deleted_primary);
 1071                 if (error) {
 1072                         SCTP_INP_DECR_REF(stcb->sctp_ep);
 1073                         return;
 1074                 }
 1075                 SCTP_TCB_LOCK_ASSERT(stcb);
 1076 #ifdef SCTP_AUDITING_ENABLED
 1077                 sctp_auditing(4, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary);
 1078 #endif
 1079                 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
 1080                 if ((stcb->asoc.num_send_timers_up == 0) &&
 1081                     (stcb->asoc.sent_queue_cnt > 0)) {
 1082                         struct sctp_tmit_chunk *chk;
 1083 
 1084                         chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
 1085                         sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
 1086                             stcb, chk->whoTo);
 1087                 }
 1088         }
 1089         return;
 1090 }
 1091 
 1092 static int
 1093     sctp_asconf_queue_mgmt(struct sctp_tcb *, struct sctp_ifa *, uint16_t);
 1094 
 1095 void
 1096 sctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net)
 1097 {
 1098         struct sctp_tmit_chunk *chk;
 1099 
 1100         SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO);
 1101         sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net,
 1102             SCTP_FROM_SCTP_TIMER + SCTP_LOC_5);
 1103         stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
 1104         net->error_count = 0;
 1105         TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
 1106                 if (chk->whoTo == net) {
 1107                         if (chk->sent < SCTP_DATAGRAM_RESEND) {
 1108                                 chk->sent = SCTP_DATAGRAM_RESEND;
 1109                                 sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
 1110                                 sctp_flight_size_decrease(chk);
 1111                                 sctp_total_flight_decrease(stcb, chk);
 1112                                 net->marked_retrans++;
 1113                                 stcb->asoc.marked_retrans++;
 1114                         }
 1115                 }
 1116         }
 1117         if (net->marked_retrans) {
 1118                 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
 1119         }
 1120 }
 1121 
 1122 static void
 1123 sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
 1124 {
 1125         struct sctp_nets *net;
 1126         int addrnum, changed;
 1127 
 1128         /*
 1129          * If number of local valid addresses is 1, the valid address is
 1130          * probably newly added address. Several valid addresses in this
 1131          * association.  A source address may not be changed.  Additionally,
 1132          * they can be configured on a same interface as "alias" addresses.
 1133          * (by micchie)
 1134          */
 1135         addrnum = sctp_local_addr_count(stcb);
 1136         SCTPDBG(SCTP_DEBUG_ASCONF1, "p_check_react(): %d local addresses\n",
 1137             addrnum);
 1138         if (addrnum == 1) {
 1139                 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1140                         /* clear any cached route and source address */
 1141                         if (net->ro.ro_rt) {
 1142                                 RTFREE(net->ro.ro_rt);
 1143                                 net->ro.ro_rt = NULL;
 1144                         }
 1145                         if (net->src_addr_selected) {
 1146                                 sctp_free_ifa(net->ro._s_addr);
 1147                                 net->ro._s_addr = NULL;
 1148                                 net->src_addr_selected = 0;
 1149                         }
 1150                         /* Retransmit unacknowledged DATA chunks immediately */
 1151                         if (sctp_is_mobility_feature_on(stcb->sctp_ep,
 1152                             SCTP_MOBILITY_FASTHANDOFF)) {
 1153                                 sctp_net_immediate_retrans(stcb, net);
 1154                         }
 1155                         /* also, SET PRIMARY is maybe already sent */
 1156                 }
 1157                 return;
 1158         }
 1159         /* Multiple local addresses exsist in the association.  */
 1160         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1161                 /* clear any cached route and source address */
 1162                 if (net->ro.ro_rt) {
 1163                         RTFREE(net->ro.ro_rt);
 1164                         net->ro.ro_rt = NULL;
 1165                 }
 1166                 if (net->src_addr_selected) {
 1167                         sctp_free_ifa(net->ro._s_addr);
 1168                         net->ro._s_addr = NULL;
 1169                         net->src_addr_selected = 0;
 1170                 }
 1171                 /*
 1172                  * Check if the nexthop is corresponding to the new address.
 1173                  * If the new address is corresponding to the current
 1174                  * nexthop, the path will be changed. If the new address is
 1175                  * NOT corresponding to the current nexthop, the path will
 1176                  * not be changed.
 1177                  */
 1178                 SCTP_RTALLOC((sctp_route_t *) & net->ro,
 1179                     stcb->sctp_ep->def_vrf_id);
 1180                 if (net->ro.ro_rt == NULL)
 1181                         continue;
 1182 
 1183                 changed = 0;
 1184                 if (net->ro._l_addr.sa.sa_family == AF_INET) {
 1185                         if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *) & net->ro))
 1186                                 changed = 1;
 1187                 }
 1188 #ifdef INET6
 1189                 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
 1190                         if (sctp_v6src_match_nexthop(
 1191                             &newifa->address.sin6, (sctp_route_t *) & net->ro))
 1192                                 changed = 1;
 1193                 }
 1194 #endif
 1195                 /*
 1196                  * if the newly added address does not relate routing
 1197                  * information, we skip.
 1198                  */
 1199                 if (changed == 0)
 1200                         continue;
 1201                 /* Retransmit unacknowledged DATA chunks immediately */
 1202                 if (sctp_is_mobility_feature_on(stcb->sctp_ep,
 1203                     SCTP_MOBILITY_FASTHANDOFF)) {
 1204                         sctp_net_immediate_retrans(stcb, net);
 1205                 }
 1206                 /* Send SET PRIMARY for this new address */
 1207                 if (net == stcb->asoc.primary_destination) {
 1208                         (void)sctp_asconf_queue_mgmt(stcb, newifa,
 1209                             SCTP_SET_PRIM_ADDR);
 1210                 }
 1211         }
 1212 }
 1213 
 1214 /*
 1215  * process an ADD/DELETE IP ack from peer.
 1216  * addr: corresponding sctp_ifa to the address being added/deleted.
 1217  * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS.
 1218  * flag: 1=success, 0=failure.
 1219  */
 1220 static void
 1221 sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr,
 1222     uint16_t type, uint32_t flag)
 1223 {
 1224         /*
 1225          * do the necessary asoc list work- if we get a failure indication,
 1226          * leave the address on the assoc's restricted list.  If we get a
 1227          * success indication, remove the address from the restricted list.
 1228          */
 1229         /*
 1230          * Note: this will only occur for ADD_IP_ADDRESS, since
 1231          * DEL_IP_ADDRESS is never actually added to the list...
 1232          */
 1233         if (flag) {
 1234                 /* success case, so remove from the restricted list */
 1235                 sctp_del_local_addr_restricted(stcb, addr);
 1236 
 1237                 if (sctp_is_mobility_feature_on(stcb->sctp_ep,
 1238                     SCTP_MOBILITY_BASE) ||
 1239                     sctp_is_mobility_feature_on(stcb->sctp_ep,
 1240                     SCTP_MOBILITY_FASTHANDOFF)) {
 1241                         sctp_path_check_and_react(stcb, addr);
 1242                         return;
 1243                 }
 1244                 /* clear any cached/topologically incorrect source addresses */
 1245                 sctp_asconf_nets_cleanup(stcb, addr->ifn_p);
 1246         }
 1247         /* else, leave it on the list */
 1248 }
 1249 
 1250 /*
 1251  * add an asconf add/delete/set primary IP address parameter to the queue.
 1252  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
 1253  * returns 0 if queued, -1 if not queued/removed.
 1254  * NOTE: if adding, but a delete for the same address is already scheduled
 1255  * (and not yet sent out), simply remove it from queue.  Same for deleting
 1256  * an address already scheduled for add.  If a duplicate operation is found,
 1257  * ignore the new one.
 1258  */
 1259 static int
 1260 sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
 1261     uint16_t type)
 1262 {
 1263         struct sctp_asconf_addr *aa, *aa_next;
 1264         struct sockaddr *sa;
 1265 
 1266         /* make sure the request isn't already in the queue */
 1267         for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
 1268             aa = aa_next) {
 1269                 aa_next = TAILQ_NEXT(aa, next);
 1270                 /* address match? */
 1271                 if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0)
 1272                         continue;
 1273                 /*
 1274                  * is the request already in queue but not sent? pass the
 1275                  * request already sent in order to resolve the following
 1276                  * case: 1. arrival of ADD, then sent 2. arrival of DEL. we
 1277                  * can't remove the ADD request already sent 3. arrival of
 1278                  * ADD
 1279                  */
 1280                 if (aa->ap.aph.ph.param_type == type && aa->sent == 0) {
 1281                         return (-1);
 1282                 }
 1283                 /* is the negative request already in queue, and not sent */
 1284                 if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) &&
 1285                     (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) {
 1286                         /* add requested, delete already queued */
 1287                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1288                         /* remove the ifa from the restricted list */
 1289                         sctp_del_local_addr_restricted(stcb, ifa);
 1290                         /* free the asconf param */
 1291                         SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1292                         SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n");
 1293                         return (-1);
 1294                 }
 1295                 if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) &&
 1296                     (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) {
 1297                         /* delete requested, add already queued */
 1298                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1299                         /* remove the aa->ifa from the restricted list */
 1300                         sctp_del_local_addr_restricted(stcb, aa->ifa);
 1301                         /* free the asconf param */
 1302                         SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1303                         SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n");
 1304                         return (-1);
 1305                 }
 1306         }                       /* for each aa */
 1307 
 1308         /* adding new request to the queue */
 1309         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 1310             SCTP_M_ASC_ADDR);
 1311         if (aa == NULL) {
 1312                 /* didn't get memory */
 1313                 SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n");
 1314                 return (-1);
 1315         }
 1316         aa->special_del = 0;
 1317         /* fill in asconf address parameter fields */
 1318         /* top level elements are "networked" during send */
 1319         aa->ap.aph.ph.param_type = type;
 1320         aa->ifa = ifa;
 1321         atomic_add_int(&ifa->refcount, 1);
 1322         /* correlation_id filled in during send routine later... */
 1323         if (ifa->address.sa.sa_family == AF_INET6) {
 1324                 /* IPv6 address */
 1325                 struct sockaddr_in6 *sin6;
 1326 
 1327                 sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
 1328                 sa = (struct sockaddr *)sin6;
 1329                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 1330                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
 1331                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
 1332                     sizeof(struct sctp_ipv6addr_param);
 1333                 memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
 1334                     sizeof(struct in6_addr));
 1335         } else if (ifa->address.sa.sa_family == AF_INET) {
 1336                 /* IPv4 address */
 1337                 struct sockaddr_in *sin;
 1338 
 1339                 sin = (struct sockaddr_in *)&ifa->address.sa;
 1340                 sa = (struct sockaddr *)sin;
 1341                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 1342                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
 1343                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
 1344                     sizeof(struct sctp_ipv4addr_param);
 1345                 memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
 1346                     sizeof(struct in_addr));
 1347         } else {
 1348                 /* invalid family! */
 1349                 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1350                 sctp_free_ifa(ifa);
 1351                 return (-1);
 1352         }
 1353         aa->sent = 0;           /* clear sent flag */
 1354 
 1355         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 1356 #ifdef SCTP_DEBUG
 1357         if (SCTP_BASE_SYSCTL(sctp_debug_on) && SCTP_DEBUG_ASCONF2) {
 1358                 if (type == SCTP_ADD_IP_ADDRESS) {
 1359                         SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: ");
 1360                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 1361                 } else if (type == SCTP_DEL_IP_ADDRESS) {
 1362                         SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: ");
 1363                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 1364                 } else {
 1365                         SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: ");
 1366                         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 1367                 }
 1368         }
 1369 #endif
 1370 
 1371         return (0);
 1372 }
 1373 
 1374 
 1375 /*
 1376  * add an asconf operation for the given ifa and type.
 1377  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
 1378  * returns 0 if completed, -1 if not completed, 1 if immediate send is
 1379  * advisable.
 1380  */
 1381 static int
 1382 sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
 1383     uint16_t type)
 1384 {
 1385         uint32_t status;
 1386         int pending_delete_queued = 0;
 1387 
 1388         /* see if peer supports ASCONF */
 1389         if (stcb->asoc.peer_supports_asconf == 0) {
 1390                 return (-1);
 1391         }
 1392         /*
 1393          * if this is deleting the last address from the assoc, mark it as
 1394          * pending.
 1395          */
 1396         if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending &&
 1397             (sctp_local_addr_count(stcb) < 2)) {
 1398                 /* set the pending delete info only */
 1399                 stcb->asoc.asconf_del_pending = 1;
 1400                 stcb->asoc.asconf_addr_del_pending = ifa;
 1401                 atomic_add_int(&ifa->refcount, 1);
 1402                 SCTPDBG(SCTP_DEBUG_ASCONF2,
 1403                     "asconf_queue_add: mark delete last address pending\n");
 1404                 return (-1);
 1405         }
 1406         /* queue an asconf parameter */
 1407         status = sctp_asconf_queue_mgmt(stcb, ifa, type);
 1408 
 1409         /*
 1410          * if this is an add, and there is a delete also pending (i.e. the
 1411          * last local address is being changed), queue the pending delete
 1412          * too.
 1413          */
 1414         if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) {
 1415                 /* queue in the pending delete */
 1416                 if (sctp_asconf_queue_mgmt(stcb,
 1417                     stcb->asoc.asconf_addr_del_pending,
 1418                     SCTP_DEL_IP_ADDRESS) == 0) {
 1419                         SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n");
 1420                         pending_delete_queued = 1;
 1421                         /* clear out the pending delete info */
 1422                         stcb->asoc.asconf_del_pending = 0;
 1423                         sctp_free_ifa(stcb->asoc.asconf_addr_del_pending);
 1424                         stcb->asoc.asconf_addr_del_pending = NULL;
 1425                 }
 1426         }
 1427         if (pending_delete_queued) {
 1428                 struct sctp_nets *net;
 1429 
 1430                 /*
 1431                  * since we know that the only/last address is now being
 1432                  * changed in this case, reset the cwnd/rto on all nets to
 1433                  * start as a new address and path.  Also clear the error
 1434                  * counts to give the assoc the best chance to complete the
 1435                  * address change.
 1436                  */
 1437                 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1438                         stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb,
 1439                             net);
 1440                         net->RTO = 0;
 1441                         net->error_count = 0;
 1442                 }
 1443                 stcb->asoc.overall_error_count = 0;
 1444                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
 1445                         sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
 1446                             stcb->asoc.overall_error_count,
 1447                             0,
 1448                             SCTP_FROM_SCTP_ASCONF,
 1449                             __LINE__);
 1450                 }
 1451                 /* queue in an advisory set primary too */
 1452                 (void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR);
 1453                 /* let caller know we should send this out immediately */
 1454                 status = 1;
 1455         }
 1456         return (status);
 1457 }
 1458 
 1459 /*-
 1460  * add an asconf delete IP address parameter to the queue by sockaddr and
 1461  * possibly with no sctp_ifa available.  This is only called by the routine
 1462  * that checks the addresses in an INIT-ACK against the current address list.
 1463  * returns 0 if completed, non-zero if not completed.
 1464  * NOTE: if an add is already scheduled (and not yet sent out), simply
 1465  * remove it from queue.  If a duplicate operation is found, ignore the
 1466  * new one.
 1467  */
 1468 static int
 1469 sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
 1470 {
 1471         struct sctp_ifa *ifa;
 1472         struct sctp_asconf_addr *aa, *aa_next;
 1473         uint32_t vrf_id;
 1474 
 1475         if (stcb == NULL) {
 1476                 return (-1);
 1477         }
 1478         /* see if peer supports ASCONF */
 1479         if (stcb->asoc.peer_supports_asconf == 0) {
 1480                 return (-1);
 1481         }
 1482         /* make sure the request isn't already in the queue */
 1483         for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
 1484             aa = aa_next) {
 1485                 aa_next = TAILQ_NEXT(aa, next);
 1486                 /* address match? */
 1487                 if (sctp_asconf_addr_match(aa, sa) == 0)
 1488                         continue;
 1489                 /* is the request already in queue (sent or not) */
 1490                 if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
 1491                         return (-1);
 1492                 }
 1493                 /* is the negative request already in queue, and not sent */
 1494                 if (aa->sent == 1)
 1495                         continue;
 1496                 if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) {
 1497                         /* add already queued, so remove existing entry */
 1498                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
 1499                         sctp_del_local_addr_restricted(stcb, aa->ifa);
 1500                         /* free the entry */
 1501                         SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1502                         return (-1);
 1503                 }
 1504         }                       /* for each aa */
 1505 
 1506         /* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */
 1507         if (stcb) {
 1508                 vrf_id = stcb->asoc.vrf_id;
 1509         } else {
 1510                 vrf_id = SCTP_DEFAULT_VRFID;
 1511         }
 1512         ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 1513 
 1514         /* adding new request to the queue */
 1515         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 1516             SCTP_M_ASC_ADDR);
 1517         if (aa == NULL) {
 1518                 /* didn't get memory */
 1519                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1520                     "sctp_asconf_queue_sa_delete: failed to get memory!\n");
 1521                 return (-1);
 1522         }
 1523         aa->special_del = 0;
 1524         /* fill in asconf address parameter fields */
 1525         /* top level elements are "networked" during send */
 1526         aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
 1527         aa->ifa = ifa;
 1528         if (ifa)
 1529                 atomic_add_int(&ifa->refcount, 1);
 1530         /* correlation_id filled in during send routine later... */
 1531         if (sa->sa_family == AF_INET6) {
 1532                 /* IPv6 address */
 1533                 struct sockaddr_in6 *sin6;
 1534 
 1535                 sin6 = (struct sockaddr_in6 *)sa;
 1536                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 1537                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
 1538                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
 1539                 memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
 1540                     sizeof(struct in6_addr));
 1541         } else if (sa->sa_family == AF_INET) {
 1542                 /* IPv4 address */
 1543                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
 1544 
 1545                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 1546                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
 1547                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
 1548                 memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
 1549                     sizeof(struct in_addr));
 1550         } else {
 1551                 /* invalid family! */
 1552                 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 1553                 if (ifa)
 1554                         sctp_free_ifa(ifa);
 1555                 return (-1);
 1556         }
 1557         aa->sent = 0;           /* clear sent flag */
 1558 
 1559         /* delete goes to the back of the queue */
 1560         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 1561 
 1562         /* sa_ignore MEMLEAK {memory is put on the tailq} */
 1563         return (0);
 1564 }
 1565 
 1566 /*
 1567  * find a specific asconf param on our "sent" queue
 1568  */
 1569 static struct sctp_asconf_addr *
 1570 sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
 1571 {
 1572         struct sctp_asconf_addr *aa;
 1573 
 1574         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 1575                 if (aa->ap.aph.correlation_id == correlation_id &&
 1576                     aa->sent == 1) {
 1577                         /* found it */
 1578                         return (aa);
 1579                 }
 1580         }
 1581         /* didn't find it */
 1582         return (NULL);
 1583 }
 1584 
 1585 /*
 1586  * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do
 1587  * notifications based on the error response
 1588  */
 1589 static void
 1590 sctp_asconf_process_error(struct sctp_tcb *stcb,
 1591     struct sctp_asconf_paramhdr *aph)
 1592 {
 1593         struct sctp_error_cause *eh;
 1594         struct sctp_paramhdr *ph;
 1595         uint16_t param_type;
 1596         uint16_t error_code;
 1597 
 1598         eh = (struct sctp_error_cause *)(aph + 1);
 1599         ph = (struct sctp_paramhdr *)(eh + 1);
 1600         /* validate lengths */
 1601         if (htons(eh->length) + sizeof(struct sctp_error_cause) >
 1602             htons(aph->ph.param_length)) {
 1603                 /* invalid error cause length */
 1604                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1605                     "asconf_process_error: cause element too long\n");
 1606                 return;
 1607         }
 1608         if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) >
 1609             htons(eh->length)) {
 1610                 /* invalid included TLV length */
 1611                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1612                     "asconf_process_error: included TLV too long\n");
 1613                 return;
 1614         }
 1615         /* which error code ? */
 1616         error_code = ntohs(eh->code);
 1617         param_type = ntohs(aph->ph.param_type);
 1618         /* FIX: this should go back up the REMOTE_ERROR ULP notify */
 1619         switch (error_code) {
 1620         case SCTP_CAUSE_RESOURCE_SHORTAGE:
 1621                 /* we allow ourselves to "try again" for this error */
 1622                 break;
 1623         default:
 1624                 /* peer can't handle it... */
 1625                 switch (param_type) {
 1626                 case SCTP_ADD_IP_ADDRESS:
 1627                 case SCTP_DEL_IP_ADDRESS:
 1628                         stcb->asoc.peer_supports_asconf = 0;
 1629                         break;
 1630                 case SCTP_SET_PRIM_ADDR:
 1631                         stcb->asoc.peer_supports_asconf = 0;
 1632                         break;
 1633                 default:
 1634                         break;
 1635                 }
 1636         }
 1637 }
 1638 
 1639 /*
 1640  * process an asconf queue param.
 1641  * aparam: parameter to process, will be removed from the queue.
 1642  * flag: 1=success case, 0=failure case
 1643  */
 1644 static void
 1645 sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
 1646     struct sctp_asconf_addr *aparam, uint32_t flag)
 1647 {
 1648         uint16_t param_type;
 1649 
 1650         /* process this param */
 1651         param_type = aparam->ap.aph.ph.param_type;
 1652         switch (param_type) {
 1653         case SCTP_ADD_IP_ADDRESS:
 1654                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1655                     "process_param_ack: added IP address\n");
 1656                 sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, param_type, flag);
 1657                 break;
 1658         case SCTP_DEL_IP_ADDRESS:
 1659                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1660                     "process_param_ack: deleted IP address\n");
 1661                 /* nothing really to do... lists already updated */
 1662                 break;
 1663         case SCTP_SET_PRIM_ADDR:
 1664                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1665                     "process_param_ack: set primary IP address\n");
 1666                 /* nothing to do... peer may start using this addr */
 1667                 if (flag == 0)
 1668                         stcb->asoc.peer_supports_asconf = 0;
 1669                 break;
 1670         default:
 1671                 /* should NEVER happen */
 1672                 break;
 1673         }
 1674 
 1675         /* remove the param and free it */
 1676         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
 1677         if (aparam->ifa)
 1678                 sctp_free_ifa(aparam->ifa);
 1679         SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
 1680 }
 1681 
 1682 /*
 1683  * cleanup from a bad asconf ack parameter
 1684  */
 1685 static void
 1686 sctp_asconf_ack_clear(struct sctp_tcb *stcb)
 1687 {
 1688         /* assume peer doesn't really know how to do asconfs */
 1689         stcb->asoc.peer_supports_asconf = 0;
 1690         /* XXX we could free the pending queue here */
 1691 }
 1692 
 1693 void
 1694 sctp_handle_asconf_ack(struct mbuf *m, int offset,
 1695     struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb,
 1696     struct sctp_nets *net, int *abort_no_unlock)
 1697 {
 1698         struct sctp_association *asoc;
 1699         uint32_t serial_num;
 1700         uint16_t ack_length;
 1701         struct sctp_asconf_paramhdr *aph;
 1702         struct sctp_asconf_addr *aa, *aa_next;
 1703         uint32_t last_error_id = 0;     /* last error correlation id */
 1704         uint32_t id;
 1705         struct sctp_asconf_addr *ap;
 1706 
 1707         /* asconf param buffer */
 1708         uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
 1709 
 1710         /* verify minimum length */
 1711         if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) {
 1712                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 1713                     "handle_asconf_ack: chunk too small = %xh\n",
 1714                     ntohs(cp->ch.chunk_length));
 1715                 return;
 1716         }
 1717         asoc = &stcb->asoc;
 1718         serial_num = ntohl(cp->serial_number);
 1719 
 1720         /*
 1721          * NOTE: we may want to handle this differently- currently, we will
 1722          * abort when we get an ack for the expected serial number + 1 (eg.
 1723          * we didn't send it), process an ack normally if it is the expected
 1724          * serial number, and re-send the previous ack for *ALL* other
 1725          * serial numbers
 1726          */
 1727 
 1728         /*
 1729          * if the serial number is the next expected, but I didn't send it,
 1730          * abort the asoc, since someone probably just hijacked us...
 1731          */
 1732         if (serial_num == (asoc->asconf_seq_out + 1)) {
 1733                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
 1734                 sctp_abort_an_association(stcb->sctp_ep, stcb,
 1735                     SCTP_CAUSE_ILLEGAL_ASCONF_ACK, NULL, SCTP_SO_NOT_LOCKED);
 1736                 *abort_no_unlock = 1;
 1737                 return;
 1738         }
 1739         if (serial_num != asoc->asconf_seq_out_acked + 1) {
 1740                 /* got a duplicate/unexpected ASCONF-ACK */
 1741                 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n",
 1742                     serial_num, asoc->asconf_seq_out_acked + 1);
 1743                 return;
 1744         }
 1745         if (serial_num == asoc->asconf_seq_out - 1) {
 1746                 /* stop our timer */
 1747                 sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
 1748                     SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3);
 1749         }
 1750         /* process the ASCONF-ACK contents */
 1751         ack_length = ntohs(cp->ch.chunk_length) -
 1752             sizeof(struct sctp_asconf_ack_chunk);
 1753         offset += sizeof(struct sctp_asconf_ack_chunk);
 1754         /* process through all parameters */
 1755         while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) {
 1756                 unsigned int param_length, param_type;
 1757 
 1758                 /* get pointer to next asconf parameter */
 1759                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
 1760                     sizeof(struct sctp_asconf_paramhdr), aparam_buf);
 1761                 if (aph == NULL) {
 1762                         /* can't get an asconf paramhdr */
 1763                         sctp_asconf_ack_clear(stcb);
 1764                         return;
 1765                 }
 1766                 param_type = ntohs(aph->ph.param_type);
 1767                 param_length = ntohs(aph->ph.param_length);
 1768                 if (param_length > ack_length) {
 1769                         sctp_asconf_ack_clear(stcb);
 1770                         return;
 1771                 }
 1772                 if (param_length < sizeof(struct sctp_paramhdr)) {
 1773                         sctp_asconf_ack_clear(stcb);
 1774                         return;
 1775                 }
 1776                 /* get the complete parameter... */
 1777                 if (param_length > sizeof(aparam_buf)) {
 1778                         SCTPDBG(SCTP_DEBUG_ASCONF1,
 1779                             "param length (%u) larger than buffer size!\n", param_length);
 1780                         sctp_asconf_ack_clear(stcb);
 1781                         return;
 1782                 }
 1783                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
 1784                 if (aph == NULL) {
 1785                         sctp_asconf_ack_clear(stcb);
 1786                         return;
 1787                 }
 1788                 /* correlation_id is transparent to peer, no ntohl needed */
 1789                 id = aph->correlation_id;
 1790 
 1791                 switch (param_type) {
 1792                 case SCTP_ERROR_CAUSE_IND:
 1793                         last_error_id = id;
 1794                         /* find the corresponding asconf param in our queue */
 1795                         ap = sctp_asconf_find_param(stcb, id);
 1796                         if (ap == NULL) {
 1797                                 /* hmm... can't find this in our queue! */
 1798                                 break;
 1799                         }
 1800                         /* process the parameter, failed flag */
 1801                         sctp_asconf_process_param_ack(stcb, ap, 0);
 1802                         /* process the error response */
 1803                         sctp_asconf_process_error(stcb, aph);
 1804                         break;
 1805                 case SCTP_SUCCESS_REPORT:
 1806                         /* find the corresponding asconf param in our queue */
 1807                         ap = sctp_asconf_find_param(stcb, id);
 1808                         if (ap == NULL) {
 1809                                 /* hmm... can't find this in our queue! */
 1810                                 break;
 1811                         }
 1812                         /* process the parameter, success flag */
 1813                         sctp_asconf_process_param_ack(stcb, ap, 1);
 1814                         break;
 1815                 default:
 1816                         break;
 1817                 }               /* switch */
 1818 
 1819                 /* update remaining ASCONF-ACK message length to process */
 1820                 ack_length -= SCTP_SIZE32(param_length);
 1821                 if (ack_length <= 0) {
 1822                         /* no more data in the mbuf chain */
 1823                         break;
 1824                 }
 1825                 offset += SCTP_SIZE32(param_length);
 1826         }                       /* while */
 1827 
 1828         /*
 1829          * if there are any "sent" params still on the queue, these are
 1830          * implicitly "success", or "failed" (if we got an error back) ...
 1831          * so process these appropriately
 1832          * 
 1833          * we assume that the correlation_id's are monotonically increasing
 1834          * beginning from 1 and that we don't have *that* many outstanding
 1835          * at any given time
 1836          */
 1837         if (last_error_id == 0)
 1838                 last_error_id--;/* set to "max" value */
 1839         for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
 1840             aa = aa_next) {
 1841                 aa_next = TAILQ_NEXT(aa, next);
 1842                 if (aa->sent == 1) {
 1843                         /*
 1844                          * implicitly successful or failed if correlation_id
 1845                          * < last_error_id, then success else, failure
 1846                          */
 1847                         if (aa->ap.aph.correlation_id < last_error_id)
 1848                                 sctp_asconf_process_param_ack(stcb, aa, 1);
 1849                         else
 1850                                 sctp_asconf_process_param_ack(stcb, aa, 0);
 1851                 } else {
 1852                         /*
 1853                          * since we always process in order (FIFO queue) if
 1854                          * we reach one that hasn't been sent, the rest
 1855                          * should not have been sent either. so, we're
 1856                          * done...
 1857                          */
 1858                         break;
 1859                 }
 1860         }
 1861 
 1862         /* update the next sequence number to use */
 1863         asoc->asconf_seq_out_acked++;
 1864         /* remove the old ASCONF on our outbound queue */
 1865         sctp_toss_old_asconf(stcb);
 1866         if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
 1867 #ifdef SCTP_TIMER_BASED_ASCONF
 1868                 /* we have more params, so restart our timer */
 1869                 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep,
 1870                     stcb, net);
 1871 #else
 1872                 /* we have more params, so send out more */
 1873                 sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
 1874 #endif
 1875         }
 1876 }
 1877 
 1878 #ifdef INET6
 1879 static uint32_t
 1880 sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa)
 1881 {
 1882         struct sockaddr_in6 *sin6, *net6;
 1883         struct sctp_nets *net;
 1884 
 1885         if (sa->sa_family != AF_INET6) {
 1886                 /* wrong family */
 1887                 return (0);
 1888         }
 1889         sin6 = (struct sockaddr_in6 *)sa;
 1890         if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) {
 1891                 /* not link local address */
 1892                 return (0);
 1893         }
 1894         /* hunt through our destination nets list for this scope_id */
 1895         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 1896                 if (((struct sockaddr *)(&net->ro._l_addr))->sa_family !=
 1897                     AF_INET6)
 1898                         continue;
 1899                 net6 = (struct sockaddr_in6 *)&net->ro._l_addr;
 1900                 if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0)
 1901                         continue;
 1902                 if (sctp_is_same_scope(sin6, net6)) {
 1903                         /* found one */
 1904                         return (1);
 1905                 }
 1906         }
 1907         /* didn't find one */
 1908         return (0);
 1909 }
 1910 
 1911 #endif
 1912 
 1913 /*
 1914  * address management functions
 1915  */
 1916 static void
 1917 sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
 1918     struct sctp_ifa *ifa, uint16_t type, int addr_locked)
 1919 {
 1920         int status;
 1921 
 1922 
 1923         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 &&
 1924             sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
 1925                 /* subset bound, no ASCONF allowed case, so ignore */
 1926                 return;
 1927         }
 1928         /*
 1929          * note: we know this is not the subset bound, no ASCONF case eg.
 1930          * this is boundall or subset bound w/ASCONF allowed
 1931          */
 1932 
 1933         /* first, make sure it's a good address family */
 1934         if (ifa->address.sa.sa_family != AF_INET6 &&
 1935             ifa->address.sa.sa_family != AF_INET) {
 1936                 return;
 1937         }
 1938         /* make sure we're "allowed" to add this type of addr */
 1939         if (ifa->address.sa.sa_family == AF_INET6) {
 1940                 /* invalid if we're not a v6 endpoint */
 1941                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)
 1942                         return;
 1943                 /* is the v6 addr really valid ? */
 1944                 if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
 1945                         return;
 1946                 }
 1947         }
 1948         /* put this address on the "pending/do not use yet" list */
 1949         sctp_add_local_addr_restricted(stcb, ifa);
 1950         /*
 1951          * check address scope if address is out of scope, don't queue
 1952          * anything... note: this would leave the address on both inp and
 1953          * asoc lists
 1954          */
 1955         switch (ifa->address.sa.sa_family) {
 1956 #ifdef INET6
 1957         case AF_INET6:
 1958                 {
 1959                         struct sockaddr_in6 *sin6;
 1960 
 1961                         sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
 1962                         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 1963                                 /* we skip unspecifed addresses */
 1964                                 return;
 1965                         }
 1966                         if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 1967                                 if (stcb->asoc.local_scope == 0) {
 1968                                         return;
 1969                                 }
 1970                                 /* is it the right link local scope? */
 1971                                 if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
 1972                                         return;
 1973                                 }
 1974                         }
 1975                         if (stcb->asoc.site_scope == 0 &&
 1976                             IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
 1977                                 return;
 1978                         }
 1979                         break;
 1980                 }
 1981 #endif
 1982         case AF_INET:
 1983                 {
 1984                         struct sockaddr_in *sin;
 1985                         struct in6pcb *inp6;
 1986 
 1987                         inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 1988                         /* invalid if we are a v6 only endpoint */
 1989                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 1990                             SCTP_IPV6_V6ONLY(inp6))
 1991                                 return;
 1992 
 1993                         sin = (struct sockaddr_in *)&ifa->address.sa;
 1994                         if (sin->sin_addr.s_addr == 0) {
 1995                                 /* we skip unspecifed addresses */
 1996                                 return;
 1997                         }
 1998                         if (stcb->asoc.ipv4_local_scope == 0 &&
 1999                             IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
 2000                                 return;
 2001                         }
 2002                         break;
 2003                 }
 2004         default:
 2005                 /* else, not AF_INET or AF_INET6, so skip */
 2006                 return;
 2007         }
 2008 
 2009         /* queue an asconf for this address add/delete */
 2010         if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
 2011                 /* does the peer do asconf? */
 2012                 if (stcb->asoc.peer_supports_asconf) {
 2013                         /* queue an asconf for this addr */
 2014                         status = sctp_asconf_queue_add(stcb, ifa, type);
 2015 
 2016                         /*
 2017                          * if queued ok, and in the open state, send out the
 2018                          * ASCONF.  If in the non-open state, these will be
 2019                          * sent when the state goes open.
 2020                          */
 2021                         if (status == 0 &&
 2022                             SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2023 #ifdef SCTP_TIMER_BASED_ASCONF
 2024                                 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
 2025                                     stcb, stcb->asoc.primary_destination);
 2026 #else
 2027                                 sctp_send_asconf(stcb, stcb->asoc.primary_destination,
 2028                                     addr_locked);
 2029 #endif
 2030                         }
 2031                 }
 2032         }
 2033 }
 2034 
 2035 
 2036 int
 2037 sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val)
 2038 {
 2039         struct sctp_asconf_iterator *asc;
 2040         struct sctp_ifa *ifa;
 2041         struct sctp_laddr *l;
 2042         int cnt_invalid = 0;
 2043 
 2044         asc = (struct sctp_asconf_iterator *)ptr;
 2045         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
 2046                 ifa = l->ifa;
 2047                 if (ifa->address.sa.sa_family == AF_INET6) {
 2048                         /* invalid if we're not a v6 endpoint */
 2049                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
 2050                                 cnt_invalid++;
 2051                                 if (asc->cnt == cnt_invalid)
 2052                                         return (1);
 2053                                 else
 2054                                         continue;
 2055                         }
 2056                 } else if (ifa->address.sa.sa_family == AF_INET) {
 2057                         /* invalid if we are a v6 only endpoint */
 2058                         struct in6pcb *inp6;
 2059 
 2060                         inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 2061                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2062                             SCTP_IPV6_V6ONLY(inp6)) {
 2063                                 cnt_invalid++;
 2064                                 if (asc->cnt == cnt_invalid)
 2065                                         return (1);
 2066                                 else
 2067                                         continue;
 2068                         }
 2069                 } else {
 2070                         /* invalid address family */
 2071                         cnt_invalid++;
 2072                         if (asc->cnt == cnt_invalid)
 2073                                 return (1);
 2074                         else
 2075                                 continue;
 2076                 }
 2077         }
 2078         return (0);
 2079 }
 2080 
 2081 static int
 2082 sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val)
 2083 {
 2084         struct sctp_ifa *ifa;
 2085         struct sctp_asconf_iterator *asc;
 2086         struct sctp_laddr *laddr, *nladdr, *l;
 2087 
 2088         /* Only for specific case not bound all */
 2089         asc = (struct sctp_asconf_iterator *)ptr;
 2090         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
 2091                 ifa = l->ifa;
 2092                 if (l->action == SCTP_ADD_IP_ADDRESS) {
 2093                         LIST_FOREACH(laddr, &inp->sctp_addr_list,
 2094                             sctp_nxt_addr) {
 2095                                 if (laddr->ifa == ifa) {
 2096                                         laddr->action = 0;
 2097                                         break;
 2098                                 }
 2099                         }
 2100                 } else if (l->action == SCTP_DEL_IP_ADDRESS) {
 2101                         laddr = LIST_FIRST(&inp->sctp_addr_list);
 2102                         while (laddr) {
 2103                                 nladdr = LIST_NEXT(laddr, sctp_nxt_addr);
 2104                                 /* remove only after all guys are done */
 2105                                 if (laddr->ifa == ifa) {
 2106                                         sctp_del_local_addr_ep(inp, ifa);
 2107                                 }
 2108                                 laddr = nladdr;
 2109                         }
 2110                 }
 2111         }
 2112         return (0);
 2113 }
 2114 
 2115 void
 2116 sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
 2117     void *ptr, uint32_t val)
 2118 {
 2119         struct sctp_asconf_iterator *asc;
 2120         struct sctp_ifa *ifa;
 2121         struct sctp_laddr *l;
 2122         int cnt_invalid = 0;
 2123         int type, status;
 2124         int num_queued = 0;
 2125 
 2126         asc = (struct sctp_asconf_iterator *)ptr;
 2127         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
 2128                 ifa = l->ifa;
 2129                 type = l->action;
 2130 
 2131                 /* address's vrf_id must be the vrf_id of the assoc */
 2132                 if (ifa->vrf_id != stcb->asoc.vrf_id) {
 2133                         continue;
 2134                 }
 2135                 /* Same checks again for assoc */
 2136                 switch (ifa->address.sa.sa_family) {
 2137 #ifdef INET6
 2138                 case AF_INET6:
 2139                         {
 2140                                 /* invalid if we're not a v6 endpoint */
 2141                                 struct sockaddr_in6 *sin6;
 2142 
 2143                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
 2144                                         cnt_invalid++;
 2145                                         if (asc->cnt == cnt_invalid)
 2146                                                 return;
 2147                                         else
 2148                                                 continue;
 2149                                 }
 2150                                 sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
 2151                                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 2152                                         /* we skip unspecifed addresses */
 2153                                         continue;
 2154                                 }
 2155                                 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 2156                                         if (stcb->asoc.local_scope == 0) {
 2157                                                 continue;
 2158                                         }
 2159                                         /* is it the right link local scope? */
 2160                                         if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
 2161                                                 continue;
 2162                                         }
 2163                                 }
 2164                                 break;
 2165                         }
 2166 #endif
 2167                 case AF_INET:
 2168                         {
 2169                                 /* invalid if we are a v6 only endpoint */
 2170                                 struct in6pcb *inp6;
 2171                                 struct sockaddr_in *sin;
 2172 
 2173                                 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 2174                                 /* invalid if we are a v6 only endpoint */
 2175                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2176                                     SCTP_IPV6_V6ONLY(inp6))
 2177                                         continue;
 2178 
 2179                                 sin = (struct sockaddr_in *)&ifa->address.sa;
 2180                                 if (sin->sin_addr.s_addr == 0) {
 2181                                         /* we skip unspecifed addresses */
 2182                                         continue;
 2183                                 }
 2184                                 if (stcb->asoc.ipv4_local_scope == 0 &&
 2185                                     IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
 2186                                         continue;
 2187                                 }
 2188                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 2189                                     SCTP_IPV6_V6ONLY(inp6)) {
 2190                                         cnt_invalid++;
 2191                                         if (asc->cnt == cnt_invalid)
 2192                                                 return;
 2193                                         else
 2194                                                 continue;
 2195                                 }
 2196                                 break;
 2197                         }
 2198                 default:
 2199                         /* invalid address family */
 2200                         cnt_invalid++;
 2201                         if (asc->cnt == cnt_invalid)
 2202                                 return;
 2203                         else
 2204                                 continue;
 2205                         break;
 2206                 }
 2207 
 2208                 if (type == SCTP_ADD_IP_ADDRESS) {
 2209                         /* prevent this address from being used as a source */
 2210                         sctp_add_local_addr_restricted(stcb, ifa);
 2211                 } else if (type == SCTP_DEL_IP_ADDRESS) {
 2212                         struct sctp_nets *net;
 2213 
 2214                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 2215                                 sctp_rtentry_t *rt;
 2216 
 2217                                 /* delete this address if cached */
 2218                                 if (net->ro._s_addr == ifa) {
 2219                                         sctp_free_ifa(net->ro._s_addr);
 2220                                         net->ro._s_addr = NULL;
 2221                                         net->src_addr_selected = 0;
 2222                                         rt = net->ro.ro_rt;
 2223                                         if (rt) {
 2224                                                 RTFREE(rt);
 2225                                                 net->ro.ro_rt = NULL;
 2226                                         }
 2227                                         /*
 2228                                          * Now we deleted our src address,
 2229                                          * should we not also now reset the
 2230                                          * cwnd/rto to start as if its a new
 2231                                          * address?
 2232                                          */
 2233                                         stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
 2234                                         net->RTO = 0;
 2235 
 2236                                 }
 2237                         }
 2238                 } else if (type == SCTP_SET_PRIM_ADDR) {
 2239                         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
 2240                                 /* must validate the ifa is in the ep */
 2241                                 if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) {
 2242                                         continue;
 2243                                 }
 2244                         } else {
 2245                                 /* Need to check scopes for this guy */
 2246                                 if (sctp_is_address_in_scope(ifa,
 2247                                     stcb->asoc.ipv4_addr_legal,
 2248                                     stcb->asoc.ipv6_addr_legal,
 2249                                     stcb->asoc.loopback_scope,
 2250                                     stcb->asoc.ipv4_local_scope,
 2251                                     stcb->asoc.local_scope,
 2252                                     stcb->asoc.site_scope, 0) == 0) {
 2253                                         continue;
 2254                                 }
 2255                         }
 2256                 }
 2257                 /* queue an asconf for this address add/delete */
 2258                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
 2259                     stcb->asoc.peer_supports_asconf) {
 2260                         /* queue an asconf for this addr */
 2261                         status = sctp_asconf_queue_add(stcb, ifa, type);
 2262                         /*
 2263                          * if queued ok, and in the open state, update the
 2264                          * count of queued params.  If in the non-open
 2265                          * state, these get sent when the assoc goes open.
 2266                          */
 2267                         if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2268                                 if (status >= 0) {
 2269                                         num_queued++;
 2270                                 }
 2271                         }
 2272                 }
 2273         }
 2274         /*
 2275          * If we have queued params in the open state, send out an ASCONF.
 2276          */
 2277         if (num_queued > 0) {
 2278                 sctp_send_asconf(stcb, stcb->asoc.primary_destination,
 2279                     SCTP_ADDR_NOT_LOCKED);
 2280         }
 2281 }
 2282 
 2283 void
 2284 sctp_asconf_iterator_end(void *ptr, uint32_t val)
 2285 {
 2286         struct sctp_asconf_iterator *asc;
 2287         struct sctp_ifa *ifa;
 2288         struct sctp_laddr *l, *l_next;
 2289 
 2290         asc = (struct sctp_asconf_iterator *)ptr;
 2291         l = LIST_FIRST(&asc->list_of_work);
 2292         while (l != NULL) {
 2293                 l_next = LIST_NEXT(l, sctp_nxt_addr);
 2294                 ifa = l->ifa;
 2295                 if (l->action == SCTP_ADD_IP_ADDRESS) {
 2296                         /* Clear the defer use flag */
 2297                         ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
 2298                 }
 2299                 sctp_free_ifa(ifa);
 2300                 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l);
 2301                 SCTP_DECR_LADDR_COUNT();
 2302                 l = l_next;
 2303         }
 2304         SCTP_FREE(asc, SCTP_M_ASC_IT);
 2305 }
 2306 
 2307 /*
 2308  * sa is the sockaddr to ask the peer to set primary to.
 2309  * returns: 0 = completed, -1 = error
 2310  */
 2311 int32_t
 2312 sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
 2313 {
 2314         uint32_t vrf_id;
 2315         struct sctp_ifa *ifa;
 2316 
 2317         /* find the ifa for the desired set primary */
 2318         vrf_id = stcb->asoc.vrf_id;
 2319         ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 2320         if (ifa == NULL) {
 2321                 /* Invalid address */
 2322                 return (-1);
 2323         }
 2324         /* queue an ASCONF:SET_PRIM_ADDR to be sent */
 2325         if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) {
 2326                 /* set primary queuing succeeded */
 2327                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 2328                     "set_primary_ip_address_sa: queued on tcb=%p, ",
 2329                     stcb);
 2330                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
 2331                 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2332 #ifdef SCTP_TIMER_BASED_ASCONF
 2333                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2334                             stcb->sctp_ep, stcb,
 2335                             stcb->asoc.primary_destination);
 2336 #else
 2337                         sctp_send_asconf(stcb, stcb->asoc.primary_destination,
 2338                             SCTP_ADDR_NOT_LOCKED);
 2339 #endif
 2340                 }
 2341         } else {
 2342                 SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ",
 2343                     stcb);
 2344                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
 2345                 return (-1);
 2346         }
 2347         return (0);
 2348 }
 2349 
 2350 void
 2351 sctp_set_primary_ip_address(struct sctp_ifa *ifa)
 2352 {
 2353         struct sctp_inpcb *inp;
 2354 
 2355         /* go through all our PCB's */
 2356         LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
 2357                 struct sctp_tcb *stcb;
 2358 
 2359                 /* process for all associations for this endpoint */
 2360                 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
 2361                         /* queue an ASCONF:SET_PRIM_ADDR to be sent */
 2362                         if (!sctp_asconf_queue_add(stcb, ifa,
 2363                             SCTP_SET_PRIM_ADDR)) {
 2364                                 /* set primary queuing succeeded */
 2365                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
 2366                                     stcb);
 2367                                 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
 2368                                 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
 2369 #ifdef SCTP_TIMER_BASED_ASCONF
 2370                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2371                                             stcb->sctp_ep, stcb,
 2372                                             stcb->asoc.primary_destination);
 2373 #else
 2374                                         sctp_send_asconf(stcb, stcb->asoc.primary_destination,
 2375                                             SCTP_ADDR_NOT_LOCKED);
 2376 #endif
 2377                                 }
 2378                         }
 2379                 }               /* for each stcb */
 2380         }                       /* for each inp */
 2381 }
 2382 
 2383 int
 2384 sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
 2385 {
 2386         struct sctp_tmit_chunk *chk, *nchk;
 2387         unsigned int offset, asconf_limit;
 2388         struct sctp_asconf_chunk *acp;
 2389         struct sctp_asconf_paramhdr *aph;
 2390         uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
 2391         struct sctp_ipv6addr_param *p_addr;
 2392         int add_cnt, del_cnt;
 2393         uint16_t last_param_type;
 2394 
 2395         add_cnt = del_cnt = 0;
 2396         last_param_type = 0;
 2397         for (chk = TAILQ_FIRST(&stcb->asoc.asconf_send_queue); chk != NULL;
 2398             chk = nchk) {
 2399                 /* get next chk */
 2400                 nchk = TAILQ_NEXT(chk, sctp_next);
 2401 
 2402                 if (chk->data == NULL) {
 2403                         SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n");
 2404                         continue;
 2405                 }
 2406                 offset = 0;
 2407                 acp = mtod(chk->data, struct sctp_asconf_chunk *);
 2408                 offset += sizeof(struct sctp_asconf_chunk);
 2409                 asconf_limit = ntohs(acp->ch.chunk_length);
 2410                 p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf);
 2411                 if (p_addr == NULL) {
 2412                         SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n");
 2413                         continue;
 2414                 }
 2415                 offset += ntohs(p_addr->ph.param_length);
 2416 
 2417                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
 2418                 if (aph == NULL) {
 2419                         SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: Empty ASCONF will be sent?\n");
 2420                         continue;
 2421                 }
 2422                 while (aph != NULL) {
 2423                         unsigned int param_length, param_type;
 2424 
 2425                         param_type = ntohs(aph->ph.param_type);
 2426                         param_length = ntohs(aph->ph.param_length);
 2427                         if (offset + param_length > asconf_limit) {
 2428                                 /* parameter goes beyond end of chunk! */
 2429                                 break;
 2430                         }
 2431                         if (param_length > sizeof(aparam_buf)) {
 2432                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length (%u) larger than buffer size!\n", param_length);
 2433                                 break;
 2434                         }
 2435                         if (param_length <= sizeof(struct sctp_paramhdr)) {
 2436                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length);
 2437                                 break;
 2438                         }
 2439                         aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf);
 2440                         if (aph == NULL) {
 2441                                 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n");
 2442                                 break;
 2443                         }
 2444                         p_addr = (struct sctp_ipv6addr_param *)(aph + 1);
 2445                         if (sctp_addr_match(p_addr, &sctp_ifa->address.sa) != 0) {
 2446                                 switch (param_type) {
 2447                                 case SCTP_ADD_IP_ADDRESS:
 2448                                         add_cnt++;
 2449                                         break;
 2450                                 case SCTP_DEL_IP_ADDRESS:
 2451                                         del_cnt++;
 2452                                         break;
 2453                                 default:
 2454                                         break;
 2455                                 }
 2456                                 last_param_type = param_type;
 2457                         }
 2458                         offset += SCTP_SIZE32(param_length);
 2459                         if (offset >= asconf_limit) {
 2460                                 /* no more data in the mbuf chain */
 2461                                 break;
 2462                         }
 2463                         /* get pointer to next asconf param */
 2464                         aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
 2465                 }
 2466         }
 2467 
 2468         /*
 2469          * we want to find the sequences which consist of ADD -> DEL -> ADD
 2470          * or DEL -> ADD
 2471          */
 2472         if (add_cnt > del_cnt ||
 2473             (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) {
 2474                 return 1;
 2475         }
 2476         return 0;
 2477 }
 2478 
 2479 static struct sockaddr *
 2480 sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
 2481 {
 2482         struct sctp_vrf *vrf = NULL;
 2483         struct sctp_ifn *sctp_ifn;
 2484         struct sctp_ifa *sctp_ifa;
 2485 
 2486         if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2487                 SCTP_IPI_ADDR_RLOCK();
 2488         vrf = sctp_find_vrf(stcb->asoc.vrf_id);
 2489         if (vrf == NULL) {
 2490                 if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2491                         SCTP_IPI_ADDR_RUNLOCK();
 2492                 return (NULL);
 2493         }
 2494         LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
 2495                 if (stcb->asoc.loopback_scope == 0 &&
 2496                     SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
 2497                         /* Skip if loopback_scope not set */
 2498                         continue;
 2499                 }
 2500                 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
 2501                         if (sctp_ifa->address.sa.sa_family == AF_INET &&
 2502                             stcb->asoc.ipv4_addr_legal) {
 2503                                 struct sockaddr_in *sin;
 2504 
 2505                                 sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
 2506                                 if (sin->sin_addr.s_addr == 0) {
 2507                                         /* skip unspecifed addresses */
 2508                                         continue;
 2509                                 }
 2510                                 if (stcb->asoc.ipv4_local_scope == 0 &&
 2511                                     IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
 2512                                         continue;
 2513 
 2514                                 if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
 2515                                     (!sctp_is_addr_pending(stcb, sctp_ifa)))
 2516                                         continue;
 2517                                 /* found a valid local v4 address to use */
 2518                                 if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2519                                         SCTP_IPI_ADDR_RUNLOCK();
 2520                                 return (&sctp_ifa->address.sa);
 2521                         } else if (sctp_ifa->address.sa.sa_family == AF_INET6 &&
 2522                             stcb->asoc.ipv6_addr_legal) {
 2523                                 struct sockaddr_in6 *sin6;
 2524 
 2525                                 if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
 2526                                         continue;
 2527                                 }
 2528                                 sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
 2529                                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 2530                                         /* we skip unspecifed addresses */
 2531                                         continue;
 2532                                 }
 2533                                 if (stcb->asoc.local_scope == 0 &&
 2534                                     IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
 2535                                         continue;
 2536                                 if (stcb->asoc.site_scope == 0 &&
 2537                                     IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
 2538                                         continue;
 2539 
 2540                                 if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
 2541                                     (!sctp_is_addr_pending(stcb, sctp_ifa)))
 2542                                         continue;
 2543                                 /* found a valid local v6 address to use */
 2544                                 if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2545                                         SCTP_IPI_ADDR_RUNLOCK();
 2546                                 return (&sctp_ifa->address.sa);
 2547                         }
 2548                 }
 2549         }
 2550         /* no valid addresses found */
 2551         if (addr_locked == SCTP_ADDR_NOT_LOCKED)
 2552                 SCTP_IPI_ADDR_RUNLOCK();
 2553         return (NULL);
 2554 }
 2555 
 2556 static struct sockaddr *
 2557 sctp_find_valid_localaddr_ep(struct sctp_tcb *stcb)
 2558 {
 2559         struct sctp_laddr *laddr;
 2560 
 2561         LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 2562                 if (laddr->ifa == NULL) {
 2563                         continue;
 2564                 }
 2565                 /* is the address restricted ? */
 2566                 if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
 2567                     (!sctp_is_addr_pending(stcb, laddr->ifa)))
 2568                         continue;
 2569 
 2570                 /* found a valid local address to use */
 2571                 return (&laddr->ifa->address.sa);
 2572         }
 2573         /* no valid addresses found */
 2574         return (NULL);
 2575 }
 2576 
 2577 /*
 2578  * builds an ASCONF chunk from queued ASCONF params.
 2579  * returns NULL on error (no mbuf, no ASCONF params queued, etc).
 2580  */
 2581 struct mbuf *
 2582 sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
 2583 {
 2584         struct mbuf *m_asconf, *m_asconf_chk;
 2585         struct sctp_asconf_addr *aa;
 2586         struct sctp_asconf_chunk *acp;
 2587         struct sctp_asconf_paramhdr *aph;
 2588         struct sctp_asconf_addr_param *aap;
 2589         uint32_t p_length;
 2590         uint32_t correlation_id = 1;    /* 0 is reserved... */
 2591         caddr_t ptr, lookup_ptr;
 2592         uint8_t lookup_used = 0;
 2593 
 2594         /* are there any asconf params to send? */
 2595         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 2596                 if (aa->sent == 0)
 2597                         break;
 2598         }
 2599         if (aa == NULL)
 2600                 return (NULL);
 2601 
 2602         /*
 2603          * get a chunk header mbuf and a cluster for the asconf params since
 2604          * it's simpler to fill in the asconf chunk header lookup address on
 2605          * the fly
 2606          */
 2607         m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_DONTWAIT, 1, MT_DATA);
 2608         if (m_asconf_chk == NULL) {
 2609                 /* no mbuf's */
 2610                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 2611                     "compose_asconf: couldn't get chunk mbuf!\n");
 2612                 return (NULL);
 2613         }
 2614         m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
 2615         if (m_asconf == NULL) {
 2616                 /* no mbuf's */
 2617                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 2618                     "compose_asconf: couldn't get mbuf!\n");
 2619                 sctp_m_freem(m_asconf_chk);
 2620                 return (NULL);
 2621         }
 2622         SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk);
 2623         SCTP_BUF_LEN(m_asconf) = 0;
 2624         acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *);
 2625         bzero(acp, sizeof(struct sctp_asconf_chunk));
 2626         /* save pointers to lookup address and asconf params */
 2627         lookup_ptr = (caddr_t)(acp + 1);        /* after the header */
 2628         ptr = mtod(m_asconf, caddr_t);  /* beginning of cluster */
 2629 
 2630         /* fill in chunk header info */
 2631         acp->ch.chunk_type = SCTP_ASCONF;
 2632         acp->ch.chunk_flags = 0;
 2633         acp->serial_number = htonl(stcb->asoc.asconf_seq_out);
 2634         stcb->asoc.asconf_seq_out++;
 2635 
 2636         /* add parameters... up to smallest MTU allowed */
 2637         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
 2638                 if (aa->sent)
 2639                         continue;
 2640                 /* get the parameter length */
 2641                 p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
 2642                 /* will it fit in current chunk? */
 2643                 if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) {
 2644                         /* won't fit, so we're done with this chunk */
 2645                         break;
 2646                 }
 2647                 /* assign (and store) a correlation id */
 2648                 aa->ap.aph.correlation_id = correlation_id++;
 2649 
 2650                 /*
 2651                  * fill in address if we're doing a delete this is a simple
 2652                  * way for us to fill in the correlation address, which
 2653                  * should only be used by the peer if we're deleting our
 2654                  * source address and adding a new address (e.g. renumbering
 2655                  * case)
 2656                  */
 2657                 if (lookup_used == 0 &&
 2658                     (aa->special_del == 0) &&
 2659                     aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
 2660                         struct sctp_ipv6addr_param *lookup;
 2661                         uint16_t p_size, addr_size;
 2662 
 2663                         lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
 2664                         lookup->ph.param_type =
 2665                             htons(aa->ap.addrp.ph.param_type);
 2666                         if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) {
 2667                                 /* copy IPv6 address */
 2668                                 p_size = sizeof(struct sctp_ipv6addr_param);
 2669                                 addr_size = sizeof(struct in6_addr);
 2670                         } else {
 2671                                 /* copy IPv4 address */
 2672                                 p_size = sizeof(struct sctp_ipv4addr_param);
 2673                                 addr_size = sizeof(struct in_addr);
 2674                         }
 2675                         lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
 2676                         memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size);
 2677                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
 2678                         lookup_used = 1;
 2679                 }
 2680                 /* copy into current space */
 2681                 memcpy(ptr, &aa->ap, p_length);
 2682 
 2683                 /* network elements and update lengths */
 2684                 aph = (struct sctp_asconf_paramhdr *)ptr;
 2685                 aap = (struct sctp_asconf_addr_param *)ptr;
 2686                 /* correlation_id is transparent to peer, no htonl needed */
 2687                 aph->ph.param_type = htons(aph->ph.param_type);
 2688                 aph->ph.param_length = htons(aph->ph.param_length);
 2689                 aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type);
 2690                 aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length);
 2691 
 2692                 SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length);
 2693                 ptr += SCTP_SIZE32(p_length);
 2694 
 2695                 /*
 2696                  * these params are removed off the pending list upon
 2697                  * getting an ASCONF-ACK back from the peer, just set flag
 2698                  */
 2699                 aa->sent = 1;
 2700         }
 2701         /* check to see if the lookup addr has been populated yet */
 2702         if (lookup_used == 0) {
 2703                 /* NOTE: if the address param is optional, can skip this... */
 2704                 /* add any valid (existing) address... */
 2705                 struct sctp_ipv6addr_param *lookup;
 2706                 uint16_t p_size, addr_size;
 2707                 struct sockaddr *found_addr;
 2708                 caddr_t addr_ptr;
 2709 
 2710                 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)
 2711                         found_addr = sctp_find_valid_localaddr(stcb,
 2712                             addr_locked);
 2713                 else
 2714                         found_addr = sctp_find_valid_localaddr_ep(stcb);
 2715 
 2716                 lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
 2717                 if (found_addr != NULL) {
 2718                         if (found_addr->sa_family == AF_INET6) {
 2719                                 /* copy IPv6 address */
 2720                                 lookup->ph.param_type =
 2721                                     htons(SCTP_IPV6_ADDRESS);
 2722                                 p_size = sizeof(struct sctp_ipv6addr_param);
 2723                                 addr_size = sizeof(struct in6_addr);
 2724                                 addr_ptr = (caddr_t)&((struct sockaddr_in6 *)
 2725                                     found_addr)->sin6_addr;
 2726                         } else {
 2727                                 /* copy IPv4 address */
 2728                                 lookup->ph.param_type =
 2729                                     htons(SCTP_IPV4_ADDRESS);
 2730                                 p_size = sizeof(struct sctp_ipv4addr_param);
 2731                                 addr_size = sizeof(struct in_addr);
 2732                                 addr_ptr = (caddr_t)&((struct sockaddr_in *)
 2733                                     found_addr)->sin_addr;
 2734                         }
 2735                         lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
 2736                         memcpy(lookup->addr, addr_ptr, addr_size);
 2737                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
 2738                         lookup_used = 1;
 2739                 } else {
 2740                         /* uh oh... don't have any address?? */
 2741                         SCTPDBG(SCTP_DEBUG_ASCONF1,
 2742                             "compose_asconf: no lookup addr!\n");
 2743                         /* for now, we send a IPv4 address of 0.0.0.0 */
 2744                         lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
 2745                         lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
 2746                         bzero(lookup->addr, sizeof(struct in_addr));
 2747                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
 2748                         lookup_used = 1;
 2749                 }
 2750         }
 2751         /* chain it all together */
 2752         SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
 2753         *retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf);
 2754         acp->ch.chunk_length = ntohs(*retlen);
 2755 
 2756         return (m_asconf_chk);
 2757 }
 2758 
 2759 /*
 2760  * section to handle address changes before an association is up eg. changes
 2761  * during INIT/INIT-ACK/COOKIE-ECHO handshake
 2762  */
 2763 
 2764 /*
 2765  * processes the (local) addresses in the INIT-ACK chunk
 2766  */
 2767 static void
 2768 sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
 2769     unsigned int offset, unsigned int length)
 2770 {
 2771         struct sctp_paramhdr tmp_param, *ph;
 2772         uint16_t plen, ptype;
 2773         struct sctp_ifa *sctp_ifa;
 2774         struct sctp_ipv6addr_param addr_store;
 2775         struct sockaddr_in6 sin6;
 2776         struct sockaddr_in sin;
 2777         struct sockaddr *sa;
 2778         uint32_t vrf_id;
 2779 
 2780         SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n");
 2781         if (stcb == NULL)       /* Un-needed check for SA */
 2782                 return;
 2783 
 2784         /* convert to upper bound */
 2785         length += offset;
 2786 
 2787         if ((offset + sizeof(struct sctp_paramhdr)) > length) {
 2788                 return;
 2789         }
 2790         /* init the addresses */
 2791         bzero(&sin6, sizeof(sin6));
 2792         sin6.sin6_family = AF_INET6;
 2793         sin6.sin6_len = sizeof(sin6);
 2794         sin6.sin6_port = stcb->rport;
 2795 
 2796         bzero(&sin, sizeof(sin));
 2797         sin.sin_len = sizeof(sin);
 2798         sin.sin_family = AF_INET;
 2799         sin.sin_port = stcb->rport;
 2800 
 2801         /* go through the addresses in the init-ack */
 2802         ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
 2803             sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
 2804         while (ph != NULL) {
 2805                 ptype = ntohs(ph->param_type);
 2806                 plen = ntohs(ph->param_length);
 2807                 if (ptype == SCTP_IPV6_ADDRESS) {
 2808                         struct sctp_ipv6addr_param *a6p;
 2809 
 2810                         /* get the entire IPv6 address param */
 2811                         a6p = (struct sctp_ipv6addr_param *)
 2812                             sctp_m_getptr(m, offset,
 2813                             sizeof(struct sctp_ipv6addr_param),
 2814                             (uint8_t *) & addr_store);
 2815                         if (plen != sizeof(struct sctp_ipv6addr_param) ||
 2816                             a6p == NULL) {
 2817                                 return;
 2818                         }
 2819                         memcpy(&sin6.sin6_addr, a6p->addr,
 2820                             sizeof(struct in6_addr));
 2821                         sa = (struct sockaddr *)&sin6;
 2822                 } else if (ptype == SCTP_IPV4_ADDRESS) {
 2823                         struct sctp_ipv4addr_param *a4p;
 2824 
 2825                         /* get the entire IPv4 address param */
 2826                         a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
 2827                             sizeof(struct sctp_ipv4addr_param),
 2828                             (uint8_t *) & addr_store);
 2829                         if (plen != sizeof(struct sctp_ipv4addr_param) ||
 2830                             a4p == NULL) {
 2831                                 return;
 2832                         }
 2833                         sin.sin_addr.s_addr = a4p->addr;
 2834                         sa = (struct sockaddr *)&sin;
 2835                 } else {
 2836                         goto next_addr;
 2837                 }
 2838 
 2839                 /* see if this address really (still) exists */
 2840                 if (stcb) {
 2841                         vrf_id = stcb->asoc.vrf_id;
 2842                 } else {
 2843                         vrf_id = SCTP_DEFAULT_VRFID;
 2844                 }
 2845                 sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id,
 2846                     SCTP_ADDR_NOT_LOCKED);
 2847                 if (sctp_ifa == NULL) {
 2848                         /* address doesn't exist anymore */
 2849                         int status;
 2850 
 2851                         /* are ASCONFs allowed ? */
 2852                         if ((sctp_is_feature_on(stcb->sctp_ep,
 2853                             SCTP_PCB_FLAGS_DO_ASCONF)) &&
 2854                             stcb->asoc.peer_supports_asconf) {
 2855                                 /* queue an ASCONF DEL_IP_ADDRESS */
 2856                                 status = sctp_asconf_queue_sa_delete(stcb, sa);
 2857                                 /*
 2858                                  * if queued ok, and in correct state, send
 2859                                  * out the ASCONF.
 2860                                  */
 2861                                 if (status == 0 &&
 2862                                     SCTP_GET_STATE(&stcb->asoc) ==
 2863                                     SCTP_STATE_OPEN) {
 2864 #ifdef SCTP_TIMER_BASED_ASCONF
 2865                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
 2866                                             stcb->sctp_ep, stcb,
 2867                                             stcb->asoc.primary_destination);
 2868 #else
 2869                                         sctp_send_asconf(stcb, stcb->asoc.primary_destination,
 2870                                             SCTP_ADDR_NOT_LOCKED);
 2871 #endif
 2872                                 }
 2873                         }
 2874                 }
 2875 next_addr:
 2876                 /*
 2877                  * Sanity check:  Make sure the length isn't 0, otherwise
 2878                  * we'll be stuck in this loop for a long time...
 2879                  */
 2880                 if (SCTP_SIZE32(plen) == 0) {
 2881                         SCTP_PRINTF("process_initack_addrs: bad len (%d) type=%xh\n",
 2882                             plen, ptype);
 2883                         return;
 2884                 }
 2885                 /* get next parameter */
 2886                 offset += SCTP_SIZE32(plen);
 2887                 if ((offset + sizeof(struct sctp_paramhdr)) > length)
 2888                         return;
 2889                 ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
 2890                     sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
 2891         }                       /* while */
 2892 }
 2893 
 2894 /* FIX ME: need to verify return result for v6 address type if v6 disabled */
 2895 /*
 2896  * checks to see if a specific address is in the initack address list returns
 2897  * 1 if found, 0 if not
 2898  */
 2899 static uint32_t
 2900 sctp_addr_in_initack(struct sctp_tcb *stcb, struct mbuf *m, uint32_t offset,
 2901     uint32_t length, struct sockaddr *sa)
 2902 {
 2903         struct sctp_paramhdr tmp_param, *ph;
 2904         uint16_t plen, ptype;
 2905         struct sctp_ipv6addr_param addr_store;
 2906         struct sockaddr_in *sin;
 2907         struct sctp_ipv4addr_param *a4p;
 2908 
 2909 #ifdef INET6
 2910         struct sockaddr_in6 *sin6;
 2911         struct sctp_ipv6addr_param *a6p;
 2912         struct sockaddr_in6 sin6_tmp;
 2913 
 2914 #endif                          /* INET6 */
 2915 
 2916         if (
 2917 #ifdef INET6
 2918             (sa->sa_family != AF_INET6) &&
 2919 #endif                          /* INET6 */
 2920             (sa->sa_family != AF_INET))
 2921                 return (0);
 2922 
 2923         SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for ");
 2924         SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
 2925         /* convert to upper bound */
 2926         length += offset;
 2927 
 2928         if ((offset + sizeof(struct sctp_paramhdr)) > length) {
 2929                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 2930                     "find_initack_addr: invalid offset?\n");
 2931                 return (0);
 2932         }
 2933         /* go through the addresses in the init-ack */
 2934         ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
 2935             sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
 2936         while (ph != NULL) {
 2937                 ptype = ntohs(ph->param_type);
 2938                 plen = ntohs(ph->param_length);
 2939 #ifdef INET6
 2940                 if (ptype == SCTP_IPV6_ADDRESS && sa->sa_family == AF_INET6) {
 2941                         /* get the entire IPv6 address param */
 2942                         a6p = (struct sctp_ipv6addr_param *)
 2943                             sctp_m_getptr(m, offset,
 2944                             sizeof(struct sctp_ipv6addr_param),
 2945                             (uint8_t *) & addr_store);
 2946                         if (plen != sizeof(struct sctp_ipv6addr_param) ||
 2947                             (ph == NULL) ||
 2948                             (a6p == NULL)) {
 2949                                 return (0);
 2950                         }
 2951                         sin6 = (struct sockaddr_in6 *)sa;
 2952                         if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
 2953                                 /* create a copy and clear scope */
 2954                                 memcpy(&sin6_tmp, sin6,
 2955                                     sizeof(struct sockaddr_in6));
 2956                                 sin6 = &sin6_tmp;
 2957                                 in6_clearscope(&sin6->sin6_addr);
 2958                         }
 2959                         if (memcmp(&sin6->sin6_addr, a6p->addr,
 2960                             sizeof(struct in6_addr)) == 0) {
 2961                                 /* found it */
 2962                                 return (1);
 2963                         }
 2964                 } else
 2965 #endif                          /* INET6 */
 2966 
 2967                         if (ptype == SCTP_IPV4_ADDRESS &&
 2968                     sa->sa_family == AF_INET) {
 2969                         /* get the entire IPv4 address param */
 2970                         a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m,
 2971                             offset, sizeof(struct sctp_ipv4addr_param),
 2972                             (uint8_t *) & addr_store);
 2973                         if (plen != sizeof(struct sctp_ipv4addr_param) ||
 2974                             (ph == NULL) ||
 2975                             (a4p == NULL)) {
 2976                                 return (0);
 2977                         }
 2978                         sin = (struct sockaddr_in *)sa;
 2979                         if (sin->sin_addr.s_addr == a4p->addr) {
 2980                                 /* found it */
 2981                                 return (1);
 2982                         }
 2983                 }
 2984                 /* get next parameter */
 2985                 offset += SCTP_SIZE32(plen);
 2986                 if (offset + sizeof(struct sctp_paramhdr) > length)
 2987                         return (0);
 2988                 ph = (struct sctp_paramhdr *)
 2989                     sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
 2990                     (uint8_t *) & tmp_param);
 2991         }                       /* while */
 2992         /* not found! */
 2993         return (0);
 2994 }
 2995 
 2996 /*
 2997  * makes sure that the current endpoint local addr list is consistent with
 2998  * the new association (eg. subset bound, asconf allowed) adds addresses as
 2999  * necessary
 3000  */
 3001 static void
 3002 sctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 3003     int length, struct sockaddr *init_addr)
 3004 {
 3005         struct sctp_laddr *laddr;
 3006 
 3007         /* go through the endpoint list */
 3008         LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 3009                 /* be paranoid and validate the laddr */
 3010                 if (laddr->ifa == NULL) {
 3011                         SCTPDBG(SCTP_DEBUG_ASCONF1,
 3012                             "check_addr_list_ep: laddr->ifa is NULL");
 3013                         continue;
 3014                 }
 3015                 if (laddr->ifa == NULL) {
 3016                         SCTPDBG(SCTP_DEBUG_ASCONF1, "check_addr_list_ep: laddr->ifa->ifa_addr is NULL");
 3017                         continue;
 3018                 }
 3019                 /* do i have it implicitly? */
 3020                 if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) {
 3021                         continue;
 3022                 }
 3023                 /* check to see if in the init-ack */
 3024                 if (!sctp_addr_in_initack(stcb, m, offset, length,
 3025                     &laddr->ifa->address.sa)) {
 3026                         /* try to add it */
 3027                         sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa,
 3028                             SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED);
 3029                 }
 3030         }
 3031 }
 3032 
 3033 /*
 3034  * makes sure that the current kernel address list is consistent with the new
 3035  * association (with all addrs bound) adds addresses as necessary
 3036  */
 3037 static void
 3038 sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 3039     int length, struct sockaddr *init_addr,
 3040     uint16_t local_scope, uint16_t site_scope,
 3041     uint16_t ipv4_scope, uint16_t loopback_scope)
 3042 {
 3043         struct sctp_vrf *vrf = NULL;
 3044         struct sctp_ifn *sctp_ifn;
 3045         struct sctp_ifa *sctp_ifa;
 3046         uint32_t vrf_id;
 3047 
 3048         if (stcb) {
 3049                 vrf_id = stcb->asoc.vrf_id;
 3050         } else {
 3051                 return;
 3052         }
 3053         SCTP_IPI_ADDR_RLOCK();
 3054         vrf = sctp_find_vrf(vrf_id);
 3055         if (vrf == NULL) {
 3056                 SCTP_IPI_ADDR_RUNLOCK();
 3057                 return;
 3058         }
 3059         /* go through all our known interfaces */
 3060         LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
 3061                 if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
 3062                         /* skip loopback interface */
 3063                         continue;
 3064                 }
 3065                 /* go through each interface address */
 3066                 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
 3067                         /* do i have it implicitly? */
 3068                         if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
 3069                                 continue;
 3070                         }
 3071                         /* check to see if in the init-ack */
 3072                         if (!sctp_addr_in_initack(stcb, m, offset, length,
 3073                             &sctp_ifa->address.sa)) {
 3074                                 /* try to add it */
 3075                                 sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
 3076                                     sctp_ifa, SCTP_ADD_IP_ADDRESS,
 3077                                     SCTP_ADDR_LOCKED);
 3078                         }
 3079                 }               /* end foreach ifa */
 3080         }                       /* end foreach ifn */
 3081         SCTP_IPI_ADDR_RUNLOCK();
 3082 }
 3083 
 3084 /*
 3085  * validates an init-ack chunk (from a cookie-echo) with current addresses
 3086  * adds addresses from the init-ack into our local address list, if needed
 3087  * queues asconf adds/deletes addresses as needed and makes appropriate list
 3088  * changes for source address selection m, offset: points to the start of the
 3089  * address list in an init-ack chunk length: total length of the address
 3090  * params only init_addr: address where my INIT-ACK was sent from
 3091  */
 3092 void
 3093 sctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 3094     int length, struct sockaddr *init_addr,
 3095     uint16_t local_scope, uint16_t site_scope,
 3096     uint16_t ipv4_scope, uint16_t loopback_scope)
 3097 {
 3098         /* process the local addresses in the initack */
 3099         sctp_process_initack_addresses(stcb, m, offset, length);
 3100 
 3101         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
 3102                 /* bound all case */
 3103                 sctp_check_address_list_all(stcb, m, offset, length, init_addr,
 3104                     local_scope, site_scope, ipv4_scope, loopback_scope);
 3105         } else {
 3106                 /* subset bound case */
 3107                 if (sctp_is_feature_on(stcb->sctp_ep,
 3108                     SCTP_PCB_FLAGS_DO_ASCONF)) {
 3109                         /* asconf's allowed */
 3110                         sctp_check_address_list_ep(stcb, m, offset, length,
 3111                             init_addr);
 3112                 }
 3113                 /* else, no asconfs allowed, so what we sent is what we get */
 3114         }
 3115 }
 3116 
 3117 /*
 3118  * sctp_bindx() support
 3119  */
 3120 uint32_t
 3121 sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
 3122     uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap)
 3123 {
 3124         struct sctp_ifa *ifa;
 3125 
 3126         if (sa->sa_len == 0) {
 3127                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
 3128                 return (EINVAL);
 3129         }
 3130         if (sctp_ifap) {
 3131                 ifa = sctp_ifap;
 3132         } else if (type == SCTP_ADD_IP_ADDRESS) {
 3133                 /* For an add the address MUST be on the system */
 3134                 ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 3135         } else if (type == SCTP_DEL_IP_ADDRESS) {
 3136                 /* For a delete we need to find it in the inp */
 3137                 ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED);
 3138         } else {
 3139                 ifa = NULL;
 3140         }
 3141         if (ifa != NULL) {
 3142                 if (type == SCTP_ADD_IP_ADDRESS) {
 3143                         sctp_add_local_addr_ep(inp, ifa, type);
 3144                 } else if (type == SCTP_DEL_IP_ADDRESS) {
 3145                         struct sctp_laddr *laddr;
 3146 
 3147                         if (inp->laddr_count < 2) {
 3148                                 /* can't delete the last local address */
 3149                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
 3150                                 return (EINVAL);
 3151                         }
 3152                         LIST_FOREACH(laddr, &inp->sctp_addr_list,
 3153                             sctp_nxt_addr) {
 3154                                 if (ifa == laddr->ifa) {
 3155                                         /* Mark in the delete */
 3156                                         laddr->action = type;
 3157                                 }
 3158                         }
 3159                 }
 3160                 if (!LIST_EMPTY(&inp->sctp_asoc_list)) {
 3161                         /*
 3162                          * There is no need to start the iterator if the inp
 3163                          * has no associations.
 3164                          */
 3165                         struct sctp_asconf_iterator *asc;
 3166                         struct sctp_laddr *wi;
 3167 
 3168                         SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
 3169                             sizeof(struct sctp_asconf_iterator),
 3170                             SCTP_M_ASC_IT);
 3171                         if (asc == NULL) {
 3172                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
 3173                                 return (ENOMEM);
 3174                         }
 3175                         wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr);
 3176                         if (wi == NULL) {
 3177                                 SCTP_FREE(asc, SCTP_M_ASC_IT);
 3178                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
 3179                                 return (ENOMEM);
 3180                         }
 3181                         LIST_INIT(&asc->list_of_work);
 3182                         asc->cnt = 1;
 3183                         SCTP_INCR_LADDR_COUNT();
 3184                         wi->ifa = ifa;
 3185                         wi->action = type;
 3186                         atomic_add_int(&ifa->refcount, 1);
 3187                         LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
 3188                         (void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
 3189                             sctp_asconf_iterator_stcb,
 3190                             sctp_asconf_iterator_ep_end,
 3191                             SCTP_PCB_ANY_FLAGS,
 3192                             SCTP_PCB_ANY_FEATURES,
 3193                             SCTP_ASOC_ANY_STATE,
 3194                             (void *)asc, 0,
 3195                             sctp_asconf_iterator_end, inp, 0);
 3196                 }
 3197                 return (0);
 3198         } else {
 3199                 /* invalid address! */
 3200                 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL);
 3201                 return (EADDRNOTAVAIL);
 3202         }
 3203 }
 3204 
 3205 void
 3206 sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
 3207     struct sctp_nets *net)
 3208 {
 3209         struct sctp_asconf_addr *aa;
 3210         struct sctp_ifa *sctp_ifap;
 3211         struct sctp_asconf_tag_param *vtag;
 3212         struct sockaddr_in *to;
 3213 
 3214 #ifdef INET6
 3215         struct sockaddr_in6 *to6;
 3216 
 3217 #endif
 3218         if (net == NULL) {
 3219                 SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n");
 3220                 return;
 3221         }
 3222         if (stcb == NULL) {
 3223                 SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n");
 3224                 return;
 3225         }
 3226         /*
 3227          * Need to have in the asconf: - vtagparam(my_vtag/peer_vtag) -
 3228          * add(0.0.0.0) - del(0.0.0.0) - Any global addresses add(addr)
 3229          */
 3230         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 3231             SCTP_M_ASC_ADDR);
 3232         if (aa == NULL) {
 3233                 /* didn't get memory */
 3234                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3235                     "sctp_asconf_send_nat_state_update: failed to get memory!\n");
 3236                 return;
 3237         }
 3238         aa->special_del = 0;
 3239         /* fill in asconf address parameter fields */
 3240         /* top level elements are "networked" during send */
 3241         aa->ifa = NULL;
 3242         aa->sent = 0;           /* clear sent flag */
 3243         vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph;
 3244         vtag->aph.ph.param_type = SCTP_NAT_VTAGS;
 3245         vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param);
 3246         vtag->local_vtag = htonl(stcb->asoc.my_vtag);
 3247         vtag->remote_vtag = htonl(stcb->asoc.peer_vtag);
 3248         TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3249 
 3250         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 3251             SCTP_M_ASC_ADDR);
 3252         if (aa == NULL) {
 3253                 /* didn't get memory */
 3254                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3255                     "sctp_asconf_send_nat_state_update: failed to get memory!\n");
 3256                 return;
 3257         }
 3258         memset(aa, 0, sizeof(struct sctp_asconf_addr));
 3259         /* fill in asconf address parameter fields */
 3260         /* ADD(0.0.0.0) */
 3261         if (net->ro._l_addr.sa.sa_family == AF_INET) {
 3262                 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
 3263                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
 3264                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 3265                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param);
 3266                 /* No need to add an address, we are using 0.0.0.0 */
 3267                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3268         }
 3269 #ifdef INET6
 3270         else if (net->ro._l_addr.sa.sa_family == AF_INET6) {
 3271                 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
 3272                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
 3273                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 3274                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param);
 3275                 /* No need to add an address, we are using 0.0.0.0 */
 3276                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3277         }
 3278 #endif                          /* INET6 */
 3279         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 3280             SCTP_M_ASC_ADDR);
 3281         if (aa == NULL) {
 3282                 /* didn't get memory */
 3283                 SCTPDBG(SCTP_DEBUG_ASCONF1,
 3284                     "sctp_asconf_send_nat_state_update: failed to get memory!\n");
 3285                 return;
 3286         }
 3287         memset(aa, 0, sizeof(struct sctp_asconf_addr));
 3288         /* fill in asconf address parameter fields */
 3289         /* ADD(0.0.0.0) */
 3290         if (net->ro._l_addr.sa.sa_family == AF_INET) {
 3291                 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
 3292                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
 3293                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 3294                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param);
 3295                 /* No need to add an address, we are using 0.0.0.0 */
 3296                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3297         }
 3298 #ifdef INET6
 3299         else if (net->ro._l_addr.sa.sa_family == AF_INET6) {
 3300                 aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
 3301                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
 3302                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 3303                 aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param);
 3304                 /* No need to add an address, we are using 0.0.0.0 */
 3305                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 3306         }
 3307 #endif                          /* INET6 */
 3308         /* Now we must hunt the addresses and add all global addresses */
 3309         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
 3310                 struct sctp_vrf *vrf = NULL;
 3311                 struct sctp_ifn *sctp_ifnp;
 3312                 uint32_t vrf_id;
 3313 
 3314                 vrf_id = stcb->sctp_ep->def_vrf_id;
 3315                 vrf = sctp_find_vrf(vrf_id);
 3316                 if (vrf == NULL) {
 3317                         goto skip_rest;
 3318                 }
 3319                 SCTP_IPI_ADDR_RLOCK();
 3320                 LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
 3321                         LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
 3322                                 if (sctp_ifap->address.sa.sa_family == AF_INET) {
 3323                                         to = &sctp_ifap->address.sin;
 3324 
 3325                                         if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
 3326                                                 continue;
 3327                                         }
 3328                                         if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
 3329                                                 continue;
 3330                                         }
 3331                                 }
 3332 #ifdef INET6
 3333                                 else if (sctp_ifap->address.sa.sa_family == AF_INET6) {
 3334                                         to6 = &sctp_ifap->address.sin6;
 3335                                         if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
 3336                                                 continue;
 3337                                         }
 3338                                         if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
 3339                                                 continue;
 3340                                         }
 3341                                 }
 3342 #endif
 3343                                 sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
 3344                         }
 3345                 }
 3346                 SCTP_IPI_ADDR_RUNLOCK();
 3347         } else {
 3348                 struct sctp_laddr *laddr;
 3349 
 3350                 LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
 3351                         if (laddr->ifa == NULL) {
 3352                                 continue;
 3353                         }
 3354                         if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED)
 3355                                 /*
 3356                                  * Address being deleted by the system, dont
 3357                                  * list.
 3358                                  */
 3359                                 continue;
 3360                         if (laddr->action == SCTP_DEL_IP_ADDRESS) {
 3361                                 /*
 3362                                  * Address being deleted on this ep don't
 3363                                  * list.
 3364                                  */
 3365                                 continue;
 3366                         }
 3367                         sctp_ifap = laddr->ifa;
 3368                         if (sctp_ifap->address.sa.sa_family == AF_INET) {
 3369                                 to = &sctp_ifap->address.sin;
 3370 
 3371                                 if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
 3372                                         continue;
 3373                                 }
 3374                                 if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
 3375                                         continue;
 3376                                 }
 3377                         }
 3378 #ifdef INET6
 3379                         else if (sctp_ifap->address.sa.sa_family == AF_INET6) {
 3380                                 to6 = &sctp_ifap->address.sin6;
 3381                                 if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
 3382                                         continue;
 3383                                 }
 3384                                 if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
 3385                                         continue;
 3386                                 }
 3387                         }
 3388 #endif
 3389                         sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
 3390                 }
 3391         }
 3392 skip_rest:
 3393         /* Now we must send the asconf into the queue */
 3394         sctp_send_asconf(stcb, net, 0);
 3395 }

Cache object: cf308204e36c99c95caf787639207773


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