1 /* $NetBSD: in_pcb.c,v 1.129 2008/10/11 13:40:57 pooka Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * 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. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /*- 33 * Copyright (c) 1998 The NetBSD Foundation, Inc. 34 * All rights reserved. 35 * 36 * This code is derived from software contributed to The NetBSD Foundation 37 * by Public Access Networks Corporation ("Panix"). It was developed under 38 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 1. Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 50 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 51 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 52 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 53 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 54 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 55 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 56 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 57 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 58 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 59 * POSSIBILITY OF SUCH DAMAGE. 60 */ 61 62 /* 63 * Copyright (c) 1982, 1986, 1991, 1993, 1995 64 * The Regents of the University of California. All rights reserved. 65 * 66 * Redistribution and use in source and binary forms, with or without 67 * modification, are permitted provided that the following conditions 68 * are met: 69 * 1. Redistributions of source code must retain the above copyright 70 * notice, this list of conditions and the following disclaimer. 71 * 2. Redistributions in binary form must reproduce the above copyright 72 * notice, this list of conditions and the following disclaimer in the 73 * documentation and/or other materials provided with the distribution. 74 * 3. Neither the name of the University nor the names of its contributors 75 * may be used to endorse or promote products derived from this software 76 * without specific prior written permission. 77 * 78 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 81 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 88 * SUCH DAMAGE. 89 * 90 * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95 91 */ 92 93 #include <sys/cdefs.h> 94 __KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.129 2008/10/11 13:40:57 pooka Exp $"); 95 96 #include "opt_inet.h" 97 #include "opt_ipsec.h" 98 99 #include <sys/param.h> 100 #include <sys/systm.h> 101 #include <sys/malloc.h> 102 #include <sys/mbuf.h> 103 #include <sys/protosw.h> 104 #include <sys/socket.h> 105 #include <sys/socketvar.h> 106 #include <sys/ioctl.h> 107 #include <sys/errno.h> 108 #include <sys/time.h> 109 #include <sys/once.h> 110 #include <sys/pool.h> 111 #include <sys/proc.h> 112 #include <sys/kauth.h> 113 #include <sys/uidinfo.h> 114 115 #include <net/if.h> 116 #include <net/route.h> 117 118 #include <netinet/in.h> 119 #include <netinet/in_systm.h> 120 #include <netinet/ip.h> 121 #include <netinet/in_pcb.h> 122 #include <netinet/in_var.h> 123 #include <netinet/ip_var.h> 124 125 #ifdef INET6 126 #include <netinet/ip6.h> 127 #include <netinet6/ip6_var.h> 128 #include <netinet6/in6_pcb.h> 129 #endif 130 131 #ifdef IPSEC 132 #include <netinet6/ipsec.h> 133 #include <netkey/key.h> 134 #elif FAST_IPSEC 135 #include <netipsec/ipsec.h> 136 #include <netipsec/key.h> 137 #endif /* IPSEC */ 138 139 struct in_addr zeroin_addr; 140 141 #define INPCBHASH_PORT(table, lport) \ 142 &(table)->inpt_porthashtbl[ntohs(lport) & (table)->inpt_porthash] 143 #define INPCBHASH_BIND(table, laddr, lport) \ 144 &(table)->inpt_bindhashtbl[ \ 145 ((ntohl((laddr).s_addr) + ntohs(lport))) & (table)->inpt_bindhash] 146 #define INPCBHASH_CONNECT(table, faddr, fport, laddr, lport) \ 147 &(table)->inpt_connecthashtbl[ \ 148 ((ntohl((faddr).s_addr) + ntohs(fport)) + \ 149 (ntohl((laddr).s_addr) + ntohs(lport))) & (table)->inpt_connecthash] 150 151 int anonportmin = IPPORT_ANONMIN; 152 int anonportmax = IPPORT_ANONMAX; 153 int lowportmin = IPPORT_RESERVEDMIN; 154 int lowportmax = IPPORT_RESERVEDMAX; 155 156 static struct pool inpcb_pool; 157 158 static int 159 inpcb_poolinit(void) 160 { 161 162 pool_init(&inpcb_pool, sizeof(struct inpcb), 0, 0, 0, "inpcbpl", NULL, 163 IPL_NET); 164 return 0; 165 } 166 167 void 168 in_pcbinit(struct inpcbtable *table, int bindhashsize, int connecthashsize) 169 { 170 static ONCE_DECL(control); 171 172 CIRCLEQ_INIT(&table->inpt_queue); 173 table->inpt_porthashtbl = hashinit(bindhashsize, HASH_LIST, true, 174 &table->inpt_porthash); 175 table->inpt_bindhashtbl = hashinit(bindhashsize, HASH_LIST, true, 176 &table->inpt_bindhash); 177 table->inpt_connecthashtbl = hashinit(connecthashsize, HASH_LIST, true, 178 &table->inpt_connecthash); 179 table->inpt_lastlow = IPPORT_RESERVEDMAX; 180 table->inpt_lastport = (u_int16_t)anonportmax; 181 182 RUN_ONCE(&control, inpcb_poolinit); 183 } 184 185 int 186 in_pcballoc(struct socket *so, void *v) 187 { 188 struct inpcbtable *table = v; 189 struct inpcb *inp; 190 int s; 191 #if defined(IPSEC) || defined(FAST_IPSEC) 192 int error; 193 #endif 194 195 s = splnet(); 196 inp = pool_get(&inpcb_pool, PR_NOWAIT); 197 splx(s); 198 if (inp == NULL) 199 return (ENOBUFS); 200 bzero((void *)inp, sizeof(*inp)); 201 inp->inp_af = AF_INET; 202 inp->inp_table = table; 203 inp->inp_socket = so; 204 inp->inp_errormtu = -1; 205 #if defined(IPSEC) || defined(FAST_IPSEC) 206 error = ipsec_init_pcbpolicy(so, &inp->inp_sp); 207 if (error != 0) { 208 s = splnet(); 209 pool_put(&inpcb_pool, inp); 210 splx(s); 211 return error; 212 } 213 #endif 214 so->so_pcb = inp; 215 s = splnet(); 216 CIRCLEQ_INSERT_HEAD(&table->inpt_queue, &inp->inp_head, 217 inph_queue); 218 LIST_INSERT_HEAD(INPCBHASH_PORT(table, inp->inp_lport), &inp->inp_head, 219 inph_lhash); 220 in_pcbstate(inp, INP_ATTACHED); 221 splx(s); 222 return (0); 223 } 224 225 int 226 in_pcbbind(void *v, struct mbuf *nam, struct lwp *l) 227 { 228 struct in_ifaddr *ia = NULL; 229 struct inpcb *inp = v; 230 struct socket *so = inp->inp_socket; 231 struct inpcbtable *table = inp->inp_table; 232 struct sockaddr_in *sin = NULL; /* XXXGCC */ 233 u_int16_t lport = 0; 234 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); 235 kauth_cred_t cred = l->l_cred; 236 237 if (inp->inp_af != AF_INET) 238 return (EINVAL); 239 240 if (TAILQ_FIRST(&in_ifaddrhead) == 0) 241 return (EADDRNOTAVAIL); 242 if (inp->inp_lport || !in_nullhost(inp->inp_laddr)) 243 return (EINVAL); 244 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) 245 wild = 1; 246 if (nam == 0) 247 goto noname; 248 sin = mtod(nam, struct sockaddr_in *); 249 if (nam->m_len != sizeof (*sin)) 250 return (EINVAL); 251 if (sin->sin_family != AF_INET) 252 return (EAFNOSUPPORT); 253 lport = sin->sin_port; 254 if (IN_MULTICAST(sin->sin_addr.s_addr)) { 255 /* 256 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 257 * allow complete duplication of binding if 258 * SO_REUSEPORT is set, or if SO_REUSEADDR is set 259 * and a multicast address is bound on both 260 * new and duplicated sockets. 261 */ 262 if (so->so_options & SO_REUSEADDR) 263 reuseport = SO_REUSEADDR|SO_REUSEPORT; 264 } else if (!in_nullhost(sin->sin_addr)) { 265 sin->sin_port = 0; /* yech... */ 266 INADDR_TO_IA(sin->sin_addr, ia); 267 /* check for broadcast addresses */ 268 if (ia == NULL) 269 ia = ifatoia(ifa_ifwithaddr(sintosa(sin))); 270 if (ia == NULL) 271 return (EADDRNOTAVAIL); 272 } 273 if (lport) { 274 struct inpcb *t; 275 #ifdef INET6 276 struct in6pcb *t6; 277 struct in6_addr mapped; 278 #endif 279 #ifndef IPNOPRIVPORTS 280 /* GROSS */ 281 if (ntohs(lport) < IPPORT_RESERVED && 282 kauth_authorize_network(cred, 283 KAUTH_NETWORK_BIND, 284 KAUTH_REQ_NETWORK_BIND_PRIVPORT, so, sin, 285 NULL)) 286 return (EACCES); 287 #endif 288 #ifdef INET6 289 memset(&mapped, 0, sizeof(mapped)); 290 mapped.s6_addr16[5] = 0xffff; 291 memcpy(&mapped.s6_addr32[3], &sin->sin_addr, 292 sizeof(mapped.s6_addr32[3])); 293 t6 = in6_pcblookup_port(table, &mapped, lport, wild); 294 if (t6 && (reuseport & t6->in6p_socket->so_options) == 0) 295 return (EADDRINUSE); 296 #endif 297 if (so->so_uidinfo->ui_uid && !IN_MULTICAST(sin->sin_addr.s_addr)) { 298 t = in_pcblookup_port(table, sin->sin_addr, lport, 1); 299 /* 300 * XXX: investigate ramifications of loosening this 301 * restriction so that as long as both ports have 302 * SO_REUSEPORT allow the bind 303 */ 304 if (t && 305 (!in_nullhost(sin->sin_addr) || 306 !in_nullhost(t->inp_laddr) || 307 (t->inp_socket->so_options & SO_REUSEPORT) == 0) 308 && (so->so_uidinfo->ui_uid != t->inp_socket->so_uidinfo->ui_uid)) { 309 return (EADDRINUSE); 310 } 311 } 312 t = in_pcblookup_port(table, sin->sin_addr, lport, wild); 313 if (t && (reuseport & t->inp_socket->so_options) == 0) 314 return (EADDRINUSE); 315 } 316 inp->inp_laddr = sin->sin_addr; 317 318 noname: 319 if (lport == 0) { 320 int cnt; 321 u_int16_t mymin, mymax; 322 u_int16_t *lastport; 323 324 if (inp->inp_flags & INP_LOWPORT) { 325 #ifndef IPNOPRIVPORTS 326 if (kauth_authorize_network(cred, 327 KAUTH_NETWORK_BIND, 328 KAUTH_REQ_NETWORK_BIND_PRIVPORT, so, 329 sin, NULL)) 330 return (EACCES); 331 #endif 332 mymin = lowportmin; 333 mymax = lowportmax; 334 lastport = &table->inpt_lastlow; 335 } else { 336 mymin = anonportmin; 337 mymax = anonportmax; 338 lastport = &table->inpt_lastport; 339 } 340 if (mymin > mymax) { /* sanity check */ 341 u_int16_t swp; 342 343 swp = mymin; 344 mymin = mymax; 345 mymax = swp; 346 } 347 348 lport = *lastport - 1; 349 for (cnt = mymax - mymin + 1; cnt; cnt--, lport--) { 350 if (lport < mymin || lport > mymax) 351 lport = mymax; 352 if (!in_pcblookup_port(table, inp->inp_laddr, 353 htons(lport), 1)) 354 goto found; 355 } 356 if (!in_nullhost(inp->inp_laddr)) 357 inp->inp_laddr.s_addr = INADDR_ANY; 358 return (EAGAIN); 359 found: 360 inp->inp_flags |= INP_ANONPORT; 361 *lastport = lport; 362 lport = htons(lport); 363 } 364 inp->inp_lport = lport; 365 LIST_REMOVE(&inp->inp_head, inph_lhash); 366 LIST_INSERT_HEAD(INPCBHASH_PORT(table, inp->inp_lport), &inp->inp_head, 367 inph_lhash); 368 in_pcbstate(inp, INP_BOUND); 369 return (0); 370 } 371 372 /* 373 * Connect from a socket to a specified address. 374 * Both address and port must be specified in argument sin. 375 * If don't have a local address for this socket yet, 376 * then pick one. 377 */ 378 int 379 in_pcbconnect(void *v, struct mbuf *nam, struct lwp *l) 380 { 381 struct inpcb *inp = v; 382 struct in_ifaddr *ia = NULL; 383 struct sockaddr_in *ifaddr = NULL; 384 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 385 int error; 386 387 if (inp->inp_af != AF_INET) 388 return (EINVAL); 389 390 if (nam->m_len != sizeof (*sin)) 391 return (EINVAL); 392 if (sin->sin_family != AF_INET) 393 return (EAFNOSUPPORT); 394 if (sin->sin_port == 0) 395 return (EADDRNOTAVAIL); 396 if (TAILQ_FIRST(&in_ifaddrhead) != 0) { 397 /* 398 * If the destination address is INADDR_ANY, 399 * use any local address (likely loopback). 400 * If the supplied address is INADDR_BROADCAST, 401 * use the broadcast address of an interface 402 * which supports broadcast. (loopback does not) 403 */ 404 405 if (in_nullhost(sin->sin_addr)) { 406 sin->sin_addr = 407 TAILQ_FIRST(&in_ifaddrhead)->ia_addr.sin_addr; 408 } else if (sin->sin_addr.s_addr == INADDR_BROADCAST) { 409 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list) { 410 if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 411 sin->sin_addr = 412 ia->ia_broadaddr.sin_addr; 413 break; 414 } 415 } 416 } 417 } 418 /* 419 * If we haven't bound which network number to use as ours, 420 * we will use the number of the outgoing interface. 421 * This depends on having done a routing lookup, which 422 * we will probably have to do anyway, so we might 423 * as well do it now. On the other hand if we are 424 * sending to multiple destinations we may have already 425 * done the lookup, so see if we can use the route 426 * from before. In any case, we only 427 * chose a port number once, even if sending to multiple 428 * destinations. 429 */ 430 if (in_nullhost(inp->inp_laddr)) { 431 int xerror; 432 ifaddr = in_selectsrc(sin, &inp->inp_route, 433 inp->inp_socket->so_options, inp->inp_moptions, &xerror); 434 if (ifaddr == NULL) { 435 if (xerror == 0) 436 xerror = EADDRNOTAVAIL; 437 return xerror; 438 } 439 INADDR_TO_IA(ifaddr->sin_addr, ia); 440 if (ia == NULL) 441 return (EADDRNOTAVAIL); 442 } 443 if (in_pcblookup_connect(inp->inp_table, sin->sin_addr, sin->sin_port, 444 !in_nullhost(inp->inp_laddr) ? inp->inp_laddr : ifaddr->sin_addr, 445 inp->inp_lport) != 0) 446 return (EADDRINUSE); 447 if (in_nullhost(inp->inp_laddr)) { 448 if (inp->inp_lport == 0) { 449 error = in_pcbbind(inp, NULL, l); 450 /* 451 * This used to ignore the return value 452 * completely, but we need to check for 453 * ephemeral port shortage. 454 * And attempts to request low ports if not root. 455 */ 456 if (error != 0) 457 return (error); 458 } 459 inp->inp_laddr = ifaddr->sin_addr; 460 } 461 inp->inp_faddr = sin->sin_addr; 462 inp->inp_fport = sin->sin_port; 463 in_pcbstate(inp, INP_CONNECTED); 464 #if defined(IPSEC) || defined(FAST_IPSEC) 465 if (inp->inp_socket->so_type == SOCK_STREAM) 466 ipsec_pcbconn(inp->inp_sp); 467 #endif 468 return (0); 469 } 470 471 void 472 in_pcbdisconnect(void *v) 473 { 474 struct inpcb *inp = v; 475 476 if (inp->inp_af != AF_INET) 477 return; 478 479 inp->inp_faddr = zeroin_addr; 480 inp->inp_fport = 0; 481 in_pcbstate(inp, INP_BOUND); 482 #if defined(IPSEC) || defined(FAST_IPSEC) 483 ipsec_pcbdisconn(inp->inp_sp); 484 #endif 485 if (inp->inp_socket->so_state & SS_NOFDREF) 486 in_pcbdetach(inp); 487 } 488 489 void 490 in_pcbdetach(void *v) 491 { 492 struct inpcb *inp = v; 493 struct socket *so = inp->inp_socket; 494 int s; 495 496 if (inp->inp_af != AF_INET) 497 return; 498 499 #if defined(IPSEC) || defined(FAST_IPSEC) 500 ipsec4_delete_pcbpolicy(inp); 501 #endif /*IPSEC*/ 502 so->so_pcb = 0; 503 if (inp->inp_options) 504 (void)m_free(inp->inp_options); 505 rtcache_free(&inp->inp_route); 506 ip_freemoptions(inp->inp_moptions); 507 s = splnet(); 508 in_pcbstate(inp, INP_ATTACHED); 509 LIST_REMOVE(&inp->inp_head, inph_lhash); 510 CIRCLEQ_REMOVE(&inp->inp_table->inpt_queue, &inp->inp_head, 511 inph_queue); 512 pool_put(&inpcb_pool, inp); 513 splx(s); 514 sofree(so); /* drops the socket's lock */ 515 mutex_enter(softnet_lock); /* reacquire the softnet_lock */ 516 } 517 518 void 519 in_setsockaddr(struct inpcb *inp, struct mbuf *nam) 520 { 521 struct sockaddr_in *sin; 522 523 if (inp->inp_af != AF_INET) 524 return; 525 526 sin = mtod(nam, struct sockaddr_in *); 527 sockaddr_in_init(sin, &inp->inp_laddr, inp->inp_lport); 528 nam->m_len = sin->sin_len; 529 } 530 531 void 532 in_setpeeraddr(struct inpcb *inp, struct mbuf *nam) 533 { 534 struct sockaddr_in *sin; 535 536 if (inp->inp_af != AF_INET) 537 return; 538 539 sin = mtod(nam, struct sockaddr_in *); 540 sockaddr_in_init(sin, &inp->inp_faddr, inp->inp_fport); 541 nam->m_len = sin->sin_len; 542 } 543 544 /* 545 * Pass some notification to all connections of a protocol 546 * associated with address dst. The local address and/or port numbers 547 * may be specified to limit the search. The "usual action" will be 548 * taken, depending on the ctlinput cmd. The caller must filter any 549 * cmds that are uninteresting (e.g., no error in the map). 550 * Call the protocol specific routine (if any) to report 551 * any errors for each matching socket. 552 * 553 * Must be called at splsoftnet. 554 */ 555 int 556 in_pcbnotify(struct inpcbtable *table, struct in_addr faddr, u_int fport_arg, 557 struct in_addr laddr, u_int lport_arg, int errno, 558 void (*notify)(struct inpcb *, int)) 559 { 560 struct inpcbhead *head; 561 struct inpcb *inp, *ninp; 562 u_int16_t fport = fport_arg, lport = lport_arg; 563 int nmatch; 564 565 if (in_nullhost(faddr) || notify == 0) 566 return (0); 567 568 nmatch = 0; 569 head = INPCBHASH_CONNECT(table, faddr, fport, laddr, lport); 570 for (inp = (struct inpcb *)LIST_FIRST(head); inp != NULL; inp = ninp) { 571 ninp = (struct inpcb *)LIST_NEXT(inp, inp_hash); 572 if (inp->inp_af != AF_INET) 573 continue; 574 if (in_hosteq(inp->inp_faddr, faddr) && 575 inp->inp_fport == fport && 576 inp->inp_lport == lport && 577 in_hosteq(inp->inp_laddr, laddr)) { 578 (*notify)(inp, errno); 579 nmatch++; 580 } 581 } 582 return (nmatch); 583 } 584 585 void 586 in_pcbnotifyall(struct inpcbtable *table, struct in_addr faddr, int errno, 587 void (*notify)(struct inpcb *, int)) 588 { 589 struct inpcb *inp, *ninp; 590 591 if (in_nullhost(faddr) || notify == 0) 592 return; 593 594 for (inp = (struct inpcb *)CIRCLEQ_FIRST(&table->inpt_queue); 595 inp != (void *)&table->inpt_queue; 596 inp = ninp) { 597 ninp = (struct inpcb *)CIRCLEQ_NEXT(inp, inp_queue); 598 if (inp->inp_af != AF_INET) 599 continue; 600 if (in_hosteq(inp->inp_faddr, faddr)) 601 (*notify)(inp, errno); 602 } 603 } 604 605 void 606 in_pcbpurgeif0(struct inpcbtable *table, struct ifnet *ifp) 607 { 608 struct inpcb *inp, *ninp; 609 struct ip_moptions *imo; 610 int i, gap; 611 612 for (inp = (struct inpcb *)CIRCLEQ_FIRST(&table->inpt_queue); 613 inp != (void *)&table->inpt_queue; 614 inp = ninp) { 615 ninp = (struct inpcb *)CIRCLEQ_NEXT(inp, inp_queue); 616 if (inp->inp_af != AF_INET) 617 continue; 618 imo = inp->inp_moptions; 619 if (imo != NULL) { 620 /* 621 * Unselect the outgoing interface if it is being 622 * detached. 623 */ 624 if (imo->imo_multicast_ifp == ifp) 625 imo->imo_multicast_ifp = NULL; 626 627 /* 628 * Drop multicast group membership if we joined 629 * through the interface being detached. 630 */ 631 for (i = 0, gap = 0; i < imo->imo_num_memberships; 632 i++) { 633 if (imo->imo_membership[i]->inm_ifp == ifp) { 634 in_delmulti(imo->imo_membership[i]); 635 gap++; 636 } else if (gap != 0) 637 imo->imo_membership[i - gap] = 638 imo->imo_membership[i]; 639 } 640 imo->imo_num_memberships -= gap; 641 } 642 } 643 } 644 645 void 646 in_pcbpurgeif(struct inpcbtable *table, struct ifnet *ifp) 647 { 648 struct rtentry *rt; 649 struct inpcb *inp, *ninp; 650 651 for (inp = (struct inpcb *)CIRCLEQ_FIRST(&table->inpt_queue); 652 inp != (void *)&table->inpt_queue; 653 inp = ninp) { 654 ninp = (struct inpcb *)CIRCLEQ_NEXT(inp, inp_queue); 655 if (inp->inp_af != AF_INET) 656 continue; 657 if ((rt = rtcache_validate(&inp->inp_route)) != NULL && 658 rt->rt_ifp == ifp) 659 in_rtchange(inp, 0); 660 } 661 } 662 663 /* 664 * Check for alternatives when higher level complains 665 * about service problems. For now, invalidate cached 666 * routing information. If the route was created dynamically 667 * (by a redirect), time to try a default gateway again. 668 */ 669 void 670 in_losing(struct inpcb *inp) 671 { 672 struct rtentry *rt; 673 struct rt_addrinfo info; 674 675 if (inp->inp_af != AF_INET) 676 return; 677 678 if ((rt = rtcache_validate(&inp->inp_route)) == NULL) 679 return; 680 681 memset(&info, 0, sizeof(info)); 682 info.rti_info[RTAX_DST] = rtcache_getdst(&inp->inp_route); 683 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 684 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 685 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); 686 if (rt->rt_flags & RTF_DYNAMIC) 687 (void) rtrequest(RTM_DELETE, rt_getkey(rt), 688 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 689 NULL); 690 /* 691 * A new route can be allocated 692 * the next time output is attempted. 693 */ 694 rtcache_free(&inp->inp_route); 695 } 696 697 /* 698 * After a routing change, flush old routing. A new route can be 699 * allocated the next time output is attempted. 700 */ 701 void 702 in_rtchange(struct inpcb *inp, int errno) 703 { 704 705 if (inp->inp_af != AF_INET) 706 return; 707 708 rtcache_free(&inp->inp_route); 709 710 /* XXX SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */ 711 } 712 713 struct inpcb * 714 in_pcblookup_port(struct inpcbtable *table, struct in_addr laddr, 715 u_int lport_arg, int lookup_wildcard) 716 { 717 struct inpcbhead *head; 718 struct inpcb_hdr *inph; 719 struct inpcb *inp, *match = 0; 720 int matchwild = 3, wildcard; 721 u_int16_t lport = lport_arg; 722 723 head = INPCBHASH_PORT(table, lport); 724 LIST_FOREACH(inph, head, inph_lhash) { 725 inp = (struct inpcb *)inph; 726 if (inp->inp_af != AF_INET) 727 continue; 728 729 if (inp->inp_lport != lport) 730 continue; 731 wildcard = 0; 732 if (!in_nullhost(inp->inp_faddr)) 733 wildcard++; 734 if (in_nullhost(inp->inp_laddr)) { 735 if (!in_nullhost(laddr)) 736 wildcard++; 737 } else { 738 if (in_nullhost(laddr)) 739 wildcard++; 740 else { 741 if (!in_hosteq(inp->inp_laddr, laddr)) 742 continue; 743 } 744 } 745 if (wildcard && !lookup_wildcard) 746 continue; 747 if (wildcard < matchwild) { 748 match = inp; 749 matchwild = wildcard; 750 if (matchwild == 0) 751 break; 752 } 753 } 754 return (match); 755 } 756 757 #ifdef DIAGNOSTIC 758 int in_pcbnotifymiss = 0; 759 #endif 760 761 struct inpcb * 762 in_pcblookup_connect(struct inpcbtable *table, 763 struct in_addr faddr, u_int fport_arg, 764 struct in_addr laddr, u_int lport_arg) 765 { 766 struct inpcbhead *head; 767 struct inpcb_hdr *inph; 768 struct inpcb *inp; 769 u_int16_t fport = fport_arg, lport = lport_arg; 770 771 head = INPCBHASH_CONNECT(table, faddr, fport, laddr, lport); 772 LIST_FOREACH(inph, head, inph_hash) { 773 inp = (struct inpcb *)inph; 774 if (inp->inp_af != AF_INET) 775 continue; 776 777 if (in_hosteq(inp->inp_faddr, faddr) && 778 inp->inp_fport == fport && 779 inp->inp_lport == lport && 780 in_hosteq(inp->inp_laddr, laddr)) 781 goto out; 782 } 783 #ifdef DIAGNOSTIC 784 if (in_pcbnotifymiss) { 785 printf("in_pcblookup_connect: faddr=%08x fport=%d laddr=%08x lport=%d\n", 786 ntohl(faddr.s_addr), ntohs(fport), 787 ntohl(laddr.s_addr), ntohs(lport)); 788 } 789 #endif 790 return (0); 791 792 out: 793 /* Move this PCB to the head of hash chain. */ 794 inph = &inp->inp_head; 795 if (inph != LIST_FIRST(head)) { 796 LIST_REMOVE(inph, inph_hash); 797 LIST_INSERT_HEAD(head, inph, inph_hash); 798 } 799 return (inp); 800 } 801 802 struct inpcb * 803 in_pcblookup_bind(struct inpcbtable *table, 804 struct in_addr laddr, u_int lport_arg) 805 { 806 struct inpcbhead *head; 807 struct inpcb_hdr *inph; 808 struct inpcb *inp; 809 u_int16_t lport = lport_arg; 810 811 head = INPCBHASH_BIND(table, laddr, lport); 812 LIST_FOREACH(inph, head, inph_hash) { 813 inp = (struct inpcb *)inph; 814 if (inp->inp_af != AF_INET) 815 continue; 816 817 if (inp->inp_lport == lport && 818 in_hosteq(inp->inp_laddr, laddr)) 819 goto out; 820 } 821 head = INPCBHASH_BIND(table, zeroin_addr, lport); 822 LIST_FOREACH(inph, head, inph_hash) { 823 inp = (struct inpcb *)inph; 824 if (inp->inp_af != AF_INET) 825 continue; 826 827 if (inp->inp_lport == lport && 828 in_hosteq(inp->inp_laddr, zeroin_addr)) 829 goto out; 830 } 831 #ifdef DIAGNOSTIC 832 if (in_pcbnotifymiss) { 833 printf("in_pcblookup_bind: laddr=%08x lport=%d\n", 834 ntohl(laddr.s_addr), ntohs(lport)); 835 } 836 #endif 837 return (0); 838 839 out: 840 /* Move this PCB to the head of hash chain. */ 841 inph = &inp->inp_head; 842 if (inph != LIST_FIRST(head)) { 843 LIST_REMOVE(inph, inph_hash); 844 LIST_INSERT_HEAD(head, inph, inph_hash); 845 } 846 return (inp); 847 } 848 849 void 850 in_pcbstate(struct inpcb *inp, int state) 851 { 852 853 if (inp->inp_af != AF_INET) 854 return; 855 856 if (inp->inp_state > INP_ATTACHED) 857 LIST_REMOVE(&inp->inp_head, inph_hash); 858 859 switch (state) { 860 case INP_BOUND: 861 LIST_INSERT_HEAD(INPCBHASH_BIND(inp->inp_table, 862 inp->inp_laddr, inp->inp_lport), &inp->inp_head, 863 inph_hash); 864 break; 865 case INP_CONNECTED: 866 LIST_INSERT_HEAD(INPCBHASH_CONNECT(inp->inp_table, 867 inp->inp_faddr, inp->inp_fport, 868 inp->inp_laddr, inp->inp_lport), &inp->inp_head, 869 inph_hash); 870 break; 871 } 872 873 inp->inp_state = state; 874 } 875 876 struct rtentry * 877 in_pcbrtentry(struct inpcb *inp) 878 { 879 struct route *ro; 880 union { 881 struct sockaddr dst; 882 struct sockaddr_in dst4; 883 } u; 884 885 if (inp->inp_af != AF_INET) 886 return (NULL); 887 888 ro = &inp->inp_route; 889 890 sockaddr_in_init(&u.dst4, &inp->inp_faddr, 0); 891 return rtcache_lookup(ro, &u.dst); 892 } 893 894 struct sockaddr_in * 895 in_selectsrc(struct sockaddr_in *sin, struct route *ro, 896 int soopts, struct ip_moptions *mopts, int *errorp) 897 { 898 struct rtentry *rt = NULL; 899 struct in_ifaddr *ia = NULL; 900 901 /* 902 * If route is known or can be allocated now, take the 903 * source address from the interface. Otherwise, punt. 904 */ 905 if ((soopts & SO_DONTROUTE) != 0) 906 rtcache_free(ro); 907 else { 908 union { 909 struct sockaddr dst; 910 struct sockaddr_in dst4; 911 } u; 912 913 sockaddr_in_init(&u.dst4, &sin->sin_addr, 0); 914 rt = rtcache_lookup(ro, &u.dst); 915 } 916 /* 917 * If we found a route, use the address 918 * corresponding to the outgoing interface 919 * unless it is the loopback (in case a route 920 * to our address on another net goes to loopback). 921 * 922 * XXX Is this still true? Do we care? 923 */ 924 if (rt != NULL && (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) 925 ia = ifatoia(rt->rt_ifa); 926 if (ia == NULL) { 927 u_int16_t fport = sin->sin_port; 928 929 sin->sin_port = 0; 930 ia = ifatoia(ifa_ifwithladdr(sintosa(sin))); 931 sin->sin_port = fport; 932 if (ia == NULL) { 933 /* Find 1st non-loopback AF_INET address */ 934 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list) { 935 if (!(ia->ia_ifp->if_flags & IFF_LOOPBACK)) 936 break; 937 } 938 } 939 if (ia == NULL) { 940 *errorp = EADDRNOTAVAIL; 941 return NULL; 942 } 943 } 944 /* 945 * If the destination address is multicast and an outgoing 946 * interface has been set as a multicast option, use the 947 * address of that interface as our source address. 948 */ 949 if (IN_MULTICAST(sin->sin_addr.s_addr) && mopts != NULL) { 950 struct ip_moptions *imo; 951 struct ifnet *ifp; 952 953 imo = mopts; 954 if (imo->imo_multicast_ifp != NULL) { 955 ifp = imo->imo_multicast_ifp; 956 IFP_TO_IA(ifp, ia); /* XXX */ 957 if (ia == 0) { 958 *errorp = EADDRNOTAVAIL; 959 return NULL; 960 } 961 } 962 } 963 if (ia->ia_ifa.ifa_getifa != NULL) { 964 ia = ifatoia((*ia->ia_ifa.ifa_getifa)(&ia->ia_ifa, 965 sintosa(sin))); 966 } 967 #ifdef GETIFA_DEBUG 968 else 969 printf("%s: missing ifa_getifa\n", __func__); 970 #endif 971 return satosin(&ia->ia_addr); 972 } 973