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.45 1998/09/17 18:42:16 fenner 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 !IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 202 t = in_pcblookup_local(inp->inp_pcbinfo, 203 sin->sin_addr, lport, INPLOOKUP_WILDCARD); 204 if (t && 205 (ntohl(sin->sin_addr.s_addr) != INADDR_ANY || 206 ntohl(t->inp_laddr.s_addr) != INADDR_ANY || 207 (t->inp_socket->so_options & 208 SO_REUSEPORT) == 0) && 209 (so->so_uid != t->inp_socket->so_uid)) 210 return (EADDRINUSE); 211 } 212 t = in_pcblookup_local(pcbinfo, sin->sin_addr, 213 lport, wild); 214 if (t && (reuseport & t->inp_socket->so_options) == 0) 215 return (EADDRINUSE); 216 } 217 inp->inp_laddr = sin->sin_addr; 218 } 219 if (lport == 0) { 220 ushort first, last; 221 int count; 222 223 inp->inp_flags |= INP_ANONPORT; 224 225 if (inp->inp_flags & INP_HIGHPORT) { 226 first = ipport_hifirstauto; /* sysctl */ 227 last = ipport_hilastauto; 228 lastport = &pcbinfo->lasthi; 229 } else if (inp->inp_flags & INP_LOWPORT) { 230 if (p && (error = suser(p->p_ucred, &p->p_acflag))) 231 return error; 232 first = ipport_lowfirstauto; /* 1023 */ 233 last = ipport_lowlastauto; /* 600 */ 234 lastport = &pcbinfo->lastlow; 235 } else { 236 first = ipport_firstauto; /* sysctl */ 237 last = ipport_lastauto; 238 lastport = &pcbinfo->lastport; 239 } 240 /* 241 * Simple check to ensure all ports are not used up causing 242 * a deadlock here. 243 * 244 * We split the two cases (up and down) so that the direction 245 * is not being tested on each round of the loop. 246 */ 247 if (first > last) { 248 /* 249 * counting down 250 */ 251 count = first - last; 252 253 do { 254 if (count-- < 0) { /* completely used? */ 255 /* 256 * Undo any address bind that may have 257 * occurred above. 258 */ 259 inp->inp_laddr.s_addr = INADDR_ANY; 260 return (EAGAIN); 261 } 262 --*lastport; 263 if (*lastport > first || *lastport < last) 264 *lastport = first; 265 lport = htons(*lastport); 266 } while (in_pcblookup_local(pcbinfo, 267 inp->inp_laddr, lport, wild)); 268 } else { 269 /* 270 * counting up 271 */ 272 count = last - first; 273 274 do { 275 if (count-- < 0) { /* completely used? */ 276 /* 277 * Undo any address bind that may have 278 * occurred above. 279 */ 280 inp->inp_laddr.s_addr = INADDR_ANY; 281 return (EAGAIN); 282 } 283 ++*lastport; 284 if (*lastport < first || *lastport > last) 285 *lastport = first; 286 lport = htons(*lastport); 287 } while (in_pcblookup_local(pcbinfo, 288 inp->inp_laddr, lport, wild)); 289 } 290 } 291 inp->inp_lport = lport; 292 if (in_pcbinshash(inp) != 0) { 293 inp->inp_laddr.s_addr = INADDR_ANY; 294 inp->inp_lport = 0; 295 return (EAGAIN); 296 } 297 return (0); 298 } 299 300 /* 301 * Transform old in_pcbconnect() into an inner subroutine for new 302 * in_pcbconnect(): Do some validity-checking on the remote 303 * address (in mbuf 'nam') and then determine local host address 304 * (i.e., which interface) to use to access that remote host. 305 * 306 * This preserves definition of in_pcbconnect(), while supporting a 307 * slightly different version for T/TCP. (This is more than 308 * a bit of a kludge, but cleaning up the internal interfaces would 309 * have forced minor changes in every protocol). 310 */ 311 312 int 313 in_pcbladdr(inp, nam, plocal_sin) 314 register struct inpcb *inp; 315 struct sockaddr *nam; 316 struct sockaddr_in **plocal_sin; 317 { 318 struct in_ifaddr *ia; 319 register struct sockaddr_in *sin = (struct sockaddr_in *)nam; 320 321 if (nam->sa_len != sizeof (*sin)) 322 return (EINVAL); 323 if (sin->sin_family != AF_INET) 324 return (EAFNOSUPPORT); 325 if (sin->sin_port == 0) 326 return (EADDRNOTAVAIL); 327 if (!TAILQ_EMPTY(&in_ifaddrhead)) { 328 /* 329 * If the destination address is INADDR_ANY, 330 * use the primary local address. 331 * If the supplied address is INADDR_BROADCAST, 332 * and the primary interface supports broadcast, 333 * choose the broadcast address for that interface. 334 */ 335 #define satosin(sa) ((struct sockaddr_in *)(sa)) 336 #define sintosa(sin) ((struct sockaddr *)(sin)) 337 #define ifatoia(ifa) ((struct in_ifaddr *)(ifa)) 338 if (sin->sin_addr.s_addr == INADDR_ANY) 339 sin->sin_addr = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr; 340 else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST && 341 (in_ifaddrhead.tqh_first->ia_ifp->if_flags & IFF_BROADCAST)) 342 sin->sin_addr = satosin(&in_ifaddrhead.tqh_first->ia_broadaddr)->sin_addr; 343 } 344 if (inp->inp_laddr.s_addr == INADDR_ANY) { 345 register struct route *ro; 346 347 ia = (struct in_ifaddr *)0; 348 /* 349 * If route is known or can be allocated now, 350 * our src addr is taken from the i/f, else punt. 351 */ 352 ro = &inp->inp_route; 353 if (ro->ro_rt && 354 (satosin(&ro->ro_dst)->sin_addr.s_addr != 355 sin->sin_addr.s_addr || 356 inp->inp_socket->so_options & SO_DONTROUTE)) { 357 RTFREE(ro->ro_rt); 358 ro->ro_rt = (struct rtentry *)0; 359 } 360 if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ 361 (ro->ro_rt == (struct rtentry *)0 || 362 ro->ro_rt->rt_ifp == (struct ifnet *)0)) { 363 /* No route yet, so try to acquire one */ 364 ro->ro_dst.sa_family = AF_INET; 365 ro->ro_dst.sa_len = sizeof(struct sockaddr_in); 366 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = 367 sin->sin_addr; 368 rtalloc(ro); 369 } 370 /* 371 * If we found a route, use the address 372 * corresponding to the outgoing interface 373 * unless it is the loopback (in case a route 374 * to our address on another net goes to loopback). 375 */ 376 if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) 377 ia = ifatoia(ro->ro_rt->rt_ifa); 378 if (ia == 0) { 379 u_short fport = sin->sin_port; 380 381 sin->sin_port = 0; 382 ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin))); 383 if (ia == 0) 384 ia = ifatoia(ifa_ifwithnet(sintosa(sin))); 385 sin->sin_port = fport; 386 if (ia == 0) 387 ia = in_ifaddrhead.tqh_first; 388 if (ia == 0) 389 return (EADDRNOTAVAIL); 390 } 391 /* 392 * If the destination address is multicast and an outgoing 393 * interface has been set as a multicast option, use the 394 * address of that interface as our source address. 395 */ 396 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) && 397 inp->inp_moptions != NULL) { 398 struct ip_moptions *imo; 399 struct ifnet *ifp; 400 401 imo = inp->inp_moptions; 402 if (imo->imo_multicast_ifp != NULL) { 403 ifp = imo->imo_multicast_ifp; 404 for (ia = in_ifaddrhead.tqh_first; ia; 405 ia = ia->ia_link.tqe_next) 406 if (ia->ia_ifp == ifp) 407 break; 408 if (ia == 0) 409 return (EADDRNOTAVAIL); 410 } 411 } 412 /* 413 * Don't do pcblookup call here; return interface in plocal_sin 414 * and exit to caller, that will do the lookup. 415 */ 416 *plocal_sin = &ia->ia_addr; 417 418 } 419 return(0); 420 } 421 422 /* 423 * Outer subroutine: 424 * Connect from a socket to a specified address. 425 * Both address and port must be specified in argument sin. 426 * If don't have a local address for this socket yet, 427 * then pick one. 428 */ 429 int 430 in_pcbconnect(inp, nam, p) 431 register struct inpcb *inp; 432 struct sockaddr *nam; 433 struct proc *p; 434 { 435 struct sockaddr_in *ifaddr; 436 register struct sockaddr_in *sin = (struct sockaddr_in *)nam; 437 int error; 438 439 /* 440 * Call inner routine, to assign local interface address. 441 */ 442 if (error = in_pcbladdr(inp, nam, &ifaddr)) 443 return(error); 444 445 if (in_pcblookup_hash(inp->inp_pcbinfo, sin->sin_addr, sin->sin_port, 446 inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr, 447 inp->inp_lport, 0) != NULL) { 448 return (EADDRINUSE); 449 } 450 if (inp->inp_laddr.s_addr == INADDR_ANY) { 451 if (inp->inp_lport == 0) 452 (void)in_pcbbind(inp, (struct sockaddr *)0, p); 453 inp->inp_laddr = ifaddr->sin_addr; 454 } 455 inp->inp_faddr = sin->sin_addr; 456 inp->inp_fport = sin->sin_port; 457 in_pcbrehash(inp); 458 return (0); 459 } 460 461 void 462 in_pcbdisconnect(inp) 463 struct inpcb *inp; 464 { 465 466 inp->inp_faddr.s_addr = INADDR_ANY; 467 inp->inp_fport = 0; 468 in_pcbrehash(inp); 469 if (inp->inp_socket->so_state & SS_NOFDREF) 470 in_pcbdetach(inp); 471 } 472 473 void 474 in_pcbdetach(inp) 475 struct inpcb *inp; 476 { 477 struct socket *so = inp->inp_socket; 478 struct inpcbinfo *ipi = inp->inp_pcbinfo; 479 480 inp->inp_gencnt = ++ipi->ipi_gencnt; 481 in_pcbremlists(inp); 482 so->so_pcb = 0; 483 sofree(so); 484 if (inp->inp_options) 485 (void)m_free(inp->inp_options); 486 if (inp->inp_route.ro_rt) 487 rtfree(inp->inp_route.ro_rt); 488 ip_freemoptions(inp->inp_moptions); 489 zfreei(ipi->ipi_zone, inp); 490 } 491 492 /* 493 * The calling convention of in_setsockaddr() and in_setpeeraddr() was 494 * modified to match the pru_sockaddr() and pru_peeraddr() entry points 495 * in struct pr_usrreqs, so that protocols can just reference then directly 496 * without the need for a wrapper function. The socket must have a valid 497 * (i.e., non-nil) PCB, but it should be impossible to get an invalid one 498 * except through a kernel programming error, so it is acceptable to panic 499 * (or in this case trap) if the PCB is invalid. (Actually, we don't trap 500 * because there actually /is/ a programming error somewhere... XXX) 501 */ 502 int 503 in_setsockaddr(so, nam) 504 struct socket *so; 505 struct sockaddr **nam; 506 { 507 int s; 508 register struct inpcb *inp; 509 register struct sockaddr_in *sin; 510 511 /* 512 * Do the malloc first in case it blocks. 513 */ 514 MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME, M_WAITOK); 515 bzero(sin, sizeof *sin); 516 sin->sin_family = AF_INET; 517 sin->sin_len = sizeof(*sin); 518 519 s = splnet(); 520 inp = sotoinpcb(so); 521 if (!inp) { 522 splx(s); 523 free(sin, M_SONAME); 524 return EINVAL; 525 } 526 sin->sin_port = inp->inp_lport; 527 sin->sin_addr = inp->inp_laddr; 528 splx(s); 529 530 *nam = (struct sockaddr *)sin; 531 return 0; 532 } 533 534 int 535 in_setpeeraddr(so, nam) 536 struct socket *so; 537 struct sockaddr **nam; 538 { 539 int s; 540 struct inpcb *inp; 541 register struct sockaddr_in *sin; 542 543 /* 544 * Do the malloc first in case it blocks. 545 */ 546 MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME, M_WAITOK); 547 bzero((caddr_t)sin, sizeof (*sin)); 548 sin->sin_family = AF_INET; 549 sin->sin_len = sizeof(*sin); 550 551 s = splnet(); 552 inp = sotoinpcb(so); 553 if (!inp) { 554 splx(s); 555 free(sin, M_SONAME); 556 return EINVAL; 557 } 558 sin->sin_port = inp->inp_fport; 559 sin->sin_addr = inp->inp_faddr; 560 splx(s); 561 562 *nam = (struct sockaddr *)sin; 563 return 0; 564 } 565 566 /* 567 * Pass some notification to all connections of a protocol 568 * associated with address dst. The local address and/or port numbers 569 * may be specified to limit the search. The "usual action" will be 570 * taken, depending on the ctlinput cmd. The caller must filter any 571 * cmds that are uninteresting (e.g., no error in the map). 572 * Call the protocol specific routine (if any) to report 573 * any errors for each matching socket. 574 */ 575 void 576 in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify) 577 struct inpcbhead *head; 578 struct sockaddr *dst; 579 u_int fport_arg, lport_arg; 580 struct in_addr laddr; 581 int cmd; 582 void (*notify) __P((struct inpcb *, int)); 583 { 584 register struct inpcb *inp, *oinp; 585 struct in_addr faddr; 586 u_short fport = fport_arg, lport = lport_arg; 587 int errno, s; 588 589 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET) 590 return; 591 faddr = ((struct sockaddr_in *)dst)->sin_addr; 592 if (faddr.s_addr == INADDR_ANY) 593 return; 594 595 /* 596 * Redirects go to all references to the destination, 597 * and use in_rtchange to invalidate the route cache. 598 * Dead host indications: notify all references to the destination. 599 * Otherwise, if we have knowledge of the local port and address, 600 * deliver only to that socket. 601 */ 602 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { 603 fport = 0; 604 lport = 0; 605 laddr.s_addr = 0; 606 if (cmd != PRC_HOSTDEAD) 607 notify = in_rtchange; 608 } 609 errno = inetctlerrmap[cmd]; 610 s = splnet(); 611 for (inp = head->lh_first; inp != NULL;) { 612 if (inp->inp_faddr.s_addr != faddr.s_addr || 613 inp->inp_socket == 0 || 614 (lport && inp->inp_lport != lport) || 615 (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) || 616 (fport && inp->inp_fport != fport)) { 617 inp = inp->inp_list.le_next; 618 continue; 619 } 620 oinp = inp; 621 inp = inp->inp_list.le_next; 622 if (notify) 623 (*notify)(oinp, errno); 624 } 625 splx(s); 626 } 627 628 /* 629 * Check for alternatives when higher level complains 630 * about service problems. For now, invalidate cached 631 * routing information. If the route was created dynamically 632 * (by a redirect), time to try a default gateway again. 633 */ 634 void 635 in_losing(inp) 636 struct inpcb *inp; 637 { 638 register struct rtentry *rt; 639 struct rt_addrinfo info; 640 641 if ((rt = inp->inp_route.ro_rt)) { 642 inp->inp_route.ro_rt = 0; 643 bzero((caddr_t)&info, sizeof(info)); 644 info.rti_info[RTAX_DST] = 645 (struct sockaddr *)&inp->inp_route.ro_dst; 646 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 647 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 648 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); 649 if (rt->rt_flags & RTF_DYNAMIC) 650 (void) rtrequest(RTM_DELETE, rt_key(rt), 651 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 652 (struct rtentry **)0); 653 else 654 /* 655 * A new route can be allocated 656 * the next time output is attempted. 657 */ 658 rtfree(rt); 659 } 660 } 661 662 /* 663 * After a routing change, flush old routing 664 * and allocate a (hopefully) better one. 665 */ 666 static void 667 in_rtchange(inp, errno) 668 register struct inpcb *inp; 669 int errno; 670 { 671 if (inp->inp_route.ro_rt) { 672 rtfree(inp->inp_route.ro_rt); 673 inp->inp_route.ro_rt = 0; 674 /* 675 * A new route can be allocated the next time 676 * output is attempted. 677 */ 678 } 679 } 680 681 /* 682 * Lookup a PCB based on the local address and port. 683 */ 684 struct inpcb * 685 in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay) 686 struct inpcbinfo *pcbinfo; 687 struct in_addr laddr; 688 u_int lport_arg; 689 int wild_okay; 690 { 691 register struct inpcb *inp; 692 int matchwild = 3, wildcard; 693 u_short lport = lport_arg; 694 695 if (!wild_okay) { 696 struct inpcbhead *head; 697 /* 698 * Look for an unconnected (wildcard foreign addr) PCB that 699 * matches the local address and port we're looking for. 700 */ 701 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)]; 702 for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { 703 if (inp->inp_faddr.s_addr == INADDR_ANY && 704 inp->inp_laddr.s_addr == laddr.s_addr && 705 inp->inp_lport == lport) { 706 /* 707 * Found. 708 */ 709 return (inp); 710 } 711 } 712 /* 713 * Not found. 714 */ 715 return (NULL); 716 } else { 717 struct inpcbporthead *porthash; 718 struct inpcbport *phd; 719 struct inpcb *match = NULL; 720 /* 721 * Best fit PCB lookup. 722 * 723 * First see if this local port is in use by looking on the 724 * port hash list. 725 */ 726 porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport, 727 pcbinfo->porthashmask)]; 728 for (phd = porthash->lh_first; phd != NULL; phd = phd->phd_hash.le_next) { 729 if (phd->phd_port == lport) 730 break; 731 } 732 if (phd != NULL) { 733 /* 734 * Port is in use by one or more PCBs. Look for best 735 * fit. 736 */ 737 for (inp = phd->phd_pcblist.lh_first; inp != NULL; 738 inp = inp->inp_portlist.le_next) { 739 wildcard = 0; 740 if (inp->inp_faddr.s_addr != INADDR_ANY) 741 wildcard++; 742 if (inp->inp_laddr.s_addr != INADDR_ANY) { 743 if (laddr.s_addr == INADDR_ANY) 744 wildcard++; 745 else if (inp->inp_laddr.s_addr != laddr.s_addr) 746 continue; 747 } else { 748 if (laddr.s_addr != INADDR_ANY) 749 wildcard++; 750 } 751 if (wildcard < matchwild) { 752 match = inp; 753 matchwild = wildcard; 754 if (matchwild == 0) { 755 break; 756 } 757 } 758 } 759 } 760 return (match); 761 } 762 } 763 764 /* 765 * Lookup PCB in hash list. 766 */ 767 struct inpcb * 768 in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard) 769 struct inpcbinfo *pcbinfo; 770 struct in_addr faddr, laddr; 771 u_int fport_arg, lport_arg; 772 int wildcard; 773 { 774 struct inpcbhead *head; 775 register struct inpcb *inp; 776 u_short fport = fport_arg, lport = lport_arg; 777 778 /* 779 * First look for an exact match. 780 */ 781 head = &pcbinfo->hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, pcbinfo->hashmask)]; 782 for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { 783 if (inp->inp_faddr.s_addr == faddr.s_addr && 784 inp->inp_laddr.s_addr == laddr.s_addr && 785 inp->inp_fport == fport && 786 inp->inp_lport == lport) { 787 /* 788 * Found. 789 */ 790 return (inp); 791 } 792 } 793 if (wildcard) { 794 struct inpcb *local_wild = NULL; 795 796 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)]; 797 for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { 798 if (inp->inp_faddr.s_addr == INADDR_ANY && 799 inp->inp_lport == lport) { 800 if (inp->inp_laddr.s_addr == laddr.s_addr) 801 return (inp); 802 else if (inp->inp_laddr.s_addr == INADDR_ANY) 803 local_wild = inp; 804 } 805 } 806 return (local_wild); 807 } 808 809 /* 810 * Not found. 811 */ 812 return (NULL); 813 } 814 815 /* 816 * Insert PCB onto various hash lists. 817 */ 818 int 819 in_pcbinshash(inp) 820 struct inpcb *inp; 821 { 822 struct inpcbhead *pcbhash; 823 struct inpcbporthead *pcbporthash; 824 struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 825 struct inpcbport *phd; 826 827 pcbhash = &pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr, 828 inp->inp_lport, inp->inp_fport, pcbinfo->hashmask)]; 829 830 pcbporthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(inp->inp_lport, 831 pcbinfo->porthashmask)]; 832 833 /* 834 * Go through port list and look for a head for this lport. 835 */ 836 for (phd = pcbporthash->lh_first; phd != NULL; phd = phd->phd_hash.le_next) { 837 if (phd->phd_port == inp->inp_lport) 838 break; 839 } 840 /* 841 * If none exists, malloc one and tack it on. 842 */ 843 if (phd == NULL) { 844 MALLOC(phd, struct inpcbport *, sizeof(struct inpcbport), M_PCB, M_NOWAIT); 845 if (phd == NULL) { 846 return (ENOBUFS); /* XXX */ 847 } 848 phd->phd_port = inp->inp_lport; 849 LIST_INIT(&phd->phd_pcblist); 850 LIST_INSERT_HEAD(pcbporthash, phd, phd_hash); 851 } 852 inp->inp_phd = phd; 853 LIST_INSERT_HEAD(&phd->phd_pcblist, inp, inp_portlist); 854 LIST_INSERT_HEAD(pcbhash, inp, inp_hash); 855 return (0); 856 } 857 858 /* 859 * Move PCB to the proper hash bucket when { faddr, fport } have been 860 * changed. NOTE: This does not handle the case of the lport changing (the 861 * hashed port list would have to be updated as well), so the lport must 862 * not change after in_pcbinshash() has been called. 863 */ 864 void 865 in_pcbrehash(inp) 866 struct inpcb *inp; 867 { 868 struct inpcbhead *head; 869 870 head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr, 871 inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)]; 872 873 LIST_REMOVE(inp, inp_hash); 874 LIST_INSERT_HEAD(head, inp, inp_hash); 875 } 876 877 /* 878 * Remove PCB from various lists. 879 */ 880 static void 881 in_pcbremlists(inp) 882 struct inpcb *inp; 883 { 884 inp->inp_gencnt = ++inp->inp_pcbinfo->ipi_gencnt; 885 if (inp->inp_lport) { 886 struct inpcbport *phd = inp->inp_phd; 887 888 LIST_REMOVE(inp, inp_hash); 889 LIST_REMOVE(inp, inp_portlist); 890 if (phd->phd_pcblist.lh_first == NULL) { 891 LIST_REMOVE(phd, phd_hash); 892 free(phd, M_PCB); 893 } 894 } 895 LIST_REMOVE(inp, inp_list); 896 inp->inp_pcbinfo->ipi_count--; 897 } 898