mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-27 08:00:11 +00:00
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.
This commit is contained in:
parent
600b915569
commit
c7c7ea4b5a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=186813
@ -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, struct thread *td)
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -287,8 +287,25 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
|
||||
|
||||
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, int proto)
|
||||
}
|
||||
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, int proto)
|
||||
}
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user