From owner-freebsd-net@FreeBSD.ORG Tue Dec 23 15:29:41 2008 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8AE64106564A for ; Tue, 23 Dec 2008 15:29:41 +0000 (UTC) (envelope-from rrs@lakerest.net) Received: from lakerest.net (unknown [IPv6:2001:240:585:2:203:6dff:fe1a:4ddc]) by mx1.freebsd.org (Postfix) with ESMTP id 12A408FC27 for ; Tue, 23 Dec 2008 15:29:40 +0000 (UTC) (envelope-from rrs@lakerest.net) Received: from [10.1.1.54] ([10.1.1.54]) (authenticated bits=0) by lakerest.net (8.14.1/8.14.1) with ESMTP id mBNFTdjc082092 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NOT); Tue, 23 Dec 2008 10:29:40 -0500 (EST) (envelope-from rrs@lakerest.net) Message-Id: <4A152664-B170-4C6C-85C1-58E2E1577CA3@lakerest.net> From: Randall Stewart To: freebsd-net In-Reply-To: <200812132030.15665.max@love2party.net> Content-Type: multipart/mixed; boundary=Apple-Mail-9-483392564 Mime-Version: 1.0 (Apple Message framework v930.3) Date: Tue, 23 Dec 2008 10:29:39 -0500 References: <494157DF.6030802@FreeBSD.org> <13C9478E-CBF6-4EDA-8E78-AD76549EB844@lakerest.net> <200812132030.15665.max@love2party.net> X-Mailer: Apple Mail (2.930.3) Cc: Max Laier Subject: Re: Heads up --- Thinking about UDP and tunneling X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Dec 2008 15:29:41 -0000 --Apple-Mail-9-483392564 Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit All: Ok here is the latest... this: 1) Incorporates Matt's changes 2) Goes with Matt's idea of adding an INP. 3) We now are holding the INP lock across the call to the tunnel as well as the append. Since the caller will have the INP they can unlock if they need to :-) 4) revamped my s9indent use.. I ran it and then patched back in just its complaints about me... that way the other s9 issues can stay in the file untouched by me :-D Note to Sam, I did not make the base code use the function.. since I thought it got a bit tricky when one started having to worry about sockaddr's being passed to the function AND the typing there of... So I deferred that until later .. :-) I will wait tell all the criticisms settle down and commit eventually here :) R --Apple-Mail-9-483392564 Content-Disposition: attachment; filename=latest_udp_diff.txt Content-Type: text/plain; x-unix-mode=0644; name="latest_udp_diff.txt" Content-Transfer-Encoding: 7bit Index: netinet/udp_usrreq.c =================================================================== --- netinet/udp_usrreq.c (revision 185928) +++ netinet/udp_usrreq.c (working copy) @@ -488,41 +488,76 @@ 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_tunnel_func_t tunnel_func; + + tunnel_func = (udp_tunnel_func_t) last->inp_ppcb; + tunnel_func(m, iphlen, last); + INP_RUNLOCK(last); + } } last = inp; /* - * Don't look for additional matches if this one does - * not have either the SO_REUSEPORT or SO_REUSEADDR - * socket options set. This heuristic avoids - * searching through all pcbs in the common case of a - * non-shared port. It assumes that an application - * will never clear these options after setting them. + * Don't look for additional matches if this one + * does not have either the SO_REUSEPORT or + * SO_REUSEADDR socket options set. This heuristic + * avoids searching through all pcbs in the common + * case of a non-shared port. It assumes that an + * application will never clear these options after + * setting them. */ if ((last->inp_socket->so_options & - (SO_REUSEPORT|SO_REUSEADDR)) == 0) + (SO_REUSEPORT | SO_REUSEADDR)) == 0) break; } if (last == NULL) { /* - * No matching pcb found; discard datagram. (No need - * to send an ICMP Port Unreachable for a broadcast - * or multicast datgram.) + * No matching pcb found; discard datagram. (No + * need to send an ICMP Port Unreachable for a + * broadcast or multicast datgram.) */ 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_tunnel_func_t tunnel_func; + + tunnel_func = (udp_tunnel_func_t) last->inp_ppcb; + tunnel_func(m, iphlen, last); + INP_RUNLOCK(last); + INP_INFO_RUNLOCK(&V_udbinfo); + } return; } - /* * Locate pcb for datagram. */ @@ -553,7 +588,6 @@ INP_INFO_RUNLOCK(&V_udbinfo); return; } - /* * Check the minimum TTL for socket. */ @@ -563,6 +597,18 @@ INP_RUNLOCK(inp); goto badunlocked; } + if (inp->inp_ppcb) { + /* + * Engage the tunneling protocol we must make sure all locks + * are released when we call the tunneling protocol. + */ + udp_tunnel_func_t tunnel_func; + + tunnel_func = (udp_tunnel_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,10 +1184,41 @@ 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_tunnel_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); +} + static int udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { Index: netinet/udp_var.h =================================================================== --- netinet/udp_var.h (revision 185928) +++ netinet/udp_var.h (working copy) @@ -107,6 +107,10 @@ void udp_input(struct mbuf *, int); struct inpcb *udp_notify(struct inpcb *inp, int errno); int udp_shutdown(struct socket *so); + + +typedef void(*udp_tunnel_func_t)(struct mbuf *, int off, struct inpcb *); +int udp_set_kernel_tunneling(struct socket *so, udp_tunnel_func_t f); #endif #endif Index: netinet6/udp6_usrreq.c =================================================================== --- netinet6/udp6_usrreq.c (revision 185928) +++ netinet6/udp6_usrreq.c (working copy) @@ -262,54 +262,72 @@ if (inp->in6p_lport != uh->uh_dport) continue; /* - * XXX: Do not check source port of incoming datagram - * unless inp_connect() has been called to bind the - * fport part of the 4-tuple; the source could be - * trying to talk to us with an ephemeral port. + * XXX: Do not check source port of incoming + * datagram unless inp_connect() has been called to + * bind the fport part of the 4-tuple; the source + * could be trying to talk to us with an ephemeral + * port. */ if (inp->inp_fport != 0 && inp->inp_fport != uh->uh_sport) continue; if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, - &ip6->ip6_dst)) + &ip6->ip6_dst)) continue; } if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, - &ip6->ip6_src) || + &ip6->ip6_src) || inp->in6p_fport != uh->uh_sport) continue; } - if (last != NULL) { struct mbuf *n; 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) { + /* + * 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_tunnel_func_t tunnel_func; + + tunnel_func = (udp_tunnel_func_t) last->inp_ppcb; + tunnel_func(m, off, last); + INP_RUNLOCK(last); + } else { + udp6_append(last, n, off, &fromsa); + INP_RUNLOCK(last); + } } } last = inp; /* - * Don't look for additional matches if this one does - * not have either the SO_REUSEPORT or SO_REUSEADDR - * socket options set. This heuristic avoids - * searching through all pcbs in the common case of a - * non-shared port. It assumes that an application - * will never clear these options after setting them. + * Don't look for additional matches if this one + * does not have either the SO_REUSEPORT or + * SO_REUSEADDR socket options set. This heuristic + * avoids searching through all pcbs in the common + * case of a non-shared port. It assumes that an + * application will never clear these options after + * setting them. */ if ((last->inp_socket->so_options & - (SO_REUSEPORT|SO_REUSEADDR)) == 0) + (SO_REUSEPORT | SO_REUSEADDR)) == 0) break; } if (last == NULL) { /* - * No matching pcb found; discard datagram. (No need - * to send an ICMP Port Unreachable for a broadcast - * or multicast datgram.) + * No matching pcb found; discard datagram. (No + * need to send an ICMP Port Unreachable for a + * broadcast or multicast datgram.) */ V_udpstat.udps_noport++; V_udpstat.udps_noportmcast++; @@ -317,6 +335,19 @@ } INP_RLOCK(last); INP_INFO_RUNLOCK(&V_udbinfo); + if (last->inp_ppcb) { + /* + * Engage the tunneling protocol we must make sure + * all locks are released when we call the tunneling + * protocol. + */ + udp_tunnel_func_t tunnel_func; + + tunnel_func = (udp_tunnel_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 +385,18 @@ } INP_RLOCK(inp); INP_INFO_RUNLOCK(&V_udbinfo); + if (inp->inp_ppcb) { + /* + * Engage the tunneling protocol we must make sure all locks + * are released when we call the tunneling protocol. + */ + udp_tunnel_func_t tunnel_func; + + tunnel_func = (udp_tunnel_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); --Apple-Mail-9-483392564 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit ------------------------------ Randall Stewart 803-317-4952 (cell) 803-345-0391(direct) --Apple-Mail-9-483392564--