in6_pcb.c (185370) | in6_pcb.c (185435) |
---|---|
1/*- 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * 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 --- 47 unchanged lines hidden (view full) --- 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94 61 */ 62 63#include <sys/cdefs.h> | 1/*- 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * 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 --- 47 unchanged lines hidden (view full) --- 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94 61 */ 62 63#include <sys/cdefs.h> |
64__FBSDID("$FreeBSD: head/sys/netinet6/in6_pcb.c 185370 2008-11-27 12:04:35Z bz $"); | 64__FBSDID("$FreeBSD: head/sys/netinet6/in6_pcb.c 185435 2008-11-29 14:32:14Z bz $"); |
65 66#include "opt_inet.h" 67#include "opt_inet6.h" 68#include "opt_ipsec.h" 69#include "opt_mac.h" 70 71#include <sys/param.h> 72#include <sys/systm.h> --- 65 unchanged lines hidden (view full) --- 138 * family check. 139 */ 140 if (nam->sa_family != AF_INET6) 141 return (EAFNOSUPPORT); 142 143 if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) 144 return(error); 145 | 65 66#include "opt_inet.h" 67#include "opt_inet6.h" 68#include "opt_ipsec.h" 69#include "opt_mac.h" 70 71#include <sys/param.h> 72#include <sys/systm.h> --- 65 unchanged lines hidden (view full) --- 138 * family check. 139 */ 140 if (nam->sa_family != AF_INET6) 141 return (EAFNOSUPPORT); 142 143 if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) 144 return(error); 145 |
146 if (prison_local_ip6(cred, &sin6->sin6_addr, 147 ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) 148 return (EINVAL); 149 |
|
146 lport = sin6->sin6_port; 147 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 148 /* 149 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 150 * allow compepte duplication of binding if 151 * SO_REUSEPORT is set, or if SO_REUSEADDR is set 152 * and a multicast address is bound on both 153 * new and duplicated sockets. --- 58 unchanged lines hidden (view full) --- 212 (so->so_type != SOCK_STREAM || 213 ntohl(t->inp_faddr.s_addr) == 214 INADDR_ANY) && 215 (inp->inp_cred->cr_uid != 216 t->inp_cred->cr_uid)) 217 return (EADDRINUSE); 218 } 219 } | 150 lport = sin6->sin6_port; 151 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 152 /* 153 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 154 * allow compepte duplication of binding if 155 * SO_REUSEPORT is set, or if SO_REUSEADDR is set 156 * and a multicast address is bound on both 157 * new and duplicated sockets. --- 58 unchanged lines hidden (view full) --- 216 (so->so_type != SOCK_STREAM || 217 ntohl(t->inp_faddr.s_addr) == 218 INADDR_ANY) && 219 (inp->inp_cred->cr_uid != 220 t->inp_cred->cr_uid)) 221 return (EADDRINUSE); 222 } 223 } |
224 if (prison_local_ip6(cred, &sin6->sin6_addr, 225 ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) 226 return (EADDRNOTAVAIL); |
|
220 t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr, 221 lport, wild, cred); 222 if (t && (reuseport & ((t->inp_vflag & INP_TIMEWAIT) ? 223 intotw(t)->tw_so_options : 224 t->inp_socket->so_options)) == 0) 225 return (EADDRINUSE); 226 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && 227 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { --- 16 unchanged lines hidden (view full) --- 244 == 0 && (ntohl(t->inp_laddr.s_addr) != 245 INADDR_ANY || INP_SOCKAF(so) == 246 INP_SOCKAF(t->inp_socket))) 247 return (EADDRINUSE); 248 } 249 } 250 inp->in6p_laddr = sin6->sin6_addr; 251 } | 227 t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr, 228 lport, wild, cred); 229 if (t && (reuseport & ((t->inp_vflag & INP_TIMEWAIT) ? 230 intotw(t)->tw_so_options : 231 t->inp_socket->so_options)) == 0) 232 return (EADDRINUSE); 233 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && 234 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { --- 16 unchanged lines hidden (view full) --- 251 == 0 && (ntohl(t->inp_laddr.s_addr) != 252 INADDR_ANY || INP_SOCKAF(so) == 253 INP_SOCKAF(t->inp_socket))) 254 return (EADDRINUSE); 255 } 256 } 257 inp->in6p_laddr = sin6->sin6_addr; 258 } |
259 if (prison_local_ip6(cred, &inp->in6p_laddr, 260 ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) 261 return (EINVAL); |
|
252 if (lport == 0) { 253 int e; 254 if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0) 255 return (e); 256 } else { 257 inp->inp_lport = lport; 258 if (in_pcbinshash(inp) != 0) { 259 inp->in6p_laddr = in6addr_any; --- 43 unchanged lines hidden (view full) --- 303 if (V_in6_ifaddr) { 304 /* 305 * If the destination address is UNSPECIFIED addr, 306 * use the loopback addr, e.g ::1. 307 */ 308 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 309 sin6->sin6_addr = in6addr_loopback; 310 } | 262 if (lport == 0) { 263 int e; 264 if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0) 265 return (e); 266 } else { 267 inp->inp_lport = lport; 268 if (in_pcbinshash(inp) != 0) { 269 inp->in6p_laddr = in6addr_any; --- 43 unchanged lines hidden (view full) --- 313 if (V_in6_ifaddr) { 314 /* 315 * If the destination address is UNSPECIFIED addr, 316 * use the loopback addr, e.g ::1. 317 */ 318 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 319 sin6->sin6_addr = in6addr_loopback; 320 } |
321 if (prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr) != 0) 322 return (EADDRNOTAVAIL); |
|
311 312 /* 313 * XXX: in6_selectsrc might replace the bound local address 314 * with the address specified by setsockopt(IPV6_PKTINFO). 315 * Is it the intended behavior? 316 */ 317 *plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts, 318 inp, NULL, --- 325 unchanged lines hidden (view full) --- 644 struct inpcbhead *head; 645 /* 646 * Look for an unconnected (wildcard foreign addr) PCB that 647 * matches the local address and port we're looking for. 648 */ 649 head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport, 650 0, pcbinfo->ipi_hashmask)]; 651 LIST_FOREACH(inp, head, inp_hash) { | 323 324 /* 325 * XXX: in6_selectsrc might replace the bound local address 326 * with the address specified by setsockopt(IPV6_PKTINFO). 327 * Is it the intended behavior? 328 */ 329 *plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts, 330 inp, NULL, --- 325 unchanged lines hidden (view full) --- 656 struct inpcbhead *head; 657 /* 658 * Look for an unconnected (wildcard foreign addr) PCB that 659 * matches the local address and port we're looking for. 660 */ 661 head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport, 662 0, pcbinfo->ipi_hashmask)]; 663 LIST_FOREACH(inp, head, inp_hash) { |
664 /* XXX inp locking */ |
|
652 if ((inp->inp_vflag & INP_IPV6) == 0) 653 continue; 654 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) && 655 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) && 656 inp->inp_lport == lport) { | 665 if ((inp->inp_vflag & INP_IPV6) == 0) 666 continue; 667 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) && 668 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) && 669 inp->inp_lport == lport) { |
657 /* 658 * Found. 659 */ 660 return (inp); | 670 /* Found. */ 671 if (cred == NULL || 672 inp->inp_cred->cr_prison == cred->cr_prison) 673 return (inp); |
661 } 662 } 663 /* 664 * Not found. 665 */ 666 return (NULL); 667 } else { 668 struct inpcbporthead *porthash; --- 13 unchanged lines hidden (view full) --- 682 } 683 if (phd != NULL) { 684 /* 685 * Port is in use by one or more PCBs. Look for best 686 * fit. 687 */ 688 LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) { 689 wildcard = 0; | 674 } 675 } 676 /* 677 * Not found. 678 */ 679 return (NULL); 680 } else { 681 struct inpcbporthead *porthash; --- 13 unchanged lines hidden (view full) --- 695 } 696 if (phd != NULL) { 697 /* 698 * Port is in use by one or more PCBs. Look for best 699 * fit. 700 */ 701 LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) { 702 wildcard = 0; |
703 if (cred != NULL && 704 inp->inp_cred->cr_prison != cred->cr_prison) 705 continue; 706 /* XXX inp locking */ |
|
690 if ((inp->inp_vflag & INP_IPV6) == 0) 691 continue; 692 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) 693 wildcard++; 694 if (!IN6_IS_ADDR_UNSPECIFIED( 695 &inp->in6p_laddr)) { 696 if (IN6_IS_ADDR_UNSPECIFIED(laddr)) 697 wildcard++; 698 else if (!IN6_ARE_ADDR_EQUAL( | 707 if ((inp->inp_vflag & INP_IPV6) == 0) 708 continue; 709 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) 710 wildcard++; 711 if (!IN6_IS_ADDR_UNSPECIFIED( 712 &inp->in6p_laddr)) { 713 if (IN6_IS_ADDR_UNSPECIFIED(laddr)) 714 wildcard++; 715 else if (!IN6_ARE_ADDR_EQUAL( |
699 &inp->in6p_laddr, laddr)) | 716 &inp->in6p_laddr, laddr)) |
700 continue; 701 } else { 702 if (!IN6_IS_ADDR_UNSPECIFIED(laddr)) 703 wildcard++; 704 } 705 if (wildcard < matchwild) { 706 match = inp; 707 matchwild = wildcard; | 717 continue; 718 } else { 719 if (!IN6_IS_ADDR_UNSPECIFIED(laddr)) 720 wildcard++; 721 } 722 if (wildcard < matchwild) { 723 match = inp; 724 matchwild = wildcard; |
708 if (matchwild == 0) { | 725 if (matchwild == 0) |
709 break; | 726 break; |
710 } | |
711 } 712 } 713 } 714 return (match); 715 } 716} 717 718void --- 66 unchanged lines hidden (view full) --- 785 return inp; 786} 787 788/* 789 * Lookup PCB in hash list. 790 */ 791struct inpcb * 792in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, | 727 } 728 } 729 } 730 return (match); 731 } 732} 733 734void --- 66 unchanged lines hidden (view full) --- 801 return inp; 802} 803 804/* 805 * Lookup PCB in hash list. 806 */ 807struct inpcb * 808in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, |
793 u_int fport_arg, struct in6_addr *laddr, u_int lport_arg, 794 int wildcard, struct ifnet *ifp) | 809 u_int fport_arg, struct in6_addr *laddr, u_int lport_arg, int wildcard, 810 struct ifnet *ifp) |
795{ 796 struct inpcbhead *head; | 811{ 812 struct inpcbhead *head; |
797 register struct inpcb *inp; | 813 struct inpcb *inp, *tmpinp; |
798 u_short fport = fport_arg, lport = lport_arg; 799 int faith; 800 801 INP_INFO_LOCK_ASSERT(pcbinfo); 802 803 if (faithprefix_p != NULL) 804 faith = (*faithprefix_p)(laddr); 805 else 806 faith = 0; 807 808 /* 809 * First look for an exact match. 810 */ | 814 u_short fport = fport_arg, lport = lport_arg; 815 int faith; 816 817 INP_INFO_LOCK_ASSERT(pcbinfo); 818 819 if (faithprefix_p != NULL) 820 faith = (*faithprefix_p)(laddr); 821 else 822 faith = 0; 823 824 /* 825 * First look for an exact match. 826 */ |
827 tmpinp = NULL; |
|
811 head = &pcbinfo->ipi_hashbase[ 812 INP_PCBHASH(faddr->s6_addr32[3] /* XXX */, lport, fport, 813 pcbinfo->ipi_hashmask)]; 814 LIST_FOREACH(inp, head, inp_hash) { | 828 head = &pcbinfo->ipi_hashbase[ 829 INP_PCBHASH(faddr->s6_addr32[3] /* XXX */, lport, fport, 830 pcbinfo->ipi_hashmask)]; 831 LIST_FOREACH(inp, head, inp_hash) { |
832 /* XXX inp locking */ |
|
815 if ((inp->inp_vflag & INP_IPV6) == 0) 816 continue; 817 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) && 818 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) && 819 inp->inp_fport == fport && 820 inp->inp_lport == lport) { 821 /* | 833 if ((inp->inp_vflag & INP_IPV6) == 0) 834 continue; 835 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) && 836 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) && 837 inp->inp_fport == fport && 838 inp->inp_lport == lport) { 839 /* |
822 * Found. | 840 * XXX We should be able to directly return 841 * the inp here, without any checks. 842 * Well unless both bound with SO_REUSEPORT? |
823 */ | 843 */ |
824 return (inp); | 844 if (jailed(inp->inp_cred)) 845 return (inp); 846 if (tmpinp == NULL) 847 tmpinp = inp; |
825 } 826 } | 848 } 849 } |
827 if (wildcard) { 828 struct inpcb *local_wild = NULL; | 850 if (tmpinp != NULL) 851 return (tmpinp); |
829 | 852 |
853 /* 854 * Then look for a wildcard match, if requested. 855 */ 856 if (wildcard == INPLOOKUP_WILDCARD) { 857 struct inpcb *local_wild = NULL, *local_exact = NULL; 858 struct inpcb *jail_wild = NULL; 859 int injail; 860 861 /* 862 * Order of socket selection - we always prefer jails. 863 * 1. jailed, non-wild. 864 * 2. jailed, wild. 865 * 3. non-jailed, non-wild. 866 * 4. non-jailed, wild. 867 */ |
|
830 head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport, 831 0, pcbinfo->ipi_hashmask)]; 832 LIST_FOREACH(inp, head, inp_hash) { | 868 head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport, 869 0, pcbinfo->ipi_hashmask)]; 870 LIST_FOREACH(inp, head, inp_hash) { |
871 /* XXX inp locking */ |
|
833 if ((inp->inp_vflag & INP_IPV6) == 0) 834 continue; | 872 if ((inp->inp_vflag & INP_IPV6) == 0) 873 continue; |
835 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) && 836 inp->inp_lport == lport) { 837 if (faith && (inp->inp_flags & INP_FAITH) == 0) | 874 875 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) || 876 inp->inp_lport != lport) { 877 continue; 878 } 879 880 /* XXX inp locking */ 881 if (faith && (inp->inp_flags & INP_FAITH) == 0) 882 continue; 883 884 injail = jailed(inp->inp_cred); 885 if (injail) { 886 if (!prison_check_ip6(inp->inp_cred, laddr)) |
838 continue; | 887 continue; |
839 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, 840 laddr)) | 888 } else { 889 if (local_exact != NULL) 890 continue; 891 } 892 893 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr)) { 894 if (injail) |
841 return (inp); | 895 return (inp); |
842 else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) | 896 else 897 local_exact = inp; 898 } else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { 899 if (injail) 900 jail_wild = inp; 901 else |
843 local_wild = inp; 844 } | 902 local_wild = inp; 903 } |
845 } 846 return (local_wild); 847 } | 904 } /* LIST_FOREACH */ |
848 | 905 |
906 if (jail_wild != NULL) 907 return (jail_wild); 908 if (local_exact != NULL) 909 return (local_exact); 910 if (local_wild != NULL) 911 return (local_wild); 912 } /* if (wildcard == INPLOOKUP_WILDCARD) */ 913 |
|
849 /* 850 * Not found. 851 */ 852 return (NULL); 853} 854 855void 856init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m) --- 13 unchanged lines hidden --- | 914 /* 915 * Not found. 916 */ 917 return (NULL); 918} 919 920void 921init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m) --- 13 unchanged lines hidden --- |