tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

code for RFC6056 - patch for sys/netinet6



Index: in6_pcb.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.114
diff -u -a -r1.114 in6_pcb.c
--- in6_pcb.c   4 May 2011 01:45:48 -0000       1.114
+++ in6_pcb.c   25 Aug 2011 21:52:31 -0000
@@ -91,6 +91,7 @@
 #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 @@
        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 @@
        }
        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: in6_pcb.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_pcb.h,v
retrieving revision 1.35
diff -u -a -r1.35 in6_pcb.h
--- in6_pcb.h   3 May 2011 18:28:45 -0000       1.35
+++ in6_pcb.h   25 Aug 2011 21:52:31 -0000
@@ -78,14 +78,15 @@

 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  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: in6_proto.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_proto.c,v
retrieving revision 1.92
diff -u -a -r1.92 in6_proto.c
--- in6_proto.c 24 May 2011 18:07:11 -0000      1.92
+++ in6_proto.c 25 Aug 2011 21:52:31 -0000
@@ -168,13 +168,13 @@
 #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 @@
        .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: in6_src.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_src.c,v
retrieving revision 1.51
diff -u -a -r1.51 in6_src.c
--- in6_src.c   17 May 2011 04:39:57 -0000      1.51
+++ in6_src.c   25 Aug 2011 21:52:31 -0000
@@ -93,6 +93,7 @@
 #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 @@
 {
        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 @@
        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: udp6_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/udp6_output.c,v
retrieving revision 1.41
diff -u -a -r1.41 udp6_output.c
--- udp6_output.c       15 Jul 2010 23:46:55 -0000      1.41
+++ udp6_output.c       25 Aug 2011 21:52:31 -0000
@@ -182,10 +182,8 @@
                /*
                 * 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 +290,9 @@
                        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: udp6_usrreq.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/udp6_usrreq.c,v
retrieving revision 1.89
diff -u -a -r1.89 udp6_usrreq.c
--- udp6_usrreq.c       3 May 2011 18:28:45 -0000       1.89
+++ udp6_usrreq.c       25 Aug 2011 21:52:31 -0000
@@ -64,6 +64,8 @@
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.89 2011/05/03 18:28:45
dyoung Exp $");

+#include "opt_inet.h"
+
 #include <sys/param.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
@@ -75,6 +77,7 @@
 #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 @@
 #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 @@
        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 @@
 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_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: udp6_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/udp6_var.h,v
retrieving revision 1.23
diff -u -a -r1.23 udp6_var.h
--- udp6_var.h  24 Apr 2008 11:38:38 -0000      1.23
+++ udp6_var.h  25 Aug 2011 21:52:31 -0000
@@ -88,7 +88,8 @@
 #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_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 */


Home | Main Index | Thread Index | Old Index