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