in_pcb.c (185371) | in_pcb.c (185435) |
---|---|
1/*- 2 * Copyright (c) 1982, 1986, 1991, 1993, 1995 3 * The Regents of the University of California. 4 * Copyright (c) 2007 Robert N. M. Watson 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 --- 18 unchanged lines hidden (view full) --- 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 * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95 32 */ 33 34#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1982, 1986, 1991, 1993, 1995 3 * The Regents of the University of California. 4 * Copyright (c) 2007 Robert N. M. Watson 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 --- 18 unchanged lines hidden (view full) --- 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 * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95 32 */ 33 34#include <sys/cdefs.h> |
35__FBSDID("$FreeBSD: head/sys/netinet/in_pcb.c 185371 2008-11-27 13:19:42Z bz $"); | 35__FBSDID("$FreeBSD: head/sys/netinet/in_pcb.c 185435 2008-11-29 14:32:14Z bz $"); |
36 37#include "opt_ddb.h" 38#include "opt_ipsec.h" 39#include "opt_inet6.h" 40#include "opt_mac.h" 41 42#include <sys/param.h> 43#include <sys/systm.h> --- 245 unchanged lines hidden (view full) --- 289 INIT_VNET_INET(inp->inp_vnet); 290 struct socket *so = inp->inp_socket; 291 unsigned short *lastport; 292 struct sockaddr_in *sin; 293 struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 294 struct in_addr laddr; 295 u_short lport = 0; 296 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); | 36 37#include "opt_ddb.h" 38#include "opt_ipsec.h" 39#include "opt_inet6.h" 40#include "opt_mac.h" 41 42#include <sys/param.h> 43#include <sys/systm.h> --- 245 unchanged lines hidden (view full) --- 289 INIT_VNET_INET(inp->inp_vnet); 290 struct socket *so = inp->inp_socket; 291 unsigned short *lastport; 292 struct sockaddr_in *sin; 293 struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 294 struct in_addr laddr; 295 u_short lport = 0; 296 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); |
297 int error, prison = 0; | 297 int error; |
298 int dorandom; 299 300 /* 301 * Because no actual state changes occur here, a global write lock on 302 * the pcbinfo isn't required. 303 */ 304 INP_INFO_LOCK_ASSERT(pcbinfo); 305 INP_LOCK_ASSERT(inp); --- 12 unchanged lines hidden (view full) --- 318#ifdef notdef 319 /* 320 * We should check the family, but old programs 321 * incorrectly fail to initialize it. 322 */ 323 if (sin->sin_family != AF_INET) 324 return (EAFNOSUPPORT); 325#endif | 298 int dorandom; 299 300 /* 301 * Because no actual state changes occur here, a global write lock on 302 * the pcbinfo isn't required. 303 */ 304 INP_INFO_LOCK_ASSERT(pcbinfo); 305 INP_LOCK_ASSERT(inp); --- 12 unchanged lines hidden (view full) --- 318#ifdef notdef 319 /* 320 * We should check the family, but old programs 321 * incorrectly fail to initialize it. 322 */ 323 if (sin->sin_family != AF_INET) 324 return (EAFNOSUPPORT); 325#endif |
326 if (sin->sin_addr.s_addr != INADDR_ANY) 327 if (prison_ip(cred, 0, &sin->sin_addr.s_addr)) 328 return(EINVAL); | 326 if (prison_local_ip4(cred, &sin->sin_addr)) 327 return (EINVAL); |
329 if (sin->sin_port != *lportp) { 330 /* Don't allow the port to change. */ 331 if (*lportp != 0) 332 return (EINVAL); 333 lport = sin->sin_port; 334 } 335 /* NB: lport is left as 0 if the port isn't being changed. */ 336 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { --- 18 unchanged lines hidden (view full) --- 355 struct tcptw *tw; 356 357 /* GROSS */ 358 if (ntohs(lport) <= V_ipport_reservedhigh && 359 ntohs(lport) >= V_ipport_reservedlow && 360 priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 361 0)) 362 return (EACCES); | 328 if (sin->sin_port != *lportp) { 329 /* Don't allow the port to change. */ 330 if (*lportp != 0) 331 return (EINVAL); 332 lport = sin->sin_port; 333 } 334 /* NB: lport is left as 0 if the port isn't being changed. */ 335 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { --- 18 unchanged lines hidden (view full) --- 354 struct tcptw *tw; 355 356 /* GROSS */ 357 if (ntohs(lport) <= V_ipport_reservedhigh && 358 ntohs(lport) >= V_ipport_reservedlow && 359 priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 360 0)) 361 return (EACCES); |
363 if (jailed(cred)) 364 prison = 1; | |
365 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) && 366 priv_check_cred(inp->inp_cred, 367 PRIV_NETINET_REUSEPORT, 0) != 0) { 368 t = in_pcblookup_local(pcbinfo, sin->sin_addr, | 362 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) && 363 priv_check_cred(inp->inp_cred, 364 PRIV_NETINET_REUSEPORT, 0) != 0) { 365 t = in_pcblookup_local(pcbinfo, sin->sin_addr, |
369 lport, prison ? 0 : INPLOOKUP_WILDCARD, 370 cred); | 366 lport, INPLOOKUP_WILDCARD, cred); |
371 /* 372 * XXX 373 * This entire block sorely needs a rewrite. 374 */ 375 if (t && 376 ((t->inp_vflag & INP_TIMEWAIT) == 0) && 377 (so->so_type != SOCK_STREAM || 378 ntohl(t->inp_faddr.s_addr) == INADDR_ANY) && 379 (ntohl(sin->sin_addr.s_addr) != INADDR_ANY || 380 ntohl(t->inp_laddr.s_addr) != INADDR_ANY || 381 (t->inp_socket->so_options & 382 SO_REUSEPORT) == 0) && 383 (inp->inp_cred->cr_uid != 384 t->inp_cred->cr_uid)) 385 return (EADDRINUSE); 386 } | 367 /* 368 * XXX 369 * This entire block sorely needs a rewrite. 370 */ 371 if (t && 372 ((t->inp_vflag & INP_TIMEWAIT) == 0) && 373 (so->so_type != SOCK_STREAM || 374 ntohl(t->inp_faddr.s_addr) == INADDR_ANY) && 375 (ntohl(sin->sin_addr.s_addr) != INADDR_ANY || 376 ntohl(t->inp_laddr.s_addr) != INADDR_ANY || 377 (t->inp_socket->so_options & 378 SO_REUSEPORT) == 0) && 379 (inp->inp_cred->cr_uid != 380 t->inp_cred->cr_uid)) 381 return (EADDRINUSE); 382 } |
387 if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr)) | 383 if (prison_local_ip4(cred, &sin->sin_addr)) |
388 return (EADDRNOTAVAIL); 389 t = in_pcblookup_local(pcbinfo, sin->sin_addr, | 384 return (EADDRNOTAVAIL); 385 t = in_pcblookup_local(pcbinfo, sin->sin_addr, |
390 lport, prison ? 0 : wild, cred); | 386 lport, wild, cred); |
391 if (t && (t->inp_vflag & INP_TIMEWAIT)) { 392 /* 393 * XXXRW: If an incpb has had its timewait 394 * state recycled, we treat the address as 395 * being in use (for now). This is better 396 * than a panic, but not desirable. 397 */ 398 tw = intotw(inp); --- 15 unchanged lines hidden (view full) --- 414 } 415 } 416 if (*lportp != 0) 417 lport = *lportp; 418 if (lport == 0) { 419 u_short first, last, aux; 420 int count; 421 | 387 if (t && (t->inp_vflag & INP_TIMEWAIT)) { 388 /* 389 * XXXRW: If an incpb has had its timewait 390 * state recycled, we treat the address as 391 * being in use (for now). This is better 392 * than a panic, but not desirable. 393 */ 394 tw = intotw(inp); --- 15 unchanged lines hidden (view full) --- 410 } 411 } 412 if (*lportp != 0) 413 lport = *lportp; 414 if (lport == 0) { 415 u_short first, last, aux; 416 int count; 417 |
422 if (laddr.s_addr != INADDR_ANY) 423 if (prison_ip(cred, 0, &laddr.s_addr)) 424 return (EINVAL); | 418 if (prison_local_ip4(cred, &laddr)) 419 return (EINVAL); |
425 426 if (inp->inp_flags & INP_HIGHPORT) { 427 first = V_ipport_hifirstauto; /* sysctl */ 428 last = V_ipport_hilastauto; 429 lastport = &pcbinfo->ipi_lasthi; 430 } else if (inp->inp_flags & INP_LOWPORT) { 431 error = priv_check_cred(cred, 432 PRIV_NETINET_RESERVEDPORT, 0); --- 49 unchanged lines hidden (view full) --- 482 return (EADDRNOTAVAIL); 483 ++*lastport; 484 if (*lastport < first || *lastport > last) 485 *lastport = first; 486 lport = htons(*lastport); 487 } while (in_pcblookup_local(pcbinfo, laddr, 488 lport, wild, cred)); 489 } | 420 421 if (inp->inp_flags & INP_HIGHPORT) { 422 first = V_ipport_hifirstauto; /* sysctl */ 423 last = V_ipport_hilastauto; 424 lastport = &pcbinfo->ipi_lasthi; 425 } else if (inp->inp_flags & INP_LOWPORT) { 426 error = priv_check_cred(cred, 427 PRIV_NETINET_RESERVEDPORT, 0); --- 49 unchanged lines hidden (view full) --- 477 return (EADDRNOTAVAIL); 478 ++*lastport; 479 if (*lastport < first || *lastport > last) 480 *lastport = first; 481 lport = htons(*lastport); 482 } while (in_pcblookup_local(pcbinfo, laddr, 483 lport, wild, cred)); 484 } |
490 if (prison_ip(cred, 0, &laddr.s_addr)) | 485 if (prison_local_ip4(cred, &laddr)) |
491 return (EINVAL); 492 *laddrp = laddr.s_addr; 493 *lportp = lport; 494 return (0); 495} 496 497/* 498 * Connect from a socket to a specified address. --- 52 unchanged lines hidden (view full) --- 551{ 552 struct in_ifaddr *ia; 553 struct ifaddr *ifa; 554 struct sockaddr *sa; 555 struct sockaddr_in *sin; 556 struct route sro; 557 int error; 558 | 486 return (EINVAL); 487 *laddrp = laddr.s_addr; 488 *lportp = lport; 489 return (0); 490} 491 492/* 493 * Connect from a socket to a specified address. --- 52 unchanged lines hidden (view full) --- 546{ 547 struct in_ifaddr *ia; 548 struct ifaddr *ifa; 549 struct sockaddr *sa; 550 struct sockaddr_in *sin; 551 struct route sro; 552 int error; 553 |
559 KASSERT(laddr != NULL, ("%s: null laddr", __func__)); | 554 KASSERT(laddr != NULL, ("%s: laddr NULL", __func__)); |
560 561 error = 0; 562 ia = NULL; 563 bzero(&sro, sizeof(sro)); 564 565 sin = (struct sockaddr_in *)&sro.ro_dst; 566 sin->sin_family = AF_INET; 567 sin->sin_len = sizeof(struct sockaddr_in); --- 35 unchanged lines hidden (view full) --- 603 ifp = ia->ia_ifp; 604 ia = NULL; 605 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 606 607 sa = ifa->ifa_addr; 608 if (sa->sa_family != AF_INET) 609 continue; 610 sin = (struct sockaddr_in *)sa; | 555 556 error = 0; 557 ia = NULL; 558 bzero(&sro, sizeof(sro)); 559 560 sin = (struct sockaddr_in *)&sro.ro_dst; 561 sin->sin_family = AF_INET; 562 sin->sin_len = sizeof(struct sockaddr_in); --- 35 unchanged lines hidden (view full) --- 598 ifp = ia->ia_ifp; 599 ia = NULL; 600 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 601 602 sa = ifa->ifa_addr; 603 if (sa->sa_family != AF_INET) 604 continue; 605 sin = (struct sockaddr_in *)sa; |
611 if (htonl(prison_getip(cred)) == sin->sin_addr.s_addr) { | 606 if (prison_check_ip4(cred, &sin->sin_addr)) { |
612 ia = (struct in_ifaddr *)ifa; 613 break; 614 } 615 } 616 if (ia != NULL) { 617 laddr->s_addr = ia->ia_addr.sin_addr.s_addr; 618 goto done; 619 } 620 621 /* 3. As a last resort return the 'default' jail address. */ | 607 ia = (struct in_ifaddr *)ifa; 608 break; 609 } 610 } 611 if (ia != NULL) { 612 laddr->s_addr = ia->ia_addr.sin_addr.s_addr; 613 goto done; 614 } 615 616 /* 3. As a last resort return the 'default' jail address. */ |
622 laddr->s_addr = htonl(prison_getip(cred)); | 617 if (prison_getip4(cred, laddr) != 0) 618 error = EADDRNOTAVAIL; |
623 goto done; 624 } 625 626 /* 627 * If the outgoing interface on the route found is not 628 * a loopback interface, use the address from that interface. 629 * In case of jails do those three steps: 630 * 1. check if the interface address belongs to the jail. If so use it. --- 8 unchanged lines hidden (view full) --- 639 ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa; 640 laddr->s_addr = ia->ia_addr.sin_addr.s_addr; 641 goto done; 642 } 643 644 /* Jailed. */ 645 /* 1. Check if the iface address belongs to the jail. */ 646 sin = (struct sockaddr_in *)sro.ro_rt->rt_ifa->ifa_addr; | 619 goto done; 620 } 621 622 /* 623 * If the outgoing interface on the route found is not 624 * a loopback interface, use the address from that interface. 625 * In case of jails do those three steps: 626 * 1. check if the interface address belongs to the jail. If so use it. --- 8 unchanged lines hidden (view full) --- 635 ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa; 636 laddr->s_addr = ia->ia_addr.sin_addr.s_addr; 637 goto done; 638 } 639 640 /* Jailed. */ 641 /* 1. Check if the iface address belongs to the jail. */ 642 sin = (struct sockaddr_in *)sro.ro_rt->rt_ifa->ifa_addr; |
647 if (htonl(prison_getip(cred)) == sin->sin_addr.s_addr) { | 643 if (prison_check_ip4(cred, &sin->sin_addr)) { |
648 ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa; 649 laddr->s_addr = ia->ia_addr.sin_addr.s_addr; 650 goto done; 651 } 652 653 /* 654 * 2. Check if we have any address on the outgoing interface 655 * belonging to this jail. 656 */ 657 TAILQ_FOREACH(ifa, &sro.ro_rt->rt_ifp->if_addrhead, ifa_link) { 658 659 sa = ifa->ifa_addr; 660 if (sa->sa_family != AF_INET) 661 continue; 662 sin = (struct sockaddr_in *)sa; | 644 ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa; 645 laddr->s_addr = ia->ia_addr.sin_addr.s_addr; 646 goto done; 647 } 648 649 /* 650 * 2. Check if we have any address on the outgoing interface 651 * belonging to this jail. 652 */ 653 TAILQ_FOREACH(ifa, &sro.ro_rt->rt_ifp->if_addrhead, ifa_link) { 654 655 sa = ifa->ifa_addr; 656 if (sa->sa_family != AF_INET) 657 continue; 658 sin = (struct sockaddr_in *)sa; |
663 if (htonl(prison_getip(cred)) == sin->sin_addr.s_addr) { | 659 if (prison_check_ip4(cred, &sin->sin_addr)) { |
664 ia = (struct in_ifaddr *)ifa; 665 break; 666 } 667 } 668 if (ia != NULL) { 669 laddr->s_addr = ia->ia_addr.sin_addr.s_addr; 670 goto done; 671 } 672 673 /* 3. As a last resort return the 'default' jail address. */ | 660 ia = (struct in_ifaddr *)ifa; 661 break; 662 } 663 } 664 if (ia != NULL) { 665 laddr->s_addr = ia->ia_addr.sin_addr.s_addr; 666 goto done; 667 } 668 669 /* 3. As a last resort return the 'default' jail address. */ |
674 laddr->s_addr = htonl(prison_getip(cred)); | 670 if (prison_getip4(cred, laddr) != 0) 671 error = EADDRNOTAVAIL; |
675 goto done; 676 } 677 678 /* 679 * The outgoing interface is marked with 'loopback net', so a route 680 * to ourselves is here. 681 * Try to find the interface of the destination address and then 682 * take the address from there. That interface is not necessarily --- 29 unchanged lines hidden (view full) --- 712 ifp = ia->ia_ifp; 713 ia = NULL; 714 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 715 716 sa = ifa->ifa_addr; 717 if (sa->sa_family != AF_INET) 718 continue; 719 sin = (struct sockaddr_in *)sa; | 672 goto done; 673 } 674 675 /* 676 * The outgoing interface is marked with 'loopback net', so a route 677 * to ourselves is here. 678 * Try to find the interface of the destination address and then 679 * take the address from there. That interface is not necessarily --- 29 unchanged lines hidden (view full) --- 709 ifp = ia->ia_ifp; 710 ia = NULL; 711 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 712 713 sa = ifa->ifa_addr; 714 if (sa->sa_family != AF_INET) 715 continue; 716 sin = (struct sockaddr_in *)sa; |
720 if (htonl(prison_getip(cred)) == 721 sin->sin_addr.s_addr) { | 717 if (prison_check_ip4(cred, &sin->sin_addr)) { |
722 ia = (struct in_ifaddr *)ifa; 723 break; 724 } 725 } 726 if (ia != NULL) { 727 laddr->s_addr = ia->ia_addr.sin_addr.s_addr; 728 goto done; 729 } 730 } 731 732 /* 3. As a last resort return the 'default' jail address. */ | 718 ia = (struct in_ifaddr *)ifa; 719 break; 720 } 721 } 722 if (ia != NULL) { 723 laddr->s_addr = ia->ia_addr.sin_addr.s_addr; 724 goto done; 725 } 726 } 727 728 /* 3. As a last resort return the 'default' jail address. */ |
733 laddr->s_addr = htonl(prison_getip(cred)); | 729 if (prison_getip4(cred, laddr) != 0) 730 error = EADDRNOTAVAIL; |
734 goto done; 735 } 736 737done: 738 if (sro.ro_rt != NULL) 739 RTFREE(sro.ro_rt); 740 return (error); 741} --- 17 unchanged lines hidden (view full) --- 759in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam, 760 in_addr_t *laddrp, u_short *lportp, in_addr_t *faddrp, u_short *fportp, 761 struct inpcb **oinpp, struct ucred *cred) 762{ 763 INIT_VNET_INET(inp->inp_vnet); 764 struct sockaddr_in *sin = (struct sockaddr_in *)nam; 765 struct in_ifaddr *ia; 766 struct inpcb *oinp; | 731 goto done; 732 } 733 734done: 735 if (sro.ro_rt != NULL) 736 RTFREE(sro.ro_rt); 737 return (error); 738} --- 17 unchanged lines hidden (view full) --- 756in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam, 757 in_addr_t *laddrp, u_short *lportp, in_addr_t *faddrp, u_short *fportp, 758 struct inpcb **oinpp, struct ucred *cred) 759{ 760 INIT_VNET_INET(inp->inp_vnet); 761 struct sockaddr_in *sin = (struct sockaddr_in *)nam; 762 struct in_ifaddr *ia; 763 struct inpcb *oinp; |
767 struct in_addr laddr, faddr; | 764 struct in_addr laddr, faddr, jailia; |
768 u_short lport, fport; 769 int error; 770 771 /* 772 * Because a global state change doesn't actually occur here, a read 773 * lock is sufficient. 774 */ 775 INP_INFO_LOCK_ASSERT(inp->inp_pcbinfo); --- 15 unchanged lines hidden (view full) --- 791 if (!TAILQ_EMPTY(&V_in_ifaddrhead)) { 792 /* 793 * If the destination address is INADDR_ANY, 794 * use the primary local address. 795 * If the supplied address is INADDR_BROADCAST, 796 * and the primary interface supports broadcast, 797 * choose the broadcast address for that interface. 798 */ | 765 u_short lport, fport; 766 int error; 767 768 /* 769 * Because a global state change doesn't actually occur here, a read 770 * lock is sufficient. 771 */ 772 INP_INFO_LOCK_ASSERT(inp->inp_pcbinfo); --- 15 unchanged lines hidden (view full) --- 788 if (!TAILQ_EMPTY(&V_in_ifaddrhead)) { 789 /* 790 * If the destination address is INADDR_ANY, 791 * use the primary local address. 792 * If the supplied address is INADDR_BROADCAST, 793 * and the primary interface supports broadcast, 794 * choose the broadcast address for that interface. 795 */ |
799 if (faddr.s_addr == INADDR_ANY) 800 faddr = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr; 801 else if (faddr.s_addr == (u_long)INADDR_BROADCAST && | 796 if (faddr.s_addr == INADDR_ANY) { 797 if (cred != NULL && jailed(cred)) { 798 if (prison_getip4(cred, &jailia) != 0) 799 return (EADDRNOTAVAIL); 800 faddr.s_addr = jailia.s_addr; 801 } else { 802 faddr = 803 IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))-> 804 sin_addr; 805 } 806 } else if (faddr.s_addr == (u_long)INADDR_BROADCAST && |
802 (TAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags & 803 IFF_BROADCAST)) 804 faddr = satosin(&TAILQ_FIRST( 805 &V_in_ifaddrhead)->ia_broadaddr)->sin_addr; 806 } 807 if (laddr.s_addr == INADDR_ANY) { 808 error = in_pcbladdr(inp, &faddr, &laddr, cred); 809 if (error) --- 300 unchanged lines hidden (view full) --- 1110 /* 1111 * Look for an unconnected (wildcard foreign addr) PCB that 1112 * matches the local address and port we're looking for. 1113 */ 1114 head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport, 1115 0, pcbinfo->ipi_hashmask)]; 1116 LIST_FOREACH(inp, head, inp_hash) { 1117#ifdef INET6 | 807 (TAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags & 808 IFF_BROADCAST)) 809 faddr = satosin(&TAILQ_FIRST( 810 &V_in_ifaddrhead)->ia_broadaddr)->sin_addr; 811 } 812 if (laddr.s_addr == INADDR_ANY) { 813 error = in_pcbladdr(inp, &faddr, &laddr, cred); 814 if (error) --- 300 unchanged lines hidden (view full) --- 1115 /* 1116 * Look for an unconnected (wildcard foreign addr) PCB that 1117 * matches the local address and port we're looking for. 1118 */ 1119 head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport, 1120 0, pcbinfo->ipi_hashmask)]; 1121 LIST_FOREACH(inp, head, inp_hash) { 1122#ifdef INET6 |
1123 /* XXX inp locking */ |
|
1118 if ((inp->inp_vflag & INP_IPV4) == 0) 1119 continue; 1120#endif 1121 if (inp->inp_faddr.s_addr == INADDR_ANY && 1122 inp->inp_laddr.s_addr == laddr.s_addr && 1123 inp->inp_lport == lport) { 1124 /* | 1124 if ((inp->inp_vflag & INP_IPV4) == 0) 1125 continue; 1126#endif 1127 if (inp->inp_faddr.s_addr == INADDR_ANY && 1128 inp->inp_laddr.s_addr == laddr.s_addr && 1129 inp->inp_lport == lport) { 1130 /* |
1125 * Found. | 1131 * Found? |
1126 */ | 1132 */ |
1127 return (inp); | 1133 if (cred == NULL || 1134 inp->inp_cred->cr_prison == cred->cr_prison) 1135 return (inp); |
1128 } 1129 } 1130 /* 1131 * Not found. 1132 */ 1133 return (NULL); 1134 } else { 1135 struct inpcbporthead *porthash; --- 13 unchanged lines hidden (view full) --- 1149 } 1150 if (phd != NULL) { 1151 /* 1152 * Port is in use by one or more PCBs. Look for best 1153 * fit. 1154 */ 1155 LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) { 1156 wildcard = 0; | 1136 } 1137 } 1138 /* 1139 * Not found. 1140 */ 1141 return (NULL); 1142 } else { 1143 struct inpcbporthead *porthash; --- 13 unchanged lines hidden (view full) --- 1157 } 1158 if (phd != NULL) { 1159 /* 1160 * Port is in use by one or more PCBs. Look for best 1161 * fit. 1162 */ 1163 LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) { 1164 wildcard = 0; |
1165 if (cred != NULL && 1166 inp->inp_cred->cr_prison != cred->cr_prison) 1167 continue; |
|
1157#ifdef INET6 | 1168#ifdef INET6 |
1169 /* XXX inp locking */ |
|
1158 if ((inp->inp_vflag & INP_IPV4) == 0) 1159 continue; 1160 /* 1161 * We never select the PCB that has 1162 * INP_IPV6 flag and is bound to :: if 1163 * we have another PCB which is bound 1164 * to 0.0.0.0. If a PCB has the 1165 * INP_IPV6 flag, then we set its cost --- 16 unchanged lines hidden (view full) --- 1182 continue; 1183 } else { 1184 if (laddr.s_addr != INADDR_ANY) 1185 wildcard++; 1186 } 1187 if (wildcard < matchwild) { 1188 match = inp; 1189 matchwild = wildcard; | 1170 if ((inp->inp_vflag & INP_IPV4) == 0) 1171 continue; 1172 /* 1173 * We never select the PCB that has 1174 * INP_IPV6 flag and is bound to :: if 1175 * we have another PCB which is bound 1176 * to 0.0.0.0. If a PCB has the 1177 * INP_IPV6 flag, then we set its cost --- 16 unchanged lines hidden (view full) --- 1194 continue; 1195 } else { 1196 if (laddr.s_addr != INADDR_ANY) 1197 wildcard++; 1198 } 1199 if (wildcard < matchwild) { 1200 match = inp; 1201 matchwild = wildcard; |
1190 if (matchwild == 0) { | 1202 if (matchwild == 0) |
1191 break; | 1203 break; |
1192 } | |
1193 } 1194 } 1195 } 1196 return (match); 1197 } 1198} 1199#undef INP_LOOKUP_MAPPED_PCB_COST 1200 1201/* 1202 * Lookup PCB in hash list. 1203 */ 1204struct inpcb * 1205in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr, 1206 u_int fport_arg, struct in_addr laddr, u_int lport_arg, int wildcard, 1207 struct ifnet *ifp) 1208{ 1209 struct inpcbhead *head; | 1204 } 1205 } 1206 } 1207 return (match); 1208 } 1209} 1210#undef INP_LOOKUP_MAPPED_PCB_COST 1211 1212/* 1213 * Lookup PCB in hash list. 1214 */ 1215struct inpcb * 1216in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr, 1217 u_int fport_arg, struct in_addr laddr, u_int lport_arg, int wildcard, 1218 struct ifnet *ifp) 1219{ 1220 struct inpcbhead *head; |
1210 struct inpcb *inp; | 1221 struct inpcb *inp, *tmpinp; |
1211 u_short fport = fport_arg, lport = lport_arg; 1212 1213 INP_INFO_LOCK_ASSERT(pcbinfo); 1214 1215 /* 1216 * First look for an exact match. 1217 */ | 1222 u_short fport = fport_arg, lport = lport_arg; 1223 1224 INP_INFO_LOCK_ASSERT(pcbinfo); 1225 1226 /* 1227 * First look for an exact match. 1228 */ |
1229 tmpinp = NULL; |
|
1218 head = &pcbinfo->ipi_hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, 1219 pcbinfo->ipi_hashmask)]; 1220 LIST_FOREACH(inp, head, inp_hash) { 1221#ifdef INET6 | 1230 head = &pcbinfo->ipi_hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, 1231 pcbinfo->ipi_hashmask)]; 1232 LIST_FOREACH(inp, head, inp_hash) { 1233#ifdef INET6 |
1234 /* XXX inp locking */ |
|
1222 if ((inp->inp_vflag & INP_IPV4) == 0) 1223 continue; 1224#endif 1225 if (inp->inp_faddr.s_addr == faddr.s_addr && 1226 inp->inp_laddr.s_addr == laddr.s_addr && 1227 inp->inp_fport == fport && | 1235 if ((inp->inp_vflag & INP_IPV4) == 0) 1236 continue; 1237#endif 1238 if (inp->inp_faddr.s_addr == faddr.s_addr && 1239 inp->inp_laddr.s_addr == laddr.s_addr && 1240 inp->inp_fport == fport && |
1228 inp->inp_lport == lport) 1229 return (inp); | 1241 inp->inp_lport == lport) { 1242 /* 1243 * XXX We should be able to directly return 1244 * the inp here, without any checks. 1245 * Well unless both bound with SO_REUSEPORT? 1246 */ 1247 if (jailed(inp->inp_cred)) 1248 return (inp); 1249 if (tmpinp == NULL) 1250 tmpinp = inp; 1251 } |
1230 } | 1252 } |
1253 if (tmpinp != NULL) 1254 return (tmpinp); |
|
1231 1232 /* 1233 * Then look for a wildcard match, if requested. 1234 */ | 1255 1256 /* 1257 * Then look for a wildcard match, if requested. 1258 */ |
1235 if (wildcard) { 1236 struct inpcb *local_wild = NULL; | 1259 if (wildcard == INPLOOKUP_WILDCARD) { 1260 struct inpcb *local_wild = NULL, *local_exact = NULL; |
1237#ifdef INET6 1238 struct inpcb *local_wild_mapped = NULL; 1239#endif | 1261#ifdef INET6 1262 struct inpcb *local_wild_mapped = NULL; 1263#endif |
1264 struct inpcb *jail_wild = NULL; 1265 int injail; |
|
1240 | 1266 |
1267 /* 1268 * Order of socket selection - we always prefer jails. 1269 * 1. jailed, non-wild. 1270 * 2. jailed, wild. 1271 * 3. non-jailed, non-wild. 1272 * 4. non-jailed, wild. 1273 */ 1274 |
|
1241 head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport, 1242 0, pcbinfo->ipi_hashmask)]; 1243 LIST_FOREACH(inp, head, inp_hash) { 1244#ifdef INET6 | 1275 head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport, 1276 0, pcbinfo->ipi_hashmask)]; 1277 LIST_FOREACH(inp, head, inp_hash) { 1278#ifdef INET6 |
1279 /* XXX inp locking */ |
|
1245 if ((inp->inp_vflag & INP_IPV4) == 0) 1246 continue; 1247#endif | 1280 if ((inp->inp_vflag & INP_IPV4) == 0) 1281 continue; 1282#endif |
1248 if (inp->inp_faddr.s_addr == INADDR_ANY && 1249 inp->inp_lport == lport) { 1250 if (ifp && ifp->if_type == IFT_FAITH && 1251 (inp->inp_flags & INP_FAITH) == 0) | 1283 if (inp->inp_faddr.s_addr != INADDR_ANY || 1284 inp->inp_lport != lport) 1285 continue; 1286 1287 /* XXX inp locking */ 1288 if (ifp && ifp->if_type == IFT_FAITH && 1289 (inp->inp_flags & INP_FAITH) == 0) 1290 continue; 1291 1292 injail = jailed(inp->inp_cred); 1293 if (injail) { 1294 if (!prison_check_ip4(inp->inp_cred, &laddr)) |
1252 continue; | 1295 continue; |
1253 if (inp->inp_laddr.s_addr == laddr.s_addr) | 1296 } else { 1297 if (local_exact != NULL) 1298 continue; 1299 } 1300 1301 if (inp->inp_laddr.s_addr == laddr.s_addr) { 1302 if (injail) |
1254 return (inp); | 1303 return (inp); |
1255 else if (inp->inp_laddr.s_addr == INADDR_ANY) { | 1304 else 1305 local_exact = inp; 1306 } else if (inp->inp_laddr.s_addr == INADDR_ANY) { |
1256#ifdef INET6 | 1307#ifdef INET6 |
1257 if (inp->inp_vflag & INP_IPV6PROTO) 1258 local_wild_mapped = inp; | 1308 /* XXX inp locking, NULL check */ 1309 if (inp->inp_vflag & INP_IPV6PROTO) 1310 local_wild_mapped = inp; 1311 else 1312#endif /* INET6 */ 1313 if (injail) 1314 jail_wild = inp; |
1259 else | 1315 else |
1260#endif | |
1261 local_wild = inp; | 1316 local_wild = inp; |
1262 } | |
1263 } | 1317 } |
1264 } | 1318 } /* LIST_FOREACH */ 1319 if (jail_wild != NULL) 1320 return (jail_wild); 1321 if (local_exact != NULL) 1322 return (local_exact); 1323 if (local_wild != NULL) 1324 return (local_wild); |
1265#ifdef INET6 | 1325#ifdef INET6 |
1266 if (local_wild == NULL) | 1326 if (local_wild_mapped != NULL) |
1267 return (local_wild_mapped); | 1327 return (local_wild_mapped); |
1268#endif 1269 return (local_wild); 1270 } | 1328#endif /* defined(INET6) */ 1329 } /* if (wildcard == INPLOOKUP_WILDCARD) */ 1330 |
1271 return (NULL); 1272} 1273 1274/* 1275 * Insert PCB onto various hash lists. 1276 */ 1277int 1278in_pcbinshash(struct inpcb *inp) --- 515 unchanged lines hidden --- | 1331 return (NULL); 1332} 1333 1334/* 1335 * Insert PCB onto various hash lists. 1336 */ 1337int 1338in_pcbinshash(struct inpcb *inp) --- 515 unchanged lines hidden --- |