Module Name:    src
Committed By:   christos
Date:           Sat Sep 24 17:22:14 UTC 2011

Modified Files:
        src/sys/netinet6: in6_pcb.c in6_pcb.h in6_proto.c in6_src.c
            udp6_output.c udp6_usrreq.c udp6_var.h

Log Message:
Add inet6 part of the rfc6056 code contributed by Vlad Balan as part of
Google SoC-2011


To generate a diff of this commit:
cvs rdiff -u -r1.115 -r1.116 src/sys/netinet6/in6_pcb.c
cvs rdiff -u -r1.35 -r1.36 src/sys/netinet6/in6_pcb.h
cvs rdiff -u -r1.92 -r1.93 src/sys/netinet6/in6_proto.c
cvs rdiff -u -r1.51 -r1.52 src/sys/netinet6/in6_src.c
cvs rdiff -u -r1.42 -r1.43 src/sys/netinet6/udp6_output.c
cvs rdiff -u -r1.89 -r1.90 src/sys/netinet6/udp6_usrreq.c
cvs rdiff -u -r1.23 -r1.24 src/sys/netinet6/udp6_var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet6/in6_pcb.c
diff -u src/sys/netinet6/in6_pcb.c:1.115 src/sys/netinet6/in6_pcb.c:1.116
--- src/sys/netinet6/in6_pcb.c:1.115	Wed Aug 31 14:31:03 2011
+++ src/sys/netinet6/in6_pcb.c	Sat Sep 24 13:22:14 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_pcb.c,v 1.115 2011/08/31 18:31:03 plunky Exp $	*/
+/*	$NetBSD: in6_pcb.c,v 1.116 2011/09/24 17:22:14 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.115 2011/08/31 18:31:03 plunky Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.116 2011/09/24 17:22:14 christos Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
@@ -91,6 +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 <netinet6/ip6_var.h>
 #include <netinet6/in6_pcb.h>
 #include <netinet6/scope6_var.h>
@@ -176,6 +177,8 @@ 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_bindportonsend = false;
 #if defined(IPSEC) || defined(FAST_IPSEC)
 	error = ipsec_init_pcbpolicy(so, &in6p->in6p_sp);
 	if (error != 0) {
@@ -547,6 +550,18 @@ in6_pcbconnect(void *v, struct mbuf *nam
 	}
 	in6p->in6p_faddr = sin6->sin6_addr;
 	in6p->in6p_fport = sin6->sin6_port;
+
+        /* Late bind, if needed */
+	if (in6p->in6p_bindportonsend) {
+               struct sockaddr_in6 lsin = *((const struct sockaddr_in6 *)
+		    in6p->in6p_socket->so_proto->pr_domain->dom_sa_any);
+		lsin.sin6_addr = in6p->in6p_laddr;
+		lsin.sin6_port = 0;
+
+               if ((error = in6_pcbbind_port(in6p, &lsin, l)) != 0)
+                       return error;
+	}
+	
 	in6_pcbstate(in6p, IN6P_CONNECTED);
 	in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
 	if (ip6_auto_flowlabel)

Index: src/sys/netinet6/in6_pcb.h
diff -u src/sys/netinet6/in6_pcb.h:1.35 src/sys/netinet6/in6_pcb.h:1.36
--- src/sys/netinet6/in6_pcb.h:1.35	Tue May  3 14:28:45 2011
+++ src/sys/netinet6/in6_pcb.h	Sat Sep 24 13:22:14 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_pcb.h,v 1.35 2011/05/03 18:28:45 dyoung Exp $	*/
+/*	$NetBSD: in6_pcb.h,v 1.36 2011/09/24 17:22:14 christos Exp $	*/
 /*	$KAME: in6_pcb.h,v 1.45 2001/02/09 05:59:46 itojun Exp $	*/
 
 /*
@@ -78,14 +78,15 @@ struct icmp6_filter;
 
 struct	in6pcb {
 	struct inpcb_hdr in6p_head;
-#define in6p_hash	in6p_head.inph_hash
-#define in6p_queue	in6p_head.inph_queue
-#define in6p_af		in6p_head.inph_af
-#define in6p_ppcb	in6p_head.inph_ppcb
-#define in6p_state	in6p_head.inph_state
-#define in6p_socket	in6p_head.inph_socket
-#define in6p_table	in6p_head.inph_table
-#define in6p_sp		in6p_head.inph_sp
+#define in6p_hash	 in6p_head.inph_hash
+#define in6p_queue	 in6p_head.inph_queue
+#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_socket	 in6p_head.inph_socket
+#define in6p_table	 in6p_head.inph_table
+#define in6p_sp		 in6p_head.inph_sp
 	struct	route in6p_route;	/* placeholder for routing entry */
 	u_int16_t in6p_fport;		/* foreign port */
 	u_int16_t in6p_lport;		/* local port */
