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