Add support for the SCTP_AUTH_SUPPORTED and SCTP_ASCONF_SUPPORTED
socket options. Add also a sysctl to control the support of ASCONF. MFC after: 1 week
This commit is contained in:
parent
36b16d1f7d
commit
c79bec9c75
@ -356,6 +356,12 @@ 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_AUTH_SUPPORTED:
|
||||
((struct sctp_assoc_value *)arg)->assoc_id = id;
|
||||
break;
|
||||
case SCTP_ASCONF_SUPPORTED:
|
||||
((struct sctp_assoc_value *)arg)->assoc_id = id;
|
||||
break;
|
||||
case SCTP_RECONFIG_SUPPORTED:
|
||||
((struct sctp_assoc_value *)arg)->assoc_id = id;
|
||||
break;
|
||||
@ -590,6 +596,7 @@ sctp_sendmsg(int s,
|
||||
cmsg->cmsg_type = SCTP_SNDRCV;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
|
||||
sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
|
||||
memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
||||
sinfo->sinfo_stream = stream_no;
|
||||
sinfo->sinfo_ssn = 0;
|
||||
sinfo->sinfo_flags = flags;
|
||||
|
@ -123,9 +123,11 @@ struct sctp_paramhdr {
|
||||
#define SCTP_REMOTE_UDP_ENCAPS_PORT 0x00000024
|
||||
#define SCTP_ECN_SUPPORTED 0x00000025
|
||||
#define SCTP_PR_SUPPORTED 0x00000026
|
||||
#define SCTP_NRSACK_SUPPORTED 0x00000027
|
||||
#define SCTP_PKTDROP_SUPPORTED 0x00000028
|
||||
#define SCTP_AUTH_SUPPORTED 0x00000027
|
||||
#define SCTP_ASCONF_SUPPORTED 0x00000028
|
||||
#define SCTP_RECONFIG_SUPPORTED 0x00000029
|
||||
#define SCTP_NRSACK_SUPPORTED 0x00000030
|
||||
#define SCTP_PKTDROP_SUPPORTED 0x00000031
|
||||
|
||||
/*
|
||||
* read-only options
|
||||
|
@ -724,13 +724,11 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
|
||||
}
|
||||
switch (param_type) {
|
||||
case SCTP_ADD_IP_ADDRESS:
|
||||
asoc->peer_supports_asconf = 1;
|
||||
m_result = sctp_process_asconf_add_ip(src, aph, stcb,
|
||||
(cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error);
|
||||
cnt++;
|
||||
break;
|
||||
case SCTP_DEL_IP_ADDRESS:
|
||||
asoc->peer_supports_asconf = 1;
|
||||
m_result = sctp_process_asconf_delete_ip(src, aph, stcb,
|
||||
error);
|
||||
break;
|
||||
@ -738,7 +736,6 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
|
||||
/* not valid in an ASCONF chunk */
|
||||
break;
|
||||
case SCTP_SET_PRIM_ADDR:
|
||||
asoc->peer_supports_asconf = 1;
|
||||
m_result = sctp_process_asconf_set_primary(src, aph,
|
||||
stcb, error);
|
||||
break;
|
||||
@ -930,8 +927,6 @@ sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
|
||||
void
|
||||
sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
|
||||
{
|
||||
/* mark peer as ASCONF incapable */
|
||||
stcb->asoc.peer_supports_asconf = 0;
|
||||
/*
|
||||
* clear out any existing asconfs going out
|
||||
*/
|
||||
@ -1340,7 +1335,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
|
||||
int pending_delete_queued = 0;
|
||||
|
||||
/* see if peer supports ASCONF */
|
||||
if (stcb->asoc.peer_supports_asconf == 0) {
|
||||
if (stcb->asoc.asconf_supported == 0) {
|
||||
return (-1);
|
||||
}
|
||||
/*
|
||||
@ -1430,7 +1425,7 @@ sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
|
||||
return (-1);
|
||||
}
|
||||
/* see if peer supports ASCONF */
|
||||
if (stcb->asoc.peer_supports_asconf == 0) {
|
||||
if (stcb->asoc.asconf_supported == 0) {
|
||||
return (-1);
|
||||
}
|
||||
/* make sure the request isn't already in the queue */
|
||||
@ -1550,7 +1545,7 @@ sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
|
||||
* notifications based on the error response
|
||||
*/
|
||||
static void
|
||||
sctp_asconf_process_error(struct sctp_tcb *stcb,
|
||||
sctp_asconf_process_error(struct sctp_tcb *stcb SCTP_UNUSED,
|
||||
struct sctp_asconf_paramhdr *aph)
|
||||
{
|
||||
struct sctp_error_cause *eh;
|
||||
@ -1588,10 +1583,7 @@ sctp_asconf_process_error(struct sctp_tcb *stcb,
|
||||
switch (param_type) {
|
||||
case SCTP_ADD_IP_ADDRESS:
|
||||
case SCTP_DEL_IP_ADDRESS:
|
||||
stcb->asoc.peer_supports_asconf = 0;
|
||||
break;
|
||||
case SCTP_SET_PRIM_ADDR:
|
||||
stcb->asoc.peer_supports_asconf = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1627,8 +1619,6 @@ sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
|
||||
SCTPDBG(SCTP_DEBUG_ASCONF1,
|
||||
"process_param_ack: set primary IP address\n");
|
||||
/* nothing to do... peer may start using this addr */
|
||||
if (flag == 0)
|
||||
stcb->asoc.peer_supports_asconf = 0;
|
||||
break;
|
||||
default:
|
||||
/* should NEVER happen */
|
||||
@ -1646,11 +1636,11 @@ sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
|
||||
* cleanup from a bad asconf ack parameter
|
||||
*/
|
||||
static void
|
||||
sctp_asconf_ack_clear(struct sctp_tcb *stcb)
|
||||
sctp_asconf_ack_clear(struct sctp_tcb *stcb SCTP_UNUSED)
|
||||
{
|
||||
/* assume peer doesn't really know how to do asconfs */
|
||||
stcb->asoc.peer_supports_asconf = 0;
|
||||
/* XXX we could free the pending queue here */
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@ -1988,7 +1978,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
/* queue an asconf for this address add/delete */
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
|
||||
/* does the peer do asconf? */
|
||||
if (stcb->asoc.peer_supports_asconf) {
|
||||
if (stcb->asoc.asconf_supported) {
|
||||
/* queue an asconf for this addr */
|
||||
status = sctp_asconf_queue_add(stcb, ifa, type);
|
||||
|
||||
@ -2238,7 +2228,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
}
|
||||
/* queue an asconf for this address add/delete */
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
|
||||
stcb->asoc.peer_supports_asconf) {
|
||||
stcb->asoc.asconf_supported == 1) {
|
||||
/* queue an asconf for this addr */
|
||||
status = sctp_asconf_queue_add(stcb, ifa, type);
|
||||
/*
|
||||
@ -2886,7 +2876,7 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
/* are ASCONFs allowed ? */
|
||||
if ((sctp_is_feature_on(stcb->sctp_ep,
|
||||
SCTP_PCB_FLAGS_DO_ASCONF)) &&
|
||||
stcb->asoc.peer_supports_asconf) {
|
||||
stcb->asoc.asconf_supported) {
|
||||
/* queue an ASCONF DEL_IP_ADDRESS */
|
||||
status = sctp_asconf_queue_sa_delete(stcb, sa);
|
||||
/*
|
||||
|
@ -133,11 +133,6 @@ sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t * list)
|
||||
if (list == NULL)
|
||||
return (-1);
|
||||
|
||||
/* is chunk restricted? */
|
||||
if ((chunk == SCTP_ASCONF) ||
|
||||
(chunk == SCTP_ASCONF_ACK)) {
|
||||
return (-1);
|
||||
}
|
||||
if (list->chunks[chunk] == 1) {
|
||||
list->chunks[chunk] = 0;
|
||||
list->num_chunks--;
|
||||
@ -157,16 +152,6 @@ sctp_auth_get_chklist_size(const sctp_auth_chklist_t * list)
|
||||
return (list->num_chunks);
|
||||
}
|
||||
|
||||
/*
|
||||
* set the default list of chunks requiring AUTH
|
||||
*/
|
||||
void
|
||||
sctp_auth_set_default_chunks(sctp_auth_chklist_t * list)
|
||||
{
|
||||
(void)sctp_auth_add_chunk(SCTP_ASCONF, list);
|
||||
(void)sctp_auth_add_chunk(SCTP_ASCONF_ACK, list);
|
||||
}
|
||||
|
||||
/*
|
||||
* return the current number and list of required chunks caller must
|
||||
* guarantee ptr has space for up to 256 bytes
|
||||
|
@ -112,7 +112,6 @@ extern sctp_auth_chklist_t *sctp_copy_chunklist(sctp_auth_chklist_t * chklist);
|
||||
extern int sctp_auth_add_chunk(uint8_t chunk, sctp_auth_chklist_t * list);
|
||||
extern int sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t * list);
|
||||
extern size_t sctp_auth_get_chklist_size(const sctp_auth_chklist_t * list);
|
||||
extern void sctp_auth_set_default_chunks(sctp_auth_chklist_t * list);
|
||||
extern int
|
||||
sctp_serialize_auth_chunks(const sctp_auth_chklist_t * list,
|
||||
uint8_t * ptr);
|
||||
|
@ -480,7 +480,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
|
||||
return (-1);
|
||||
}
|
||||
/* if the peer doesn't support asconf, flush the asconf queue */
|
||||
if (asoc->peer_supports_asconf == 0) {
|
||||
if (asoc->asconf_supported == 0) {
|
||||
struct sctp_asconf_addr *param, *nparam;
|
||||
|
||||
TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) {
|
||||
@ -756,7 +756,7 @@ sctp_handle_nat_missing_state(struct sctp_tcb *stcb,
|
||||
* return 0 means we want you to proceed with the abort non-zero
|
||||
* means no abort processing
|
||||
*/
|
||||
if (stcb->asoc.peer_supports_auth == 0) {
|
||||
if (stcb->asoc.auth_supported == 0) {
|
||||
SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n");
|
||||
return (0);
|
||||
}
|
||||
@ -1096,6 +1096,7 @@ sctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr,
|
||||
* Skip past the param header and then we will find the param that caused the
|
||||
* problem. There are a number of param's in a ASCONF OR the prsctp param
|
||||
* these will turn of specific features.
|
||||
* XXX: Is this the right thing to do?
|
||||
*/
|
||||
static void
|
||||
sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr)
|
||||
@ -1117,14 +1118,14 @@ sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr)
|
||||
case SCTP_ADD_IP_ADDRESS:
|
||||
case SCTP_DEL_IP_ADDRESS:
|
||||
case SCTP_SET_PRIM_ADDR:
|
||||
stcb->asoc.peer_supports_asconf = 0;
|
||||
stcb->asoc.asconf_supported = 0;
|
||||
break;
|
||||
case SCTP_SUCCESS_REPORT:
|
||||
case SCTP_ERROR_CAUSE_IND:
|
||||
SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n");
|
||||
SCTPDBG(SCTP_DEBUG_INPUT2,
|
||||
"Turning off ASCONF to this strange peer\n");
|
||||
stcb->asoc.peer_supports_asconf = 0;
|
||||
stcb->asoc.asconf_supported = 0;
|
||||
break;
|
||||
default:
|
||||
SCTPDBG(SCTP_DEBUG_INPUT2,
|
||||
@ -2787,6 +2788,8 @@ 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->auth_supported = (*inp_p)->auth_supported;
|
||||
inp->asconf_supported = (*inp_p)->asconf_supported;
|
||||
inp->reconfig_supported = (*inp_p)->reconfig_supported;
|
||||
inp->nrsack_supported = (*inp_p)->nrsack_supported;
|
||||
inp->pktdrop_supported = (*inp_p)->pktdrop_supported;
|
||||
@ -2966,7 +2969,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
|
||||
* in flight)
|
||||
*/
|
||||
if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) &&
|
||||
(stcb->asoc.peer_supports_asconf) &&
|
||||
(stcb->asoc.asconf_supported == 1) &&
|
||||
(!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) {
|
||||
#ifdef SCTP_TIMER_BASED_ASCONF
|
||||
sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
|
||||
@ -4439,7 +4442,7 @@ __attribute__((noinline))
|
||||
*/
|
||||
if ((ch->chunk_type == SCTP_AUTHENTICATION) &&
|
||||
(stcb == NULL) &&
|
||||
!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
|
||||
(inp->auth_supported == 1)) {
|
||||
/* save this chunk for later processing */
|
||||
auth_skipped = 1;
|
||||
auth_offset = *offset;
|
||||
@ -4706,7 +4709,7 @@ __attribute__((noinline))
|
||||
|
||||
/* check to see if this chunk required auth, but isn't */
|
||||
if ((stcb != NULL) &&
|
||||
!SCTP_BASE_SYSCTL(sctp_auth_disable) &&
|
||||
(stcb->asoc.auth_supported == 1) &&
|
||||
sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) &&
|
||||
!stcb->asoc.authenticated) {
|
||||
/* "silently" ignore */
|
||||
@ -5225,6 +5228,9 @@ __attribute__((noinline))
|
||||
return (NULL);
|
||||
}
|
||||
if (stcb) {
|
||||
if (stcb->asoc.ecn_supported == 0) {
|
||||
goto unknown_chunk;
|
||||
}
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
|
||||
sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
|
||||
stcb->asoc.overall_error_count,
|
||||
@ -5250,6 +5256,9 @@ __attribute__((noinline))
|
||||
return (NULL);
|
||||
}
|
||||
if (stcb) {
|
||||
if (stcb->asoc.ecn_supported == 0) {
|
||||
goto unknown_chunk;
|
||||
}
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
|
||||
sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
|
||||
stcb->asoc.overall_error_count,
|
||||
@ -5283,6 +5292,9 @@ __attribute__((noinline))
|
||||
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n");
|
||||
/* He's alive so give him credit */
|
||||
if (stcb) {
|
||||
if (stcb->asoc.asconf_supported == 0) {
|
||||
goto unknown_chunk;
|
||||
}
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
|
||||
sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
|
||||
stcb->asoc.overall_error_count,
|
||||
@ -5307,6 +5319,9 @@ __attribute__((noinline))
|
||||
return (NULL);
|
||||
}
|
||||
if ((stcb) && netp && *netp) {
|
||||
if (stcb->asoc.asconf_supported == 0) {
|
||||
goto unknown_chunk;
|
||||
}
|
||||
/* He's alive so give him credit */
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
|
||||
sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
|
||||
@ -5336,6 +5351,9 @@ __attribute__((noinline))
|
||||
if (stcb) {
|
||||
int abort_flag = 0;
|
||||
|
||||
if (stcb->asoc.prsctp_supported == 0) {
|
||||
goto unknown_chunk;
|
||||
}
|
||||
stcb->asoc.overall_error_count = 0;
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
|
||||
sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
|
||||
@ -5391,12 +5409,7 @@ __attribute__((noinline))
|
||||
return (NULL);
|
||||
}
|
||||
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.reconfig_supported = 1;
|
||||
goto unknown_chunk;
|
||||
}
|
||||
if (sctp_handle_stream_reset(stcb, m, *offset, ch)) {
|
||||
/* stop processing */
|
||||
@ -5416,18 +5429,17 @@ __attribute__((noinline))
|
||||
return (NULL);
|
||||
}
|
||||
if (ch && (stcb) && netp && (*netp)) {
|
||||
if (stcb->asoc.pktdrop_supported == 0) {
|
||||
goto unknown_chunk;
|
||||
}
|
||||
sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch,
|
||||
stcb, *netp,
|
||||
min(chk_length, (sizeof(chunk_buf) - 4)));
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case SCTP_AUTHENTICATION:
|
||||
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n");
|
||||
if (SCTP_BASE_SYSCTL(sctp_auth_disable))
|
||||
goto unknown_chunk;
|
||||
|
||||
if (stcb == NULL) {
|
||||
/* save the first AUTH for later processing */
|
||||
if (auth_skipped == 0) {
|
||||
@ -5438,6 +5450,9 @@ __attribute__((noinline))
|
||||
/* skip this chunk (temporarily) */
|
||||
goto next_chunk;
|
||||
}
|
||||
if (stcb->asoc.auth_supported == 0) {
|
||||
goto unknown_chunk;
|
||||
}
|
||||
if ((chk_length < (sizeof(struct sctp_auth_chunk))) ||
|
||||
(chk_length > (sizeof(struct sctp_auth_chunk) +
|
||||
SCTP_AUTH_DIGEST_LEN_MAX))) {
|
||||
@ -5778,7 +5793,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
|
||||
* chunks
|
||||
*/
|
||||
if ((stcb != NULL) &&
|
||||
!SCTP_BASE_SYSCTL(sctp_auth_disable) &&
|
||||
(stcb->asoc.auth_supported == 1) &&
|
||||
sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) {
|
||||
/* "silently" ignore */
|
||||
SCTP_STAT_INCR(sctps_recvauthmissing);
|
||||
@ -5820,7 +5835,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
|
||||
*/
|
||||
if ((length > offset) &&
|
||||
(stcb != NULL) &&
|
||||
!SCTP_BASE_SYSCTL(sctp_auth_disable) &&
|
||||
(stcb->asoc.auth_supported == 1) &&
|
||||
sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) &&
|
||||
!stcb->asoc.authenticated) {
|
||||
/* "silently" ignore */
|
||||
|
@ -4753,12 +4753,6 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
}
|
||||
chunk_len = (uint16_t) sizeof(struct sctp_init_chunk);
|
||||
padding_len = 0;
|
||||
/*
|
||||
* assume peer supports asconf in order to be able to queue local
|
||||
* address changes while an INIT is in flight and before the assoc
|
||||
* is established.
|
||||
*/
|
||||
stcb->asoc.peer_supports_asconf = 1;
|
||||
/* Now lets put the chunk header in place */
|
||||
init = mtod(m, struct sctp_init_chunk *);
|
||||
/* now the chunk header */
|
||||
@ -4811,31 +4805,34 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
/* And now tell the peer which extensions we support */
|
||||
num_ext = 0;
|
||||
pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
|
||||
pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
|
||||
if (stcb->asoc.prsctp_supported == 1) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
|
||||
}
|
||||
if (stcb->asoc.pktdrop_supported == 1) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
|
||||
if (stcb->asoc.auth_supported == 1) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
|
||||
}
|
||||
if (stcb->asoc.asconf_supported == 1) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (stcb->asoc.nrsack_supported == 1) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
|
||||
}
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_supported_chunk_types_param) + num_ext;
|
||||
pr_supported->ph.param_length = htons(parameter_len);
|
||||
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
|
||||
chunk_len += parameter_len;
|
||||
|
||||
if (stcb->asoc.pktdrop_supported == 1) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
|
||||
}
|
||||
if (num_ext > 0) {
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_supported_chunk_types_param) + num_ext;
|
||||
pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
|
||||
pr_supported->ph.param_length = htons(parameter_len);
|
||||
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* add authentication parameters */
|
||||
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
|
||||
if (stcb->asoc.auth_supported) {
|
||||
/* attach RANDOM parameter, if available */
|
||||
if (stcb->asoc.authinfo.random != NULL) {
|
||||
struct sctp_auth_random *randp;
|
||||
@ -4853,8 +4850,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* add HMAC_ALGO parameter */
|
||||
if ((stcb->asoc.local_hmacs != NULL) &&
|
||||
(stcb->asoc.local_hmacs->num_algo > 0)) {
|
||||
if (stcb->asoc.local_hmacs != NULL) {
|
||||
struct sctp_auth_hmac_algo *hmacs;
|
||||
|
||||
if (padding_len > 0) {
|
||||
@ -4872,7 +4868,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* add CHUNKS parameter */
|
||||
if (sctp_auth_get_chklist_size(stcb->asoc.local_auth_chunks) > 0) {
|
||||
if (stcb->asoc.local_auth_chunks != NULL) {
|
||||
struct sctp_auth_chunk_list *chunks;
|
||||
|
||||
if (padding_len > 0) {
|
||||
@ -5917,35 +5913,41 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
/* And now tell the peer which extensions we support */
|
||||
num_ext = 0;
|
||||
pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
|
||||
pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
|
||||
if (((asoc != NULL) && (asoc->prsctp_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->prsctp_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
|
||||
}
|
||||
if (((asoc != NULL) && (asoc->pktdrop_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->pktdrop_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
|
||||
if (((asoc != NULL) && (asoc->auth_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->auth_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
|
||||
}
|
||||
if (((asoc != NULL) && (asoc->asconf_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->asconf_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (((asoc != NULL) && (asoc->nrsack_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->nrsack_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
|
||||
}
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_supported_chunk_types_param) + num_ext;
|
||||
pr_supported->ph.param_length = htons(parameter_len);
|
||||
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
|
||||
chunk_len += parameter_len;
|
||||
|
||||
if (((asoc != NULL) && (asoc->pktdrop_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->pktdrop_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
|
||||
}
|
||||
if (num_ext > 0) {
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_supported_chunk_types_param) + num_ext;
|
||||
pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
|
||||
pr_supported->ph.param_length = htons(parameter_len);
|
||||
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* add authentication parameters */
|
||||
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
|
||||
if (((asoc != NULL) && (asoc->auth_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->auth_supported == 1))) {
|
||||
struct sctp_auth_random *randp;
|
||||
struct sctp_auth_hmac_algo *hmacs;
|
||||
struct sctp_auth_chunk_list *chunks;
|
||||
@ -7806,7 +7808,6 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
|
||||
|
||||
*num_out = 0;
|
||||
auth_keyid = stcb->asoc.authinfo.active_keyid;
|
||||
|
||||
if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
|
||||
(asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED) ||
|
||||
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) {
|
||||
@ -13417,12 +13418,7 @@ sctp_add_auth_chunk(struct mbuf *m, struct mbuf **m_end,
|
||||
(stcb == NULL))
|
||||
return (m);
|
||||
|
||||
/* sysctl disabled auth? */
|
||||
if (SCTP_BASE_SYSCTL(sctp_auth_disable))
|
||||
return (m);
|
||||
|
||||
/* peer doesn't do auth... */
|
||||
if (!stcb->asoc.peer_supports_auth) {
|
||||
if (stcb->asoc.auth_supported == 0) {
|
||||
return (m);
|
||||
}
|
||||
/* does the requested chunk require auth? */
|
||||
|
@ -2485,6 +2485,12 @@ 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);
|
||||
if (SCTP_BASE_SYSCTL(sctp_auth_disable)) {
|
||||
inp->auth_supported = 0;
|
||||
} else {
|
||||
inp->auth_supported = 1;
|
||||
}
|
||||
inp->asconf_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_asconf_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);
|
||||
@ -2651,12 +2657,15 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
*/
|
||||
m->local_hmacs = sctp_default_supported_hmaclist();
|
||||
m->local_auth_chunks = sctp_alloc_chunklist();
|
||||
if (inp->asconf_supported) {
|
||||
sctp_auth_add_chunk(SCTP_ASCONF, m->local_auth_chunks);
|
||||
sctp_auth_add_chunk(SCTP_ASCONF_ACK, m->local_auth_chunks);
|
||||
}
|
||||
m->default_dscp = 0;
|
||||
#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 */
|
||||
null_key = sctp_alloc_sharedkey();
|
||||
@ -6085,11 +6094,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
sctp_key_t *new_key;
|
||||
uint32_t keylen;
|
||||
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;
|
||||
uint8_t peer_supports_ecn;
|
||||
uint8_t peer_supports_prsctp;
|
||||
uint8_t peer_supports_auth;
|
||||
uint8_t peer_supports_asconf;
|
||||
uint8_t peer_supports_asconf_ack;
|
||||
uint8_t peer_supports_reconfig;
|
||||
uint8_t peer_supports_nrsack;
|
||||
uint8_t peer_supports_pktdrop;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in sin;
|
||||
@ -6118,11 +6130,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
} else {
|
||||
sa = src;
|
||||
}
|
||||
ecn_supported = 0;
|
||||
prsctp_supported = 0;
|
||||
reconfig_supported = 0;
|
||||
nrsack_supported = 0;
|
||||
pktdrop_supported = 0;
|
||||
peer_supports_ecn = 0;
|
||||
peer_supports_prsctp = 0;
|
||||
peer_supports_auth = 0;
|
||||
peer_supports_asconf = 0;
|
||||
peer_supports_asconf = 0;
|
||||
peer_supports_reconfig = 0;
|
||||
peer_supports_nrsack = 0;
|
||||
peer_supports_pktdrop = 0;
|
||||
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
|
||||
/* mark all addresses that we have currently on the list */
|
||||
net->dest_state |= SCTP_ADDR_NOT_IN_ASSOC;
|
||||
@ -6172,12 +6187,6 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
/* the assoc was freed? */
|
||||
return (-4);
|
||||
}
|
||||
/*
|
||||
* peer must explicitly turn this on. This may have been initialized
|
||||
* to be "on" in order to allow local addr changes while INIT's are
|
||||
* in flight.
|
||||
*/
|
||||
stcb->asoc.peer_supports_asconf = 0;
|
||||
/* now we must go through each of the params. */
|
||||
phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
|
||||
while (phdr) {
|
||||
@ -6371,7 +6380,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
} else
|
||||
#endif
|
||||
if (ptype == SCTP_ECN_CAPABLE) {
|
||||
ecn_supported = 1;
|
||||
peer_supports_ecn = 1;
|
||||
} else if (ptype == SCTP_ULP_ADAPTATION) {
|
||||
if (stcb->asoc.state != SCTP_STATE_OPEN) {
|
||||
struct sctp_adaptation_layer_indication ai,
|
||||
@ -6395,7 +6404,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
|
||||
#endif
|
||||
|
||||
stcb->asoc.peer_supports_asconf = 1;
|
||||
if (stcb->asoc.asconf_supported == 0) {
|
||||
return (-100);
|
||||
}
|
||||
if (plen > sizeof(lstore)) {
|
||||
return (-23);
|
||||
}
|
||||
@ -6447,7 +6458,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
stcb->asoc.peer_supports_nat = 1;
|
||||
} else if (ptype == SCTP_PRSCTP_SUPPORTED) {
|
||||
/* Peer supports pr-sctp */
|
||||
prsctp_supported = 1;
|
||||
peer_supports_prsctp = 1;
|
||||
} else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
|
||||
/* A supported extension chunk */
|
||||
struct sctp_supported_chunk_types_param *pr_supported;
|
||||
@ -6459,30 +6470,29 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
if (phdr == NULL) {
|
||||
return (-25);
|
||||
}
|
||||
stcb->asoc.peer_supports_asconf = 0;
|
||||
stcb->asoc.peer_supports_auth = 0;
|
||||
pr_supported = (struct sctp_supported_chunk_types_param *)phdr;
|
||||
num_ent = plen - sizeof(struct sctp_paramhdr);
|
||||
for (i = 0; i < num_ent; i++) {
|
||||
switch (pr_supported->chunk_types[i]) {
|
||||
case SCTP_ASCONF:
|
||||
peer_supports_asconf = 1;
|
||||
case SCTP_ASCONF_ACK:
|
||||
stcb->asoc.peer_supports_asconf = 1;
|
||||
peer_supports_asconf_ack = 1;
|
||||
break;
|
||||
case SCTP_FORWARD_CUM_TSN:
|
||||
prsctp_supported = 1;
|
||||
peer_supports_prsctp = 1;
|
||||
break;
|
||||
case SCTP_PACKET_DROPPED:
|
||||
pktdrop_supported = 1;
|
||||
peer_supports_pktdrop = 1;
|
||||
break;
|
||||
case SCTP_NR_SELECTIVE_ACK:
|
||||
nrsack_supported = 1;
|
||||
peer_supports_nrsack = 1;
|
||||
break;
|
||||
case SCTP_STREAM_RESET:
|
||||
reconfig_supported = 1;
|
||||
peer_supports_reconfig = 1;
|
||||
break;
|
||||
case SCTP_AUTHENTICATION:
|
||||
stcb->asoc.peer_supports_auth = 1;
|
||||
peer_supports_auth = 1;
|
||||
break;
|
||||
default:
|
||||
/* one I have not learned yet */
|
||||
@ -6619,25 +6629,47 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
}
|
||||
}
|
||||
}
|
||||
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 */
|
||||
if (got_random && got_hmacs) {
|
||||
stcb->asoc.peer_supports_auth = 1;
|
||||
} else {
|
||||
stcb->asoc.peer_supports_auth = 0;
|
||||
if ((stcb->asoc.ecn_supported == 1) &&
|
||||
(peer_supports_ecn == 0)) {
|
||||
stcb->asoc.ecn_supported = 0;
|
||||
}
|
||||
if (!stcb->asoc.peer_supports_auth && got_chklist) {
|
||||
if ((stcb->asoc.prsctp_supported == 1) &&
|
||||
(peer_supports_prsctp == 0)) {
|
||||
stcb->asoc.prsctp_supported = 0;
|
||||
}
|
||||
if ((stcb->asoc.auth_supported == 1) &&
|
||||
((peer_supports_auth == 0) ||
|
||||
(got_random == 0) || (got_hmacs == 0))) {
|
||||
stcb->asoc.auth_supported = 0;
|
||||
}
|
||||
if ((stcb->asoc.asconf_supported == 1) &&
|
||||
((peer_supports_asconf == 0) || (peer_supports_asconf_ack == 0) ||
|
||||
(stcb->asoc.auth_supported == 0) ||
|
||||
(saw_asconf == 0) || (saw_asconf_ack == 0))) {
|
||||
stcb->asoc.asconf_supported = 0;
|
||||
}
|
||||
if ((stcb->asoc.reconfig_supported == 1) &&
|
||||
(peer_supports_reconfig == 0)) {
|
||||
stcb->asoc.reconfig_supported = 0;
|
||||
}
|
||||
if ((stcb->asoc.nrsack_supported == 1) &&
|
||||
(peer_supports_nrsack == 0)) {
|
||||
stcb->asoc.nrsack_supported = 0;
|
||||
}
|
||||
if ((stcb->asoc.pktdrop_supported == 1) &&
|
||||
(peer_supports_pktdrop == 0)) {
|
||||
stcb->asoc.pktdrop_supported = 0;
|
||||
}
|
||||
/* validate authentication required parameters */
|
||||
if ((peer_supports_auth == 0) && (got_chklist == 1)) {
|
||||
/* peer does not support auth but sent a chunks list? */
|
||||
return (-31);
|
||||
}
|
||||
if (stcb->asoc.peer_supports_asconf && !stcb->asoc.peer_supports_auth) {
|
||||
if ((peer_supports_asconf == 1) && (peer_supports_auth == 0)) {
|
||||
/* peer supports asconf but not auth? */
|
||||
return (-32);
|
||||
} else if ((stcb->asoc.peer_supports_asconf) && (stcb->asoc.peer_supports_auth) &&
|
||||
} else if ((peer_supports_asconf == 1) &&
|
||||
(peer_supports_auth == 1) &&
|
||||
((saw_asconf == 0) || (saw_asconf_ack == 0))) {
|
||||
return (-33);
|
||||
}
|
||||
|
@ -408,6 +408,8 @@ struct sctp_inpcb {
|
||||
uint32_t sctp_cmt_on_off;
|
||||
uint8_t ecn_supported;
|
||||
uint8_t prsctp_supported;
|
||||
uint8_t auth_supported;
|
||||
uint8_t asconf_supported;
|
||||
uint8_t reconfig_supported;
|
||||
uint8_t nrsack_supported;
|
||||
uint8_t pktdrop_supported;
|
||||
|
@ -120,6 +120,8 @@ 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->auth_supported = inp->auth_supported;
|
||||
n_inp->asconf_supported = inp->asconf_supported;
|
||||
n_inp->reconfig_supported = inp->reconfig_supported;
|
||||
n_inp->nrsack_supported = inp->nrsack_supported;
|
||||
n_inp->pktdrop_supported = inp->pktdrop_supported;
|
||||
|
@ -1153,6 +1153,8 @@ struct sctp_association {
|
||||
/* Flags whether an extension is supported or not */
|
||||
uint8_t ecn_supported;
|
||||
uint8_t prsctp_supported;
|
||||
uint8_t auth_supported;
|
||||
uint8_t asconf_supported;
|
||||
uint8_t reconfig_supported;
|
||||
uint8_t nrsack_supported;
|
||||
uint8_t pktdrop_supported;
|
||||
@ -1160,10 +1162,6 @@ struct sctp_association {
|
||||
/* Did the peer make the stream config (add out) request */
|
||||
uint8_t peer_req_out;
|
||||
|
||||
/* flag to indicate if peer can do asconf */
|
||||
uint8_t peer_supports_asconf;
|
||||
/* peer authentication support flag */
|
||||
uint8_t peer_supports_auth;
|
||||
uint8_t local_strreset_support;
|
||||
|
||||
uint8_t peer_supports_nat;
|
||||
|
@ -55,6 +55,8 @@ 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_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_asconf_enable) = SCTPCTL_ASCONF_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;
|
||||
@ -90,7 +92,6 @@ sctp_init_sysctls()
|
||||
SCTP_BASE_SYSCTL(sctp_cmt_on_off) = SCTPCTL_CMT_ON_OFF_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_cmt_use_dac) = SCTPCTL_CMT_USE_DAC_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) = SCTPCTL_CWND_MAXBURST_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_nat_friendly) = SCTPCTL_NAT_FRIENDLY_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_L2_abc_variable) = SCTPCTL_ABC_L_VAR_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count) = SCTPCTL_MAX_CHAINED_MBUFS_DEFAULT;
|
||||
@ -638,7 +639,6 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_on_off), SCTPCTL_CMT_ON_OFF_MIN, SCTPCTL_CMT_ON_OFF_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_use_dac), SCTPCTL_CMT_USE_DAC_MIN, SCTPCTL_CMT_USE_DAC_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), SCTPCTL_CWND_MAXBURST_MIN, SCTPCTL_CWND_MAXBURST_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_auth_disable), SCTPCTL_AUTH_DISABLE_MIN, SCTPCTL_AUTH_DISABLE_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_nat_friendly), SCTPCTL_NAT_FRIENDLY_MIN, SCTPCTL_NAT_FRIENDLY_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_L2_abc_variable), SCTPCTL_ABC_L_VAR_MIN, SCTPCTL_ABC_L_VAR_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), SCTPCTL_MAX_CHAINED_MBUFS_MIN, SCTPCTL_MAX_CHAINED_MBUFS_MAX);
|
||||
@ -677,6 +677,56 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_sctp_auth_check(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
|
||||
if (error == 0) {
|
||||
if (SCTP_BASE_SYSCTL(sctp_auth_disable) < SCTPCTL_AUTH_DISABLE_MIN) {
|
||||
SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_MIN;
|
||||
}
|
||||
if (SCTP_BASE_SYSCTL(sctp_auth_disable) > SCTPCTL_AUTH_DISABLE_MAX) {
|
||||
SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_MAX;
|
||||
}
|
||||
if ((SCTP_BASE_SYSCTL(sctp_auth_disable) == 1) &&
|
||||
(SCTP_BASE_SYSCTL(sctp_asconf_enable) == 1)) {
|
||||
/*
|
||||
* You can't disable AUTH with disabling ASCONF
|
||||
* first
|
||||
*/
|
||||
SCTP_BASE_SYSCTL(sctp_auth_disable) = 0;
|
||||
}
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_sctp_asconf_check(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
|
||||
if (error == 0) {
|
||||
if (SCTP_BASE_SYSCTL(sctp_asconf_enable) < SCTPCTL_ASCONF_ENABLE_MIN) {
|
||||
SCTP_BASE_SYSCTL(sctp_asconf_enable) = SCTPCTL_ASCONF_ENABLE_MIN;
|
||||
}
|
||||
if (SCTP_BASE_SYSCTL(sctp_asconf_enable) > SCTPCTL_ASCONF_ENABLE_MAX) {
|
||||
SCTP_BASE_SYSCTL(sctp_asconf_enable) = SCTPCTL_ASCONF_ENABLE_MAX;
|
||||
}
|
||||
if ((SCTP_BASE_SYSCTL(sctp_asconf_enable) == 1) &&
|
||||
(SCTP_BASE_SYSCTL(sctp_auth_disable) == 1)) {
|
||||
/*
|
||||
* You can't enable ASCONF without enabling AUTH
|
||||
* first
|
||||
*/
|
||||
SCTP_BASE_SYSCTL(sctp_asconf_enable) = 0;
|
||||
}
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
|
||||
static int
|
||||
sysctl_stat_get(SYSCTL_HANDLER_ARGS)
|
||||
@ -869,6 +919,14 @@ 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, auth_disable, CTLTYPE_UINT | CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_auth_disable), 0, sysctl_sctp_auth_check, "IU",
|
||||
SCTPCTL_AUTH_DISABLE_DESC);
|
||||
|
||||
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, asconf_enable, CTLTYPE_UINT | CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_asconf_enable), 0, sysctl_sctp_asconf_check, "IU",
|
||||
SCTPCTL_ASCONF_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);
|
||||
@ -1010,10 +1068,6 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLTYPE_UINT | CTLFLAG
|
||||
&SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), 0, sysctl_sctp_check, "IU",
|
||||
SCTPCTL_CWND_MAXBURST_DESC);
|
||||
|
||||
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_UINT | CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_auth_disable), 0, sysctl_sctp_check, "IU",
|
||||
SCTPCTL_AUTH_DISABLE_DESC);
|
||||
|
||||
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nat_friendly, CTLTYPE_UINT | CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_nat_friendly), 0, sysctl_sctp_check, "IU",
|
||||
SCTPCTL_NAT_FRIENDLY_DESC);
|
||||
|
@ -46,6 +46,8 @@ struct sctp_sysctl {
|
||||
uint32_t sctp_multiple_asconfs;
|
||||
uint32_t sctp_ecn_enable;
|
||||
uint32_t sctp_pr_enable;
|
||||
uint32_t sctp_auth_disable;
|
||||
uint32_t sctp_asconf_enable;
|
||||
uint32_t sctp_reconfig_enable;
|
||||
uint32_t sctp_nrsack_enable;
|
||||
uint32_t sctp_pktdrop_enable;
|
||||
@ -81,7 +83,6 @@ struct sctp_sysctl {
|
||||
uint32_t sctp_cmt_on_off;
|
||||
uint32_t sctp_cmt_use_dac;
|
||||
uint32_t sctp_use_cwnd_based_maxburst;
|
||||
uint32_t sctp_auth_disable;
|
||||
uint32_t sctp_nat_friendly;
|
||||
uint32_t sctp_L2_abc_variable;
|
||||
uint32_t sctp_mbuf_threshold_count;
|
||||
@ -162,6 +163,18 @@ struct sctp_sysctl {
|
||||
#define SCTPCTL_PR_ENABLE_MAX 1
|
||||
#define SCTPCTL_PR_ENABLE_DEFAULT 1
|
||||
|
||||
/* auth_disable: Disable SCTP AUTH function */
|
||||
#define SCTPCTL_AUTH_DISABLE_DESC "Disable SCTP AUTH function"
|
||||
#define SCTPCTL_AUTH_DISABLE_MIN 0
|
||||
#define SCTPCTL_AUTH_DISABLE_MAX 1
|
||||
#define SCTPCTL_AUTH_DISABLE_DEFAULT 0
|
||||
|
||||
/* asconf_enable: Enable SCTP ASCONF */
|
||||
#define SCTPCTL_ASCONF_ENABLE_DESC "Enable SCTP ASCONF"
|
||||
#define SCTPCTL_ASCONF_ENABLE_MIN 0
|
||||
#define SCTPCTL_ASCONF_ENABLE_MAX 1
|
||||
#define SCTPCTL_ASCONF_ENABLE_DEFAULT 1
|
||||
|
||||
/* reconfig_enable: Enable SCTP RE-CONFIG */
|
||||
#define SCTPCTL_RECONFIG_ENABLE_DESC "Enable SCTP RE-CONFIG"
|
||||
#define SCTPCTL_RECONFIG_ENABLE_MIN 0
|
||||
@ -379,12 +392,6 @@ struct sctp_sysctl {
|
||||
#define SCTPCTL_CWND_MAXBURST_MAX 1
|
||||
#define SCTPCTL_CWND_MAXBURST_DEFAULT 1
|
||||
|
||||
/* auth_disable: Disable SCTP AUTH function */
|
||||
#define SCTPCTL_AUTH_DISABLE_DESC "Disable SCTP AUTH function"
|
||||
#define SCTPCTL_AUTH_DISABLE_MIN 0
|
||||
#define SCTPCTL_AUTH_DISABLE_MAX 1
|
||||
#define SCTPCTL_AUTH_DISABLE_DEFAULT 0
|
||||
|
||||
/* nat_friendly: SCTP NAT friendly operation */
|
||||
#define SCTPCTL_NAT_FRIENDLY_DESC "SCTP NAT friendly operation"
|
||||
#define SCTPCTL_NAT_FRIENDLY_MIN 0
|
||||
|
@ -3348,6 +3348,60 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_AUTH_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.auth_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->auth_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_ASCONF_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.asconf_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->asconf_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_RECONFIG_SUPPORTED:
|
||||
{
|
||||
struct sctp_assoc_value *av;
|
||||
@ -6050,6 +6104,92 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_AUTH_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)) {
|
||||
if ((av->assoc_value == 0) &&
|
||||
(inp->asconf_supported == 1)) {
|
||||
/*
|
||||
* AUTH is required for
|
||||
* ASCONF
|
||||
*/
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
} else {
|
||||
SCTP_INP_WLOCK(inp);
|
||||
if (av->assoc_value == 0) {
|
||||
inp->auth_supported = 0;
|
||||
} else {
|
||||
inp->auth_supported = 1;
|
||||
}
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
}
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_ASCONF_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)) {
|
||||
if ((av->assoc_value != 0) &&
|
||||
(inp->auth_supported == 0)) {
|
||||
/*
|
||||
* AUTH is required for
|
||||
* ASCONF
|
||||
*/
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
} else {
|
||||
SCTP_INP_WLOCK(inp);
|
||||
if (av->assoc_value == 0) {
|
||||
inp->asconf_supported = 0;
|
||||
sctp_auth_delete_chunk(SCTP_ASCONF,
|
||||
inp->sctp_ep.local_auth_chunks);
|
||||
sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
|
||||
inp->sctp_ep.local_auth_chunks);
|
||||
} else {
|
||||
inp->asconf_supported = 1;
|
||||
sctp_auth_add_chunk(SCTP_ASCONF,
|
||||
inp->sctp_ep.local_auth_chunks);
|
||||
sctp_auth_add_chunk(SCTP_ASCONF_ACK,
|
||||
inp->sctp_ep.local_auth_chunks);
|
||||
}
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
}
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_RECONFIG_SUPPORTED:
|
||||
{
|
||||
struct sctp_assoc_value *av;
|
||||
|
@ -906,6 +906,8 @@ 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->auth_supported = inp->auth_supported;
|
||||
asoc->asconf_supported = inp->asconf_supported;
|
||||
asoc->reconfig_supported = inp->reconfig_supported;
|
||||
asoc->nrsack_supported = inp->nrsack_supported;
|
||||
asoc->pktdrop_supported = inp->pktdrop_supported;
|
||||
@ -2622,17 +2624,17 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
|
||||
if (notif_len > sizeof(struct sctp_assoc_change)) {
|
||||
if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
|
||||
i = 0;
|
||||
if (stcb->asoc.prsctp_supported) {
|
||||
if (stcb->asoc.prsctp_supported == 1) {
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR;
|
||||
}
|
||||
if (stcb->asoc.peer_supports_auth) {
|
||||
if (stcb->asoc.auth_supported == 1) {
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH;
|
||||
}
|
||||
if (stcb->asoc.peer_supports_asconf) {
|
||||
if (stcb->asoc.asconf_supported == 1) {
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
|
||||
}
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
|
||||
if (stcb->asoc.reconfig_supported) {
|
||||
if (stcb->asoc.reconfig_supported == 1) {
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG;
|
||||
}
|
||||
sac->sac_length += i;
|
||||
@ -3541,7 +3543,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) {
|
||||
sctp_notify_adaptation_layer(stcb);
|
||||
}
|
||||
if (stcb->asoc.peer_supports_auth == 0) {
|
||||
if (stcb->asoc.auth_supported == 0) {
|
||||
sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
|
||||
NULL, so_locked);
|
||||
}
|
||||
@ -3615,7 +3617,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
break;
|
||||
case SCTP_NOTIFY_ASSOC_RESTART:
|
||||
sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked);
|
||||
if (stcb->asoc.peer_supports_auth == 0) {
|
||||
if (stcb->asoc.auth_supported == 0) {
|
||||
sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
|
||||
NULL, so_locked);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user