1 /* 2 * Copyright (c) 1982, 1986, 1991, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95 34 * $Id: in_pcb.c,v 1.43 1998/04/19 17:22:30 phk Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/malloc.h> 40 #include <sys/mbuf.h> 41 #include <sys/protosw.h> 42 #include <sys/socket.h> 43 #include <sys/socketvar.h> 44 #include <sys/proc.h> 45 #include <sys/kernel.h> 46 #include <sys/sysctl.h> 47 48 #include <machine/limits.h> 49 50 #include <vm/vm_zone.h> 51 52 #include <net/if.h> 53 #include <net/route.h> 54 55 #include <netinet/in.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 static void in_pcbremlists __P((struct inpcb *)); 63 static void in_rtchange __P((struct inpcb *, int)); 64 65 /* 66 * These configure the range of local port addresses assigned to 67 * "unspecified" outgoing connections/packets/whatever. 68 */ 69 static int ipport_lowfirstauto = IPPORT_RESERVED - 1; /* 1023 */ 70 static int ipport_lowlastauto = IPPORT_RESERVEDSTART; /* 600 */ 71 static int ipport_firstauto = IPPORT_RESERVED; /* 1024 */ 72 static int ipport_lastauto = IPPORT_USERRESERVED; /* 5000 */ 73 static int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; /* 49152 */ 74 static int ipport_hilastauto = IPPORT_HILASTAUTO; /* 65535 */ 75 76 #define RANGECHK(var, min, max) \ 77 if ((var) < (min)) { (var) = (min); } \ 78 else if ((var) > (max)) { (var) = (max); } 79 80 static int 81 sysctl_net_ipport_check SYSCTL_HANDLER_ARGS 82 { 83 int error = sysctl_handle_int(oidp, 84 oidp->oid_arg1, oidp->oid_arg2, req); 85 if (!error) { 86 RANGECHK(ipport_lowfirstauto, 1, IPPORT_RESERVED - 1); 87 RANGECHK(ipport_lowlastauto, 1, IPPORT_RESERVED - 1); 88 RANGECHK(ipport_firstauto, IPPORT_RESERVED, USHRT_MAX); 89 RANGECHK(ipport_lastauto, IPPORT_RESERVED, USHRT_MAX); 90 RANGECHK(ipport_hifirstauto, IPPORT_RESERVED, USHRT_MAX); 91 RANGECHK(ipport_hilastauto, IPPORT_RESERVED, USHRT_MAX); 92 } 93 return error; 94 } 95 96 #undef RANGECHK 97 98 SYSCTL_NODE(_net_inet_ip, IPPROTO_IP, portrange, CTLFLAG_RW, 0, "IP Ports"); 99 100 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, lowfirst, CTLTYPE_INT|CTLFLAG_RW, 101 &ipport_lowfirstauto, 0, &sysctl_net_ipport_check, "I", ""); 102 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, lowlast, CTLTYPE_INT|CTLFLAG_RW, 103 &ipport_lowlastauto, 0, &sysctl_net_ipport_check, "I", ""); 104 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, first, CTLTYPE_INT|CTLFLAG_RW, 105 &ipport_firstauto, 0, &sysctl_net_ipport_check, "I", ""); 106 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, last, CTLTYPE_INT|CTLFLAG_RW, 107 &ipport_lastauto, 0, &sysctl_net_ipport_check, "I", ""); 108 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hifirst, CTLTYPE_INT|CTLFLAG_RW, 109 &ipport_hifirstauto, 0, &sysctl_net_ipport_check, "I", ""); 110 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hilast, CTLTYPE_INT|CTLFLAG_RW, 111 &ipport_hilastauto, 0, &sysctl_net_ipport_check, "I", ""); 112 113 /* 114 * in_pcb.c: manage the Protocol Control Blocks. 115 * 116 * NOTE: It is assumed that most of these functions will be called at 117 * splnet(). XXX - There are, unfortunately, a few exceptions to this 118 * rule that should be fixed. 119 */ 120 121 /* 122 * Allocate a PCB and associate it with the socket. 123 */ 124 int 125 in_pcballoc(so, pcbinfo, p) 126 struct socket *so; 127 struct inpcbinfo *pcbinfo; 128 struct proc *p; 129 { 130 register struct inpcb *inp; 131 132 inp = zalloci(pcbinfo->ipi_zone); 133 if (inp == NULL) 134 return (ENOBUFS); 135 bzero((caddr_t)inp, sizeof(*inp)); 136 inp->inp_gencnt = ++pcbinfo->ipi_gencnt; 137 inp->inp_pcbinfo = pcbinfo; 138 inp->inp_socket = so; 139 LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list); 140 pcbinfo->ipi_count++; 141 so->so_pcb = (caddr_t)inp; 142 return (0); 143 } 144 145 int 146 in_pcbbind(inp, nam, p) 147 register struct inpcb *inp; 148 struct sockaddr *nam; 149 struct proc *p; 150 { 151 register struct socket *so = inp->inp_socket; 152 unsigned short *lastport; 153 struct sockaddr_in *sin; 154 struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 155 u_short lport = 0; 156 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); 157 int error; 158 159 if (TAILQ_EMPTY(&in_ifaddrhead)) /* XXX broken! */ 160 return (EADDRNOTAVAIL); 161 if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY) 162 return (EINVAL); 163 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) 164 wild = 1; 165 if (nam) { 166 sin = (struct sockaddr_in *)nam; 167 if (nam->sa_len != sizeof (*sin)) 168 return (EINVAL); 169 #ifdef notdef 170 /* 171 * We should check the family, but old programs 172 * incorrectly fail to initialize it. 173 */ 174 if (sin->sin_family != AF_INET) 175 return (EAFNOSUPPORT); 176 #endif 177 lport = sin->sin_port; 178 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 179 /* 180 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 181 * allow complete duplication of binding if 182 * SO_REUSEPORT is set, or if SO_REUSEADDR is set 183 * and a multicast address is bound on both 184 * new and duplicated sockets. 185 */ 186 if (so->so_options & SO_REUSEADDR) 187 reuseport = SO_REUSEADDR|SO_REUSEPORT; 188 } else if (sin->sin_addr.s_addr != INADDR_ANY) { 189 sin->sin_port = 0; /* yech... */ 190 if (ifa_ifwithaddr((struct sockaddr *)sin) == 0) 191 return (EADDRNOTAVAIL); 192 } 193 if (lport) { 194 struct inpcb *t; 195 196 /* GROSS */ 197 if (ntohs(lport) < IPPORT_RESERVED && p && 198 suser(p->p_ucred, &p->p_acflag)) 199 return (EACCES); 200 if (so->so_uid) { 201 t = in_pcblookup_local(inp->inp_pcbinfo, 202 sin->sin_addr, lport, INPLOOKUP_WILDCARD); 203 if (t && (so->so_uid != t->inp_socket->so_uid)) 204 return (EADDRINUSE); 205 } 206 t = in_pcblookup_local(pcbinfo, sin->sin_addr, 207 lport, wild); 208 if (t && (reuseport & t->inp_socket->so_options) == 0) 209 return (EADDRINUSE); 210 } 211 inp->inp_laddr = sin->sin_addr; 212 } 213 if (lport == 0) { 214 ushort first, last; 215 int count; 216 217 inp->inp_flags |= INP_ANONPORT; 218 219 if (inp->inp_flags & INP_HIGHPORT) { 220 first = ipport_hifirstauto; /* sysctl */ 221 last = ipport_hilastauto; 222 lastport = &pcbinfo->lasthi; 223 } else if (inp->inp_flags & INP_LOWPORT) { 224 if (p && (error = suser(p->p_ucred, &p->p_acflag))) 225 return error; 226 first = ipport_lowfirstauto; /* 1023 */ 227 last = ipport_lowlastauto; /* 600 */ 228 lastport = &pcbinfo->lastlow; 229 } else { 230 first = ipport_firstauto; /* sysctl */ 231 last = ipport_lastauto; 232 lastport = &pcbinfo->lastport; 233 } 234 /* 235 * Simple check to ensure all ports are not used up causing 236 * a deadlock here. 237 * 238 * We split the two cases (up and down) so that the direction 239 * is not being tested on each round of the loop. 240 */ 241 if (first > last) { 242 /* 243 * counting down 244 */ 245 count = first - last; 246 247 do { 248 if (count-- < 0) { /* completely used? */ 249 /* 250 * Undo any address bind that may have 251 * occurred above. 252 */ 253 inp->inp_laddr.s_addr = INADDR_ANY; 254 return (EAGAIN); 255 } 256 --*lastport; 257 if (*lastport > first || *lastport < last) 258 *lastport = first; 259 lport = htons(*lastport); 260 } while (in_pcblookup_local(pcbinfo, 261 inp->inp_laddr, lport, wild)); 262 } else { 263 /* 264 * counting up 265 */ 266 count = last - first; 267 268 do { 269 if (count-- < 0) { /* completely used? */ 270 /* 271 * Undo any address bind that may have 272 * occurred above. 273 */ 274 inp->inp_laddr.s_addr = INADDR_ANY; 275 return (EAGAIN); 276 } 277 ++*lastport; 278 if (*lastport < first || *lastport > last) 279 *lastport = first; 280 lport = htons(*lastport); 281 } while (in_pcblookup_local(pcbinfo, 282 inp->inp_laddr, lport, wild)); 283 } 284 } 285 inp->inp_lport = lport; 286 if (in_pcbinshash(inp) != 0) { 287 inp->inp_laddr.s_addr = INADDR_ANY; 288 inp->inp_lport = 0; 289 return (EAGAIN); 290 } 291 return (0); 292 } 293 294 /* 295 * Transform old in_pcbconnect() into an inner subroutine for new 296 * in_pcbconnect(): Do some validity-checking on the remote 297 * address (in mbuf 'nam') and then determine local host address 298 * (i.e., which interface) to use to access that remote host. 299 * 300 * This preserves definition of in_pcbconnect(), while supporting a 301 * slightly different version for T/TCP. (This is more than 302 * a bit of a kludge, but cleaning up the internal interfaces would 303 * have forced minor changes in every protocol). 304 */ 305 306 int 307 in_pcbladdr(inp, nam, plocal_sin) 308 register struct inpcb *inp; 309 struct sockaddr *nam; 310 struct sockaddr_in **plocal_sin; 311 { 312 struct in_ifaddr *ia; 313 register struct sockaddr_in *sin = (struct sockaddr_in *)nam; 314 315 if (nam->sa_len != sizeof (*sin)) 316 return (EINVAL); 317 if (sin->sin_family != AF_INET) 318 return (EAFNOSUPPORT); 319 if (sin->sin_port == 0) 320 return (EADDRNOTAVAIL); 321 if (!TAILQ_EMPTY(&in_ifaddrhead)) { 322 /* 323 * If the destination address is INADDR_ANY, 324 * use the primary local address. 325 * If the supplied address is INADDR_BROADCAST, 326 * and the primary interface supports broadcast, 327 * choose the broadcast address for that interface. 328 */ 329 #define satosin(sa) ((struct sockaddr_in *)(sa)) 330 #define sintosa(sin) ((struct sockaddr *)(sin)) 331 #define ifatoia(ifa) ((struct in_ifaddr *)(ifa)) 332 if (sin->sin_addr.s_addr == INADDR_ANY) 333 sin->sin_addr = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr; 334 else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST && 335 (in_ifaddrhead.tqh_first->ia_ifp->if_flags & IFF_BROADCAST)) 336 sin->sin_addr = satosin(&in_ifaddrhead.tqh_first->ia_broadaddr)->sin_addr; 337 } 338 if (inp->inp_laddr.s_addr == INADDR_ANY) { 339 register struct route *ro; 340 341 ia = (struct in_ifaddr *)0; 342 /* 343 * If route is known or can be allocated now, 344 * our src addr is taken from the i/f, else punt. 345 */ 346 ro = &inp->inp_route; 347 if (ro->ro_rt && 348 (satosin(&ro->ro_dst)->sin_addr.s_addr != 349 sin->sin_addr.s_addr || 350 inp->inp_socket->so_options & SO_DONTROUTE)) { 351 RTFREE(ro->ro_rt); 352 ro->ro_rt = (struct rtentry *)0; 353 } 354 if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ 355 (ro->ro_rt == (struct rtentry *)0 || 356 ro->ro_rt->rt_ifp == (struct ifnet *)0)) { 357 /* No route yet, so try to acquire one */ 358 ro->ro_dst.sa_family = AF_INET; 359 ro->ro_dst.sa_len = sizeof(struct sockaddr_in); 360 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = 361 sin->sin_addr; 362 rtalloc(ro); 363 } 364 /* 365 * If we found a route, use the address 366 * corresponding to the outgoing interface 367 * unless it is the loopback (in case a route 368 * to our address on another net goes to loopback). 369 */ 370 if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) 371 ia = ifatoia(ro->ro_rt->rt_ifa); 372 if (ia == 0) { 373 u_short fport = sin->sin_port; 374 375 sin->sin_port = 0; 376 ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin))); 377 if (ia == 0) 378 ia = ifatoia(ifa_ifwithnet(sintosa(sin))); 379 sin->sin_port = fport; 380 if (ia == 0) 381 ia = in_ifaddrhead.tqh_first; 382 if (ia == 0) 383 return (EADDRNOTAVAIL); 384 } 385 /* 386 * If the destination address is multicast and an outgoing 387 * interface has been set as a multicast option, use the 388 * address of that interface as our source address. 389 */ 390 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) && 391 inp->inp_moptions != NULL) { 392 struct ip_moptions *imo; 393 struct ifnet *ifp; 394 395 imo = inp->inp_moptions; 396 if (imo->imo_multicast_ifp != NULL) { 397 ifp = imo->imo_multicast_ifp; 398 for (ia = in_ifaddrhead.tqh_first; ia; 399 ia = ia->ia_link.tqe_next) 400 if (ia->ia_ifp == ifp) 401 break; 402 if (ia == 0) 403 return (EADDRNOTAVAIL); 404 } 405 } 406 /* 407 * Don't do pcblookup call here; return interface in plocal_sin 408 * and exit to caller, that will do the lookup. 409 */ 410 *plocal_sin = &ia->ia_addr; 411 412 } 413 return(0); 414 } 415 416 /* 417 * Outer subroutine: 418 * Connect from a socket to a specified address. 419 * Both address and port must be specified in argument sin. 420 * If don't have a local address for this socket yet, 421 * then pick one. 422 */ 423 int 424 in_pcbconnect(inp, nam, p) 425 register struct inpcb *inp; 426 struct sockaddr *nam; 427 struct proc *p; 428 { 429 struct sockaddr_in *ifaddr; 430 register struct sockaddr_in *sin = (struct sockaddr_in *)nam; 431 int error; 432 433 /* 434 * Call inner routine, to assign local interface address. 435 */ 436 if (error = in_pcbladdr(inp, nam, &ifaddr)) 437 return(error); 438 439 if (in_pcblookup_hash(inp->inp_pcbinfo, sin->sin_addr, sin->sin_port, 440 inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr, 441 inp->inp_lport, 0) != NULL) { 442 return (EADDRINUSE); 443 } 444 if (inp->inp_laddr.s_addr == INADDR_ANY) { 445 if (inp->inp_lport == 0) 446 (void)in_pcbbind(inp, (struct sockaddr *)0, p); 447 inp->inp_laddr = ifaddr->sin_addr; 448 } 449 inp->inp_faddr = sin->sin_addr; 450 inp->inp_fport = sin->sin_port; 451 in_pcbrehash(inp); 452 return (0); 453 } 454 455 void 456 in_pcbdisconnect(inp) 457 struct inpcb *inp; 458 { 459 460 inp->inp_faddr.s_addr = INADDR_ANY; 461 inp->inp_fport = 0; 462 in_pcbrehash(inp); 463 if (inp->inp_socket->so_state & SS_NOFDREF) 464 in_pcbdetach(inp); 465 } 466 467 void 468 in_pcbdetach(inp) 469 struct inpcb *inp; 470 { 471 struct socket *so = inp->inp_socket; 472 struct inpcbinfo *ipi = inp->inp_pcbinfo; 473 474 inp->inp_gencnt = ++ipi->ipi_gencnt; 475 in_pcbremlists(inp); 476 so->so_pcb = 0; 477 sofree(so); 478 if (inp->inp_options) 479 (void)m_free(inp->inp_options); 480 if (inp->inp_route.ro_rt) 481 rtfree(inp->inp_route.ro_rt); 482 ip_freemoptions(inp->inp_moptions); 483 zfreei(ipi->ipi_zone, inp); 484 } 485 486 /* 487 * The calling convention of in_setsockaddr() and in_setpeeraddr() was 488 * modified to match the pru_sockaddr() and pru_peeraddr() entry points 489 * in struct pr_usrreqs, so that protocols can just reference then directly 490 * without the need for a wrapper function. The socket must have a valid 491 * (i.e., non-nil) PCB, but it should be impossible to get an invalid one 492 * except through a kernel programming error, so it is acceptable to panic 493 * (or in this case trap) if the PCB is invalid. (Actually, we don't trap 494 * because there actually /is/ a programming error somewhere... XXX) 495 */ 496 int 497 in_setsockaddr(so, nam) 498 struct socket *so; 499 struct sockaddr **nam; 500 { 501 int s; 502 register struct inpcb *inp; 503 register struct sockaddr_in *sin; 504 505 /* 506 * Do the malloc first in case it blocks. 507 */ 508 MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME, M_WAITOK); 509 bzero(sin, sizeof *sin); 510 sin->sin_family = AF_INET; 511 sin->sin_len = sizeof(*sin); 512 513 s = splnet(); 514 inp = sotoinpcb(so); 515 if (!inp) { 516 splx(s); 517 free(sin, M_SONAME); 518 return EINVAL; 519 } 520 sin->sin_port = inp->inp_lport; 521 sin->sin_addr = inp->inp_laddr; 522 splx(s); 523 524 *nam = (struct sockaddr *)sin; 525 return 0; 526 } 527 528 int 529 in_setpeeraddr(so, nam) 530 struct socket *so; 531 struct sockaddr **nam; 532 { 533 int s; 534 struct inpcb *inp; 535 register struct sockaddr_in *sin; 536 537 /* 538 * Do the malloc first in case it blocks. 539 */ 540 MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME, M_WAITOK); 541 bzero((caddr_t)sin, sizeof (*sin)); 542 sin->sin_family = AF_INET; 543 sin->sin_len = sizeof(*sin); 544 545 s = splnet(); 546 inp = sotoinpcb(so); 547 if (!inp) { 548 splx(s); 549 free(sin, M_SONAME); 550 return EINVAL; 551 } 552 sin->sin_port = inp->inp_fport; 553 sin->sin_addr = inp->inp_faddr; 554 splx(s); 555 556 *nam = (struct sockaddr *)sin; 557 return 0; 558 } 559 560 /* 561 * Pass some notification to all connections of a protocol 562 * associated with address dst. The local address and/or port numbers 563 * may be specified to limit the search. The "usual action" will be 564 * taken, depending on the ctlinput cmd. The caller must filter any 565 * cmds that are uninteresting (e.g., no error in the map). 566 * Call the protocol specific routine (if any) to report 567 * any errors for each matching socket. 568 */ 569 void 570 in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify) 571 struct inpcbhead *head; 572 struct sockaddr *dst; 573 u_int fport_arg, lport_arg; 574 struct in_addr laddr; 575 int cmd; 576 void (*notify) __P((struct inpcb *, int)); 577 { 578 register struct inpcb *inp, *oinp; 579 struct in_addr faddr; 580 u_short fport = fport_arg, lport = lport_arg; 581 int errno, s; 582 583 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET) 584 return; 585 faddr = ((struct sockaddr_in *)dst)->sin_addr; 586 if (faddr.s_addr == INADDR_ANY) 587 return; 588 589 /* 590 * Redirects go to all references to the destination, 591 * and use in_rtchange to invalidate the route cache. 592 * Dead host indications: notify all references to the destination. 593 * Otherwise, if we have knowledge of the local port and address, 594 * deliver only to that socket. 595 */ 596 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { 597 fport = 0; 598 lport = 0; 599 laddr.s_addr = 0; 600 if (cmd != PRC_HOSTDEAD) 601 notify = in_rtchange; 602 } 603 errno = inetctlerrmap[cmd]; 604 s = splnet(); 605 for (inp = head->lh_first; inp != NULL;) { 606 if (inp->inp_faddr.s_addr != faddr.s_addr || 607 inp->inp_socket == 0 || 608 (lport && inp->inp_lport != lport) || 609 (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) || 610 (fport && inp->inp_fport != fport)) { 611 inp = inp->inp_list.le_next; 612 continue; 613 } 614 oinp = inp; 615 inp = inp->inp_list.le_next; 616 if (notify) 617 (*notify)(oinp, errno); 618 } 619 splx(s); 620 } 621 622 /* 623 * Check for alternatives when higher level complains 624 * about service problems. For now, invalidate cached 625 * routing information. If the route was created dynamically 626 * (by a redirect), time to try a default gateway again. 627 */ 628 void 629 in_losing(inp) 630 struct inpcb *inp; 631 { 632 register struct rtentry *rt; 633 struct rt_addrinfo info; 634 635 if ((rt = inp->inp_route.ro_rt)) { 636 inp->inp_route.ro_rt = 0; 637 bzero((caddr_t)&info, sizeof(info)); 638 info.rti_info[RTAX_DST] = 639 (struct sockaddr *)&inp->inp_route.ro_dst; 640 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 641 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 642 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); 643 if (rt->rt_flags & RTF_DYNAMIC) 644 (void) rtrequest(RTM_DELETE, rt_key(rt), 645 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 646 (struct rtentry **)0); 647 else 648 /* 649 * A new route can be allocated 650 * the next time output is attempted. 651 */ 652 rtfree(rt); 653 } 654 } 655 656 /* 657 * After a routing change, flush old routing 658 * and allocate a (hopefully) better one. 659 */ 660 static void 661 in_rtchange(inp, errno) 662 register struct inpcb *inp; 663 int errno; 664 { 665 if (inp->inp_route.ro_rt) { 666 rtfree(inp->inp_route.ro_rt); 667 inp->inp_route.ro_rt = 0; 668 /* 669 * A new route can be allocated the next time 670 * output is attempted. 671 */ 672 } 673 } 674 675 /* 676 * Lookup a PCB based on the local address and port. 677 */ 678 struct inpcb * 679 in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay) 680 struct inpcbinfo *pcbinfo; 681 struct in_addr laddr; 682 u_int lport_arg; 683 int wild_okay; 684 { 685 register struct inpcb *inp, *match = NULL; 686 int matchwild = 3, wildcard; 687 u_short lport = lport_arg; 688 689 if (!wild_okay) { 690 struct inpcbhead *head; 691 /* 692 * Look for an unconnected (wildcard foreign addr) PCB that 693 * matches the local address and port we're looking for. 694 */ 695 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)]; 696 for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { 697 if (inp->inp_faddr.s_addr == INADDR_ANY && 698 inp->inp_laddr.s_addr == laddr.s_addr && 699 inp->inp_lport == lport) { 700 /* 701 * Found. 702 */ 703 return (inp); 704 } 705 } 706 /* 707 * Not found. 708 */ 709 return (NULL); 710 } else { 711 struct inpcbporthead *porthash; 712 struct inpcbport *phd; 713 struct inpcb *match = NULL; 714 /* 715 * Best fit PCB lookup. 716 * 717 * First see if this local port is in use by looking on the 718 * port hash list. 719 */ 720 porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport, 721 pcbinfo->porthashmask)]; 722 for (phd = porthash->lh_first; phd != NULL; phd = phd->phd_hash.le_next) { 723 if (phd->phd_port == lport) 724 break; 725 } 726 if (phd != NULL) { 727 /* 728 * Port is in use by one or more PCBs. Look for best 729 * fit. 730 */ 731 for (inp = phd->phd_pcblist.lh_first; inp != NULL; 732 inp = inp->inp_portlist.le_next) { 733 wildcard = 0; 734 if (inp->inp_faddr.s_addr != INADDR_ANY) 735 wildcard++; 736 if (inp->inp_laddr.s_addr != INADDR_ANY) { 737 if (laddr.s_addr == INADDR_ANY) 738 wildcard++; 739 else if (inp->inp_laddr.s_addr != laddr.s_addr) 740 continue; 741 } else { 742 if (laddr.s_addr != INADDR_ANY) 743 wildcard++; 744 } 745 if (wildcard < matchwild) { 746 match = inp; 747 matchwild = wildcard; 748 if (matchwild == 0) { 749 break; 750 } 751 } 752 } 753 } 754 return (match); 755 } 756 } 757 758 /* 759 * Lookup PCB in hash list. 760 */ 761 struct inpcb * 762 in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard) 763 struct inpcbinfo *pcbinfo; 764 struct in_addr faddr, laddr; 765 u_int fport_arg, lport_arg; 766 int wildcard; 767 { 768 struct inpcbhead *head; 769 register struct inpcb *inp; 770 u_short fport = fport_arg, lport = lport_arg; 771 772 /* 773 * First look for an exact match. 774 */ 775 head = &pcbinfo->hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, pcbinfo->hashmask)]; 776 for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { 777 if (inp->inp_faddr.s_addr == faddr.s_addr && 778 inp->inp_laddr.s_addr == laddr.s_addr && 779 inp->inp_fport == fport && 780 inp->inp_lport == lport) { 781 /* 782 * Found. 783 */ 784 return (inp); 785 } 786 } 787 if (wildcard) { 788 struct inpcb *local_wild = NULL; 789 790 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)]; 791 for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { 792 if (inp->inp_faddr.s_addr == INADDR_ANY && 793 inp->inp_lport == lport) { 794 if (inp->inp_laddr.s_addr == laddr.s_addr) 795 return (inp); 796 else if (inp->inp_laddr.s_addr == INADDR_ANY) 797 local_wild = inp; 798 } 799 } 800 return (local_wild); 801 } 802 803 /* 804 * Not found. 805 */ 806 return (NULL); 807 } 808 809 /* 810 * Insert PCB onto various hash lists. 811 */ 812 int 813 in_pcbinshash(inp) 814 struct inpcb *inp; 815 { 816 struct inpcbhead *pcbhash; 817 struct inpcbporthead *pcbporthash; 818 struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 819 struct inpcbport *phd; 820 821 pcbhash = &pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr, 822 inp->inp_lport, inp->inp_fport, pcbinfo->hashmask)]; 823 824 pcbporthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(inp->inp_lport, 825 pcbinfo->porthashmask)]; 826 827 /* 828 * Go through port list and look for a head for this lport. 829 */ 830 for (phd = pcbporthash->lh_first; phd != NULL; phd = phd->phd_hash.le_next) { 831 if (phd->phd_port == inp->inp_lport) 832 break; 833 } 834 /* 835 * If none exists, malloc one and tack it on. 836 */ 837 if (phd == NULL) { 838 MALLOC(phd, struct inpcbport *, sizeof(struct inpcbport), M_PCB, M_NOWAIT); 839 if (phd == NULL) { 840 return (ENOBUFS); /* XXX */ 841 } 842 phd->phd_port = inp->inp_lport; 843 LIST_INIT(&phd->phd_pcblist); 844 LIST_INSERT_HEAD(pcbporthash, phd, phd_hash); 845 } 846 inp->inp_phd = phd; 847 LIST_INSERT_HEAD(&phd->phd_pcblist, inp, inp_portlist); 848 LIST_INSERT_HEAD(pcbhash, inp, inp_hash); 849 return (0); 850 } 851 852 /* 853 * Move PCB to the proper hash bucket when { faddr, fport } have been 854 * changed. NOTE: This does not handle the case of the lport changing (the 855 * hashed port list would have to be updated as well), so the lport must 856 * not change after in_pcbinshash() has been called. 857 */ 858 void 859 in_pcbrehash(inp) 860 struct inpcb *inp; 861 { 862 struct inpcbhead *head; 863 864 head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr, 865 inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)]; 866 867 LIST_REMOVE(inp, inp_hash); 868 LIST_INSERT_HEAD(head, inp, inp_hash); 869 } 870 871 /* 872 * Remove PCB from various lists. 873 */ 874 static void 875 in_pcbremlists(inp) 876 struct inpcb *inp; 877 { 878 inp->inp_gencnt = ++inp->inp_pcbinfo->ipi_gencnt; 879 if (inp->inp_lport) { 880 struct inpcbport *phd = inp->inp_phd; 881 882 LIST_REMOVE(inp, inp_hash); 883 LIST_REMOVE(inp, inp_portlist); 884 if (phd->phd_pcblist.lh_first == NULL) { 885 LIST_REMOVE(phd, phd_hash); 886 free(phd, M_PCB); 887 } 888 } 889 LIST_REMOVE(inp, inp_list); 890 inp->inp_pcbinfo->ipi_count--; 891 } 892