Date: Tue, 6 Jan 2009 12:13:41 +0000 (UTC) From: Randall Stewart <rrs@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r186813 - in head/sys: netinet netinet6 Message-ID: <200901061213.n06CDfuv030333@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rrs Date: Tue Jan 6 12:13:40 2009 New Revision: 186813 URL: http://svn.freebsd.org/changeset/base/186813 Log: Add the ability of an alternate transport protocol to easily tunnel over udp by providing a hook function that will be called instead of appending to the socket buffer. Modified: head/sys/netinet/udp_usrreq.c head/sys/netinet/udp_var.h head/sys/netinet6/udp6_usrreq.c Modified: head/sys/netinet/udp_usrreq.c ============================================================================== --- head/sys/netinet/udp_usrreq.c Tue Jan 6 12:12:39 2009 (r186812) +++ head/sys/netinet/udp_usrreq.c Tue Jan 6 12:13:40 2009 (r186813) @@ -488,10 +488,33 @@ udp_input(struct mbuf *m, int off) struct mbuf *n; n = m_copy(m, 0, M_COPYALL); - if (n != NULL) - udp_append(last, ip, n, iphlen + - sizeof(struct udphdr), &udp_in); - INP_RUNLOCK(last); + if (last->inp_ppcb == NULL) { + if (n != NULL) + udp_append(last, + ip, n, + iphlen + + sizeof(struct udphdr), + &udp_in); + INP_RUNLOCK(last); + } else { + /* + * Engage the tunneling protocol we + * will have to leave the info_lock + * up, since we are hunting through + * multiple UDP inp's hope we don't + * break. + * + * XXXML: Maybe add a flag to the + * prototype so that the tunneling + * can defer work that can't be done + * under the info lock? + */ + udp_tun_func_t tunnel_func; + + tunnel_func = (udp_tun_func_t)last->inp_ppcb; + tunnel_func(n, iphlen, last); + INP_RUNLOCK(last); + } } last = inp; /* @@ -516,10 +539,24 @@ udp_input(struct mbuf *m, int off) V_udpstat.udps_noportbcast++; goto badheadlocked; } - udp_append(last, ip, m, iphlen + sizeof(struct udphdr), - &udp_in); - INP_RUNLOCK(last); - INP_INFO_RUNLOCK(&V_udbinfo); + if (last->inp_ppcb == NULL) { + udp_append(last, ip, m, iphlen + sizeof(struct udphdr), + &udp_in); + INP_RUNLOCK(last); + INP_INFO_RUNLOCK(&V_udbinfo); + } else { + /* + * Engage the tunneling protocol we must make sure + * all locks are released when we call the tunneling + * protocol. + */ + udp_tun_func_t tunnel_func; + + tunnel_func = (udp_tun_func_t)last->inp_ppcb; + tunnel_func(m, iphlen, last); + INP_RUNLOCK(last); + INP_INFO_RUNLOCK(&V_udbinfo); + } return; } @@ -563,6 +600,18 @@ udp_input(struct mbuf *m, int off) INP_RUNLOCK(inp); goto badunlocked; } + if (inp->inp_ppcb != NULL) { + /* + * Engage the tunneling protocol we must make sure all locks + * are released when we call the tunneling protocol. + */ + udp_tun_func_t tunnel_func; + + tunnel_func = (udp_tun_func_t)inp->inp_ppcb; + tunnel_func(m, iphlen, inp); + INP_RUNLOCK(inp); + return; + } udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in); INP_RUNLOCK(inp); return; @@ -1138,6 +1187,34 @@ udp_attach(struct socket *so, int proto, INP_INFO_WUNLOCK(&V_udbinfo); inp->inp_vflag |= INP_IPV4; inp->inp_ip_ttl = V_ip_defttl; + /* + * UDP does not have a per-protocol pcb (inp->inp_ppcb). + * We use this pointer for kernel tunneling pointer. + * If we ever need to have a protocol block we will + * need to move this function pointer there. Null + * in this pointer means "do the normal thing". + */ + inp->inp_ppcb = NULL; + INP_WUNLOCK(inp); + return (0); +} + +int +udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f) +{ + struct inpcb *inp; + + inp = (struct inpcb *)so->so_pcb; + if (so->so_type != SOCK_DGRAM) { + /* Not UDP socket... sorry! */ + return (ENOTSUP); + } + if (inp == NULL) { + /* NULL INP? */ + return (EINVAL); + } + INP_WLOCK(inp); + inp->inp_ppcb = f; INP_WUNLOCK(inp); return (0); } Modified: head/sys/netinet/udp_var.h ============================================================================== --- head/sys/netinet/udp_var.h Tue Jan 6 12:12:39 2009 (r186812) +++ head/sys/netinet/udp_var.h Tue Jan 6 12:13:40 2009 (r186813) @@ -110,6 +110,10 @@ void udp_init(void); void udp_input(struct mbuf *, int); struct inpcb *udp_notify(struct inpcb *inp, int errno); int udp_shutdown(struct socket *so); + + +typedef void(*udp_tun_func_t)(struct mbuf *, int off, struct inpcb *); +int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f); #endif #endif Modified: head/sys/netinet6/udp6_usrreq.c ============================================================================== --- head/sys/netinet6/udp6_usrreq.c Tue Jan 6 12:12:39 2009 (r186812) +++ head/sys/netinet6/udp6_usrreq.c Tue Jan 6 12:13:40 2009 (r186813) @@ -287,8 +287,25 @@ udp6_input(struct mbuf **mp, int *offp, if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { INP_RLOCK(last); - udp6_append(last, n, off, &fromsa); - INP_RUNLOCK(last); + if (last->inp_ppcb != NULL) { + /* + * Engage the tunneling + * protocol we will have to + * leave the info_lock up, + * since we are hunting + * through multiple UDP + * inp's hope we don't break. + * + */ + udp_tun_func_t tunnel_func; + + tunnel_func = (udp_tun_func_t)last->inp_ppcb; + tunnel_func(n, off, last); + INP_RUNLOCK(last); + } else { + udp6_append(last, n, off, &fromsa); + INP_RUNLOCK(last); + } } } last = inp; @@ -317,6 +334,19 @@ udp6_input(struct mbuf **mp, int *offp, } INP_RLOCK(last); INP_INFO_RUNLOCK(&V_udbinfo); + if (last->inp_ppcb != NULL) { + /* + * Engage the tunneling protocol we must make sure + * all locks are released when we call the tunneling + * protocol. + */ + udp_tun_func_t tunnel_func; + + tunnel_func = (udp_tun_func_t)inp->inp_ppcb; + tunnel_func(m, off, last); + INP_RUNLOCK(last); + return (IPPROTO_DONE); + } udp6_append(last, m, off, &fromsa); INP_RUNLOCK(last); return (IPPROTO_DONE); @@ -354,6 +384,18 @@ udp6_input(struct mbuf **mp, int *offp, } INP_RLOCK(inp); INP_INFO_RUNLOCK(&V_udbinfo); + if (inp->inp_ppcb != NULL) { + /* + * Engage the tunneling protocol we must make sure all locks + * are released when we call the tunneling protocol. + */ + udp_tun_func_t tunnel_func; + + tunnel_func = (udp_tun_func_t)inp->inp_ppcb; + tunnel_func(m, off, inp); + INP_RUNLOCK(inp); + return (IPPROTO_DONE); + } udp6_append(inp, m, off, &fromsa); INP_RUNLOCK(inp); return (IPPROTO_DONE);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901061213.n06CDfuv030333>