aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Stewart <rrs@FreeBSD.org>2016-04-28 15:53:10 +0000
committerRandall Stewart <rrs@FreeBSD.org>2016-04-28 15:53:10 +0000
commitabb901c5d78fb904202a4b98f2996c3ad9afd542 (patch)
tree3a6517c36d65bb8d50cdb69df4ceeff85cc6d0ab
parent0b33b55b014e6098f1a20bf7416822e2ed73fb8a (diff)
downloadsrc-abb901c5d78fb904202a4b98f2996c3ad9afd542.tar.gz
src-abb901c5d78fb904202a4b98f2996c3ad9afd542.zip
Complete the UDP tunneling of ICMP msgs to those protocols
interested in having tunneled UDP and finding out about the ICMP (tested by Michael Tuexen with SCTP.. soon to be using this feature). Differential Revision: http://reviews.freebsd.org/D5875
Notes
Notes: svn path=/head/; revision=298747
-rw-r--r--sys/net/if_vxlan.c2
-rw-r--r--sys/netinet/sctputil.c4
-rw-r--r--sys/netinet/udp_usrreq.c21
-rw-r--r--sys/netinet/udp_var.h8
-rw-r--r--sys/netinet6/udp6_usrreq.c23
5 files changed, 50 insertions, 8 deletions
diff --git a/sys/net/if_vxlan.c b/sys/net/if_vxlan.c
index 59c76ebf4f1b..a5631fcc20df 100644
--- a/sys/net/if_vxlan.c
+++ b/sys/net/if_vxlan.c
@@ -930,7 +930,7 @@ vxlan_socket_init(struct vxlan_socket *vso, struct ifnet *ifp)
}
error = udp_set_kernel_tunneling(vso->vxlso_sock,
- vxlan_rcv_udp_packet, vso);
+ vxlan_rcv_udp_packet, NULL, vso);
if (error) {
if_printf(ifp, "cannot set tunneling function: %d\n", error);
return (error);
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 77c62a113f79..b39d66a1cdff 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -6945,7 +6945,7 @@ sctp_over_udp_start(void)
}
/* Call the special UDP hook. */
if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket),
- sctp_recv_udp_tunneled_packet, NULL))) {
+ sctp_recv_udp_tunneled_packet, NULL, NULL))) {
sctp_over_udp_stop();
return (ret);
}
@@ -6969,7 +6969,7 @@ sctp_over_udp_start(void)
}
/* Call the special UDP hook. */
if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket),
- sctp_recv_udp_tunneled_packet, NULL))) {
+ sctp_recv_udp_tunneled_packet, NULL, NULL))) {
sctp_over_udp_stop();
return (ret);
}
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index fdc2e76dbcfb..503f059a3873 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -792,6 +792,21 @@ udp_common_ctlinput(int cmd, struct sockaddr *sa, void *vip,
udp_notify(inp, inetctlerrmap[cmd]);
}
INP_RUNLOCK(inp);
+ } else {
+ inp = in_pcblookup(pcbinfo, faddr, uh->uh_dport,
+ ip->ip_src, uh->uh_sport,
+ INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL);
+ if (inp != NULL) {
+ struct udpcb *up;
+
+ up = intoudpcb(inp);
+ if (up->u_icmp_func != NULL) {
+ INP_RUNLOCK(inp);
+ (*up->u_icmp_func)(cmd, sa, vip, up->u_tun_ctx);
+ } else {
+ INP_RUNLOCK(inp);
+ }
+ }
}
} else
in_pcbnotifyall(pcbinfo, faddr, inetctlerrmap[cmd],
@@ -1748,7 +1763,7 @@ udp_attach(struct socket *so, int proto, struct thread *td)
#endif /* INET */
int
-udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f, void *ctx)
+udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f, udp_tun_icmp_t i, void *ctx)
{
struct inpcb *inp;
struct udpcb *up;
@@ -1759,11 +1774,13 @@ udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f, void *ctx)
KASSERT(inp != NULL, ("udp_set_kernel_tunneling: inp == NULL"));
INP_WLOCK(inp);
up = intoudpcb(inp);
- if (up->u_tun_func != NULL) {
+ if ((up->u_tun_func != NULL) ||
+ (up->u_icmp_func != NULL)) {
INP_WUNLOCK(inp);
return (EBUSY);
}
up->u_tun_func = f;
+ up->u_icmp_func = i;
up->u_tun_ctx = ctx;
INP_WUNLOCK(inp);
return (0);
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index 40d35ef43812..6d19deea103e 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -55,14 +55,16 @@ struct udpiphdr {
struct inpcb;
struct mbuf;
-typedef void(*udp_tun_func_t)(struct mbuf *, int off, struct inpcb *,
+typedef void(*udp_tun_func_t)(struct mbuf *, int, struct inpcb *,
const struct sockaddr *, void *);
-
+typedef void(*udp_tun_icmp_t)(int, struct sockaddr *, void *, void *);
+
/*
* UDP control block; one per udp.
*/
struct udpcb {
udp_tun_func_t u_tun_func; /* UDP kernel tunneling callback. */
+ udp_tun_icmp_t u_icmp_func; /* UDP kernel tunneling icmp callback */
u_int u_flags; /* Generic UDP flags. */
uint16_t u_rxcslen; /* Coverage for incoming datagrams. */
uint16_t u_txcslen; /* Coverage for outgoing datagrams. */
@@ -179,7 +181,7 @@ struct inpcb *udp_notify(struct inpcb *inp, int errno);
int udp_shutdown(struct socket *so);
int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f,
- void *ctx);
+ udp_tun_icmp_t i, void *ctx);
#endif /* _KERNEL */
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 03479fdbdb40..f6f4d5825c2b 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -553,6 +553,29 @@ udp6_common_ctlinput(int cmd, struct sockaddr *sa, void *d,
bzero(&uh, sizeof(uh));
m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh);
+ if (!PRC_IS_REDIRECT(cmd)) {
+ /* Check to see if its tunneled */
+ struct inpcb *inp;
+ inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_src,
+ uh.uh_sport, &ip6->ip6_dst, uh.uh_dport,
+ INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,
+ m->m_pkthdr.rcvif, m);
+ if (inp != NULL) {
+ struct udpcb *up;
+
+ up = intoudpcb(inp);
+ if (up->u_icmp_func) {
+ /* Yes it is. */
+ INP_RUNLOCK(inp);
+ (*up->u_icmp_func)(cmd, (struct sockaddr *)ip6cp->ip6c_src,
+ d, up->u_tun_ctx);
+ return;
+ } else {
+ /* Can't find it. */
+ INP_RUNLOCK(inp);
+ }
+ }
+ }
(void)in6_pcbnotify(pcbinfo, sa, uh.uh_dport,
(struct sockaddr *)ip6cp->ip6c_src, uh.uh_sport, cmd,
cmdarg, notify);