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