1 /* $OpenBSD: in_pcb.c,v 1.208 2016/06/30 12:36:27 mpi Exp $ */ 2 /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1991, 1993 6 * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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 * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 33 * 34 * NRL grants permission for redistribution and use in source and binary 35 * forms, with or without modification, of the software and documentation 36 * created at NRL provided that the following conditions are met: 37 * 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. All advertising materials mentioning features or use of this software 44 * must display the following acknowledgements: 45 * This product includes software developed by the University of 46 * California, Berkeley and its contributors. 47 * This product includes software developed at the Information 48 * Technology Division, US Naval Research Laboratory. 49 * 4. Neither the name of the NRL nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS 54 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 56 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR 57 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 58 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 59 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 60 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 61 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 62 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 63 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 * 65 * The views and conclusions contained in the software and documentation 66 * are those of the authors and should not be interpreted as representing 67 * official policies, either expressed or implied, of the US Naval 68 * Research Laboratory (NRL). 69 */ 70 71 #include "pf.h" 72 73 #include <sys/param.h> 74 #include <sys/systm.h> 75 #include <sys/mbuf.h> 76 #include <sys/protosw.h> 77 #include <sys/socket.h> 78 #include <sys/socketvar.h> 79 #include <sys/proc.h> 80 #include <sys/pledge.h> 81 #include <sys/domain.h> 82 #include <sys/pool.h> 83 84 #include <net/if.h> 85 #include <net/if_var.h> 86 #include <net/route.h> 87 88 #include <netinet/in.h> 89 #include <netinet/ip.h> 90 #include <netinet/in_pcb.h> 91 #include <netinet/in_var.h> 92 #include <netinet/ip_var.h> 93 94 #include <net/pfvar.h> 95 96 #include <sys/mount.h> 97 #include <nfs/nfsproto.h> 98 99 #ifdef INET6 100 #include <netinet6/in6_var.h> 101 #include <netinet6/ip6_var.h> 102 #endif /* INET6 */ 103 #ifdef IPSEC 104 #include <netinet/ip_esp.h> 105 #endif /* IPSEC */ 106 107 struct in_addr zeroin_addr; 108 109 union { 110 struct in_addr za_in; 111 struct in6_addr za_in6; 112 } zeroin46_addr; 113 114 /* 115 * These configure the range of local port addresses assigned to 116 * "unspecified" outgoing connections/packets/whatever. 117 */ 118 int ipport_firstauto = IPPORT_RESERVED; 119 int ipport_lastauto = IPPORT_USERRESERVED; 120 int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; 121 int ipport_hilastauto = IPPORT_HILASTAUTO; 122 123 struct baddynamicports baddynamicports; 124 struct baddynamicports rootonlyports; 125 struct pool inpcb_pool; 126 int inpcb_pool_initialized = 0; 127 128 int in_pcbresize (struct inpcbtable *, int); 129 130 #define INPCBHASH_LOADFACTOR(_x) (((_x) * 3) / 4) 131 132 struct inpcbhead *in_pcbhash(struct inpcbtable *, int, 133 const struct in_addr *, u_short, const struct in_addr *, u_short); 134 struct inpcbhead *in6_pcbhash(struct inpcbtable *, int, 135 const struct in6_addr *, u_short, const struct in6_addr *, u_short); 136 struct inpcbhead *in_pcblhash(struct inpcbtable *, int, u_short); 137 138 struct inpcbhead * 139 in_pcbhash(struct inpcbtable *table, int rdom, 140 const struct in_addr *faddr, u_short fport, 141 const struct in_addr *laddr, u_short lport) 142 { 143 SIPHASH_CTX ctx; 144 u_int32_t nrdom = htonl(rdom); 145 146 SipHash24_Init(&ctx, &table->inpt_key); 147 SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); 148 SipHash24_Update(&ctx, faddr, sizeof(*faddr)); 149 SipHash24_Update(&ctx, &fport, sizeof(fport)); 150 SipHash24_Update(&ctx, laddr, sizeof(*laddr)); 151 SipHash24_Update(&ctx, &lport, sizeof(lport)); 152 153 return (&table->inpt_hashtbl[SipHash24_End(&ctx) & table->inpt_hash]); 154 } 155 156 #define INPCBHASH(table, faddr, fport, laddr, lport, rdom) \ 157 in_pcbhash(table, rdom, faddr, fport, laddr, lport) 158 159 struct inpcbhead * 160 in6_pcbhash(struct inpcbtable *table, int rdom, 161 const struct in6_addr *faddr, u_short fport, 162 const struct in6_addr *laddr, u_short lport) 163 { 164 SIPHASH_CTX ctx; 165 u_int32_t nrdom = htonl(rdom); 166 167 SipHash24_Init(&ctx, &table->inpt_key); 168 SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); 169 SipHash24_Update(&ctx, faddr, sizeof(*faddr)); 170 SipHash24_Update(&ctx, &fport, sizeof(fport)); 171 SipHash24_Update(&ctx, laddr, sizeof(*laddr)); 172 SipHash24_Update(&ctx, &lport, sizeof(lport)); 173 174 return (&table->inpt_hashtbl[SipHash24_End(&ctx) & table->inpt_hash]); 175 } 176 177 #define IN6PCBHASH(table, faddr, fport, laddr, lport, rdom) \ 178 in6_pcbhash(table, rdom, faddr, fport, laddr, lport) 179 180 struct inpcbhead * 181 in_pcblhash(struct inpcbtable *table, int rdom, u_short lport) 182 { 183 SIPHASH_CTX ctx; 184 u_int32_t nrdom = htonl(rdom); 185 186 SipHash24_Init(&ctx, &table->inpt_key); 187 SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); 188 SipHash24_Update(&ctx, &lport, sizeof(lport)); 189 190 return (&table->inpt_lhashtbl[SipHash24_End(&ctx) & table->inpt_lhash]); 191 } 192 193 #define INPCBLHASH(table, lport, rdom) in_pcblhash(table, rdom, lport) 194 195 void 196 in_pcbinit(struct inpcbtable *table, int hashsize) 197 { 198 199 TAILQ_INIT(&table->inpt_queue); 200 table->inpt_hashtbl = hashinit(hashsize, M_PCB, M_NOWAIT, 201 &table->inpt_hash); 202 if (table->inpt_hashtbl == NULL) 203 panic("in_pcbinit: hashinit failed"); 204 table->inpt_lhashtbl = hashinit(hashsize, M_PCB, M_NOWAIT, 205 &table->inpt_lhash); 206 if (table->inpt_lhashtbl == NULL) 207 panic("in_pcbinit: hashinit failed for lport"); 208 table->inpt_count = 0; 209 arc4random_buf(&table->inpt_key, sizeof(table->inpt_key)); 210 } 211 212 /* 213 * Check if the specified port is invalid for dynamic allocation. 214 */ 215 int 216 in_baddynamic(u_int16_t port, u_int16_t proto) 217 { 218 switch (proto) { 219 case IPPROTO_TCP: 220 return (DP_ISSET(baddynamicports.tcp, port)); 221 case IPPROTO_UDP: 222 #ifdef IPSEC 223 /* Cannot preset this as it is a sysctl */ 224 if (port == udpencap_port) 225 return (1); 226 #endif 227 return (DP_ISSET(baddynamicports.udp, port)); 228 default: 229 return (0); 230 } 231 } 232 233 int 234 in_rootonly(u_int16_t port, u_int16_t proto) 235 { 236 switch (proto) { 237 case IPPROTO_TCP: 238 return (port < IPPORT_RESERVED || 239 DP_ISSET(rootonlyports.tcp, port)); 240 case IPPROTO_UDP: 241 return (port < IPPORT_RESERVED || 242 DP_ISSET(rootonlyports.udp, port)); 243 default: 244 return (0); 245 } 246 } 247 248 int 249 in_pcballoc(struct socket *so, struct inpcbtable *table) 250 { 251 struct inpcb *inp; 252 int s; 253 struct inpcbhead *head; 254 255 splsoftassert(IPL_SOFTNET); 256 257 if (inpcb_pool_initialized == 0) { 258 pool_init(&inpcb_pool, sizeof(struct inpcb), 0, 0, 0, 259 "inpcbpl", NULL); 260 inpcb_pool_initialized = 1; 261 } 262 inp = pool_get(&inpcb_pool, PR_NOWAIT|PR_ZERO); 263 if (inp == NULL) 264 return (ENOBUFS); 265 inp->inp_table = table; 266 inp->inp_socket = so; 267 inp->inp_seclevel[SL_AUTH] = IPSEC_AUTH_LEVEL_DEFAULT; 268 inp->inp_seclevel[SL_ESP_TRANS] = IPSEC_ESP_TRANS_LEVEL_DEFAULT; 269 inp->inp_seclevel[SL_ESP_NETWORK] = IPSEC_ESP_NETWORK_LEVEL_DEFAULT; 270 inp->inp_seclevel[SL_IPCOMP] = IPSEC_IPCOMP_LEVEL_DEFAULT; 271 inp->inp_rtableid = curproc->p_p->ps_rtableid; 272 s = splnet(); 273 if (table->inpt_hash != 0 && 274 table->inpt_count++ > INPCBHASH_LOADFACTOR(table->inpt_hash)) 275 (void)in_pcbresize(table, (table->inpt_hash + 1) * 2); 276 TAILQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue); 277 head = INPCBLHASH(table, inp->inp_lport, inp->inp_rtableid); 278 LIST_INSERT_HEAD(head, inp, inp_lhash); 279 head = INPCBHASH(table, &inp->inp_faddr, inp->inp_fport, 280 &inp->inp_laddr, inp->inp_lport, rtable_l2(inp->inp_rtableid)); 281 LIST_INSERT_HEAD(head, inp, inp_hash); 282 splx(s); 283 so->so_pcb = inp; 284 inp->inp_hops = -1; 285 286 #ifdef INET6 287 /* 288 * Small change in this function to set the INP_IPV6 flag so routines 289 * outside pcb-specific routines don't need to use sotopf(), and all 290 * of its pointer chasing, later. 291 */ 292 if (sotopf(so) == PF_INET6) 293 inp->inp_flags = INP_IPV6; 294 inp->inp_cksum6 = -1; 295 #endif /* INET6 */ 296 return (0); 297 } 298 299 int 300 in_pcbbind(struct inpcb *inp, struct mbuf *nam, struct proc *p) 301 { 302 struct socket *so = inp->inp_socket; 303 u_int16_t lport = 0; 304 int wild = 0; 305 void *laddr = &zeroin46_addr; 306 int error; 307 308 if (inp->inp_lport) 309 return (EINVAL); 310 311 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && 312 ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || 313 (so->so_options & SO_ACCEPTCONN) == 0)) 314 wild = INPLOOKUP_WILDCARD; 315 316 switch (sotopf(so)) { 317 #ifdef INET6 318 case PF_INET6: 319 if (TAILQ_EMPTY(&in6_ifaddr)) 320 return (EADDRNOTAVAIL); 321 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) 322 return (EINVAL); 323 wild |= INPLOOKUP_IPV6; 324 325 if (nam) { 326 struct sockaddr_in6 *sin6; 327 sin6 = mtod(nam, struct sockaddr_in6 *); 328 if (nam->m_len != sizeof(struct sockaddr_in6)) 329 return (EINVAL); 330 if (sin6->sin6_family != AF_INET6) 331 return (EAFNOSUPPORT); 332 333 if ((error = in6_pcbaddrisavail(inp, sin6, wild, p))) 334 return (error); 335 laddr = &sin6->sin6_addr; 336 lport = sin6->sin6_port; 337 } 338 break; 339 #endif 340 case PF_INET: 341 if (inp->inp_laddr.s_addr != INADDR_ANY) 342 return (EINVAL); 343 344 if (nam) { 345 struct sockaddr_in *sin; 346 sin = mtod(nam, struct sockaddr_in *); 347 if (nam->m_len != sizeof(*sin)) 348 return (EINVAL); 349 if (sin->sin_family != AF_INET) 350 return (EAFNOSUPPORT); 351 352 if ((error = in_pcbaddrisavail(inp, sin, wild, p))) 353 return (error); 354 laddr = &sin->sin_addr; 355 lport = sin->sin_port; 356 } 357 break; 358 default: 359 return (EINVAL); 360 } 361 362 if (lport == 0) { 363 if ((error = in_pcbpickport(&lport, laddr, wild, inp, p))) 364 return (error); 365 } else { 366 if (in_rootonly(ntohs(lport), so->so_proto->pr_protocol) && 367 suser(p, 0) != 0) 368 return (EACCES); 369 } 370 if (nam) { 371 switch (sotopf(so)) { 372 #ifdef INET6 373 case PF_INET6: 374 inp->inp_laddr6 = *(struct in6_addr *)laddr; 375 break; 376 #endif 377 case PF_INET: 378 inp->inp_laddr = *(struct in_addr *)laddr; 379 break; 380 } 381 } 382 inp->inp_lport = lport; 383 in_pcbrehash(inp); 384 return (0); 385 } 386 387 int 388 in_pcbaddrisavail(struct inpcb *inp, struct sockaddr_in *sin, int wild, 389 struct proc *p) 390 { 391 struct socket *so = inp->inp_socket; 392 struct inpcbtable *table = inp->inp_table; 393 u_int16_t lport = sin->sin_port; 394 int reuseport = (so->so_options & SO_REUSEPORT); 395 396 if (IN_MULTICAST(sin->sin_addr.s_addr)) { 397 /* 398 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 399 * allow complete duplication of binding if 400 * SO_REUSEPORT is set, or if SO_REUSEADDR is set 401 * and a multicast address is bound on both 402 * new and duplicated sockets. 403 */ 404 if (so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) 405 reuseport = SO_REUSEADDR|SO_REUSEPORT; 406 } else if (sin->sin_addr.s_addr != INADDR_ANY) { 407 /* 408 * we must check that we are binding to an address we 409 * own except when: 410 * - SO_BINDANY is set or 411 * - we are binding a UDP socket to 255.255.255.255 or 412 * - we are binding a UDP socket to one of our broadcast 413 * addresses 414 */ 415 if (!ISSET(so->so_options, SO_BINDANY) && 416 !(so->so_type == SOCK_DGRAM && 417 sin->sin_addr.s_addr == INADDR_BROADCAST) && 418 !(so->so_type == SOCK_DGRAM && 419 in_broadcast(sin->sin_addr, inp->inp_rtableid))) { 420 struct ifaddr *ia; 421 422 sin->sin_port = 0; 423 memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); 424 ia = ifa_ifwithaddr(sintosa(sin), inp->inp_rtableid); 425 sin->sin_port = lport; 426 427 if (ia == NULL) 428 return (EADDRNOTAVAIL); 429 } 430 } 431 if (lport) { 432 struct inpcb *t; 433 434 if (so->so_euid) { 435 t = in_pcblookup_local(table, &sin->sin_addr, lport, 436 INPLOOKUP_WILDCARD, inp->inp_rtableid); 437 if (t && (so->so_euid != t->inp_socket->so_euid)) 438 return (EADDRINUSE); 439 } 440 t = in_pcblookup_local(table, &sin->sin_addr, lport, 441 wild, inp->inp_rtableid); 442 if (t && (reuseport & t->inp_socket->so_options) == 0) 443 return (EADDRINUSE); 444 } 445 446 return (0); 447 } 448 449 int 450 in_pcbpickport(u_int16_t *lport, void *laddr, int wild, struct inpcb *inp, 451 struct proc *p) 452 { 453 struct socket *so = inp->inp_socket; 454 struct inpcbtable *table = inp->inp_table; 455 u_int16_t first, last, lower, higher, candidate, localport; 456 int count; 457 458 if (inp->inp_flags & INP_HIGHPORT) { 459 first = ipport_hifirstauto; /* sysctl */ 460 last = ipport_hilastauto; 461 } else if (inp->inp_flags & INP_LOWPORT) { 462 if (suser(p, 0)) 463 return (EACCES); 464 first = IPPORT_RESERVED-1; /* 1023 */ 465 last = 600; /* not IPPORT_RESERVED/2 */ 466 } else { 467 first = ipport_firstauto; /* sysctl */ 468 last = ipport_lastauto; 469 } 470 if (first < last) { 471 lower = first; 472 higher = last; 473 } else { 474 lower = last; 475 higher = first; 476 } 477 478 /* 479 * Simple check to ensure all ports are not used up causing 480 * a deadlock here. 481 */ 482 483 count = higher - lower; 484 candidate = lower + arc4random_uniform(count); 485 486 do { 487 if (count-- < 0) /* completely used? */ 488 return (EADDRNOTAVAIL); 489 ++candidate; 490 if (candidate < lower || candidate > higher) 491 candidate = lower; 492 localport = htons(candidate); 493 } while (in_baddynamic(candidate, so->so_proto->pr_protocol) || 494 in_pcblookup_local(table, laddr, localport, wild, 495 inp->inp_rtableid)); 496 *lport = localport; 497 498 return (0); 499 } 500 501 /* 502 * Connect from a socket to a specified address. 503 * Both address and port must be specified in argument sin. 504 * If don't have a local address for this socket yet, 505 * then pick one. 506 */ 507 int 508 in_pcbconnect(struct inpcb *inp, struct mbuf *nam) 509 { 510 struct in_addr *ina = NULL; 511 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 512 int error; 513 514 #ifdef INET6 515 if (sotopf(inp->inp_socket) == PF_INET6) 516 return (in6_pcbconnect(inp, nam)); 517 if ((inp->inp_flags & INP_IPV6) != 0) 518 panic("IPv6 pcb passed into in_pcbconnect"); 519 #endif /* INET6 */ 520 521 if (nam->m_len != sizeof(*sin)) 522 return (EINVAL); 523 if (sin->sin_family != AF_INET) 524 return (EAFNOSUPPORT); 525 if (sin->sin_port == 0) 526 return (EADDRNOTAVAIL); 527 528 error = in_selectsrc(&ina, sin, inp->inp_moptions, &inp->inp_route, 529 &inp->inp_laddr, inp->inp_rtableid); 530 if (error) 531 return (error); 532 533 if (in_pcbhashlookup(inp->inp_table, sin->sin_addr, sin->sin_port, 534 *ina, inp->inp_lport, inp->inp_rtableid) != 0) 535 return (EADDRINUSE); 536 537 KASSERT(inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_lport); 538 539 if (inp->inp_laddr.s_addr == INADDR_ANY) { 540 if (inp->inp_lport == 0 && 541 in_pcbbind(inp, NULL, curproc) == EADDRNOTAVAIL) 542 return (EADDRNOTAVAIL); 543 inp->inp_laddr = *ina; 544 } 545 inp->inp_faddr = sin->sin_addr; 546 inp->inp_fport = sin->sin_port; 547 in_pcbrehash(inp); 548 #ifdef IPSEC 549 { 550 /* Cause an IPsec SA to be established. */ 551 /* error is just ignored */ 552 ipsp_spd_inp(NULL, AF_INET, 0, &error, IPSP_DIRECTION_OUT, 553 NULL, inp, NULL); 554 } 555 #endif 556 return (0); 557 } 558 559 void 560 in_pcbdisconnect(struct inpcb *inp) 561 { 562 switch (sotopf(inp->inp_socket)) { 563 #ifdef INET6 564 case PF_INET6: 565 inp->inp_faddr6 = in6addr_any; 566 break; 567 #endif 568 case PF_INET: 569 inp->inp_faddr.s_addr = INADDR_ANY; 570 break; 571 } 572 573 inp->inp_fport = 0; 574 in_pcbrehash(inp); 575 if (inp->inp_socket->so_state & SS_NOFDREF) 576 in_pcbdetach(inp); 577 } 578 579 void 580 in_pcbdetach(struct inpcb *inp) 581 { 582 struct socket *so = inp->inp_socket; 583 int s; 584 585 splsoftassert(IPL_SOFTNET); 586 587 so->so_pcb = 0; 588 sofree(so); 589 m_freem(inp->inp_options); 590 if (inp->inp_route.ro_rt) 591 rtfree(inp->inp_route.ro_rt); 592 #ifdef INET6 593 if (inp->inp_flags & INP_IPV6) { 594 ip6_freepcbopts(inp->inp_outputopts6); 595 ip6_freemoptions(inp->inp_moptions6); 596 } else 597 #endif 598 ip_freemoptions(inp->inp_moptions); 599 #if NPF > 0 600 if (inp->inp_pf_sk) { 601 pf_remove_divert_state(inp->inp_pf_sk); 602 /* pf_remove_divert_state() may have detached the state */ 603 pf_inp_unlink(inp); 604 } 605 #endif 606 s = splnet(); 607 LIST_REMOVE(inp, inp_lhash); 608 LIST_REMOVE(inp, inp_hash); 609 TAILQ_REMOVE(&inp->inp_table->inpt_queue, inp, inp_queue); 610 inp->inp_table->inpt_count--; 611 splx(s); 612 pool_put(&inpcb_pool, inp); 613 } 614 615 void 616 in_setsockaddr(struct inpcb *inp, struct mbuf *nam) 617 { 618 struct sockaddr_in *sin; 619 620 nam->m_len = sizeof(*sin); 621 sin = mtod(nam, struct sockaddr_in *); 622 memset(sin, 0, sizeof(*sin)); 623 sin->sin_family = AF_INET; 624 sin->sin_len = sizeof(*sin); 625 sin->sin_port = inp->inp_lport; 626 sin->sin_addr = inp->inp_laddr; 627 } 628 629 void 630 in_setpeeraddr(struct inpcb *inp, struct mbuf *nam) 631 { 632 struct sockaddr_in *sin; 633 634 #ifdef INET6 635 if (sotopf(inp->inp_socket) == PF_INET6) { 636 in6_setpeeraddr(inp, nam); 637 return; 638 } 639 #endif /* INET6 */ 640 641 nam->m_len = sizeof(*sin); 642 sin = mtod(nam, struct sockaddr_in *); 643 memset(sin, 0, sizeof(*sin)); 644 sin->sin_family = AF_INET; 645 sin->sin_len = sizeof(*sin); 646 sin->sin_port = inp->inp_fport; 647 sin->sin_addr = inp->inp_faddr; 648 } 649 650 /* 651 * Pass some notification to all connections of a protocol 652 * associated with address dst. The "usual action" will be 653 * taken, depending on the ctlinput cmd. The caller must filter any 654 * cmds that are uninteresting (e.g., no error in the map). 655 * Call the protocol specific routine (if any) to report 656 * any errors for each matching socket. 657 * 658 * Must be called at splsoftnet. 659 */ 660 void 661 in_pcbnotifyall(struct inpcbtable *table, struct sockaddr *dst, u_int rdomain, 662 int errno, void (*notify)(struct inpcb *, int)) 663 { 664 struct inpcb *inp, *ninp; 665 struct in_addr faddr; 666 667 splsoftassert(IPL_SOFTNET); 668 669 #ifdef INET6 670 /* 671 * See in6_pcbnotify() for IPv6 codepath. By the time this 672 * gets called, the addresses passed are either definitely IPv4 or 673 * IPv6; *_pcbnotify() never gets called with v4-mapped v6 addresses. 674 */ 675 #endif /* INET6 */ 676 677 if (dst->sa_family != AF_INET) 678 return; 679 faddr = satosin(dst)->sin_addr; 680 if (faddr.s_addr == INADDR_ANY) 681 return; 682 683 rdomain = rtable_l2(rdomain); 684 TAILQ_FOREACH_SAFE(inp, &table->inpt_queue, inp_queue, ninp) { 685 #ifdef INET6 686 if (inp->inp_flags & INP_IPV6) 687 continue; 688 #endif 689 if (inp->inp_faddr.s_addr != faddr.s_addr || 690 rtable_l2(inp->inp_rtableid) != rdomain || 691 inp->inp_socket == 0) { 692 continue; 693 } 694 if (notify) 695 (*notify)(inp, errno); 696 } 697 } 698 699 /* 700 * Check for alternatives when higher level complains 701 * about service problems. For now, invalidate cached 702 * routing information. If the route was created dynamically 703 * (by a redirect), time to try a default gateway again. 704 */ 705 void 706 in_losing(struct inpcb *inp) 707 { 708 struct rtentry *rt; 709 struct rt_addrinfo info; 710 struct sockaddr_in6 sa_mask; 711 712 if ((rt = inp->inp_route.ro_rt)) { 713 inp->inp_route.ro_rt = 0; 714 715 memset(&info, 0, sizeof(info)); 716 info.rti_flags = rt->rt_flags; 717 info.rti_info[RTAX_DST] = &inp->inp_route.ro_dst; 718 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 719 info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask); 720 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, rt->rt_priority, 721 rt->rt_ifidx, 0, inp->inp_rtableid); 722 if (rt->rt_flags & RTF_DYNAMIC) 723 (void)rtrequest(RTM_DELETE, &info, rt->rt_priority, 724 NULL, inp->inp_rtableid); 725 /* 726 * A new route can be allocated 727 * the next time output is attempted. 728 * rtfree() needs to be called in anycase because the inp 729 * is still holding a reference to rt. 730 */ 731 rtfree(rt); 732 } 733 } 734 735 /* 736 * After a routing change, flush old routing 737 * and allocate a (hopefully) better one. 738 */ 739 void 740 in_rtchange(struct inpcb *inp, int errno) 741 { 742 if (inp->inp_route.ro_rt) { 743 rtfree(inp->inp_route.ro_rt); 744 inp->inp_route.ro_rt = 0; 745 /* 746 * A new route can be allocated the next time 747 * output is attempted. 748 */ 749 } 750 } 751 752 struct inpcb * 753 in_pcblookup_local(struct inpcbtable *table, void *laddrp, u_int lport_arg, 754 int flags, u_int rdomain) 755 { 756 struct inpcb *inp, *match = NULL; 757 int matchwild = 3, wildcard; 758 u_int16_t lport = lport_arg; 759 struct in_addr laddr = *(struct in_addr *)laddrp; 760 #ifdef INET6 761 struct in6_addr *laddr6 = (struct in6_addr *)laddrp; 762 #endif 763 struct inpcbhead *head; 764 765 rdomain = rtable_l2(rdomain); /* convert passed rtableid to rdomain */ 766 head = INPCBLHASH(table, lport, rdomain); 767 LIST_FOREACH(inp, head, inp_lhash) { 768 if (rtable_l2(inp->inp_rtableid) != rdomain) 769 continue; 770 if (inp->inp_lport != lport) 771 continue; 772 wildcard = 0; 773 #ifdef INET6 774 if (ISSET(flags, INPLOOKUP_IPV6)) { 775 if (!ISSET(inp->inp_flags, INP_IPV6)) 776 continue; 777 778 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) 779 wildcard++; 780 781 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr6)) { 782 if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) || 783 IN6_IS_ADDR_UNSPECIFIED(laddr6)) 784 wildcard++; 785 else 786 continue; 787 } 788 789 } else 790 #endif /* INET6 */ 791 { 792 #ifdef INET6 793 if (ISSET(inp->inp_flags, INP_IPV6)) 794 continue; 795 #endif /* INET6 */ 796 797 if (inp->inp_faddr.s_addr != INADDR_ANY) 798 wildcard++; 799 800 if (inp->inp_laddr.s_addr != laddr.s_addr) { 801 if (inp->inp_laddr.s_addr == INADDR_ANY || 802 laddr.s_addr == INADDR_ANY) 803 wildcard++; 804 else 805 continue; 806 } 807 808 } 809 if ((!wildcard || (flags & INPLOOKUP_WILDCARD)) && 810 wildcard < matchwild) { 811 match = inp; 812 if ((matchwild = wildcard) == 0) 813 break; 814 } 815 } 816 return (match); 817 } 818 819 struct rtentry * 820 in_pcbrtentry(struct inpcb *inp) 821 { 822 struct route *ro; 823 824 ro = &inp->inp_route; 825 826 /* check if route is still valid */ 827 if (!rtisvalid(ro->ro_rt)) { 828 rtfree(ro->ro_rt); 829 ro->ro_rt = NULL; 830 } 831 832 /* 833 * No route yet, so try to acquire one. 834 */ 835 if (ro->ro_rt == NULL) { 836 #ifdef INET6 837 memset(ro, 0, sizeof(struct route_in6)); 838 #else 839 memset(ro, 0, sizeof(struct route)); 840 #endif 841 842 switch(sotopf(inp->inp_socket)) { 843 #ifdef INET6 844 case PF_INET6: 845 if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) 846 break; 847 ro->ro_dst.sa_family = AF_INET6; 848 ro->ro_dst.sa_len = sizeof(struct sockaddr_in6); 849 satosin6(&ro->ro_dst)->sin6_addr = inp->inp_faddr6; 850 ro->ro_tableid = inp->inp_rtableid; 851 ro->ro_rt = rtalloc_mpath(&ro->ro_dst, 852 &inp->inp_laddr6.s6_addr32[0], ro->ro_tableid); 853 break; 854 #endif /* INET6 */ 855 case PF_INET: 856 if (inp->inp_faddr.s_addr == INADDR_ANY) 857 break; 858 ro->ro_dst.sa_family = AF_INET; 859 ro->ro_dst.sa_len = sizeof(struct sockaddr_in); 860 satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr; 861 ro->ro_tableid = inp->inp_rtableid; 862 ro->ro_rt = rtalloc_mpath(&ro->ro_dst, 863 &inp->inp_laddr.s_addr, ro->ro_tableid); 864 break; 865 } 866 } 867 return (ro->ro_rt); 868 } 869 870 /* 871 * Return an IPv4 address, which is the most appropriate for a given 872 * destination. 873 * If necessary, this function lookups the routing table and returns 874 * an entry to the caller for later use. 875 */ 876 int 877 in_selectsrc(struct in_addr **insrc, struct sockaddr_in *sin, 878 struct ip_moptions *mopts, struct route *ro, struct in_addr *laddr, 879 u_int rtableid) 880 { 881 struct sockaddr_in *sin2; 882 883 /* 884 * If the socket(if any) is already bound, use that bound address 885 * unless it is INADDR_ANY or INADDR_BROADCAST. 886 */ 887 if (laddr && laddr->s_addr != INADDR_ANY && 888 laddr->s_addr != INADDR_BROADCAST) { 889 *insrc = laddr; 890 return (0); 891 } 892 893 /* 894 * If the destination address is multicast and an outgoing 895 * interface has been set as a multicast option, use the 896 * address of that interface as our source address. 897 */ 898 if (IN_MULTICAST(sin->sin_addr.s_addr) && mopts != NULL) { 899 struct ifnet *ifp; 900 901 ifp = if_get(mopts->imo_ifidx); 902 if (ifp != NULL) { 903 struct in_ifaddr *ia = NULL; 904 905 if (ifp->if_rdomain == rtable_l2(rtableid)) 906 IFP_TO_IA(ifp, ia); 907 if (ia == NULL) { 908 if_put(ifp); 909 return (EADDRNOTAVAIL); 910 } 911 912 *insrc = &ia->ia_addr.sin_addr; 913 if_put(ifp); 914 return (0); 915 } 916 } 917 /* 918 * If route is known or can be allocated now, 919 * our src addr is taken from the i/f, else punt. 920 */ 921 if (!rtisvalid(ro->ro_rt) || (ro->ro_tableid != rtableid) || 922 (satosin(&ro->ro_dst)->sin_addr.s_addr != sin->sin_addr.s_addr)) { 923 rtfree(ro->ro_rt); 924 ro->ro_rt = NULL; 925 } 926 if (ro->ro_rt == NULL) { 927 /* No route yet, so try to acquire one */ 928 ro->ro_dst.sa_family = AF_INET; 929 ro->ro_dst.sa_len = sizeof(struct sockaddr_in); 930 satosin(&ro->ro_dst)->sin_addr = sin->sin_addr; 931 ro->ro_tableid = rtableid; 932 ro->ro_rt = rtalloc_mpath(&ro->ro_dst, NULL, ro->ro_tableid); 933 934 /* 935 * It is important to zero out the rest of the 936 * struct sockaddr_in when mixing v6 & v4! 937 */ 938 sin2 = satosin(&ro->ro_dst); 939 memset(sin2->sin_zero, 0, sizeof(sin2->sin_zero)); 940 } 941 /* 942 * If we found a route, use the address 943 * corresponding to the outgoing interface. 944 */ 945 if (ro->ro_rt != NULL) { 946 *insrc = &satosin(ro->ro_rt->rt_addr)->sin_addr; 947 return (0); 948 } 949 950 return (EADDRNOTAVAIL); 951 } 952 953 void 954 in_pcbrehash(struct inpcb *inp) 955 { 956 struct inpcbtable *table = inp->inp_table; 957 int s; 958 struct inpcbhead *head; 959 960 s = splnet(); 961 LIST_REMOVE(inp, inp_lhash); 962 head = INPCBLHASH(table, inp->inp_lport, inp->inp_rtableid); 963 LIST_INSERT_HEAD(head, inp, inp_lhash); 964 LIST_REMOVE(inp, inp_hash); 965 #ifdef INET6 966 if (inp->inp_flags & INP_IPV6) 967 head = IN6PCBHASH(table, &inp->inp_faddr6, inp->inp_fport, 968 &inp->inp_laddr6, inp->inp_lport, 969 rtable_l2(inp->inp_rtableid)); 970 else 971 #endif /* INET6 */ 972 head = INPCBHASH(table, &inp->inp_faddr, inp->inp_fport, 973 &inp->inp_laddr, inp->inp_lport, 974 rtable_l2(inp->inp_rtableid)); 975 LIST_INSERT_HEAD(head, inp, inp_hash); 976 splx(s); 977 } 978 979 int 980 in_pcbresize(struct inpcbtable *table, int hashsize) 981 { 982 u_long nhash, nlhash; 983 void *nhashtbl, *nlhashtbl, *ohashtbl, *olhashtbl; 984 struct inpcb *inp0, *inp1; 985 986 ohashtbl = table->inpt_hashtbl; 987 olhashtbl = table->inpt_lhashtbl; 988 989 nhashtbl = hashinit(hashsize, M_PCB, M_NOWAIT, &nhash); 990 nlhashtbl = hashinit(hashsize, M_PCB, M_NOWAIT, &nlhash); 991 if (nhashtbl == NULL || nlhashtbl == NULL) { 992 if (nhashtbl != NULL) 993 free(nhashtbl, M_PCB, 0); 994 if (nlhashtbl != NULL) 995 free(nlhashtbl, M_PCB, 0); 996 return (ENOBUFS); 997 } 998 table->inpt_hashtbl = nhashtbl; 999 table->inpt_lhashtbl = nlhashtbl; 1000 table->inpt_hash = nhash; 1001 table->inpt_lhash = nlhash; 1002 arc4random_buf(&table->inpt_key, sizeof(table->inpt_key)); 1003 1004 TAILQ_FOREACH_SAFE(inp0, &table->inpt_queue, inp_queue, inp1) { 1005 in_pcbrehash(inp0); 1006 } 1007 free(ohashtbl, M_PCB, 0); 1008 free(olhashtbl, M_PCB, 0); 1009 1010 return (0); 1011 } 1012 1013 #ifdef DIAGNOSTIC 1014 int in_pcbnotifymiss = 0; 1015 #endif 1016 1017 /* 1018 * The in(6)_pcbhashlookup functions are used to locate connected sockets 1019 * quickly: 1020 * faddr.fport <-> laddr.lport 1021 * No wildcard matching is done so that listening sockets are not found. 1022 * If the functions return NULL in(6)_pcblookup_listen can be used to 1023 * find a listening/bound socket that may accept the connection. 1024 * After those two lookups no other are necessary. 1025 */ 1026 struct inpcb * 1027 in_pcbhashlookup(struct inpcbtable *table, struct in_addr faddr, 1028 u_int fport_arg, struct in_addr laddr, u_int lport_arg, u_int rdomain) 1029 { 1030 struct inpcbhead *head; 1031 struct inpcb *inp; 1032 u_int16_t fport = fport_arg, lport = lport_arg; 1033 1034 rdomain = rtable_l2(rdomain); /* convert passed rtableid to rdomain */ 1035 head = INPCBHASH(table, &faddr, fport, &laddr, lport, rdomain); 1036 LIST_FOREACH(inp, head, inp_hash) { 1037 #ifdef INET6 1038 if (inp->inp_flags & INP_IPV6) 1039 continue; /*XXX*/ 1040 #endif 1041 if (inp->inp_faddr.s_addr == faddr.s_addr && 1042 inp->inp_fport == fport && inp->inp_lport == lport && 1043 inp->inp_laddr.s_addr == laddr.s_addr && 1044 rtable_l2(inp->inp_rtableid) == rdomain) { 1045 /* 1046 * Move this PCB to the head of hash chain so that 1047 * repeated accesses are quicker. This is analogous to 1048 * the historic single-entry PCB cache. 1049 */ 1050 if (inp != LIST_FIRST(head)) { 1051 LIST_REMOVE(inp, inp_hash); 1052 LIST_INSERT_HEAD(head, inp, inp_hash); 1053 } 1054 break; 1055 } 1056 } 1057 #ifdef DIAGNOSTIC 1058 if (inp == NULL && in_pcbnotifymiss) { 1059 printf("in_pcbhashlookup: faddr=%08x fport=%d laddr=%08x lport=%d rdom=%d\n", 1060 ntohl(faddr.s_addr), ntohs(fport), 1061 ntohl(laddr.s_addr), ntohs(lport), rdomain); 1062 } 1063 #endif 1064 return (inp); 1065 } 1066 1067 #ifdef INET6 1068 struct inpcb * 1069 in6_pcbhashlookup(struct inpcbtable *table, const struct in6_addr *faddr, 1070 u_int fport_arg, const struct in6_addr *laddr, u_int lport_arg, 1071 u_int rtable) 1072 { 1073 struct inpcbhead *head; 1074 struct inpcb *inp; 1075 u_int16_t fport = fport_arg, lport = lport_arg; 1076 1077 rtable = rtable_l2(rtable); /* convert passed rtableid to rdomain */ 1078 head = IN6PCBHASH(table, faddr, fport, laddr, lport, rtable); 1079 LIST_FOREACH(inp, head, inp_hash) { 1080 if (!(inp->inp_flags & INP_IPV6)) 1081 continue; 1082 if (IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, faddr) && 1083 inp->inp_fport == fport && inp->inp_lport == lport && 1084 IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr) && 1085 rtable_l2(inp->inp_rtableid) == rtable) { 1086 /* 1087 * Move this PCB to the head of hash chain so that 1088 * repeated accesses are quicker. This is analogous to 1089 * the historic single-entry PCB cache. 1090 */ 1091 if (inp != LIST_FIRST(head)) { 1092 LIST_REMOVE(inp, inp_hash); 1093 LIST_INSERT_HEAD(head, inp, inp_hash); 1094 } 1095 break; 1096 } 1097 } 1098 #ifdef DIAGNOSTIC 1099 if (inp == NULL && in_pcbnotifymiss) { 1100 printf("in6_pcbhashlookup: faddr="); 1101 printf(" fport=%d laddr=", ntohs(fport)); 1102 printf(" lport=%d\n", ntohs(lport)); 1103 } 1104 #endif 1105 return (inp); 1106 } 1107 #endif /* INET6 */ 1108 1109 /* 1110 * The in(6)_pcblookup_listen functions are used to locate listening 1111 * sockets quickly. This are sockets with unspecified foreign address 1112 * and port: 1113 * *.* <-> laddr.lport 1114 * *.* <-> *.lport 1115 */ 1116 struct inpcb * 1117 in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr, 1118 u_int lport_arg, int reverse, struct mbuf *m, u_int rdomain) 1119 { 1120 struct inpcbhead *head; 1121 struct in_addr *key1, *key2; 1122 struct inpcb *inp; 1123 u_int16_t lport = lport_arg; 1124 1125 rdomain = rtable_l2(rdomain); /* convert passed rtableid to rdomain */ 1126 #if NPF > 0 1127 if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { 1128 struct pf_divert *divert; 1129 1130 if ((divert = pf_find_divert(m)) == NULL) 1131 return (NULL); 1132 key1 = key2 = &divert->addr.v4; 1133 lport = divert->port; 1134 } else 1135 #endif 1136 if (reverse) { 1137 key1 = &zeroin_addr; 1138 key2 = &laddr; 1139 } else { 1140 key1 = &laddr; 1141 key2 = &zeroin_addr; 1142 } 1143 1144 head = INPCBHASH(table, &zeroin_addr, 0, key1, lport, rdomain); 1145 LIST_FOREACH(inp, head, inp_hash) { 1146 #ifdef INET6 1147 if (inp->inp_flags & INP_IPV6) 1148 continue; /*XXX*/ 1149 #endif 1150 if (inp->inp_lport == lport && inp->inp_fport == 0 && 1151 inp->inp_laddr.s_addr == key1->s_addr && 1152 inp->inp_faddr.s_addr == INADDR_ANY && 1153 rtable_l2(inp->inp_rtableid) == rdomain) 1154 break; 1155 } 1156 if (inp == NULL && key1->s_addr != key2->s_addr) { 1157 head = INPCBHASH(table, &zeroin_addr, 0, key2, lport, rdomain); 1158 LIST_FOREACH(inp, head, inp_hash) { 1159 #ifdef INET6 1160 if (inp->inp_flags & INP_IPV6) 1161 continue; /*XXX*/ 1162 #endif 1163 if (inp->inp_lport == lport && inp->inp_fport == 0 && 1164 inp->inp_laddr.s_addr == key2->s_addr && 1165 inp->inp_faddr.s_addr == INADDR_ANY && 1166 rtable_l2(inp->inp_rtableid) == rdomain) 1167 break; 1168 } 1169 } 1170 #ifdef DIAGNOSTIC 1171 if (inp == NULL && in_pcbnotifymiss) { 1172 printf("in_pcblookup_listen: laddr=%08x lport=%d\n", 1173 ntohl(laddr.s_addr), ntohs(lport)); 1174 } 1175 #endif 1176 /* 1177 * Move this PCB to the head of hash chain so that 1178 * repeated accesses are quicker. This is analogous to 1179 * the historic single-entry PCB cache. 1180 */ 1181 if (inp != NULL && inp != LIST_FIRST(head)) { 1182 LIST_REMOVE(inp, inp_hash); 1183 LIST_INSERT_HEAD(head, inp, inp_hash); 1184 } 1185 return (inp); 1186 } 1187 1188 #ifdef INET6 1189 struct inpcb * 1190 in6_pcblookup_listen(struct inpcbtable *table, struct in6_addr *laddr, 1191 u_int lport_arg, int reverse, struct mbuf *m, u_int rtable) 1192 { 1193 struct inpcbhead *head; 1194 struct in6_addr *key1, *key2; 1195 struct inpcb *inp; 1196 u_int16_t lport = lport_arg; 1197 1198 rtable = rtable_l2(rtable); /* convert passed rtableid to rdomain */ 1199 #if NPF > 0 1200 if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { 1201 struct pf_divert *divert; 1202 1203 if ((divert = pf_find_divert(m)) == NULL) 1204 return (NULL); 1205 key1 = key2 = &divert->addr.v6; 1206 lport = divert->port; 1207 } else 1208 #endif 1209 if (reverse) { 1210 key1 = &zeroin6_addr; 1211 key2 = laddr; 1212 } else { 1213 key1 = laddr; 1214 key2 = &zeroin6_addr; 1215 } 1216 1217 head = IN6PCBHASH(table, &zeroin6_addr, 0, key1, lport, rtable); 1218 LIST_FOREACH(inp, head, inp_hash) { 1219 if (!(inp->inp_flags & INP_IPV6)) 1220 continue; 1221 if (inp->inp_lport == lport && inp->inp_fport == 0 && 1222 IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, key1) && 1223 IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6) && 1224 rtable_l2(inp->inp_rtableid) == rtable) 1225 break; 1226 } 1227 if (inp == NULL && ! IN6_ARE_ADDR_EQUAL(key1, key2)) { 1228 head = IN6PCBHASH(table, &zeroin6_addr, 0, key2, lport, rtable); 1229 LIST_FOREACH(inp, head, inp_hash) { 1230 if (!(inp->inp_flags & INP_IPV6)) 1231 continue; 1232 if (inp->inp_lport == lport && inp->inp_fport == 0 && 1233 IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, key2) && 1234 IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6) && 1235 rtable_l2(inp->inp_rtableid) == rtable) 1236 break; 1237 } 1238 } 1239 #ifdef DIAGNOSTIC 1240 if (inp == NULL && in_pcbnotifymiss) { 1241 printf("in6_pcblookup_listen: laddr= lport=%d\n", 1242 ntohs(lport)); 1243 } 1244 #endif 1245 /* 1246 * Move this PCB to the head of hash chain so that 1247 * repeated accesses are quicker. This is analogous to 1248 * the historic single-entry PCB cache. 1249 */ 1250 if (inp != NULL && inp != LIST_FIRST(head)) { 1251 LIST_REMOVE(inp, inp_hash); 1252 LIST_INSERT_HEAD(head, inp, inp_hash); 1253 } 1254 return (inp); 1255 } 1256 #endif /* INET6 */ 1257