Deleted Added
full compact
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 ---