Module Name: src Committed By: christos Date: Mon Jun 25 15:28:40 UTC 2012
Modified Files: src/sys/netinet: Makefile files.netinet in_pcb.c in_pcb.h in_pcb_hdr.h ip_input.c ip_output.c src/sys/netinet6: in6_pcb.c in6_pcb.h in6_src.c ip6_input.c ip6_output.c Added Files: src/sys/netinet: portalgo.c portalgo.h Removed Files: src/sys/netinet: rfc6056.c rfc6056.h Log Message: rename rfc6056 -> portalgo, requested by yamt To generate a diff of this commit: cvs rdiff -u -r1.23 -r1.24 src/sys/netinet/Makefile \ src/sys/netinet/files.netinet cvs rdiff -u -r1.142 -r1.143 src/sys/netinet/in_pcb.c cvs rdiff -u -r1.49 -r1.50 src/sys/netinet/in_pcb.h cvs rdiff -u -r1.7 -r1.8 src/sys/netinet/in_pcb_hdr.h cvs rdiff -u -r1.301 -r1.302 src/sys/netinet/ip_input.c cvs rdiff -u -r1.216 -r1.217 src/sys/netinet/ip_output.c cvs rdiff -u -r0 -r1.1 src/sys/netinet/portalgo.c src/sys/netinet/portalgo.h cvs rdiff -u -r1.8 -r0 src/sys/netinet/rfc6056.c cvs rdiff -u -r1.3 -r0 src/sys/netinet/rfc6056.h cvs rdiff -u -r1.119 -r1.120 src/sys/netinet6/in6_pcb.c cvs rdiff -u -r1.36 -r1.37 src/sys/netinet6/in6_pcb.h cvs rdiff -u -r1.52 -r1.53 src/sys/netinet6/in6_src.c cvs rdiff -u -r1.139 -r1.140 src/sys/netinet6/ip6_input.c cvs rdiff -u -r1.148 -r1.149 src/sys/netinet6/ip6_output.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netinet/Makefile diff -u src/sys/netinet/Makefile:1.23 src/sys/netinet/Makefile:1.24 --- src/sys/netinet/Makefile:1.23 Wed Feb 15 12:55:24 2012 +++ src/sys/netinet/Makefile Mon Jun 25 11:28:38 2012 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.23 2012/02/15 17:55:24 riz Exp $ +# $NetBSD: Makefile,v 1.24 2012/06/25 15:28:38 christos Exp $ INCSDIR= /usr/include/netinet @@ -6,7 +6,7 @@ INCS= icmp6.h icmp_var.h if_atm.h if_eth igmp_var.h in.h in_gif.h in_pcb.h in_pcb_hdr.h \ in_selsrc.h in_systm.h \ in_var.h ip.h ip_carp.h ip6.h ip_ecn.h ip_encap.h \ - ip_icmp.h ip_mroute.h ip_var.h pim.h pim_var.h rfc6056.h \ + ip_icmp.h ip_mroute.h ip_var.h pim.h pim_var.h portalgo.h \ tcp.h tcp_debug.h tcp_fsm.h tcp_seq.h tcp_timer.h tcp_var.h \ tcpip.h udp.h udp_var.h \ tcp_vtw.h Index: src/sys/netinet/files.netinet diff -u src/sys/netinet/files.netinet:1.23 src/sys/netinet/files.netinet:1.24 --- src/sys/netinet/files.netinet:1.23 Sat Sep 24 13:18:17 2011 +++ src/sys/netinet/files.netinet Mon Jun 25 11:28:39 2012 @@ -1,4 +1,4 @@ -# $NetBSD: files.netinet,v 1.23 2011/09/24 17:18:17 christos Exp $ +# $NetBSD: files.netinet,v 1.24 2012/06/25 15:28:39 christos Exp $ defflag opt_tcp_debug.h TCP_DEBUG defparam opt_tcp_debug.h TCP_NDEBUG @@ -43,4 +43,4 @@ file netinet/tcp_congctl.c inet | inet6 file netinet/tcp_vtw.c inet | inet6 file netinet/udp_usrreq.c inet | inet6 -file netinet/rfc6056.c inet | inet6 +file netinet/portalgo.c inet | inet6 Index: src/sys/netinet/in_pcb.c diff -u src/sys/netinet/in_pcb.c:1.142 src/sys/netinet/in_pcb.c:1.143 --- src/sys/netinet/in_pcb.c:1.142 Thu Jun 21 06:31:45 2012 +++ src/sys/netinet/in_pcb.c Mon Jun 25 11:28:39 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: in_pcb.c,v 1.142 2012/06/21 10:31:45 yamt Exp $ */ +/* $NetBSD: in_pcb.c,v 1.143 2012/06/25 15:28:39 christos Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -93,7 +93,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.142 2012/06/21 10:31:45 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.143 2012/06/25 15:28:39 christos Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -124,7 +124,7 @@ __KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1 #include <netinet/in_pcb.h> #include <netinet/in_var.h> #include <netinet/ip_var.h> -#include <netinet/rfc6056.h> +#include <netinet/portalgo.h> #ifdef INET6 #include <netinet/ip6.h> @@ -205,7 +205,7 @@ in_pcballoc(struct socket *so, void *v) inp->inp_table = table; inp->inp_socket = so; inp->inp_errormtu = -1; - inp->inp_rfc6056algo = RFC6056_ALGO_DEFAULT; + inp->inp_portalgo = PORTALGO_DEFAULT; inp->inp_bindportonsend = false; #if defined(FAST_IPSEC) error = ipsec_init_pcbpolicy(so, &inp->inp_sp); @@ -260,7 +260,7 @@ in_pcbsetport(struct sockaddr_in *sin, s /* * Use RFC6056 randomized port selection */ - error = rfc6056_randport(&lport, &inp->inp_head, cred); + error = portalgo_randport(&lport, &inp->inp_head, cred); if (error) return error; Index: src/sys/netinet/in_pcb.h diff -u src/sys/netinet/in_pcb.h:1.49 src/sys/netinet/in_pcb.h:1.50 --- src/sys/netinet/in_pcb.h:1.49 Sat Sep 24 13:18:17 2011 +++ src/sys/netinet/in_pcb.h Mon Jun 25 11:28:39 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: in_pcb.h,v 1.49 2011/09/24 17:18:17 christos Exp $ */ +/* $NetBSD: in_pcb.h,v 1.50 2012/06/25 15:28:39 christos Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -80,7 +80,7 @@ struct inpcb { #define inp_af inp_head.inph_af #define inp_ppcb inp_head.inph_ppcb #define inp_state inp_head.inph_state -#define inp_rfc6056algo inp_head.inph_rfc6056algo +#define inp_portalgo inp_head.inph_portalgo #define inp_socket inp_head.inph_socket #define inp_table inp_head.inph_table #define inp_sp inp_head.inph_sp Index: src/sys/netinet/in_pcb_hdr.h diff -u src/sys/netinet/in_pcb_hdr.h:1.7 src/sys/netinet/in_pcb_hdr.h:1.8 --- src/sys/netinet/in_pcb_hdr.h:1.7 Sat Sep 24 13:18:17 2011 +++ src/sys/netinet/in_pcb_hdr.h Mon Jun 25 11:28:39 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: in_pcb_hdr.h,v 1.7 2011/09/24 17:18:17 christos Exp $ */ +/* $NetBSD: in_pcb_hdr.h,v 1.8 2012/06/25 15:28:39 christos Exp $ */ /* * Copyright (C) 2003 WIDE Project. @@ -77,7 +77,7 @@ struct inpcb_hdr { int inph_af; /* address family - AF_INET */ void * inph_ppcb; /* pointer to per-protocol pcb */ int inph_state; /* bind/connect state */ - int inph_rfc6056algo; + int inph_portalgo; struct socket *inph_socket; /* back pointer to socket */ struct inpcbtable *inph_table; #if 1 /* IPSEC */ Index: src/sys/netinet/ip_input.c diff -u src/sys/netinet/ip_input.c:1.301 src/sys/netinet/ip_input.c:1.302 --- src/sys/netinet/ip_input.c:1.301 Fri Jun 22 10:54:35 2012 +++ src/sys/netinet/ip_input.c Mon Jun 25 11:28:39 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.301 2012/06/22 14:54:35 christos Exp $ */ +/* $NetBSD: ip_input.c,v 1.302 2012/06/25 15:28:39 christos Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,7 +91,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.301 2012/06/22 14:54:35 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.302 2012/06/25 15:28:39 christos Exp $"); #include "opt_inet.h" #include "opt_compat_netbsd.h" @@ -139,7 +139,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #ifdef MROUTING #include <netinet/ip_mroute.h> #endif -#include <netinet/rfc6056.h> +#include <netinet/portalgo.h> #ifdef FAST_IPSEC #include <netipsec/ipsec.h> @@ -1889,24 +1889,24 @@ sysctl_net_inet_ip_setup(struct sysctllo CTL_EOL); /* anonportalgo RFC6056 subtree */ - const struct sysctlnode *rfc6056_node; - sysctl_createv(clog, 0, NULL, &rfc6056_node, + const struct sysctlnode *portalgo_node; + sysctl_createv(clog, 0, NULL, &portalgo_node, CTLFLAG_PERMANENT, CTLTYPE_NODE, "anonportalgo", SYSCTL_DESCR("Anonymous Port Algorithm Selection (RFC 6056)"), NULL, 0, NULL, 0, CTL_NET, PF_INET, IPPROTO_IP, CTL_CREATE, CTL_EOL); - sysctl_createv(clog, 0, &rfc6056_node, NULL, + sysctl_createv(clog, 0, &portalgo_node, NULL, CTLFLAG_PERMANENT, CTLTYPE_STRING, "available", SYSCTL_DESCR("available algorithms"), - sysctl_rfc6056_available, 0, NULL, RFC6056_MAXLEN, + sysctl_portalgo_available, 0, NULL, PORTALGO_MAXLEN, CTL_CREATE, CTL_EOL); - sysctl_createv(clog, 0, &rfc6056_node, NULL, + sysctl_createv(clog, 0, &portalgo_node, NULL, CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRING, "selected", SYSCTL_DESCR("selected algorithm"), - sysctl_rfc6056_selected, 0, NULL, RFC6056_MAXLEN, + sysctl_portalgo_selected, 0, NULL, PORTALGO_MAXLEN, CTL_CREATE, CTL_EOL); } Index: src/sys/netinet/ip_output.c diff -u src/sys/netinet/ip_output.c:1.216 src/sys/netinet/ip_output.c:1.217 --- src/sys/netinet/ip_output.c:1.216 Fri Jun 22 10:54:35 2012 +++ src/sys/netinet/ip_output.c Mon Jun 25 11:28:39 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_output.c,v 1.216 2012/06/22 14:54:35 christos Exp $ */ +/* $NetBSD: ip_output.c,v 1.217 2012/06/25 15:28:39 christos Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,7 +91,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.216 2012/06/22 14:54:35 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.217 2012/06/25 15:28:39 christos Exp $"); #include "opt_pfil_hooks.h" #include "opt_inet.h" @@ -125,7 +125,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_output.c, #include <netinet/ip_var.h> #include <netinet/ip_private.h> #include <netinet/in_offload.h> -#include <netinet/rfc6056.h> +#include <netinet/portalgo.h> #ifdef MROUTING #include <netinet/ip_mroute.h> @@ -1148,7 +1148,7 @@ ip_ctloutput(int op, struct socket *so, if (error) break; - error = rfc6056_algo_index_select( + error = portalgo_algo_index_select( (struct inpcb_hdr *)inp, optval); break; @@ -1267,7 +1267,7 @@ ip_ctloutput(int op, struct socket *so, break; case IP_PORTALGO: - optval = ((struct inpcb_hdr *)inp)->inph_rfc6056algo; + optval = ((struct inpcb_hdr *)inp)->inph_portalgo; error = sockopt_setint(sopt, optval); break; Index: src/sys/netinet6/in6_pcb.c diff -u src/sys/netinet6/in6_pcb.c:1.119 src/sys/netinet6/in6_pcb.c:1.120 --- src/sys/netinet6/in6_pcb.c:1.119 Thu Mar 22 16:34:40 2012 +++ src/sys/netinet6/in6_pcb.c Mon Jun 25 11:28:39 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: in6_pcb.c,v 1.119 2012/03/22 20:34:40 drochner Exp $ */ +/* $NetBSD: in6_pcb.c,v 1.120 2012/06/25 15:28:39 christos Exp $ */ /* $KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.119 2012/03/22 20:34:40 drochner Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.120 2012/06/25 15:28:39 christos Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -91,7 +91,7 @@ __KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip6.h> -#include <netinet/rfc6056.h> +#include <netinet/portalgo.h> #include <netinet6/ip6_var.h> #include <netinet6/in6_pcb.h> #include <netinet6/scope6_var.h> @@ -172,7 +172,7 @@ in6_pcballoc(struct socket *so, void *v) in6p->in6p_socket = so; in6p->in6p_hops = -1; /* use kernel default */ in6p->in6p_icmp6filt = NULL; - in6p->in6p_rfc6056algo = RFC6056_ALGO_DEFAULT; + in6p->in6p_portalgo = PORTALGO_DEFAULT; in6p->in6p_bindportonsend = false; #if defined(FAST_IPSEC) error = ipsec_init_pcbpolicy(so, &in6p->in6p_sp); Index: src/sys/netinet6/in6_pcb.h diff -u src/sys/netinet6/in6_pcb.h:1.36 src/sys/netinet6/in6_pcb.h:1.37 --- src/sys/netinet6/in6_pcb.h:1.36 Sat Sep 24 13:22:14 2011 +++ src/sys/netinet6/in6_pcb.h Mon Jun 25 11:28:39 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: in6_pcb.h,v 1.36 2011/09/24 17:22:14 christos Exp $ */ +/* $NetBSD: in6_pcb.h,v 1.37 2012/06/25 15:28:39 christos Exp $ */ /* $KAME: in6_pcb.h,v 1.45 2001/02/09 05:59:46 itojun Exp $ */ /* @@ -83,7 +83,7 @@ struct in6pcb { #define in6p_af in6p_head.inph_af #define in6p_ppcb in6p_head.inph_ppcb #define in6p_state in6p_head.inph_state -#define in6p_rfc6056algo in6p_head.inph_rfc6056algo +#define in6p_portalgo in6p_head.inph_portalgo #define in6p_socket in6p_head.inph_socket #define in6p_table in6p_head.inph_table #define in6p_sp in6p_head.inph_sp Index: src/sys/netinet6/in6_src.c diff -u src/sys/netinet6/in6_src.c:1.52 src/sys/netinet6/in6_src.c:1.53 --- src/sys/netinet6/in6_src.c:1.52 Sat Sep 24 13:22:14 2011 +++ src/sys/netinet6/in6_src.c Mon Jun 25 11:28:39 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: in6_src.c,v 1.52 2011/09/24 17:22:14 christos Exp $ */ +/* $NetBSD: in6_src.c,v 1.53 2012/06/25 15:28:39 christos Exp $ */ /* $KAME: in6_src.c,v 1.159 2005/10/19 01:40:32 t-momose Exp $ */ /* @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.52 2011/09/24 17:22:14 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.53 2012/06/25 15:28:39 christos Exp $"); #include "opt_inet.h" @@ -93,7 +93,7 @@ __KERNEL_RCSID(0, "$NetBSD: in6_src.c,v #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> -#include <netinet/rfc6056.h> +#include <netinet/portalgo.h> #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/in6_pcb.h> @@ -828,7 +828,7 @@ in6_pcbsetport(struct sockaddr_in6 *sin6 /* * Use RFC6056 randomized port selection */ - error = rfc6056_randport(&lport, &in6p->in6p_head, l->l_cred); + error = portalgo_randport(&lport, &in6p->in6p_head, l->l_cred); if (error) return error; Index: src/sys/netinet6/ip6_input.c diff -u src/sys/netinet6/ip6_input.c:1.139 src/sys/netinet6/ip6_input.c:1.140 --- src/sys/netinet6/ip6_input.c:1.139 Fri Jun 22 23:14:04 2012 +++ src/sys/netinet6/ip6_input.c Mon Jun 25 11:28:40 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: ip6_input.c,v 1.139 2012/06/23 03:14:04 christos Exp $ */ +/* $NetBSD: ip6_input.c,v 1.140 2012/06/25 15:28:40 christos Exp $ */ /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.139 2012/06/23 03:14:04 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.140 2012/06/25 15:28:40 christos Exp $"); #include "opt_gateway.h" #include "opt_inet.h" @@ -103,7 +103,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_input.c, #include <netinet/ip_icmp.h> #endif /* INET */ #include <netinet/ip6.h> -#include <netinet/rfc6056.h> +#include <netinet/portalgo.h> #include <netinet6/in6_var.h> #include <netinet6/ip6_var.h> #include <netinet6/ip6_private.h> @@ -1958,24 +1958,24 @@ sysctl_net_inet6_ip6_setup(struct sysctl CTL_CREATE, CTL_EOL); #endif /* anonportalgo RFC6056 subtree */ - const struct sysctlnode *rfc6056_node; - sysctl_createv(clog, 0, NULL, &rfc6056_node, + const struct sysctlnode *portalgo_node; + sysctl_createv(clog, 0, NULL, &portalgo_node, CTLFLAG_PERMANENT, CTLTYPE_NODE, "anonportalgo", SYSCTL_DESCR("Anonymous port algorithm selection (RFC 6056)"), NULL, 0, NULL, 0, CTL_NET, PF_INET6, IPPROTO_IPV6, CTL_CREATE, CTL_EOL); - sysctl_createv(clog, 0, &rfc6056_node, NULL, + sysctl_createv(clog, 0, &portalgo_node, NULL, CTLFLAG_PERMANENT, CTLTYPE_STRING, "available", SYSCTL_DESCR("available algorithms"), - sysctl_rfc6056_available, 0, NULL, RFC6056_MAXLEN, + sysctl_portalgo_available, 0, NULL, PORTALGO_MAXLEN, CTL_CREATE, CTL_EOL); - sysctl_createv(clog, 0, &rfc6056_node, NULL, + sysctl_createv(clog, 0, &portalgo_node, NULL, CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRING, "selected", SYSCTL_DESCR("selected algorithm"), - sysctl_rfc6056_selected6, 0, NULL, RFC6056_MAXLEN, + sysctl_portalgo_selected6, 0, NULL, PORTALGO_MAXLEN, CTL_CREATE, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_READWRITE, Index: src/sys/netinet6/ip6_output.c diff -u src/sys/netinet6/ip6_output.c:1.148 src/sys/netinet6/ip6_output.c:1.149 --- src/sys/netinet6/ip6_output.c:1.148 Fri Jun 22 10:54:35 2012 +++ src/sys/netinet6/ip6_output.c Mon Jun 25 11:28:40 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: ip6_output.c,v 1.148 2012/06/22 14:54:35 christos Exp $ */ +/* $NetBSD: ip6_output.c,v 1.149 2012/06/25 15:28:40 christos Exp $ */ /* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.148 2012/06/22 14:54:35 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.149 2012/06/25 15:28:40 christos Exp $"); #include "opt_inet.h" #include "opt_inet6.h" @@ -91,7 +91,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_output.c #include <netinet/ip6.h> #include <netinet/icmp6.h> #include <netinet/in_offload.h> -#include <netinet/rfc6056.h> +#include <netinet/portalgo.h> #include <netinet6/in6_offload.h> #include <netinet6/ip6_var.h> #include <netinet6/ip6_private.h> @@ -1639,7 +1639,7 @@ else \ if (error) break; - error = rfc6056_algo_index_select( + error = portalgo_algo_index_select( (struct inpcb_hdr *)in6p, optval); break; @@ -1828,7 +1828,7 @@ else \ break; case IPV6_PORTALGO: - optval = ((struct inpcb_hdr *)in6p)->inph_rfc6056algo; + optval = ((struct inpcb_hdr *)in6p)->inph_portalgo; error = sockopt_setint(sopt, optval); break; Added files: Index: src/sys/netinet/portalgo.c diff -u /dev/null src/sys/netinet/portalgo.c:1.1 --- /dev/null Mon Jun 25 11:28:41 2012 +++ src/sys/netinet/portalgo.c Mon Jun 25 11:28:39 2012 @@ -0,0 +1,942 @@ +/* $NetBSD: portalgo.c,v 1.1 2012/06/25 15:28:39 christos Exp $ */ + +/* + * Copyright 2011 Vlad Balan + * + * Written by Vlad Balan for the NetBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * see: + * RFC 6056 Recommendations for Transport-Protocol Port Randomization + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: portalgo.c,v 1.1 2012/06/25 15:28:39 christos Exp $"); + +#include "opt_inet.h" + +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/kauth.h> +#include <sys/uidinfo.h> +#include <sys/domain.h> +#include <sys/md5.h> +#include <sys/cprng.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/in_var.h> +#include <netinet/ip_var.h> + +#ifdef INET6 +#include <netinet/ip6.h> +#include <netinet6/ip6_var.h> +#include <netinet6/in6_pcb.h> +#endif + +#include <netinet/tcp_vtw.h> + +#include "portalgo.h" + +#define NPROTO 2 +#define PORTALGO_TCP 0 +#define PORTALGO_UDP 1 + +#define NAF 2 +#define PORTALGO_IPV4 0 +#define PORTALGO_IPV6 1 + +#define NRANGES 2 +#define PORTALGO_LOWPORT 0 +#define PORTALGO_HIGHPORT 1 + +#if PORTALGO_DEBUG +static bool portalgo_debug = true; +#define DPRINTF if (portalgo_debug) printf +#else +#define DPRINTF while (/*CONSTCOND*/0) printf +#endif + +#ifdef INET +static int inet4_portalgo = PORTALGO_BSD; +#endif +#ifdef INET6 +static int inet6_portalgo = PORTALGO_BSD; +#endif + +typedef struct { + const char *name; + int (*func)(int, uint16_t *, struct inpcb_hdr *, kauth_cred_t); +} portalgo_algorithm_t; + +static int algo_bsd(int, uint16_t *, struct inpcb_hdr *, kauth_cred_t); +static int algo_random_start(int, uint16_t *, struct inpcb_hdr *, kauth_cred_t); +static int algo_random_pick(int, uint16_t *, struct inpcb_hdr *, kauth_cred_t); +static int algo_hash(int, uint16_t *, struct inpcb_hdr *, kauth_cred_t); +static int algo_doublehash(int, uint16_t *, struct inpcb_hdr *, kauth_cred_t); +static int algo_randinc(int, uint16_t *, struct inpcb_hdr *, kauth_cred_t); + +static const portalgo_algorithm_t algos[] = { + { + .name = "bsd", + .func = algo_bsd + }, + { + .name = "random_start", + .func = algo_random_start + }, + { + .name = "random_pick", + .func = algo_random_pick + }, + { + .name = "hash", + .func = algo_hash + }, + { + .name = "doublehash", + .func = algo_doublehash + }, + { + .name = "randinc", + .func = algo_randinc + } +}; + +#define NALGOS __arraycount(algos) + +static uint16_t portalgo_next_ephemeral[NPROTO][NAF][NRANGES][NALGOS]; + +/* + * Access the pcb and copy the values of the last port and the ends of + * the port range. + */ +static int +pcb_getports(struct inpcb_hdr *inp_hdr, uint16_t *lastport, + uint16_t *mymin, uint16_t *mymax, uint16_t **pnext_ephemeral, int algo) +{ + struct inpcbtable * const table = inp_hdr->inph_table; + struct socket *so; + int portalgo_proto; + int portalgo_af; + int portalgo_range; + + so = inp_hdr->inph_socket; + switch (so->so_type) { + case SOCK_DGRAM: /* UDP or DCCP */ + portalgo_proto = PORTALGO_UDP; + break; + case SOCK_STREAM: /* TCP or SCTP */ + portalgo_proto = PORTALGO_TCP; + break; + default: + return EPFNOSUPPORT; + } + + switch (inp_hdr->inph_af) { +#ifdef INET + case AF_INET: { + struct inpcb *inp = (struct inpcb *)(void *)inp_hdr; + + portalgo_af = PORTALGO_IPV4; + if (inp->inp_flags & INP_LOWPORT) { + *mymin = lowportmin; + *mymax = lowportmax; + *lastport = table->inpt_lastlow; + portalgo_range = PORTALGO_LOWPORT; + } else { + *mymin = anonportmin; + *mymax = anonportmax; + *lastport = table->inpt_lastport; + portalgo_range = PORTALGO_HIGHPORT; + } + break; + } +#endif +#ifdef INET6 + case AF_INET6: { + struct in6pcb *in6p = (struct in6pcb *)(void *)inp_hdr; + + portalgo_af = PORTALGO_IPV6; + if (in6p->in6p_flags & IN6P_LOWPORT) { + *mymin = ip6_lowportmin; + *mymax = ip6_lowportmax; + *lastport = table->inpt_lastlow; + portalgo_range = PORTALGO_LOWPORT; + } else { + *mymin = ip6_anonportmin; + *mymax = ip6_anonportmax; + *lastport = table->inpt_lastport; + portalgo_range = PORTALGO_HIGHPORT; + } + break; + } +#endif + default: + return EAFNOSUPPORT; + } + + if (*mymin > *mymax) { /* sanity check */ + u_int16_t swp; + + swp = *mymin; + *mymin = *mymax; + *mymax = swp; + } + + DPRINTF("%s mymin:%d mymax:%d lastport:%d\n", __func__, + *mymin, *mymax, *lastport); + + *pnext_ephemeral = &portalgo_next_ephemeral[portalgo_proto] + [portalgo_af][portalgo_range][algo]; + + DPRINTF("%s portalgo_proto:%d portalgo_af:%d portalgo_range:%d\n", + __func__, portalgo_proto, portalgo_af, portalgo_range); + return 0; +} + +/* + * Check whether the port picked by the port randomizer is available + * and whether KAUTH approves of our choice. This part of the code + * shamelessly copied from in_pcb.c. + */ +static bool +check_suitable_port(uint16_t port, struct inpcb_hdr *inp_hdr, kauth_cred_t cred) +{ + struct inpcbtable * const table = inp_hdr->inph_table; +#ifdef INET + vestigial_inpcb_t vestigial; +#endif + int error; +#ifdef INET6 + struct socket *so; + int wild = 0; +#endif + + DPRINTF("%s called for argument %d\n", __func__, port); + + switch (inp_hdr->inph_af) { +#ifdef INET + case AF_INET: { /* IPv4 */ + struct inpcb *inp = (struct inpcb *)(void *)inp_hdr; + struct inpcb *pcb; + struct sockaddr_in sin; + + sin.sin_addr = inp->inp_laddr; + pcb = in_pcblookup_port(table, sin.sin_addr, htons(port), 1, + &vestigial); + + DPRINTF("%s in_pcblookup_port returned %p and " + "vestigial.valid %d\n", + __func__, pcb, vestigial.valid); + + if ((!pcb) && (!vestigial.valid)) { + enum kauth_network_req req; + + /* We have a free port. Check with the secmodel. */ + if (inp->inp_flags & INP_LOWPORT) { +#ifndef IPNOPRIVPORTS + req = KAUTH_REQ_NETWORK_BIND_PRIVPORT; +#else + req = KAUTH_REQ_NETWORK_BIND_PORT; +#endif + } else + req = KAUTH_REQ_NETWORK_BIND_PORT; + + sin.sin_port = port; + error = kauth_authorize_network(cred, + KAUTH_NETWORK_BIND, + req, inp->inp_socket, &sin, NULL); + DPRINTF("%s kauth_authorize_network returned %d\n", + __func__, error); + + if (error == 0) { + DPRINTF("%s port approved\n", __func__); + return true; /* KAUTH agrees */ + } + } + break; + } +#endif +#ifdef INET6 + case AF_INET6: { /* IPv6 */ + struct in6pcb *in6p = (struct in6pcb *)(void *)inp_hdr; + struct sockaddr_in6 sin6; + void *t; + + sin6.sin6_addr = in6p->in6p_laddr; + so = in6p->in6p_socket; + + /* XXX: this is redundant when called from in6_pcbbind */ + if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && + ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || + (so->so_options & SO_ACCEPTCONN) == 0)) + wild = 1; + +#ifdef INET + if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) { + t = in_pcblookup_port(table, + *(struct in_addr *)&sin6.sin6_addr.s6_addr32[3], + htons(port), wild, &vestigial); + if (!t && vestigial.valid) { + DPRINTF("%s in_pcblookup_port returned " + "a result\n", __func__); + return false; + } + } else +#endif + { + t = in6_pcblookup_port(table, &sin6.sin6_addr, + htons(port), wild, &vestigial); + if (!t && vestigial.valid) { + DPRINTF("%s in6_pcblookup_port returned " + "a result\n", __func__); + return false; + } + } + if (t == NULL) { + enum kauth_network_req req; + + /* We have a free port. Check with the secmodel. */ + if (in6p->in6p_flags & IN6P_LOWPORT) { +#ifndef IPNOPRIVPORTS + req = KAUTH_REQ_NETWORK_BIND_PRIVPORT; +#else + req = KAUTH_REQ_NETWORK_BIND_PORT; +#endif + } else { + req = KAUTH_REQ_NETWORK_BIND_PORT; + } + + sin6.sin6_port = port; + error = kauth_authorize_network(cred, + KAUTH_NETWORK_BIND, req, so, &sin6, NULL); + if (error) { + /* Secmodel says no. Keep looking. */ + DPRINTF("%s secmodel says no\n", __func__); + return false; + } + DPRINTF("%s port approved\n", __func__); + return true; + } + break; + } +#endif + default: + DPRINTF("%s unknown address family\n", __func__); + return false; + } + return false; +} + +/* This is the default BSD algorithm, as described in RFC 6056 */ +static int +algo_bsd(int algo, uint16_t *port, struct inpcb_hdr *inp_hdr, kauth_cred_t cred) +{ + uint16_t count; + uint16_t mymin, mymax, lastport; + uint16_t *next_ephemeral; + int error; + + DPRINTF("%s called\n", __func__); + error = pcb_getports(inp_hdr, &lastport, &mymin, &mymax, + &next_ephemeral, algo); + if (error) + return error; + count = mymax - mymin + 1; + do { + uint16_t myport = *next_ephemeral; + + if (myport < mymin || mymax < myport) + myport = mymax; + *next_ephemeral = myport - 1; + if (check_suitable_port(myport, inp_hdr, cred)) { + *port = myport; + DPRINTF("%s returning port %d\n", __func__, *port); + return 0; + } + count--; + } while (count > 0); + + DPRINTF("%s returning EAGAIN\n", __func__); + return EAGAIN; +} + +/* + * The straightforward algorithm that calls random() in order to + * compute the increment to the next port number. + */ +static int +algo_random_start(int algo, uint16_t *port, struct inpcb_hdr *inp_hdr, + kauth_cred_t cred) +{ + uint16_t count, num_ephemeral; + uint16_t mymin, mymax, lastport; + uint16_t *next_ephemeral; + int error; + + DPRINTF("%s called\n", __func__); + + error = pcb_getports(inp_hdr, &lastport, &mymin, &mymax, + &next_ephemeral, algo); + if (error) + return error; + + num_ephemeral = mymax - mymin + 1; + + DPRINTF("num_ephemeral: %u\n", num_ephemeral); + + *next_ephemeral = mymin + (cprng_fast32() % num_ephemeral); + + DPRINTF("next_ephemeral initially: %u\n", *next_ephemeral); + + count = num_ephemeral; + + do { + if (check_suitable_port(*next_ephemeral, inp_hdr, cred)) { + *port = *next_ephemeral; + DPRINTF("%s returning port %d\n", __func__, *port); + return 0; + } + if (*next_ephemeral == mymax) { + *next_ephemeral = mymin; + } else + (*next_ephemeral)++; + + count--; + + + DPRINTF("next_ephemeral: %u count: %u\n", *next_ephemeral, + count); + + } while (count > 0); + + DPRINTF("%s returning EINVAL\n", __func__); + + return EINVAL; +} + +/* + * Since there is no state kept on the ports tried, we might actually + * give up before exhausting the free ports. + */ +static int +algo_random_pick(int algo, uint16_t *port, struct inpcb_hdr *inp_hdr, + kauth_cred_t cred) +{ + uint16_t count, num_ephemeral; + uint16_t mymin, mymax, lastport; + uint16_t *next_ephemeral; + int error; + + DPRINTF("%s called\n", __func__); + + error = pcb_getports(inp_hdr, &lastport, &mymin, &mymax, + &next_ephemeral, algo); + if (error) + return error; + + num_ephemeral = mymax - mymin + 1; + + DPRINTF("num_ephemeral: %u\n", num_ephemeral); + *next_ephemeral = mymin + (cprng_fast32() % num_ephemeral); + + DPRINTF("next_ephemeral initially: %u\n", *next_ephemeral); + + count = num_ephemeral; + + do { + if (check_suitable_port(*next_ephemeral, inp_hdr, cred)) { + *port = *next_ephemeral; + DPRINTF("%s returning port %d\n", __func__, *port); + return 0; + } + *next_ephemeral = mymin + + (cprng_fast32() % num_ephemeral); + + count--; + + DPRINTF("next_ephemeral: %u count: %u\n", + *next_ephemeral, count); + } while (count > 0); + + DPRINTF("%s returning EINVAL\n", __func__); + + return EINVAL; +} + +/* This is the implementation from FreeBSD, with tweaks */ +static uint16_t +Fhash(const struct inpcb_hdr *inp_hdr) +{ + MD5_CTX f_ctx; + uint32_t Ff[4]; + uint32_t secret_f[4]; + uint32_t offset; + uint16_t soffset[2]; + + cprng_fast(secret_f, sizeof(secret_f)); + + MD5Init(&f_ctx); + switch (inp_hdr->inph_af) { +#ifdef INET + case AF_INET: { + const struct inpcb *inp = + (const struct inpcb *)(const void *)inp_hdr; + MD5Update(&f_ctx, (const u_char *)&inp->inp_laddr, + sizeof(inp->inp_laddr)); + MD5Update(&f_ctx, (const u_char *)&inp->inp_faddr, + sizeof(inp->inp_faddr)); + MD5Update(&f_ctx, (const u_char *)&inp->inp_fport, + sizeof(inp->inp_fport)); + break; + } +#endif +#ifdef INET6 + case AF_INET6: { + const struct in6pcb *in6p = + (const struct in6pcb *)(const void *)inp_hdr; + MD5Update(&f_ctx, (const u_char *)&in6p->in6p_laddr, + sizeof(in6p->in6p_laddr)); + MD5Update(&f_ctx, (const u_char *)&in6p->in6p_faddr, + sizeof(in6p->in6p_faddr)); + MD5Update(&f_ctx, (const u_char *)&in6p->in6p_fport, + sizeof(in6p->in6p_fport)); + break; + } +#endif + default: + break; + } + MD5Update(&f_ctx, (const u_char *)secret_f, sizeof(secret_f)); + MD5Final((u_char *)&Ff, &f_ctx); + + offset = (Ff[0] ^ Ff[1]) ^ (Ff[2] ^ Ff[3]); + + memcpy(&soffset, &offset, sizeof(soffset)); + + return soffset[0] ^ soffset[1]; +} + +/* + * Checks whether the tuple is complete. If not, marks the pcb for + * late binding. + */ +static bool +iscompletetuple(struct inpcb_hdr *inp_hdr) +{ +#ifdef INET6 + struct in6pcb *in6p; +#endif + + switch (inp_hdr->inph_af) { +#ifdef INET + case AF_INET: { + struct inpcb *inp = (struct inpcb *)(void *)inp_hdr; + if (inp->inp_fport == 0 || in_nullhost(inp->inp_faddr)) { + DPRINTF("%s fport or faddr missing, delaying port " + "to connect/send\n", __func__); + inp->inp_bindportonsend = true; + return false; + } else { + inp->inp_bindportonsend = false; + } + break; + } +#endif +#ifdef INET6 + case AF_INET6: { + in6p = (struct in6pcb *)(void *)inp_hdr; + if (in6p->in6p_fport == 0 || memcmp(&in6p->in6p_faddr, + &in6addr_any, sizeof(in6p->in6p_faddr)) == 0) { + DPRINTF("%s fport or faddr missing, delaying port " + "to connect/send\n", __func__); + in6p->in6p_bindportonsend = true; + return false; + } else { + in6p->in6p_bindportonsend = false; + } + break; + } +#endif + default: + DPRINTF("%s incorrect address family\n", __func__); + return false; + } + + return true; +} + +static int +algo_hash(int algo, uint16_t *port, struct inpcb_hdr *inp_hdr, + kauth_cred_t cred) +{ + uint16_t count, num_ephemeral; + uint16_t mymin, mymax, lastport; + uint16_t *next_ephemeral; + uint16_t offset, myport; + int error; + + DPRINTF("%s called\n", __func__); + + error = pcb_getports(inp_hdr, &lastport, &mymin, &mymax, + &next_ephemeral, algo); + if (error) + return error; + + if (!iscompletetuple(inp_hdr)) { + *port = 0; + return 0; + } + + /* Ephemeral port selection function */ + num_ephemeral = mymax - mymin + 1; + + DPRINTF("num_ephemeral: %d\n", num_ephemeral); + + offset = Fhash(inp_hdr); + + count = num_ephemeral; + do { + myport = mymin + (*next_ephemeral + offset) + % num_ephemeral; + + (*next_ephemeral)++; + + if (check_suitable_port(myport, inp_hdr, cred)) { + *port = myport; + DPRINTF("%s returning port %d\n", __func__, *port); + return 0; + } + count--; + } while (count > 0); + + DPRINTF("%s returning EINVAL\n", __func__); + + return EINVAL; +} + +static int +algo_doublehash(int algo, uint16_t *port, struct inpcb_hdr *inp_hdr, + kauth_cred_t cred) +{ + uint16_t count, num_ephemeral; + uint16_t mymin, mymax, lastport; + uint16_t *next_ephemeral; + uint16_t offset, myport; + static uint16_t dhtable[8]; + size_t idx; + int error; + + DPRINTF("%s called\n", __func__); + + error = pcb_getports(inp_hdr, &lastport, &mymin, &mymax, + &next_ephemeral, algo); + if (error) + return error; + + if (!iscompletetuple(inp_hdr)) { + *port = 0; + return 0; + } + /* first time initialization */ + if (dhtable[0] == 0) + for (size_t i = 0; i < __arraycount(dhtable); i++) + dhtable[i] = random() & 0xffff; + + /* Ephemeral port selection function */ + num_ephemeral = mymax - mymin + 1; + offset = Fhash(inp_hdr); + idx = Fhash(inp_hdr) % __arraycount(dhtable); /* G */ + count = num_ephemeral; + + do { + myport = mymin + (offset + dhtable[idx]) + % num_ephemeral; + dhtable[idx]++; + + if (check_suitable_port(myport, inp_hdr, cred)) { + *port = myport; + DPRINTF("%s returning port %d\n", __func__, *port); + return 0; + } + count--; + + } while (count > 0); + + DPRINTF("%s returning EINVAL\n", __func__); + + return EINVAL; +} + +static int +algo_randinc(int algo, uint16_t *port, struct inpcb_hdr *inp_hdr, + kauth_cred_t cred) +{ + static const uint16_t N = 500; /* Determines the trade-off */ + uint16_t count, num_ephemeral; + uint16_t mymin, mymax, lastport; + uint16_t *next_ephemeral; + uint16_t myport; + int error; + + DPRINTF("%s called\n", __func__); + + error = pcb_getports(inp_hdr, &lastport, &mymin, &mymax, + &next_ephemeral, algo); + if (error) + return error; + + if (*next_ephemeral == 0) + *next_ephemeral = cprng_fast32() & 0xffff; + + /* Ephemeral port selection function */ + num_ephemeral = mymax - mymin + 1; + + count = num_ephemeral; + do { + *next_ephemeral = *next_ephemeral + + (cprng_fast32() % N) + 1; + myport = mymin + + (*next_ephemeral % num_ephemeral); + + if (check_suitable_port(myport, inp_hdr, cred)) { + *port = myport; + DPRINTF("%s returning port %d\n", __func__, *port); + return 0; + } + count--; + } while (count > 0); + + return EINVAL; +} + +/* The generic function called in order to pick a port. */ +int +portalgo_randport(uint16_t *port, struct inpcb_hdr *inp_hdr, kauth_cred_t cred) +{ + int algo, error; + uint16_t lport; + int default_algo; + + DPRINTF("%s called\n", __func__); + + if (inp_hdr->inph_portalgo == PORTALGO_DEFAULT) { + switch (inp_hdr->inph_af) { +#ifdef INET + case AF_INET: + default_algo = inet4_portalgo; + break; +#endif +#ifdef INET6 + case AF_INET6: + default_algo = inet6_portalgo; + break; +#endif + default: + return EINVAL; + } + + if (default_algo == PORTALGO_DEFAULT) + algo = PORTALGO_BSD; + else + algo = default_algo; + } + else /* socket specifies the algorithm */ + algo = inp_hdr->inph_portalgo; + + KASSERT(algo >= 0); + KASSERT(algo < NALGOS); + + switch (inp_hdr->inph_af) { +#ifdef INET + case AF_INET: { + struct inpcb *inp = (struct inpcb *)(void *)inp_hdr; + DPRINTF("local addr: %s\n", inet_ntoa(inp->inp_laddr)); + DPRINTF("local port: %d\n", inp->inp_lport); + DPRINTF("foreign addr: %s\n", inet_ntoa(inp->inp_faddr)); + DPRINTF("foreign port: %d\n", inp->inp_fport); + break; + } +#endif +#ifdef INET6 + case AF_INET6: { + struct in6pcb *in6p = (struct in6pcb *)(void *)inp_hdr; + + DPRINTF("local addr: %s\n", ip6_sprintf(&in6p->in6p_laddr)); + DPRINTF("local port: %d\n", in6p->in6p_lport); + DPRINTF("foreign addr: %s\n", ip6_sprintf(&in6p->in6p_faddr)); + DPRINTF("foreign port: %d\n", in6p->in6p_fport); + break; + } +#endif + default: + break; + } + + DPRINTF("%s portalgo = %d\n", __func__, algo); + + error = (*algos[algo].func)(algo, &lport, inp_hdr, cred); + if (error == 0) { + *port = lport; + } else if (error != EAGAIN) { + uint16_t lastport, mymin, mymax, *pnext_ephemeral; + + error = pcb_getports(inp_hdr, &lastport, &mymin, + &mymax, &pnext_ephemeral, algo); + if (error) + return error; + *port = lastport - 1; + } + return error; +} + +/* Sets the algorithm to be used globally */ +static int +portalgo_algo_name_select(const char *name, int *algo) +{ + size_t ai; + + DPRINTF("%s called\n", __func__); + + for (ai = 0; ai < NALGOS; ai++) + if (strcmp(algos[ai].name, name) == 0) { + DPRINTF("%s: found idx %zu\n", __func__, ai); + *algo = ai; + return 0; + } + return EINVAL; +} + +/* Sets the algorithm to be used by the pcb inp. */ +int +portalgo_algo_index_select(struct inpcb_hdr *inp, int algo) +{ + + DPRINTF("%s called with algo %d for pcb %p\n", __func__, algo, inp ); + + if ((algo < 0 || algo >= NALGOS) && + (algo != PORTALGO_DEFAULT)) + return EINVAL; + + inp->inph_portalgo = algo; + return 0; +} + +/* + * The sysctl hook that is supposed to check that we are picking one + * of the valid algorithms. IPv4. + */ +static int +sysctl_portalgo_helper(SYSCTLFN_ARGS, int *algo) +{ + struct sysctlnode node; + int error; + char newalgo[PORTALGO_MAXLEN]; + + DPRINTF("%s called\n", __func__); + + strlcpy(newalgo, algos[*algo].name, sizeof(newalgo)); + + node = *rnode; + node.sysctl_data = newalgo; + node.sysctl_size = sizeof(newalgo); + + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + + DPRINTF("newalgo: %s\n", newalgo); + + if (error || newp == NULL || + strncmp(newalgo, algos[*algo].name, sizeof(newalgo)) == 0) + return error; + +#ifdef KAUTH_NETWORK_SOCKET_PORT_RANDOMIZE + if (l != NULL && (error = kauth_authorize_system(l->l_cred, + KAUTH_NETWORK_SOCKET, KAUTH_NETWORK_SOCKET_PORT_RANDOMIZE, newname, + NULL, NULL)) != 0) + return error; +#endif + + mutex_enter(softnet_lock); + error = portalgo_algo_name_select(newalgo, algo); + mutex_exit(softnet_lock); + return error; +} + +/* + * The sysctl hook that is supposed to check that we are picking one + * of the valid algorithms. + */ +int +sysctl_portalgo_selected(SYSCTLFN_ARGS) +{ + + return sysctl_portalgo_helper(SYSCTLFN_CALL(rnode), &inet4_portalgo); +} + +#ifdef INET6 +int +sysctl_portalgo_selected6(SYSCTLFN_ARGS) +{ + + return sysctl_portalgo_helper(SYSCTLFN_CALL(rnode), &inet6_portalgo); +} +#endif + +/* + * The sysctl hook that returns the available + * algorithms. + */ +int +sysctl_portalgo_available(SYSCTLFN_ARGS) +{ + size_t ai, len = 0; + struct sysctlnode node; + char availalgo[NALGOS * PORTALGO_MAXLEN]; + + DPRINTF("%s called\n", __func__); + + availalgo[0] = '\0'; + + for (ai = 0; ai < NALGOS; ai++) { + len = strlcat(availalgo, algos[ai].name, sizeof(availalgo)); + if (ai < NALGOS - 1) + strlcat(availalgo, " ", sizeof(availalgo)); + } + + DPRINTF("available algos: %s\n", availalgo); + + node = *rnode; + node.sysctl_data = availalgo; + node.sysctl_size = len; + + return sysctl_lookup(SYSCTLFN_CALL(&node)); +} Index: src/sys/netinet/portalgo.h diff -u /dev/null src/sys/netinet/portalgo.h:1.1 --- /dev/null Mon Jun 25 11:28:41 2012 +++ src/sys/netinet/portalgo.h Mon Jun 25 11:28:39 2012 @@ -0,0 +1,57 @@ +/* $NetBSD: portalgo.h,v 1.1 2012/06/25 15:28:39 christos Exp $ */ + +/* + * Copyright 2011 Vlad Balan + * + * Written by Vlad Balan for the NetBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef _NETINET_PORTALGO_H_ +#define _NETINET_PORTALGO_H_ + +#ifdef _KERNEL +#include <sys/sysctl.h> + +struct inpcb_hdr; +int portalgo_randport(uint16_t *, struct inpcb_hdr *, kauth_cred_t); +int sysctl_portalgo_selected(SYSCTLFN_ARGS); +int sysctl_portalgo_selected6(SYSCTLFN_ARGS); +int sysctl_portalgo_available(SYSCTLFN_ARGS); +int portalgo_algo_index_select(struct inpcb_hdr *, int); + +#define PORTALGO_MAXLEN 16 +#endif /* _KERNEL */ + +/* + * User-settable options (used with setsockopt). + */ +#define PORTALGO_DEFAULT 0xffff +#define PORTALGO_BSD 0 +#define PORTALGO_RANDOM_START 1 +#define PORTALGO_RANDOM_PICK 2 +#define PORTALGO_HASH 3 +#define PORTALGO_DOUBLEHASH 4 +#define PORTALGO_RANDINC 5 + +#endif /* !_NETINET_PORTALGO_H_ */