1 /* $NetBSD: in6_pcb.c,v 1.145 2016/06/21 10:25:27 ozaki-r Exp $ */ 2 /* $KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1982, 1986, 1991, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94 62 */ 63 64 #include <sys/cdefs.h> 65 __KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.145 2016/06/21 10:25:27 ozaki-r Exp $"); 66 67 #ifdef _KERNEL_OPT 68 #include "opt_inet.h" 69 #include "opt_ipsec.h" 70 #endif 71 72 #include <sys/param.h> 73 #include <sys/systm.h> 74 #include <sys/mbuf.h> 75 #include <sys/protosw.h> 76 #include <sys/socket.h> 77 #include <sys/socketvar.h> 78 #include <sys/ioctl.h> 79 #include <sys/errno.h> 80 #include <sys/time.h> 81 #include <sys/proc.h> 82 #include <sys/kauth.h> 83 #include <sys/domain.h> 84 #include <sys/once.h> 85 86 #include <net/if.h> 87 #include <net/route.h> 88 89 #include <netinet/in.h> 90 #include <netinet/in_var.h> 91 #include <netinet/in_systm.h> 92 #include <netinet/ip.h> 93 #include <netinet/in_pcb.h> 94 #include <netinet/ip6.h> 95 #include <netinet/portalgo.h> 96 #include <netinet6/ip6_var.h> 97 #include <netinet6/in6_pcb.h> 98 #include <netinet6/scope6_var.h> 99 #include <netinet6/nd6.h> 100 101 #include "faith.h" 102 103 #ifdef IPSEC 104 #include <netipsec/ipsec.h> 105 #include <netipsec/ipsec6.h> 106 #include <netipsec/key.h> 107 #endif /* IPSEC */ 108 109 #include <netinet/tcp_vtw.h> 110 111 const struct in6_addr zeroin6_addr; 112 113 #define IN6PCBHASH_PORT(table, lport) \ 114 &(table)->inpt_porthashtbl[ntohs(lport) & (table)->inpt_porthash] 115 #define IN6PCBHASH_BIND(table, laddr, lport) \ 116 &(table)->inpt_bindhashtbl[ \ 117 (((laddr)->s6_addr32[0] ^ (laddr)->s6_addr32[1] ^ \ 118 (laddr)->s6_addr32[2] ^ (laddr)->s6_addr32[3]) + ntohs(lport)) & \ 119 (table)->inpt_bindhash] 120 #define IN6PCBHASH_CONNECT(table, faddr, fport, laddr, lport) \ 121 &(table)->inpt_bindhashtbl[ \ 122 ((((faddr)->s6_addr32[0] ^ (faddr)->s6_addr32[1] ^ \ 123 (faddr)->s6_addr32[2] ^ (faddr)->s6_addr32[3]) + ntohs(fport)) + \ 124 (((laddr)->s6_addr32[0] ^ (laddr)->s6_addr32[1] ^ \ 125 (laddr)->s6_addr32[2] ^ (laddr)->s6_addr32[3]) + \ 126 ntohs(lport))) & (table)->inpt_bindhash] 127 128 int ip6_anonportmin = IPV6PORT_ANONMIN; 129 int ip6_anonportmax = IPV6PORT_ANONMAX; 130 int ip6_lowportmin = IPV6PORT_RESERVEDMIN; 131 int ip6_lowportmax = IPV6PORT_RESERVEDMAX; 132 133 static struct pool in6pcb_pool; 134 135 static int 136 in6pcb_poolinit(void) 137 { 138 139 pool_init(&in6pcb_pool, sizeof(struct in6pcb), 0, 0, 0, "in6pcbpl", 140 NULL, IPL_SOFTNET); 141 return 0; 142 } 143 144 void 145 in6_pcbinit(struct inpcbtable *table, int bindhashsize, int connecthashsize) 146 { 147 static ONCE_DECL(control); 148 149 in_pcbinit(table, bindhashsize, connecthashsize); 150 table->inpt_lastport = (u_int16_t)ip6_anonportmax; 151 152 RUN_ONCE(&control, in6pcb_poolinit); 153 } 154 155 int 156 in6_pcballoc(struct socket *so, void *v) 157 { 158 struct inpcbtable *table = v; 159 struct in6pcb *in6p; 160 int s; 161 162 s = splnet(); 163 in6p = pool_get(&in6pcb_pool, PR_NOWAIT); 164 splx(s); 165 if (in6p == NULL) 166 return (ENOBUFS); 167 memset((void *)in6p, 0, sizeof(*in6p)); 168 in6p->in6p_af = AF_INET6; 169 in6p->in6p_table = table; 170 in6p->in6p_socket = so; 171 in6p->in6p_hops = -1; /* use kernel default */ 172 in6p->in6p_icmp6filt = NULL; 173 in6p->in6p_portalgo = PORTALGO_DEFAULT; 174 in6p->in6p_bindportonsend = false; 175 #if defined(IPSEC) 176 if (ipsec_enabled) { 177 int error = ipsec_init_pcbpolicy(so, &in6p->in6p_sp); 178 if (error != 0) { 179 s = splnet(); 180 pool_put(&in6pcb_pool, in6p); 181 splx(s); 182 return error; 183 } 184 } 185 #endif /* IPSEC */ 186 s = splnet(); 187 TAILQ_INSERT_HEAD(&table->inpt_queue, (struct inpcb_hdr*)in6p, 188 inph_queue); 189 LIST_INSERT_HEAD(IN6PCBHASH_PORT(table, in6p->in6p_lport), 190 &in6p->in6p_head, inph_lhash); 191 in6_pcbstate(in6p, IN6P_ATTACHED); 192 splx(s); 193 if (ip6_v6only) 194 in6p->in6p_flags |= IN6P_IPV6_V6ONLY; 195 so->so_pcb = (void *)in6p; 196 return (0); 197 } 198 199 /* 200 * Bind address from sin6 to in6p. 201 */ 202 static int 203 in6_pcbbind_addr(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l) 204 { 205 int error; 206 207 /* 208 * We should check the family, but old programs 209 * incorrectly fail to intialize it. 210 */ 211 if (sin6->sin6_family != AF_INET6) 212 return (EAFNOSUPPORT); 213 214 #ifndef INET 215 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 216 return (EADDRNOTAVAIL); 217 #endif 218 219 if ((error = sa6_embedscope(sin6, ip6_use_defzone)) != 0) 220 return (error); 221 222 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 223 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 224 return (EINVAL); 225 if (sin6->sin6_addr.s6_addr32[3]) { 226 struct sockaddr_in sin; 227 228 memset(&sin, 0, sizeof(sin)); 229 sin.sin_len = sizeof(sin); 230 sin.sin_family = AF_INET; 231 bcopy(&sin6->sin6_addr.s6_addr32[3], 232 &sin.sin_addr, sizeof(sin.sin_addr)); 233 if (!IN_MULTICAST(sin.sin_addr.s_addr) && 234 ifa_ifwithaddr((struct sockaddr *)&sin) == NULL) 235 return EADDRNOTAVAIL; 236 } 237 } else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 238 // succeed 239 } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 240 struct ifaddr *ia = NULL; 241 242 if ((in6p->in6p_flags & IN6P_FAITH) == 0 && 243 (ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == NULL) 244 return (EADDRNOTAVAIL); 245 246 /* 247 * bind to an anycast address might accidentally 248 * cause sending a packet with an anycast source 249 * address, so we forbid it. 250 * 251 * We should allow to bind to a deprecated address, 252 * since the application dare to use it. 253 * But, can we assume that they are careful enough 254 * to check if the address is deprecated or not? 255 * Maybe, as a safeguard, we should have a setsockopt 256 * flag to control the bind(2) behavior against 257 * deprecated addresses (default: forbid bind(2)). 258 */ 259 if (ia && 260 ((struct in6_ifaddr *)ia)->ia6_flags & 261 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) 262 return (EADDRNOTAVAIL); 263 } 264 265 266 in6p->in6p_laddr = sin6->sin6_addr; 267 268 269 return (0); 270 } 271 272 /* 273 * Bind port from sin6 to in6p. 274 */ 275 static int 276 in6_pcbbind_port(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l) 277 { 278 struct inpcbtable *table = in6p->in6p_table; 279 struct socket *so = in6p->in6p_socket; 280 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); 281 int error; 282 283 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && 284 ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || 285 (so->so_options & SO_ACCEPTCONN) == 0)) 286 wild = 1; 287 288 if (sin6->sin6_port != 0) { 289 enum kauth_network_req req; 290 291 #ifndef IPNOPRIVPORTS 292 if (ntohs(sin6->sin6_port) < IPV6PORT_RESERVED) 293 req = KAUTH_REQ_NETWORK_BIND_PRIVPORT; 294 else 295 #endif /* IPNOPRIVPORTS */ 296 req = KAUTH_REQ_NETWORK_BIND_PORT; 297 298 error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_BIND, 299 req, so, sin6, NULL); 300 if (error) 301 return (EACCES); 302 } 303 304 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 305 /* 306 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 307 * allow compepte duplication of binding if 308 * SO_REUSEPORT is set, or if SO_REUSEADDR is set 309 * and a multicast address is bound on both 310 * new and duplicated sockets. 311 */ 312 if (so->so_options & (SO_REUSEADDR | SO_REUSEPORT)) 313 reuseport = SO_REUSEADDR|SO_REUSEPORT; 314 } 315 316 if (sin6->sin6_port != 0) { 317 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 318 #ifdef INET 319 struct inpcb *t; 320 struct vestigial_inpcb vestige; 321 322 t = in_pcblookup_port(table, 323 *(struct in_addr *)&sin6->sin6_addr.s6_addr32[3], 324 sin6->sin6_port, wild, &vestige); 325 if (t && (reuseport & t->inp_socket->so_options) == 0) 326 return (EADDRINUSE); 327 if (!t 328 && vestige.valid 329 && !(reuseport && vestige.reuse_port)) 330 return EADDRINUSE; 331 #else 332 return (EADDRNOTAVAIL); 333 #endif 334 } 335 336 { 337 struct in6pcb *t; 338 struct vestigial_inpcb vestige; 339 340 t = in6_pcblookup_port(table, &sin6->sin6_addr, 341 sin6->sin6_port, wild, &vestige); 342 if (t && (reuseport & t->in6p_socket->so_options) == 0) 343 return (EADDRINUSE); 344 if (!t 345 && vestige.valid 346 && !(reuseport && vestige.reuse_port)) 347 return EADDRINUSE; 348 } 349 } 350 351 if (sin6->sin6_port == 0) { 352 int e; 353 e = in6_pcbsetport(sin6, in6p, l); 354 if (e != 0) 355 return (e); 356 } else { 357 in6p->in6p_lport = sin6->sin6_port; 358 in6_pcbstate(in6p, IN6P_BOUND); 359 } 360 361 LIST_REMOVE(&in6p->in6p_head, inph_lhash); 362 LIST_INSERT_HEAD(IN6PCBHASH_PORT(table, in6p->in6p_lport), 363 &in6p->in6p_head, inph_lhash); 364 365 return (0); 366 } 367 368 int 369 in6_pcbbind(void *v, struct sockaddr_in6 *sin6, struct lwp *l) 370 { 371 struct in6pcb *in6p = v; 372 struct sockaddr_in6 lsin6; 373 int error; 374 375 if (in6p->in6p_af != AF_INET6) 376 return (EINVAL); 377 378 /* 379 * If we already have a local port or a local address it means we're 380 * bounded. 381 */ 382 if (in6p->in6p_lport || !(IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) || 383 (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr) && 384 in6p->in6p_laddr.s6_addr32[3] == 0))) 385 return (EINVAL); 386 387 if (NULL != sin6) { 388 /* We were provided a sockaddr_in6 to use. */ 389 if (sin6->sin6_len != sizeof(*sin6)) 390 return (EINVAL); 391 } else { 392 /* We always bind to *something*, even if it's "anything". */ 393 lsin6 = *((const struct sockaddr_in6 *) 394 in6p->in6p_socket->so_proto->pr_domain->dom_sa_any); 395 sin6 = &lsin6; 396 } 397 398 /* Bind address. */ 399 error = in6_pcbbind_addr(in6p, sin6, l); 400 if (error) 401 return (error); 402 403 /* Bind port. */ 404 error = in6_pcbbind_port(in6p, sin6, l); 405 if (error) { 406 /* 407 * Reset the address here to "any" so we don't "leak" the 408 * in6pcb. 409 */ 410 in6p->in6p_laddr = in6addr_any; 411 412 return (error); 413 } 414 415 416 #if 0 417 in6p->in6p_flowinfo = 0; /* XXX */ 418 #endif 419 return (0); 420 } 421 422 /* 423 * Connect from a socket to a specified address. 424 * Both address and port must be specified in argument sin6. 425 * If don't have a local address for this socket yet, 426 * then pick one. 427 */ 428 int 429 in6_pcbconnect(void *v, struct sockaddr_in6 *sin6, struct lwp *l) 430 { 431 struct in6pcb *in6p = v; 432 struct in6_addr *in6a = NULL; 433 struct ifnet *ifp = NULL; /* outgoing interface */ 434 int error = 0; 435 int scope_ambiguous = 0; 436 #ifdef INET 437 struct in6_addr mapped; 438 #endif 439 struct sockaddr_in6 tmp; 440 struct vestigial_inpcb vestige; 441 struct psref psref; 442 int bound; 443 444 (void)&in6a; /* XXX fool gcc */ 445 446 if (in6p->in6p_af != AF_INET6) 447 return (EINVAL); 448 449 if (sin6->sin6_len != sizeof(*sin6)) 450 return (EINVAL); 451 if (sin6->sin6_family != AF_INET6) 452 return (EAFNOSUPPORT); 453 if (sin6->sin6_port == 0) 454 return (EADDRNOTAVAIL); 455 456 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) && 457 in6p->in6p_socket->so_type == SOCK_STREAM) 458 return EADDRNOTAVAIL; 459 460 if (sin6->sin6_scope_id == 0 && !ip6_use_defzone) 461 scope_ambiguous = 1; 462 if ((error = sa6_embedscope(sin6, ip6_use_defzone)) != 0) 463 return(error); 464 465 /* sanity check for mapped address case */ 466 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 467 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 468 return EINVAL; 469 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) 470 in6p->in6p_laddr.s6_addr16[5] = htons(0xffff); 471 if (!IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)) 472 return EINVAL; 473 } else 474 { 475 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)) 476 return EINVAL; 477 } 478 479 /* protect *sin6 from overwrites */ 480 tmp = *sin6; 481 sin6 = &tmp; 482 483 bound = curlwp_bind(); 484 /* Source address selection. */ 485 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr) && 486 in6p->in6p_laddr.s6_addr32[3] == 0) { 487 #ifdef INET 488 struct sockaddr_in sin, *sinp; 489 490 memset(&sin, 0, sizeof(sin)); 491 sin.sin_len = sizeof(sin); 492 sin.sin_family = AF_INET; 493 memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr32[3], 494 sizeof(sin.sin_addr)); 495 sinp = in_selectsrc(&sin, &in6p->in6p_route, 496 in6p->in6p_socket->so_options, NULL, &error); 497 if (sinp == NULL) { 498 if (error == 0) 499 error = EADDRNOTAVAIL; 500 return (error); 501 } 502 memset(&mapped, 0, sizeof(mapped)); 503 mapped.s6_addr16[5] = htons(0xffff); 504 memcpy(&mapped.s6_addr32[3], &sinp->sin_addr, sizeof(sinp->sin_addr)); 505 in6a = &mapped; 506 #else 507 return EADDRNOTAVAIL; 508 #endif 509 } else { 510 /* 511 * XXX: in6_selectsrc might replace the bound local address 512 * with the address specified by setsockopt(IPV6_PKTINFO). 513 * Is it the intended behavior? 514 */ 515 in6a = in6_selectsrc(sin6, in6p->in6p_outputopts, 516 in6p->in6p_moptions, 517 &in6p->in6p_route, 518 &in6p->in6p_laddr, &ifp, &psref, &error); 519 if (ifp && scope_ambiguous && 520 (error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) { 521 if_put(ifp, &psref); 522 curlwp_bindx(bound); 523 return(error); 524 } 525 526 if (in6a == NULL) { 527 if_put(ifp, &psref); 528 curlwp_bindx(bound); 529 if (error == 0) 530 error = EADDRNOTAVAIL; 531 return (error); 532 } 533 } 534 535 if (ifp != NULL) { 536 in6p->in6p_ip6.ip6_hlim = (u_int8_t)in6_selecthlim(in6p, ifp); 537 if_put(ifp, &psref); 538 } else 539 in6p->in6p_ip6.ip6_hlim = (u_int8_t)in6_selecthlim_rt(in6p); 540 curlwp_bindx(bound); 541 542 if (in6_pcblookup_connect(in6p->in6p_table, &sin6->sin6_addr, 543 sin6->sin6_port, 544 IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) ? in6a : &in6p->in6p_laddr, 545 in6p->in6p_lport, 0, &vestige) 546 || vestige.valid) 547 return (EADDRINUSE); 548 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) || 549 (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr) && 550 in6p->in6p_laddr.s6_addr32[3] == 0)) 551 { 552 if (in6p->in6p_lport == 0) { 553 error = in6_pcbbind(in6p, NULL, l); 554 if (error != 0) 555 return error; 556 } 557 in6p->in6p_laddr = *in6a; 558 } 559 in6p->in6p_faddr = sin6->sin6_addr; 560 in6p->in6p_fport = sin6->sin6_port; 561 562 /* Late bind, if needed */ 563 if (in6p->in6p_bindportonsend) { 564 struct sockaddr_in6 lsin = *((const struct sockaddr_in6 *) 565 in6p->in6p_socket->so_proto->pr_domain->dom_sa_any); 566 lsin.sin6_addr = in6p->in6p_laddr; 567 lsin.sin6_port = 0; 568 569 if ((error = in6_pcbbind_port(in6p, &lsin, l)) != 0) 570 return error; 571 } 572 573 in6_pcbstate(in6p, IN6P_CONNECTED); 574 in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; 575 if (ip6_auto_flowlabel) 576 in6p->in6p_flowinfo |= 577 (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK); 578 #if defined(IPSEC) 579 if (ipsec_enabled && in6p->in6p_socket->so_type == SOCK_STREAM) 580 ipsec_pcbconn(in6p->in6p_sp); 581 #endif 582 return (0); 583 } 584 585 void 586 in6_pcbdisconnect(struct in6pcb *in6p) 587 { 588 memset((void *)&in6p->in6p_faddr, 0, sizeof(in6p->in6p_faddr)); 589 in6p->in6p_fport = 0; 590 in6_pcbstate(in6p, IN6P_BOUND); 591 in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; 592 #if defined(IPSEC) 593 if (ipsec_enabled) 594 ipsec_pcbdisconn(in6p->in6p_sp); 595 #endif 596 if (in6p->in6p_socket->so_state & SS_NOFDREF) 597 in6_pcbdetach(in6p); 598 } 599 600 void 601 in6_pcbdetach(struct in6pcb *in6p) 602 { 603 struct socket *so = in6p->in6p_socket; 604 int s; 605 606 if (in6p->in6p_af != AF_INET6) 607 return; 608 609 #if defined(IPSEC) 610 if (ipsec_enabled) 611 ipsec6_delete_pcbpolicy(in6p); 612 #endif 613 so->so_pcb = NULL; 614 615 s = splnet(); 616 in6_pcbstate(in6p, IN6P_ATTACHED); 617 LIST_REMOVE(&in6p->in6p_head, inph_lhash); 618 TAILQ_REMOVE(&in6p->in6p_table->inpt_queue, &in6p->in6p_head, 619 inph_queue); 620 splx(s); 621 622 if (in6p->in6p_options) { 623 m_freem(in6p->in6p_options); 624 } 625 if (in6p->in6p_outputopts != NULL) { 626 ip6_clearpktopts(in6p->in6p_outputopts, -1); 627 free(in6p->in6p_outputopts, M_IP6OPT); 628 } 629 rtcache_free(&in6p->in6p_route); 630 ip6_freemoptions(in6p->in6p_moptions); 631 ip_freemoptions(in6p->in6p_v4moptions); 632 sofree(so); /* drops the socket's lock */ 633 634 pool_put(&in6pcb_pool, in6p); 635 mutex_enter(softnet_lock); /* reacquire it */ 636 } 637 638 void 639 in6_setsockaddr(struct in6pcb *in6p, struct sockaddr_in6 *sin6) 640 { 641 642 if (in6p->in6p_af != AF_INET6) 643 return; 644 645 sockaddr_in6_init(sin6, &in6p->in6p_laddr, in6p->in6p_lport, 0, 0); 646 (void)sa6_recoverscope(sin6); /* XXX: should catch errors */ 647 } 648 649 void 650 in6_setpeeraddr(struct in6pcb *in6p, struct sockaddr_in6 *sin6) 651 { 652 653 if (in6p->in6p_af != AF_INET6) 654 return; 655 656 sockaddr_in6_init(sin6, &in6p->in6p_faddr, in6p->in6p_fport, 0, 0); 657 (void)sa6_recoverscope(sin6); /* XXX: should catch errors */ 658 } 659 660 /* 661 * Pass some notification to all connections of a protocol 662 * associated with address dst. The local address and/or port numbers 663 * may be specified to limit the search. The "usual action" will be 664 * taken, depending on the ctlinput cmd. The caller must filter any 665 * cmds that are uninteresting (e.g., no error in the map). 666 * Call the protocol specific routine (if any) to report 667 * any errors for each matching socket. 668 * 669 * Must be called at splsoftnet. 670 * 671 * Note: src (4th arg) carries the flowlabel value on the original IPv6 672 * header, in sin6_flowinfo member. 673 */ 674 int 675 in6_pcbnotify(struct inpcbtable *table, const struct sockaddr *dst, 676 u_int fport_arg, const struct sockaddr *src, u_int lport_arg, int cmd, 677 void *cmdarg, void (*notify)(struct in6pcb *, int)) 678 { 679 struct rtentry *rt; 680 struct inpcb_hdr *inph, *ninph; 681 struct sockaddr_in6 sa6_src; 682 const struct sockaddr_in6 *sa6_dst; 683 u_int16_t fport = fport_arg, lport = lport_arg; 684 int errno; 685 int nmatch = 0; 686 u_int32_t flowinfo; 687 688 if ((unsigned)cmd >= PRC_NCMDS || dst->sa_family != AF_INET6) 689 return 0; 690 691 sa6_dst = (const struct sockaddr_in6 *)dst; 692 if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr)) 693 return 0; 694 695 /* 696 * note that src can be NULL when we get notify by local fragmentation. 697 */ 698 sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src; 699 flowinfo = sa6_src.sin6_flowinfo; 700 701 /* 702 * Redirects go to all references to the destination, 703 * and use in6_rtchange to invalidate the route cache. 704 * Dead host indications: also use in6_rtchange to invalidate 705 * the cache, and deliver the error to all the sockets. 706 * Otherwise, if we have knowledge of the local port and address, 707 * deliver only to that socket. 708 */ 709 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { 710 fport = 0; 711 lport = 0; 712 memset((void *)&sa6_src.sin6_addr, 0, sizeof(sa6_src.sin6_addr)); 713 714 if (cmd != PRC_HOSTDEAD) 715 notify = in6_rtchange; 716 } 717 718 errno = inet6ctlerrmap[cmd]; 719 TAILQ_FOREACH_SAFE(inph, &table->inpt_queue, inph_queue, ninph) { 720 struct in6pcb *in6p = (struct in6pcb *)inph; 721 if (in6p->in6p_af != AF_INET6) 722 continue; 723 724 /* 725 * Under the following condition, notify of redirects 726 * to the pcb, without making address matches against inpcb. 727 * - redirect notification is arrived. 728 * - the inpcb is unconnected. 729 * - the inpcb is caching !RTF_HOST routing entry. 730 * - the ICMPv6 notification is from the gateway cached in the 731 * inpcb. i.e. ICMPv6 notification is from nexthop gateway 732 * the inpcb used very recently. 733 * 734 * This is to improve interaction between netbsd/openbsd 735 * redirect handling code, and inpcb route cache code. 736 * without the clause, !RTF_HOST routing entry (which carries 737 * gateway used by inpcb right before the ICMPv6 redirect) 738 * will be cached forever in unconnected inpcb. 739 * 740 * There still is a question regarding to what is TRT: 741 * - On bsdi/freebsd, RTF_HOST (cloned) routing entry will be 742 * generated on packet output. inpcb will always cache 743 * RTF_HOST routing entry so there's no need for the clause 744 * (ICMPv6 redirect will update RTF_HOST routing entry, 745 * and inpcb is caching it already). 746 * However, bsdi/freebsd are vulnerable to local DoS attacks 747 * due to the cloned routing entries. 748 * - Specwise, "destination cache" is mentioned in RFC2461. 749 * Jinmei says that it implies bsdi/freebsd behavior, itojun 750 * is not really convinced. 751 * - Having hiwat/lowat on # of cloned host route (redirect/ 752 * pmtud) may be a good idea. netbsd/openbsd has it. see 753 * icmp6_mtudisc_update(). 754 */ 755 if ((PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) && 756 IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 757 (rt = rtcache_validate(&in6p->in6p_route)) != NULL && 758 !(rt->rt_flags & RTF_HOST)) { 759 const struct sockaddr_in6 *dst6; 760 761 dst6 = (const struct sockaddr_in6 *) 762 rtcache_getdst(&in6p->in6p_route); 763 if (dst6 == NULL) 764 ; 765 else if (IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, 766 &sa6_dst->sin6_addr)) 767 goto do_notify; 768 } 769 770 /* 771 * If the error designates a new path MTU for a destination 772 * and the application (associated with this socket) wanted to 773 * know the value, notify. Note that we notify for all 774 * disconnected sockets if the corresponding application 775 * wanted. This is because some UDP applications keep sending 776 * sockets disconnected. 777 * XXX: should we avoid to notify the value to TCP sockets? 778 */ 779 if (cmd == PRC_MSGSIZE && (in6p->in6p_flags & IN6P_MTU) != 0 && 780 (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) || 781 IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &sa6_dst->sin6_addr))) { 782 ip6_notify_pmtu(in6p, (const struct sockaddr_in6 *)dst, 783 (u_int32_t *)cmdarg); 784 } 785 786 /* 787 * Detect if we should notify the error. If no source and 788 * destination ports are specified, but non-zero flowinfo and 789 * local address match, notify the error. This is the case 790 * when the error is delivered with an encrypted buffer 791 * by ESP. Otherwise, just compare addresses and ports 792 * as usual. 793 */ 794 if (lport == 0 && fport == 0 && flowinfo && 795 in6p->in6p_socket != NULL && 796 flowinfo == (in6p->in6p_flowinfo & IPV6_FLOWLABEL_MASK) && 797 IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &sa6_src.sin6_addr)) 798 goto do_notify; 799 else if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, 800 &sa6_dst->sin6_addr) || 801 in6p->in6p_socket == NULL || 802 (lport && in6p->in6p_lport != lport) || 803 (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) && 804 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, 805 &sa6_src.sin6_addr)) || 806 (fport && in6p->in6p_fport != fport)) 807 continue; 808 809 do_notify: 810 if (notify) 811 (*notify)(in6p, errno); 812 nmatch++; 813 } 814 return nmatch; 815 } 816 817 void 818 in6_pcbpurgeif0(struct inpcbtable *table, struct ifnet *ifp) 819 { 820 struct inpcb_hdr *inph, *ninph; 821 struct ip6_moptions *im6o; 822 struct in6_multi_mship *imm, *nimm; 823 824 KASSERT(ifp != NULL); 825 826 TAILQ_FOREACH_SAFE(inph, &table->inpt_queue, inph_queue, ninph) { 827 struct in6pcb *in6p = (struct in6pcb *)inph; 828 if (in6p->in6p_af != AF_INET6) 829 continue; 830 831 im6o = in6p->in6p_moptions; 832 if (im6o) { 833 /* 834 * Unselect the outgoing interface if it is being 835 * detached. 836 */ 837 if (im6o->im6o_multicast_if_index == ifp->if_index) 838 im6o->im6o_multicast_if_index = 0; 839 840 /* 841 * Drop multicast group membership if we joined 842 * through the interface being detached. 843 * XXX controversial - is it really legal for kernel 844 * to force this? 845 */ 846 for (imm = im6o->im6o_memberships.lh_first; 847 imm != NULL; imm = nimm) { 848 nimm = imm->i6mm_chain.le_next; 849 if (imm->i6mm_maddr->in6m_ifp == ifp) { 850 LIST_REMOVE(imm, i6mm_chain); 851 in6_leavegroup(imm); 852 } 853 } 854 } 855 in_purgeifmcast(in6p->in6p_v4moptions, ifp); 856 } 857 } 858 859 void 860 in6_pcbpurgeif(struct inpcbtable *table, struct ifnet *ifp) 861 { 862 struct rtentry *rt; 863 struct inpcb_hdr *inph, *ninph; 864 865 TAILQ_FOREACH_SAFE(inph, &table->inpt_queue, inph_queue, ninph) { 866 struct in6pcb *in6p = (struct in6pcb *)inph; 867 if (in6p->in6p_af != AF_INET6) 868 continue; 869 if ((rt = rtcache_validate(&in6p->in6p_route)) != NULL && 870 rt->rt_ifp == ifp) 871 in6_rtchange(in6p, 0); 872 } 873 } 874 875 /* 876 * Check for alternatives when higher level complains 877 * about service problems. For now, invalidate cached 878 * routing information. If the route was created dynamically 879 * (by a redirect), time to try a default gateway again. 880 */ 881 void 882 in6_losing(struct in6pcb *in6p) 883 { 884 struct rtentry *rt; 885 struct rt_addrinfo info; 886 887 if (in6p->in6p_af != AF_INET6) 888 return; 889 890 if ((rt = rtcache_validate(&in6p->in6p_route)) == NULL) 891 return; 892 893 memset(&info, 0, sizeof(info)); 894 info.rti_info[RTAX_DST] = rtcache_getdst(&in6p->in6p_route); 895 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 896 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 897 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); 898 if (rt->rt_flags & RTF_DYNAMIC) { 899 (void)rtrequest(RTM_DELETE, rt_getkey(rt), 900 rt->rt_gateway, rt_mask(rt), rt->rt_flags, NULL); 901 } 902 /* 903 * A new route can be allocated 904 * the next time output is attempted. 905 */ 906 rtcache_free(&in6p->in6p_route); 907 } 908 909 /* 910 * After a routing change, flush old routing. A new route can be 911 * allocated the next time output is attempted. 912 */ 913 void 914 in6_rtchange(struct in6pcb *in6p, int errno) 915 { 916 if (in6p->in6p_af != AF_INET6) 917 return; 918 919 rtcache_free(&in6p->in6p_route); 920 /* 921 * A new route can be allocated the next time 922 * output is attempted. 923 */ 924 } 925 926 struct in6pcb * 927 in6_pcblookup_port(struct inpcbtable *table, struct in6_addr *laddr6, 928 u_int lport_arg, int lookup_wildcard, struct vestigial_inpcb *vp) 929 { 930 struct inpcbhead *head; 931 struct inpcb_hdr *inph; 932 struct in6pcb *in6p, *match = NULL; 933 int matchwild = 3, wildcard; 934 u_int16_t lport = lport_arg; 935 936 if (vp) 937 vp->valid = 0; 938 939 head = IN6PCBHASH_PORT(table, lport); 940 LIST_FOREACH(inph, head, inph_lhash) { 941 in6p = (struct in6pcb *)inph; 942 if (in6p->in6p_af != AF_INET6) 943 continue; 944 945 if (in6p->in6p_lport != lport) 946 continue; 947 wildcard = 0; 948 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr)) { 949 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 950 continue; 951 } 952 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) 953 wildcard++; 954 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)) { 955 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 956 continue; 957 if (!IN6_IS_ADDR_V4MAPPED(laddr6)) 958 continue; 959 960 /* duplicate of IPv4 logic */ 961 wildcard = 0; 962 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr) && 963 in6p->in6p_faddr.s6_addr32[3]) 964 wildcard++; 965 if (!in6p->in6p_laddr.s6_addr32[3]) { 966 if (laddr6->s6_addr32[3]) 967 wildcard++; 968 } else { 969 if (!laddr6->s6_addr32[3]) 970 wildcard++; 971 else { 972 if (in6p->in6p_laddr.s6_addr32[3] != 973 laddr6->s6_addr32[3]) 974 continue; 975 } 976 } 977 } else if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) { 978 if (IN6_IS_ADDR_V4MAPPED(laddr6)) { 979 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 980 continue; 981 } 982 if (!IN6_IS_ADDR_UNSPECIFIED(laddr6)) 983 wildcard++; 984 } else { 985 if (IN6_IS_ADDR_V4MAPPED(laddr6)) { 986 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 987 continue; 988 } 989 if (IN6_IS_ADDR_UNSPECIFIED(laddr6)) 990 wildcard++; 991 else { 992 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, 993 laddr6)) 994 continue; 995 } 996 } 997 if (wildcard && !lookup_wildcard) 998 continue; 999 if (wildcard < matchwild) { 1000 match = in6p; 1001 matchwild = wildcard; 1002 if (matchwild == 0) 1003 break; 1004 } 1005 } 1006 if (match && matchwild == 0) 1007 return match; 1008 1009 if (vp && table->vestige && table->vestige->init_ports6) { 1010 struct vestigial_inpcb better; 1011 void *state; 1012 1013 state = (*table->vestige->init_ports6)(laddr6, 1014 lport_arg, 1015 lookup_wildcard); 1016 while (table->vestige 1017 && (*table->vestige->next_port6)(state, vp)) { 1018 1019 if (vp->lport != lport) 1020 continue; 1021 wildcard = 0; 1022 if (!IN6_IS_ADDR_UNSPECIFIED(&vp->faddr.v6)) 1023 wildcard++; 1024 if (IN6_IS_ADDR_UNSPECIFIED(&vp->laddr.v6)) { 1025 if (!IN6_IS_ADDR_UNSPECIFIED(laddr6)) 1026 wildcard++; 1027 } else { 1028 if (IN6_IS_ADDR_V4MAPPED(laddr6)) { 1029 if (vp->v6only) 1030 continue; 1031 } 1032 if (IN6_IS_ADDR_UNSPECIFIED(laddr6)) 1033 wildcard++; 1034 else { 1035 if (!IN6_ARE_ADDR_EQUAL(&vp->laddr.v6, laddr6)) 1036 continue; 1037 } 1038 } 1039 if (wildcard && !lookup_wildcard) 1040 continue; 1041 if (wildcard < matchwild) { 1042 better = *vp; 1043 match = (void*)&better; 1044 1045 matchwild = wildcard; 1046 if (matchwild == 0) 1047 break; 1048 } 1049 } 1050 1051 if (match) { 1052 if (match != (void*)&better) 1053 return match; 1054 else { 1055 *vp = better; 1056 return 0; 1057 } 1058 } 1059 } 1060 return (match); 1061 } 1062 1063 /* 1064 * WARNING: return value (rtentry) could be IPv4 one if in6pcb is connected to 1065 * IPv4 mapped address. 1066 */ 1067 struct rtentry * 1068 in6_pcbrtentry(struct in6pcb *in6p) 1069 { 1070 struct rtentry *rt; 1071 struct route *ro; 1072 union { 1073 const struct sockaddr *sa; 1074 const struct sockaddr_in6 *sa6; 1075 #ifdef INET 1076 const struct sockaddr_in *sa4; 1077 #endif 1078 } cdst; 1079 1080 ro = &in6p->in6p_route; 1081 1082 if (in6p->in6p_af != AF_INET6) 1083 return (NULL); 1084 1085 cdst.sa = rtcache_getdst(ro); 1086 if (cdst.sa == NULL) 1087 ; 1088 #ifdef INET 1089 else if (cdst.sa->sa_family == AF_INET) { 1090 KASSERT(IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr)); 1091 if (cdst.sa4->sin_addr.s_addr != in6p->in6p_faddr.s6_addr32[3]) 1092 rtcache_free(ro); 1093 } 1094 #endif 1095 else { 1096 if (!IN6_ARE_ADDR_EQUAL(&cdst.sa6->sin6_addr, 1097 &in6p->in6p_faddr)) 1098 rtcache_free(ro); 1099 } 1100 if ((rt = rtcache_validate(ro)) == NULL) 1101 rt = rtcache_update(ro, 1); 1102 #ifdef INET 1103 if (rt == NULL && IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr)) { 1104 union { 1105 struct sockaddr dst; 1106 struct sockaddr_in dst4; 1107 } u; 1108 struct in_addr addr; 1109 1110 addr.s_addr = in6p->in6p_faddr.s6_addr32[3]; 1111 1112 sockaddr_in_init(&u.dst4, &addr, 0); 1113 if (rtcache_setdst(ro, &u.dst) != 0) 1114 return NULL; 1115 1116 rt = rtcache_init(ro); 1117 } else 1118 #endif 1119 if (rt == NULL && !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 1120 union { 1121 struct sockaddr dst; 1122 struct sockaddr_in6 dst6; 1123 } u; 1124 1125 sockaddr_in6_init(&u.dst6, &in6p->in6p_faddr, 0, 0, 0); 1126 if (rtcache_setdst(ro, &u.dst) != 0) 1127 return NULL; 1128 1129 rt = rtcache_init(ro); 1130 } 1131 return rt; 1132 } 1133 1134 struct in6pcb * 1135 in6_pcblookup_connect(struct inpcbtable *table, const struct in6_addr *faddr6, 1136 u_int fport_arg, const struct in6_addr *laddr6, u_int lport_arg, 1137 int faith, 1138 struct vestigial_inpcb *vp) 1139 { 1140 struct inpcbhead *head; 1141 struct inpcb_hdr *inph; 1142 struct in6pcb *in6p; 1143 u_int16_t fport = fport_arg, lport = lport_arg; 1144 1145 if (vp) 1146 vp->valid = 0; 1147 1148 head = IN6PCBHASH_CONNECT(table, faddr6, fport, laddr6, lport); 1149 LIST_FOREACH(inph, head, inph_hash) { 1150 in6p = (struct in6pcb *)inph; 1151 if (in6p->in6p_af != AF_INET6) 1152 continue; 1153 1154 /* find exact match on both source and dest */ 1155 if (in6p->in6p_fport != fport) 1156 continue; 1157 if (in6p->in6p_lport != lport) 1158 continue; 1159 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) 1160 continue; 1161 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, faddr6)) 1162 continue; 1163 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) 1164 continue; 1165 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, laddr6)) 1166 continue; 1167 if ((IN6_IS_ADDR_V4MAPPED(laddr6) || 1168 IN6_IS_ADDR_V4MAPPED(faddr6)) && 1169 (in6p->in6p_flags & IN6P_IPV6_V6ONLY)) 1170 continue; 1171 return in6p; 1172 } 1173 if (vp && table->vestige) { 1174 if ((*table->vestige->lookup6)(faddr6, fport_arg, 1175 laddr6, lport_arg, vp)) 1176 return NULL; 1177 } 1178 1179 return NULL; 1180 } 1181 1182 struct in6pcb * 1183 in6_pcblookup_bind(struct inpcbtable *table, const struct in6_addr *laddr6, 1184 u_int lport_arg, int faith) 1185 { 1186 struct inpcbhead *head; 1187 struct inpcb_hdr *inph; 1188 struct in6pcb *in6p; 1189 u_int16_t lport = lport_arg; 1190 #ifdef INET 1191 struct in6_addr zero_mapped; 1192 #endif 1193 1194 head = IN6PCBHASH_BIND(table, laddr6, lport); 1195 LIST_FOREACH(inph, head, inph_hash) { 1196 in6p = (struct in6pcb *)inph; 1197 if (in6p->in6p_af != AF_INET6) 1198 continue; 1199 1200 if (faith && (in6p->in6p_flags & IN6P_FAITH) == 0) 1201 continue; 1202 if (in6p->in6p_fport != 0) 1203 continue; 1204 if (in6p->in6p_lport != lport) 1205 continue; 1206 if (IN6_IS_ADDR_V4MAPPED(laddr6) && 1207 (in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 1208 continue; 1209 if (IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, laddr6)) 1210 goto out; 1211 } 1212 #ifdef INET 1213 if (IN6_IS_ADDR_V4MAPPED(laddr6)) { 1214 memset(&zero_mapped, 0, sizeof(zero_mapped)); 1215 zero_mapped.s6_addr16[5] = 0xffff; 1216 head = IN6PCBHASH_BIND(table, &zero_mapped, lport); 1217 LIST_FOREACH(inph, head, inph_hash) { 1218 in6p = (struct in6pcb *)inph; 1219 if (in6p->in6p_af != AF_INET6) 1220 continue; 1221 1222 if (faith && (in6p->in6p_flags & IN6P_FAITH) == 0) 1223 continue; 1224 if (in6p->in6p_fport != 0) 1225 continue; 1226 if (in6p->in6p_lport != lport) 1227 continue; 1228 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 1229 continue; 1230 if (IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &zero_mapped)) 1231 goto out; 1232 } 1233 } 1234 #endif 1235 head = IN6PCBHASH_BIND(table, &zeroin6_addr, lport); 1236 LIST_FOREACH(inph, head, inph_hash) { 1237 in6p = (struct in6pcb *)inph; 1238 if (in6p->in6p_af != AF_INET6) 1239 continue; 1240 1241 if (faith && (in6p->in6p_flags & IN6P_FAITH) == 0) 1242 continue; 1243 if (in6p->in6p_fport != 0) 1244 continue; 1245 if (in6p->in6p_lport != lport) 1246 continue; 1247 if (IN6_IS_ADDR_V4MAPPED(laddr6) && 1248 (in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 1249 continue; 1250 if (IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &zeroin6_addr)) 1251 goto out; 1252 } 1253 return (NULL); 1254 1255 out: 1256 inph = &in6p->in6p_head; 1257 if (inph != LIST_FIRST(head)) { 1258 LIST_REMOVE(inph, inph_hash); 1259 LIST_INSERT_HEAD(head, inph, inph_hash); 1260 } 1261 return in6p; 1262 } 1263 1264 void 1265 in6_pcbstate(struct in6pcb *in6p, int state) 1266 { 1267 1268 if (in6p->in6p_af != AF_INET6) 1269 return; 1270 1271 if (in6p->in6p_state > IN6P_ATTACHED) 1272 LIST_REMOVE(&in6p->in6p_head, inph_hash); 1273 1274 switch (state) { 1275 case IN6P_BOUND: 1276 LIST_INSERT_HEAD(IN6PCBHASH_BIND(in6p->in6p_table, 1277 &in6p->in6p_laddr, in6p->in6p_lport), &in6p->in6p_head, 1278 inph_hash); 1279 break; 1280 case IN6P_CONNECTED: 1281 LIST_INSERT_HEAD(IN6PCBHASH_CONNECT(in6p->in6p_table, 1282 &in6p->in6p_faddr, in6p->in6p_fport, 1283 &in6p->in6p_laddr, in6p->in6p_lport), &in6p->in6p_head, 1284 inph_hash); 1285 break; 1286 } 1287 1288 in6p->in6p_state = state; 1289 } 1290