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