@@ -98,6 +99,7 @@ struct	in6pcb {
 	struct	ip6_moptions *in6p_moptions; /* IP6 multicast options */
 	struct icmp6_filter *in6p_icmp6filt;
 	int	in6p_cksum;		/* IPV6_CHECKSUM setsockopt */
+	bool    in6p_bindportonsend;
 };
 
 #define in6p_faddr	in6p_ip6.ip6_dst

Index: src/sys/netinet6/in6_proto.c
diff -u src/sys/netinet6/in6_proto.c:1.92 src/sys/netinet6/in6_proto.c:1.93
--- src/sys/netinet6/in6_proto.c:1.92	Tue May 24 14:07:11 2011
+++ src/sys/netinet6/in6_proto.c	Sat Sep 24 13:22:14 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_proto.c,v 1.92 2011/05/24 18:07:11 spz Exp $	*/
+/*	$NetBSD: in6_proto.c,v 1.93 2011/09/24 17:22:14 christos Exp $	*/
 /*	$KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.92 2011/05/24 18:07:11 spz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.93 2011/09/24 17:22:14 christos Exp $");
 
 #include "opt_gateway.h"
 #include "opt_inet.h"
@@ -168,13 +168,13 @@ PR_WRAP_CTLINPUT(tcp6_ctlinput)
 #define	tcp6_ctlinput	tcp6_ctlinput_wrapper
 
 PR_WRAP_CTLOUTPUT(rip6_ctloutput)
-PR_WRAP_CTLOUTPUT(ip6_ctloutput)
 PR_WRAP_CTLOUTPUT(tcp_ctloutput)
+PR_WRAP_CTLOUTPUT(udp6_ctloutput)
 PR_WRAP_CTLOUTPUT(icmp6_ctloutput)
 
 #define	rip6_ctloutput	rip6_ctloutput_wrapper
-#define	ip6_ctloutput	ip6_ctloutput_wrapper
 #define	tcp_ctloutput	tcp_ctloutput_wrapper
+#define	udp6_ctloutput	udp6_ctloutput_wrapper
 #define	icmp6_ctloutput	icmp6_ctloutput_wrapper
 
 #if defined(IPSEC) || defined(FAST_IPSEC)
@@ -203,7 +203,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_PURGEIF,
 	.pr_input = udp6_input,
 	.pr_ctlinput = udp6_ctlinput,
-	.pr_ctloutput = ip6_ctloutput,
+	.pr_ctloutput = udp6_ctloutput,
 	.pr_usrreq = udp6_usrreq,
 	.pr_init = udp6_init,
 },

Index: src/sys/netinet6/in6_src.c
diff -u src/sys/netinet6/in6_src.c:1.51 src/sys/netinet6/in6_src.c:1.52
--- src/sys/netinet6/in6_src.c:1.51	Tue May 17 00:39:57 2011
+++ src/sys/netinet6/in6_src.c	Sat Sep 24 13:22:14 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_src.c,v 1.51 2011/05/17 04:39:57 dholland Exp $	*/
+/*	$NetBSD: in6_src.c,v 1.52 2011/09/24 17:22:14 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.51 2011/05/17 04:39:57 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.52 2011/09/24 17:22:14 christos Exp $");
 
 #include "opt_inet.h"
 
@@ -93,6 +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 <netinet6/in6_var.h>
 #include <netinet/ip6.h>
 #include <netinet6/in6_pcb.h>
@@ -801,35 +802,20 @@ in6_pcbsetport(struct sockaddr_in6 *sin6
 {
 	struct socket *so = in6p->in6p_socket;
 	struct inpcbtable *table = in6p->in6p_table;
-	int cnt;
-	u_int16_t minport, maxport;
 	u_int16_t lport, *lastport;
-	int wild = 0;
-	void *t;
-	int error;
 	enum kauth_network_req req;
-
-	/* 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;
-
+	int error = 0;
+	
 	if (in6p->in6p_flags & IN6P_LOWPORT) {
 #ifndef IPNOPRIVPORTS
 		req = KAUTH_REQ_NETWORK_BIND_PRIVPORT;
 #else
 		req = KAUTH_REQ_NETWORK_BIND_PORT;
 #endif
-
-		minport = ip6_lowportmin;
-		maxport = ip6_lowportmax;
 		lastport = &table->inpt_lastlow;
 	} else {
 		req = KAUTH_REQ_NETWORK_BIND_PORT;
 
-		minport = ip6_anonportmin;
-		maxport = ip6_anonportmax;
 		lastport = &table->inpt_lastport;
 	}
 
@@ -839,52 +825,13 @@ in6_pcbsetport(struct sockaddr_in6 *sin6
 	if (error)
 		return (EACCES);
 
-	if (minport > maxport) {	/* sanity check */
-		u_int16_t swp;
-		
-		swp = minport;
-		minport = maxport;
-		maxport = swp;
-	}
-
-	lport = *lastport - 1;
-	for (cnt = maxport - minport + 1; cnt; cnt--, lport--) {
-		vestigial_inpcb_t vestige;
-
-		if (lport < minport || lport > maxport)
-			lport = maxport;
-#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(lport), wild, &vestige);
-			if (!t && vestige.valid)
-				continue;
-		} else
-#endif
-		{
-			t = in6_pcblookup_port(table, &sin6->sin6_addr,
-			    htons(lport), wild, &vestige);
-			if (!t && vestige.valid)
-				continue;
-		}
-		if (t == 0) {
-			/* We have a free port. Check with the secmodel. */
-			sin6->sin6_port = lport;
-			error = kauth_authorize_network(l->l_cred,
-			    KAUTH_NETWORK_BIND, req, so, sin6, NULL);
-			if (error) {
-				/* Secmodel says no. Keep looking. */
-				continue;
-			}
+       /*
+        * Use RFC6056 randomized port selection
+        */
+	error = rfc6056_randport(&lport, &in6p->in6p_head, l->l_cred);
+	if (error)
+		return error;
 	
-			goto found;
-		}
-	}
-
-	return (EAGAIN);
-
-found:
 	in6p->in6p_flags |= IN6P_ANONPORT;
 	*lastport = lport;
 	in6p->in6p_lport = htons(lport);

