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