1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (c) 2010-2011 Juniper Networks, Inc. 6 * All rights reserved. 7 * 8 * Portions of this software were developed by Robert N. M. Watson under 9 * contract to Juniper Networks, Inc. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the project nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $KAME: in6_pcb.c,v 1.31 2001/05/21 05:45:10 jinmei Exp $ 36 */ 37 38 /*- 39 * Copyright (c) 1982, 1986, 1991, 1993 40 * The Regents of the University of California. All rights reserved. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. Neither the name of the University nor the names of its contributors 51 * may be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 * SUCH DAMAGE. 65 * 66 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94 67 */ 68 69 #include <sys/cdefs.h> 70 __FBSDID("$FreeBSD$"); 71 72 #include "opt_inet.h" 73 #include "opt_inet6.h" 74 #include "opt_ipsec.h" 75 #include "opt_pcbgroup.h" 76 #include "opt_rss.h" 77 78 #include <sys/param.h> 79 #include <sys/systm.h> 80 #include <sys/malloc.h> 81 #include <sys/mbuf.h> 82 #include <sys/domain.h> 83 #include <sys/protosw.h> 84 #include <sys/socket.h> 85 #include <sys/socketvar.h> 86 #include <sys/sockio.h> 87 #include <sys/errno.h> 88 #include <sys/time.h> 89 #include <sys/priv.h> 90 #include <sys/proc.h> 91 #include <sys/jail.h> 92 93 #include <vm/uma.h> 94 95 #include <net/if.h> 96 #include <net/if_var.h> 97 #include <net/if_llatbl.h> 98 #include <net/if_types.h> 99 #include <net/route.h> 100 101 #include <netinet/in.h> 102 #include <netinet/in_var.h> 103 #include <netinet/in_systm.h> 104 #include <netinet/tcp_var.h> 105 #include <netinet/ip6.h> 106 #include <netinet/ip_var.h> 107 108 #include <netinet6/ip6_var.h> 109 #include <netinet6/nd6.h> 110 #include <netinet/in_pcb.h> 111 #include <netinet6/in6_pcb.h> 112 #include <netinet6/scope6_var.h> 113 114 static struct inpcb *in6_pcblookup_hash_locked(struct inpcbinfo *, 115 struct in6_addr *, u_int, struct in6_addr *, u_int, int, struct ifnet *); 116 117 int 118 in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, 119 struct ucred *cred) 120 { 121 struct socket *so = inp->inp_socket; 122 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL; 123 struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 124 u_short lport = 0; 125 int error, lookupflags = 0; 126 int reuseport = (so->so_options & SO_REUSEPORT); 127 128 /* 129 * XXX: Maybe we could let SO_REUSEPORT_LB set SO_REUSEPORT bit here 130 * so that we don't have to add to the (already messy) code below. 131 */ 132 int reuseport_lb = (so->so_options & SO_REUSEPORT_LB); 133 134 INP_WLOCK_ASSERT(inp); 135 INP_HASH_WLOCK_ASSERT(pcbinfo); 136 137 if (CK_STAILQ_EMPTY(&V_in6_ifaddrhead)) /* XXX broken! */ 138 return (EADDRNOTAVAIL); 139 if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) 140 return (EINVAL); 141 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT|SO_REUSEPORT_LB)) == 0) 142 lookupflags = INPLOOKUP_WILDCARD; 143 if (nam == NULL) { 144 if ((error = prison_local_ip6(cred, &inp->in6p_laddr, 145 ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) 146 return (error); 147 } else { 148 sin6 = (struct sockaddr_in6 *)nam; 149 if (nam->sa_len != sizeof(*sin6)) 150 return (EINVAL); 151 /* 152 * family check. 153 */ 154 if (nam->sa_family != AF_INET6) 155 return (EAFNOSUPPORT); 156 157 if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) 158 return(error); 159 160 if ((error = prison_local_ip6(cred, &sin6->sin6_addr, 161 ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) 162 return (error); 163 164 lport = sin6->sin6_port; 165 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 166 /* 167 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 168 * allow compepte duplication of binding if 169 * SO_REUSEPORT is set, or if SO_REUSEADDR is set 170 * and a multicast address is bound on both 171 * new and duplicated sockets. 172 */ 173 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) != 0) 174 reuseport = SO_REUSEADDR|SO_REUSEPORT; 175 /* 176 * XXX: How to deal with SO_REUSEPORT_LB here? 177 * Treat same as SO_REUSEPORT for now. 178 */ 179 if ((so->so_options & 180 (SO_REUSEADDR|SO_REUSEPORT_LB)) != 0) 181 reuseport_lb = SO_REUSEADDR|SO_REUSEPORT_LB; 182 } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 183 struct ifaddr *ifa; 184 185 sin6->sin6_port = 0; /* yech... */ 186 NET_EPOCH_ENTER(); 187 if ((ifa = ifa_ifwithaddr((struct sockaddr *)sin6)) == 188 NULL && 189 (inp->inp_flags & INP_BINDANY) == 0) { 190 NET_EPOCH_EXIT(); 191 return (EADDRNOTAVAIL); 192 } 193 194 /* 195 * XXX: bind to an anycast address might accidentally 196 * cause sending a packet with anycast source address. 197 * We should allow to bind to a deprecated address, since 198 * the application dares to use it. 199 */ 200 if (ifa != NULL && 201 ((struct in6_ifaddr *)ifa)->ia6_flags & 202 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) { 203 NET_EPOCH_EXIT(); 204 return (EADDRNOTAVAIL); 205 } 206 NET_EPOCH_EXIT(); 207 } 208 if (lport) { 209 struct inpcb *t; 210 struct tcptw *tw; 211 212 /* GROSS */ 213 if (ntohs(lport) <= V_ipport_reservedhigh && 214 ntohs(lport) >= V_ipport_reservedlow && 215 priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT)) 216 return (EACCES); 217 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) && 218 priv_check_cred(inp->inp_cred, PRIV_NETINET_REUSEPORT) != 0) { 219 t = in6_pcblookup_local(pcbinfo, 220 &sin6->sin6_addr, lport, 221 INPLOOKUP_WILDCARD, cred); 222 if (t && 223 ((inp->inp_flags2 & INP_BINDMULTI) == 0) && 224 ((t->inp_flags & INP_TIMEWAIT) == 0) && 225 (so->so_type != SOCK_STREAM || 226 IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) && 227 (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || 228 !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) || 229 (t->inp_flags2 & INP_REUSEPORT) || 230 (t->inp_flags2 & INP_REUSEPORT_LB) == 0) && 231 (inp->inp_cred->cr_uid != 232 t->inp_cred->cr_uid)) 233 return (EADDRINUSE); 234 235 /* 236 * If the socket is a BINDMULTI socket, then 237 * the credentials need to match and the 238 * original socket also has to have been bound 239 * with BINDMULTI. 240 */ 241 if (t && (! in_pcbbind_check_bindmulti(inp, t))) 242 return (EADDRINUSE); 243 244 #ifdef INET 245 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && 246 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 247 struct sockaddr_in sin; 248 249 in6_sin6_2_sin(&sin, sin6); 250 t = in_pcblookup_local(pcbinfo, 251 sin.sin_addr, lport, 252 INPLOOKUP_WILDCARD, cred); 253 if (t && 254 ((inp->inp_flags2 & INP_BINDMULTI) == 0) && 255 ((t->inp_flags & 256 INP_TIMEWAIT) == 0) && 257 (so->so_type != SOCK_STREAM || 258 ntohl(t->inp_faddr.s_addr) == 259 INADDR_ANY) && 260 (inp->inp_cred->cr_uid != 261 t->inp_cred->cr_uid)) 262 return (EADDRINUSE); 263 264 if (t && (! in_pcbbind_check_bindmulti(inp, t))) 265 return (EADDRINUSE); 266 } 267 #endif 268 } 269 t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr, 270 lport, lookupflags, cred); 271 if (t && (t->inp_flags & INP_TIMEWAIT)) { 272 /* 273 * XXXRW: If an incpb has had its timewait 274 * state recycled, we treat the address as 275 * being in use (for now). This is better 276 * than a panic, but not desirable. 277 */ 278 tw = intotw(t); 279 if (tw == NULL || 280 ((reuseport & tw->tw_so_options) == 0 && 281 (reuseport_lb & tw->tw_so_options) == 0)) 282 return (EADDRINUSE); 283 } else if (t && (reuseport & inp_so_options(t)) == 0 && 284 (reuseport_lb & inp_so_options(t)) == 0) { 285 return (EADDRINUSE); 286 } 287 #ifdef INET 288 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && 289 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 290 struct sockaddr_in sin; 291 292 in6_sin6_2_sin(&sin, sin6); 293 t = in_pcblookup_local(pcbinfo, sin.sin_addr, 294 lport, lookupflags, cred); 295 if (t && t->inp_flags & INP_TIMEWAIT) { 296 tw = intotw(t); 297 if (tw == NULL) 298 return (EADDRINUSE); 299 if ((reuseport & tw->tw_so_options) == 0 300 && (reuseport_lb & tw->tw_so_options) == 0 301 && (ntohl(t->inp_laddr.s_addr) != 302 INADDR_ANY || ((inp->inp_vflag & 303 INP_IPV6PROTO) == 304 (t->inp_vflag & INP_IPV6PROTO)))) 305 return (EADDRINUSE); 306 } else if (t && 307 (reuseport & inp_so_options(t)) == 0 && 308 (reuseport_lb & inp_so_options(t)) == 0 && 309 (ntohl(t->inp_laddr.s_addr) != INADDR_ANY || 310 (t->inp_vflag & INP_IPV6PROTO) != 0)) { 311 return (EADDRINUSE); 312 } 313 } 314 #endif 315 } 316 inp->in6p_laddr = sin6->sin6_addr; 317 } 318 if (lport == 0) { 319 if ((error = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0) { 320 /* Undo an address bind that may have occurred. */ 321 inp->in6p_laddr = in6addr_any; 322 return (error); 323 } 324 } else { 325 inp->inp_lport = lport; 326 if (in_pcbinshash(inp) != 0) { 327 inp->in6p_laddr = in6addr_any; 328 inp->inp_lport = 0; 329 return (EAGAIN); 330 } 331 } 332 return (0); 333 } 334 335 /* 336 * Transform old in6_pcbconnect() into an inner subroutine for new 337 * in6_pcbconnect(): Do some validity-checking on the remote 338 * address (in mbuf 'nam') and then determine local host address 339 * (i.e., which interface) to use to access that remote host. 340 * 341 * This preserves definition of in6_pcbconnect(), while supporting a 342 * slightly different version for T/TCP. (This is more than 343 * a bit of a kludge, but cleaning up the internal interfaces would 344 * have forced minor changes in every protocol). 345 */ 346 static int 347 in6_pcbladdr(struct inpcb *inp, struct sockaddr *nam, 348 struct in6_addr *plocal_addr6) 349 { 350 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; 351 int error = 0; 352 int scope_ambiguous = 0; 353 struct in6_addr in6a; 354 355 INP_WLOCK_ASSERT(inp); 356 INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); /* XXXRW: why? */ 357 358 if (nam->sa_len != sizeof (*sin6)) 359 return (EINVAL); 360 if (sin6->sin6_family != AF_INET6) 361 return (EAFNOSUPPORT); 362 if (sin6->sin6_port == 0) 363 return (EADDRNOTAVAIL); 364 365 if (sin6->sin6_scope_id == 0 && !V_ip6_use_defzone) 366 scope_ambiguous = 1; 367 if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) 368 return(error); 369 370 if (!CK_STAILQ_EMPTY(&V_in6_ifaddrhead)) { 371 /* 372 * If the destination address is UNSPECIFIED addr, 373 * use the loopback addr, e.g ::1. 374 */ 375 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 376 sin6->sin6_addr = in6addr_loopback; 377 } 378 if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0) 379 return (error); 380 381 error = in6_selectsrc_socket(sin6, inp->in6p_outputopts, 382 inp, inp->inp_cred, scope_ambiguous, &in6a, NULL); 383 if (error) 384 return (error); 385 386 /* 387 * Do not update this earlier, in case we return with an error. 388 * 389 * XXX: this in6_selectsrc_socket result might replace the bound local 390 * address with the address specified by setsockopt(IPV6_PKTINFO). 391 * Is it the intended behavior? 392 */ 393 *plocal_addr6 = in6a; 394 395 /* 396 * Don't do pcblookup call here; return interface in 397 * plocal_addr6 398 * and exit to caller, that will do the lookup. 399 */ 400 401 return (0); 402 } 403 404 /* 405 * Outer subroutine: 406 * Connect from a socket to a specified address. 407 * Both address and port must be specified in argument sin. 408 * If don't have a local address for this socket yet, 409 * then pick one. 410 */ 411 int 412 in6_pcbconnect_mbuf(struct inpcb *inp, struct sockaddr *nam, 413 struct ucred *cred, struct mbuf *m) 414 { 415 struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 416 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; 417 struct in6_addr addr6; 418 int error; 419 420 INP_WLOCK_ASSERT(inp); 421 INP_HASH_WLOCK_ASSERT(pcbinfo); 422 423 /* 424 * Call inner routine, to assign local interface address. 425 * in6_pcbladdr() may automatically fill in sin6_scope_id. 426 */ 427 if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0) 428 return (error); 429 430 if (in6_pcblookup_hash_locked(pcbinfo, &sin6->sin6_addr, 431 sin6->sin6_port, 432 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) 433 ? &addr6 : &inp->in6p_laddr, 434 inp->inp_lport, 0, NULL) != NULL) { 435 return (EADDRINUSE); 436 } 437 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { 438 if (inp->inp_lport == 0) { 439 error = in6_pcbbind(inp, (struct sockaddr *)0, cred); 440 if (error) 441 return (error); 442 } 443 inp->in6p_laddr = addr6; 444 } 445 inp->in6p_faddr = sin6->sin6_addr; 446 inp->inp_fport = sin6->sin6_port; 447 /* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */ 448 inp->inp_flow &= ~IPV6_FLOWLABEL_MASK; 449 if (inp->inp_flags & IN6P_AUTOFLOWLABEL) 450 inp->inp_flow |= 451 (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK); 452 453 in_pcbrehash_mbuf(inp, m); 454 455 return (0); 456 } 457 458 int 459 in6_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred) 460 { 461 462 return (in6_pcbconnect_mbuf(inp, nam, cred, NULL)); 463 } 464 465 void 466 in6_pcbdisconnect(struct inpcb *inp) 467 { 468 469 INP_WLOCK_ASSERT(inp); 470 INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); 471 472 bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr)); 473 inp->inp_fport = 0; 474 /* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */ 475 inp->inp_flow &= ~IPV6_FLOWLABEL_MASK; 476 in_pcbrehash(inp); 477 } 478 479 struct sockaddr * 480 in6_sockaddr(in_port_t port, struct in6_addr *addr_p) 481 { 482 struct sockaddr_in6 *sin6; 483 484 sin6 = malloc(sizeof *sin6, M_SONAME, M_WAITOK); 485 bzero(sin6, sizeof *sin6); 486 sin6->sin6_family = AF_INET6; 487 sin6->sin6_len = sizeof(*sin6); 488 sin6->sin6_port = port; 489 sin6->sin6_addr = *addr_p; 490 (void)sa6_recoverscope(sin6); /* XXX: should catch errors */ 491 492 return (struct sockaddr *)sin6; 493 } 494 495 struct sockaddr * 496 in6_v4mapsin6_sockaddr(in_port_t port, struct in_addr *addr_p) 497 { 498 struct sockaddr_in sin; 499 struct sockaddr_in6 *sin6_p; 500 501 bzero(&sin, sizeof sin); 502 sin.sin_family = AF_INET; 503 sin.sin_len = sizeof(sin); 504 sin.sin_port = port; 505 sin.sin_addr = *addr_p; 506 507 sin6_p = malloc(sizeof *sin6_p, M_SONAME, 508 M_WAITOK); 509 in6_sin_2_v4mapsin6(&sin, sin6_p); 510 511 return (struct sockaddr *)sin6_p; 512 } 513 514 int 515 in6_getsockaddr(struct socket *so, struct sockaddr **nam) 516 { 517 struct inpcb *inp; 518 struct in6_addr addr; 519 in_port_t port; 520 521 inp = sotoinpcb(so); 522 KASSERT(inp != NULL, ("in6_getsockaddr: inp == NULL")); 523 524 INP_RLOCK(inp); 525 port = inp->inp_lport; 526 addr = inp->in6p_laddr; 527 INP_RUNLOCK(inp); 528 529 *nam = in6_sockaddr(port, &addr); 530 return 0; 531 } 532 533 int 534 in6_getpeeraddr(struct socket *so, struct sockaddr **nam) 535 { 536 struct inpcb *inp; 537 struct in6_addr addr; 538 in_port_t port; 539 540 inp = sotoinpcb(so); 541 KASSERT(inp != NULL, ("in6_getpeeraddr: inp == NULL")); 542 543 INP_RLOCK(inp); 544 port = inp->inp_fport; 545 addr = inp->in6p_faddr; 546 INP_RUNLOCK(inp); 547 548 *nam = in6_sockaddr(port, &addr); 549 return 0; 550 } 551 552 int 553 in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam) 554 { 555 struct inpcb *inp; 556 int error; 557 558 inp = sotoinpcb(so); 559 KASSERT(inp != NULL, ("in6_mapped_sockaddr: inp == NULL")); 560 561 #ifdef INET 562 if ((inp->inp_vflag & (INP_IPV4 | INP_IPV6)) == INP_IPV4) { 563 error = in_getsockaddr(so, nam); 564 if (error == 0) 565 in6_sin_2_v4mapsin6_in_sock(nam); 566 } else 567 #endif 568 { 569 /* scope issues will be handled in in6_getsockaddr(). */ 570 error = in6_getsockaddr(so, nam); 571 } 572 573 return error; 574 } 575 576 int 577 in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam) 578 { 579 struct inpcb *inp; 580 int error; 581 582 inp = sotoinpcb(so); 583 KASSERT(inp != NULL, ("in6_mapped_peeraddr: inp == NULL")); 584 585 #ifdef INET 586 if ((inp->inp_vflag & (INP_IPV4 | INP_IPV6)) == INP_IPV4) { 587 error = in_getpeeraddr(so, nam); 588 if (error == 0) 589 in6_sin_2_v4mapsin6_in_sock(nam); 590 } else 591 #endif 592 /* scope issues will be handled in in6_getpeeraddr(). */ 593 error = in6_getpeeraddr(so, nam); 594 595 return error; 596 } 597 598 /* 599 * Pass some notification to all connections of a protocol 600 * associated with address dst. The local address and/or port numbers 601 * may be specified to limit the search. The "usual action" will be 602 * taken, depending on the ctlinput cmd. The caller must filter any 603 * cmds that are uninteresting (e.g., no error in the map). 604 * Call the protocol specific routine (if any) to report 605 * any errors for each matching socket. 606 */ 607 void 608 in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr *dst, 609 u_int fport_arg, const struct sockaddr *src, u_int lport_arg, 610 int cmd, void *cmdarg, 611 struct inpcb *(*notify)(struct inpcb *, int)) 612 { 613 struct inpcb *inp, *inp_temp; 614 struct sockaddr_in6 sa6_src, *sa6_dst; 615 u_short fport = fport_arg, lport = lport_arg; 616 u_int32_t flowinfo; 617 int errno; 618 619 if ((unsigned)cmd >= PRC_NCMDS || dst->sa_family != AF_INET6) 620 return; 621 622 sa6_dst = (struct sockaddr_in6 *)dst; 623 if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr)) 624 return; 625 626 /* 627 * note that src can be NULL when we get notify by local fragmentation. 628 */ 629 sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src; 630 flowinfo = sa6_src.sin6_flowinfo; 631 632 /* 633 * Redirects go to all references to the destination, 634 * and use in6_rtchange to invalidate the route cache. 635 * Dead host indications: also use in6_rtchange to invalidate 636 * the cache, and deliver the error to all the sockets. 637 * Otherwise, if we have knowledge of the local port and address, 638 * deliver only to that socket. 639 */ 640 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { 641 fport = 0; 642 lport = 0; 643 bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr)); 644 645 if (cmd != PRC_HOSTDEAD) 646 notify = in6_rtchange; 647 } 648 errno = inet6ctlerrmap[cmd]; 649 INP_INFO_WLOCK(pcbinfo); 650 CK_LIST_FOREACH_SAFE(inp, pcbinfo->ipi_listhead, inp_list, inp_temp) { 651 INP_WLOCK(inp); 652 if ((inp->inp_vflag & INP_IPV6) == 0) { 653 INP_WUNLOCK(inp); 654 continue; 655 } 656 657 /* 658 * If the error designates a new path MTU for a destination 659 * and the application (associated with this socket) wanted to 660 * know the value, notify. 661 * XXX: should we avoid to notify the value to TCP sockets? 662 */ 663 if (cmd == PRC_MSGSIZE && cmdarg != NULL) 664 ip6_notify_pmtu(inp, (struct sockaddr_in6 *)dst, 665 *(u_int32_t *)cmdarg); 666 667 /* 668 * Detect if we should notify the error. If no source and 669 * destination ports are specifed, but non-zero flowinfo and 670 * local address match, notify the error. This is the case 671 * when the error is delivered with an encrypted buffer 672 * by ESP. Otherwise, just compare addresses and ports 673 * as usual. 674 */ 675 if (lport == 0 && fport == 0 && flowinfo && 676 inp->inp_socket != NULL && 677 flowinfo == (inp->inp_flow & IPV6_FLOWLABEL_MASK) && 678 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr)) 679 goto do_notify; 680 else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, 681 &sa6_dst->sin6_addr) || 682 inp->inp_socket == 0 || 683 (lport && inp->inp_lport != lport) || 684 (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) && 685 !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, 686 &sa6_src.sin6_addr)) || 687 (fport && inp->inp_fport != fport)) { 688 INP_WUNLOCK(inp); 689 continue; 690 } 691 692 do_notify: 693 if (notify) { 694 if ((*notify)(inp, errno)) 695 INP_WUNLOCK(inp); 696 } else 697 INP_WUNLOCK(inp); 698 } 699 INP_INFO_WUNLOCK(pcbinfo); 700 } 701 702 /* 703 * Lookup a PCB based on the local address and port. Caller must hold the 704 * hash lock. No inpcb locks or references are acquired. 705 */ 706 struct inpcb * 707 in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr, 708 u_short lport, int lookupflags, struct ucred *cred) 709 { 710 struct inpcb *inp; 711 int matchwild = 3, wildcard; 712 713 KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0, 714 ("%s: invalid lookup flags %d", __func__, lookupflags)); 715 716 INP_HASH_WLOCK_ASSERT(pcbinfo); 717 718 if ((lookupflags & INPLOOKUP_WILDCARD) == 0) { 719 struct inpcbhead *head; 720 /* 721 * Look for an unconnected (wildcard foreign addr) PCB that 722 * matches the local address and port we're looking for. 723 */ 724 head = &pcbinfo->ipi_hashbase[INP_PCBHASH( 725 INP6_PCBHASHKEY(&in6addr_any), lport, 0, 726 pcbinfo->ipi_hashmask)]; 727 CK_LIST_FOREACH(inp, head, inp_hash) { 728 /* XXX inp locking */ 729 if ((inp->inp_vflag & INP_IPV6) == 0) 730 continue; 731 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) && 732 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) && 733 inp->inp_lport == lport) { 734 /* Found. */ 735 if (cred == NULL || 736 prison_equal_ip6(cred->cr_prison, 737 inp->inp_cred->cr_prison)) 738 return (inp); 739 } 740 } 741 /* 742 * Not found. 743 */ 744 return (NULL); 745 } else { 746 struct inpcbporthead *porthash; 747 struct inpcbport *phd; 748 struct inpcb *match = NULL; 749 /* 750 * Best fit PCB lookup. 751 * 752 * First see if this local port is in use by looking on the 753 * port hash list. 754 */ 755 porthash = &pcbinfo->ipi_porthashbase[INP_PCBPORTHASH(lport, 756 pcbinfo->ipi_porthashmask)]; 757 CK_LIST_FOREACH(phd, porthash, phd_hash) { 758 if (phd->phd_port == lport) 759 break; 760 } 761 if (phd != NULL) { 762 /* 763 * Port is in use by one or more PCBs. Look for best 764 * fit. 765 */ 766 CK_LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) { 767 wildcard = 0; 768 if (cred != NULL && 769 !prison_equal_ip6(cred->cr_prison, 770 inp->inp_cred->cr_prison)) 771 continue; 772 /* XXX inp locking */ 773 if ((inp->inp_vflag & INP_IPV6) == 0) 774 continue; 775 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) 776 wildcard++; 777 if (!IN6_IS_ADDR_UNSPECIFIED( 778 &inp->in6p_laddr)) { 779 if (IN6_IS_ADDR_UNSPECIFIED(laddr)) 780 wildcard++; 781 else if (!IN6_ARE_ADDR_EQUAL( 782 &inp->in6p_laddr, laddr)) 783 continue; 784 } else { 785 if (!IN6_IS_ADDR_UNSPECIFIED(laddr)) 786 wildcard++; 787 } 788 if (wildcard < matchwild) { 789 match = inp; 790 matchwild = wildcard; 791 if (matchwild == 0) 792 break; 793 } 794 } 795 } 796 return (match); 797 } 798 } 799 800 void 801 in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp) 802 { 803 struct inpcb *in6p; 804 struct ip6_moptions *im6o; 805 int i, gap; 806 807 INP_INFO_WLOCK(pcbinfo); 808 CK_LIST_FOREACH(in6p, pcbinfo->ipi_listhead, inp_list) { 809 INP_WLOCK(in6p); 810 if (__predict_false(in6p->inp_flags2 & INP_FREED)) { 811 INP_WUNLOCK(in6p); 812 continue; 813 } 814 im6o = in6p->in6p_moptions; 815 if ((in6p->inp_vflag & INP_IPV6) && im6o != NULL) { 816 /* 817 * Unselect the outgoing ifp for multicast if it 818 * is being detached. 819 */ 820 if (im6o->im6o_multicast_ifp == ifp) 821 im6o->im6o_multicast_ifp = NULL; 822 /* 823 * Drop multicast group membership if we joined 824 * through the interface being detached. 825 */ 826 gap = 0; 827 for (i = 0; i < im6o->im6o_num_memberships; i++) { 828 if (im6o->im6o_membership[i]->in6m_ifp == 829 ifp) { 830 in6_leavegroup(im6o->im6o_membership[i], NULL); 831 gap++; 832 } else if (gap != 0) { 833 im6o->im6o_membership[i - gap] = 834 im6o->im6o_membership[i]; 835 } 836 } 837 im6o->im6o_num_memberships -= gap; 838 } 839 INP_WUNLOCK(in6p); 840 } 841 INP_INFO_WUNLOCK(pcbinfo); 842 } 843 844 /* 845 * Check for alternatives when higher level complains 846 * about service problems. For now, invalidate cached 847 * routing information. If the route was created dynamically 848 * (by a redirect), time to try a default gateway again. 849 */ 850 void 851 in6_losing(struct inpcb *inp) 852 { 853 854 RO_INVALIDATE_CACHE(&inp->inp_route6); 855 } 856 857 /* 858 * After a routing change, flush old routing 859 * and allocate a (hopefully) better one. 860 */ 861 struct inpcb * 862 in6_rtchange(struct inpcb *inp, int errno __unused) 863 { 864 865 RO_INVALIDATE_CACHE(&inp->inp_route6); 866 return inp; 867 } 868 869 static struct inpcb * 870 in6_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo, 871 const struct in6_addr *laddr, uint16_t lport, const struct in6_addr *faddr, 872 uint16_t fport, int lookupflags) 873 { 874 struct inpcb *local_wild; 875 const struct inpcblbgrouphead *hdr; 876 struct inpcblbgroup *grp; 877 uint32_t idx; 878 879 INP_HASH_LOCK_ASSERT(pcbinfo); 880 881 hdr = &pcbinfo->ipi_lbgrouphashbase[ 882 INP_PCBPORTHASH(lport, pcbinfo->ipi_lbgrouphashmask)]; 883 884 /* 885 * Order of socket selection: 886 * 1. non-wild. 887 * 2. wild (if lookupflags contains INPLOOKUP_WILDCARD). 888 * 889 * NOTE: 890 * - Load balanced group does not contain jailed sockets. 891 * - Load balanced does not contain IPv4 mapped INET6 wild sockets. 892 */ 893 local_wild = NULL; 894 CK_LIST_FOREACH(grp, hdr, il_list) { 895 #ifdef INET 896 if (!(grp->il_vflag & INP_IPV6)) 897 continue; 898 #endif 899 if (grp->il_lport != lport) 900 continue; 901 902 idx = INP_PCBLBGROUP_PKTHASH(INP6_PCBHASHKEY(faddr), lport, 903 fport) % grp->il_inpcnt; 904 if (IN6_ARE_ADDR_EQUAL(&grp->il6_laddr, laddr)) 905 return (grp->il_inp[idx]); 906 if (IN6_IS_ADDR_UNSPECIFIED(&grp->il6_laddr) && 907 (lookupflags & INPLOOKUP_WILDCARD) != 0) 908 local_wild = grp->il_inp[idx]; 909 } 910 return (local_wild); 911 } 912 913 #ifdef PCBGROUP 914 /* 915 * Lookup PCB in hash list, using pcbgroup tables. 916 */ 917 static struct inpcb * 918 in6_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup, 919 struct in6_addr *faddr, u_int fport_arg, struct in6_addr *laddr, 920 u_int lport_arg, int lookupflags, struct ifnet *ifp) 921 { 922 struct inpcbhead *head; 923 struct inpcb *inp, *tmpinp; 924 u_short fport = fport_arg, lport = lport_arg; 925 bool locked; 926 927 /* 928 * First look for an exact match. 929 */ 930 tmpinp = NULL; 931 INP_GROUP_LOCK(pcbgroup); 932 head = &pcbgroup->ipg_hashbase[INP_PCBHASH( 933 INP6_PCBHASHKEY(faddr), lport, fport, pcbgroup->ipg_hashmask)]; 934 CK_LIST_FOREACH(inp, head, inp_pcbgrouphash) { 935 /* XXX inp locking */ 936 if ((inp->inp_vflag & INP_IPV6) == 0) 937 continue; 938 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) && 939 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) && 940 inp->inp_fport == fport && 941 inp->inp_lport == lport) { 942 /* 943 * XXX We should be able to directly return 944 * the inp here, without any checks. 945 * Well unless both bound with SO_REUSEPORT? 946 */ 947 if (prison_flag(inp->inp_cred, PR_IP6)) 948 goto found; 949 if (tmpinp == NULL) 950 tmpinp = inp; 951 } 952 } 953 if (tmpinp != NULL) { 954 inp = tmpinp; 955 goto found; 956 } 957 958 /* 959 * Then look for a wildcard match in the pcbgroup. 960 */ 961 if ((lookupflags & INPLOOKUP_WILDCARD) != 0) { 962 struct inpcb *local_wild = NULL, *local_exact = NULL; 963 struct inpcb *jail_wild = NULL; 964 int injail; 965 966 /* 967 * Order of socket selection - we always prefer jails. 968 * 1. jailed, non-wild. 969 * 2. jailed, wild. 970 * 3. non-jailed, non-wild. 971 * 4. non-jailed, wild. 972 */ 973 head = &pcbgroup->ipg_hashbase[ 974 INP_PCBHASH(INADDR_ANY, lport, 0, pcbgroup->ipg_hashmask)]; 975 CK_LIST_FOREACH(inp, head, inp_pcbgrouphash) { 976 /* XXX inp locking */ 977 if ((inp->inp_vflag & INP_IPV6) == 0) 978 continue; 979 980 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) || 981 inp->inp_lport != lport) { 982 continue; 983 } 984 985 injail = prison_flag(inp->inp_cred, PR_IP6); 986 if (injail) { 987 if (prison_check_ip6(inp->inp_cred, 988 laddr) != 0) 989 continue; 990 } else { 991 if (local_exact != NULL) 992 continue; 993 } 994 995 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr)) { 996 if (injail) 997 goto found; 998 else 999 local_exact = inp; 1000 } else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { 1001 if (injail) 1002 jail_wild = inp; 1003 else 1004 local_wild = inp; 1005 } 1006 } /* LIST_FOREACH */ 1007 1008 inp = jail_wild; 1009 if (inp == NULL) 1010 inp = jail_wild; 1011 if (inp == NULL) 1012 inp = local_exact; 1013 if (inp == NULL) 1014 inp = local_wild; 1015 if (inp != NULL) 1016 goto found; 1017 } 1018 1019 /* 1020 * Then look for a wildcard match, if requested. 1021 */ 1022 if ((lookupflags & INPLOOKUP_WILDCARD) != 0) { 1023 struct inpcb *local_wild = NULL, *local_exact = NULL; 1024 struct inpcb *jail_wild = NULL; 1025 int injail; 1026 1027 /* 1028 * Order of socket selection - we always prefer jails. 1029 * 1. jailed, non-wild. 1030 * 2. jailed, wild. 1031 * 3. non-jailed, non-wild. 1032 * 4. non-jailed, wild. 1033 */ 1034 head = &pcbinfo->ipi_wildbase[INP_PCBHASH( 1035 INP6_PCBHASHKEY(&in6addr_any), lport, 0, 1036 pcbinfo->ipi_wildmask)]; 1037 CK_LIST_FOREACH(inp, head, inp_pcbgroup_wild) { 1038 /* XXX inp locking */ 1039 if ((inp->inp_vflag & INP_IPV6) == 0) 1040 continue; 1041 1042 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) || 1043 inp->inp_lport != lport) { 1044 continue; 1045 } 1046 1047 injail = prison_flag(inp->inp_cred, PR_IP6); 1048 if (injail) { 1049 if (prison_check_ip6(inp->inp_cred, 1050 laddr) != 0) 1051 continue; 1052 } else { 1053 if (local_exact != NULL) 1054 continue; 1055 } 1056 1057 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr)) { 1058 if (injail) 1059 goto found; 1060 else 1061 local_exact = inp; 1062 } else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { 1063 if (injail) 1064 jail_wild = inp; 1065 else 1066 local_wild = inp; 1067 } 1068 } /* LIST_FOREACH */ 1069 1070 inp = jail_wild; 1071 if (inp == NULL) 1072 inp = jail_wild; 1073 if (inp == NULL) 1074 inp = local_exact; 1075 if (inp == NULL) 1076 inp = local_wild; 1077 if (inp != NULL) 1078 goto found; 1079 } /* if ((lookupflags & INPLOOKUP_WILDCARD) != 0) */ 1080 INP_GROUP_UNLOCK(pcbgroup); 1081 return (NULL); 1082 1083 found: 1084 if (lookupflags & INPLOOKUP_WLOCKPCB) 1085 locked = INP_TRY_WLOCK(inp); 1086 else if (lookupflags & INPLOOKUP_RLOCKPCB) 1087 locked = INP_TRY_RLOCK(inp); 1088 else 1089 panic("%s: locking buf", __func__); 1090 if (!locked) 1091 in_pcbref(inp); 1092 INP_GROUP_UNLOCK(pcbgroup); 1093 if (!locked) { 1094 if (lookupflags & INPLOOKUP_WLOCKPCB) { 1095 INP_WLOCK(inp); 1096 if (in_pcbrele_wlocked(inp)) 1097 return (NULL); 1098 } else { 1099 INP_RLOCK(inp); 1100 if (in_pcbrele_rlocked(inp)) 1101 return (NULL); 1102 } 1103 } 1104 #ifdef INVARIANTS 1105 if (lookupflags & INPLOOKUP_WLOCKPCB) 1106 INP_WLOCK_ASSERT(inp); 1107 else 1108 INP_RLOCK_ASSERT(inp); 1109 #endif 1110 return (inp); 1111 } 1112 #endif /* PCBGROUP */ 1113 1114 /* 1115 * Lookup PCB in hash list. 1116 */ 1117 static struct inpcb * 1118 in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, 1119 u_int fport_arg, struct in6_addr *laddr, u_int lport_arg, 1120 int lookupflags, struct ifnet *ifp) 1121 { 1122 struct inpcbhead *head; 1123 struct inpcb *inp, *tmpinp; 1124 u_short fport = fport_arg, lport = lport_arg; 1125 1126 KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0, 1127 ("%s: invalid lookup flags %d", __func__, lookupflags)); 1128 1129 INP_HASH_LOCK_ASSERT(pcbinfo); 1130 1131 /* 1132 * First look for an exact match. 1133 */ 1134 tmpinp = NULL; 1135 head = &pcbinfo->ipi_hashbase[INP_PCBHASH( 1136 INP6_PCBHASHKEY(faddr), lport, fport, pcbinfo->ipi_hashmask)]; 1137 CK_LIST_FOREACH(inp, head, inp_hash) { 1138 /* XXX inp locking */ 1139 if ((inp->inp_vflag & INP_IPV6) == 0) 1140 continue; 1141 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) && 1142 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) && 1143 inp->inp_fport == fport && 1144 inp->inp_lport == lport) { 1145 /* 1146 * XXX We should be able to directly return 1147 * the inp here, without any checks. 1148 * Well unless both bound with SO_REUSEPORT? 1149 */ 1150 if (prison_flag(inp->inp_cred, PR_IP6)) 1151 return (inp); 1152 if (tmpinp == NULL) 1153 tmpinp = inp; 1154 } 1155 } 1156 if (tmpinp != NULL) 1157 return (tmpinp); 1158 1159 /* 1160 * Then look in lb group (for wildcard match). 1161 */ 1162 if ((lookupflags & INPLOOKUP_WILDCARD) != 0) { 1163 inp = in6_pcblookup_lbgroup(pcbinfo, laddr, lport, faddr, 1164 fport, lookupflags); 1165 if (inp != NULL) 1166 return (inp); 1167 } 1168 1169 /* 1170 * Then look for a wildcard match, if requested. 1171 */ 1172 if ((lookupflags & INPLOOKUP_WILDCARD) != 0) { 1173 struct inpcb *local_wild = NULL, *local_exact = NULL; 1174 struct inpcb *jail_wild = NULL; 1175 int injail; 1176 1177 /* 1178 * Order of socket selection - we always prefer jails. 1179 * 1. jailed, non-wild. 1180 * 2. jailed, wild. 1181 * 3. non-jailed, non-wild. 1182 * 4. non-jailed, wild. 1183 */ 1184 head = &pcbinfo->ipi_hashbase[INP_PCBHASH( 1185 INP6_PCBHASHKEY(&in6addr_any), lport, 0, 1186 pcbinfo->ipi_hashmask)]; 1187 CK_LIST_FOREACH(inp, head, inp_hash) { 1188 /* XXX inp locking */ 1189 if ((inp->inp_vflag & INP_IPV6) == 0) 1190 continue; 1191 1192 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) || 1193 inp->inp_lport != lport) { 1194 continue; 1195 } 1196 1197 injail = prison_flag(inp->inp_cred, PR_IP6); 1198 if (injail) { 1199 if (prison_check_ip6(inp->inp_cred, 1200 laddr) != 0) 1201 continue; 1202 } else { 1203 if (local_exact != NULL) 1204 continue; 1205 } 1206 1207 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr)) { 1208 if (injail) 1209 return (inp); 1210 else 1211 local_exact = inp; 1212 } else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { 1213 if (injail) 1214 jail_wild = inp; 1215 else 1216 local_wild = inp; 1217 } 1218 } /* LIST_FOREACH */ 1219 1220 if (jail_wild != NULL) 1221 return (jail_wild); 1222 if (local_exact != NULL) 1223 return (local_exact); 1224 if (local_wild != NULL) 1225 return (local_wild); 1226 } /* if ((lookupflags & INPLOOKUP_WILDCARD) != 0) */ 1227 1228 /* 1229 * Not found. 1230 */ 1231 return (NULL); 1232 } 1233 1234 /* 1235 * Lookup PCB in hash list, using pcbinfo tables. This variation locks the 1236 * hash list lock, and will return the inpcb locked (i.e., requires 1237 * INPLOOKUP_LOCKPCB). 1238 */ 1239 static struct inpcb * 1240 in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, 1241 u_int fport, struct in6_addr *laddr, u_int lport, int lookupflags, 1242 struct ifnet *ifp) 1243 { 1244 struct inpcb *inp; 1245 1246 INP_HASH_RLOCK(pcbinfo); 1247 inp = in6_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport, 1248 (lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp); 1249 if (inp != NULL) { 1250 if (lookupflags & INPLOOKUP_WLOCKPCB) { 1251 INP_WLOCK(inp); 1252 if (__predict_false(inp->inp_flags2 & INP_FREED)) { 1253 INP_WUNLOCK(inp); 1254 inp = NULL; 1255 } 1256 } else if (lookupflags & INPLOOKUP_RLOCKPCB) { 1257 INP_RLOCK(inp); 1258 if (__predict_false(inp->inp_flags2 & INP_FREED)) { 1259 INP_RUNLOCK(inp); 1260 inp = NULL; 1261 } 1262 } else 1263 panic("%s: locking bug", __func__); 1264 #ifdef INVARIANTS 1265 if (inp != NULL) { 1266 if (lookupflags & INPLOOKUP_WLOCKPCB) 1267 INP_WLOCK_ASSERT(inp); 1268 else 1269 INP_RLOCK_ASSERT(inp); 1270 } 1271 #endif 1272 } 1273 INP_HASH_RUNLOCK(pcbinfo); 1274 return (inp); 1275 } 1276 1277 /* 1278 * Public inpcb lookup routines, accepting a 4-tuple, and optionally, an mbuf 1279 * from which a pre-calculated hash value may be extracted. 1280 * 1281 * Possibly more of this logic should be in in6_pcbgroup.c. 1282 */ 1283 struct inpcb * 1284 in6_pcblookup(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, u_int fport, 1285 struct in6_addr *laddr, u_int lport, int lookupflags, struct ifnet *ifp) 1286 { 1287 #if defined(PCBGROUP) && !defined(RSS) 1288 struct inpcbgroup *pcbgroup; 1289 #endif 1290 1291 KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0, 1292 ("%s: invalid lookup flags %d", __func__, lookupflags)); 1293 KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0, 1294 ("%s: LOCKPCB not set", __func__)); 1295 1296 /* 1297 * When not using RSS, use connection groups in preference to the 1298 * reservation table when looking up 4-tuples. When using RSS, just 1299 * use the reservation table, due to the cost of the Toeplitz hash 1300 * in software. 1301 * 1302 * XXXRW: This policy belongs in the pcbgroup code, as in principle 1303 * we could be doing RSS with a non-Toeplitz hash that is affordable 1304 * in software. 1305 */ 1306 #if defined(PCBGROUP) && !defined(RSS) 1307 if (in_pcbgroup_enabled(pcbinfo)) { 1308 pcbgroup = in6_pcbgroup_bytuple(pcbinfo, laddr, lport, faddr, 1309 fport); 1310 return (in6_pcblookup_group(pcbinfo, pcbgroup, faddr, fport, 1311 laddr, lport, lookupflags, ifp)); 1312 } 1313 #endif 1314 return (in6_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport, 1315 lookupflags, ifp)); 1316 } 1317 1318 struct inpcb * 1319 in6_pcblookup_mbuf(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, 1320 u_int fport, struct in6_addr *laddr, u_int lport, int lookupflags, 1321 struct ifnet *ifp, struct mbuf *m) 1322 { 1323 #ifdef PCBGROUP 1324 struct inpcbgroup *pcbgroup; 1325 #endif 1326 1327 KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0, 1328 ("%s: invalid lookup flags %d", __func__, lookupflags)); 1329 KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0, 1330 ("%s: LOCKPCB not set", __func__)); 1331 1332 #ifdef PCBGROUP 1333 /* 1334 * If we can use a hardware-generated hash to look up the connection 1335 * group, use that connection group to find the inpcb. Otherwise 1336 * fall back on a software hash -- or the reservation table if we're 1337 * using RSS. 1338 * 1339 * XXXRW: As above, that policy belongs in the pcbgroup code. 1340 */ 1341 if (in_pcbgroup_enabled(pcbinfo) && 1342 M_HASHTYPE_TEST(m, M_HASHTYPE_NONE) == 0) { 1343 pcbgroup = in6_pcbgroup_byhash(pcbinfo, M_HASHTYPE_GET(m), 1344 m->m_pkthdr.flowid); 1345 if (pcbgroup != NULL) 1346 return (in6_pcblookup_group(pcbinfo, pcbgroup, faddr, 1347 fport, laddr, lport, lookupflags, ifp)); 1348 #ifndef RSS 1349 pcbgroup = in6_pcbgroup_bytuple(pcbinfo, laddr, lport, faddr, 1350 fport); 1351 return (in6_pcblookup_group(pcbinfo, pcbgroup, faddr, fport, 1352 laddr, lport, lookupflags, ifp)); 1353 #endif 1354 } 1355 #endif 1356 return (in6_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport, 1357 lookupflags, ifp)); 1358 } 1359 1360 void 1361 init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m, int srcordst) 1362 { 1363 struct ip6_hdr *ip; 1364 1365 ip = mtod(m, struct ip6_hdr *); 1366 bzero(sin6, sizeof(*sin6)); 1367 sin6->sin6_len = sizeof(*sin6); 1368 sin6->sin6_family = AF_INET6; 1369 sin6->sin6_addr = srcordst ? ip->ip6_dst : ip->ip6_src; 1370 1371 (void)sa6_recoverscope(sin6); /* XXX: should catch errors... */ 1372 1373 return; 1374 } 1375