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
This commit is contained in:
Randall Stewart 2016-04-28 15:53:10 +00:00
parent 0b33b55b01
commit abb901c5d7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=298747
5 changed files with 50 additions and 8 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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 */

View File

@ -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);