LCOV - code coverage report
Current view: top level - netwerk/sctp/src/netinet - sctp_asconf.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 887 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 41 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13