diff options
author | pjd <pjd@FreeBSD.org> | 2009-06-01 10:30:00 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2009-06-01 10:30:00 +0000 |
commit | 5243d2d206ac372ee679c11bde715a4a4f2f93fd (patch) | |
tree | ce73855429371a51ef92709203be008be66b6119 /sys | |
parent | eb2d64c1bdd4159506f34e57ff8df73c843b7500 (diff) | |
download | FreeBSD-src-5243d2d206ac372ee679c11bde715a4a4f2f93fd.zip FreeBSD-src-5243d2d206ac372ee679c11bde715a4a4f2f93fd.tar.gz |
- Rename IP_NONLOCALOK IP socket option to IP_BINDANY, to be more consistent
with OpenBSD (and BSD/OS originally). We can't easly do it SOL_SOCKET option
as there is no more space for more SOL_SOCKET options, but this option also
fits better as an IP socket option, it seems.
- Implement this functionality also for IPv6 and RAW IP sockets.
- Always compile it in (don't use additional kernel options).
- Remove sysctl to turn this functionality on and off.
- Introduce new privilege - PRIV_NETINET_BINDANY, which allows to use this
functionality (currently only unjail root can use it).
Discussed with: julian, adrian, jhb, rwatson, kmacy
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/NOTES | 8 | ||||
-rw-r--r-- | sys/conf/options | 1 | ||||
-rw-r--r-- | sys/netinet/in.h | 3 | ||||
-rw-r--r-- | sys/netinet/in_pcb.c | 10 | ||||
-rw-r--r-- | sys/netinet/in_pcb.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 25 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 9 | ||||
-rw-r--r-- | sys/netinet6/in6.h | 2 | ||||
-rw-r--r-- | sys/netinet6/in6_pcb.c | 6 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 15 | ||||
-rw-r--r-- | sys/sys/priv.h | 1 |
11 files changed, 40 insertions, 43 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 4770064..2402802 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -639,14 +639,6 @@ options ALTQ_PRIQ # Priority Queueing options ALTQ_NOPCC # Required if the TSC is unusable options ALTQ_DEBUG -# IP optional behaviour. -# IP_NONLOCALBIND disables the check that bind() usually makes that the -# address is one that is assigned to an interface on this machine. -# It allows transparent proxies to pretend to be other machines. -# How the packet GET to that machine is a problem solved elsewhere, -# smart routers, ipfw fwd, etc. -options IP_NONLOCALBIND # Allow impersonation for proxies. - # netgraph(4). Enable the base netgraph code with the NETGRAPH option. # Individual node types can be enabled with the corresponding option # listed below; however, this is not strictly necessary as netgraph diff --git a/sys/conf/options b/sys/conf/options index a668ea5..426d983 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -400,7 +400,6 @@ IPFIREWALL_VERBOSE opt_ipfw.h IPFIREWALL_VERBOSE_LIMIT opt_ipfw.h IPSEC opt_ipsec.h IPSEC_DEBUG opt_ipsec.h -IP_NONLOCALBIND opt_inet.h IPSEC_FILTERTUNNEL opt_ipsec.h IPSTEALTH IPX diff --git a/sys/netinet/in.h b/sys/netinet/in.h index dd302a5..ad07aba 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -441,8 +441,7 @@ __END_DECLS #define IP_FAITH 22 /* bool; accept FAITH'ed connections */ #define IP_ONESBCAST 23 /* bool: send all-ones broadcast */ -#define IP_NONLOCALOK 24 /* bool: allow bind to spoof non-local addresses; - requires kernel compile option IP_NONLOCALBIND */ +#define IP_BINDANY 24 /* bool: allow bind to any address */ #define IP_FW_TABLE_ADD 40 /* add entry */ #define IP_FW_TABLE_DEL 41 /* delete entry */ diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index b507fbf..0b4ef27 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" -#include "opt_inet.h" #include "opt_ipsec.h" #include "opt_inet6.h" #include "opt_mac.h" @@ -357,14 +356,11 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, bzero(&sin->sin_zero, sizeof(sin->sin_zero)); /* * Is the address a local IP address? - * If INP_NONLOCALOK is set, then the socket may be bound + * If INP_BINDANY is set, then the socket may be bound * to any endpoint address, local or not. */ - if ( -#if defined(IP_NONLOCALBIND) - ((inp->inp_flags & INP_NONLOCALOK) == 0) && -#endif - (ifa_ifwithaddr((struct sockaddr *)sin) == 0)) + if ((inp->inp_flags & INP_BINDANY) == 0 && + ifa_ifwithaddr((struct sockaddr *)sin) == NULL) return (EADDRNOTAVAIL); } laddr = sin->sin_addr; diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index aa30e43..da1e80d 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -410,8 +410,7 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp, #define INP_FAITH 0x00000200 /* accept FAITH'ed connections */ #define INP_RECVTTL 0x00000400 /* receive incoming IP TTL */ #define INP_DONTFRAG 0x00000800 /* don't fragment packet */ -#define INP_NONLOCALOK 0x00001000 /* Allow bind to spoof any address */ - /* - requires options IP_NONLOCALBIND */ +#define INP_BINDANY 0x00001000 /* allow bind to any address */ #define INP_INHASHLIST 0x00002000 /* in_pcbinshash() has been called */ #define IN6P_IPV6_V6ONLY 0x00008000 /* restrict AF_INET6 socket for v6 */ #define IN6P_PKTINFO 0x00010000 /* receive IP6 dst and I/F */ diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 6e4f879..65e06a0 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -33,7 +33,6 @@ __FBSDID("$FreeBSD$"); #include "opt_ipfw.h" -#include "opt_inet.h" #include "opt_ipsec.h" #include "opt_route.h" #include "opt_mac.h" @@ -103,12 +102,6 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_frag_size, CTLFLAG_RW, &mbuf_frag_size, 0, "Fragment outgoing mbufs to this size"); #endif -#if defined(IP_NONLOCALBIND) -static int ip_nonlocalok = 0; -SYSCTL_INT(_net_inet_ip, OID_AUTO, nonlocalok, - CTLFLAG_RW|CTLFLAG_SECURE, &ip_nonlocalok, 0, ""); -#endif - static void ip_mloopback (struct ifnet *, struct mbuf *, struct sockaddr_in *, int); @@ -931,14 +924,14 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt) return (error); } -#if defined(IP_NONLOCALBIND) - case IP_NONLOCALOK: - if (! ip_nonlocalok) { - error = ENOPROTOOPT; - break; + case IP_BINDANY: + if (sopt->sopt_td != NULL) { + error = priv_check(sopt->sopt_td, + PRIV_NETINET_BINDANY); + if (error) + break; } /* FALLTHROUGH */ -#endif case IP_TOS: case IP_TTL: case IP_MINTTL: @@ -1010,11 +1003,9 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt) case IP_DONTFRAG: OPTSET(INP_DONTFRAG); break; -#if defined(IP_NONLOCALBIND) - case IP_NONLOCALOK: - OPTSET(INP_NONLOCALOK); + case IP_BINDANY: + OPTSET(INP_BINDANY); break; -#endif } break; #undef OPTSET diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 695a9cb..080ab09 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -853,15 +853,16 @@ rip_bind(struct socket *so, struct sockaddr *nam, struct thread *td) if (error != 0) return (error); + inp = sotoinpcb(so); + KASSERT(inp != NULL, ("rip_bind: inp == NULL")); + if (TAILQ_EMPTY(&V_ifnet) || (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) || (addr->sin_addr.s_addr && - ifa_ifwithaddr((struct sockaddr *)addr) == 0)) + (inp->inp_flags & INP_BINDANY) == 0 && + ifa_ifwithaddr((struct sockaddr *)addr) == NULL)) return (EADDRNOTAVAIL); - inp = sotoinpcb(so); - KASSERT(inp != NULL, ("rip_bind: inp == NULL")); - INP_INFO_WLOCK(&V_ripcbinfo); INP_WLOCK(inp); rip_delhash(inp); diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h index 751569c..eadfc09 100644 --- a/sys/netinet6/in6.h +++ b/sys/netinet6/in6.h @@ -477,6 +477,8 @@ struct route_in6 { * the source address. */ +#define IPV6_BINDANY 64 /* bool: allow bind to any address */ + /* * The following option is private; do not use it from user applications. * It is deliberately defined to the same value as IP_MSFILTER. diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index e572712..800564c 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -163,11 +163,13 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam, if (so->so_options & SO_REUSEADDR) reuseport = SO_REUSEADDR|SO_REUSEPORT; } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - struct ifaddr *ia = NULL; + struct ifaddr *ia; sin6->sin6_port = 0; /* yech... */ - if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0) + if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == NULL && + (inp->inp_flags & INP_BINDANY) == 0) { return (EADDRNOTAVAIL); + } /* * XXX: bind to an anycast address might accidentally diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 8f2e632c..7f6aae4 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -1405,6 +1405,14 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt) case IPV6_RECVTCLASS: case IPV6_V6ONLY: case IPV6_AUTOFLOWLABEL: + case IPV6_BINDANY: + if (optname == IPV6_BINDANY && td != NULL) { + error = priv_check(td, + PRIV_NETINET_BINDANY); + if (error) + break; + } + if (optlen != sizeof(int)) { error = EINVAL; break; @@ -1558,6 +1566,9 @@ do { \ OPTSET(IN6P_AUTOFLOWLABEL); break; + case IPV6_BINDANY: + OPTSET(INP_BINDANY); + break; } break; @@ -1831,6 +1842,10 @@ do { \ case IPV6_AUTOFLOWLABEL: optval = OPTBIT(IN6P_AUTOFLOWLABEL); break; + + case IPV6_BINDANY: + optval = OPTBIT(INP_BINDANY); + break; } if (error) break; diff --git a/sys/sys/priv.h b/sys/sys/priv.h index 3f1eb83..6f9f63b 100644 --- a/sys/sys/priv.h +++ b/sys/sys/priv.h @@ -374,6 +374,7 @@ #define PRIV_NETINET_IPSEC 503 /* Administer IPSEC. */ #define PRIV_NETINET_REUSEPORT 504 /* Allow [rapid] port/address reuse. */ #define PRIV_NETINET_SETHDROPTS 505 /* Set certain IPv4/6 header options. */ +#define PRIV_NETINET_BINDANY 506 /* Allow bind to any address. */ /* * IPX/SPX privileges. |