1 /* $NetBSD: in_pcb.c,v 1.57 1998/12/19 02:46:12 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Public Access Networks Corporation ("Panix"). It was developed under 9 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon. 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. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1982, 1986, 1991, 1993, 1995 42 * The Regents of the University of California. All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by the University of 55 * California, Berkeley and its contributors. 56 * 4. Neither the name of the University nor the names of its contributors 57 * may be used to endorse or promote products derived from this software 58 * without specific prior written permission. 59 * 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 * SUCH DAMAGE. 71 * 72 * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95 73 */ 74 75 #include <sys/param.h> 76 #include <sys/systm.h> 77 #include <sys/malloc.h> 78 #include <sys/mbuf.h> 79 #include <sys/protosw.h> 80 #include <sys/socket.h> 81 #include <sys/socketvar.h> 82 #include <sys/ioctl.h> 83 #include <sys/errno.h> 84 #include <sys/time.h> 85 #include <sys/pool.h> 86 #include <sys/proc.h> 87 88 #include <net/if.h> 89 #include <net/route.h> 90 91 #include <netinet/in.h> 92 #include <netinet/in_systm.h> 93 #include <netinet/ip.h> 94 #include <netinet/in_pcb.h> 95 #include <netinet/in_var.h> 96 #include <netinet/ip_var.h> 97 98 struct in_addr zeroin_addr; 99 100 #define INPCBHASH_BIND(table, laddr, lport) \ 101 &(table)->inpt_bindhashtbl[ \ 102 ((ntohl((laddr).s_addr) + ntohs(lport))) & (table)->inpt_bindhash] 103 #define INPCBHASH_CONNECT(table, faddr, fport, laddr, lport) \ 104 &(table)->inpt_connecthashtbl[ \ 105 ((ntohl((faddr).s_addr) + ntohs(fport)) + \ 106 (ntohl((laddr).s_addr) + ntohs(lport))) & (table)->inpt_connecthash] 107 108 struct inpcb * 109 in_pcblookup_port __P((struct inpcbtable *, 110 struct in_addr, u_int, int)); 111 112 int anonportmin = IPPORT_ANONMIN; 113 int anonportmax = IPPORT_ANONMAX; 114 115 struct pool inpcb_pool; 116 117 void 118 in_pcbinit(table, bindhashsize, connecthashsize) 119 struct inpcbtable *table; 120 int bindhashsize, connecthashsize; 121 { 122 static int inpcb_pool_initialized; 123 124 if (inpcb_pool_initialized == 0) { 125 pool_init(&inpcb_pool, sizeof(struct inpcb), 0, 0, 0, 126 "inpcbpl", 0, NULL, NULL, M_PCB); 127 inpcb_pool_initialized = 1; 128 } 129 130 CIRCLEQ_INIT(&table->inpt_queue); 131 table->inpt_bindhashtbl = 132 hashinit(bindhashsize, M_PCB, M_WAITOK, &table->inpt_bindhash); 133 table->inpt_connecthashtbl = 134 hashinit(connecthashsize, M_PCB, M_WAITOK, &table->inpt_connecthash); 135 table->inpt_lastlow = IPPORT_RESERVEDMAX; 136 table->inpt_lastport = (u_int16_t)anonportmax; 137 } 138 139 int 140 in_pcballoc(so, v) 141 struct socket *so; 142 void *v; 143 { 144 struct inpcbtable *table = v; 145 register struct inpcb *inp; 146 int s; 147 148 inp = pool_get(&inpcb_pool, PR_NOWAIT); 149 if (inp == NULL) 150 return (ENOBUFS); 151 bzero((caddr_t)inp, sizeof(*inp)); 152 inp->inp_table = table; 153 inp->inp_socket = so; 154 inp->inp_errormtu = -1; 155 so->so_pcb = inp; 156 s = splnet(); 157 CIRCLEQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue); 158 in_pcbstate(inp, INP_ATTACHED); 159 splx(s); 160 return (0); 161 } 162 163 int 164 in_pcbbind(v, nam, p) 165 void *v; 166 struct mbuf *nam; 167 struct proc *p; 168 { 169 register struct inpcb *inp = v; 170 register struct socket *so = inp->inp_socket; 171 register struct inpcbtable *table = inp->inp_table; 172 register struct sockaddr_in *sin; 173 u_int16_t lport = 0; 174 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); 175 #ifndef IPNOPRIVPORTS 176 int error; 177 #endif 178 179 if (in_ifaddr.tqh_first == 0) 180 return (EADDRNOTAVAIL); 181 if (inp->inp_lport || !in_nullhost(inp->inp_laddr)) 182 return (EINVAL); 183 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) 184 wild = 1; 185 if (nam == 0) 186 goto noname; 187 sin = mtod(nam, struct sockaddr_in *); 188 if (nam->m_len != sizeof (*sin)) 189 return (EINVAL); 190 #ifdef notdef 191 /* 192 * We should check the family, but old programs 193 * incorrectly fail to initialize it. 194 */ 195 if (sin->sin_family != AF_INET) 196 return (EAFNOSUPPORT); 197 #endif 198 lport = sin->sin_port; 199 if (IN_MULTICAST(sin->sin_addr.s_addr)) { 200 /* 201 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 202 * allow complete duplication of binding if 203 * SO_REUSEPORT is set, or if SO_REUSEADDR is set 204 * and a multicast address is bound on both 205 * new and duplicated sockets. 206 */ 207 if (so->so_options & SO_REUSEADDR) 208 reuseport = SO_REUSEADDR|SO_REUSEPORT; 209 } else if (!in_nullhost(sin->sin_addr)) { 210 sin->sin_port = 0; /* yech... */ 211 if (ifa_ifwithaddr(sintosa(sin)) == 0) 212 return (EADDRNOTAVAIL); 213 } 214 if (lport) { 215 struct inpcb *t; 216 #ifndef IPNOPRIVPORTS 217 /* GROSS */ 218 if (ntohs(lport) < IPPORT_RESERVED && 219 (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))) 220 return (EACCES); 221 #endif 222 t = in_pcblookup_port(table, sin->sin_addr, lport, wild); 223 if (t && (reuseport & t->inp_socket->so_options) == 0) 224 return (EADDRINUSE); 225 } 226 inp->inp_laddr = sin->sin_addr; 227 228 noname: 229 if (lport == 0) { 230 int cnt; 231 u_int16_t min, max; 232 u_int16_t *lastport; 233 234 if (inp->inp_flags & INP_LOWPORT) { 235 #ifndef IPNOPRIVPORTS 236 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) 237 return (EACCES); 238 #endif 239 min = IPPORT_RESERVEDMIN; 240 max = IPPORT_RESERVEDMAX; 241 lastport = &table->inpt_lastlow; 242 } else { 243 min = anonportmin; 244 max = anonportmax; 245 lastport = &table->inpt_lastport; 246 } 247 if (min > max) { /* sanity check */ 248 u_int16_t swp; 249 250 swp = min; 251 min = max; 252 max = swp; 253 } 254 255 lport = *lastport - 1; 256 for (cnt = max - min + 1; cnt; cnt--, lport--) { 257 if (lport < min || lport > max) 258 lport = max; 259 if (!in_pcblookup_port(table, inp->inp_laddr, 260 htons(lport), 1)) 261 goto found; 262 } 263 if (!in_nullhost(inp->inp_laddr)) 264 inp->inp_laddr.s_addr = INADDR_ANY; 265 return (EAGAIN); 266 found: 267 inp->inp_flags |= INP_ANONPORT; 268 *lastport = lport; 269 lport = htons(lport); 270 } 271 inp->inp_lport = lport; 272 in_pcbstate(inp, INP_BOUND); 273 return (0); 274 } 275 276 /* 277 * Connect from a socket to a specified address. 278 * Both address and port must be specified in argument sin. 279 * If don't have a local address for this socket yet, 280 * then pick one. 281 */ 282 int 283 in_pcbconnect(v, nam) 284 register void *v; 285 struct mbuf *nam; 286 { 287 register struct inpcb *inp = v; 288 struct in_ifaddr *ia; 289 struct sockaddr_in *ifaddr = NULL; 290 register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 291 int error; 292 293 if (nam->m_len != sizeof (*sin)) 294 return (EINVAL); 295 if (sin->sin_family != AF_INET) 296 return (EAFNOSUPPORT); 297 if (sin->sin_port == 0) 298 return (EADDRNOTAVAIL); 299 if (in_ifaddr.tqh_first != 0) { 300 /* 301 * If the destination address is INADDR_ANY, 302 * use any local address (likely loopback). 303 * If the supplied address is INADDR_BROADCAST, 304 * use the broadcast address of an interface 305 * which supports broadcast. (loopback does not) 306 */ 307 308 if (in_nullhost(sin->sin_addr)) 309 sin->sin_addr = in_ifaddr.tqh_first->ia_addr.sin_addr; 310 else if (sin->sin_addr.s_addr == INADDR_BROADCAST) 311 for (ia = in_ifaddr.tqh_first; ia != NULL; 312 ia = ia->ia_list.tqe_next) 313 if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 314 sin->sin_addr = ia->ia_broadaddr.sin_addr; 315 break; 316 } 317 } 318 /* 319 * If we haven't bound which network number to use as ours, 320 * we will use the number of the outgoing interface. 321 * This depends on having done a routing lookup, which 322 * we will probably have to do anyway, so we might 323 * as well do it now. On the other hand if we are 324 * sending to multiple destinations we may have already 325 * done the lookup, so see if we can use the route 326 * from before. In any case, we only 327 * chose a port number once, even if sending to multiple 328 * destinations. 329 */ 330 if (in_nullhost(inp->inp_laddr)) { 331 register struct route *ro; 332 333 ia = (struct in_ifaddr *)0; 334 /* 335 * If route is known or can be allocated now, 336 * our src addr is taken from the i/f, else punt. 337 */ 338 ro = &inp->inp_route; 339 if (ro->ro_rt && 340 (!in_hosteq(satosin(&ro->ro_dst)->sin_addr, 341 sin->sin_addr) || 342 inp->inp_socket->so_options & SO_DONTROUTE)) { 343 RTFREE(ro->ro_rt); 344 ro->ro_rt = (struct rtentry *)0; 345 } 346 if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ 347 (ro->ro_rt == (struct rtentry *)0 || 348 ro->ro_rt->rt_ifp == (struct ifnet *)0)) { 349 /* No route yet, so try to acquire one */ 350 ro->ro_dst.sa_family = AF_INET; 351 ro->ro_dst.sa_len = sizeof(struct sockaddr_in); 352 satosin(&ro->ro_dst)->sin_addr = sin->sin_addr; 353 rtalloc(ro); 354 } 355 /* 356 * If we found a route, use the address 357 * corresponding to the outgoing interface 358 * unless it is the loopback (in case a route 359 * to our address on another net goes to loopback). 360 * 361 * XXX Is this still true? Do we care? 362 */ 363 if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) 364 ia = ifatoia(ro->ro_rt->rt_ifa); 365 if (ia == 0) { 366 u_int16_t fport = sin->sin_port; 367 368 sin->sin_port = 0; 369 ia = ifatoia(ifa_ifwithladdr(sintosa(sin))); 370 sin->sin_port = fport; 371 if (ia == 0) 372 /* Find 1st non-loopback AF_INET address */ 373 for (ia = in_ifaddr.tqh_first ; ia != NULL ; 374 ia = ia->ia_list.tqe_next) 375 if (!(ia->ia_ifp->if_flags & IFF_LOOPBACK)) 376 break; 377 if (ia == 0) 378 return (EADDRNOTAVAIL); 379 } 380 /* 381 * If the destination address is multicast and an outgoing 382 * interface has been set as a multicast option, use the 383 * address of that interface as our source address. 384 */ 385 if (IN_MULTICAST(sin->sin_addr.s_addr) && 386 inp->inp_moptions != NULL) { 387 struct ip_moptions *imo; 388 struct ifnet *ifp; 389 390 imo = inp->inp_moptions; 391 if (imo->imo_multicast_ifp != NULL) { 392 ifp = imo->imo_multicast_ifp; 393 IFP_TO_IA(ifp, ia); /* XXX */ 394 if (ia == 0) 395 return (EADDRNOTAVAIL); 396 } 397 } 398 ifaddr = satosin(&ia->ia_addr); 399 } 400 if (in_pcblookup_connect(inp->inp_table, sin->sin_addr, sin->sin_port, 401 !in_nullhost(inp->inp_laddr) ? inp->inp_laddr : ifaddr->sin_addr, 402 inp->inp_lport) != 0) 403 return (EADDRINUSE); 404 if (in_nullhost(inp->inp_laddr)) { 405 if (inp->inp_lport == 0) { 406 error = in_pcbbind(inp, (struct mbuf *)0, 407 (struct proc *)0); 408 /* 409 * This used to ignore the return value 410 * completely, but we need to check for 411 * ephemeral port shortage. 412 * XXX Should we check for other errors, too? 413 */ 414 if (error == EAGAIN) 415 return (error); 416 } 417 inp->inp_laddr = ifaddr->sin_addr; 418 } 419 inp->inp_faddr = sin->sin_addr; 420 inp->inp_fport = sin->sin_port; 421 in_pcbstate(inp, INP_CONNECTED); 422 return (0); 423 } 424 425 void 426 in_pcbdisconnect(v) 427 void *v; 428 { 429 struct inpcb *inp = v; 430 431 inp->inp_faddr = zeroin_addr; 432 inp->inp_fport = 0; 433 in_pcbstate(inp, INP_BOUND); 434 if (inp->inp_socket->so_state & SS_NOFDREF) 435 in_pcbdetach(inp); 436 } 437 438 void 439 in_pcbdetach(v) 440 void *v; 441 { 442 struct inpcb *inp = v; 443 struct socket *so = inp->inp_socket; 444 int s; 445 446 so->so_pcb = 0; 447 sofree(so); 448 if (inp->inp_options) 449 (void)m_free(inp->inp_options); 450 if (inp->inp_route.ro_rt) 451 rtfree(inp->inp_route.ro_rt); 452 ip_freemoptions(inp->inp_moptions); 453 s = splnet(); 454 in_pcbstate(inp, INP_ATTACHED); 455 CIRCLEQ_REMOVE(&inp->inp_table->inpt_queue, inp, inp_queue); 456 splx(s); 457 pool_put(&inpcb_pool, inp); 458 } 459 460 void 461 in_setsockaddr(inp, nam) 462 register struct inpcb *inp; 463 struct mbuf *nam; 464 { 465 register struct sockaddr_in *sin; 466 467 nam->m_len = sizeof (*sin); 468 sin = mtod(nam, struct sockaddr_in *); 469 bzero((caddr_t)sin, sizeof (*sin)); 470 sin->sin_family = AF_INET; 471 sin->sin_len = sizeof(*sin); 472 sin->sin_port = inp->inp_lport; 473 sin->sin_addr = inp->inp_laddr; 474 } 475 476 void 477 in_setpeeraddr(inp, nam) 478 struct inpcb *inp; 479 struct mbuf *nam; 480 { 481 register struct sockaddr_in *sin; 482 483 nam->m_len = sizeof (*sin); 484 sin = mtod(nam, struct sockaddr_in *); 485 bzero((caddr_t)sin, sizeof (*sin)); 486 sin->sin_family = AF_INET; 487 sin->sin_len = sizeof(*sin); 488 sin->sin_port = inp->inp_fport; 489 sin->sin_addr = inp->inp_faddr; 490 } 491 492 /* 493 * Pass some notification to all connections of a protocol 494 * associated with address dst. The local address and/or port numbers 495 * may be specified to limit the search. The "usual action" will be 496 * taken, depending on the ctlinput cmd. The caller must filter any 497 * cmds that are uninteresting (e.g., no error in the map). 498 * Call the protocol specific routine (if any) to report 499 * any errors for each matching socket. 500 * 501 * Must be called at splsoftnet. 502 */ 503 int 504 in_pcbnotify(table, faddr, fport_arg, laddr, lport_arg, errno, notify) 505 struct inpcbtable *table; 506 struct in_addr faddr, laddr; 507 u_int fport_arg, lport_arg; 508 int errno; 509 void (*notify) __P((struct inpcb *, int)); 510 { 511 struct inpcbhead *head; 512 register struct inpcb *inp, *ninp; 513 u_int16_t fport = fport_arg, lport = lport_arg; 514 int nmatch; 515 516 if (in_nullhost(faddr) || notify == 0) 517 return (0); 518 519 nmatch = 0; 520 head = INPCBHASH_CONNECT(table, faddr, fport, laddr, lport); 521 for (inp = head->lh_first; inp != NULL; inp = ninp) { 522 ninp = inp->inp_hash.le_next; 523 if (in_hosteq(inp->inp_faddr, faddr) && 524 inp->inp_fport == fport && 525 inp->inp_lport == lport && 526 in_hosteq(inp->inp_laddr, laddr)) { 527 (*notify)(inp, errno); 528 nmatch++; 529 } 530 } 531 return (nmatch); 532 } 533 534 void 535 in_pcbnotifyall(table, faddr, errno, notify) 536 struct inpcbtable *table; 537 struct in_addr faddr; 538 int errno; 539 void (*notify) __P((struct inpcb *, int)); 540 { 541 register struct inpcb *inp, *ninp; 542 543 if (in_nullhost(faddr) || notify == 0) 544 return; 545 546 for (inp = table->inpt_queue.cqh_first; 547 inp != (struct inpcb *)&table->inpt_queue; 548 inp = ninp) { 549 ninp = inp->inp_queue.cqe_next; 550 if (in_hosteq(inp->inp_faddr, faddr)) 551 (*notify)(inp, errno); 552 } 553 } 554 555 /* 556 * Check for alternatives when higher level complains 557 * about service problems. For now, invalidate cached 558 * routing information. If the route was created dynamically 559 * (by a redirect), time to try a default gateway again. 560 */ 561 void 562 in_losing(inp) 563 struct inpcb *inp; 564 { 565 register struct rtentry *rt; 566 struct rt_addrinfo info; 567 568 if ((rt = inp->inp_route.ro_rt)) { 569 inp->inp_route.ro_rt = 0; 570 bzero((caddr_t)&info, sizeof(info)); 571 info.rti_info[RTAX_DST] = &inp->inp_route.ro_dst; 572 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 573 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 574 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); 575 if (rt->rt_flags & RTF_DYNAMIC) 576 (void) rtrequest(RTM_DELETE, rt_key(rt), 577 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 578 (struct rtentry **)0); 579 else 580 /* 581 * A new route can be allocated 582 * the next time output is attempted. 583 */ 584 rtfree(rt); 585 } 586 } 587 588 /* 589 * After a routing change, flush old routing 590 * and allocate a (hopefully) better one. 591 */ 592 void 593 in_rtchange(inp, errno) 594 register struct inpcb *inp; 595 int errno; 596 { 597 598 if (inp->inp_route.ro_rt) { 599 rtfree(inp->inp_route.ro_rt); 600 inp->inp_route.ro_rt = 0; 601 /* 602 * A new route can be allocated the next time 603 * output is attempted. 604 */ 605 } 606 /* XXX SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */ 607 } 608 609 struct inpcb * 610 in_pcblookup_port(table, laddr, lport_arg, lookup_wildcard) 611 struct inpcbtable *table; 612 struct in_addr laddr; 613 u_int lport_arg; 614 int lookup_wildcard; 615 { 616 register struct inpcb *inp, *match = 0; 617 int matchwild = 3, wildcard; 618 u_int16_t lport = lport_arg; 619 620 for (inp = table->inpt_queue.cqh_first; 621 inp != (struct inpcb *)&table->inpt_queue; 622 inp = inp->inp_queue.cqe_next) { 623 if (inp->inp_lport != lport) 624 continue; 625 wildcard = 0; 626 if (!in_nullhost(inp->inp_faddr)) 627 wildcard++; 628 if (in_nullhost(inp->inp_laddr)) { 629 if (!in_nullhost(laddr)) 630 wildcard++; 631 } else { 632 if (in_nullhost(laddr)) 633 wildcard++; 634 else { 635 if (!in_hosteq(inp->inp_laddr, laddr)) 636 continue; 637 } 638 } 639 if (wildcard && !lookup_wildcard) 640 continue; 641 if (wildcard < matchwild) { 642 match = inp; 643 matchwild = wildcard; 644 if (matchwild == 0) 645 break; 646 } 647 } 648 return (match); 649 } 650 651 #ifdef DIAGNOSTIC 652 int in_pcbnotifymiss = 0; 653 #endif 654 655 struct inpcb * 656 in_pcblookup_connect(table, faddr, fport_arg, laddr, lport_arg) 657 struct inpcbtable *table; 658 struct in_addr faddr, laddr; 659 u_int fport_arg, lport_arg; 660 { 661 struct inpcbhead *head; 662 register struct inpcb *inp; 663 u_int16_t fport = fport_arg, lport = lport_arg; 664 665 head = INPCBHASH_CONNECT(table, faddr, fport, laddr, lport); 666 for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { 667 if (in_hosteq(inp->inp_faddr, faddr) && 668 inp->inp_fport == fport && 669 inp->inp_lport == lport && 670 in_hosteq(inp->inp_laddr, laddr)) 671 goto out; 672 } 673 #ifdef DIAGNOSTIC 674 if (in_pcbnotifymiss) { 675 printf("in_pcblookup_connect: faddr=%08x fport=%d laddr=%08x lport=%d\n", 676 ntohl(faddr.s_addr), ntohs(fport), 677 ntohl(laddr.s_addr), ntohs(lport)); 678 } 679 #endif 680 return (0); 681 682 out: 683 /* Move this PCB to the head of hash chain. */ 684 if (inp != head->lh_first) { 685 LIST_REMOVE(inp, inp_hash); 686 LIST_INSERT_HEAD(head, inp, inp_hash); 687 } 688 return (inp); 689 } 690 691 struct inpcb * 692 in_pcblookup_bind(table, laddr, lport_arg) 693 struct inpcbtable *table; 694 struct in_addr laddr; 695 u_int lport_arg; 696 { 697 struct inpcbhead *head; 698 register struct inpcb *inp; 699 u_int16_t lport = lport_arg; 700 701 head = INPCBHASH_BIND(table, laddr, lport); 702 for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { 703 if (inp->inp_lport == lport && 704 in_hosteq(inp->inp_laddr, laddr)) 705 goto out; 706 } 707 head = INPCBHASH_BIND(table, zeroin_addr, lport); 708 for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { 709 if (inp->inp_lport == lport && 710 in_hosteq(inp->inp_laddr, zeroin_addr)) 711 goto out; 712 } 713 #ifdef DIAGNOSTIC 714 if (in_pcbnotifymiss) { 715 printf("in_pcblookup_bind: laddr=%08x lport=%d\n", 716 ntohl(laddr.s_addr), ntohs(lport)); 717 } 718 #endif 719 return (0); 720 721 out: 722 /* Move this PCB to the head of hash chain. */ 723 if (inp != head->lh_first) { 724 LIST_REMOVE(inp, inp_hash); 725 LIST_INSERT_HEAD(head, inp, inp_hash); 726 } 727 return (inp); 728 } 729 730 void 731 in_pcbstate(inp, state) 732 struct inpcb *inp; 733 int state; 734 { 735 736 if (inp->inp_state > INP_ATTACHED) 737 LIST_REMOVE(inp, inp_hash); 738 739 switch (state) { 740 case INP_BOUND: 741 LIST_INSERT_HEAD(INPCBHASH_BIND(inp->inp_table, 742 inp->inp_laddr, inp->inp_lport), inp, inp_hash); 743 break; 744 case INP_CONNECTED: 745 LIST_INSERT_HEAD(INPCBHASH_CONNECT(inp->inp_table, 746 inp->inp_faddr, inp->inp_fport, 747 inp->inp_laddr, inp->inp_lport), inp, inp_hash); 748 break; 749 } 750 751 inp->inp_state = state; 752 } 753 754 struct rtentry * 755 in_pcbrtentry(inp) 756 struct inpcb *inp; 757 { 758 struct route *ro; 759 760 ro = &inp->inp_route; 761 762 if (ro->ro_rt == NULL) { 763 /* 764 * No route yet, so try to acquire one. 765 */ 766 if (!in_nullhost(inp->inp_faddr)) { 767 ro->ro_dst.sa_family = AF_INET; 768 ro->ro_dst.sa_len = sizeof(ro->ro_dst); 769 satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr; 770 rtalloc(ro); 771 } 772 } 773 return (ro->ro_rt); 774 } 775