Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Jun 2009 10:30:00 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r193217 - in head/sys: conf netinet netinet6 sys
Message-ID:  <200906011030.n51AU0SW072735@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: pjd
Date: Mon Jun  1 10:30:00 2009
New Revision: 193217
URL: http://svn.freebsd.org/changeset/base/193217

Log:
  - 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

Modified:
  head/sys/conf/NOTES
  head/sys/conf/options
  head/sys/netinet/in.h
  head/sys/netinet/in_pcb.c
  head/sys/netinet/in_pcb.h
  head/sys/netinet/ip_output.c
  head/sys/netinet/raw_ip.c
  head/sys/netinet6/in6.h
  head/sys/netinet6/in6_pcb.c
  head/sys/netinet6/ip6_output.c
  head/sys/sys/priv.h

Modified: head/sys/conf/NOTES
==============================================================================
--- head/sys/conf/NOTES	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/conf/NOTES	Mon Jun  1 10:30:00 2009	(r193217)
@@ -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

Modified: head/sys/conf/options
==============================================================================
--- head/sys/conf/options	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/conf/options	Mon Jun  1 10:30:00 2009	(r193217)
@@ -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

Modified: head/sys/netinet/in.h
==============================================================================
--- head/sys/netinet/in.h	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/netinet/in.h	Mon Jun  1 10:30:00 2009	(r193217)
@@ -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 */

Modified: head/sys/netinet/in_pcb.c
==============================================================================
--- head/sys/netinet/in_pcb.c	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/netinet/in_pcb.c	Mon Jun  1 10:30:00 2009	(r193217)
@@ -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, stru
 			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;

Modified: head/sys/netinet/in_pcb.h
==============================================================================
--- head/sys/netinet/in_pcb.h	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/netinet/in_pcb.h	Mon Jun  1 10:30:00 2009	(r193217)
@@ -410,8 +410,7 @@ void 	inp_4tuple_get(struct inpcb *inp, 
 #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 */

Modified: head/sys/netinet/ip_output.c
==============================================================================
--- head/sys/netinet/ip_output.c	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/netinet/ip_output.c	Mon Jun  1 10:30:00 2009	(r193217)
@@ -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_
 	&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 s
 			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 s
 			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

Modified: head/sys/netinet/raw_ip.c
==============================================================================
--- head/sys/netinet/raw_ip.c	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/netinet/raw_ip.c	Mon Jun  1 10:30:00 2009	(r193217)
@@ -853,15 +853,16 @@ rip_bind(struct socket *so, struct socka
 	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);

Modified: head/sys/netinet6/in6.h
==============================================================================
--- head/sys/netinet6/in6.h	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/netinet6/in6.h	Mon Jun  1 10:30:00 2009	(r193217)
@@ -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.

Modified: head/sys/netinet6/in6_pcb.c
==============================================================================
--- head/sys/netinet6/in6_pcb.c	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/netinet6/in6_pcb.c	Mon Jun  1 10:30:00 2009	(r193217)
@@ -163,11 +163,13 @@ in6_pcbbind(register struct inpcb *inp, 
 			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

Modified: head/sys/netinet6/ip6_output.c
==============================================================================
--- head/sys/netinet6/ip6_output.c	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/netinet6/ip6_output.c	Mon Jun  1 10:30:00 2009	(r193217)
@@ -1405,6 +1405,14 @@ ip6_ctloutput(struct socket *so, struct 
 			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;

Modified: head/sys/sys/priv.h
==============================================================================
--- head/sys/sys/priv.h	Mon Jun  1 10:04:37 2009	(r193216)
+++ head/sys/sys/priv.h	Mon Jun  1 10:30:00 2009	(r193217)
@@ -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.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906011030.n51AU0SW072735>