From 5243d2d206ac372ee679c11bde715a4a4f2f93fd Mon Sep 17 00:00:00 2001 From: pjd Date: Mon, 1 Jun 2009 10:30:00 +0000 Subject: - 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 --- sys/netinet/in.h | 3 +-- sys/netinet/in_pcb.c | 10 +++------- sys/netinet/in_pcb.h | 3 +-- sys/netinet/ip_output.c | 25 ++++++++----------------- sys/netinet/raw_ip.c | 9 +++++---- 5 files changed, 18 insertions(+), 32 deletions(-) (limited to 'sys/netinet') 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); -- cgit v1.1