udp: allow udp_tun_func_t() to indicate it did not eat the packet

Allow udp tunnel functions to indicate they have not taken ownership of
the packet, and that normal UDP processing should continue.

This is especially useful for scenarios where the kernel has taken
ownership of a socket that was originally created by userspace. It
allows the tunnel function to pass through certain packets for userspace
processing.

The primary user of this is if_ovpn, when it receives messages from
unknown peers (which might be a new client).

Reviewed by:	tuexen
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D34883
This commit is contained in:
Kristof Provost 2022-04-11 15:58:28 +02:00
parent b93f47eaee
commit 742e7210d0
7 changed files with 29 additions and 14 deletions

View File

@ -363,7 +363,7 @@ static int vxlan_encap6(struct vxlan_softc *,
const union vxlan_sockaddr *, struct mbuf *);
static int vxlan_transmit(struct ifnet *, struct mbuf *);
static void vxlan_qflush(struct ifnet *);
static void vxlan_rcv_udp_packet(struct mbuf *, int, struct inpcb *,
static bool vxlan_rcv_udp_packet(struct mbuf *, int, struct inpcb *,
const struct sockaddr *, void *);
static int vxlan_input(struct vxlan_socket *, uint32_t, struct mbuf **,
const struct sockaddr *);
@ -2758,7 +2758,7 @@ vxlan_qflush(struct ifnet *ifp __unused)
{
}
static void
static bool
vxlan_rcv_udp_packet(struct mbuf *m, int offset, struct inpcb *inpcb,
const struct sockaddr *srcsa, void *xvso)
{
@ -2802,6 +2802,8 @@ vxlan_rcv_udp_packet(struct mbuf *m, int offset, struct inpcb *inpcb,
out:
if (m != NULL)
m_freem(m);
return (true);
}
static int

View File

@ -219,7 +219,7 @@ in_gre_srcaddr(void *arg __unused, const struct sockaddr *sa,
}
}
static void
static bool
in_gre_udp_input(struct mbuf *m, int off, struct inpcb *inp,
const struct sockaddr *sa, void *ctx)
{
@ -237,9 +237,11 @@ in_gre_udp_input(struct mbuf *m, int off, struct inpcb *inp,
}
if (sc != NULL && (GRE2IFP(sc)->if_flags & IFF_UP) != 0){
gre_input(m, off + sizeof(struct udphdr), IPPROTO_UDP, sc);
return;
return (true);
}
m_freem(m);
return (true);
}
static int

View File

@ -7094,7 +7094,7 @@ sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_
}
#endif
static void
static bool
sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp,
const struct sockaddr *sa SCTP_UNUSED, void *ctx SCTP_UNUSED)
{
@ -7172,9 +7172,11 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp,
goto out;
break;
}
return;
return (true);
out:
m_freem(m);
return (true);
}
#ifdef INET

View File

@ -590,7 +590,7 @@ tcp_switch_back_to_default(struct tcpcb *tp)
}
}
static void
static bool
tcp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp,
const struct sockaddr *sa, void *ctx)
{
@ -659,9 +659,11 @@ tcp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp,
goto out;
break;
}
return;
return (true);
out:
m_freem(m);
return (true);
}
static int

View File

@ -278,6 +278,7 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off,
struct sockaddr_in6 udp_in6;
#endif
struct udpcb *up;
bool filtered;
INP_LOCK_ASSERT(inp);
@ -288,10 +289,11 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off,
if (up->u_tun_func != NULL) {
in_pcbref(inp);
INP_RUNLOCK(inp);
(*up->u_tun_func)(n, off, inp, (struct sockaddr *)&udp_in[0],
filtered = (*up->u_tun_func)(n, off, inp, (struct sockaddr *)&udp_in[0],
up->u_tun_ctx);
INP_RLOCK(inp);
return (in_pcbrele_rlocked(inp));
if (filtered)
return (in_pcbrele_rlocked(inp));
}
off += sizeof(struct udphdr);

View File

@ -36,6 +36,7 @@
#ifndef _NETINET_UDP_VAR_H_
#define _NETINET_UDP_VAR_H_
#include <sys/types.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
@ -60,7 +61,8 @@ struct udpiphdr {
struct inpcb;
struct mbuf;
typedef void(*udp_tun_func_t)(struct mbuf *, int, struct inpcb *,
#ifdef _KERNEL
typedef bool(*udp_tun_func_t)(struct mbuf *, int, struct inpcb *,
const struct sockaddr *, void *);
typedef void(*udp_tun_icmp_t)(int, struct sockaddr *, void *, void *);
@ -78,6 +80,7 @@ struct udpcb {
#define intoudpcb(ip) ((struct udpcb *)(ip)->inp_ppcb)
#define sotoudpcb(so) (intoudpcb(sotoinpcb(so)))
#endif
/* IPsec: ESP in UDP tunneling: */
#define UF_ESPINUDP_NON_IKE 0x00000001 /* w/ non-IKE marker .. */

View File

@ -212,7 +212,7 @@ in6_gre_srcaddr(void *arg __unused, const struct sockaddr *sa,
}
}
static void
static bool
in6_gre_udp_input(struct mbuf *m, int off, struct inpcb *inp,
const struct sockaddr *sa, void *ctx)
{
@ -226,7 +226,7 @@ in6_gre_udp_input(struct mbuf *m, int off, struct inpcb *inp,
dst = *(const struct sockaddr_in6 *)sa;
if (sa6_embedscope(&dst, 0)) {
m_freem(m);
return;
return (true);
}
CK_LIST_FOREACH(sc, &gs->list, chain) {
if (IN6_ARE_ADDR_EQUAL(&sc->gre_oip6.ip6_dst, &dst.sin6_addr))
@ -234,9 +234,11 @@ in6_gre_udp_input(struct mbuf *m, int off, struct inpcb *inp,
}
if (sc != NULL && (GRE2IFP(sc)->if_flags & IFF_UP) != 0){
gre_input(m, off + sizeof(struct udphdr), IPPROTO_UDP, sc);
return;
return (true);
}
m_freem(m);
return (true);
}
static int