summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2014-08-04 20:07:35 +0000
committertuexen <tuexen@FreeBSD.org>2014-08-04 20:07:35 +0000
commite7d5338a8e65c54966be29abef1484db617906bc (patch)
treea943ca14889fa90564a6d1f712a78e122a1aaefd
parent203dc5e795f4b986be5839f34c789a17eca1c30f (diff)
downloadFreeBSD-src-e7d5338a8e65c54966be29abef1484db617906bc.zip
FreeBSD-src-e7d5338a8e65c54966be29abef1484db617906bc.tar.gz
Add support for the SCTP_RECONFIG_SUPPORTED and the corresponding
sysctl controlling the negotiation of the RE-CONFIG extension. MFC after: 3 days
-rw-r--r--lib/libc/net/sctp_sys_calls.c3
-rw-r--r--sys/netinet/sctp.h1
-rw-r--r--sys/netinet/sctp_input.c5
-rw-r--r--sys/netinet/sctp_output.c9
-rw-r--r--sys/netinet/sctp_pcb.c8
-rw-r--r--sys/netinet/sctp_pcb.h1
-rw-r--r--sys/netinet/sctp_peeloff.c1
-rw-r--r--sys/netinet/sctp_structs.h3
-rw-r--r--sys/netinet/sctp_sysctl.c6
-rw-r--r--sys/netinet/sctp_sysctl.h9
-rw-r--r--sys/netinet/sctp_usrreq.c62
-rw-r--r--sys/netinet/sctputil.c3
12 files changed, 97 insertions, 14 deletions
diff --git a/lib/libc/net/sctp_sys_calls.c b/lib/libc/net/sctp_sys_calls.c
index 6fd136e..8e7d709 100644
--- a/lib/libc/net/sctp_sys_calls.c
+++ b/lib/libc/net/sctp_sys_calls.c
@@ -356,6 +356,9 @@ sctp_opt_info(int sd, sctp_assoc_t id, int opt, void *arg, socklen_t * size)
case SCTP_PR_SUPPORTED:
((struct sctp_assoc_value *)arg)->assoc_id = id;
break;
+ case SCTP_RECONFIG_SUPPORTED:
+ ((struct sctp_assoc_value *)arg)->assoc_id = id;
+ break;
case SCTP_NRSACK_SUPPORTED:
((struct sctp_assoc_value *)arg)->assoc_id = id;
break;
diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h
index da13cab..324609c 100644
--- a/sys/netinet/sctp.h
+++ b/sys/netinet/sctp.h
@@ -125,6 +125,7 @@ struct sctp_paramhdr {
#define SCTP_PR_SUPPORTED 0x00000026
#define SCTP_NRSACK_SUPPORTED 0x00000027
#define SCTP_PKTDROP_SUPPORTED 0x00000028
+#define SCTP_RECONFIG_SUPPORTED 0x00000029
/*
* read-only options
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index b7f533a..ba624ba 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -2787,6 +2787,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
inp->ecn_supported = (*inp_p)->ecn_supported;
inp->prsctp_supported = (*inp_p)->prsctp_supported;
+ inp->reconfig_supported = (*inp_p)->reconfig_supported;
inp->nrsack_supported = (*inp_p)->nrsack_supported;
inp->pktdrop_supported = (*inp_p)->pktdrop_supported;
inp->partial_delivery_point = (*inp_p)->partial_delivery_point;
@@ -5389,13 +5390,13 @@ process_control_chunks:
*offset = length;
return (NULL);
}
- if (stcb->asoc.peer_supports_strreset == 0) {
+ if (stcb->asoc.reconfig_supported == 0) {
/*
* hmm, peer should have announced this, but
* we will turn it on since he is sending us
* a stream reset.
*/
- stcb->asoc.peer_supports_strreset = 1;
+ stcb->asoc.reconfig_supported = 1;
}
if (sctp_handle_stream_reset(stcb, m, *offset, ch)) {
/* stop processing */
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 6edabc1..5165f5f 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -4820,7 +4820,9 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
if (stcb->asoc.pktdrop_supported == 1) {
pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
}
- pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
+ if (stcb->asoc.reconfig_supported == 1) {
+ pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
+ }
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
}
@@ -5926,7 +5928,10 @@ do_a_abort:
((asoc == NULL) && (inp->pktdrop_supported == 1))) {
pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
}
- pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
+ if (((asoc != NULL) && (asoc->reconfig_supported == 1)) ||
+ ((asoc == NULL) && (inp->reconfig_supported == 1))) {
+ pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
+ }
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
}
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 11f0793..67ee1fa 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2485,6 +2485,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off);
inp->ecn_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_ecn_enable);
inp->prsctp_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pr_enable);
+ inp->reconfig_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_reconfig_enable);
inp->nrsack_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_nrsack_enable);
inp->pktdrop_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pktdrop_enable);
/* init the small hash table we use to track asocid <-> tcb */
@@ -6086,6 +6087,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
int got_random = 0, got_hmacs = 0, got_chklist = 0;
uint8_t ecn_supported;
uint8_t prsctp_supported;
+ uint8_t reconfig_supported;
uint8_t nrsack_supported;
uint8_t pktdrop_supported;
@@ -6116,9 +6118,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
} else {
sa = src;
}
- /* Turn off ECN until we get through all params */
ecn_supported = 0;
prsctp_supported = 0;
+ reconfig_supported = 0;
nrsack_supported = 0;
pktdrop_supported = 0;
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@@ -6458,7 +6460,6 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
return (-25);
}
stcb->asoc.peer_supports_asconf = 0;
- stcb->asoc.peer_supports_strreset = 0;
stcb->asoc.peer_supports_auth = 0;
pr_supported = (struct sctp_supported_chunk_types_param *)phdr;
num_ent = plen - sizeof(struct sctp_paramhdr);
@@ -6478,7 +6479,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
nrsack_supported = 1;
break;
case SCTP_STREAM_RESET:
- stcb->asoc.peer_supports_strreset = 1;
+ reconfig_supported = 1;
break;
case SCTP_AUTHENTICATION:
stcb->asoc.peer_supports_auth = 1;
@@ -6620,6 +6621,7 @@ next_param:
}
stcb->asoc.ecn_supported &= ecn_supported;
stcb->asoc.prsctp_supported &= prsctp_supported;
+ stcb->asoc.reconfig_supported &= reconfig_supported;
stcb->asoc.nrsack_supported &= nrsack_supported;
stcb->asoc.pktdrop_supported &= pktdrop_supported;
/* validate authentication required parameters */
diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h
index 30e35f8..694148a 100644
--- a/sys/netinet/sctp_pcb.h
+++ b/sys/netinet/sctp_pcb.h
@@ -408,6 +408,7 @@ struct sctp_inpcb {
uint32_t sctp_cmt_on_off;
uint8_t ecn_supported;
uint8_t prsctp_supported;
+ uint8_t reconfig_supported;
uint8_t nrsack_supported;
uint8_t pktdrop_supported;
struct sctp_nonpad_sndrcvinfo def_send;
diff --git a/sys/netinet/sctp_peeloff.c b/sys/netinet/sctp_peeloff.c
index 2aa691d..ed4ef49 100644
--- a/sys/netinet/sctp_peeloff.c
+++ b/sys/netinet/sctp_peeloff.c
@@ -120,6 +120,7 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
n_inp->ecn_supported = inp->ecn_supported;
n_inp->prsctp_supported = inp->prsctp_supported;
+ n_inp->reconfig_supported = inp->reconfig_supported;
n_inp->nrsack_supported = inp->nrsack_supported;
n_inp->pktdrop_supported = inp->pktdrop_supported;
n_inp->partial_delivery_point = inp->partial_delivery_point;
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index 29a9d89..5c63f85 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -1153,6 +1153,7 @@ struct sctp_association {
/* Flags whether an extension is supported or not */
uint8_t ecn_supported;
uint8_t prsctp_supported;
+ uint8_t reconfig_supported;
uint8_t nrsack_supported;
uint8_t pktdrop_supported;
@@ -1163,8 +1164,6 @@ struct sctp_association {
uint8_t peer_supports_asconf;
/* peer authentication support flag */
uint8_t peer_supports_auth;
- /* stream resets are supported by the peer */
- uint8_t peer_supports_strreset;
uint8_t local_strreset_support;
uint8_t peer_supports_nat;
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index c27a3a8..8dfda56 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -55,6 +55,7 @@ sctp_init_sysctls()
SCTP_BASE_SYSCTL(sctp_multiple_asconfs) = SCTPCTL_MULTIPLEASCONFS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_ecn_enable) = SCTPCTL_ECN_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pr_enable) = SCTPCTL_PR_ENABLE_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_reconfig_enable) = SCTPCTL_RECONFIG_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nrsack_enable) = SCTPCTL_NRSACK_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pktdrop_enable) = SCTPCTL_PKTDROP_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_strict_sacks) = SCTPCTL_STRICT_SACKS_DEFAULT;
@@ -602,6 +603,7 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
RANGECHK(SCTP_BASE_SYSCTL(sctp_auto_asconf), SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_enable), SCTPCTL_ECN_ENABLE_MIN, SCTPCTL_ECN_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_pr_enable), SCTPCTL_PR_ENABLE_MIN, SCTPCTL_PR_ENABLE_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_reconfig_enable), SCTPCTL_RECONFIG_ENABLE_MIN, SCTPCTL_RECONFIG_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_nrsack_enable), SCTPCTL_NRSACK_ENABLE_MIN, SCTPCTL_NRSACK_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_pktdrop_enable), SCTPCTL_PKTDROP_ENABLE_MIN, SCTPCTL_PKTDROP_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_sacks), SCTPCTL_STRICT_SACKS_MIN, SCTPCTL_STRICT_SACKS_MAX);
@@ -867,6 +869,10 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, pr_enable, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_pr_enable), 0, sysctl_sctp_check, "IU",
SCTPCTL_PR_ENABLE_DESC);
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, reconfig_enable, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_reconfig_enable), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_RECONFIG_ENABLE_DESC);
+
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nrsack_enable, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_nrsack_enable), 0, sysctl_sctp_check, "IU",
SCTPCTL_NRSACK_ENABLE_DESC);
diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h
index 741d031..bcf270f 100644
--- a/sys/netinet/sctp_sysctl.h
+++ b/sys/netinet/sctp_sysctl.h
@@ -46,6 +46,7 @@ struct sctp_sysctl {
uint32_t sctp_multiple_asconfs;
uint32_t sctp_ecn_enable;
uint32_t sctp_pr_enable;
+ uint32_t sctp_reconfig_enable;
uint32_t sctp_nrsack_enable;
uint32_t sctp_pktdrop_enable;
uint32_t sctp_fr_max_burst_default;
@@ -161,8 +162,14 @@ struct sctp_sysctl {
#define SCTPCTL_PR_ENABLE_MAX 1
#define SCTPCTL_PR_ENABLE_DEFAULT 1
+/* reconfig_enable: Enable SCTP RE-CONFIG */
+#define SCTPCTL_RECONFIG_ENABLE_DESC "Enable SCTP RE-CONFIG"
+#define SCTPCTL_RECONFIG_ENABLE_MIN 0
+#define SCTPCTL_RECONFIG_ENABLE_MAX 1
+#define SCTPCTL_RECONFIG_ENABLE_DEFAULT 1
+
/* nrsack_enable: Enable NR_SACK */
-#define SCTPCTL_NRSACK_ENABLE_DESC "Enable NR_SACK"
+#define SCTPCTL_NRSACK_ENABLE_DESC "Enable SCTP NR-SACK"
#define SCTPCTL_NRSACK_ENABLE_MIN 0
#define SCTPCTL_NRSACK_ENABLE_MAX 1
#define SCTPCTL_NRSACK_ENABLE_DEFAULT 0
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 7f2e6ee..01f5376 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -3348,6 +3348,33 @@ flags_out:
}
break;
}
+ case SCTP_RECONFIG_SUPPORTED:
+ {
+ struct sctp_assoc_value *av;
+
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+ if (stcb) {
+ av->assoc_value = stcb->asoc.reconfig_supported;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ av->assoc_value = inp->reconfig_supported;
+ 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_assoc_value);
+ }
+ break;
+ }
case SCTP_NRSACK_SUPPORTED:
{
struct sctp_assoc_value *av;
@@ -4274,7 +4301,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = ENOENT;
break;
}
- if (stcb->asoc.peer_supports_strreset == 0) {
+ if (stcb->asoc.reconfig_supported == 0) {
/*
* Peer does not support the chunk type.
*/
@@ -4341,7 +4368,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = ENOENT;
break;
}
- if (stcb->asoc.peer_supports_strreset == 0) {
+ if (stcb->asoc.reconfig_supported == 0) {
/*
* Peer does not support the chunk type.
*/
@@ -4410,7 +4437,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = ENOENT;
break;
}
- if (stcb->asoc.peer_supports_strreset == 0) {
+ if (stcb->asoc.reconfig_supported == 0) {
/*
* Peer does not support the chunk type.
*/
@@ -6023,6 +6050,35 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
break;
}
+ case SCTP_RECONFIG_SUPPORTED:
+ {
+ struct sctp_assoc_value *av;
+
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+ if (stcb) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ if (av->assoc_value == 0) {
+ inp->reconfig_supported = 0;
+ } else {
+ inp->reconfig_supported = 1;
+ }
+ SCTP_INP_WUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ break;
+ }
case SCTP_NRSACK_SUPPORTED:
{
struct sctp_assoc_value *av;
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 1c83177..8c2ec48 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -906,6 +906,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
asoc->ecn_supported = inp->ecn_supported;
asoc->prsctp_supported = inp->prsctp_supported;
+ asoc->reconfig_supported = inp->reconfig_supported;
asoc->nrsack_supported = inp->nrsack_supported;
asoc->pktdrop_supported = inp->pktdrop_supported;
asoc->sctp_cmt_pf = (uint8_t) 0;
@@ -2631,7 +2632,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
}
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
- if (stcb->asoc.peer_supports_strreset) {
+ if (stcb->asoc.reconfig_supported) {
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG;
}
sac->sac_length += i;
OpenPOWER on IntegriCloud