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