Index: src/sys/netinet6/udp6_output.c
diff -u src/sys/netinet6/udp6_output.c:1.42 src/sys/netinet6/udp6_output.c:1.43
--- src/sys/netinet6/udp6_output.c:1.42	Wed Aug 31 14:31:03 2011
+++ src/sys/netinet6/udp6_output.c	Sat Sep 24 13:22:14 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: udp6_output.c,v 1.42 2011/08/31 18:31:03 plunky Exp $	*/
+/*	$NetBSD: udp6_output.c,v 1.43 2011/09/24 17:22:14 christos Exp $	*/
 /*	$KAME: udp6_output.c,v 1.43 2001/10/15 09:19:52 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.42 2011/08/31 18:31:03 plunky Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.43 2011/09/24 17:22:14 christos Exp $");
 
 #include "opt_inet.h"
 
@@ -182,10 +182,9 @@ udp6_output(struct in6pcb * const in6p, 
 		/*
 		 * IPv4 version of udp_output calls in_pcbconnect in this case,
 		 * which needs splnet and affects performance.
-		 * Since we saw no essential reason for calling in_pcbconnect,
-		 * we get rid of such kind of logic, and call in6_selectsrc
-		 * and in6_pcbsetport in order to fill in the local address
-		 * and the local port.
+		 * We have to do this as well, since in6_pcbsetport needs to
+		 * know the foreign address for some of the algorithms that
+		 * it employs.
 		 */
 		if (sin6->sin6_port == 0) {
 			error = EADDRNOTAVAIL;
@@ -292,7 +291,9 @@ udp6_output(struct in6pcb * const in6p, 
 			error = sa6_recoverscope(&lsin6);
 			if (error)
 				goto release;
-			error = in6_pcbsetport(&lsin6, in6p, l);
+
+			error = in6_pcbconnect(in6p, addr6, l);
+
 			if (error)
 				goto release;
 		}

Index: src/sys/netinet6/udp6_usrreq.c
diff -u src/sys/netinet6/udp6_usrreq.c:1.89 src/sys/netinet6/udp6_usrreq.c:1.90
--- src/sys/netinet6/udp6_usrreq.c:1.89	Tue May  3 14:28:45 2011
+++ src/sys/netinet6/udp6_usrreq.c	Sat Sep 24 13:22:14 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: udp6_usrreq.c,v 1.89 2011/05/03 18:28:45 dyoung Exp $	*/
+/*	$NetBSD: udp6_usrreq.c,v 1.90 2011/09/24 17:22:14 christos Exp $	*/
 /*	$KAME: udp6_usrreq.c,v 1.86 2001/05/27 17:33:00 itojun Exp $	*/
 
 /*
@@ -62,7 +62,9 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.89 2011/05/03 18:28:45 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.90 2011/09/24 17:22:14 christos Exp $");
+
+#include "opt_inet.h"
 
 #include <sys/param.h>
 #include <sys/malloc.h>
@@ -75,6 +77,7 @@ __KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.
 #include <sys/systm.h>
 #include <sys/proc.h>
 #include <sys/syslog.h>
+#include <sys/domain.h>
 #include <sys/sysctl.h>
 
 #include <net/if.h>
@@ -89,6 +92,7 @@ __KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.
 #include <netinet/in_pcb.h>
 #include <netinet/udp.h>
 #include <netinet/udp_var.h>
+#include <netinet/rfc6056.h>
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
 #include <netinet6/in6_pcb.h>
@@ -254,6 +258,71 @@ udp6_ctlinput(int cmd, const struct sock
 	return NULL;
 }
 
+int
+udp6_ctloutput(int op, struct socket *so, struct sockopt *sopt)
+{
+	int s;
+	int error = 0;
+	struct inpcb *inp;
+	int family;
+	int optval;
+
+	family = so->so_proto->pr_domain->dom_family;
+
+	s = splsoftnet();
+	switch (family) {
+#ifdef INET
+	case PF_INET:
+		if (sopt->sopt_level != IPPROTO_UDP) {
+			error = ip_ctloutput(op, so, sopt);
+			goto end;
+		}
+		break;
+#endif
+#ifdef INET6
+	case PF_INET6:
+		if (sopt->sopt_level != IPPROTO_UDP) {
+			error = ip6_ctloutput(op, so, sopt);
+			goto end;
+		}
+		break;
+#endif
+	default:
+		error = EAFNOSUPPORT;
+		goto end;
+	}
+	
+	switch (op) {
+	case PRCO_SETOPT:
+		inp = sotoinpcb(so);
+
+		switch (sopt->sopt_name) {
+		case UDP_RFC6056ALGO:
+			error = sockopt_getint(sopt, &optval);
+			if (error)
+				break;
+
+			error = rfc6056_algo_index_select(
+			    (struct inpcb_hdr *)inp, optval);
+			break;
+
+		default:
+			error = ENOPROTOOPT;
+			break;
+		}
+		break;
+
+	default:
+		error = EINVAL;
+		break;
+	}
+
+end:
+	splx(s);
+	return error;
+}
+
+
 extern	int udp6_sendspace;
 extern	int udp6_recvspace;
 
@@ -419,6 +488,8 @@ sysctl_net_inet6_udp6_stats(SYSCTLFN_ARG
 static void
 sysctl_net_inet6_udp6_setup(struct sysctllog **clog)
 {
+	const struct sysctlnode *rfc6056_node;
+	
 	sysctl_createv(clog, 0, NULL, NULL,
 		       CTLFLAG_PERMANENT,
 		       CTLTYPE_NODE, "net", NULL,
@@ -471,6 +542,25 @@ sysctl_net_inet6_udp6_setup(struct sysct
 		       sysctl_net_inet6_udp6_stats, 0, NULL, 0,
 		       CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_STATS,
 		       CTL_EOL);
+	/* RFC6056 subtree */
+	sysctl_createv(clog, 0, NULL, &rfc6056_node,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "rfc6056",
+		       SYSCTL_DESCR("RFC 6056"),
+	    	       NULL, 0, NULL, 0,
+		       CTL_NET, PF_INET6, IPPROTO_UDP, CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &rfc6056_node, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_STRING, "available",
+		       SYSCTL_DESCR("RFC 6056 available algorithms"),
+		       sysctl_rfc6056_available, 0, NULL, RFC6056_MAXLEN,
+		       CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &rfc6056_node, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_STRING, "selected",
+		       SYSCTL_DESCR("RFC 6056 selected algorithm"),
+	               sysctl_rfc6056_selected6, 0, NULL, RFC6056_MAXLEN,
+		       CTL_CREATE, CTL_EOL);
 }
 
 void

