sctp_asconf.c revision 164085
1191783Srmacklem/*- 2191783Srmacklem * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved. 3191783Srmacklem * 4191783Srmacklem * Redistribution and use in source and binary forms, with or without 5191783Srmacklem * modification, are permitted provided that the following conditions are met: 6191783Srmacklem * 7191783Srmacklem * a) Redistributions of source code must retain the above copyright notice, 8191783Srmacklem * this list of conditions and the following disclaimer. 9191783Srmacklem * 10191783Srmacklem * b) Redistributions in binary form must reproduce the above copyright 11191783Srmacklem * notice, this list of conditions and the following disclaimer in 12191783Srmacklem * the documentation and/or other materials provided with the distribution. 13191783Srmacklem * 14191783Srmacklem * c) Neither the name of Cisco Systems, Inc. nor the names of its 15191783Srmacklem * contributors may be used to endorse or promote products derived 16191783Srmacklem * from this software without specific prior written permission. 17191783Srmacklem * 18191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19191783Srmacklem * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 20191783Srmacklem * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21191783Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22191783Srmacklem * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23191783Srmacklem * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24191783Srmacklem * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25191783Srmacklem * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26191783Srmacklem * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27191783Srmacklem * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28191783Srmacklem * THE POSSIBILITY OF SUCH DAMAGE. 29191783Srmacklem */ 30191783Srmacklem 31191783Srmacklem/* $KAME: sctp_asconf.c,v 1.24 2005/03/06 16:04:16 itojun Exp $ */ 32191783Srmacklem 33191783Srmacklem#include <sys/cdefs.h> 34191783Srmacklem__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 164085 2006-11-08 00:21:13Z rrs $"); 35191783Srmacklem 36191783Srmacklem 37228217Srmacklem 38191783Srmacklem#include "opt_ipsec.h" 39191783Srmacklem#include "opt_compat.h" 40191783Srmacklem#include "opt_inet6.h" 41191783Srmacklem#include "opt_inet.h" 42191783Srmacklem 43244042Srmacklem#include "opt_sctp.h" 44244042Srmacklem 45244042Srmacklem#include <sys/param.h> 46244042Srmacklem#include <sys/systm.h> 47244042Srmacklem#include <sys/malloc.h> 48191783Srmacklem#include <sys/mbuf.h> 49244042Srmacklem#include <sys/socket.h> 50191783Srmacklem#include <sys/socketvar.h> 51244042Srmacklem#include <sys/kernel.h> 52244042Srmacklem#include <sys/sysctl.h> 53244042Srmacklem 54191783Srmacklem#include <net/if.h> 55244042Srmacklem#include <net/if_types.h> 56244042Srmacklem#include <net/route.h> 57244042Srmacklem 58244042Srmacklem#include <netinet/in.h> 59244042Srmacklem#include <netinet/in_systm.h> 60269398Srmacklem#include <netinet/ip.h> 61244042Srmacklem#include <netinet/in_pcb.h> 62244042Srmacklem#include <netinet/in_var.h> 63244042Srmacklem#include <netinet/ip_var.h> 64244042Srmacklem 65244042Srmacklem#ifdef INET6 66244042Srmacklem#include <netinet/ip6.h> 67244042Srmacklem#include <netinet6/ip6_var.h> 68244042Srmacklem#include <netinet6/in6_pcb.h> 69244042Srmacklem#include <netinet/icmp6.h> 70244042Srmacklem#include <netinet6/nd6.h> 71244042Srmacklem#include <netinet6/scope6_var.h> 72244042Srmacklem#endif /* INET6 */ 73244042Srmacklem 74244042Srmacklem#include <netinet/in_pcb.h> 75244042Srmacklem 76244042Srmacklem#include <netinet/sctp_os.h> 77244042Srmacklem#include <netinet/sctp_var.h> 78244042Srmacklem#include <netinet/sctp_pcb.h> 79244042Srmacklem#include <netinet/sctp_header.h> 80244042Srmacklem#include <netinet/sctputil.h> 81244042Srmacklem#include <netinet/sctp_output.h> 82244042Srmacklem#include <netinet/sctp_bsd_addr.h> 83244042Srmacklem#include <netinet/sctp_asconf.h> 84244042Srmacklem 85244042Srmacklem/* 86244042Srmacklem * debug flags: 87244042Srmacklem * SCTP_DEBUG_ASCONF1: protocol info, general info and errors 88244042Srmacklem * SCTP_DEBUG_ASCONF2: detailed info 89244042Srmacklem */ 90244042Srmacklem#ifdef SCTP_DEBUG 91244042Srmacklemextern uint32_t sctp_debug_on; 92244042Srmacklem 93244042Srmacklem#endif /* SCTP_DEBUG */ 94191783Srmacklem 95191783Srmacklem 96191783Srmacklemstatic int 97191783Srmacklemsctp_asconf_get_source_ip(struct mbuf *m, struct sockaddr *sa) 98191783Srmacklem{ 99244042Srmacklem struct ip *iph; 100244042Srmacklem struct sockaddr_in *sin; 101244042Srmacklem 102244042Srmacklem#ifdef INET6 103244042Srmacklem struct sockaddr_in6 *sin6; 104244042Srmacklem 105244042Srmacklem#endif 106244042Srmacklem 107244042Srmacklem iph = mtod(m, struct ip *); 108244042Srmacklem if (iph->ip_v == IPVERSION) { 109244042Srmacklem /* IPv4 source */ 110244042Srmacklem sin = (struct sockaddr_in *)sa; 111244042Srmacklem bzero(sin, sizeof(*sin)); 112244042Srmacklem sin->sin_family = AF_INET; 113191783Srmacklem sin->sin_len = sizeof(struct sockaddr_in); 114191783Srmacklem sin->sin_port = 0; 115191783Srmacklem sin->sin_addr.s_addr = iph->ip_src.s_addr; 116191783Srmacklem return 0; 117191783Srmacklem } 118191783Srmacklem#ifdef INET6 119191783Srmacklem else if (iph->ip_v == (IPV6_VERSION >> 4)) { 120191783Srmacklem /* IPv6 source */ 121191783Srmacklem struct ip6_hdr *ip6; 122191783Srmacklem 123191783Srmacklem sin6 = (struct sockaddr_in6 *)sa; 124191783Srmacklem bzero(sin6, sizeof(*sin6)); 125191783Srmacklem sin6->sin6_family = AF_INET6; 126191783Srmacklem sin6->sin6_len = sizeof(struct sockaddr_in6); 127206818Srmacklem sin6->sin6_port = 0; 128191783Srmacklem ip6 = mtod(m, struct ip6_hdr *); 129191783Srmacklem sin6->sin6_addr = ip6->ip6_src; 130191783Srmacklem return 0; 131191783Srmacklem } 132191783Srmacklem#endif /* INET6 */ 133191783Srmacklem else 134191783Srmacklem return -1; 135191783Srmacklem} 136191783Srmacklem 137191783Srmacklem/* 138191783Srmacklem * draft-ietf-tsvwg-addip-sctp 139191783Srmacklem * 140191783Srmacklem * Address management only currently supported For the bound all case: the asoc 141191783Srmacklem * local addr list is always a "DO NOT USE" list For the subset bound case: 142191783Srmacklem * If ASCONFs are allowed: the endpoint local addr list is the usable address 143191783Srmacklem * list the asoc local addr list is the "DO NOT USE" list If ASCONFs are not 144191783Srmacklem * allowed: the endpoint local addr list is the default usable list the asoc 145191783Srmacklem * local addr list is the usable address list 146191783Srmacklem * 147191783Srmacklem * An ASCONF parameter queue exists per asoc which holds the pending address 148191783Srmacklem * operations. Lists are updated upon receipt of ASCONF-ACK. 149191783Srmacklem * 150191783Srmacklem * Deleted addresses are always immediately removed from the lists as they will 151191783Srmacklem * (shortly) no longer exist in the kernel. We send ASCONFs as a courtesy, 152191783Srmacklem * only if allowed. 153191783Srmacklem */ 154191783Srmacklem 155191783Srmacklem/* 156191783Srmacklem * ASCONF parameter processing response_required: set if a reply is required 157191783Srmacklem * (eg. SUCCESS_REPORT) returns a mbuf to an "error" response parameter or 158191783Srmacklem * NULL/"success" if ok FIX: allocating this many mbufs on the fly is pretty 159191783Srmacklem * inefficient... 160191783Srmacklem */ 161191783Srmacklemstatic struct mbuf * 162191783Srmacklemsctp_asconf_success_response(uint32_t id) 163191783Srmacklem{ 164191783Srmacklem struct mbuf *m_reply = NULL; 165191783Srmacklem struct sctp_asconf_paramhdr *aph; 166191783Srmacklem 167191783Srmacklem m_reply = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_paramhdr), 168191783Srmacklem 0, M_DONTWAIT, 1, MT_DATA); 169191783Srmacklem if (m_reply == NULL) { 170191783Srmacklem#ifdef SCTP_DEBUG 171214406Srmacklem if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 172191783Srmacklem printf("asconf_success_response: couldn't get mbuf!\n"); 173191783Srmacklem } 174191783Srmacklem#endif /* SCTP_DEBUG */ 175191783Srmacklem return NULL; 176191783Srmacklem } 177191783Srmacklem aph = mtod(m_reply, struct sctp_asconf_paramhdr *); 178191783Srmacklem aph->correlation_id = id; 179191783Srmacklem aph->ph.param_type = htons(SCTP_SUCCESS_REPORT); 180191783Srmacklem aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr); 181191783Srmacklem m_reply->m_len = aph->ph.param_length; 182191783Srmacklem aph->ph.param_length = htons(aph->ph.param_length); 183191783Srmacklem 184191783Srmacklem return m_reply; 185191783Srmacklem} 186191783Srmacklem 187191783Srmacklemstatic struct mbuf * 188191783Srmacklemsctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv, 189191783Srmacklem uint16_t tlv_length) 190191783Srmacklem{ 191191783Srmacklem struct mbuf *m_reply = NULL; 192191783Srmacklem struct sctp_asconf_paramhdr *aph; 193191783Srmacklem struct sctp_error_cause *error; 194191783Srmacklem uint8_t *tlv; 195206688Srmacklem 196191783Srmacklem m_reply = sctp_get_mbuf_for_msg((sizeof(struct sctp_asconf_paramhdr) + 197191783Srmacklem tlv_length + 198191783Srmacklem sizeof(struct sctp_error_cause)), 199191783Srmacklem 0, M_DONTWAIT, 1, MT_DATA); 200191783Srmacklem if (m_reply == NULL) { 201191783Srmacklem#ifdef SCTP_DEBUG 202191783Srmacklem if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 203228217Srmacklem printf("asconf_error_response: couldn't get mbuf!\n"); 204191783Srmacklem } 205191783Srmacklem#endif /* SCTP_DEBUG */ 206191783Srmacklem return NULL; 207191783Srmacklem } 208191783Srmacklem aph = mtod(m_reply, struct sctp_asconf_paramhdr *); 209191783Srmacklem error = (struct sctp_error_cause *)(aph + 1); 210191783Srmacklem 211191783Srmacklem aph->correlation_id = id; 212191783Srmacklem aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND); 213191783Srmacklem error->code = htons(cause); 214191783Srmacklem error->length = tlv_length + sizeof(struct sctp_error_cause); 215191783Srmacklem aph->ph.param_length = error->length + 216191783Srmacklem sizeof(struct sctp_asconf_paramhdr); 217191783Srmacklem 218191783Srmacklem if (aph->ph.param_length > MLEN) { 219191783Srmacklem#ifdef SCTP_DEBUG 220228217Srmacklem if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 221228217Srmacklem printf("asconf_error_response: tlv_length (%xh) too big\n", 222228217Srmacklem tlv_length); 223228217Srmacklem } 224228217Srmacklem#endif /* SCTP_DEBUG */ 225228217Srmacklem sctp_m_freem(m_reply); /* discard */ 226228217Srmacklem return NULL; 227228217Srmacklem } 228191783Srmacklem if (error_tlv != NULL) { 229244042Srmacklem tlv = (uint8_t *) (error + 1); 230244042Srmacklem memcpy(tlv, error_tlv, tlv_length); 231244042Srmacklem } 232244042Srmacklem m_reply->m_len = aph->ph.param_length; 233244042Srmacklem error->length = htons(error->length); 234244042Srmacklem aph->ph.param_length = htons(aph->ph.param_length); 235244042Srmacklem 236244042Srmacklem return m_reply; 237244042Srmacklem} 238244042Srmacklem 239244042Srmacklemstatic struct mbuf * 240244042Srmacklemsctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, 241244042Srmacklem struct sctp_tcb *stcb, int response_required) 242244042Srmacklem{ 243244042Srmacklem struct mbuf *m_reply = NULL; 244244042Srmacklem struct sockaddr_storage sa_source, sa_store; 245244042Srmacklem struct sctp_ipv4addr_param *v4addr; 246244042Srmacklem uint16_t param_type, param_length, aparam_length; 247244042Srmacklem struct sockaddr *sa; 248244042Srmacklem struct sockaddr_in *sin; 249244042Srmacklem int zero_address = 0; 250244042Srmacklem 251244042Srmacklem#ifdef INET6 252244042Srmacklem struct sockaddr_in6 *sin6; 253244042Srmacklem struct sctp_ipv6addr_param *v6addr; 254244042Srmacklem 255244042Srmacklem#endif /* INET6 */ 256244042Srmacklem 257244042Srmacklem aparam_length = ntohs(aph->ph.param_length); 258244042Srmacklem v4addr = (struct sctp_ipv4addr_param *)(aph + 1); 259244042Srmacklem#ifdef INET6 260244042Srmacklem v6addr = (struct sctp_ipv6addr_param *)(aph + 1); 261244042Srmacklem#endif /* INET6 */ 262244042Srmacklem param_type = ntohs(v4addr->ph.param_type); 263244042Srmacklem param_length = ntohs(v4addr->ph.param_length); 264244042Srmacklem 265244042Srmacklem sa = (struct sockaddr *)&sa_store; 266244042Srmacklem switch (param_type) { 267244042Srmacklem case SCTP_IPV4_ADDRESS: 268244042Srmacklem if (param_length != sizeof(struct sctp_ipv4addr_param)) { 269244042Srmacklem /* invalid param size */ 270244042Srmacklem return NULL; 271244042Srmacklem } 272244042Srmacklem sin = (struct sockaddr_in *)&sa_store; 273244042Srmacklem bzero(sin, sizeof(*sin)); 274244042Srmacklem sin->sin_family = AF_INET; 275244042Srmacklem sin->sin_len = sizeof(struct sockaddr_in); 276244042Srmacklem sin->sin_port = stcb->rport; 277244042Srmacklem sin->sin_addr.s_addr = v4addr->addr; 278244042Srmacklem if (sin->sin_addr.s_addr == INADDR_ANY) 279244042Srmacklem zero_address = 1; 280244042Srmacklem#ifdef SCTP_DEBUG 281244042Srmacklem if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 282244042Srmacklem printf("process_asconf_add_ip: adding "); 283244042Srmacklem sctp_print_address(sa); 284244042Srmacklem } 285244042Srmacklem#endif /* SCTP_DEBUG */ 286244042Srmacklem break; 287244042Srmacklem case SCTP_IPV6_ADDRESS: 288244042Srmacklem#ifdef INET6 289244042Srmacklem if (param_length != sizeof(struct sctp_ipv6addr_param)) { 290244042Srmacklem /* invalid param size */ 291244042Srmacklem return NULL; 292244042Srmacklem } 293244042Srmacklem sin6 = (struct sockaddr_in6 *)&sa_store; 294244042Srmacklem bzero(sin6, sizeof(*sin6)); 295244042Srmacklem sin6->sin6_family = AF_INET6; 296244042Srmacklem sin6->sin6_len = sizeof(struct sockaddr_in6); 297244042Srmacklem sin6->sin6_port = stcb->rport; 298244042Srmacklem memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr, 299244042Srmacklem sizeof(struct in6_addr)); 300244042Srmacklem if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 301244042Srmacklem zero_address = 1; 302244042Srmacklem#ifdef SCTP_DEBUG 303244042Srmacklem if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 304244042Srmacklem printf("process_asconf_add_ip: adding "); 305244042Srmacklem sctp_print_address(sa); 306244042Srmacklem } 307244042Srmacklem#endif /* SCTP_DEBUG */ 308244042Srmacklem#else 309244042Srmacklem /* IPv6 not enabled! */ 310244042Srmacklem /* FIX ME: currently sends back an invalid param error */ 311244042Srmacklem m_reply = sctp_asconf_error_response(aph->correlation_id, 312244042Srmacklem SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, aparam_length); 313244042Srmacklem#ifdef SCTP_DEBUG 314244042Srmacklem if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 315244042Srmacklem printf("process_asconf_add_ip: v6 disabled- skipping "); 316244042Srmacklem sctp_print_address(sa); 317244042Srmacklem } 318244042Srmacklem#endif /* SCTP_DEBUG */ 319244042Srmacklem return m_reply; 320244042Srmacklem#endif /* INET6 */ 321244042Srmacklem break; 322244042Srmacklem default: 323244042Srmacklem m_reply = sctp_asconf_error_response(aph->correlation_id, 324244042Srmacklem SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 325244042Srmacklem aparam_length); 326244042Srmacklem return m_reply; 327244042Srmacklem } /* end switch */ 328244042Srmacklem 329244042Srmacklem /* if 0.0.0.0/::0, add the source address instead */ 330244042Srmacklem if (zero_address) { 331244042Srmacklem sa = (struct sockaddr *)&sa_source; 332244042Srmacklem sctp_asconf_get_source_ip(m, sa); 333244042Srmacklem#ifdef SCTP_DEBUG 334244042Srmacklem if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 335244042Srmacklem printf("process_asconf_add_ip: using source addr "); 336244042Srmacklem sctp_print_address(sa); 337244042Srmacklem } 338244042Srmacklem#endif /* SCTP_DEBUG */ 339244042Srmacklem } 340244042Srmacklem /* add the address */ 341244042Srmacklem if (sctp_add_remote_addr(stcb, sa, 0, 6) != 0) { 342244042Srmacklem#ifdef SCTP_DEBUG 343244042Srmacklem if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 344244042Srmacklem printf("process_asconf_add_ip: error adding address\n"); 345244042Srmacklem } 346244042Srmacklem#endif /* SCTP_DEBUG */ 347244042Srmacklem m_reply = sctp_asconf_error_response(aph->correlation_id, 348244042Srmacklem SCTP_CAUSE_RESOURCE_SHORTAGE, (uint8_t *) aph, 349244042Srmacklem aparam_length); 350244042Srmacklem } else { 351244042Srmacklem /* notify upper layer */ 352244042Srmacklem sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa); 353244042Srmacklem if (response_required) { 354244042Srmacklem m_reply = 355244042Srmacklem sctp_asconf_success_response(aph->correlation_id); 356244042Srmacklem } 357244042Srmacklem sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, NULL); 358244042Srmacklem sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, NULL); 359244042Srmacklem 360244042Srmacklem } 361244042Srmacklem 362244042Srmacklem return m_reply; 363244042Srmacklem} 364191783Srmacklem 365191783Srmacklemstatic int 366191783Srmacklemsctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, 367191783Srmacklem struct sockaddr *src) 368191783Srmacklem{ 369191783Srmacklem struct sctp_nets *src_net, *net; 370191783Srmacklem 371191783Srmacklem /* make sure the source address exists as a destination net */ 372 src_net = sctp_findnet(stcb, src); 373 if (src_net == NULL) { 374 /* not found */ 375 return -1; 376 } 377 /* delete all destination addresses except the source */ 378 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 379 if (net != src_net) { 380 /* delete this address */ 381 sctp_remove_net(stcb, net); 382#ifdef SCTP_DEBUG 383 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 384 printf("asconf_del_remote_addrs_except: deleting "); 385 sctp_print_address((struct sockaddr *)&net->ro._l_addr); 386 } 387#endif 388 /* notify upper layer */ 389 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, 390 (struct sockaddr *)&net->ro._l_addr); 391 } 392 } 393 return 0; 394} 395 396static struct mbuf * 397sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, 398 struct sctp_tcb *stcb, int response_required) 399{ 400 struct mbuf *m_reply = NULL; 401 struct sockaddr_storage sa_source, sa_store; 402 struct sctp_ipv4addr_param *v4addr; 403 uint16_t param_type, param_length, aparam_length; 404 struct sockaddr *sa; 405 struct sockaddr_in *sin; 406 int zero_address = 0; 407 int result; 408 409#ifdef INET6 410 struct sockaddr_in6 *sin6; 411 struct sctp_ipv6addr_param *v6addr; 412 413#endif /* INET6 */ 414 415 /* get the source IP address for src and 0.0.0.0/::0 delete checks */ 416 sctp_asconf_get_source_ip(m, (struct sockaddr *)&sa_source); 417 418 aparam_length = ntohs(aph->ph.param_length); 419 v4addr = (struct sctp_ipv4addr_param *)(aph + 1); 420#ifdef INET6 421 v6addr = (struct sctp_ipv6addr_param *)(aph + 1); 422#endif /* INET6 */ 423 param_type = ntohs(v4addr->ph.param_type); 424 param_length = ntohs(v4addr->ph.param_length); 425 426 sa = (struct sockaddr *)&sa_store; 427 switch (param_type) { 428 case SCTP_IPV4_ADDRESS: 429 if (param_length != sizeof(struct sctp_ipv4addr_param)) { 430 /* invalid param size */ 431 return NULL; 432 } 433 sin = (struct sockaddr_in *)&sa_store; 434 bzero(sin, sizeof(*sin)); 435 sin->sin_family = AF_INET; 436 sin->sin_len = sizeof(struct sockaddr_in); 437 sin->sin_port = stcb->rport; 438 sin->sin_addr.s_addr = v4addr->addr; 439 if (sin->sin_addr.s_addr == INADDR_ANY) 440 zero_address = 1; 441#ifdef SCTP_DEBUG 442 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 443 printf("process_asconf_delete_ip: deleting "); 444 sctp_print_address(sa); 445 } 446#endif /* SCTP_DEBUG */ 447 break; 448 case SCTP_IPV6_ADDRESS: 449 if (param_length != sizeof(struct sctp_ipv6addr_param)) { 450 /* invalid param size */ 451 return NULL; 452 } 453#ifdef INET6 454 sin6 = (struct sockaddr_in6 *)&sa_store; 455 bzero(sin6, sizeof(*sin6)); 456 sin6->sin6_family = AF_INET6; 457 sin6->sin6_len = sizeof(struct sockaddr_in6); 458 sin6->sin6_port = stcb->rport; 459 memcpy(&sin6->sin6_addr, v6addr->addr, 460 sizeof(struct in6_addr)); 461 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 462 zero_address = 1; 463#ifdef SCTP_DEBUG 464 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 465 printf("process_asconf_delete_ip: deleting "); 466 sctp_print_address(sa); 467 } 468#endif /* SCTP_DEBUG */ 469#else 470 /* IPv6 not enabled! No "action" needed; just ack it */ 471#ifdef SCTP_DEBUG 472 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 473 printf("process_asconf_delete_ip: v6 disabled- ignoring: "); 474 sctp_print_address(sa); 475 } 476#endif /* SCTP_DEBUG */ 477 /* just respond with a "success" ASCONF-ACK */ 478 return NULL; 479#endif /* INET6 */ 480 break; 481 default: 482 m_reply = sctp_asconf_error_response(aph->correlation_id, 483 SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 484 aparam_length); 485 return m_reply; 486 } 487 488 /* make sure the source address is not being deleted */ 489 if (sctp_cmpaddr(sa, (struct sockaddr *)&sa_source)) { 490 /* trying to delete the source address! */ 491#ifdef SCTP_DEBUG 492 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 493 printf("process_asconf_delete_ip: tried to delete source addr\n"); 494 } 495#endif /* SCTP_DEBUG */ 496 m_reply = sctp_asconf_error_response(aph->correlation_id, 497 SCTP_CAUSE_DELETING_SRC_ADDR, (uint8_t *) aph, 498 aparam_length); 499 return m_reply; 500 } 501 /* if deleting 0.0.0.0/::0, delete all addresses except src addr */ 502 if (zero_address) { 503 result = sctp_asconf_del_remote_addrs_except(stcb, 504 (struct sockaddr *)&sa_source); 505 506 if (result) { 507 /* src address did not exist? */ 508#ifdef SCTP_DEBUG 509 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 510 printf("process_asconf_delete_ip: src addr does not exist?\n"); 511 } 512#endif /* SCTP_DEBUG */ 513 /* what error to reply with?? */ 514 m_reply = 515 sctp_asconf_error_response(aph->correlation_id, 516 SCTP_CAUSE_REQUEST_REFUSED, (uint8_t *) aph, 517 aparam_length); 518 } else if (response_required) { 519 m_reply = 520 sctp_asconf_success_response(aph->correlation_id); 521 } 522 return m_reply; 523 } 524 /* delete the address */ 525 result = sctp_del_remote_addr(stcb, sa); 526 /* 527 * note if result == -2, the address doesn't exist in the asoc but 528 * since it's being deleted anyways, we just ack the delete -- but 529 * this probably means something has already gone awry 530 */ 531 if (result == -1) { 532 /* only one address in the asoc */ 533#ifdef SCTP_DEBUG 534 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 535 printf("process_asconf_delete_ip: tried to delete last IP addr!\n"); 536 } 537#endif /* SCTP_DEBUG */ 538 m_reply = sctp_asconf_error_response(aph->correlation_id, 539 SCTP_CAUSE_DELETING_LAST_ADDR, (uint8_t *) aph, 540 aparam_length); 541 } else { 542 if (response_required) { 543 m_reply = sctp_asconf_success_response(aph->correlation_id); 544 } 545 /* notify upper layer */ 546 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa); 547 } 548 return m_reply; 549} 550 551static struct mbuf * 552sctp_process_asconf_set_primary(struct mbuf *m, 553 struct sctp_asconf_paramhdr *aph, struct sctp_tcb *stcb, 554 int response_required) 555{ 556 struct mbuf *m_reply = NULL; 557 struct sockaddr_storage sa_source, sa_store; 558 struct sctp_ipv4addr_param *v4addr; 559 uint16_t param_type, param_length, aparam_length; 560 struct sockaddr *sa; 561 struct sockaddr_in *sin; 562 int zero_address = 0; 563 564#ifdef INET6 565 struct sockaddr_in6 *sin6; 566 struct sctp_ipv6addr_param *v6addr; 567 568#endif /* INET6 */ 569 570 aparam_length = ntohs(aph->ph.param_length); 571 v4addr = (struct sctp_ipv4addr_param *)(aph + 1); 572#ifdef INET6 573 v6addr = (struct sctp_ipv6addr_param *)(aph + 1); 574#endif /* INET6 */ 575 param_type = ntohs(v4addr->ph.param_type); 576 param_length = ntohs(v4addr->ph.param_length); 577 578 sa = (struct sockaddr *)&sa_store; 579 switch (param_type) { 580 case SCTP_IPV4_ADDRESS: 581 if (param_length != sizeof(struct sctp_ipv4addr_param)) { 582 /* invalid param size */ 583 return NULL; 584 } 585 sin = (struct sockaddr_in *)&sa_store; 586 bzero(sin, sizeof(*sin)); 587 sin->sin_family = AF_INET; 588 sin->sin_len = sizeof(struct sockaddr_in); 589 sin->sin_addr.s_addr = v4addr->addr; 590 if (sin->sin_addr.s_addr == INADDR_ANY) 591 zero_address = 1; 592#ifdef SCTP_DEBUG 593 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 594 printf("process_asconf_set_primary: "); 595 sctp_print_address(sa); 596 } 597#endif /* SCTP_DEBUG */ 598 break; 599 case SCTP_IPV6_ADDRESS: 600 if (param_length != sizeof(struct sctp_ipv6addr_param)) { 601 /* invalid param size */ 602 return NULL; 603 } 604#ifdef INET6 605 sin6 = (struct sockaddr_in6 *)&sa_store; 606 bzero(sin6, sizeof(*sin6)); 607 sin6->sin6_family = AF_INET6; 608 sin6->sin6_len = sizeof(struct sockaddr_in6); 609 memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr, 610 sizeof(struct in6_addr)); 611 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 612 zero_address = 1; 613#ifdef SCTP_DEBUG 614 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 615 printf("process_asconf_set_primary: "); 616 sctp_print_address(sa); 617 } 618#endif /* SCTP_DEBUG */ 619#else 620 /* IPv6 not enabled! No "action" needed; just ack it */ 621#ifdef SCTP_DEBUG 622 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 623 printf("process_asconf_set_primary: v6 disabled- ignoring: "); 624 sctp_print_address(sa); 625 } 626#endif /* SCTP_DEBUG */ 627 /* just respond with a "success" ASCONF-ACK */ 628 return NULL; 629#endif /* INET6 */ 630 break; 631 default: 632 m_reply = sctp_asconf_error_response(aph->correlation_id, 633 SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 634 aparam_length); 635 return m_reply; 636 } 637 638 /* if 0.0.0.0/::0, use the source address instead */ 639 if (zero_address) { 640 sa = (struct sockaddr *)&sa_source; 641 sctp_asconf_get_source_ip(m, sa); 642#ifdef SCTP_DEBUG 643 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 644 printf("process_asconf_set_primary: using source addr "); 645 sctp_print_address(sa); 646 } 647#endif /* SCTP_DEBUG */ 648 } 649 /* set the primary address */ 650 if (sctp_set_primary_addr(stcb, sa, NULL) == 0) { 651#ifdef SCTP_DEBUG 652 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 653 printf("process_asconf_set_primary: primary address set\n"); 654 } 655#endif /* SCTP_DEBUG */ 656 /* notify upper layer */ 657 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa); 658 659 if (response_required) { 660 m_reply = sctp_asconf_success_response(aph->correlation_id); 661 } 662 } else { 663 /* couldn't set the requested primary address! */ 664#ifdef SCTP_DEBUG 665 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 666 printf("process_asconf_set_primary: set primary failed!\n"); 667 } 668#endif /* SCTP_DEBUG */ 669 /* must have been an invalid address, so report */ 670 m_reply = sctp_asconf_error_response(aph->correlation_id, 671 SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 672 aparam_length); 673 } 674 675 return m_reply; 676} 677 678/* 679 * handles an ASCONF chunk. 680 * if all parameters are processed ok, send a plain (empty) ASCONF-ACK 681 */ 682void 683sctp_handle_asconf(struct mbuf *m, unsigned int offset, 684 struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb) 685{ 686 struct sctp_association *asoc; 687 uint32_t serial_num; 688 struct mbuf *m_ack, *m_result, *m_tail; 689 struct sctp_asconf_ack_chunk *ack_cp; 690 struct sctp_asconf_paramhdr *aph, *ack_aph; 691 struct sctp_ipv6addr_param *p_addr; 692 unsigned int asconf_limit; 693 int error = 0; /* did an error occur? */ 694 695 /* asconf param buffer */ 696 static uint8_t aparam_buf[DEFAULT_PARAM_BUFFER]; 697 698 /* verify minimum length */ 699 if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) { 700#ifdef SCTP_DEBUG 701 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 702 printf("handle_asconf: chunk too small = %xh\n", 703 ntohs(cp->ch.chunk_length)); 704 } 705#endif /* SCTP_DEBUG */ 706 return; 707 } 708 asoc = &stcb->asoc; 709 serial_num = ntohl(cp->serial_number); 710 711 if (serial_num == asoc->asconf_seq_in) { 712 /* got a duplicate ASCONF */ 713#ifdef SCTP_DEBUG 714 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 715 printf("handle_asconf: got duplicate serial number = %xh\n", 716 serial_num); 717 } 718#endif /* SCTP_DEBUG */ 719 /* resend last ASCONF-ACK... */ 720 sctp_send_asconf_ack(stcb, 1); 721 return; 722 } else if (serial_num != (asoc->asconf_seq_in + 1)) { 723#ifdef SCTP_DEBUG 724 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 725 printf("handle_asconf: incorrect serial number = %xh (expected next = %xh)\n", 726 serial_num, asoc->asconf_seq_in + 1); 727 } 728#endif /* SCTP_DEBUG */ 729 return; 730 } 731 /* it's the expected "next" sequence number, so process it */ 732 asoc->asconf_seq_in = serial_num; /* update sequence */ 733 /* get length of all the param's in the ASCONF */ 734 asconf_limit = offset + ntohs(cp->ch.chunk_length); 735#ifdef SCTP_DEBUG 736 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 737 printf("handle_asconf: asconf_limit=%u, sequence=%xh\n", 738 asconf_limit, serial_num); 739 } 740#endif /* SCTP_DEBUG */ 741 if (asoc->last_asconf_ack_sent != NULL) { 742 /* free last ASCONF-ACK message sent */ 743 sctp_m_freem(asoc->last_asconf_ack_sent); 744 asoc->last_asconf_ack_sent = NULL; 745 } 746 m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 1, 747 M_DONTWAIT, 1, MT_DATA); 748 if (m_ack == NULL) { 749#ifdef SCTP_DEBUG 750 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 751 printf("handle_asconf: couldn't get mbuf!\n"); 752 } 753#endif /* SCTP_DEBUG */ 754 return; 755 } 756 m_tail = m_ack; /* current reply chain's tail */ 757 758 /* fill in ASCONF-ACK header */ 759 ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *); 760 ack_cp->ch.chunk_type = SCTP_ASCONF_ACK; 761 ack_cp->ch.chunk_flags = 0; 762 ack_cp->serial_number = htonl(serial_num); 763 /* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */ 764 m_ack->m_len = sizeof(struct sctp_asconf_ack_chunk); 765 ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk); 766 m_ack->m_pkthdr.len = sizeof(struct sctp_asconf_ack_chunk); 767 768 /* skip the lookup address parameter */ 769 offset += sizeof(struct sctp_asconf_chunk); 770 p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *) & aparam_buf); 771 if (p_addr == NULL) { 772#ifdef SCTP_DEBUG 773 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 774 printf("handle_asconf: couldn't get lookup addr!\n"); 775 } 776#endif /* SCTP_DEBUG */ 777 778 /* respond with a missing/invalid mandatory parameter error */ 779 return; 780 } 781 /* param_length is already validated in process_control... */ 782 offset += ntohs(p_addr->ph.param_length); /* skip lookup addr */ 783 784 /* get pointer to first asconf param in ASCONF-ACK */ 785 ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t)+sizeof(struct sctp_asconf_ack_chunk)); 786 if (ack_aph == NULL) { 787#ifdef SCTP_DEBUG 788 printf("Gak in asconf2\n"); 789#endif 790 return; 791 } 792 /* get pointer to first asconf param in ASCONF */ 793 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *) & aparam_buf); 794 if (aph == NULL) { 795#ifdef SCTP_DEBUG 796 printf("Empty ASCONF received?\n"); 797#endif 798 goto send_reply; 799 } 800 /* process through all parameters */ 801 while (aph != NULL) { 802 unsigned int param_length, param_type; 803 804 param_type = ntohs(aph->ph.param_type); 805 param_length = ntohs(aph->ph.param_length); 806 if (offset + param_length > asconf_limit) { 807 /* parameter goes beyond end of chunk! */ 808 sctp_m_freem(m_ack); 809 return; 810 } 811 m_result = NULL; 812 813 if (param_length > sizeof(aparam_buf)) { 814#ifdef SCTP_DEBUG 815 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 816 printf("handle_asconf: param length (%u) larger than buffer size!\n", param_length); 817 } 818#endif /* SCTP_DEBUG */ 819 sctp_m_freem(m_ack); 820 return; 821 } 822 if (param_length <= sizeof(struct sctp_paramhdr)) { 823#ifdef SCTP_DEBUG 824 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 825 printf("handle_asconf: param length (%u) too short\n", param_length); 826 } 827#endif /* SCTP_DEBUG */ 828 sctp_m_freem(m_ack); 829 } 830 /* get the entire parameter */ 831 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf); 832 if (aph == NULL) { 833#ifdef SCTP_DEBUG 834 printf("Gag\n"); 835#endif 836 sctp_m_freem(m_ack); 837 return; 838 } 839 switch (param_type) { 840 case SCTP_ADD_IP_ADDRESS: 841 asoc->peer_supports_asconf = 1; 842 m_result = sctp_process_asconf_add_ip(m, aph, stcb, 843 error); 844 break; 845 case SCTP_DEL_IP_ADDRESS: 846 asoc->peer_supports_asconf = 1; 847 m_result = sctp_process_asconf_delete_ip(m, aph, stcb, 848 error); 849 break; 850 case SCTP_ERROR_CAUSE_IND: 851 /* not valid in an ASCONF chunk */ 852 break; 853 case SCTP_SET_PRIM_ADDR: 854 asoc->peer_supports_asconf = 1; 855 m_result = sctp_process_asconf_set_primary(m, aph, 856 stcb, error); 857 break; 858 case SCTP_SUCCESS_REPORT: 859 /* not valid in an ASCONF chunk */ 860 break; 861 case SCTP_ULP_ADAPTATION: 862 /* FIX */ 863 break; 864 default: 865 if ((param_type & 0x8000) == 0) { 866 /* Been told to STOP at this param */ 867 asconf_limit = offset; 868 /* 869 * FIX FIX - We need to call 870 * sctp_arethere_unrecognized_parameters() 871 * to get a operr and send it for any 872 * param's with the 0x4000 bit set OR do it 873 * here ourselves... note we still must STOP 874 * if the 0x8000 bit is clear. 875 */ 876 } 877 /* unknown/invalid param type */ 878 break; 879 } /* switch */ 880 881 /* add any (error) result to the reply mbuf chain */ 882 if (m_result != NULL) { 883 m_tail->m_next = m_result; 884 m_tail = m_result; 885 /* update lengths, make sure it's aligned too */ 886 m_result->m_len = SCTP_SIZE32(m_result->m_len); 887 m_ack->m_pkthdr.len += m_result->m_len; 888 ack_cp->ch.chunk_length += m_result->m_len; 889 /* set flag to force success reports */ 890 error = 1; 891 } 892 offset += SCTP_SIZE32(param_length); 893 /* update remaining ASCONF message length to process */ 894 if (offset >= asconf_limit) { 895 /* no more data in the mbuf chain */ 896 break; 897 } 898 /* get pointer to next asconf param */ 899 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, 900 sizeof(struct sctp_asconf_paramhdr), 901 (uint8_t *) & aparam_buf); 902 if (aph == NULL) { 903 /* can't get an asconf paramhdr */ 904#ifdef SCTP_DEBUG 905 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 906 printf("handle_asconf: can't get asconf param hdr!\n"); 907 } 908#endif /* SCTP_DEBUG */ 909 /* FIX ME - add error here... */ 910 } 911 } /* while */ 912 913send_reply: 914 ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length); 915 /* save the ASCONF-ACK reply */ 916 asoc->last_asconf_ack_sent = m_ack; 917 918 /* see if last_control_chunk_from is set properly (use IP src addr) */ 919 if (stcb->asoc.last_control_chunk_from == NULL) { 920 /* 921 * this could happen if the source address was just newly 922 * added 923 */ 924 struct ip *iph; 925 struct sctphdr *sh; 926 struct sockaddr_storage from_store; 927 struct sockaddr *from = (struct sockaddr *)&from_store; 928 929#ifdef SCTP_DEBUG 930 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) 931 printf("handle_asconf: looking up net for IP source address\n"); 932#endif /* SCTP_DEBUG */ 933 /* pullup already done, IP options already stripped */ 934 iph = mtod(m, struct ip *); 935 sh = (struct sctphdr *)((caddr_t)iph + sizeof(*iph)); 936 if (iph->ip_v == IPVERSION) { 937 struct sockaddr_in *from4; 938 939 from4 = (struct sockaddr_in *)&from_store; 940 bzero(from4, sizeof(*from4)); 941 from4->sin_family = AF_INET; 942 from4->sin_len = sizeof(struct sockaddr_in); 943 from4->sin_addr.s_addr = iph->ip_src.s_addr; 944 from4->sin_port = sh->src_port; 945 } else if (iph->ip_v == (IPV6_VERSION >> 4)) { 946 struct ip6_hdr *ip6; 947 struct sockaddr_in6 *from6; 948 949 ip6 = mtod(m, struct ip6_hdr *); 950 from6 = (struct sockaddr_in6 *)&from_store; 951 bzero(from6, sizeof(*from6)); 952 from6->sin6_family = AF_INET6; 953 from6->sin6_len = sizeof(struct sockaddr_in6); 954 from6->sin6_addr = ip6->ip6_src; 955 from6->sin6_port = sh->src_port; 956 /* Get the scopes in properly to the sin6 addr's */ 957 /* we probably don't need these operations */ 958 (void)sa6_recoverscope(from6); 959 sa6_embedscope(from6, ip6_use_defzone); 960 } else { 961 /* unknown address type */ 962 from = NULL; 963 } 964 if (from != NULL) { 965#ifdef SCTP_DEBUG 966 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 967 printf("Looking for IP source: "); 968 sctp_print_address(from); 969 } 970#endif /* SCTP_DEBUG */ 971 /* look up the from address */ 972 stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, from); 973#ifdef SCTP_DEBUG 974 if ((stcb->asoc.last_control_chunk_from == NULL) && 975 (sctp_debug_on & SCTP_DEBUG_ASCONF1)) 976 printf("handle_asconf: IP source address not found?!\n"); 977#endif /* SCTP_DEBUG */ 978 } 979 } 980 /* and send it (a new one) out... */ 981 sctp_send_asconf_ack(stcb, 0); 982} 983 984/* 985 * does the address match? returns 0 if not, 1 if so 986 */ 987static uint32_t 988sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa) 989{ 990#ifdef INET6 991 if (sa->sa_family == AF_INET6) { 992 /* IPv6 sa address */ 993 /* XXX scopeid */ 994 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 995 996 if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) && 997 (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr, 998 sizeof(struct in6_addr)) == 0)) { 999 return (1); 1000 } 1001 } else 1002#endif /* INET6 */ 1003 if (sa->sa_family == AF_INET) { 1004 /* IPv4 sa address */ 1005 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 1006 1007 if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) && 1008 (memcmp(&aa->ap.addrp.addr, &sin->sin_addr, 1009 sizeof(struct in_addr)) == 0)) { 1010 return (1); 1011 } 1012 } 1013 return (0); 1014} 1015 1016/* 1017 * Cleanup for non-responded/OP ERR'd ASCONF 1018 */ 1019void 1020sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net) 1021{ 1022 /* mark peer as ASCONF incapable */ 1023 stcb->asoc.peer_supports_asconf = 0; 1024 /* 1025 * clear out any existing asconfs going out 1026 */ 1027 sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net); 1028 stcb->asoc.asconf_seq_out++; 1029 /* remove the old ASCONF on our outbound queue */ 1030 sctp_toss_old_asconf(stcb); 1031} 1032 1033/* 1034 * process an ADD/DELETE IP ack from peer. 1035 * addr corresponding ifaddr to the address being added/deleted. 1036 * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS. 1037 * flag: 1=success, 0=failure. 1038 */ 1039static void 1040sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct ifaddr *addr, 1041 uint16_t type, uint32_t flag) 1042{ 1043 /* 1044 * do the necessary asoc list work- if we get a failure indication, 1045 * leave the address on the "do not use" asoc list if we get a 1046 * success indication, remove the address from the list 1047 */ 1048 /* 1049 * Note: this will only occur for ADD_IP_ADDRESS, since 1050 * DEL_IP_ADDRESS is never actually added to the list... 1051 */ 1052 if (flag) { 1053 /* success case, so remove from the list */ 1054 sctp_del_local_addr_assoc(stcb, addr); 1055 } 1056 /* else, leave it on the list */ 1057} 1058 1059/* 1060 * add an asconf add/delete IP address parameter to the queue. 1061 * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. 1062 * returns 0 if completed, non-zero if not completed. 1063 * NOTE: if adding, but delete already scheduled (and not yet sent out), 1064 * simply remove from queue. Same for deleting an address already scheduled 1065 * for add. If a duplicate operation is found, ignore the new one. 1066 */ 1067static uint32_t 1068sctp_asconf_queue_add(struct sctp_tcb *stcb, struct ifaddr *ifa, uint16_t type) 1069{ 1070 struct sctp_asconf_addr *aa, *aa_next; 1071 struct sockaddr *sa; 1072 1073 /* see if peer supports ASCONF */ 1074 if (stcb->asoc.peer_supports_asconf == 0) { 1075 return (-1); 1076 } 1077 /* make sure the request isn't already in the queue */ 1078 for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL; 1079 aa = aa_next) { 1080 aa_next = TAILQ_NEXT(aa, next); 1081 /* address match? */ 1082 if (sctp_asconf_addr_match(aa, ifa->ifa_addr) == 0) 1083 continue; 1084 /* is the request already in queue (sent or not) */ 1085 if (aa->ap.aph.ph.param_type == type) { 1086 return (-1); 1087 } 1088 /* is the negative request already in queue, and not sent */ 1089 if (aa->sent == 0 && 1090 /* add requested, delete already queued */ 1091 ((type == SCTP_ADD_IP_ADDRESS && 1092 aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) || 1093 /* delete requested, add already queued */ 1094 (type == SCTP_DEL_IP_ADDRESS && 1095 aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS))) { 1096 /* delete the existing entry in the queue */ 1097 TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 1098 /* take the entry off the appropriate list */ 1099 sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1); 1100 /* free the entry */ 1101 SCTP_FREE(aa); 1102 return (-1); 1103 } 1104 } /* for each aa */ 1105 1106 /* adding new request to the queue */ 1107 SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), "AsconfAddr"); 1108 if (aa == NULL) { 1109 /* didn't get memory */ 1110#ifdef SCTP_DEBUG 1111 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1112 printf("asconf_queue_add: failed to get memory!\n"); 1113 } 1114#endif /* SCTP_DEBUG */ 1115 return (-1); 1116 } 1117 /* fill in asconf address parameter fields */ 1118 /* top level elements are "networked" during send */ 1119 aa->ap.aph.ph.param_type = type; 1120 aa->ifa = ifa; 1121 /* correlation_id filled in during send routine later... */ 1122 if (ifa->ifa_addr->sa_family == AF_INET6) { 1123 /* IPv6 address */ 1124 struct sockaddr_in6 *sin6; 1125 1126 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 1127 sa = (struct sockaddr *)sin6; 1128 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 1129 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); 1130 aa->ap.aph.ph.param_length = 1131 sizeof(struct sctp_asconf_paramhdr) + 1132 sizeof(struct sctp_ipv6addr_param); 1133 memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, 1134 sizeof(struct in6_addr)); 1135 } else if (ifa->ifa_addr->sa_family == AF_INET) { 1136 /* IPv4 address */ 1137 struct sockaddr_in *sin = (struct sockaddr_in *)ifa->ifa_addr; 1138 1139 sa = (struct sockaddr *)sin; 1140 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 1141 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); 1142 aa->ap.aph.ph.param_length = 1143 sizeof(struct sctp_asconf_paramhdr) + 1144 sizeof(struct sctp_ipv4addr_param); 1145 memcpy(&aa->ap.addrp.addr, &sin->sin_addr, 1146 sizeof(struct in_addr)); 1147 } else { 1148 /* invalid family! */ 1149 return (-1); 1150 } 1151 aa->sent = 0; /* clear sent flag */ 1152 1153 /* 1154 * if we are deleting an address it should go out last otherwise, 1155 * add it to front of the pending queue 1156 */ 1157 if (type == SCTP_ADD_IP_ADDRESS) { 1158 /* add goes to the front of the queue */ 1159 TAILQ_INSERT_HEAD(&stcb->asoc.asconf_queue, aa, next); 1160#ifdef SCTP_DEBUG 1161 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) { 1162 printf("asconf_queue_add: appended asconf ADD_IP_ADDRESS: "); 1163 sctp_print_address(sa); 1164 } 1165#endif /* SCTP_DEBUG */ 1166 } else { 1167 /* delete and set primary goes to the back of the queue */ 1168 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 1169#ifdef SCTP_DEBUG 1170 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) { 1171 if (type == SCTP_DEL_IP_ADDRESS) { 1172 printf("asconf_queue_add: inserted asconf DEL_IP_ADDRESS: "); 1173 sctp_print_address(sa); 1174 } else { 1175 printf("asconf_queue_add: inserted asconf SET_PRIM_ADDR: "); 1176 sctp_print_address(sa); 1177 } 1178 } 1179#endif /* SCTP_DEBUG */ 1180 } 1181 1182 return (0); 1183} 1184 1185/* 1186 * add an asconf add/delete IP address parameter to the queue by addr. 1187 * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. 1188 * returns 0 if completed, non-zero if not completed. 1189 * NOTE: if adding, but delete already scheduled (and not yet sent out), 1190 * simply remove from queue. Same for deleting an address already scheduled 1191 * for add. If a duplicate operation is found, ignore the new one. 1192 */ 1193static uint32_t 1194sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, 1195 uint16_t type) 1196{ 1197 struct sctp_asconf_addr *aa, *aa_next; 1198 1199 /* see if peer supports ASCONF */ 1200 if (stcb->asoc.peer_supports_asconf == 0) { 1201 return (-1); 1202 } 1203 /* make sure the request isn't already in the queue */ 1204 for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL; 1205 aa = aa_next) { 1206 aa_next = TAILQ_NEXT(aa, next); 1207 /* address match? */ 1208 if (sctp_asconf_addr_match(aa, sa) == 0) 1209 continue; 1210 /* is the request already in queue (sent or not) */ 1211 if (aa->ap.aph.ph.param_type == type) { 1212 return (-1); 1213 } 1214 /* is the negative request already in queue, and not sent */ 1215 if (aa->sent == 1) 1216 continue; 1217 if (type == SCTP_ADD_IP_ADDRESS && 1218 aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) { 1219 /* add requested, delete already queued */ 1220 1221 /* delete the existing entry in the queue */ 1222 TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 1223 /* free the entry */ 1224 SCTP_FREE(aa); 1225 return (-1); 1226 } else if (type == SCTP_DEL_IP_ADDRESS && 1227 aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) { 1228 /* delete requested, add already queued */ 1229 1230 /* delete the existing entry in the queue */ 1231 TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 1232 /* take the entry off the appropriate list */ 1233 sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1); 1234 /* free the entry */ 1235 SCTP_FREE(aa); 1236 return (-1); 1237 } 1238 } /* for each aa */ 1239 1240 /* adding new request to the queue */ 1241 SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), "AsconfAddr"); 1242 if (aa == NULL) { 1243 /* didn't get memory */ 1244#ifdef SCTP_DEBUG 1245 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1246 printf("asconf_queue_add_sa: failed to get memory!\n"); 1247 } 1248#endif /* SCTP_DEBUG */ 1249 return (-1); 1250 } 1251 /* fill in asconf address parameter fields */ 1252 /* top level elements are "networked" during send */ 1253 aa->ap.aph.ph.param_type = type; 1254 aa->ifa = sctp_find_ifa_by_addr(sa); 1255 /* correlation_id filled in during send routine later... */ 1256 if (sa->sa_family == AF_INET6) { 1257 /* IPv6 address */ 1258 struct sockaddr_in6 *sin6; 1259 1260 sin6 = (struct sockaddr_in6 *)sa; 1261 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 1262 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); 1263 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param); 1264 memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, 1265 sizeof(struct in6_addr)); 1266 } else if (sa->sa_family == AF_INET) { 1267 /* IPv4 address */ 1268 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 1269 1270 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 1271 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); 1272 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param); 1273 memcpy(&aa->ap.addrp.addr, &sin->sin_addr, 1274 sizeof(struct in_addr)); 1275 } else { 1276 /* invalid family! */ 1277 SCTP_FREE(aa); 1278 return (-1); 1279 } 1280 aa->sent = 0; /* clear sent flag */ 1281 1282 /* 1283 * if we are deleting an address it should go out last otherwise, 1284 * add it to front of the pending queue 1285 */ 1286 if (type == SCTP_ADD_IP_ADDRESS) { 1287 /* add goes to the front of the queue */ 1288 TAILQ_INSERT_HEAD(&stcb->asoc.asconf_queue, aa, next); 1289 } else { 1290 /* delete and set primary goes to the back of the queue */ 1291 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 1292 } 1293 1294 return (0); 1295} 1296 1297/* 1298 * find a specific asconf param on our "sent" queue 1299 */ 1300static struct sctp_asconf_addr * 1301sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id) 1302{ 1303 struct sctp_asconf_addr *aa; 1304 1305 TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 1306 if (aa->ap.aph.correlation_id == correlation_id && 1307 aa->sent == 1) { 1308 /* found it */ 1309 return (aa); 1310 } 1311 } 1312 /* didn't find it */ 1313 return (NULL); 1314} 1315 1316/* 1317 * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do 1318 * notifications based on the error response 1319 */ 1320static void 1321sctp_asconf_process_error(struct sctp_tcb *stcb, 1322 struct sctp_asconf_paramhdr *aph) 1323{ 1324 struct sctp_error_cause *eh; 1325 struct sctp_paramhdr *ph; 1326 uint16_t param_type; 1327 uint16_t error_code; 1328 1329 eh = (struct sctp_error_cause *)(aph + 1); 1330 ph = (struct sctp_paramhdr *)(eh + 1); 1331 /* validate lengths */ 1332 if (htons(eh->length) + sizeof(struct sctp_error_cause) > 1333 htons(aph->ph.param_length)) { 1334 /* invalid error cause length */ 1335#ifdef SCTP_DEBUG 1336 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1337 printf("asconf_process_error: cause element too long\n"); 1338 } 1339#endif /* SCTP_DEBUG */ 1340 return; 1341 } 1342 if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) > 1343 htons(eh->length)) { 1344 /* invalid included TLV length */ 1345#ifdef SCTP_DEBUG 1346 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1347 printf("asconf_process_error: included TLV too long\n"); 1348 } 1349#endif /* SCTP_DEBUG */ 1350 return; 1351 } 1352 /* which error code ? */ 1353 error_code = ntohs(eh->code); 1354 param_type = ntohs(aph->ph.param_type); 1355 /* FIX: this should go back up the REMOTE_ERROR ULP notify */ 1356 switch (error_code) { 1357 case SCTP_CAUSE_RESOURCE_SHORTAGE: 1358 /* we allow ourselves to "try again" for this error */ 1359 break; 1360 default: 1361 /* peer can't handle it... */ 1362 switch (param_type) { 1363 case SCTP_ADD_IP_ADDRESS: 1364 case SCTP_DEL_IP_ADDRESS: 1365 stcb->asoc.peer_supports_asconf = 0; 1366 break; 1367 case SCTP_SET_PRIM_ADDR: 1368 stcb->asoc.peer_supports_asconf = 0; 1369 break; 1370 default: 1371 break; 1372 } 1373 } 1374} 1375 1376/* 1377 * process an asconf queue param aparam: parameter to process, will be 1378 * removed from the queue flag: 1=success, 0=failure 1379 */ 1380static void 1381sctp_asconf_process_param_ack(struct sctp_tcb *stcb, 1382 struct sctp_asconf_addr *aparam, uint32_t flag) 1383{ 1384 uint16_t param_type; 1385 1386 /* process this param */ 1387 param_type = aparam->ap.aph.ph.param_type; 1388 switch (param_type) { 1389 case SCTP_ADD_IP_ADDRESS: 1390#ifdef SCTP_DEBUG 1391 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1392 printf("process_param_ack: added IP address\n"); 1393 } 1394#endif /* SCTP_DEBUG */ 1395 sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, param_type, flag); 1396 break; 1397 case SCTP_DEL_IP_ADDRESS: 1398#ifdef SCTP_DEBUG 1399 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1400 printf("process_param_ack: deleted IP address\n"); 1401 } 1402#endif /* SCTP_DEBUG */ 1403 /* nothing really to do... lists already updated */ 1404 break; 1405 case SCTP_SET_PRIM_ADDR: 1406 /* nothing to do... peer may start using this addr */ 1407 if (flag == 0) 1408 stcb->asoc.peer_supports_asconf = 0; 1409 break; 1410 default: 1411 /* should NEVER happen */ 1412 break; 1413 } 1414 1415 /* remove the param and free it */ 1416 TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next); 1417 SCTP_FREE(aparam); 1418} 1419 1420/* 1421 * cleanup from a bad asconf ack parameter 1422 */ 1423static void 1424sctp_asconf_ack_clear(struct sctp_tcb *stcb) 1425{ 1426 /* assume peer doesn't really know how to do asconfs */ 1427 stcb->asoc.peer_supports_asconf = 0; 1428 /* XXX we could free the pending queue here */ 1429} 1430 1431void 1432sctp_handle_asconf_ack(struct mbuf *m, int offset, 1433 struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb, 1434 struct sctp_nets *net) 1435{ 1436 struct sctp_association *asoc; 1437 uint32_t serial_num; 1438 uint16_t ack_length; 1439 struct sctp_asconf_paramhdr *aph; 1440 struct sctp_asconf_addr *aa, *aa_next; 1441 uint32_t last_error_id = 0; /* last error correlation id */ 1442 uint32_t id; 1443 struct sctp_asconf_addr *ap; 1444 1445 /* asconf param buffer */ 1446 static uint8_t aparam_buf[DEFAULT_PARAM_BUFFER]; 1447 1448 /* verify minimum length */ 1449 if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) { 1450#ifdef SCTP_DEBUG 1451 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1452 printf("handle_asconf_ack: chunk too small = %xh\n", 1453 ntohs(cp->ch.chunk_length)); 1454 } 1455#endif /* SCTP_DEBUG */ 1456 return; 1457 } 1458 asoc = &stcb->asoc; 1459 serial_num = ntohl(cp->serial_number); 1460 1461 /* 1462 * NOTE: we may want to handle this differently- currently, we will 1463 * abort when we get an ack for the expected serial number + 1 (eg. 1464 * we didn't send it), process an ack normally if it is the expected 1465 * serial number, and re-send the previous ack for *ALL* other 1466 * serial numbers 1467 */ 1468 1469 /* 1470 * if the serial number is the next expected, but I didn't send it, 1471 * abort the asoc, since someone probably just hijacked us... 1472 */ 1473 if (serial_num == (asoc->asconf_seq_out + 1)) { 1474#ifdef SCTP_DEBUG 1475 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1476 printf("handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n"); 1477 } 1478#endif /* SCTP_DEBUG */ 1479 sctp_abort_an_association(stcb->sctp_ep, stcb, 1480 SCTP_CAUSE_ILLEGAL_ASCONF_ACK, NULL); 1481 return; 1482 } 1483 if (serial_num != asoc->asconf_seq_out) { 1484 /* got a duplicate/unexpected ASCONF-ACK */ 1485#ifdef SCTP_DEBUG 1486 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1487 printf("handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n", serial_num, asoc->asconf_seq_out); 1488 } 1489#endif /* SCTP_DEBUG */ 1490 return; 1491 } 1492 if (stcb->asoc.asconf_sent == 0) { 1493 /* got a unexpected ASCONF-ACK for serial not in flight */ 1494#ifdef SCTP_DEBUG 1495 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1496 printf("handle_asconf_ack: got serial number = %xh but not in flight\n", serial_num); 1497 } 1498#endif /* SCTP_DEBUG */ 1499 /* nothing to do... duplicate ACK received */ 1500 return; 1501 } 1502 /* stop our timer */ 1503 sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net); 1504 1505 /* process the ASCONF-ACK contents */ 1506 ack_length = ntohs(cp->ch.chunk_length) - 1507 sizeof(struct sctp_asconf_ack_chunk); 1508 offset += sizeof(struct sctp_asconf_ack_chunk); 1509 /* process through all parameters */ 1510 while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) { 1511 unsigned int param_length, param_type; 1512 1513 /* get pointer to next asconf parameter */ 1514 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, 1515 sizeof(struct sctp_asconf_paramhdr), aparam_buf); 1516 if (aph == NULL) { 1517 /* can't get an asconf paramhdr */ 1518 sctp_asconf_ack_clear(stcb); 1519 return; 1520 } 1521 param_type = ntohs(aph->ph.param_type); 1522 param_length = ntohs(aph->ph.param_length); 1523 if (param_length > ack_length) { 1524 sctp_asconf_ack_clear(stcb); 1525 return; 1526 } 1527 if (param_length < sizeof(struct sctp_paramhdr)) { 1528 sctp_asconf_ack_clear(stcb); 1529 return; 1530 } 1531 /* get the complete parameter... */ 1532 if (param_length > sizeof(aparam_buf)) { 1533#ifdef SCTP_DEBUG 1534 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1535 printf("param length (%u) larger than buffer size!\n", param_length); 1536 } 1537#endif /* SCTP_DEBUG */ 1538 sctp_asconf_ack_clear(stcb); 1539 return; 1540 } 1541 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf); 1542 if (aph == NULL) { 1543 sctp_asconf_ack_clear(stcb); 1544 return; 1545 } 1546 /* correlation_id is transparent to peer, no ntohl needed */ 1547 id = aph->correlation_id; 1548 1549 switch (param_type) { 1550 case SCTP_ERROR_CAUSE_IND: 1551 last_error_id = id; 1552 /* find the corresponding asconf param in our queue */ 1553 ap = sctp_asconf_find_param(stcb, id); 1554 if (ap == NULL) { 1555 /* hmm... can't find this in our queue! */ 1556 break; 1557 } 1558 /* process the parameter, failed flag */ 1559 sctp_asconf_process_param_ack(stcb, ap, 0); 1560 /* process the error response */ 1561 sctp_asconf_process_error(stcb, aph); 1562 break; 1563 case SCTP_SUCCESS_REPORT: 1564 /* find the corresponding asconf param in our queue */ 1565 ap = sctp_asconf_find_param(stcb, id); 1566 if (ap == NULL) { 1567 /* hmm... can't find this in our queue! */ 1568 break; 1569 } 1570 /* process the parameter, success flag */ 1571 sctp_asconf_process_param_ack(stcb, ap, 1); 1572 break; 1573 default: 1574 break; 1575 } /* switch */ 1576 1577 /* update remaining ASCONF-ACK message length to process */ 1578 ack_length -= SCTP_SIZE32(param_length); 1579 if (ack_length <= 0) { 1580 /* no more data in the mbuf chain */ 1581 break; 1582 } 1583 offset += SCTP_SIZE32(param_length); 1584 } /* while */ 1585 1586 /* 1587 * if there are any "sent" params still on the queue, these are 1588 * implicitly "success", or "failed" (if we got an error back) ... 1589 * so process these appropriately 1590 * 1591 * we assume that the correlation_id's are monotonically increasing 1592 * beginning from 1 and that we don't have *that* many outstanding 1593 * at any given time 1594 */ 1595 if (last_error_id == 0) 1596 last_error_id--;/* set to "max" value */ 1597 for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL; 1598 aa = aa_next) { 1599 aa_next = TAILQ_NEXT(aa, next); 1600 if (aa->sent == 1) { 1601 /* 1602 * implicitly successful or failed if correlation_id 1603 * < last_error_id, then success else, failure 1604 */ 1605 if (aa->ap.aph.correlation_id < last_error_id) 1606 sctp_asconf_process_param_ack(stcb, aa, 1607 SCTP_SUCCESS_REPORT); 1608 else 1609 sctp_asconf_process_param_ack(stcb, aa, 1610 SCTP_ERROR_CAUSE_IND); 1611 } else { 1612 /* 1613 * since we always process in order (FIFO queue) if 1614 * we reach one that hasn't been sent, the rest 1615 * should not have been sent either. so, we're 1616 * done... 1617 */ 1618 break; 1619 } 1620 } 1621 1622 /* update the next sequence number to use */ 1623 asoc->asconf_seq_out++; 1624 /* remove the old ASCONF on our outbound queue */ 1625 sctp_toss_old_asconf(stcb); 1626 /* clear the sent flag to allow new ASCONFs */ 1627 asoc->asconf_sent = 0; 1628 if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) { 1629 /* we have more params, so restart our timer */ 1630 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, 1631 stcb, net); 1632 } 1633} 1634 1635/* is this an interface that we care about at all? */ 1636static uint32_t 1637sctp_is_desired_interface_type(struct ifaddr *ifa) 1638{ 1639 int result; 1640 1641 /* check the interface type to see if it's one we care about */ 1642 switch (ifa->ifa_ifp->if_type) { 1643 case IFT_ETHER: 1644 case IFT_ISO88023: 1645 case IFT_ISO88025: 1646 case IFT_STARLAN: 1647 case IFT_P10: 1648 case IFT_P80: 1649 case IFT_HY: 1650 case IFT_FDDI: 1651 case IFT_PPP: 1652 case IFT_XETHER: 1653 case IFT_SLIP: 1654 case IFT_GIF: 1655 result = 1; 1656 break; 1657 default: 1658 result = 0; 1659 } 1660 1661 return (result); 1662} 1663 1664static uint32_t 1665sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa) 1666{ 1667 struct sockaddr_in6 *sin6, *net6; 1668 struct sctp_nets *net; 1669 1670 if (sa->sa_family != AF_INET6) { 1671 /* wrong family */ 1672 return (0); 1673 } 1674 sin6 = (struct sockaddr_in6 *)sa; 1675 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) { 1676 /* not link local address */ 1677 return (0); 1678 } 1679 /* hunt through our destination nets list for this scope_id */ 1680 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1681 if (((struct sockaddr *)(&net->ro._l_addr))->sa_family != 1682 AF_INET6) 1683 continue; 1684 net6 = (struct sockaddr_in6 *)&net->ro._l_addr; 1685 if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0) 1686 continue; 1687 if (sctp_is_same_scope(sin6, net6)) { 1688 /* found one */ 1689 return (1); 1690 } 1691 } 1692 /* didn't find one */ 1693 return (0); 1694} 1695 1696/* 1697 * address management functions 1698 */ 1699static void 1700sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1701 struct ifaddr *ifa, uint16_t type) 1702{ 1703 int status; 1704 1705 1706 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 && 1707 sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 1708 /* subset bound, no ASCONF allowed case, so ignore */ 1709 return; 1710 } 1711 /* 1712 * note: we know this is not the subset bound, no ASCONF case eg. 1713 * this is boundall or subset bound w/ASCONF allowed 1714 */ 1715 1716 /* first, make sure it's a good address family */ 1717 if (ifa->ifa_addr->sa_family != AF_INET6 && 1718 ifa->ifa_addr->sa_family != AF_INET) { 1719 return; 1720 } 1721 /* make sure we're "allowed" to add this type of addr */ 1722 if (ifa->ifa_addr->sa_family == AF_INET6) { 1723 struct in6_ifaddr *ifa6; 1724 1725 /* invalid if we're not a v6 endpoint */ 1726 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) 1727 return; 1728 /* is the v6 addr really valid ? */ 1729 ifa6 = (struct in6_ifaddr *)ifa; 1730 if (IFA6_IS_DEPRECATED(ifa6) || 1731 (ifa6->ia6_flags & 1732 (IN6_IFF_DETACHED | IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) { 1733 /* can't use an invalid address */ 1734 return; 1735 } 1736 } 1737 /* put this address on the "pending/do not use yet" list */ 1738 /* 1739 * Note: we do this primarily for the subset bind case We don't have 1740 * scoping flags at the EP level, so we must add link local/site 1741 * local addresses to the EP, then need to "negate" them here. 1742 * Recall that this routine is only called for the subset bound 1743 * w/ASCONF allowed case. 1744 */ 1745 1746 /* 1747 * do a scope_id check against any link local addresses in the 1748 * destination nets list to see if we should put this local address 1749 * on the pending list or not eg. don't put on the list if we have a 1750 * link local destination with the same scope_id 1751 */ 1752 if (type == SCTP_ADD_IP_ADDRESS) { 1753 if (sctp_is_scopeid_in_nets(stcb, ifa->ifa_addr) == 0) { 1754 sctp_add_local_addr_assoc(stcb, ifa); 1755 } 1756 } 1757 /* 1758 * check address scope if address is out of scope, don't queue 1759 * anything... note: this would leave the address on both inp and 1760 * asoc lists 1761 */ 1762 if (ifa->ifa_addr->sa_family == AF_INET6) { 1763 struct sockaddr_in6 *sin6; 1764 1765 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 1766 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1767 /* we skip unspecifed addresses */ 1768 return; 1769 } 1770 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1771 if (stcb->asoc.local_scope == 0) { 1772 return; 1773 } 1774 /* is it the right link local scope? */ 1775 if (sctp_is_scopeid_in_nets(stcb, ifa->ifa_addr) == 0) { 1776 return; 1777 } 1778 } 1779 if (stcb->asoc.site_scope == 0 && 1780 IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { 1781 return; 1782 } 1783 } else if (ifa->ifa_addr->sa_family == AF_INET) { 1784 struct sockaddr_in *sin; 1785 struct in6pcb *inp6; 1786 1787 inp6 = (struct in6pcb *)&inp->ip_inp.inp; 1788 /* invalid if we are a v6 only endpoint */ 1789 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1790 (inp6->inp_flags & IN6P_IPV6_V6ONLY) 1791 ) 1792 return; 1793 1794 sin = (struct sockaddr_in *)ifa->ifa_addr; 1795 if (sin->sin_addr.s_addr == 0) { 1796 /* we skip unspecifed addresses */ 1797 return; 1798 } 1799 if (stcb->asoc.ipv4_local_scope == 0 && 1800 IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 1801 return; 1802 } 1803 } else { 1804 /* else, not AF_INET or AF_INET6, so skip */ 1805#ifdef SCTP_DEBUG 1806 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1807 printf("addr_mgmt_assoc: not AF_INET or AF_INET6\n"); 1808 } 1809#endif /* SCTP_DEBUG */ 1810 return; 1811 } 1812 1813 /* queue an asconf for this address add/delete */ 1814 1815 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 1816 /* does the peer do asconf? */ 1817 if (stcb->asoc.peer_supports_asconf) { 1818 /* queue an asconf for this addr */ 1819 status = sctp_asconf_queue_add(stcb, ifa, type); 1820 /* 1821 * if queued ok, and in correct state, set the 1822 * ASCONF timer if in non-open state, we will set 1823 * this timer when the state does go open and do all 1824 * the asconf's 1825 */ 1826 if (status == 0 && 1827 SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { 1828 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, 1829 stcb, stcb->asoc.primary_destination); 1830 } 1831 } 1832 } else { 1833 /* this is the boundall, no ASCONF case */ 1834#if 0 1835 /* Peter: Fixe me? why the if 0? */ 1836 /* 1837 * assume kernel will delete this very shortly; add done 1838 * above 1839 */ 1840 if (type == SCTP_DEL_IP_ADDRESS) { 1841 /* if deleting, add this addr to the do not use list */ 1842 sctp_add_local_addr_assoc(stcb, ifa); 1843 } 1844#endif 1845 } 1846} 1847 1848static void 1849sctp_addr_mgmt_ep(struct sctp_inpcb *inp, struct ifaddr *ifa, uint16_t type) 1850{ 1851 struct sctp_tcb *stcb; 1852 int s; 1853 1854 1855 SCTP_INP_WLOCK(inp); 1856 /* make sure we're "allowed" to add this type of addr */ 1857 if (ifa->ifa_addr->sa_family == AF_INET6) { 1858 struct in6_ifaddr *ifa6; 1859 1860 /* invalid if we're not a v6 endpoint */ 1861 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 1862 SCTP_INP_WUNLOCK(inp); 1863 return; 1864 } 1865 /* is the v6 addr really valid ? */ 1866 ifa6 = (struct in6_ifaddr *)ifa; 1867 if (IFA6_IS_DEPRECATED(ifa6) || 1868 (ifa6->ia6_flags & 1869 (IN6_IFF_DETACHED | IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) { 1870 /* can't use an invalid address */ 1871 SCTP_INP_WUNLOCK(inp); 1872 return; 1873 } 1874 } else if (ifa->ifa_addr->sa_family == AF_INET) { 1875 /* invalid if we are a v6 only endpoint */ 1876 struct in6pcb *inp6; 1877 1878 inp6 = (struct in6pcb *)&inp->ip_inp.inp; 1879 1880 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1881 (inp6->inp_flags & IN6P_IPV6_V6ONLY) 1882 ) { 1883 SCTP_INP_WUNLOCK(inp); 1884 return; 1885 } 1886 } else { 1887 /* invalid address family */ 1888 SCTP_INP_WUNLOCK(inp); 1889 return; 1890 } 1891 /* is this endpoint subset bound ? */ 1892 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 1893 /* subset bound endpoint */ 1894 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 1895 /* 1896 * subset bound, but ASCONFs not allowed... if 1897 * adding, nothing to do, since not allowed if 1898 * deleting, remove address from endpoint peer will 1899 * have to "timeout" this addr 1900 */ 1901 if (type == SCTP_DEL_IP_ADDRESS) { 1902 sctp_del_local_addr_ep(inp, ifa); 1903 } 1904 /* no asconfs to queue for this inp... */ 1905 SCTP_INP_WUNLOCK(inp); 1906 return; 1907 } else { 1908 /* 1909 * subset bound, ASCONFs allowed... if adding, add 1910 * address to endpoint list if deleting, remove 1911 * address from endpoint 1912 */ 1913 if (type == SCTP_ADD_IP_ADDRESS) { 1914 sctp_add_local_addr_ep(inp, ifa); 1915 } else { 1916 sctp_del_local_addr_ep(inp, ifa); 1917 } 1918 /* drop through and notify all asocs */ 1919 } 1920 } 1921 s = splnet(); 1922 /* process for all associations for this endpoint */ 1923 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 1924 SCTP_TCB_LOCK(stcb); 1925 sctp_addr_mgmt_assoc(inp, stcb, ifa, type); 1926 SCTP_TCB_UNLOCK(stcb); 1927 } 1928 splx(s); 1929 SCTP_INP_WUNLOCK(inp); 1930} 1931 1932/* 1933 * restrict the use of this address 1934 */ 1935static void 1936sctp_addr_mgmt_restrict_ep(struct sctp_inpcb *inp, struct ifaddr *ifa) 1937{ 1938 struct sctp_tcb *stcb; 1939 int s; 1940 1941 /* is this endpoint bound to all? */ 1942 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 1943 /* 1944 * Nothing to do for subset bound case. Allow sctp_bindx() 1945 * to manage the address lists 1946 */ 1947 return; 1948 } 1949 s = splnet(); 1950 SCTP_INP_RLOCK(inp); 1951 /* process for all associations for this endpoint */ 1952 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 1953 /* put this address on the "pending/do not use yet" list */ 1954 SCTP_TCB_LOCK(stcb); 1955 sctp_add_local_addr_assoc(stcb, ifa); 1956 SCTP_TCB_UNLOCK(stcb); 1957 } 1958 splx(s); 1959 SCTP_INP_RUNLOCK(inp); 1960} 1961 1962/* 1963 * this is only called for kernel initiated address changes eg. it will check 1964 * the PCB_FLAGS_AUTO_ASCONF flag 1965 */ 1966static void 1967sctp_addr_mgmt(struct ifaddr *ifa, uint16_t type) 1968{ 1969 struct sockaddr *sa; 1970 struct sctp_inpcb *inp; 1971 1972 /* make sure we care about this interface... */ 1973 if (!sctp_is_desired_interface_type(ifa)) { 1974 return; 1975 } 1976 sa = ifa->ifa_addr; 1977 if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6) 1978 return; 1979 1980#ifdef SCTP_DEBUG 1981 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 1982 if (type == SCTP_ADD_IP_ADDRESS) 1983 printf("sctp_addr_mgmt: kernel adds "); 1984 else 1985 printf("sctp_addr_mgmt: kernel deletes "); 1986 sctp_print_address(sa); 1987 } 1988#endif /* SCTP_DEBUG */ 1989 1990 /* go through all our PCB's */ 1991 LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) { 1992 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF)) { 1993 sctp_addr_mgmt_ep(inp, ifa, type); 1994 } else { 1995 /* this address is going away anyways... */ 1996 if (type == SCTP_DEL_IP_ADDRESS) 1997 return; 1998 /* (temporarily) restrict this address */ 1999 sctp_addr_mgmt_restrict_ep(inp, ifa); 2000 } 2001 /* else, not allowing automatic asconf's, so ignore */ 2002 } 2003} 2004 2005/* 2006 * add/delete IP address requests from kernel (via routing change) assumed 2007 * that the address is non-broadcast, non-multicast all addresses are passed 2008 * from any type of interface-- need to filter duplicate addresses may get 2009 * requested 2010 */ 2011 2012void 2013sctp_add_ip_address(struct ifaddr *ifa) 2014{ 2015 sctp_addr_mgmt(ifa, SCTP_ADD_IP_ADDRESS); 2016} 2017 2018void 2019sctp_delete_ip_address(struct ifaddr *ifa) 2020{ 2021 struct sctp_inpcb *inp; 2022 2023 /* process the delete */ 2024 sctp_addr_mgmt(ifa, SCTP_DEL_IP_ADDRESS); 2025 2026 /* 2027 * need to remove this ifaddr from any cached routes and also any 2028 * from any assoc "restricted/pending" lists 2029 */ 2030 /* make sure we care about this interface... */ 2031 if (!sctp_is_desired_interface_type(ifa)) { 2032 return; 2033 } 2034 /* go through all our PCB's */ 2035 SCTP_INP_INFO_RLOCK(); 2036 LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) { 2037 struct sctp_tcb *stcb; 2038 struct sctp_laddr *laddr, *laddr_next; 2039 2040 /* process for all associations for this endpoint */ 2041 SCTP_INP_RLOCK(inp); 2042 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 2043 struct sctp_nets *net; 2044 2045 /* process through the nets list */ 2046 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 2047 struct rtentry *rt; 2048 2049 /* delete this address if cached */ 2050 rt = net->ro.ro_rt; 2051 if (rt != NULL && rt->rt_ifa == ifa) { 2052 /* RTFREE(rt); */ 2053 net->ro.ro_rt = NULL; 2054 } 2055 } /* for each net */ 2056 /* process through the asoc "pending" list */ 2057 laddr = LIST_FIRST(&stcb->asoc.sctp_local_addr_list); 2058 while (laddr != NULL) { 2059 laddr_next = LIST_NEXT(laddr, sctp_nxt_addr); 2060 /* remove if in use */ 2061 if (laddr->ifa == ifa) { 2062 sctp_remove_laddr(laddr); 2063 } 2064 laddr = laddr_next; 2065 } /* while */ 2066 } /* for each stcb */ 2067 /* process through the inp bound addr list */ 2068 laddr = LIST_FIRST(&inp->sctp_addr_list); 2069 while (laddr != NULL) { 2070 laddr_next = LIST_NEXT(laddr, sctp_nxt_addr); 2071 /* remove if in use */ 2072 if (laddr->ifa == ifa) { 2073 sctp_remove_laddr(laddr); 2074 } 2075 laddr = laddr_next; 2076 } 2077 SCTP_INP_RUNLOCK(inp); 2078 } 2079 SCTP_INP_INFO_RUNLOCK(); 2080} 2081 2082/* 2083 * sa is the sockaddr to ask the peer to set primary to returns: 0 = 2084 * completed, -1 = error 2085 */ 2086int32_t 2087sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa) 2088{ 2089 /* NOTE: we currently don't check the validity of the address! */ 2090 2091 /* queue an ASCONF:SET_PRIM_ADDR to be sent */ 2092 if (!sctp_asconf_queue_add_sa(stcb, sa, SCTP_SET_PRIM_ADDR)) { 2093 /* set primary queuing succeeded */ 2094 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { 2095 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2096 stcb->sctp_ep, stcb, 2097 stcb->asoc.primary_destination); 2098 } 2099#ifdef SCTP_DEBUG 2100 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 2101 printf("set_primary_ip_address_sa: queued on tcb=%p, ", 2102 stcb); 2103 sctp_print_address(sa); 2104 } 2105#endif /* SCTP_DEBUG */ 2106 } else { 2107#ifdef SCTP_DEBUG 2108 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 2109 printf("set_primary_ip_address_sa: failed to add to queue on tcb=%p, ", 2110 stcb); 2111 sctp_print_address(sa); 2112 } 2113#endif /* SCTP_DEBUG */ 2114 return (-1); 2115 } 2116 return (0); 2117} 2118 2119void 2120sctp_set_primary_ip_address(struct ifaddr *ifa) 2121{ 2122 struct sctp_inpcb *inp; 2123 2124 /* make sure we care about this interface... */ 2125 if (!sctp_is_desired_interface_type(ifa)) { 2126 return; 2127 } 2128 /* go through all our PCB's */ 2129 LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) { 2130 struct sctp_tcb *stcb; 2131 2132 /* process for all associations for this endpoint */ 2133 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 2134 /* queue an ASCONF:SET_PRIM_ADDR to be sent */ 2135 if (!sctp_asconf_queue_add(stcb, ifa, 2136 SCTP_SET_PRIM_ADDR)) { 2137 /* set primary queuing succeeded */ 2138 if (SCTP_GET_STATE(&stcb->asoc) == 2139 SCTP_STATE_OPEN) { 2140 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2141 stcb->sctp_ep, stcb, 2142 stcb->asoc.primary_destination); 2143 } 2144#ifdef SCTP_DEBUG 2145 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 2146 printf("set_primary_ip_address: queued on stcb=%p, ", 2147 stcb); 2148 sctp_print_address(ifa->ifa_addr); 2149 } 2150#endif /* SCTP_DEBUG */ 2151 } 2152 } /* for each stcb */ 2153 } /* for each inp */ 2154} 2155 2156static struct sockaddr * 2157sctp_find_valid_localaddr(struct sctp_tcb *stcb) 2158{ 2159 struct ifnet *ifn; 2160 struct ifaddr *ifa; 2161 2162 2163 TAILQ_FOREACH(ifn, &ifnet, if_list) { 2164 if (stcb->asoc.loopback_scope == 0 && ifn->if_type == IFT_LOOP) { 2165 /* Skip if loopback_scope not set */ 2166 continue; 2167 } 2168 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { 2169 if (ifa->ifa_addr->sa_family == AF_INET && 2170 stcb->asoc.ipv4_addr_legal) { 2171 struct sockaddr_in *sin; 2172 2173 sin = (struct sockaddr_in *)ifa->ifa_addr; 2174 if (sin->sin_addr.s_addr == 0) { 2175 /* skip unspecifed addresses */ 2176 continue; 2177 } 2178 if (stcb->asoc.ipv4_local_scope == 0 && 2179 IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) 2180 continue; 2181 2182 if (sctp_is_addr_restricted(stcb, 2183 ifa->ifa_addr)) 2184 continue; 2185 /* found a valid local v4 address to use */ 2186 return (ifa->ifa_addr); 2187 } else if (ifa->ifa_addr->sa_family == AF_INET6 && 2188 stcb->asoc.ipv6_addr_legal) { 2189 struct sockaddr_in6 *sin6; 2190 struct in6_ifaddr *ifa6; 2191 2192 ifa6 = (struct in6_ifaddr *)ifa; 2193 if (IFA6_IS_DEPRECATED(ifa6) || 2194 (ifa6->ia6_flags & (IN6_IFF_DETACHED | 2195 IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) 2196 continue; 2197 2198 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 2199 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2200 /* we skip unspecifed addresses */ 2201 continue; 2202 } 2203 if (stcb->asoc.local_scope == 0 && 2204 IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 2205 continue; 2206 if (stcb->asoc.site_scope == 0 && 2207 IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) 2208 continue; 2209 2210 /* found a valid local v6 address to use */ 2211 return (ifa->ifa_addr); 2212 } 2213 } 2214 } 2215 /* no valid addresses found */ 2216 return (NULL); 2217} 2218 2219static struct sockaddr * 2220sctp_find_valid_localaddr_ep(struct sctp_tcb *stcb) 2221{ 2222 struct sctp_laddr *laddr; 2223 2224 LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 2225 if (laddr->ifa == NULL) { 2226 continue; 2227 } 2228 if (laddr->ifa->ifa_addr == NULL) { 2229 continue; 2230 } 2231 /* is the address restricted ? */ 2232 if (sctp_is_addr_restricted(stcb, laddr->ifa->ifa_addr)) 2233 continue; 2234 2235 /* found a valid local address to use */ 2236 return (laddr->ifa->ifa_addr); 2237 } 2238 /* no valid addresses found */ 2239 return (NULL); 2240} 2241 2242/* 2243 * builds an ASCONF chunk from queued ASCONF params returns NULL on error (no 2244 * mbuf, no ASCONF params queued, etc) 2245 */ 2246struct mbuf * 2247sctp_compose_asconf(struct sctp_tcb *stcb) 2248{ 2249 struct mbuf *m_asconf, *m_asconf_chk; 2250 struct sctp_asconf_addr *aa; 2251 struct sctp_asconf_chunk *acp; 2252 struct sctp_asconf_paramhdr *aph; 2253 struct sctp_asconf_addr_param *aap; 2254 uint32_t p_length; 2255 uint32_t correlation_id = 1; /* 0 is reserved... */ 2256 caddr_t ptr, lookup_ptr; 2257 uint8_t lookup_used = 0; 2258 2259 /* are there any asconf params to send? */ 2260 if (TAILQ_EMPTY(&stcb->asoc.asconf_queue)) { 2261 return (NULL); 2262 } 2263 /* 2264 * get a chunk header mbuf and a cluster for the asconf params since 2265 * it's simpler to fill in the asconf chunk header lookup address on 2266 * the fly 2267 */ 2268 m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 1, M_DONTWAIT, 1, MT_DATA); 2269 if (m_asconf_chk == NULL) { 2270 /* no mbuf's */ 2271#ifdef SCTP_DEBUG 2272 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) 2273 printf("compose_asconf: couldn't get chunk mbuf!\n"); 2274#endif /* SCTP_DEBUG */ 2275 return (NULL); 2276 } 2277 m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_DATA); 2278 if (m_asconf == NULL) { 2279 /* no mbuf's */ 2280#ifdef SCTP_DEBUG 2281 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) 2282 printf("compose_asconf: couldn't get mbuf!\n"); 2283#endif /* SCTP_DEBUG */ 2284 sctp_m_freem(m_asconf_chk); 2285 return (NULL); 2286 } 2287 m_asconf_chk->m_len = sizeof(struct sctp_asconf_chunk); 2288 m_asconf->m_len = 0; 2289 acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *); 2290 bzero(acp, sizeof(struct sctp_asconf_chunk)); 2291 /* save pointers to lookup address and asconf params */ 2292 lookup_ptr = (caddr_t)(acp + 1); /* after the header */ 2293 ptr = mtod(m_asconf, caddr_t); /* beginning of cluster */ 2294 2295 /* fill in chunk header info */ 2296 acp->ch.chunk_type = SCTP_ASCONF; 2297 acp->ch.chunk_flags = 0; 2298 acp->serial_number = htonl(stcb->asoc.asconf_seq_out); 2299 2300 /* add parameters... up to smallest MTU allowed */ 2301 TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 2302 /* get the parameter length */ 2303 p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length); 2304 /* will it fit in current chunk? */ 2305 if (m_asconf->m_len + p_length > stcb->asoc.smallest_mtu) { 2306 /* won't fit, so we're done with this chunk */ 2307 break; 2308 } 2309 /* assign (and store) a correlation id */ 2310 aa->ap.aph.correlation_id = correlation_id++; 2311 2312 /* 2313 * fill in address if we're doing a delete this is a simple 2314 * way for us to fill in the correlation address, which 2315 * should only be used by the peer if we're deleting our 2316 * source address and adding a new address (e.g. renumbering 2317 * case) 2318 */ 2319 if (lookup_used == 0 && 2320 aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) { 2321 struct sctp_ipv6addr_param *lookup; 2322 uint16_t p_size, addr_size; 2323 2324 lookup = (struct sctp_ipv6addr_param *)lookup_ptr; 2325 lookup->ph.param_type = 2326 htons(aa->ap.addrp.ph.param_type); 2327 if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) { 2328 /* copy IPv6 address */ 2329 p_size = sizeof(struct sctp_ipv6addr_param); 2330 addr_size = sizeof(struct in6_addr); 2331 } else { 2332 /* copy IPv4 address */ 2333 p_size = sizeof(struct sctp_ipv4addr_param); 2334 addr_size = sizeof(struct in_addr); 2335 } 2336 lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); 2337 memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size); 2338 m_asconf_chk->m_len += SCTP_SIZE32(p_size); 2339 lookup_used = 1; 2340 } 2341 /* copy into current space */ 2342 memcpy(ptr, &aa->ap, p_length); 2343 2344 /* network elements and update lengths */ 2345 aph = (struct sctp_asconf_paramhdr *)ptr; 2346 aap = (struct sctp_asconf_addr_param *)ptr; 2347 /* correlation_id is transparent to peer, no htonl needed */ 2348 aph->ph.param_type = htons(aph->ph.param_type); 2349 aph->ph.param_length = htons(aph->ph.param_length); 2350 aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type); 2351 aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length); 2352 2353 m_asconf->m_len += SCTP_SIZE32(p_length); 2354 ptr += SCTP_SIZE32(p_length); 2355 2356 /* 2357 * these params are removed off the pending list upon 2358 * getting an ASCONF-ACK back from the peer, just set flag 2359 */ 2360 aa->sent = 1; 2361 } 2362 /* check to see if the lookup addr has been populated yet */ 2363 if (lookup_used == 0) { 2364 /* NOTE: if the address param is optional, can skip this... */ 2365 /* add any valid (existing) address... */ 2366 struct sctp_ipv6addr_param *lookup; 2367 uint16_t p_size, addr_size; 2368 struct sockaddr *found_addr; 2369 caddr_t addr_ptr; 2370 2371 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) 2372 found_addr = sctp_find_valid_localaddr(stcb); 2373 else 2374 found_addr = sctp_find_valid_localaddr_ep(stcb); 2375 2376 lookup = (struct sctp_ipv6addr_param *)lookup_ptr; 2377 if (found_addr != NULL) { 2378 if (found_addr->sa_family == AF_INET6) { 2379 /* copy IPv6 address */ 2380 lookup->ph.param_type = 2381 htons(SCTP_IPV6_ADDRESS); 2382 p_size = sizeof(struct sctp_ipv6addr_param); 2383 addr_size = sizeof(struct in6_addr); 2384 addr_ptr = (caddr_t)&((struct sockaddr_in6 *) 2385 found_addr)->sin6_addr; 2386 } else { 2387 /* copy IPv4 address */ 2388 lookup->ph.param_type = 2389 htons(SCTP_IPV4_ADDRESS); 2390 p_size = sizeof(struct sctp_ipv4addr_param); 2391 addr_size = sizeof(struct in_addr); 2392 addr_ptr = (caddr_t)&((struct sockaddr_in *) 2393 found_addr)->sin_addr; 2394 } 2395 lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); 2396 memcpy(lookup->addr, addr_ptr, addr_size); 2397 m_asconf_chk->m_len += SCTP_SIZE32(p_size); 2398 lookup_used = 1; 2399 } else { 2400 /* uh oh... don't have any address?? */ 2401#ifdef SCTP_DEBUG 2402 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) 2403 printf("compose_asconf: no lookup addr!\n"); 2404#endif /* SCTP_DEBUG */ 2405 /* for now, we send a IPv4 address of 0.0.0.0 */ 2406 lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS); 2407 lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param))); 2408 bzero(lookup->addr, sizeof(struct in_addr)); 2409 m_asconf_chk->m_len += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)); 2410 lookup_used = 1; 2411 } 2412 } 2413 /* chain it all together */ 2414 m_asconf_chk->m_next = m_asconf; 2415 m_asconf_chk->m_pkthdr.len = m_asconf_chk->m_len + m_asconf->m_len; 2416 acp->ch.chunk_length = ntohs(m_asconf_chk->m_pkthdr.len); 2417 2418 /* update "sent" flag */ 2419 stcb->asoc.asconf_sent++; 2420 2421 return (m_asconf_chk); 2422} 2423 2424/* 2425 * section to handle address changes before an association is up eg. changes 2426 * during INIT/INIT-ACK/COOKIE-ECHO handshake 2427 */ 2428 2429/* 2430 * processes the (local) addresses in the INIT-ACK chunk 2431 */ 2432static void 2433sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, 2434 unsigned int offset, unsigned int length) 2435{ 2436 struct sctp_paramhdr tmp_param, *ph; 2437 uint16_t plen, ptype; 2438 struct sctp_ipv6addr_param addr_store; 2439 struct sockaddr_in6 sin6; 2440 struct sockaddr_in sin; 2441 struct sockaddr *sa; 2442 struct ifaddr *ifa; 2443 2444#ifdef SCTP_DEBUG 2445 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) { 2446 printf("processing init-ack addresses\n"); 2447 } 2448#endif /* SCTP_DEBUG */ 2449 2450 /* convert to upper bound */ 2451 length += offset; 2452 2453 if ((offset + sizeof(struct sctp_paramhdr)) > length) { 2454 return; 2455 } 2456 /* init the addresses */ 2457 bzero(&sin6, sizeof(sin6)); 2458 sin6.sin6_family = AF_INET6; 2459 sin6.sin6_len = sizeof(sin6); 2460 sin6.sin6_port = stcb->rport; 2461 2462 bzero(&sin, sizeof(sin)); 2463 sin.sin_len = sizeof(sin); 2464 sin.sin_family = AF_INET; 2465 sin.sin_port = stcb->rport; 2466 2467 /* go through the addresses in the init-ack */ 2468 ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, 2469 sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); 2470 while (ph != NULL) { 2471 ptype = ntohs(ph->param_type); 2472 plen = ntohs(ph->param_length); 2473 if (ptype == SCTP_IPV6_ADDRESS) { 2474 struct sctp_ipv6addr_param *a6p; 2475 2476 /* get the entire IPv6 address param */ 2477 a6p = (struct sctp_ipv6addr_param *) 2478 sctp_m_getptr(m, offset, 2479 sizeof(struct sctp_ipv6addr_param), 2480 (uint8_t *) & addr_store); 2481 if (plen != sizeof(struct sctp_ipv6addr_param) || 2482 a6p == NULL) { 2483 return; 2484 } 2485 memcpy(&sin6.sin6_addr, a6p->addr, 2486 sizeof(struct in6_addr)); 2487 sa = (struct sockaddr *)&sin6; 2488 } else if (ptype == SCTP_IPV4_ADDRESS) { 2489 struct sctp_ipv4addr_param *a4p; 2490 2491 /* get the entire IPv4 address param */ 2492 a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_ipv4addr_param), (uint8_t *) & addr_store); 2493 if (plen != sizeof(struct sctp_ipv4addr_param) || 2494 a4p == NULL) { 2495 return; 2496 } 2497 sin.sin_addr.s_addr = a4p->addr; 2498 sa = (struct sockaddr *)&sin; 2499 } else { 2500 goto next_addr; 2501 } 2502 2503 /* see if this address really (still) exists */ 2504 ifa = sctp_find_ifa_by_addr(sa); 2505 if (ifa == NULL) { 2506 /* address doesn't exist anymore */ 2507 int status; 2508 2509 /* are ASCONFs allowed ? */ 2510 if ((sctp_is_feature_on(stcb->sctp_ep, 2511 SCTP_PCB_FLAGS_DO_ASCONF)) && 2512 stcb->asoc.peer_supports_asconf) { 2513 /* queue an ASCONF DEL_IP_ADDRESS */ 2514 status = sctp_asconf_queue_add_sa(stcb, sa, 2515 SCTP_DEL_IP_ADDRESS); 2516 /* 2517 * if queued ok, and in correct state, set 2518 * the ASCONF timer 2519 */ 2520 if (status == 0 && 2521 SCTP_GET_STATE(&stcb->asoc) == 2522 SCTP_STATE_OPEN) { 2523 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2524 stcb->sctp_ep, stcb, 2525 stcb->asoc.primary_destination); 2526 } 2527 } 2528 } else { 2529 /* address still exists */ 2530 /* 2531 * if subset bound, ep addr's managed by default if 2532 * not doing ASCONF, add the address to the assoc 2533 */ 2534 if ((stcb->sctp_ep->sctp_flags & 2535 SCTP_PCB_FLAGS_BOUNDALL) == 0 && 2536 (sctp_is_feature_off(stcb->sctp_ep, 2537 SCTP_PCB_FLAGS_DO_ASCONF))) { 2538#ifdef SCTP_DEBUG 2539 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) { 2540 printf("process_initack_addrs: adding local addr to asoc\n"); 2541 } 2542#endif /* SCTP_DEBUG */ 2543 sctp_add_local_addr_assoc(stcb, ifa); 2544 } 2545 } 2546 2547next_addr: 2548 /* 2549 * Sanity check: Make sure the length isn't 0, otherwise 2550 * we'll be stuck in this loop for a long time... 2551 */ 2552 if (SCTP_SIZE32(plen) == 0) { 2553#ifdef SCTP_DEBUG 2554 printf("process_initack_addrs: bad len (%d) type=%xh\n", 2555 plen, ptype); 2556#endif 2557 return; 2558 } 2559 /* get next parameter */ 2560 offset += SCTP_SIZE32(plen); 2561 if ((offset + sizeof(struct sctp_paramhdr)) > length) 2562 return; 2563 ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, 2564 sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); 2565 } /* while */ 2566} 2567 2568/* FIX ME: need to verify return result for v6 address type if v6 disabled */ 2569/* 2570 * checks to see if a specific address is in the initack address list returns 2571 * 1 if found, 0 if not 2572 */ 2573static uint32_t 2574sctp_addr_in_initack(struct sctp_tcb *stcb, struct mbuf *m, uint32_t offset, 2575 uint32_t length, struct sockaddr *sa) 2576{ 2577 struct sctp_paramhdr tmp_param, *ph; 2578 uint16_t plen, ptype; 2579 struct sctp_ipv6addr_param addr_store; 2580 struct sockaddr_in *sin; 2581 struct sctp_ipv4addr_param *a4p; 2582 2583#ifdef INET6 2584 struct sockaddr_in6 *sin6, sin6_tmp; 2585 struct sctp_ipv6addr_param *a6p; 2586 2587#endif /* INET6 */ 2588 2589 if ( 2590#ifdef INET6 2591 (sa->sa_family != AF_INET6) && 2592#endif /* INET6 */ 2593 (sa->sa_family != AF_INET)) 2594 return (0); 2595 2596#ifdef SCTP_DEBUG 2597 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) { 2598 printf("find_initack_addr: starting search for "); 2599 sctp_print_address(sa); 2600 } 2601#endif /* SCTP_DEBUG */ 2602 /* convert to upper bound */ 2603 length += offset; 2604 2605 if ((offset + sizeof(struct sctp_paramhdr)) > length) { 2606#ifdef SCTP_DEBUG 2607 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 2608 printf("find_initack_addr: invalid offset?\n"); 2609 } 2610#endif /* SCTP_DEBUG */ 2611 return (0); 2612 } 2613 /* go through the addresses in the init-ack */ 2614 ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, 2615 sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); 2616 while (ph != NULL) { 2617 ptype = ntohs(ph->param_type); 2618 plen = ntohs(ph->param_length); 2619#ifdef INET6 2620 if (ptype == SCTP_IPV6_ADDRESS && sa->sa_family == AF_INET6) { 2621 /* get the entire IPv6 address param */ 2622 a6p = (struct sctp_ipv6addr_param *) 2623 sctp_m_getptr(m, offset, 2624 sizeof(struct sctp_ipv6addr_param), 2625 (uint8_t *) & addr_store); 2626 if (plen != sizeof(struct sctp_ipv6addr_param) || 2627 ph == NULL) { 2628 return (0); 2629 } 2630 sin6 = (struct sockaddr_in6 *)sa; 2631 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { 2632 /* create a copy and clear scope */ 2633 memcpy(&sin6_tmp, sin6, 2634 sizeof(struct sockaddr_in6)); 2635 sin6 = &sin6_tmp; 2636 in6_clearscope(&sin6->sin6_addr); 2637 } 2638 if (memcmp(&sin6->sin6_addr, a6p->addr, 2639 sizeof(struct in6_addr)) == 0) { 2640 /* found it */ 2641 return (1); 2642 } 2643 } else 2644#endif /* INET6 */ 2645 2646 if (ptype == SCTP_IPV4_ADDRESS && 2647 sa->sa_family == AF_INET) { 2648 /* get the entire IPv4 address param */ 2649 a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, 2650 offset, sizeof(struct sctp_ipv4addr_param), 2651 (uint8_t *) & addr_store); 2652 if (plen != sizeof(struct sctp_ipv4addr_param) || 2653 ph == NULL) { 2654 return (0); 2655 } 2656 sin = (struct sockaddr_in *)sa; 2657 if (sin->sin_addr.s_addr == a4p->addr) { 2658 /* found it */ 2659 return (1); 2660 } 2661 } 2662 /* get next parameter */ 2663 offset += SCTP_SIZE32(plen); 2664 if (offset + sizeof(struct sctp_paramhdr) > length) 2665 return (0); 2666 ph = (struct sctp_paramhdr *) 2667 sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), 2668 (uint8_t *) & tmp_param); 2669 } /* while */ 2670 /* not found! */ 2671 return (0); 2672} 2673 2674/* 2675 * makes sure that the current endpoint local addr list is consistent with 2676 * the new association (eg. subset bound, asconf allowed) adds addresses as 2677 * necessary 2678 */ 2679static void 2680sctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset, 2681 int length, struct sockaddr *init_addr) 2682{ 2683 struct sctp_laddr *laddr; 2684 2685 /* go through the endpoint list */ 2686 LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 2687 /* be paranoid and validate the laddr */ 2688 if (laddr->ifa == NULL) { 2689#ifdef SCTP_DEBUG 2690 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 2691 printf("check_addr_list_ep: laddr->ifa is NULL"); 2692 } 2693#endif /* SCTP_DEBUG */ 2694 continue; 2695 } 2696 if (laddr->ifa->ifa_addr == NULL) { 2697#ifdef SCTP_DEBUG 2698 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) { 2699 printf("check_addr_list_ep: laddr->ifa->ifa_addr is NULL"); 2700 } 2701#endif /* SCTP_DEBUG */ 2702 continue; 2703 } 2704 /* do i have it implicitly? */ 2705 if (sctp_cmpaddr(laddr->ifa->ifa_addr, init_addr)) { 2706 continue; 2707 } 2708 /* check to see if in the init-ack */ 2709 if (!sctp_addr_in_initack(stcb, m, offset, length, 2710 laddr->ifa->ifa_addr)) { 2711 /* try to add it */ 2712 sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa, 2713 SCTP_ADD_IP_ADDRESS); 2714 } 2715 } 2716} 2717 2718/* 2719 * makes sure that the current kernel address list is consistent with the new 2720 * association (with all addrs bound) adds addresses as necessary 2721 */ 2722static void 2723sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset, 2724 int length, struct sockaddr *init_addr, 2725 uint16_t local_scope, uint16_t site_scope, 2726 uint16_t ipv4_scope, uint16_t loopback_scope) 2727{ 2728 struct ifnet *ifn; 2729 struct ifaddr *ifa; 2730 2731 /* go through all our known interfaces */ 2732 TAILQ_FOREACH(ifn, &ifnet, if_list) { 2733 if (loopback_scope == 0 && ifn->if_type == IFT_LOOP) { 2734 /* skip loopback interface */ 2735 continue; 2736 } 2737 /* go through each interface address */ 2738 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { 2739 /* do i have it implicitly? */ 2740 if (sctp_cmpaddr(ifa->ifa_addr, init_addr)) { 2741 continue; 2742 } 2743 /* check to see if in the init-ack */ 2744 if (!sctp_addr_in_initack(stcb, m, offset, length, 2745 ifa->ifa_addr)) { 2746 /* try to add it */ 2747 sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, 2748 ifa, SCTP_ADD_IP_ADDRESS); 2749 } 2750 } /* end foreach ifa */ 2751 } /* end foreach ifn */ 2752} 2753 2754/* 2755 * validates an init-ack chunk (from a cookie-echo) with current addresses 2756 * adds addresses from the init-ack into our local address list, if needed 2757 * queues asconf adds/deletes addresses as needed and makes appropriate list 2758 * changes for source address selection m, offset: points to the start of the 2759 * address list in an init-ack chunk length: total length of the address 2760 * params only init_addr: address where my INIT-ACK was sent from 2761 */ 2762void 2763sctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset, 2764 int length, struct sockaddr *init_addr, 2765 uint16_t local_scope, uint16_t site_scope, 2766 uint16_t ipv4_scope, uint16_t loopback_scope) 2767{ 2768 /* process the local addresses in the initack */ 2769 sctp_process_initack_addresses(stcb, m, offset, length); 2770 2771 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 2772 /* bound all case */ 2773 sctp_check_address_list_all(stcb, m, offset, length, init_addr, 2774 local_scope, site_scope, ipv4_scope, loopback_scope); 2775 } else { 2776 /* subset bound case */ 2777 if (sctp_is_feature_on(stcb->sctp_ep, 2778 SCTP_PCB_FLAGS_DO_ASCONF)) { 2779 /* asconf's allowed */ 2780 sctp_check_address_list_ep(stcb, m, offset, length, 2781 init_addr); 2782 } 2783 /* else, no asconfs allowed, so what we sent is what we get */ 2784 } 2785} 2786 2787/* 2788 * sctp_bindx() support 2789 */ 2790uint32_t 2791sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, uint16_t type) 2792{ 2793 struct ifaddr *ifa; 2794 2795 2796 if (sa->sa_len == 0) 2797 return (EINVAL); 2798 2799 ifa = sctp_find_ifa_by_addr(sa); 2800 if (ifa != NULL) { 2801#ifdef INET6 2802 if (ifa->ifa_addr->sa_family == AF_INET6) { 2803 struct in6_ifaddr *ifa6; 2804 2805 ifa6 = (struct in6_ifaddr *)ifa; 2806 if (IFA6_IS_DEPRECATED(ifa6) || 2807 (ifa6->ia6_flags & (IN6_IFF_DETACHED | 2808 IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) { 2809 /* Can't bind a non-existent addr. */ 2810 return (EINVAL); 2811 } 2812 } 2813#endif /* INET6 */ 2814 /* add this address */ 2815 sctp_addr_mgmt_ep(inp, ifa, type); 2816 } else { 2817 /* invalid address! */ 2818 return (EADDRNOTAVAIL); 2819 } 2820 return (0); 2821} 2822 2823void 2824sctp_addr_change(struct ifaddr *ifa, int cmd) 2825{ 2826 struct sctp_laddr *wi; 2827 2828 wi = (struct sctp_laddr *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr); 2829 if (wi == NULL) { 2830 /* 2831 * Gak, what can we do? We have lost an address change can 2832 * you say HOSED? 2833 */ 2834#ifdef SCTP_DEBUG 2835 if (sctp_debug_on & SCTP_DEBUG_PCB1) { 2836 printf("Lost and address change ???\n"); 2837 } 2838#endif /* SCTP_DEBUG */ 2839 return; 2840 } 2841 SCTP_INCR_LADDR_COUNT(); 2842 bzero(wi, sizeof(*wi)); 2843 wi->ifa = ifa; 2844 IFAREF(ifa); 2845 2846 wi->action = cmd; 2847 SCTP_IPI_ADDR_LOCK(); 2848 /* 2849 * Should this really be a tailq? As it is we will process the 2850 * newest first :-0 2851 */ 2852 LIST_INSERT_HEAD(&sctppcbinfo.addr_wq, wi, sctp_nxt_addr); 2853 sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 2854 (struct sctp_inpcb *)NULL, 2855 (struct sctp_tcb *)NULL, 2856 (struct sctp_nets *)NULL); 2857 SCTP_IPI_ADDR_UNLOCK(); 2858} 2859