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