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