Add support for the SCTP_REMOTE_UDP_ENCAPS_PORT socket option.
Retire the the now unused sctp_udp_tunneling_for_client_enable sysctl variable. MFC after: 3 months.
This commit is contained in:
parent
3c87aa1d3d
commit
c9c5805975
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=227755
@ -413,6 +413,9 @@ sctp_opt_info(int sd, sctp_assoc_t id, int opt, void *arg, socklen_t * size)
|
||||
case SCTP_PEER_ADDR_THLDS:
|
||||
((struct sctp_paddrthlds *)arg)->spt_assoc_id = id;
|
||||
break;
|
||||
case SCTP_REMOTE_UDP_ENCAPS_PORT:
|
||||
((struct sctp_udpencaps *)arg)->sue_assoc_id = id;
|
||||
break;
|
||||
case SCTP_MAX_BURST:
|
||||
((struct sctp_assoc_value *)arg)->assoc_id = id;
|
||||
break;
|
||||
|
@ -120,6 +120,7 @@ struct sctp_paramhdr {
|
||||
#define SCTP_DEFAULT_SNDINFO 0x00000021
|
||||
#define SCTP_DEFAULT_PRINFO 0x00000022
|
||||
#define SCTP_PEER_ADDR_THLDS 0x00000023
|
||||
#define SCTP_REMOTE_UDP_ENCAPS_PORT 0x00000024
|
||||
|
||||
/*
|
||||
* read-only options
|
||||
|
@ -4062,6 +4062,12 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
}
|
||||
}
|
||||
if (port) {
|
||||
if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
|
||||
sctp_handle_no_route(stcb, net, so_locked);
|
||||
SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
|
||||
sctp_m_freem(m);
|
||||
return (EHOSTUNREACH);
|
||||
}
|
||||
udp = (struct udphdr *)((caddr_t)ip + sizeof(struct ip));
|
||||
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
|
||||
udp->uh_dport = port;
|
||||
@ -4413,6 +4419,12 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
ip6h->ip6_src = lsa6->sin6_addr;
|
||||
|
||||
if (port) {
|
||||
if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
|
||||
sctp_handle_no_route(stcb, net, so_locked);
|
||||
SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
|
||||
sctp_m_freem(m);
|
||||
return (EHOSTUNREACH);
|
||||
}
|
||||
udp = (struct udphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr));
|
||||
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
|
||||
udp->uh_dport = port;
|
||||
@ -10965,6 +10977,10 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh,
|
||||
return;
|
||||
}
|
||||
if (port) {
|
||||
if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
|
||||
sctp_m_freem(mout);
|
||||
return;
|
||||
}
|
||||
udp = (struct udphdr *)comp_cp;
|
||||
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
|
||||
udp->uh_dport = port;
|
||||
@ -11925,6 +11941,10 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
|
||||
|
||||
udp = (struct udphdr *)abm;
|
||||
if (port) {
|
||||
if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
|
||||
sctp_m_freem(mout);
|
||||
return;
|
||||
}
|
||||
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
|
||||
udp->uh_dport = port;
|
||||
/* set udp->uh_ulen later */
|
||||
@ -12186,6 +12206,10 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag,
|
||||
|
||||
udp = (struct udphdr *)sh_out;
|
||||
if (port) {
|
||||
if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
|
||||
sctp_m_freem(mout);
|
||||
return;
|
||||
}
|
||||
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
|
||||
udp->uh_dport = port;
|
||||
/* set udp->uh_ulen later */
|
||||
|
@ -2650,6 +2650,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
#ifdef INET6
|
||||
m->default_flowlabel = 0;
|
||||
#endif
|
||||
m->port = 0; /* encapsulation disabled by default */
|
||||
sctp_auth_set_default_chunks(m->local_auth_chunks);
|
||||
LIST_INIT(&m->shared_keys);
|
||||
/* add default NULL key as key id 0 */
|
||||
@ -3993,13 +3994,9 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
net->RTO = 0;
|
||||
net->RTO_measured = 0;
|
||||
stcb->asoc.numnets++;
|
||||
*(&net->ref_count) = 1;
|
||||
net->ref_count = 1;
|
||||
net->cwr_window_tsn = net->last_cwr_tsn = stcb->asoc.sending_seq - 1;
|
||||
if (SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable)) {
|
||||
net->port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
|
||||
} else {
|
||||
net->port = 0;
|
||||
}
|
||||
net->port = stcb->asoc.port;
|
||||
net->dscp = stcb->asoc.default_dscp;
|
||||
#ifdef INET6
|
||||
net->flowlabel = stcb->asoc.default_flowlabel;
|
||||
|
@ -328,6 +328,7 @@ struct sctp_pcb {
|
||||
uint8_t default_dscp;
|
||||
char current_secret_number;
|
||||
char last_secret_number;
|
||||
uint16_t port; /* remote UDP encapsulation port */
|
||||
};
|
||||
|
||||
#ifndef SCTP_ALIGNMENT
|
||||
|
@ -416,7 +416,7 @@ TAILQ_HEAD(sctpchunk_listhead, sctp_tmit_chunk);
|
||||
#define CHUNK_FLAGS_PR_SCTP_BUF SCTP_PR_SCTP_BUF
|
||||
#define CHUNK_FLAGS_PR_SCTP_RTX SCTP_PR_SCTP_RTX
|
||||
|
||||
/* The upper byte is used as a bit mask */
|
||||
/* The upper byte is used a a bit mask */
|
||||
#define CHUNK_FLAGS_FRAGMENT_OK 0x0100
|
||||
|
||||
struct chk_id {
|
||||
@ -1213,6 +1213,7 @@ struct sctp_association {
|
||||
uint8_t sctp_cmt_pf;
|
||||
uint8_t use_precise_time;
|
||||
uint32_t sctp_features;
|
||||
uint16_t port; /* remote UDP encapsulation port */
|
||||
/*
|
||||
* The mapping array is used to track out of order sequences above
|
||||
* last_acked_seq. 0 indicates packet missing 1 indicates packet
|
||||
|
@ -122,7 +122,6 @@ sctp_init_sysctls()
|
||||
#if defined(SCTP_LOCAL_TRACE_BUF)
|
||||
memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log));
|
||||
#endif
|
||||
SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable) = SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = SCTPCTL_UDP_TUNNELING_PORT_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_enable_sack_immediately) = SCTPCTL_SACK_IMMEDIATELY_ENABLE_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly) = SCTPCTL_NAT_FRIENDLY_INITS_DEFAULT;
|
||||
@ -666,10 +665,6 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), SCTPCTL_RTTVAR_DCCCECN_MIN, SCTPCTL_RTTVAR_DCCCECN_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_base), SCTPCTL_MOBILITY_BASE_MIN, SCTPCTL_MOBILITY_BASE_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), SCTPCTL_MOBILITY_FASTHANDOFF_MIN, SCTPCTL_MOBILITY_FASTHANDOFF_MAX);
|
||||
/* XXX: Remove the #if after tunneling over IPv6 works also on FreeBSD. */
|
||||
#if !defined(__FreeBSD__) || defined(INET)
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MIN, SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MAX);
|
||||
#endif
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), SCTPCTL_SACK_IMMEDIATELY_ENABLE_MIN, SCTPCTL_SACK_IMMEDIATELY_ENABLE_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), SCTPCTL_NAT_FRIENDLY_INITS_MIN, SCTPCTL_NAT_FRIENDLY_INITS_MAX);
|
||||
|
||||
@ -1089,10 +1084,6 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLTYPE_UINT | CTLFLAG_R
|
||||
|
||||
/* 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_for_client_enable, CTLTYPE_UINT | CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), 0, sysctl_sctp_check, "IU",
|
||||
SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DESC);
|
||||
|
||||
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);
|
||||
|
@ -110,7 +110,6 @@ struct sctp_sysctl {
|
||||
#if defined(SCTP_LOCAL_TRACE_BUF)
|
||||
struct sctp_log sctp_log;
|
||||
#endif
|
||||
uint32_t sctp_udp_tunneling_for_client_enable;
|
||||
uint32_t sctp_udp_tunneling_port;
|
||||
uint32_t sctp_enable_sack_immediately;
|
||||
uint32_t sctp_vtag_time_wait;
|
||||
@ -464,12 +463,6 @@ struct sctp_sysctl {
|
||||
#define SCTPCTL_MOBILITY_FASTHANDOFF_MAX 1
|
||||
#define SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT SCTP_DEFAULT_MOBILITY_FASTHANDOFF
|
||||
|
||||
/* Enable SCTP/UDP tunneling for clients*/
|
||||
#define SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DESC "Enable SCTP/UDP tunneling for client"
|
||||
#define SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MIN 0
|
||||
#define SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MAX 1
|
||||
#define SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DEFAULT SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MIN
|
||||
|
||||
/* Enable SCTP/UDP tunneling port */
|
||||
#define SCTPCTL_UDP_TUNNELING_PORT_DESC "Set the SCTP/UDP tunneling port"
|
||||
#define SCTPCTL_UDP_TUNNELING_PORT_MIN 0
|
||||
|
@ -671,6 +671,12 @@ struct sctp_timeouts {
|
||||
uint32_t stimo_shutdownack;
|
||||
};
|
||||
|
||||
struct sctp_udpencaps {
|
||||
sctp_assoc_t sue_assoc_id;
|
||||
struct sockaddr_storage sue_address;
|
||||
uint16_t sue_port;
|
||||
};
|
||||
|
||||
struct sctp_cwnd_args {
|
||||
struct sctp_nets *net; /* network to *//* FIXME: LP64 issue */
|
||||
uint32_t cwnd_new_value;/* cwnd in k */
|
||||
|
@ -3208,6 +3208,92 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_REMOTE_UDP_ENCAPS_PORT:
|
||||
{
|
||||
struct sctp_udpencaps *encaps;
|
||||
struct sctp_nets *net;
|
||||
|
||||
SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
|
||||
|
||||
if (stcb) {
|
||||
net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
|
||||
} else {
|
||||
/*
|
||||
* We increment here since
|
||||
* sctp_findassociation_ep_addr() wil do a
|
||||
* decrement if it finds the stcb as long as
|
||||
* the locked tcb (last argument) is NOT a
|
||||
* TCB.. aka NULL.
|
||||
*/
|
||||
net = NULL;
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
}
|
||||
if (stcb && (net == NULL)) {
|
||||
struct sockaddr *sa;
|
||||
|
||||
sa = (struct sockaddr *)&encaps->sue_address;
|
||||
#ifdef INET
|
||||
if (sa->sa_family == AF_INET) {
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
if (sin->sin_addr.s_addr) {
|
||||
error = EINVAL;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
error = EINVAL;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
error = EAFNOSUPPORT;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stcb) {
|
||||
if (net) {
|
||||
encaps->sue_port = net->port;
|
||||
} else {
|
||||
encaps->sue_port = stcb->asoc.port;
|
||||
}
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
} else {
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
|
||||
(encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
|
||||
SCTP_INP_RLOCK(inp);
|
||||
encaps->sue_port = inp->sctp_ep.port;
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
if (error == 0) {
|
||||
*optsize = sizeof(struct sctp_paddrparams);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
|
||||
error = ENOPROTOOPT;
|
||||
@ -4526,7 +4612,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
break;
|
||||
}
|
||||
case SCTP_PEER_ADDR_PARAMS:
|
||||
/* Applies to the specific association */
|
||||
{
|
||||
struct sctp_paddrparams *paddrp;
|
||||
struct sctp_nets *net;
|
||||
@ -5583,6 +5668,89 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_REMOTE_UDP_ENCAPS_PORT:
|
||||
{
|
||||
struct sctp_udpencaps *encaps;
|
||||
struct sctp_nets *net;
|
||||
|
||||
SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
|
||||
if (stcb) {
|
||||
net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
|
||||
} else {
|
||||
/*
|
||||
* We increment here since
|
||||
* sctp_findassociation_ep_addr() wil do a
|
||||
* decrement if it finds the stcb as long as
|
||||
* the locked tcb (last argument) is NOT a
|
||||
* TCB.. aka NULL.
|
||||
*/
|
||||
net = NULL;
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
}
|
||||
if (stcb && (net == NULL)) {
|
||||
struct sockaddr *sa;
|
||||
|
||||
sa = (struct sockaddr *)&encaps->sue_address;
|
||||
#ifdef INET
|
||||
if (sa->sa_family == AF_INET) {
|
||||
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
if (sin->sin_addr.s_addr) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
error = EAFNOSUPPORT;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stcb) {
|
||||
if (net) {
|
||||
net->port = encaps->sue_port;
|
||||
} else {
|
||||
stcb->asoc.port = encaps->sue_port;
|
||||
}
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
} else {
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
|
||||
(encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
|
||||
SCTP_INP_WLOCK(inp);
|
||||
inp->sctp_ep.port = encaps->sue_port;
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
|
||||
error = ENOPROTOOPT;
|
||||
|
@ -1117,6 +1117,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
|
||||
asoc->authinfo.recv_keyid = 0;
|
||||
LIST_INIT(&asoc->shared_keys);
|
||||
asoc->marked_retrans = 0;
|
||||
asoc->port = m->sctp_ep.port;
|
||||
asoc->timoinit = 0;
|
||||
asoc->timodata = 0;
|
||||
asoc->timosack = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user