Hello, I would like to propose a patch (against FreeBSD RELENG_8) to extend the port randomization support in FreeBSD, according to RFC6056 (https://www.rfc-editor.org/rfc/rfc6056.txt)
Currently the patch implements: - Algorithm 1 (default in FreeBSD 8) - Algorithm 2 - Algorithm 5 from the aforementioned RFC6056. Any of those algorithms can be chosen with the sysctl variable net.inet.ip.portrange.rfc6056_algorithm. I deliberately skipped Algorithm 3 and Algorithm 4, because I believe usage of cryptographic hash functions will introduce unnecessary latency in vital network operations. However, in case of expressed interest, I will be glad to add those too. I would like to ask what is the proper way to validate the sysctl input in order to accept only a specific values? In my case only '1', '2' and '5'. Thank you very much. Ivo Vachkov
diff -r fbf1313362d7 src/sys/netinet/in_pcb.c --- a/src/sys/netinet/in_pcb.c Tue Jan 25 14:03:37 2011 +0200 +++ b/src/sys/netinet/in_pcb.c Wed Jan 26 12:58:05 2011 +0200 @@ -109,6 +109,7 @@ VNET_DEFINE(int, ipport_stoprandom); /* toggled by ipport_tick */ VNET_DEFINE(int, ipport_tcpallocs); static VNET_DEFINE(int, ipport_tcplastcount); +VNET_DEFINE(int, ipport_rfc6056alg) = 1; /* user controlled via sysctl */ #define V_ipport_tcplastcount VNET(ipport_tcplastcount) @@ -174,6 +175,8 @@ &VNET_NAME(ipport_randomtime), 0, "Minimum time to keep sequental port " "allocation before switching to a random one"); +SYSCTL_VNET_INT(_net_inet_ip_portrange, OID_AUTO, rfc6056_algorithm, CTLFLAG_RW, + &VNET_NAME(ipport_rfc6056alg), 0, "RFC 6056 Port randomization algorithm"); /* * in_pcb.c: manage the Protocol Control Blocks. @@ -468,21 +471,75 @@ last = aux; } - if (dorandom) - *lastport = first + - (arc4random() % (last - first)); - count = last - first; - do { - if (count-- < 0) /* completely used? */ - return (EADDRNOTAVAIL); - ++*lastport; - if (*lastport < first || *lastport > last) - *lastport = first; - lport = htons(*lastport); - } while (in_pcblookup_local(pcbinfo, laddr, - lport, wild, cred)); + /* + * According to RFC6056 there are 5 (five) possible algorithms + * for random port allocation. Usage of a particular algorithm + * is specified with the 'net.inet.ip.portrange.rfc6056_algorithm' + * sysctl variable. Default value is 1, which represents the + * legacy random port allocation algorithm in FreeBSD. + */ + if (dorandom) { + switch (V_ipport_rfc6056alg) { + case 5: /* Random-Increments Port Selection */ + do { + if (count-- < 0) /* completely used? */ + return (EADDRNOTAVAIL); + + *lastport = first + ((arc4random() % 65536) + + (arc4random() % 500) + 1); + + if (*lastport < first || *lastport > last) + *lastport = first; + lport = htons(*lastport); + } while (in_pcblookup_local(pcbinfo, laddr, + lport, wild, cred)); + + break; + case 2: /* Simple Port Randomization Algorithm II */ + do { + if (count-- < 0) /* completely used? */ + return (EADDRNOTAVAIL); + + *lastport = first + (arc4random() % (last - first)); + + if (*lastport < first || *lastport > last) + *lastport = first; + lport = htons(*lastport); + } while (in_pcblookup_local(pcbinfo, laddr, + lport, wild, cred)); + + break; + case 1: /* Simple Port Randomization Algorithm I */ + default: + *lastport = first + (arc4random() % (last - first)); + + do { + if (count-- < 0) /* completely used? */ + return (EADDRNOTAVAIL); + + ++*lastport; + + if (*lastport < first || *lastport > last) + *lastport = first; + lport = htons(*lastport); + } while (in_pcblookup_local(pcbinfo, laddr, + lport, wild, cred)); + } + } else { + do { + if (count-- < 0) /* completely used? */ + return (EADDRNOTAVAIL); + + ++*lastport; + + if (*lastport < first || *lastport > last) + *lastport = first; + lport = htons(*lastport); + } while (in_pcblookup_local(pcbinfo, laddr, + lport, wild, cred)); + } } *laddrp = laddr.s_addr; *lportp = lport; diff -r fbf1313362d7 src/sys/netinet/in_pcb.h --- a/src/sys/netinet/in_pcb.h Tue Jan 25 14:03:37 2011 +0200 +++ b/src/sys/netinet/in_pcb.h Wed Jan 26 12:58:05 2011 +0200 @@ -466,6 +466,7 @@ VNET_DECLARE(int, ipport_randomtime); VNET_DECLARE(int, ipport_stoprandom); VNET_DECLARE(int, ipport_tcpallocs); +VNET_DECLARE(int, ipport_rfc6056alg); #define V_ipport_reservedhigh VNET(ipport_reservedhigh) #define V_ipport_reservedlow VNET(ipport_reservedlow) @@ -480,6 +481,7 @@ #define V_ipport_randomtime VNET(ipport_randomtime) #define V_ipport_stoprandom VNET(ipport_stoprandom) #define V_ipport_tcpallocs VNET(ipport_tcpallocs) +#define V_ipport_rfc6056alg VNET(ipport_rfc6056alg) extern struct callout ipport_tick_callout;
_______________________________________________ freebsd-net@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-net To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"