Index: sys/net/vnet.h =================================================================== --- sys/net/vnet.h +++ sys/net/vnet.h @@ -65,6 +65,7 @@ * as required for libkvm. */ #if defined(_KERNEL) || defined(_WANT_VNET) +#include /* for CACHE_LINE_SIZE */ #include struct vnet { Index: sys/netinet/in.h =================================================================== --- sys/netinet/in.h +++ sys/netinet/in.h @@ -383,7 +383,12 @@ #define IN_BADCLASS(i) (((in_addr_t)(i) & 0xf0000000) == 0xf0000000) #define IN_LINKLOCAL(i) (((in_addr_t)(i) & 0xffff0000) == 0xa9fe0000) +#ifdef _KERNEL +#define IN_LOOPBACK(i) \ + (((in_addr_t)(i) & V_in_loopback_mask) == 0x7f000000) +#else #define IN_LOOPBACK(i) (((in_addr_t)(i) & 0xff000000) == 0x7f000000) +#endif #define IN_ZERONET(i) (((in_addr_t)(i) & 0xff000000) == 0) #define IN_PRIVATE(i) ((((in_addr_t)(i) & 0xff000000) == 0x0a000000) || \ @@ -414,6 +419,18 @@ #define IN_RFC3021_MASK ((in_addr_t)0xfffffffe) +#ifdef _KERNEL +#include + +VNET_DECLARE(bool, ip_allow_zeronet); +VNET_DECLARE(bool, ip_allow_experimental); +/* Address space reserved for loopback */ +VNET_DECLARE(uint32_t, in_loopback_mask); +#define V_ip_allow_zeronet VNET(ip_allow_zeronet) +#define V_ip_allow_experimental VNET(ip_allow_experimental) +#define V_in_loopback_mask VNET(in_loopback_mask) +#endif + /* * Options for use with [gs]etsockopt at the IP level. * First word of comment is data type; bool is stored in int. Index: sys/netinet/in.c =================================================================== --- sys/netinet/in.c +++ sys/netinet/in.c @@ -97,6 +97,23 @@ &VNET_NAME(broadcast_lowest), 0, "Treat lowest address on a subnet (host 0) as broadcast"); +VNET_DEFINE(bool, ip_allow_experimental) = false; +#define V_ip_allow_experimental VNET(ip_allow_experimental) +SYSCTL_BOOL(_net_inet_ip, OID_AUTO, allow_experimental, + CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip_allow_experimental), 0, + "Allow use of Experimental addresses, aka Class E (240/4)"); + +VNET_DEFINE(bool, ip_allow_zeronet) = false; +SYSCTL_BOOL(_net_inet_ip, OID_AUTO, allow_zeronet, + CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip_allow_zeronet), 0, + "Allow use of addresses in network 0/8"); + +VNET_DEFINE(uint32_t, in_loopback_mask) = 0xff000000; +#define V_in_loopback_mask VNET(in_loopback_mask) +SYSCTL_U32(_net_inet_ip, OID_AUTO, loopback_mask, + CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(in_loopback_mask), 0, + "Mask of address space reserved for loopback"); + VNET_DECLARE(struct inpcbinfo, ripcbinfo); #define V_ripcbinfo VNET(ripcbinfo) @@ -251,8 +268,11 @@ { u_long i = ntohl(in.s_addr); - if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i) || - IN_ZERONET(i) || IN_LOOPBACK(i)) + if (IN_MULTICAST(i) || IN_LINKLOCAL(i) || IN_LOOPBACK(i)) + return (0); + if (IN_EXPERIMENTAL(i) && !V_ip_allow_experimental) + return (0); + if (IN_ZERONET(i) && !V_ip_allow_zeronet) return (0); return (1); } Index: sys/netinet/ip_icmp.c =================================================================== --- sys/netinet/ip_icmp.c +++ sys/netinet/ip_icmp.c @@ -775,8 +775,9 @@ NET_EPOCH_ASSERT(); if (IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || - IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)) || - IN_ZERONET(ntohl(ip->ip_src.s_addr)) ) { + (IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)) && + !V_ip_allow_experimental) || + (IN_ZERONET(ntohl(ip->ip_src.s_addr)) && !V_ip_allow_zeronet) ) { m_freem(m); /* Bad return address */ ICMPSTAT_INC(icps_badaddr); goto done; /* Ip_output() will check for broadcast */