mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-25 11:37:56 +00:00
Add support for SCTP/UDP/IPV6.
This completes the support of http://tools.ietf.org/html/draft-ietf-tsvwg-sctp-udp-encaps MFC after: 1 week
This commit is contained in:
parent
9ba63ff592
commit
3a51a2647a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=243186
@ -144,7 +144,12 @@ struct sctp_tagblock {
|
||||
|
||||
|
||||
struct sctp_epinfo {
|
||||
struct socket *udp_tun_socket;
|
||||
#ifdef INET
|
||||
struct socket *udp4_tun_socket;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct socket *udp6_tun_socket;
|
||||
#endif
|
||||
struct sctpasochead *sctp_asochash;
|
||||
u_long hashasocmark;
|
||||
|
||||
|
@ -549,8 +549,6 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
|
||||
if ((var) < (min)) { (var) = (min); } \
|
||||
else if ((var) > (max)) { (var) = (max); }
|
||||
|
||||
/* XXX: Remove the #if after tunneling over IPv6 works also on FreeBSD. */
|
||||
#if !defined(__FreeBSD__) || defined(INET)
|
||||
static int
|
||||
sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
@ -582,8 +580,6 @@ sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS)
|
||||
return (error);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
|
||||
@ -1067,12 +1063,9 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLTYPE_UINT | CTLFLAG_R
|
||||
"Clear SCTP Logging buffer");
|
||||
#endif
|
||||
|
||||
/* XXX: Remove the #if after tunneling over IPv6 works also on FreeBSD. */
|
||||
#if !defined(__FreeBSD__) || defined(INET)
|
||||
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLTYPE_UINT | CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), 0, sysctl_sctp_udp_tunneling_check, "IU",
|
||||
SCTPCTL_UDP_TUNNELING_PORT_DESC);
|
||||
#endif
|
||||
|
||||
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, enable_sack_immediately, CTLTYPE_UINT | CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), 0, sysctl_sctp_check, "IU",
|
||||
|
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/sctp_var.h>
|
||||
#include <netinet/sctp_sysctl.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/sctp6_var.h>
|
||||
#endif
|
||||
#include <netinet/sctp_header.h>
|
||||
#include <netinet/sctp_output.h>
|
||||
@ -48,6 +49,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/sctp_auth.h>
|
||||
#include <netinet/sctp_asconf.h>
|
||||
#include <netinet/sctp_bsd_addr.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
|
||||
#ifndef KTR_SCTP
|
||||
@ -6769,24 +6773,15 @@ sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_
|
||||
}
|
||||
|
||||
#endif
|
||||
/* XXX: Remove the #ifdef after tunneling over IPv6 works also on FreeBSD. */
|
||||
#ifdef INET
|
||||
/* We will need to add support
|
||||
* to bind the ports and such here
|
||||
* so we can do UDP tunneling. In
|
||||
* the mean-time, we return error
|
||||
*/
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
#include <sys/proc.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/sctp6_var.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
|
||||
{
|
||||
struct ip *iph;
|
||||
|
||||
#ifdef INET6
|
||||
struct ip6_hdr *ip6;
|
||||
|
||||
#endif
|
||||
struct mbuf *sp, *last;
|
||||
struct udphdr *uhdr;
|
||||
uint16_t port;
|
||||
@ -6836,10 +6831,10 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case IPV6_VERSION >> 4:
|
||||
/* Not yet supported. */
|
||||
goto out;
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - sizeof(struct udphdr));
|
||||
sctp6_input_with_port(&m, &off, port);
|
||||
break;
|
||||
|
||||
#endif
|
||||
default:
|
||||
goto out;
|
||||
@ -6853,19 +6848,22 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
|
||||
void
|
||||
sctp_over_udp_stop(void)
|
||||
{
|
||||
struct socket *sop;
|
||||
|
||||
/*
|
||||
* This function assumes sysctl caller holds sctp_sysctl_info_lock()
|
||||
* for writting!
|
||||
*/
|
||||
if (SCTP_BASE_INFO(udp_tun_socket) == NULL) {
|
||||
/* Nothing to do */
|
||||
return;
|
||||
#ifdef INET
|
||||
if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) {
|
||||
soclose(SCTP_BASE_INFO(udp4_tun_socket));
|
||||
SCTP_BASE_INFO(udp4_tun_socket) = NULL;
|
||||
}
|
||||
sop = SCTP_BASE_INFO(udp_tun_socket);
|
||||
soclose(sop);
|
||||
SCTP_BASE_INFO(udp_tun_socket) = NULL;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) {
|
||||
soclose(SCTP_BASE_INFO(udp6_tun_socket));
|
||||
SCTP_BASE_INFO(udp6_tun_socket) = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@ -6873,53 +6871,83 @@ sctp_over_udp_start(void)
|
||||
{
|
||||
uint16_t port;
|
||||
int ret;
|
||||
struct sockaddr_in sin;
|
||||
struct socket *sop = NULL;
|
||||
struct thread *th;
|
||||
struct ucred *cred;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in sin;
|
||||
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
#endif
|
||||
/*
|
||||
* This function assumes sysctl caller holds sctp_sysctl_info_lock()
|
||||
* for writting!
|
||||
*/
|
||||
port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
|
||||
if (port == 0) {
|
||||
if (ntohs(port) == 0) {
|
||||
/* Must have a port set */
|
||||
return (EINVAL);
|
||||
}
|
||||
if (SCTP_BASE_INFO(udp_tun_socket) != NULL) {
|
||||
#ifdef INET
|
||||
if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) {
|
||||
/* Already running -- must stop first */
|
||||
return (EALREADY);
|
||||
}
|
||||
th = curthread;
|
||||
cred = th->td_ucred;
|
||||
if ((ret = socreate(PF_INET, &sop,
|
||||
SOCK_DGRAM, IPPROTO_UDP, cred, th))) {
|
||||
return (ret);
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) {
|
||||
/* Already running -- must stop first */
|
||||
return (EALREADY);
|
||||
}
|
||||
SCTP_BASE_INFO(udp_tun_socket) = sop;
|
||||
/* call the special UDP hook */
|
||||
ret = udp_set_kernel_tunneling(sop, sctp_recv_udp_tunneled_packet);
|
||||
if (ret) {
|
||||
goto exit_stage_left;
|
||||
}
|
||||
/* Ok we have a socket, bind it to the port */
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
ret = sobind(sop, (struct sockaddr *)&sin, th);
|
||||
if (ret) {
|
||||
/* Close up we cant get the port */
|
||||
exit_stage_left:
|
||||
#endif
|
||||
#ifdef INET
|
||||
if ((ret = socreate(PF_INET, &SCTP_BASE_INFO(udp4_tun_socket),
|
||||
SOCK_DGRAM, IPPROTO_UDP,
|
||||
curthread->td_ucred, curthread))) {
|
||||
sctp_over_udp_stop();
|
||||
return (ret);
|
||||
}
|
||||
/*
|
||||
* Ok we should now get UDP packets directly to our input routine
|
||||
* sctp_recv_upd_tunneled_packet().
|
||||
*/
|
||||
/* Call the special UDP hook. */
|
||||
if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket),
|
||||
sctp_recv_udp_tunneled_packet))) {
|
||||
sctp_over_udp_stop();
|
||||
return (ret);
|
||||
}
|
||||
/* Ok, we have a socket, bind it to the port. */
|
||||
memset(&sin, 0, sizeof(struct sockaddr_in));
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
if ((ret = sobind(SCTP_BASE_INFO(udp4_tun_socket),
|
||||
(struct sockaddr *)&sin, curthread))) {
|
||||
sctp_over_udp_stop();
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((ret = socreate(PF_INET6, &SCTP_BASE_INFO(udp6_tun_socket),
|
||||
SOCK_DGRAM, IPPROTO_UDP,
|
||||
curthread->td_ucred, curthread))) {
|
||||
sctp_over_udp_stop();
|
||||
return (ret);
|
||||
}
|
||||
/* Call the special UDP hook. */
|
||||
if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket),
|
||||
sctp_recv_udp_tunneled_packet))) {
|
||||
sctp_over_udp_stop();
|
||||
return (ret);
|
||||
}
|
||||
/* Ok, we have a socket, bind it to the port. */
|
||||
memset(&sin6, 0, sizeof(struct sockaddr_in6));
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_port = htons(port);
|
||||
if ((ret = sobind(SCTP_BASE_INFO(udp6_tun_socket),
|
||||
(struct sockaddr *)&sin6, curthread))) {
|
||||
sctp_over_udp_stop();
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -323,13 +323,9 @@ do { \
|
||||
} while (0)
|
||||
|
||||
/* functions to start/stop udp tunneling */
|
||||
/* XXX: Remove the #ifdef after tunneling over IPv6 works also on FreeBSD. */
|
||||
#ifdef INET
|
||||
void sctp_over_udp_stop(void);
|
||||
int sctp_over_udp_start(void);
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
sctp_soreceive(struct socket *so, struct sockaddr **psa,
|
||||
struct uio *uio,
|
||||
|
@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$");
|
||||
extern struct protosw inetsw[];
|
||||
|
||||
int
|
||||
sctp6_input(struct mbuf **i_pak, int *offp, int proto)
|
||||
sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
|
||||
{
|
||||
struct mbuf *m;
|
||||
int iphlen;
|
||||
@ -84,7 +84,6 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
|
||||
#endif
|
||||
uint32_t mflowid;
|
||||
uint8_t use_mflowid;
|
||||
uint16_t port = 0;
|
||||
|
||||
iphlen = *offp;
|
||||
if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
|
||||
@ -195,6 +194,12 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sctp6_input(struct mbuf **i_pak, int *offp, int proto SCTP_UNUSED)
|
||||
{
|
||||
return (sctp6_input_with_port(i_pak, offp, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
sctp6_notify_mbuf(struct sctp_inpcb *inp, struct icmp6_hdr *icmp6,
|
||||
struct sctphdr *sh, struct sctp_tcb *stcb, struct sctp_nets *net)
|
||||
|
@ -42,6 +42,7 @@ SYSCTL_DECL(_net_inet6_sctp6);
|
||||
extern struct pr_usrreqs sctp6_usrreqs;
|
||||
|
||||
int sctp6_input(struct mbuf **, int *, int);
|
||||
int sctp6_input_with_port(struct mbuf **, int *, uint16_t);
|
||||
int
|
||||
sctp6_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
|
||||
struct mbuf *, struct proc *);
|
||||
|
Loading…
Reference in New Issue
Block a user