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