netwerk/sctp/src/netinet/sctp_asconf.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rwxr-xr-x

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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  */
    33 #ifdef __FreeBSD__
    34 #include <sys/cdefs.h>
    35 __FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 257803 2013-11-07 17:08:09Z tuexen $");
    36 #endif
    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>
    48 /*
    49  * debug flags:
    50  * SCTP_DEBUG_ASCONF1: protocol info, general info and errors
    51  * SCTP_DEBUG_ASCONF2: detailed info
    52  */
    54 #if defined(__APPLE__)
    55 #define APPLE_FILE_NO 1
    56 #endif
    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  */
    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 sctp_asconf_success_response(uint32_t id)
    83 {
    84 	struct mbuf *m_reply = NULL;
    85 	struct sctp_asconf_paramhdr *aph;
    87 	m_reply = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_paramhdr),
    88 					0, M_NOWAIT, 1, MT_DATA);
    89 	if (m_reply == NULL) {
    90 		SCTPDBG(SCTP_DEBUG_ASCONF1,
    91 			"asconf_success_response: couldn't get mbuf!\n");
    92 		return (NULL);
    93 	}
    94 	aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
    95 	aph->correlation_id = id;
    96 	aph->ph.param_type = htons(SCTP_SUCCESS_REPORT);
    97 	aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr);
    98 	SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
    99 	aph->ph.param_length = htons(aph->ph.param_length);
   101 	return (m_reply);
   102 }
   104 static struct mbuf *
   105 sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t *error_tlv,
   106 			   uint16_t tlv_length)
   107 {
   108 	struct mbuf *m_reply = NULL;
   109 	struct sctp_asconf_paramhdr *aph;
   110 	struct sctp_error_cause *error;
   111 	uint8_t *tlv;
   113 	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 	if (m_reply == NULL) {
   118 		SCTPDBG(SCTP_DEBUG_ASCONF1,
   119 			"asconf_error_response: couldn't get mbuf!\n");
   120 		return (NULL);
   121 	}
   122 	aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
   123 	error = (struct sctp_error_cause *)(aph + 1);
   125 	aph->correlation_id = id;
   126 	aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND);
   127 	error->code = htons(cause);
   128 	error->length = tlv_length + sizeof(struct sctp_error_cause);
   129 	aph->ph.param_length = error->length +
   130 	    sizeof(struct sctp_asconf_paramhdr);
   132 	if (aph->ph.param_length > MLEN) {
   133 		SCTPDBG(SCTP_DEBUG_ASCONF1,
   134 			"asconf_error_response: tlv_length (%xh) too big\n",
   135 			tlv_length);
   136 		sctp_m_freem(m_reply);	/* discard */
   137 		return (NULL);
   138 	}
   139 	if (error_tlv != NULL) {
   140 		tlv = (uint8_t *) (error + 1);
   141 		memcpy(tlv, error_tlv, tlv_length);
   142 	}
   143 	SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
   144 	error->length = htons(error->length);
   145 	aph->ph.param_length = htons(aph->ph.param_length);
   147 	return (m_reply);
   148 }
   150 static struct mbuf *
   151 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 	struct mbuf *m_reply = NULL;
   156 	struct sockaddr_storage sa_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 	int zero_address = 0;
   164 	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
   174 	aparam_length = ntohs(aph->ph.param_length);
   175 	ph = (struct sctp_paramhdr *)(aph + 1);
   176 	param_type = ntohs(ph->param_type);
   177 #if defined(INET) || defined(INET6)
   178 	param_length = ntohs(ph->param_length);
   179 #endif
   180 	sa = (struct sockaddr *)&sa_store;
   181 	switch (param_type) {
   182 #ifdef INET
   183 	case SCTP_IPV4_ADDRESS:
   184 		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
   185 			/* invalid param size */
   186 			return (NULL);
   187 		}
   188 		v4addr = (struct sctp_ipv4addr_param *)ph;
   189 		sin = (struct sockaddr_in *)&sa_store;
   190 		bzero(sin, sizeof(*sin));
   191 		sin->sin_family = AF_INET;
   192 #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 = (struct sockaddr_in6 *)&sa_store;
   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 		m_reply = sctp_asconf_error_response(aph->correlation_id,
   234 		    SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
   235 		    aparam_length);
   236 		return (m_reply);
   237 	}			/* end switch */
   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 }
   275 static int
   276 sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src)
   277 {
   278 	struct sctp_nets *src_net, *net;
   280 	/* make sure the source address exists as a destination net */
   281 	src_net = sctp_findnet(stcb, src);
   282 	if (src_net == NULL) {
   283 		/* not found */
   284 		return (-1);
   285 	}
   287 	/* delete all destination addresses except the source */
   288 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   289 		if (net != src_net) {
   290 			/* delete this address */
   291 			sctp_remove_net(stcb, net);
   292 			SCTPDBG(SCTP_DEBUG_ASCONF1,
   293 				"asconf_del_remote_addrs_except: deleting ");
   294 			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1,
   295 				     (struct sockaddr *)&net->ro._l_addr);
   296 			/* notify upper layer */
   297 			sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0,
   298 			    (struct sockaddr *)&net->ro._l_addr, SCTP_SO_NOT_LOCKED);
   299 		}
   300 	}
   301 	return (0);
   302 }
   304 static struct mbuf *
   305 sctp_process_asconf_delete_ip(struct sockaddr *src,
   306                               struct sctp_asconf_paramhdr *aph,
   307 			      struct sctp_tcb *stcb, int response_required)
   308 {
   309 	struct mbuf *m_reply = NULL;
   310 	struct sockaddr_storage sa_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 	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
   328 	aparam_length = ntohs(aph->ph.param_length);
   329 	ph = (struct sctp_paramhdr *)(aph + 1);
   330 	param_type = ntohs(ph->param_type);
   331 #if defined(INET) || defined(INET6)
   332 	param_length = ntohs(ph->param_length);
   333 #endif
   334 	sa = (struct sockaddr *)&sa_store;
   335 	switch (param_type) {
   336 #ifdef INET
   337 	case SCTP_IPV4_ADDRESS:
   338 		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
   339 			/* invalid param size */
   340 			return (NULL);
   341 		}
   342 		v4addr = (struct sctp_ipv4addr_param *)ph;
   343 		sin = (struct sockaddr_in *)&sa_store;
   344 		bzero(sin, sizeof(*sin));
   345 		sin->sin_family = AF_INET;
   346 #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 = (struct sockaddr_in6 *)&sa_store;
   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 		m_reply = sctp_asconf_error_response(aph->correlation_id,
   383 		    SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
   384 		    aparam_length);
   385 		return (m_reply);
   386 	}
   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 	}
   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);
   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 	}
   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 }
   440 static struct mbuf *
   441 sctp_process_asconf_set_primary(struct sockaddr *src,
   442 				struct sctp_asconf_paramhdr *aph,
   443 				struct sctp_tcb *stcb, int response_required)
   444 {
   445 	struct mbuf *m_reply = NULL;
   446 	struct sockaddr_storage sa_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 	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
   463 	aparam_length = ntohs(aph->ph.param_length);
   464 	ph = (struct sctp_paramhdr *)(aph + 1);
   465 	param_type = ntohs(ph->param_type);
   466 #if defined(INET) || defined(INET6)
   467 	param_length = ntohs(ph->param_length);
   468 #endif
   469 	sa = (struct sockaddr *)&sa_store;
   470 	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 = (struct sockaddr_in *)&sa_store;
   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 = (struct sockaddr_in6 *)&sa_store;
   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 		m_reply = sctp_asconf_error_response(aph->correlation_id,
   514 		    SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
   515 		    aparam_length);
   516 		return (m_reply);
   517 	}
   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) {
   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 	}
   587 	return (m_reply);
   588 }
   590 /*
   591  * handles an ASCONF chunk.
   592  * if all parameters are processed ok, send a plain (empty) ASCONF-ACK
   593  */
   594 void
   595 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, *ack_aph;
   605 	struct sctp_ipv6addr_param *p_addr;
   606 	unsigned int asconf_limit, cnt;
   607 	int error = 0;		/* did an error occur? */
   609 	/* asconf param buffer */
   610 	uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
   611 	struct sctp_asconf_ack *ack, *ack_next;
   613 	/* verify minimum length */
   614 	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) {
   615 		SCTPDBG(SCTP_DEBUG_ASCONF1,
   616 			"handle_asconf: chunk too small = %xh\n",
   617 			ntohs(cp->ch.chunk_length));
   618 		return;
   619 	}
   620 	asoc = &stcb->asoc;
   621 	serial_num = ntohl(cp->serial_number);
   623 	if (SCTP_TSN_GE(asoc->asconf_seq_in, serial_num)) {
   624 		/* got a duplicate ASCONF */
   625 		SCTPDBG(SCTP_DEBUG_ASCONF1,
   626 			"handle_asconf: got duplicate serial number = %xh\n",
   627 			serial_num);
   628 		return;
   629 	} else if (serial_num != (asoc->asconf_seq_in + 1)) {
   630 		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: incorrect serial number = %xh (expected next = %xh)\n",
   631 			serial_num, asoc->asconf_seq_in + 1);
   632 		return;
   633 	}
   635 	/* it's the expected "next" sequence number, so process it */
   636 	asoc->asconf_seq_in = serial_num;	/* update sequence */
   637 	/* get length of all the param's in the ASCONF */
   638 	asconf_limit = offset + ntohs(cp->ch.chunk_length);
   639 	SCTPDBG(SCTP_DEBUG_ASCONF1,
   640 		"handle_asconf: asconf_limit=%u, sequence=%xh\n",
   641 		asconf_limit, serial_num);
   643 	if (first) {
   644 		/* delete old cache */
   645 		SCTPDBG(SCTP_DEBUG_ASCONF1,"handle_asconf: Now processing first ASCONF. Try to delete old cache\n");
   647 		TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) {
   648 			if (ack->serial_number == serial_num)
   649 				break;
   650 			SCTPDBG(SCTP_DEBUG_ASCONF1,"handle_asconf: delete old(%u) < first(%u)\n",
   651 			    ack->serial_number, serial_num);
   652 			TAILQ_REMOVE(&asoc->asconf_ack_sent, ack, next);
   653 			if (ack->data != NULL) {
   654 				sctp_m_freem(ack->data);
   655 			}
   656 			SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack);
   657 		}
   658 	}
   660 	m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0,
   661 				      M_NOWAIT, 1, MT_DATA);
   662 	if (m_ack == NULL) {
   663 		SCTPDBG(SCTP_DEBUG_ASCONF1,
   664 			"handle_asconf: couldn't get mbuf!\n");
   665 		return;
   666 	}
   667 	m_tail = m_ack;		/* current reply chain's tail */
   669 	/* fill in ASCONF-ACK header */
   670 	ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *);
   671 	ack_cp->ch.chunk_type = SCTP_ASCONF_ACK;
   672 	ack_cp->ch.chunk_flags = 0;
   673 	ack_cp->serial_number = htonl(serial_num);
   674 	/* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */
   675 	SCTP_BUF_LEN(m_ack) = sizeof(struct sctp_asconf_ack_chunk);
   676 	ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk);
   678 	/* skip the lookup address parameter */
   679 	offset += sizeof(struct sctp_asconf_chunk);
   680 	p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *)&aparam_buf);
   681 	if (p_addr == NULL) {
   682 		SCTPDBG(SCTP_DEBUG_ASCONF1,
   683 			"handle_asconf: couldn't get lookup addr!\n");
   684 		/* respond with a missing/invalid mandatory parameter error */
   685 		return;
   686 	}
   687 	/* param_length is already validated in process_control... */
   688 	offset += ntohs(p_addr->ph.param_length);	/* skip lookup addr */
   690 	/* get pointer to first asconf param in ASCONF-ACK */
   691 	ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t) + sizeof(struct sctp_asconf_ack_chunk));
   692 	if (ack_aph == NULL) {
   693 		SCTPDBG(SCTP_DEBUG_ASCONF1, "Gak in asconf2\n");
   694 		return;
   695 	}
   696 	/* get pointer to first asconf param in ASCONF */
   697 	aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *)&aparam_buf);
   698 	if (aph == NULL) {
   699 		SCTPDBG(SCTP_DEBUG_ASCONF1, "Empty ASCONF received?\n");
   700 		goto send_reply;
   701 	}
   702 	/* process through all parameters */
   703 	cnt = 0;
   704 	while (aph != NULL) {
   705 		unsigned int param_length, param_type;
   707 		param_type = ntohs(aph->ph.param_type);
   708 		param_length = ntohs(aph->ph.param_length);
   709 		if (offset + param_length > asconf_limit) {
   710 			/* parameter goes beyond end of chunk! */
   711 			sctp_m_freem(m_ack);
   712 			return;
   713 		}
   714 		m_result = NULL;
   716 		if (param_length > sizeof(aparam_buf)) {
   717 			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) larger than buffer size!\n", param_length);
   718 			sctp_m_freem(m_ack);
   719 			return;
   720 		}
   721 		if (param_length <= sizeof(struct sctp_paramhdr)) {
   722 			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) too short\n", param_length);
   723 			sctp_m_freem(m_ack);
   724 		}
   725 		/* get the entire parameter */
   726 		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
   727 		if (aph == NULL) {
   728 			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: couldn't get entire param\n");
   729 			sctp_m_freem(m_ack);
   730 			return;
   731 		}
   732 		switch (param_type) {
   733 		case SCTP_ADD_IP_ADDRESS:
   734 			asoc->peer_supports_asconf = 1;
   735 			m_result = sctp_process_asconf_add_ip(src, aph, stcb,
   736 			    (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error);
   737 			cnt++;
   738 			break;
   739 		case SCTP_DEL_IP_ADDRESS:
   740 			asoc->peer_supports_asconf = 1;
   741 			m_result = sctp_process_asconf_delete_ip(src, aph, stcb,
   742 			    error);
   743 			break;
   744 		case SCTP_ERROR_CAUSE_IND:
   745 			/* not valid in an ASCONF chunk */
   746 			break;
   747 		case SCTP_SET_PRIM_ADDR:
   748 			asoc->peer_supports_asconf = 1;
   749 			m_result = sctp_process_asconf_set_primary(src, aph,
   750 			    stcb, error);
   751 			break;
   752 		case SCTP_NAT_VTAGS:
   753 		        SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: sees a NAT VTAG state parameter\n");
   754 		        break;
   755 		case SCTP_SUCCESS_REPORT:
   756 			/* not valid in an ASCONF chunk */
   757 			break;
   758 		case SCTP_ULP_ADAPTATION:
   759 			/* FIX */
   760 			break;
   761 		default:
   762 			if ((param_type & 0x8000) == 0) {
   763 				/* Been told to STOP at this param */
   764 				asconf_limit = offset;
   765 				/*
   766 				 * FIX FIX - We need to call
   767 				 * sctp_arethere_unrecognized_parameters()
   768 				 * to get a operr and send it for any
   769 				 * param's with the 0x4000 bit set OR do it
   770 				 * here ourselves... note we still must STOP
   771 				 * if the 0x8000 bit is clear.
   772 				 */
   773 			}
   774 			/* unknown/invalid param type */
   775 			break;
   776 		} /* switch */
   778 		/* add any (error) result to the reply mbuf chain */
   779 		if (m_result != NULL) {
   780 			SCTP_BUF_NEXT(m_tail) = m_result;
   781 			m_tail = m_result;
   782 			/* update lengths, make sure it's aligned too */
   783 			SCTP_BUF_LEN(m_result) = SCTP_SIZE32(SCTP_BUF_LEN(m_result));
   784 			ack_cp->ch.chunk_length += SCTP_BUF_LEN(m_result);
   785 			/* set flag to force success reports */
   786 			error = 1;
   787 		}
   788 		offset += SCTP_SIZE32(param_length);
   789 		/* update remaining ASCONF message length to process */
   790 		if (offset >= asconf_limit) {
   791 			/* no more data in the mbuf chain */
   792 			break;
   793 		}
   794 		/* get pointer to next asconf param */
   795 		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
   796 		    sizeof(struct sctp_asconf_paramhdr),
   797 		    (uint8_t *)&aparam_buf);
   798 		if (aph == NULL) {
   799 			/* can't get an asconf paramhdr */
   800 			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: can't get asconf param hdr!\n");
   801 			/* FIX ME - add error here... */
   802 		}
   803 	}
   805  send_reply:
   806 	ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length);
   807 	/* save the ASCONF-ACK reply */
   808 	ack = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_asconf_ack),
   809 	    struct sctp_asconf_ack);
   810 	if (ack == NULL) {
   811 		sctp_m_freem(m_ack);
   812 		return;
   813 	}
   814 	ack->serial_number = serial_num;
   815 	ack->last_sent_to = NULL;
   816 	ack->data = m_ack;
   817 	ack->len = 0;
   818 	for (n = m_ack; n != NULL; n = SCTP_BUF_NEXT(n)) {
   819 		ack->len += SCTP_BUF_LEN(n);
   820 	}
   821 	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next);
   823 	/* see if last_control_chunk_from is set properly (use IP src addr) */
   824 	if (stcb->asoc.last_control_chunk_from == NULL) {
   825 		/*
   826 		 * this could happen if the source address was just newly
   827 		 * added
   828 		 */
   829 		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n");
   830 		SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: ");
   831 		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src);
   832 		/* look up the from address */
   833 		stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, src);
   834 #ifdef SCTP_DEBUG
   835 		if (stcb->asoc.last_control_chunk_from == NULL) {
   836 			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n");
   837 		}
   838 #endif
   839 	}
   840 }
   842 /*
   843  * does the address match? returns 0 if not, 1 if so
   844  */
   845 static uint32_t
   846 sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
   847 {
   848 	switch (sa->sa_family) {
   849 #ifdef INET6
   850 	case AF_INET6:
   851 	{
   852 		/* XXX scopeid */
   853 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
   855 		if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) &&
   856 		    (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr,
   857 		    sizeof(struct in6_addr)) == 0)) {
   858 			return (1);
   859 		}
   860 		break;
   861 	}
   862 #endif
   863 #ifdef INET
   864 	case AF_INET:
   865 	{
   866 		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
   868 		if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) &&
   869 		    (memcmp(&aa->ap.addrp.addr, &sin->sin_addr,
   870 		    sizeof(struct in_addr)) == 0)) {
   871 			return (1);
   872 		}
   873 		break;
   874 	}
   875 #endif
   876 	default:
   877 		break;
   878 	}
   879 	return (0);
   880 }
   882 /*
   883  * does the address match? returns 0 if not, 1 if so
   884  */
   885 static uint32_t
   886 sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
   887 {
   888 #if defined(INET) || defined(INET6)
   889 	uint16_t param_type, param_length;
   891 	param_type = ntohs(ph->param_type);
   892 	param_length = ntohs(ph->param_length);
   893 #endif
   894 	switch (sa->sa_family) {
   895 #ifdef INET6
   896 	case AF_INET6:
   897 	{
   898 		/* XXX scopeid */
   899 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
   900 		struct sctp_ipv6addr_param *v6addr;
   902 		v6addr = (struct sctp_ipv6addr_param *)ph;
   903 		if ((param_type == SCTP_IPV6_ADDRESS) &&
   904 		    (param_length == sizeof(struct sctp_ipv6addr_param)) &&
   905 		    (memcmp(&v6addr->addr, &sin6->sin6_addr,
   906 		    sizeof(struct in6_addr)) == 0)) {
   907 			return (1);
   908 		}
   909 		break;
   910 	}
   911 #endif
   912 #ifdef INET
   913 	case AF_INET:
   914 	{
   915 		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
   916 		struct sctp_ipv4addr_param *v4addr;
   918 		v4addr = (struct sctp_ipv4addr_param *)ph;
   919 		if ((param_type == SCTP_IPV4_ADDRESS) &&
   920 		    (param_length == sizeof(struct sctp_ipv4addr_param)) &&
   921 		    (memcmp(&v4addr->addr, &sin->sin_addr,
   922 		    sizeof(struct in_addr)) == 0)) {
   923 			return (1);
   924 		}
   925 		break;
   926 	}
   927 #endif
   928 	default:
   929 		break;
   930 	}
   931 	return (0);
   932 }
   933 /*
   934  * Cleanup for non-responded/OP ERR'd ASCONF
   935  */
   936 void
   937 sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
   938 {
   939 	/* mark peer as ASCONF incapable */
   940 	stcb->asoc.peer_supports_asconf = 0;
   941 	/*
   942 	 * clear out any existing asconfs going out
   943 	 */
   944 	sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
   945 			SCTP_FROM_SCTP_ASCONF+SCTP_LOC_2);
   946 	stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out;
   947 	/* remove the old ASCONF on our outbound queue */
   948 	sctp_toss_old_asconf(stcb);
   949 }
   951 /*
   952  * cleanup any cached source addresses that may be topologically
   953  * incorrect after a new address has been added to this interface.
   954  */
   955 static void
   956 sctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn)
   957 {
   958 	struct sctp_nets *net;
   960 	/*
   961 	 * Ideally, we want to only clear cached routes and source addresses
   962 	 * that are topologically incorrect.  But since there is no easy way
   963 	 * to know whether the newly added address on the ifn would cause a
   964 	 * routing change (i.e. a new egress interface would be chosen)
   965 	 * without doing a new routing lookup and source address selection,
   966 	 * we will (for now) just flush any cached route using a different
   967 	 * ifn (and cached source addrs) and let output re-choose them during
   968 	 * the next send on that net.
   969 	 */
   970 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   971 		/*
   972 		 * clear any cached route (and cached source address) if the
   973 		 * route's interface is NOT the same as the address change.
   974 		 * If it's the same interface, just clear the cached source
   975 		 * address.
   976 		 */
   977 		if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) &&
   978 		    ((ifn == NULL) ||
   979 		     (SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) {
   980 			/* clear any cached route */
   981 			RTFREE(net->ro.ro_rt);
   982 			net->ro.ro_rt = NULL;
   983 		}
   984 		/* clear any cached source address */
   985 		if (net->src_addr_selected) {
   986 			sctp_free_ifa(net->ro._s_addr);
   987 			net->ro._s_addr = NULL;
   988 			net->src_addr_selected = 0;
   989 		}
   990 	}
   991 }
   994 void
   995 sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet)
   996 {
   997 	int error;
   999 	if (dstnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
  1000 		return;
  1002 	if (stcb->asoc.deleted_primary == NULL) {
  1003 		return;
  1006 	if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
  1007 		SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Deleted primary is ");
  1008 		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa);
  1009 		SCTPDBG(SCTP_DEBUG_ASCONF1, "Current Primary is ");
  1010 		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa);
  1011 		sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb,
  1012 				stcb->asoc.deleted_primary,
  1013 				SCTP_FROM_SCTP_TIMER+SCTP_LOC_8);
  1014 		stcb->asoc.num_send_timers_up--;
  1015 		if (stcb->asoc.num_send_timers_up < 0) {
  1016 			stcb->asoc.num_send_timers_up = 0;
  1018 		SCTP_TCB_LOCK_ASSERT(stcb);
  1019 		error = sctp_t3rxt_timer(stcb->sctp_ep, stcb,
  1020 					stcb->asoc.deleted_primary);
  1021 		if (error) {
  1022 			SCTP_INP_DECR_REF(stcb->sctp_ep);
  1023 			return;
  1025 		SCTP_TCB_LOCK_ASSERT(stcb);
  1026 #ifdef SCTP_AUDITING_ENABLED
  1027 		sctp_auditing(4, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary);
  1028 #endif
  1029 		sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
  1030 		if ((stcb->asoc.num_send_timers_up == 0) &&
  1031 		    (stcb->asoc.sent_queue_cnt > 0)) {
  1032 			struct sctp_tmit_chunk *chk;
  1034 			chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
  1035 			sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
  1036 					 stcb, chk->whoTo);
  1039 	return;
  1042 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__)
  1043 static int
  1044 sctp_asconf_queue_mgmt(struct sctp_tcb *, struct sctp_ifa *, uint16_t);
  1046 void
  1047 sctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net)
  1049 	struct sctp_tmit_chunk *chk;
  1051 	SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO);
  1052 	sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net,
  1053 	    SCTP_FROM_SCTP_TIMER+SCTP_LOC_5);
  1054 	stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
  1055 	net->error_count = 0;
  1056 	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
  1057 		if (chk->whoTo == net) {
  1058 			if (chk->sent < SCTP_DATAGRAM_RESEND) {
  1059 				chk->sent = SCTP_DATAGRAM_RESEND;
  1060 				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
  1061 				sctp_flight_size_decrease(chk);
  1062 				sctp_total_flight_decrease(stcb, chk);
  1063 				net->marked_retrans++;
  1064 				stcb->asoc.marked_retrans++;
  1068 	if (net->marked_retrans) {
  1069 		sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
  1073 static void
  1074 sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
  1076 	struct sctp_nets *net;
  1077 	int addrnum, changed;
  1079 	/*   If number of local valid addresses is 1, the valid address is
  1080 	     probably newly added address.
  1081 	     Several valid addresses in this association.  A source address
  1082 	     may not be changed.  Additionally, they can be configured on a
  1083 	     same interface as "alias" addresses.  (by micchie)
  1084 	 */
  1085 	addrnum = sctp_local_addr_count(stcb);
  1086 	SCTPDBG(SCTP_DEBUG_ASCONF1, "p_check_react(): %d local addresses\n",
  1087 		addrnum);
  1088 	if (addrnum == 1) {
  1089 		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
  1090 			/* clear any cached route and source address */
  1091 			if (net->ro.ro_rt) {
  1092 				RTFREE(net->ro.ro_rt);
  1093 				net->ro.ro_rt = NULL;
  1095 			if (net->src_addr_selected) {
  1096 				sctp_free_ifa(net->ro._s_addr);
  1097 				net->ro._s_addr = NULL;
  1098 				net->src_addr_selected = 0;
  1100 			/* Retransmit unacknowledged DATA chunks immediately */
  1101 			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
  1102 		    		SCTP_MOBILITY_FASTHANDOFF)) {
  1103 				sctp_net_immediate_retrans(stcb, net);
  1105 			/* also, SET PRIMARY is maybe already sent */
  1107 		return;
  1110 	/* Multiple local addresses exsist in the association.  */
  1111 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
  1112 		/* clear any cached route and source address */
  1113 		if (net->ro.ro_rt) {
  1114 			RTFREE(net->ro.ro_rt);
  1115 			net->ro.ro_rt = NULL;
  1117 		if (net->src_addr_selected) {
  1118 			sctp_free_ifa(net->ro._s_addr);
  1119 			net->ro._s_addr = NULL;
  1120 			net->src_addr_selected = 0;
  1122 		/* Check if the nexthop is corresponding to the new address.
  1123 		   If the new address is corresponding to the current nexthop,
  1124 		   the path will be changed.
  1125 		   If the new address is NOT corresponding to the current
  1126 		   nexthop, the path will not be changed.
  1127 		 */
  1128 		SCTP_RTALLOC((sctp_route_t *)&net->ro,
  1129 			     stcb->sctp_ep->def_vrf_id);
  1130 		if (net->ro.ro_rt == NULL)
  1131 			continue;
  1133 		changed = 0;
  1134 		switch (net->ro._l_addr.sa.sa_family) {
  1135 #ifdef INET
  1136 		case AF_INET:
  1137 			if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *)&net->ro)) {
  1138 				changed = 1;
  1140 			break;
  1141 #endif
  1142 #ifdef INET6
  1143 		case AF_INET6:
  1144 			if (sctp_v6src_match_nexthop(
  1145 			    &newifa->address.sin6, (sctp_route_t *)&net->ro)) {
  1146 				changed = 1;
  1148 			break;
  1149 #endif
  1150 		default:
  1151 			break;
  1153 		/* if the newly added address does not relate routing
  1154 		   information, we skip.
  1155 		 */
  1156 		if (changed == 0)
  1157 			continue;
  1158 		/* Retransmit unacknowledged DATA chunks immediately */
  1159 		if (sctp_is_mobility_feature_on(stcb->sctp_ep,
  1160 		   		SCTP_MOBILITY_FASTHANDOFF)) {
  1161 			sctp_net_immediate_retrans(stcb, net);
  1163 		/* Send SET PRIMARY for this new address */
  1164 		if (net == stcb->asoc.primary_destination) {
  1165 			(void)sctp_asconf_queue_mgmt(stcb, newifa,
  1166 						     SCTP_SET_PRIM_ADDR);
  1170 #endif /* __FreeBSD__  __APPLE__  __Userspace__ */
  1172 /*
  1173  * process an ADD/DELETE IP ack from peer.
  1174  * addr: corresponding sctp_ifa to the address being added/deleted.
  1175  * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS.
  1176  * flag: 1=success, 0=failure.
  1177  */
  1178 static void
  1179 sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr, uint32_t flag)
  1181 	/*
  1182 	 * do the necessary asoc list work- if we get a failure indication,
  1183 	 * leave the address on the assoc's restricted list.  If we get a
  1184 	 * success indication, remove the address from the restricted list.
  1185 	 */
  1186 	/*
  1187 	 * Note: this will only occur for ADD_IP_ADDRESS, since
  1188 	 * DEL_IP_ADDRESS is never actually added to the list...
  1189 	 */
  1190 	if (flag) {
  1191 		/* success case, so remove from the restricted list */
  1192 		sctp_del_local_addr_restricted(stcb, addr);
  1194 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__)
  1195 		if (sctp_is_mobility_feature_on(stcb->sctp_ep,
  1196 						SCTP_MOBILITY_BASE) ||
  1197 		    sctp_is_mobility_feature_on(stcb->sctp_ep,
  1198 			    			SCTP_MOBILITY_FASTHANDOFF)) {
  1199 			sctp_path_check_and_react(stcb, addr);
  1200 			return;
  1202 #endif /* __FreeBSD__ __APPLE__ __Userspace__ */
  1203 		/* clear any cached/topologically incorrect source addresses */
  1204 		sctp_asconf_nets_cleanup(stcb, addr->ifn_p);
  1206 	/* else, leave it on the list */
  1209 /*
  1210  * add an asconf add/delete/set primary IP address parameter to the queue.
  1211  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
  1212  * returns 0 if queued, -1 if not queued/removed.
  1213  * NOTE: if adding, but a delete for the same address is already scheduled
  1214  * (and not yet sent out), simply remove it from queue.  Same for deleting
  1215  * an address already scheduled for add.  If a duplicate operation is found,
  1216  * ignore the new one.
  1217  */
  1218 static int
  1219 sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
  1220 		       uint16_t type)
  1222 	struct sctp_asconf_addr *aa, *aa_next;
  1224 	/* make sure the request isn't already in the queue */
  1225 	TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
  1226 		/* address match? */
  1227 		if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0)
  1228 			continue;
  1229 		/* is the request already in queue but not sent?
  1230 		 * pass the request already sent in order to resolve the following case:
  1231 		 *  1. arrival of ADD, then sent
  1232 		 *  2. arrival of DEL. we can't remove the ADD request already sent
  1233 		 *  3. arrival of ADD
  1234 		 */
  1235 		if (aa->ap.aph.ph.param_type == type && aa->sent == 0) {
  1236 			return (-1);
  1238 		/* is the negative request already in queue, and not sent */
  1239 		if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) &&
  1240 		    (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) {
  1241 			/* add requested, delete already queued */
  1242 			TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
  1243 			/* remove the ifa from the restricted list */
  1244 			sctp_del_local_addr_restricted(stcb, ifa);
  1245 			/* free the asconf param */
  1246 			SCTP_FREE(aa, SCTP_M_ASC_ADDR);
  1247 			SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n");
  1248 			return (-1);
  1250 		if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) &&
  1251 		    (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) {
  1252 			/* delete requested, add already queued */
  1253 			TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
  1254 			/* remove the aa->ifa from the restricted list */
  1255 			sctp_del_local_addr_restricted(stcb, aa->ifa);
  1256 			/* free the asconf param */
  1257 			SCTP_FREE(aa, SCTP_M_ASC_ADDR);
  1258 			SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n");
  1259 			return (-1);
  1261 	} /* for each aa */
  1263 	/* adding new request to the queue */
  1264 	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
  1265 		    SCTP_M_ASC_ADDR);
  1266 	if (aa == NULL) {
  1267 		/* didn't get memory */
  1268 		SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n");
  1269 		return (-1);
  1271 	aa->special_del = 0;
  1272 	/* fill in asconf address parameter fields */
  1273 	/* top level elements are "networked" during send */
  1274 	aa->ap.aph.ph.param_type = type;
  1275 	aa->ifa = ifa;
  1276 	atomic_add_int(&ifa->refcount, 1);
  1277 	/* correlation_id filled in during send routine later... */
  1278 	switch (ifa->address.sa.sa_family) {
  1279 #ifdef INET6
  1280 	case AF_INET6:
  1282 		struct sockaddr_in6 *sin6;
  1284 		sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
  1285 		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
  1286 		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
  1287 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
  1288 		    sizeof(struct sctp_ipv6addr_param);
  1289 		memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
  1290 		       sizeof(struct in6_addr));
  1291 		break;
  1293 #endif
  1294 #ifdef INET
  1295 	case AF_INET:
  1297 		struct sockaddr_in *sin;
  1299 		sin= (struct sockaddr_in *)&ifa->address.sa;
  1300 		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
  1301 		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
  1302 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
  1303 		    sizeof(struct sctp_ipv4addr_param);
  1304 		memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
  1305 		       sizeof(struct in_addr));
  1306 		break;
  1308 #endif
  1309 	default:
  1310 		/* invalid family! */
  1311 		SCTP_FREE(aa, SCTP_M_ASC_ADDR);
  1312 		sctp_free_ifa(ifa);
  1313 		return (-1);
  1315 	aa->sent = 0;		/* clear sent flag */
  1317 	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
  1318 #ifdef SCTP_DEBUG
  1319 	if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) {
  1320 		if (type == SCTP_ADD_IP_ADDRESS) {
  1321 			SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: ");
  1322 			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
  1323 		} else if (type == SCTP_DEL_IP_ADDRESS) {
  1324 			SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: ");
  1325 			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
  1326 		} else {
  1327 			SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: ");
  1328 			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
  1331 #endif
  1333 	return (0);
  1337 /*
  1338  * add an asconf operation for the given ifa and type.
  1339  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
  1340  * returns 0 if completed, -1 if not completed, 1 if immediate send is
  1341  * advisable.
  1342  */
  1343 static int
  1344 sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
  1345 		      uint16_t type)
  1347 	uint32_t status;
  1348 	int pending_delete_queued = 0;
  1350 	/* see if peer supports ASCONF */
  1351 	if (stcb->asoc.peer_supports_asconf == 0) {
  1352 		return (-1);
  1355 	/*
  1356 	 * if this is deleting the last address from the assoc, mark it as
  1357 	 * pending.
  1358 	 */
  1359 	if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending &&
  1360 	    (sctp_local_addr_count(stcb) < 2)) {
  1361 		/* set the pending delete info only */
  1362 		stcb->asoc.asconf_del_pending = 1;
  1363 		stcb->asoc.asconf_addr_del_pending = ifa;
  1364 		atomic_add_int(&ifa->refcount, 1);
  1365 		SCTPDBG(SCTP_DEBUG_ASCONF2,
  1366 			"asconf_queue_add: mark delete last address pending\n");
  1367 		return (-1);
  1370 	/* queue an asconf parameter */
  1371 	status = sctp_asconf_queue_mgmt(stcb, ifa, type);
  1373 	/*
  1374 	 * if this is an add, and there is a delete also pending (i.e. the
  1375 	 * last local address is being changed), queue the pending delete too.
  1376 	 */
  1377 	if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) {
  1378 		/* queue in the pending delete */
  1379 		if (sctp_asconf_queue_mgmt(stcb,
  1380 					   stcb->asoc.asconf_addr_del_pending,
  1381 					   SCTP_DEL_IP_ADDRESS) == 0) {
  1382 			SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n");
  1383 			pending_delete_queued = 1;
  1384 			/* clear out the pending delete info */
  1385 			stcb->asoc.asconf_del_pending = 0;
  1386 			sctp_free_ifa(stcb->asoc.asconf_addr_del_pending);
  1387 			stcb->asoc.asconf_addr_del_pending = NULL;
  1391 	if (pending_delete_queued) {
  1392 		struct sctp_nets *net;
  1393 		/*
  1394 		 * since we know that the only/last address is now being
  1395 		 * changed in this case, reset the cwnd/rto on all nets to
  1396 		 * start as a new address and path.  Also clear the error
  1397 		 * counts to give the assoc the best chance to complete the
  1398 		 * address change.
  1399 		 */
  1400 		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
  1401 			stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb,
  1402 									  net);
  1403 			net->RTO = 0;
  1404 			net->error_count = 0;
  1406 		stcb->asoc.overall_error_count = 0;
  1407 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
  1408 			sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
  1409 				       stcb->asoc.overall_error_count,
  1410 				       0,
  1411 				       SCTP_FROM_SCTP_ASCONF,
  1412 				       __LINE__);
  1415 		/* queue in an advisory set primary too */
  1416 		(void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR);
  1417 		/* let caller know we should send this out immediately */
  1418 		status = 1;
  1420 	return (status);
  1423 /*-
  1424  * add an asconf delete IP address parameter to the queue by sockaddr and
  1425  * possibly with no sctp_ifa available.  This is only called by the routine
  1426  * that checks the addresses in an INIT-ACK against the current address list.
  1427  * returns 0 if completed, non-zero if not completed.
  1428  * NOTE: if an add is already scheduled (and not yet sent out), simply
  1429  * remove it from queue.  If a duplicate operation is found, ignore the
  1430  * new one.
  1431  */
  1432 static int
  1433 sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
  1435 	struct sctp_ifa *ifa;
  1436 	struct sctp_asconf_addr *aa, *aa_next;
  1437 	uint32_t vrf_id;
  1439 	if (stcb == NULL) {
  1440 		return (-1);
  1442 	/* see if peer supports ASCONF */
  1443 	if (stcb->asoc.peer_supports_asconf == 0) {
  1444 		return (-1);
  1446 	/* make sure the request isn't already in the queue */
  1447 	TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
  1448 		/* address match? */
  1449 		if (sctp_asconf_addr_match(aa, sa) == 0)
  1450 			continue;
  1451 		/* is the request already in queue (sent or not) */
  1452 		if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
  1453 			return (-1);
  1455 		/* is the negative request already in queue, and not sent */
  1456 		if (aa->sent == 1)
  1457 			continue;
  1458 		if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) {
  1459 			/* add already queued, so remove existing entry */
  1460 			TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
  1461 			sctp_del_local_addr_restricted(stcb, aa->ifa);
  1462 			/* free the entry */
  1463 			SCTP_FREE(aa, SCTP_M_ASC_ADDR);
  1464 			return (-1);
  1466 	} /* for each aa */
  1468 	/* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */
  1469 	if (stcb) {
  1470 		vrf_id = stcb->asoc.vrf_id;
  1471 	} else {
  1472 		vrf_id = SCTP_DEFAULT_VRFID;
  1474 	ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
  1476 	/* adding new request to the queue */
  1477 	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
  1478 		    SCTP_M_ASC_ADDR);
  1479 	if (aa == NULL) {
  1480 		/* didn't get memory */
  1481 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  1482 			"sctp_asconf_queue_sa_delete: failed to get memory!\n");
  1483 		return (-1);
  1485 	aa->special_del = 0;
  1486 	/* fill in asconf address parameter fields */
  1487 	/* top level elements are "networked" during send */
  1488 	aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
  1489 	aa->ifa = ifa;
  1490 	if (ifa)
  1491 		atomic_add_int(&ifa->refcount, 1);
  1492 	/* correlation_id filled in during send routine later... */
  1493 	switch (sa->sa_family) {
  1494 #ifdef INET6
  1495 	case AF_INET6:
  1497 		/* IPv6 address */
  1498 		struct sockaddr_in6 *sin6;
  1500 		sin6 = (struct sockaddr_in6 *)sa;
  1501 		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
  1502 		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
  1503 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
  1504 		memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
  1505 		    sizeof(struct in6_addr));
  1506 		break;
  1508 #endif
  1509 #ifdef INET
  1510 	case AF_INET:
  1512 		/* IPv4 address */
  1513 		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
  1515 		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
  1516 		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
  1517 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
  1518 		memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
  1519 		    sizeof(struct in_addr));
  1520 		break;
  1522 #endif
  1523 	default:
  1524 		/* invalid family! */
  1525 		SCTP_FREE(aa, SCTP_M_ASC_ADDR);
  1526 		if (ifa)
  1527 			sctp_free_ifa(ifa);
  1528 		return (-1);
  1530 	aa->sent = 0;		/* clear sent flag */
  1532 	/* delete goes to the back of the queue */
  1533 	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
  1535 	/* sa_ignore MEMLEAK {memory is put on the tailq} */
  1536 	return (0);
  1539 /*
  1540  * find a specific asconf param on our "sent" queue
  1541  */
  1542 static struct sctp_asconf_addr *
  1543 sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
  1545 	struct sctp_asconf_addr *aa;
  1547 	TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
  1548 		if (aa->ap.aph.correlation_id == correlation_id &&
  1549 		    aa->sent == 1) {
  1550 			/* found it */
  1551 			return (aa);
  1554 	/* didn't find it */
  1555 	return (NULL);
  1558 /*
  1559  * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do
  1560  * notifications based on the error response
  1561  */
  1562 static void
  1563 sctp_asconf_process_error(struct sctp_tcb *stcb,
  1564 			  struct sctp_asconf_paramhdr *aph)
  1566 	struct sctp_error_cause *eh;
  1567 	struct sctp_paramhdr *ph;
  1568 	uint16_t param_type;
  1569 	uint16_t error_code;
  1571 	eh = (struct sctp_error_cause *)(aph + 1);
  1572 	ph = (struct sctp_paramhdr *)(eh + 1);
  1573 	/* validate lengths */
  1574 	if (htons(eh->length) + sizeof(struct sctp_error_cause) >
  1575 	    htons(aph->ph.param_length)) {
  1576 		/* invalid error cause length */
  1577 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  1578 			"asconf_process_error: cause element too long\n");
  1579 		return;
  1581 	if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) >
  1582 	    htons(eh->length)) {
  1583 		/* invalid included TLV length */
  1584 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  1585 			"asconf_process_error: included TLV too long\n");
  1586 		return;
  1588 	/* which error code ? */
  1589 	error_code = ntohs(eh->code);
  1590 	param_type = ntohs(aph->ph.param_type);
  1591 	/* FIX: this should go back up the REMOTE_ERROR ULP notify */
  1592 	switch (error_code) {
  1593 	case SCTP_CAUSE_RESOURCE_SHORTAGE:
  1594 		/* we allow ourselves to "try again" for this error */
  1595 		break;
  1596 	default:
  1597 		/* peer can't handle it... */
  1598 		switch (param_type) {
  1599 		case SCTP_ADD_IP_ADDRESS:
  1600 		case SCTP_DEL_IP_ADDRESS:
  1601 			stcb->asoc.peer_supports_asconf = 0;
  1602 			break;
  1603 		case SCTP_SET_PRIM_ADDR:
  1604 			stcb->asoc.peer_supports_asconf = 0;
  1605 			break;
  1606 		default:
  1607 			break;
  1612 /*
  1613  * process an asconf queue param.
  1614  * aparam: parameter to process, will be removed from the queue.
  1615  * flag: 1=success case, 0=failure case
  1616  */
  1617 static void
  1618 sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
  1619 			      struct sctp_asconf_addr *aparam, uint32_t flag)
  1621 	uint16_t param_type;
  1623 	/* process this param */
  1624 	param_type = aparam->ap.aph.ph.param_type;
  1625 	switch (param_type) {
  1626 	case SCTP_ADD_IP_ADDRESS:
  1627 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  1628 			"process_param_ack: added IP address\n");
  1629 		sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, flag);
  1630 		break;
  1631 	case SCTP_DEL_IP_ADDRESS:
  1632 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  1633 			"process_param_ack: deleted IP address\n");
  1634 		/* nothing really to do... lists already updated */
  1635 		break;
  1636 	case SCTP_SET_PRIM_ADDR:
  1637 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  1638 			"process_param_ack: set primary IP address\n");
  1639 		/* nothing to do... peer may start using this addr */
  1640 		if (flag == 0)
  1641 			stcb->asoc.peer_supports_asconf = 0;
  1642 		break;
  1643 	default:
  1644 		/* should NEVER happen */
  1645 		break;
  1648 	/* remove the param and free it */
  1649 	TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
  1650 	if (aparam->ifa)
  1651 		sctp_free_ifa(aparam->ifa);
  1652 	SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
  1655 /*
  1656  * cleanup from a bad asconf ack parameter
  1657  */
  1658 static void
  1659 sctp_asconf_ack_clear(struct sctp_tcb *stcb)
  1661 	/* assume peer doesn't really know how to do asconfs */
  1662 	stcb->asoc.peer_supports_asconf = 0;
  1663 	/* XXX we could free the pending queue here */
  1666 void
  1667 sctp_handle_asconf_ack(struct mbuf *m, int offset,
  1668 		       struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb,
  1669 		       struct sctp_nets *net, int *abort_no_unlock)
  1671 	struct sctp_association *asoc;
  1672 	uint32_t serial_num;
  1673 	uint16_t ack_length;
  1674 	struct sctp_asconf_paramhdr *aph;
  1675 	struct sctp_asconf_addr *aa, *aa_next;
  1676 	uint32_t last_error_id = 0;	/* last error correlation id */
  1677 	uint32_t id;
  1678 	struct sctp_asconf_addr *ap;
  1680 	/* asconf param buffer */
  1681 	uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
  1683 	/* verify minimum length */
  1684 	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) {
  1685 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  1686 			"handle_asconf_ack: chunk too small = %xh\n",
  1687 			ntohs(cp->ch.chunk_length));
  1688 		return;
  1690 	asoc = &stcb->asoc;
  1691 	serial_num = ntohl(cp->serial_number);
  1693 	/*
  1694 	 * NOTE: we may want to handle this differently- currently, we will
  1695 	 * abort when we get an ack for the expected serial number + 1 (eg.
  1696 	 * we didn't send it), process an ack normally if it is the expected
  1697 	 * serial number, and re-send the previous ack for *ALL* other
  1698 	 * serial numbers
  1699 	 */
  1701 	/*
  1702 	 * if the serial number is the next expected, but I didn't send it,
  1703 	 * abort the asoc, since someone probably just hijacked us...
  1704 	 */
  1705 	if (serial_num == (asoc->asconf_seq_out + 1)) {
  1706 		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
  1707 		sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, SCTP_SO_NOT_LOCKED);
  1708 		*abort_no_unlock = 1;
  1709 		return;
  1711 	if (serial_num != asoc->asconf_seq_out_acked + 1) {
  1712 		/* got a duplicate/unexpected ASCONF-ACK */
  1713 		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n",
  1714 			serial_num, asoc->asconf_seq_out_acked + 1);
  1715 		return;
  1718 	if (serial_num == asoc->asconf_seq_out - 1) {
  1719 		/* stop our timer */
  1720 		sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
  1721 				SCTP_FROM_SCTP_ASCONF+SCTP_LOC_3);
  1724 	/* process the ASCONF-ACK contents */
  1725 	ack_length = ntohs(cp->ch.chunk_length) -
  1726 	    sizeof(struct sctp_asconf_ack_chunk);
  1727 	offset += sizeof(struct sctp_asconf_ack_chunk);
  1728 	/* process through all parameters */
  1729 	while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) {
  1730 		unsigned int param_length, param_type;
  1732 		/* get pointer to next asconf parameter */
  1733 		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
  1734 		    sizeof(struct sctp_asconf_paramhdr), aparam_buf);
  1735 		if (aph == NULL) {
  1736 			/* can't get an asconf paramhdr */
  1737 			sctp_asconf_ack_clear(stcb);
  1738 			return;
  1740 		param_type = ntohs(aph->ph.param_type);
  1741 		param_length = ntohs(aph->ph.param_length);
  1742 		if (param_length > ack_length) {
  1743 			sctp_asconf_ack_clear(stcb);
  1744 			return;
  1746 		if (param_length < sizeof(struct sctp_paramhdr)) {
  1747 			sctp_asconf_ack_clear(stcb);
  1748 			return;
  1750 		/* get the complete parameter... */
  1751 		if (param_length > sizeof(aparam_buf)) {
  1752 			SCTPDBG(SCTP_DEBUG_ASCONF1,
  1753 				"param length (%u) larger than buffer size!\n", param_length);
  1754 			sctp_asconf_ack_clear(stcb);
  1755 			return;
  1757 		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
  1758 		if (aph == NULL) {
  1759 			sctp_asconf_ack_clear(stcb);
  1760 			return;
  1762 		/* correlation_id is transparent to peer, no ntohl needed */
  1763 		id = aph->correlation_id;
  1765 		switch (param_type) {
  1766 		case SCTP_ERROR_CAUSE_IND:
  1767 			last_error_id = id;
  1768 			/* find the corresponding asconf param in our queue */
  1769 			ap = sctp_asconf_find_param(stcb, id);
  1770 			if (ap == NULL) {
  1771 				/* hmm... can't find this in our queue! */
  1772 				break;
  1774 			/* process the parameter, failed flag */
  1775 			sctp_asconf_process_param_ack(stcb, ap, 0);
  1776 			/* process the error response */
  1777 			sctp_asconf_process_error(stcb, aph);
  1778 			break;
  1779 		case SCTP_SUCCESS_REPORT:
  1780 			/* find the corresponding asconf param in our queue */
  1781 			ap = sctp_asconf_find_param(stcb, id);
  1782 			if (ap == NULL) {
  1783 				/* hmm... can't find this in our queue! */
  1784 				break;
  1786 			/* process the parameter, success flag */
  1787 			sctp_asconf_process_param_ack(stcb, ap, 1);
  1788 			break;
  1789 		default:
  1790 			break;
  1791 		}		/* switch */
  1793 		/* update remaining ASCONF-ACK message length to process */
  1794 		ack_length -= SCTP_SIZE32(param_length);
  1795 		if (ack_length <= 0) {
  1796 			/* no more data in the mbuf chain */
  1797 			break;
  1799 		offset += SCTP_SIZE32(param_length);
  1800 	} /* while */
  1802 	/*
  1803 	 * if there are any "sent" params still on the queue, these are
  1804 	 * implicitly "success", or "failed" (if we got an error back) ...
  1805 	 * so process these appropriately
  1807 	 * we assume that the correlation_id's are monotonically increasing
  1808 	 * beginning from 1 and that we don't have *that* many outstanding
  1809 	 * at any given time
  1810 	 */
  1811 	if (last_error_id == 0)
  1812 		last_error_id--;	/* set to "max" value */
  1813 	TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
  1814 		if (aa->sent == 1) {
  1815 			/*
  1816 			 * implicitly successful or failed if correlation_id
  1817 			 * < last_error_id, then success else, failure
  1818 			 */
  1819 			if (aa->ap.aph.correlation_id < last_error_id)
  1820 				sctp_asconf_process_param_ack(stcb, aa, 1);
  1821 			else
  1822 				sctp_asconf_process_param_ack(stcb, aa, 0);
  1823 		} else {
  1824 			/*
  1825 			 * since we always process in order (FIFO queue) if
  1826 			 * we reach one that hasn't been sent, the rest
  1827 			 * should not have been sent either. so, we're
  1828 			 * done...
  1829 			 */
  1830 			break;
  1834 	/* update the next sequence number to use */
  1835 	asoc->asconf_seq_out_acked++;
  1836 	/* remove the old ASCONF on our outbound queue */
  1837 	sctp_toss_old_asconf(stcb);
  1838 	if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
  1839 #ifdef SCTP_TIMER_BASED_ASCONF
  1840 		/* we have more params, so restart our timer */
  1841 		sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep,
  1842 				 stcb, net);
  1843 #else
  1844 		/* we have more params, so send out more */
  1845 		sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
  1846 #endif
  1850 #ifdef INET6
  1851 static uint32_t
  1852 sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa)
  1854 	struct sockaddr_in6 *sin6, *net6;
  1855 	struct sctp_nets *net;
  1857 	if (sa->sa_family != AF_INET6) {
  1858 		/* wrong family */
  1859 		return (0);
  1861 	sin6 = (struct sockaddr_in6 *)sa;
  1862 	if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) {
  1863 		/* not link local address */
  1864 		return (0);
  1866 	/* hunt through our destination nets list for this scope_id */
  1867 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
  1868 		if (((struct sockaddr *)(&net->ro._l_addr))->sa_family !=
  1869 		    AF_INET6)
  1870 			continue;
  1871 		net6 = (struct sockaddr_in6 *)&net->ro._l_addr;
  1872 		if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0)
  1873 			continue;
  1874 		if (sctp_is_same_scope(sin6, net6)) {
  1875 			/* found one */
  1876 			return (1);
  1879 	/* didn't find one */
  1880 	return (0);
  1882 #endif
  1884 /*
  1885  * address management functions
  1886  */
  1887 static void
  1888 sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
  1889 		     struct sctp_ifa *ifa, uint16_t type, int addr_locked)
  1891 	int status;
  1893 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 ||
  1894 	    sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
  1895 		/* subset bound, no ASCONF allowed case, so ignore */
  1896 		return;
  1898 	/*
  1899 	 * note: we know this is not the subset bound, no ASCONF case eg.
  1900 	 * this is boundall or subset bound w/ASCONF allowed
  1901 	 */
  1903 	/* first, make sure it's a good address family */
  1904 	switch (ifa->address.sa.sa_family) {
  1905 #ifdef INET6
  1906 	case AF_INET6:
  1907 		break;
  1908 #endif
  1909 #ifdef INET
  1910 	case AF_INET:
  1911 		break;
  1912 #endif
  1913 	default:
  1914 		return;
  1916 #ifdef INET6
  1917 	/* make sure we're "allowed" to add this type of addr */
  1918 	if (ifa->address.sa.sa_family == AF_INET6) {
  1919 		/* invalid if we're not a v6 endpoint */
  1920 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)
  1921 			return;
  1922 		/* is the v6 addr really valid ? */
  1923 		if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
  1924 			return;
  1927 #endif
  1928 	/* put this address on the "pending/do not use yet" list */
  1929 	sctp_add_local_addr_restricted(stcb, ifa);
  1930 	/*
  1931 	 * check address scope if address is out of scope, don't queue
  1932 	 * anything... note: this would leave the address on both inp and
  1933 	 * asoc lists
  1934 	 */
  1935 	switch (ifa->address.sa.sa_family) {
  1936 #ifdef INET6
  1937 	case AF_INET6:
  1939 		struct sockaddr_in6 *sin6;
  1941 		sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
  1942 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  1943 			/* we skip unspecifed addresses */
  1944 			return;
  1946 		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
  1947 			if (stcb->asoc.scope.local_scope == 0) {
  1948 				return;
  1950 			/* is it the right link local scope? */
  1951 			if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
  1952 				return;
  1955 		if (stcb->asoc.scope.site_scope == 0 &&
  1956 		    IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
  1957 			return;
  1959 		break;
  1961 #endif
  1962 #ifdef INET
  1963 	case AF_INET:
  1965 		struct sockaddr_in *sin;
  1966 		struct in6pcb *inp6;
  1968 		inp6 = (struct in6pcb *)&inp->ip_inp.inp;
  1969 		/* invalid if we are a v6 only endpoint */
  1970 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
  1971 		    SCTP_IPV6_V6ONLY(inp6))
  1972 			return;
  1974 		sin = (struct sockaddr_in *)&ifa->address.sa;
  1975 		if (sin->sin_addr.s_addr == 0) {
  1976 			/* we skip unspecifed addresses */
  1977 			return;
  1979 		if (stcb->asoc.scope.ipv4_local_scope == 0 &&
  1980 		    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
  1981 			return;
  1983 		break;
  1985 #endif
  1986 	default:
  1987 		/* else, not AF_INET or AF_INET6, so skip */
  1988 		return;
  1991 	/* queue an asconf for this address add/delete */
  1992 	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
  1993 		/* does the peer do asconf? */
  1994 		if (stcb->asoc.peer_supports_asconf) {
  1995 			/* queue an asconf for this addr */
  1996 			status = sctp_asconf_queue_add(stcb, ifa, type);
  1998 			/*
  1999 			 * if queued ok, and in the open state, send out the
  2000 			 * ASCONF.  If in the non-open state, these will be
  2001 			 * sent when the state goes open.
  2002 			 */
  2003 			if (status == 0 &&
  2004 			    SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
  2005 #ifdef SCTP_TIMER_BASED_ASCONF
  2006 				sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
  2007 				    stcb, stcb->asoc.primary_destination);
  2008 #else
  2009 				sctp_send_asconf(stcb, NULL, addr_locked);
  2010 #endif
  2017 int
  2018 sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED)
  2020 	struct sctp_asconf_iterator *asc;
  2021 	struct sctp_ifa *ifa;
  2022 	struct sctp_laddr *l;
  2023 	int cnt_invalid = 0;
  2025 	asc = (struct sctp_asconf_iterator *)ptr;
  2026 	LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
  2027 		ifa = l->ifa;
  2028 		switch (ifa->address.sa.sa_family) {
  2029 #ifdef INET6
  2030 		case AF_INET6:
  2031 			/* invalid if we're not a v6 endpoint */
  2032 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
  2033 				cnt_invalid++;
  2034 				if (asc->cnt == cnt_invalid)
  2035 					return (1);
  2037 			break;
  2038 #endif
  2039 #ifdef INET
  2040 		case AF_INET:
  2042 			/* invalid if we are a v6 only endpoint */
  2043 			struct in6pcb *inp6;
  2044 			inp6 = (struct in6pcb *)&inp->ip_inp.inp;
  2045 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
  2046 			    SCTP_IPV6_V6ONLY(inp6)) {
  2047 				cnt_invalid++;
  2048 				if (asc->cnt == cnt_invalid)
  2049 					return (1);
  2051 			break;
  2053 #endif
  2054 		default:
  2055 			/* invalid address family */
  2056 			cnt_invalid++;
  2057 			if (asc->cnt == cnt_invalid)
  2058 				return (1);
  2061 	return (0);
  2064 static int
  2065 sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED)
  2067 	struct sctp_ifa *ifa;
  2068 	struct sctp_asconf_iterator *asc;
  2069 	struct sctp_laddr *laddr, *nladdr, *l;
  2071 	/* Only for specific case not bound all */
  2072 	asc = (struct sctp_asconf_iterator *)ptr;
  2073 	LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
  2074 		ifa = l->ifa;
  2075 		if (l->action == SCTP_ADD_IP_ADDRESS) {
  2076 			LIST_FOREACH(laddr, &inp->sctp_addr_list,
  2077 				     sctp_nxt_addr) {
  2078 				if (laddr->ifa == ifa) {
  2079 					laddr->action = 0;
  2080 					break;
  2084 		} else if (l->action == SCTP_DEL_IP_ADDRESS) {
  2085 			LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
  2086 				/* remove only after all guys are done */
  2087 				if (laddr->ifa == ifa) {
  2088 					sctp_del_local_addr_ep(inp, ifa);
  2093 	return (0);
  2096 void
  2097 sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
  2098 			  void *ptr, uint32_t val SCTP_UNUSED)
  2100 	struct sctp_asconf_iterator *asc;
  2101 	struct sctp_ifa *ifa;
  2102 	struct sctp_laddr *l;
  2103 	int cnt_invalid = 0;
  2104 	int type, status;
  2105 	int num_queued = 0;
  2107 	asc = (struct sctp_asconf_iterator *)ptr;
  2108 	LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
  2109 		ifa = l->ifa;
  2110 		type = l->action;
  2112 		/* address's vrf_id must be the vrf_id of the assoc */
  2113 		if (ifa->vrf_id != stcb->asoc.vrf_id) {
  2114 			continue;
  2117 		/* Same checks again for assoc */
  2118 		switch (ifa->address.sa.sa_family) {
  2119 #ifdef INET6
  2120 		case AF_INET6:
  2122 			/* invalid if we're not a v6 endpoint */
  2123 			struct sockaddr_in6 *sin6;
  2125 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
  2126 				cnt_invalid++;
  2127 				if (asc->cnt == cnt_invalid)
  2128 					return;
  2129 				else
  2130 					continue;
  2132 			sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
  2133 			if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  2134 				/* we skip unspecifed addresses */
  2135 				continue;
  2137 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
  2138 				if (stcb->asoc.scope.local_scope == 0) {
  2139 					continue;
  2141 				/* is it the right link local scope? */
  2142 				if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
  2143 					continue;
  2146 			break;
  2148 #endif
  2149 #ifdef INET
  2150 		case AF_INET:
  2152 			/* invalid if we are a v6 only endpoint */
  2153 			struct in6pcb *inp6;
  2154 			struct sockaddr_in *sin;
  2156 			inp6 = (struct in6pcb *)&inp->ip_inp.inp;
  2157 			/* invalid if we are a v6 only endpoint */
  2158 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
  2159 			    SCTP_IPV6_V6ONLY(inp6))
  2160 				continue;
  2162 			sin = (struct sockaddr_in *)&ifa->address.sa;
  2163 			if (sin->sin_addr.s_addr == 0) {
  2164 				/* we skip unspecifed addresses */
  2165 				continue;
  2167 			if (stcb->asoc.scope.ipv4_local_scope == 0 &&
  2168 			    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
  2169 				continue;
  2171 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
  2172 			    SCTP_IPV6_V6ONLY(inp6)) {
  2173 				cnt_invalid++;
  2174 				if (asc->cnt == cnt_invalid)
  2175 					return;
  2176 				else
  2177 					continue;
  2179 			break;
  2181 #endif
  2182 		default:
  2183 			/* invalid address family */
  2184 			cnt_invalid++;
  2185 			if (asc->cnt == cnt_invalid)
  2186 				return;
  2187 			else
  2188 				continue;
  2189 			break;
  2192 		if (type == SCTP_ADD_IP_ADDRESS) {
  2193 			/* prevent this address from being used as a source */
  2194 			sctp_add_local_addr_restricted(stcb, ifa);
  2195 		} else if (type == SCTP_DEL_IP_ADDRESS) {
  2196 			struct sctp_nets *net;
  2197 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
  2198 				sctp_rtentry_t *rt;
  2200 				/* delete this address if cached */
  2201 				if (net->ro._s_addr == ifa) {
  2202 					sctp_free_ifa(net->ro._s_addr);
  2203 					net->ro._s_addr = NULL;
  2204 					net->src_addr_selected = 0;
  2205 					rt = net->ro.ro_rt;
  2206 					if (rt) {
  2207 						RTFREE(rt);
  2208 						net->ro.ro_rt = NULL;
  2210 					/*
  2211 					 * Now we deleted our src address,
  2212 					 * should we not also now reset the
  2213 					 * cwnd/rto to start as if its a new
  2214 					 * address?
  2215 					 */
  2216 					stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
  2217 					net->RTO = 0;
  2221 		} else if (type == SCTP_SET_PRIM_ADDR) {
  2222 			if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
  2223 				/* must validate the ifa is in the ep */
  2224 				if (sctp_is_addr_in_ep(stcb->sctp_ep,ifa) == 0) {
  2225 					continue;
  2227 			} else {
  2228 				/* Need to check scopes for this guy */
  2229 				if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) {
  2230 					continue;
  2234 		/* queue an asconf for this address add/delete */
  2235 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
  2236 		    stcb->asoc.peer_supports_asconf) {
  2237 			/* queue an asconf for this addr */
  2238 			status = sctp_asconf_queue_add(stcb, ifa, type);
  2239 			/*
  2240 			 * if queued ok, and in the open state, update the
  2241 			 * count of queued params.  If in the non-open state,
  2242 			 * these get sent when the assoc goes open.
  2243 			 */
  2244 			if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
  2245 				if (status >= 0) {
  2246 					num_queued++;
  2251 	/*
  2252 	 * If we have queued params in the open state, send out an ASCONF.
  2253 	 */
  2254 	if (num_queued > 0) {
  2255 		sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
  2259 void
  2260 sctp_asconf_iterator_end(void *ptr, uint32_t val SCTP_UNUSED)
  2262 	struct sctp_asconf_iterator *asc;
  2263 	struct sctp_ifa *ifa;
  2264 	struct sctp_laddr *l, *nl;
  2266 	asc = (struct sctp_asconf_iterator *)ptr;
  2267 	LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) {
  2268 		ifa = l->ifa;
  2269 		if (l->action == SCTP_ADD_IP_ADDRESS) {
  2270 			/* Clear the defer use flag */
  2271 			ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
  2273 		sctp_free_ifa(ifa);
  2274 		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l);
  2275 		SCTP_DECR_LADDR_COUNT();
  2277 	SCTP_FREE(asc, SCTP_M_ASC_IT);
  2280 /*
  2281  * sa is the sockaddr to ask the peer to set primary to.
  2282  * returns: 0 = completed, -1 = error
  2283  */
  2284 int32_t
  2285 sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
  2287  	uint32_t vrf_id;
  2288 	struct sctp_ifa *ifa;
  2290 	/* find the ifa for the desired set primary */
  2291 	vrf_id = stcb->asoc.vrf_id;
  2292 	ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
  2293 	if (ifa == NULL) {
  2294 		/* Invalid address */
  2295 		return (-1);
  2298 	/* queue an ASCONF:SET_PRIM_ADDR to be sent */
  2299 	if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) {
  2300 		/* set primary queuing succeeded */
  2301 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  2302 			"set_primary_ip_address_sa: queued on tcb=%p, ",
  2303 			(void *)stcb);
  2304 		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
  2305 		if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
  2306 #ifdef SCTP_TIMER_BASED_ASCONF
  2307 			sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
  2308 					 stcb->sctp_ep, stcb,
  2309 					 stcb->asoc.primary_destination);
  2310 #else
  2311 			sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
  2312 #endif
  2314 	} else {
  2315 		SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ",
  2316 			(void *)stcb);
  2317 		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
  2318 		return (-1);
  2320 	return (0);
  2323 void
  2324 sctp_set_primary_ip_address(struct sctp_ifa *ifa)
  2326 	struct sctp_inpcb *inp;
  2328 	/* go through all our PCB's */
  2329 	LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
  2330 		struct sctp_tcb *stcb;
  2332 		/* process for all associations for this endpoint */
  2333 		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
  2334 			/* queue an ASCONF:SET_PRIM_ADDR to be sent */
  2335 			if (!sctp_asconf_queue_add(stcb, ifa,
  2336 						   SCTP_SET_PRIM_ADDR)) {
  2337 				/* set primary queuing succeeded */
  2338 				SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
  2339 					(void *)stcb);
  2340 				SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
  2341 				if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
  2342 #ifdef SCTP_TIMER_BASED_ASCONF
  2343 					sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
  2344 							 stcb->sctp_ep, stcb,
  2345 							 stcb->asoc.primary_destination);
  2346 #else
  2347 					sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
  2348 #endif
  2351 		} /* for each stcb */
  2352 	} /* for each inp */
  2355 int
  2356 sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
  2358 	struct sctp_tmit_chunk *chk, *nchk;
  2359 	unsigned int offset, asconf_limit;
  2360 	struct sctp_asconf_chunk *acp;
  2361 	struct sctp_asconf_paramhdr *aph;
  2362 	uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
  2363 	struct sctp_paramhdr *ph;
  2364 	int add_cnt, del_cnt;
  2365 	uint16_t last_param_type;
  2367 	add_cnt = del_cnt = 0;
  2368 	last_param_type = 0;
  2369 	TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) {
  2370 		if (chk->data == NULL) {
  2371 			SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n");
  2372 			continue;
  2374 		offset = 0;
  2375 		acp = mtod(chk->data, struct sctp_asconf_chunk *);
  2376 		offset += sizeof(struct sctp_asconf_chunk);
  2377 		asconf_limit = ntohs(acp->ch.chunk_length);
  2378 		ph = (struct sctp_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf);
  2379 		if (ph == NULL) {
  2380 			SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n");
  2381 			continue;
  2383 		offset += ntohs(ph->param_length);
  2385 		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
  2386 		if (aph == NULL) {
  2387 			SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: Empty ASCONF will be sent?\n");
  2388 			continue;
  2390 		while (aph != NULL) {
  2391 			unsigned int param_length, param_type;
  2393 			param_type = ntohs(aph->ph.param_type);
  2394 			param_length = ntohs(aph->ph.param_length);
  2395 			if (offset + param_length > asconf_limit) {
  2396 				/* parameter goes beyond end of chunk! */
  2397 				break;
  2399 			if (param_length > sizeof(aparam_buf)) {
  2400 				SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length (%u) larger than buffer size!\n", param_length);
  2401 				break;
  2403 			if (param_length <= sizeof(struct sctp_paramhdr)) {
  2404 				SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length);
  2405 				break;
  2408 			aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf);
  2409 			if (aph == NULL) {
  2410 				SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n");
  2411 				break;
  2414 			ph = (struct sctp_paramhdr *)(aph + 1);
  2415 			if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) {
  2416 				switch (param_type) {
  2417 				case SCTP_ADD_IP_ADDRESS:
  2418 					add_cnt++;
  2419 					break;
  2420 				case SCTP_DEL_IP_ADDRESS:
  2421 					del_cnt++;
  2422 					break;
  2423 				default:
  2424 					break;
  2426 				last_param_type = param_type;
  2429 			offset += SCTP_SIZE32(param_length);
  2430 			if (offset >= asconf_limit) {
  2431 				/* no more data in the mbuf chain */
  2432 				break;
  2434 			/* get pointer to next asconf param */
  2435 			aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
  2439 	/* we want to find the sequences which consist of ADD -> DEL -> ADD or DEL -> ADD */
  2440 	if (add_cnt > del_cnt ||
  2441 	    (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) {
  2442 		return (1);
  2444 	return (0);
  2447 static struct sockaddr *
  2448 sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
  2450 	struct sctp_vrf *vrf = NULL;
  2451 	struct sctp_ifn *sctp_ifn;
  2452 	struct sctp_ifa *sctp_ifa;
  2454 	if (addr_locked == SCTP_ADDR_NOT_LOCKED)
  2455 		SCTP_IPI_ADDR_RLOCK();
  2456 	vrf = sctp_find_vrf(stcb->asoc.vrf_id);
  2457 	if (vrf == NULL) {
  2458 		if (addr_locked == SCTP_ADDR_NOT_LOCKED)
  2459 			SCTP_IPI_ADDR_RUNLOCK();
  2460 		return (NULL);
  2462 	LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
  2463 		if (stcb->asoc.scope.loopback_scope == 0 &&
  2464 		    SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
  2465 			/* Skip if loopback_scope not set */
  2466 			continue;
  2468 		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
  2469 			switch (sctp_ifa->address.sa.sa_family) {
  2470 #ifdef INET
  2471 			case AF_INET:
  2472 				if (stcb->asoc.scope.ipv4_addr_legal) {
  2473 					struct sockaddr_in *sin;
  2475 					sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
  2476 					if (sin->sin_addr.s_addr == 0) {
  2477 						/* skip unspecifed addresses */
  2478 						continue;
  2480 					if (stcb->asoc.scope.ipv4_local_scope == 0 &&
  2481 					    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
  2482 						continue;
  2484 					if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
  2485 					    (!sctp_is_addr_pending(stcb, sctp_ifa)))
  2486 						continue;
  2487 					/* found a valid local v4 address to use */
  2488 					if (addr_locked == SCTP_ADDR_NOT_LOCKED)
  2489 						SCTP_IPI_ADDR_RUNLOCK();
  2490 					return (&sctp_ifa->address.sa);
  2492 				break;
  2493 #endif
  2494 #ifdef INET6
  2495 			case AF_INET6:
  2496 				if (stcb->asoc.scope.ipv6_addr_legal) {
  2497 					struct sockaddr_in6 *sin6;
  2499 					if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
  2500 						continue;
  2503 					sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
  2504 					if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  2505 						/* we skip unspecifed addresses */
  2506 						continue;
  2508 					if (stcb->asoc.scope.local_scope == 0 &&
  2509 					    IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
  2510 						continue;
  2511 					if (stcb->asoc.scope.site_scope == 0 &&
  2512 					    IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
  2513 						continue;
  2515 					if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
  2516 					    (!sctp_is_addr_pending(stcb, sctp_ifa)))
  2517 						continue;
  2518 					/* found a valid local v6 address to use */
  2519 					if (addr_locked == SCTP_ADDR_NOT_LOCKED)
  2520 						SCTP_IPI_ADDR_RUNLOCK();
  2521 					return (&sctp_ifa->address.sa);
  2523 				break;
  2524 #endif
  2525 			default:
  2526 				break;
  2530 	/* no valid addresses found */
  2531 	if (addr_locked == SCTP_ADDR_NOT_LOCKED)
  2532 		SCTP_IPI_ADDR_RUNLOCK();
  2533 	return (NULL);
  2536 static struct sockaddr *
  2537 sctp_find_valid_localaddr_ep(struct sctp_tcb *stcb)
  2539 	struct sctp_laddr *laddr;
  2541 	LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
  2542 		if (laddr->ifa == NULL) {
  2543 			continue;
  2545 		/* is the address restricted ? */
  2546 		if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
  2547 		    (!sctp_is_addr_pending(stcb, laddr->ifa)))
  2548 			continue;
  2550 		/* found a valid local address to use */
  2551 		return (&laddr->ifa->address.sa);
  2553 	/* no valid addresses found */
  2554 	return (NULL);
  2557 /*
  2558  * builds an ASCONF chunk from queued ASCONF params.
  2559  * returns NULL on error (no mbuf, no ASCONF params queued, etc).
  2560  */
  2561 struct mbuf *
  2562 sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
  2564 	struct mbuf *m_asconf, *m_asconf_chk;
  2565 	struct sctp_asconf_addr *aa;
  2566 	struct sctp_asconf_chunk *acp;
  2567 	struct sctp_asconf_paramhdr *aph;
  2568 	struct sctp_asconf_addr_param *aap;
  2569 	uint32_t p_length;
  2570 	uint32_t correlation_id = 1;	/* 0 is reserved... */
  2571 	caddr_t ptr, lookup_ptr;
  2572 	uint8_t lookup_used = 0;
  2574 	/* are there any asconf params to send? */
  2575 	TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
  2576 		if (aa->sent == 0)
  2577 			break;
  2579 	if (aa == NULL)
  2580 		return (NULL);
  2582 	/*
  2583 	 * get a chunk header mbuf and a cluster for the asconf params since
  2584 	 * it's simpler to fill in the asconf chunk header lookup address on
  2585 	 * the fly
  2586 	 */
  2587 	m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_NOWAIT, 1, MT_DATA);
  2588 	if (m_asconf_chk == NULL) {
  2589 		/* no mbuf's */
  2590 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  2591 			"compose_asconf: couldn't get chunk mbuf!\n");
  2592 		return (NULL);
  2594 	m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
  2595 	if (m_asconf == NULL) {
  2596 		/* no mbuf's */
  2597 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  2598 			"compose_asconf: couldn't get mbuf!\n");
  2599 		sctp_m_freem(m_asconf_chk);
  2600 		return (NULL);
  2602 	SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk);
  2603 	SCTP_BUF_LEN(m_asconf) = 0;
  2604 	acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *);
  2605 	bzero(acp, sizeof(struct sctp_asconf_chunk));
  2606 	/* save pointers to lookup address and asconf params */
  2607 	lookup_ptr = (caddr_t)(acp + 1);	/* after the header */
  2608 	ptr = mtod(m_asconf, caddr_t);	/* beginning of cluster */
  2610 	/* fill in chunk header info */
  2611 	acp->ch.chunk_type = SCTP_ASCONF;
  2612 	acp->ch.chunk_flags = 0;
  2613 	acp->serial_number = htonl(stcb->asoc.asconf_seq_out);
  2614 	stcb->asoc.asconf_seq_out++;
  2616 	/* add parameters... up to smallest MTU allowed */
  2617 	TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
  2618 		if (aa->sent)
  2619 			continue;
  2620 		/* get the parameter length */
  2621 		p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
  2622 		/* will it fit in current chunk? */
  2623 		if ((SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) ||
  2624 		    (SCTP_BUF_LEN(m_asconf) + p_length > MCLBYTES)) {
  2625 			/* won't fit, so we're done with this chunk */
  2626 			break;
  2628 		/* assign (and store) a correlation id */
  2629 		aa->ap.aph.correlation_id = correlation_id++;
  2631 		/*
  2632 		 * fill in address if we're doing a delete this is a simple
  2633 		 * way for us to fill in the correlation address, which
  2634 		 * should only be used by the peer if we're deleting our
  2635 		 * source address and adding a new address (e.g. renumbering
  2636 		 * case)
  2637 		 */
  2638 		if (lookup_used == 0 &&
  2639 		    (aa->special_del == 0) &&
  2640 		    aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
  2641 			struct sctp_ipv6addr_param *lookup;
  2642 			uint16_t p_size, addr_size;
  2644 			lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
  2645 			lookup->ph.param_type =
  2646 			    htons(aa->ap.addrp.ph.param_type);
  2647 			if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) {
  2648 				/* copy IPv6 address */
  2649 				p_size = sizeof(struct sctp_ipv6addr_param);
  2650 				addr_size = sizeof(struct in6_addr);
  2651 			} else {
  2652 				/* copy IPv4 address */
  2653 				p_size = sizeof(struct sctp_ipv4addr_param);
  2654 				addr_size = sizeof(struct in_addr);
  2656 			lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
  2657 			memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size);
  2658 			SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
  2659 			lookup_used = 1;
  2661 		/* copy into current space */
  2662 		memcpy(ptr, &aa->ap, p_length);
  2664 		/* network elements and update lengths */
  2665 		aph = (struct sctp_asconf_paramhdr *)ptr;
  2666 		aap = (struct sctp_asconf_addr_param *)ptr;
  2667 		/* correlation_id is transparent to peer, no htonl needed */
  2668 		aph->ph.param_type = htons(aph->ph.param_type);
  2669 		aph->ph.param_length = htons(aph->ph.param_length);
  2670 		aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type);
  2671 		aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length);
  2673 		SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length);
  2674 		ptr += SCTP_SIZE32(p_length);
  2676 		/*
  2677 		 * these params are removed off the pending list upon
  2678 		 * getting an ASCONF-ACK back from the peer, just set flag
  2679 		 */
  2680 		aa->sent = 1;
  2682 	/* check to see if the lookup addr has been populated yet */
  2683 	if (lookup_used == 0) {
  2684 		/* NOTE: if the address param is optional, can skip this... */
  2685 		/* add any valid (existing) address... */
  2686 		struct sctp_ipv6addr_param *lookup;
  2687 		uint16_t p_size, addr_size;
  2688 		struct sockaddr *found_addr;
  2689 		caddr_t addr_ptr;
  2691 		if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)
  2692 			found_addr = sctp_find_valid_localaddr(stcb,
  2693 							       addr_locked);
  2694 		else
  2695 			found_addr = sctp_find_valid_localaddr_ep(stcb);
  2697 		lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
  2698 		if (found_addr != NULL) {
  2699 			switch (found_addr->sa_family) {
  2700 #ifdef INET6
  2701 			case AF_INET6:
  2702 				/* copy IPv6 address */
  2703 				lookup->ph.param_type =
  2704 				    htons(SCTP_IPV6_ADDRESS);
  2705 				p_size = sizeof(struct sctp_ipv6addr_param);
  2706 				addr_size = sizeof(struct in6_addr);
  2707 				addr_ptr = (caddr_t)&((struct sockaddr_in6 *)
  2708 				    found_addr)->sin6_addr;
  2709 				break;
  2710 #endif
  2711 #ifdef INET
  2712 			case AF_INET:
  2713 				/* copy IPv4 address */
  2714 				lookup->ph.param_type =
  2715 				    htons(SCTP_IPV4_ADDRESS);
  2716 				p_size = sizeof(struct sctp_ipv4addr_param);
  2717 				addr_size = sizeof(struct in_addr);
  2718 				addr_ptr = (caddr_t)&((struct sockaddr_in *)
  2719 				    found_addr)->sin_addr;
  2720 				break;
  2721 #endif
  2722 			default:
  2723 				p_size = 0;
  2724 				addr_size = 0;
  2725 				addr_ptr = NULL;
  2726 				break;
  2728 			lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
  2729 			memcpy(lookup->addr, addr_ptr, addr_size);
  2730 			SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
  2731 		} else {
  2732 			/* uh oh... don't have any address?? */
  2733 			SCTPDBG(SCTP_DEBUG_ASCONF1,
  2734 				"compose_asconf: no lookup addr!\n");
  2735 			/* XXX for now, we send a IPv4 address of 0.0.0.0 */
  2736 			lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
  2737 			lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
  2738 			bzero(lookup->addr, sizeof(struct in_addr));
  2739 			SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
  2742 	/* chain it all together */
  2743 	SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
  2744 	*retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf);
  2745 	acp->ch.chunk_length = htons(*retlen);
  2747 	return (m_asconf_chk);
  2750 /*
  2751  * section to handle address changes before an association is up eg. changes
  2752  * during INIT/INIT-ACK/COOKIE-ECHO handshake
  2753  */
  2755 /*
  2756  * processes the (local) addresses in the INIT-ACK chunk
  2757  */
  2758 static void
  2759 sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
  2760     unsigned int offset, unsigned int length)
  2762 	struct sctp_paramhdr tmp_param, *ph;
  2763 	uint16_t plen, ptype;
  2764 	struct sctp_ifa *sctp_ifa;
  2765 #ifdef INET6
  2766 	struct sctp_ipv6addr_param addr6_store;
  2767 	struct sockaddr_in6 sin6;
  2768 #endif
  2769 #ifdef INET
  2770 	struct sctp_ipv4addr_param addr4_store;
  2771 	struct sockaddr_in sin;
  2772 #endif
  2773 	struct sockaddr *sa;
  2774 	uint32_t vrf_id;
  2776 	SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n");
  2777 	if (stcb == NULL) /* Un-needed check for SA */
  2778 		return;
  2780 	/* convert to upper bound */
  2781 	length += offset;
  2783 	if ((offset + sizeof(struct sctp_paramhdr)) > length) {
  2784 		return;
  2786 	/* init the addresses */
  2787 #ifdef INET6
  2788 	bzero(&sin6, sizeof(sin6));
  2789 	sin6.sin6_family = AF_INET6;
  2790 #ifdef HAVE_SIN6_LEN
  2791 	sin6.sin6_len = sizeof(sin6);
  2792 #endif
  2793 	sin6.sin6_port = stcb->rport;
  2794 #endif
  2796 #ifdef INET
  2797 	bzero(&sin, sizeof(sin));
  2798 	sin.sin_family = AF_INET;
  2799 #ifdef HAVE_SIN_LEN
  2800 	sin.sin_len = sizeof(sin);
  2801 #endif
  2802 	sin.sin_port = stcb->rport;
  2803 #endif
  2805 	/* go through the addresses in the init-ack */
  2806 	ph = (struct sctp_paramhdr *)
  2807 	     sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
  2808 	                   (uint8_t *)&tmp_param);
  2809 	while (ph != NULL) {
  2810 		ptype = ntohs(ph->param_type);
  2811 		plen = ntohs(ph->param_length);
  2812 		switch (ptype) {
  2813 #ifdef INET6
  2814 		case SCTP_IPV6_ADDRESS:
  2816 			struct sctp_ipv6addr_param *a6p;
  2818 			/* get the entire IPv6 address param */
  2819 			a6p = (struct sctp_ipv6addr_param *)
  2820 			    sctp_m_getptr(m, offset,
  2821 			    sizeof(struct sctp_ipv6addr_param),
  2822 			    (uint8_t *)&addr6_store);
  2823 			if (plen != sizeof(struct sctp_ipv6addr_param) ||
  2824 			    a6p == NULL) {
  2825 				return;
  2827 			memcpy(&sin6.sin6_addr, a6p->addr,
  2828 			    sizeof(struct in6_addr));
  2829 			sa = (struct sockaddr *)&sin6;
  2830 			break;
  2832 #endif
  2833 #ifdef INET
  2834 		case SCTP_IPV4_ADDRESS:
  2836 			struct sctp_ipv4addr_param *a4p;
  2838 			/* get the entire IPv4 address param */
  2839 			a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
  2840 									  sizeof(struct sctp_ipv4addr_param),
  2841 									  (uint8_t *)&addr4_store);
  2842 			if (plen != sizeof(struct sctp_ipv4addr_param) ||
  2843 			    a4p == NULL) {
  2844 				return;
  2846 			sin.sin_addr.s_addr = a4p->addr;
  2847 			sa = (struct sockaddr *)&sin;
  2848 			break;
  2850 #endif
  2851 		default:
  2852 			goto next_addr;
  2855 		/* see if this address really (still) exists */
  2856 		if (stcb) {
  2857 			vrf_id = stcb->asoc.vrf_id;
  2858 		} else {
  2859 			vrf_id = SCTP_DEFAULT_VRFID;
  2861 		sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id,
  2862 						 SCTP_ADDR_NOT_LOCKED);
  2863 		if (sctp_ifa == NULL) {
  2864 			/* address doesn't exist anymore */
  2865 			int status;
  2867 			/* are ASCONFs allowed ? */
  2868 			if ((sctp_is_feature_on(stcb->sctp_ep,
  2869 			    SCTP_PCB_FLAGS_DO_ASCONF)) &&
  2870 			    stcb->asoc.peer_supports_asconf) {
  2871 				/* queue an ASCONF DEL_IP_ADDRESS */
  2872 				status = sctp_asconf_queue_sa_delete(stcb, sa);
  2873 				/*
  2874 				 * if queued ok, and in correct state, send
  2875 				 * out the ASCONF.
  2876 				 */
  2877 				if (status == 0 &&
  2878 				    SCTP_GET_STATE(&stcb->asoc) ==
  2879 				    SCTP_STATE_OPEN) {
  2880 #ifdef SCTP_TIMER_BASED_ASCONF
  2881 					sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
  2882 							 stcb->sctp_ep, stcb,
  2883 							 stcb->asoc.primary_destination);
  2884 #else
  2885 					sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
  2886 #endif
  2891 next_addr:
  2892 		/*
  2893 		 * Sanity check:  Make sure the length isn't 0, otherwise
  2894 		 * we'll be stuck in this loop for a long time...
  2895 		 */
  2896 		if (SCTP_SIZE32(plen) == 0) {
  2897 			SCTP_PRINTF("process_initack_addrs: bad len (%d) type=%xh\n",
  2898 				    plen, ptype);
  2899 			return;
  2901 		/* get next parameter */
  2902 		offset += SCTP_SIZE32(plen);
  2903 		if ((offset + sizeof(struct sctp_paramhdr)) > length)
  2904 			return;
  2905 		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
  2906 		    sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
  2907 	} /* while */
  2910 /* FIX ME: need to verify return result for v6 address type if v6 disabled */
  2911 /*
  2912  * checks to see if a specific address is in the initack address list returns
  2913  * 1 if found, 0 if not
  2914  */
  2915 static uint32_t
  2916 sctp_addr_in_initack(struct mbuf *m, uint32_t offset, uint32_t length, struct sockaddr *sa)
  2918 	struct sctp_paramhdr tmp_param, *ph;
  2919 	uint16_t plen, ptype;
  2920 #ifdef INET
  2921 	struct sockaddr_in *sin;
  2922 	struct sctp_ipv4addr_param *a4p;
  2923 	struct sctp_ipv6addr_param addr4_store;
  2924 #endif
  2925 #ifdef INET6
  2926 	struct sockaddr_in6 *sin6;
  2927 	struct sctp_ipv6addr_param *a6p;
  2928 	struct sctp_ipv6addr_param addr6_store;
  2929 #ifdef SCTP_EMBEDDED_V6_SCOPE
  2930 	struct sockaddr_in6 sin6_tmp;
  2931 #endif
  2932 #endif
  2934 	switch (sa->sa_family) {
  2935 #ifdef INET
  2936 	case AF_INET:
  2937 		break;
  2938 #endif
  2939 #ifdef INET6
  2940 	case AF_INET6:
  2941 		break;
  2942 #endif
  2943 	default:
  2944 		return (0);
  2947 	SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for ");
  2948 	SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
  2949 	/* convert to upper bound */
  2950 	length += offset;
  2952 	if ((offset + sizeof(struct sctp_paramhdr)) > length) {
  2953 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  2954 			"find_initack_addr: invalid offset?\n");
  2955 		return (0);
  2957 	/* go through the addresses in the init-ack */
  2958 	ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
  2959 	    sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
  2960 	while (ph != NULL) {
  2961 		ptype = ntohs(ph->param_type);
  2962 		plen = ntohs(ph->param_length);
  2963 		switch (ptype) {
  2964 #ifdef INET6
  2965 		case SCTP_IPV6_ADDRESS:
  2966 			if (sa->sa_family == AF_INET6) {
  2967 				/* get the entire IPv6 address param */
  2968 				if (plen != sizeof(struct sctp_ipv6addr_param)) {
  2969 					break;
  2971 				/* get the entire IPv6 address param */
  2972 				a6p = (struct sctp_ipv6addr_param *)
  2973 				      sctp_m_getptr(m, offset,
  2974 				                    sizeof(struct sctp_ipv6addr_param),
  2975 				                    (uint8_t *)&addr6_store);
  2976 				if (a6p == NULL) {
  2977 					return (0);
  2979 				sin6 = (struct sockaddr_in6 *)sa;
  2980 #ifdef SCTP_EMBEDDED_V6_SCOPE
  2981 				if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
  2982 					/* create a copy and clear scope */
  2983 					memcpy(&sin6_tmp, sin6,
  2984 					       sizeof(struct sockaddr_in6));
  2985 					sin6 = &sin6_tmp;
  2986 					in6_clearscope(&sin6->sin6_addr);
  2988 #endif /* SCTP_EMBEDDED_V6_SCOPE */
  2989 				if (memcmp(&sin6->sin6_addr, a6p->addr,
  2990 				           sizeof(struct in6_addr)) == 0) {
  2991 					/* found it */
  2992 					return (1);
  2995 			break;
  2996 #endif /* INET6 */
  2997 #ifdef INET
  2998 		case SCTP_IPV4_ADDRESS:
  2999 			if (sa->sa_family == AF_INET) {
  3000 				if (plen != sizeof(struct sctp_ipv4addr_param)) {
  3001 					break;
  3003 				/* get the entire IPv4 address param */
  3004 				a4p = (struct sctp_ipv4addr_param *)
  3005 				      sctp_m_getptr(m, offset,
  3006 				                    sizeof(struct sctp_ipv4addr_param),
  3007 				                    (uint8_t *)&addr4_store);
  3008 				if (a4p == NULL) {
  3009 					return (0);
  3011 				sin = (struct sockaddr_in *)sa;
  3012 				if (sin->sin_addr.s_addr == a4p->addr) {
  3013 					/* found it */
  3014 					return (1);
  3017 			break;
  3018 #endif
  3019 		default:
  3020 			break;
  3022 		/* get next parameter */
  3023 		offset += SCTP_SIZE32(plen);
  3024 		if (offset + sizeof(struct sctp_paramhdr) > length) {
  3025 			return (0);
  3027 		ph = (struct sctp_paramhdr *)
  3028 		    sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
  3029 		    (uint8_t *) & tmp_param);
  3030 	} /* while */
  3031 	/* not found! */
  3032 	return (0);
  3035 /*
  3036  * makes sure that the current endpoint local addr list is consistent with
  3037  * the new association (eg. subset bound, asconf allowed) adds addresses as
  3038  * necessary
  3039  */
  3040 static void
  3041 sctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset,
  3042     int length, struct sockaddr *init_addr)
  3044 	struct sctp_laddr *laddr;
  3046 	/* go through the endpoint list */
  3047 	LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
  3048 		/* be paranoid and validate the laddr */
  3049 		if (laddr->ifa == NULL) {
  3050 			SCTPDBG(SCTP_DEBUG_ASCONF1,
  3051 				"check_addr_list_ep: laddr->ifa is NULL");
  3052 			continue;
  3054 		if (laddr->ifa == NULL) {
  3055 			SCTPDBG(SCTP_DEBUG_ASCONF1, "check_addr_list_ep: laddr->ifa->ifa_addr is NULL");
  3056 			continue;
  3058 		/* do i have it implicitly? */
  3059 		if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) {
  3060 			continue;
  3062 		/* check to see if in the init-ack */
  3063 		if (!sctp_addr_in_initack(m, offset, length, &laddr->ifa->address.sa)) {
  3064 			/* try to add it */
  3065 			sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa,
  3066 			    SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED);
  3071 /*
  3072  * makes sure that the current kernel address list is consistent with the new
  3073  * association (with all addrs bound) adds addresses as necessary
  3074  */
  3075 static void
  3076 sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
  3077     int length, struct sockaddr *init_addr,
  3078     uint16_t local_scope, uint16_t site_scope,
  3079     uint16_t ipv4_scope, uint16_t loopback_scope)
  3081 	struct sctp_vrf *vrf = NULL;
  3082 	struct sctp_ifn *sctp_ifn;
  3083 	struct sctp_ifa *sctp_ifa;
  3084 	uint32_t vrf_id;
  3085 #ifdef INET
  3086 	struct sockaddr_in *sin;
  3087 #endif
  3088 #ifdef INET6
  3089 	struct sockaddr_in6 *sin6;
  3090 #endif
  3092 	if (stcb) {
  3093 		vrf_id = stcb->asoc.vrf_id;
  3094 	} else {
  3095 		return;
  3097 	SCTP_IPI_ADDR_RLOCK();
  3098 	vrf = sctp_find_vrf(vrf_id);
  3099 	if (vrf == NULL) {
  3100 		SCTP_IPI_ADDR_RUNLOCK();
  3101 		return;
  3103 	/* go through all our known interfaces */
  3104 	LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
  3105 		if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
  3106 			/* skip loopback interface */
  3107 			continue;
  3109 		/* go through each interface address */
  3110 		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
  3111 			/* do i have it implicitly? */
  3112 			if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
  3113 				continue;
  3115 			switch (sctp_ifa->address.sa.sa_family) {
  3116 #ifdef INET
  3117 			case AF_INET:
  3118 				sin = (struct sockaddr_in *)&sctp_ifa->address.sin;
  3119 				if ((ipv4_scope == 0) &&
  3120 				    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
  3121 					/* private address not in scope */
  3122 					continue;
  3124 				break;
  3125 #endif
  3126 #ifdef INET6
  3127 			case AF_INET6:
  3128 				sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6;
  3129 				if ((local_scope == 0) &&
  3130 				    (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
  3131 					continue;
  3133 				if ((site_scope == 0) &&
  3134 				    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
  3135 					continue;
  3137 				break;
  3138 #endif
  3139 			default:
  3140 				break;
  3142 			/* check to see if in the init-ack */
  3143 			if (!sctp_addr_in_initack(m, offset, length, &sctp_ifa->address.sa)) {
  3144 				/* try to add it */
  3145 				sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
  3146 				    sctp_ifa, SCTP_ADD_IP_ADDRESS,
  3147 				    SCTP_ADDR_LOCKED);
  3149 		} /* end foreach ifa */
  3150 	} /* end foreach ifn */
  3151 	SCTP_IPI_ADDR_RUNLOCK();
  3154 /*
  3155  * validates an init-ack chunk (from a cookie-echo) with current addresses
  3156  * adds addresses from the init-ack into our local address list, if needed
  3157  * queues asconf adds/deletes addresses as needed and makes appropriate list
  3158  * changes for source address selection m, offset: points to the start of the
  3159  * address list in an init-ack chunk length: total length of the address
  3160  * params only init_addr: address where my INIT-ACK was sent from
  3161  */
  3162 void
  3163 sctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset,
  3164     int length, struct sockaddr *init_addr,
  3165     uint16_t local_scope, uint16_t site_scope,
  3166     uint16_t ipv4_scope, uint16_t loopback_scope)
  3168 	/* process the local addresses in the initack */
  3169 	sctp_process_initack_addresses(stcb, m, offset, length);
  3171 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
  3172 		/* bound all case */
  3173 		sctp_check_address_list_all(stcb, m, offset, length, init_addr,
  3174 		    local_scope, site_scope, ipv4_scope, loopback_scope);
  3175 	} else {
  3176 		/* subset bound case */
  3177 		if (sctp_is_feature_on(stcb->sctp_ep,
  3178 		    SCTP_PCB_FLAGS_DO_ASCONF)) {
  3179 			/* asconf's allowed */
  3180 			sctp_check_address_list_ep(stcb, m, offset, length,
  3181 			    init_addr);
  3183 		/* else, no asconfs allowed, so what we sent is what we get */
  3187 /*
  3188  * sctp_bindx() support
  3189  */
  3190 uint32_t
  3191 sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
  3192     uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap)
  3194 	struct sctp_ifa *ifa;
  3195 	struct sctp_laddr *laddr, *nladdr;
  3197 #ifdef HAVE_SA_LEN
  3198 	if (sa->sa_len == 0) {
  3199 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
  3200 		return (EINVAL);
  3202 #endif
  3203 	if (sctp_ifap) {
  3204 		ifa = sctp_ifap;
  3205 	} else 	if (type == SCTP_ADD_IP_ADDRESS) {
  3206 		/* For an add the address MUST be on the system */
  3207 		ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
  3208 	} else if (type == SCTP_DEL_IP_ADDRESS) {
  3209 		/* For a delete we need to find it in the inp */
  3210 		ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED);
  3211 	} else {
  3212 		ifa = NULL;
  3214 	if (ifa != NULL) {
  3215 		if (type == SCTP_ADD_IP_ADDRESS) {
  3216 			sctp_add_local_addr_ep(inp, ifa, type);
  3217 		} else if (type == SCTP_DEL_IP_ADDRESS) {
  3218 			if (inp->laddr_count < 2) {
  3219 				/* can't delete the last local address */
  3220 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
  3221 				return (EINVAL);
  3223 			LIST_FOREACH(laddr, &inp->sctp_addr_list,
  3224 				     sctp_nxt_addr) {
  3225 				if (ifa == laddr->ifa) {
  3226 					/* Mark in the delete */
  3227 					laddr->action = type;
  3231 		if (LIST_EMPTY(&inp->sctp_asoc_list)) {
  3232 			/*
  3233 			 * There is no need to start the iterator if
  3234 			 * the inp has no associations.
  3235 			 */
  3236 			if (type == SCTP_DEL_IP_ADDRESS) {
  3237 				LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
  3238 					if (laddr->ifa == ifa) {
  3239 						sctp_del_local_addr_ep(inp, ifa);
  3243 		} else {
  3244 			struct sctp_asconf_iterator *asc;
  3245 			struct sctp_laddr *wi;
  3247 			SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
  3248 			            sizeof(struct sctp_asconf_iterator),
  3249 			            SCTP_M_ASC_IT);
  3250 			if (asc == NULL) {
  3251 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
  3252 				return (ENOMEM);
  3254 			wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr);
  3255 			if (wi == NULL) {
  3256 				SCTP_FREE(asc, SCTP_M_ASC_IT);
  3257 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
  3258 				return (ENOMEM);
  3260 			LIST_INIT(&asc->list_of_work);
  3261 			asc->cnt = 1;
  3262 			SCTP_INCR_LADDR_COUNT();
  3263 			wi->ifa = ifa;
  3264 			wi->action = type;
  3265 			atomic_add_int(&ifa->refcount, 1);
  3266 			LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
  3267 			(void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
  3268 			                             sctp_asconf_iterator_stcb,
  3269 			                             sctp_asconf_iterator_ep_end,
  3270 			                             SCTP_PCB_ANY_FLAGS,
  3271 			                             SCTP_PCB_ANY_FEATURES,
  3272 			                             SCTP_ASOC_ANY_STATE,
  3273 			                             (void *)asc, 0,
  3274 			                             sctp_asconf_iterator_end, inp, 0);
  3276 		return (0);
  3277 	} else {
  3278 		/* invalid address! */
  3279 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL);
  3280 		return (EADDRNOTAVAIL);
  3284 void
  3285 sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
  3286 				  struct sctp_nets *net)
  3288 	struct sctp_asconf_addr *aa;
  3289 	struct sctp_ifa *sctp_ifap;
  3290 	struct sctp_asconf_tag_param *vtag;
  3291 #ifdef INET
  3292 	struct sockaddr_in *to;
  3293 #endif
  3294 #ifdef INET6
  3295 	struct sockaddr_in6 *to6;
  3296 #endif
  3297 	if (net == NULL) {
  3298 		SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n");
  3299 		return;
  3301 	if (stcb == NULL) {
  3302 		SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n");
  3303 		return;
  3305   /* Need to have in the asconf:
  3306    * - vtagparam(my_vtag/peer_vtag)
  3307    * - add(0.0.0.0)
  3308    * - del(0.0.0.0)
  3309    * - Any global addresses add(addr)
  3310    */
  3311 	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
  3312 	            SCTP_M_ASC_ADDR);
  3313 	if (aa == NULL) {
  3314 		/* didn't get memory */
  3315 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  3316 		        "sctp_asconf_send_nat_state_update: failed to get memory!\n");
  3317 		return;
  3319 	aa->special_del = 0;
  3320 	/* fill in asconf address parameter fields */
  3321 	/* top level elements are "networked" during send */
  3322 	aa->ifa = NULL;
  3323 	aa->sent = 0;		/* clear sent flag */
  3324 	vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph;
  3325 	vtag->aph.ph.param_type = SCTP_NAT_VTAGS;
  3326 	vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param);
  3327 	vtag->local_vtag = htonl(stcb->asoc.my_vtag);
  3328 	vtag->remote_vtag = htonl(stcb->asoc.peer_vtag);
  3329 	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
  3331 	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
  3332 	            SCTP_M_ASC_ADDR);
  3333 	if (aa == NULL) {
  3334 		/* didn't get memory */
  3335 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  3336 		        "sctp_asconf_send_nat_state_update: failed to get memory!\n");
  3337 		return;
  3339 	memset(aa, 0, sizeof(struct sctp_asconf_addr));
  3340 	/* fill in asconf address parameter fields */
  3341 	/* ADD(0.0.0.0) */
  3342 	switch (net->ro._l_addr.sa.sa_family) {
  3343 #ifdef INET
  3344 	case AF_INET:
  3345 		aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
  3346 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
  3347 		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
  3348 		aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv4addr_param);
  3349 		/* No need to add an address, we are using 0.0.0.0 */
  3350 		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
  3351 		break;
  3352 #endif
  3353 #ifdef INET6
  3354 	case AF_INET6:
  3355 		aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
  3356 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
  3357 		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
  3358 		aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv6addr_param);
  3359 		/* No need to add an address, we are using 0.0.0.0 */
  3360 		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
  3361 		break;
  3362 #endif
  3364 	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
  3365 	            SCTP_M_ASC_ADDR);
  3366 	if (aa == NULL) {
  3367 		/* didn't get memory */
  3368 		SCTPDBG(SCTP_DEBUG_ASCONF1,
  3369 		        "sctp_asconf_send_nat_state_update: failed to get memory!\n");
  3370 		return;
  3372 	memset(aa, 0, sizeof(struct sctp_asconf_addr));
  3373 	/* fill in asconf address parameter fields */
  3374 	/* ADD(0.0.0.0) */
  3375 	switch (net->ro._l_addr.sa.sa_family) {
  3376 #ifdef INET
  3377 	case AF_INET:
  3378 		aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
  3379 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
  3380 		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
  3381 		aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv4addr_param);
  3382 		/* No need to add an address, we are using 0.0.0.0 */
  3383 		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
  3384 		break;
  3385 #endif
  3386 #ifdef INET6
  3387 	case AF_INET6:
  3388 		aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
  3389 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
  3390 		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
  3391 		aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv6addr_param);
  3392 		/* No need to add an address, we are using 0.0.0.0 */
  3393 		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
  3394 		break;
  3395 #endif
  3397 	/* Now we must hunt the addresses and add all global addresses */
  3398 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
  3399 		struct sctp_vrf *vrf = NULL;
  3400 		struct sctp_ifn *sctp_ifnp;
  3401 		uint32_t vrf_id;
  3403 		vrf_id = stcb->sctp_ep->def_vrf_id;
  3404 		vrf = sctp_find_vrf(vrf_id);
  3405 		if (vrf == NULL) {
  3406 			goto skip_rest;
  3409 		SCTP_IPI_ADDR_RLOCK();
  3410 		LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
  3411 			LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
  3412 				switch (sctp_ifap->address.sa.sa_family) {
  3413 #ifdef INET
  3414 				case AF_INET:
  3415 					to = &sctp_ifap->address.sin;
  3416 					if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
  3417 						continue;
  3419 					if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
  3420 						continue;
  3422 					break;
  3423 #endif
  3424 #ifdef INET6
  3425 				case AF_INET6:
  3426 					to6 = &sctp_ifap->address.sin6;
  3427 					if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
  3428 						continue;
  3430 					if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
  3431 						continue;
  3433 					break;
  3434 #endif
  3435 				default:
  3436 					continue;
  3438 				sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
  3441 		SCTP_IPI_ADDR_RUNLOCK();
  3442 	} else {
  3443 		struct sctp_laddr *laddr;
  3445 		LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
  3446 			if (laddr->ifa == NULL) {
  3447 				continue;
  3449 			if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED)
  3450 				/* Address being deleted by the system, dont
  3451 				 * list.
  3452 				 */
  3453 				continue;
  3454 			if (laddr->action == SCTP_DEL_IP_ADDRESS) {
  3455 				/* Address being deleted on this ep
  3456 				 * don't list.
  3457 				 */
  3458 				continue;
  3460 			sctp_ifap = laddr->ifa;
  3461 			switch (sctp_ifap->address.sa.sa_family) {
  3462 #ifdef INET
  3463 			case AF_INET:
  3464 				to = &sctp_ifap->address.sin;
  3465 				if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
  3466 					continue;
  3468 				if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
  3469 					continue;
  3471 				break;
  3472 #endif
  3473 #ifdef INET6
  3474 			case AF_INET6:
  3475 				to6 = &sctp_ifap->address.sin6;
  3476 				if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
  3477 					continue;
  3479 				if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
  3480 					continue;
  3482 				break;
  3483 #endif
  3484 			default:
  3485 				continue;
  3487 			sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
  3490  skip_rest:
  3491 	/* Now we must send the asconf into the queue */
  3492 	sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);

mercurial