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