Index: src/sys/netinet6/udp6_var.h
diff -u src/sys/netinet6/udp6_var.h:1.23 src/sys/netinet6/udp6_var.h:1.24
--- src/sys/netinet6/udp6_var.h:1.23	Thu Apr 24 07:38:38 2008
+++ src/sys/netinet6/udp6_var.h	Sat Sep 24 13:22:14 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: udp6_var.h,v 1.23 2008/04/24 11:38:38 ad Exp $	*/
+/*	$NetBSD: udp6_var.h,v 1.24 2011/09/24 17:22:14 christos Exp $	*/
 /*	$KAME: udp6_var.h,v 1.11 2000/06/05 00:14:31 itojun Exp $	*/
 
 /*
@@ -84,11 +84,12 @@
 /*
  * Names for UDP6 sysctl objects
  */
-#define UDP6CTL_SENDSPACE	1	/* default send buffer */
-#define UDP6CTL_RECVSPACE	2	/* default recv buffer */
+#define	UDP6CTL_SENDSPACE	1	/* default send buffer */
+#define	UDP6CTL_RECVSPACE	2	/* default recv buffer */
 #define	UDP6CTL_LOOPBACKCKSUM	3	/* do UDP checksum on loopback? */
-#define UDP6CTL_STATS		4	/* udp6 statistics */
-#define UDP6CTL_MAXID		5
+#define	UDP6CTL_STATS		4	/* udp6 statistics */
+#define	UDP6CTL_RFC6056		5	/* RFC 6056 algorithm selection */
+#define	UDP6CTL_MAXID		6
 
 #define UDP6CTL_NAMES { \
 	{ 0, 0 }, \
@@ -100,14 +101,14 @@
 
 #ifdef _KERNEL
 void	*udp6_ctlinput(int, const struct sockaddr *, void *);
+int	udp6_ctloutput(int, struct socket *, struct sockopt *);
 void	udp6_init(void);
 int	udp6_input(struct mbuf **, int *, int);
 int	udp6_output(struct in6pcb *, struct mbuf *, struct mbuf *,
-	struct mbuf *, struct lwp *);
+    struct mbuf *, struct lwp *);
 int	udp6_sysctl(int *, u_int, void *, size_t *, void *, size_t);
-int	udp6_usrreq(struct socket *,
-			 int, struct mbuf *, struct mbuf *, struct mbuf *,
-			 struct lwp *);
+int	udp6_usrreq(struct socket *, int, struct mbuf *, struct mbuf *,
+    struct mbuf *, struct lwp *);
 
 void	udp6_statinc(u_int);
 #endif /* _KERNEL */

Reply via email to