diff options
author | tuexen <tuexen@FreeBSD.org> | 2012-05-04 17:18:02 +0000 |
---|---|---|
committer | tuexen <tuexen@FreeBSD.org> | 2012-05-04 17:18:02 +0000 |
commit | 6dac06847559a77b0b65d71ae92a248c9d3c5cd6 (patch) | |
tree | c6cd12da67185fc69f8351e8095d2c4c017eb3c1 /sys/netinet/sctp_usrreq.c | |
parent | 48ad9597cd4704c9adbb1d6bb78719e57f8b0f0b (diff) | |
download | FreeBSD-src-6dac06847559a77b0b65d71ae92a248c9d3c5cd6.zip FreeBSD-src-6dac06847559a77b0b65d71ae92a248c9d3c5cd6.tar.gz |
Add support for the SCTP_ENABLE_STREAM_RESET socket option to
getsockopt(). This improves the support of RFC 6525.
MFC after: 3 days
Diffstat (limited to 'sys/netinet/sctp_usrreq.c')
-rw-r--r-- | sys/netinet/sctp_usrreq.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 6523641..3d415c7 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -3296,6 +3296,33 @@ flags_out: } break; } + case SCTP_ENABLE_STREAM_RESET: + { + 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 = (uint32_t) stcb->asoc.local_strreset_support; + 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 = (uint32_t) inp->local_strreset_support; + 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; + } default: SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT); error = ENOPROTOOPT; @@ -4096,7 +4123,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, case SCTP_ENABLE_STREAM_RESET: { struct sctp_assoc_value *av; - uint8_t set_value = 0; SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) { @@ -4104,10 +4130,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, error = EINVAL; break; } - set_value = av->assoc_value & SCTP_ENABLE_VALUE_MASK; SCTP_FIND_STCB(inp, stcb, av->assoc_id); if (stcb) { - stcb->asoc.local_strreset_support = set_value; + stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value; SCTP_TCB_UNLOCK(stcb); } else { if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || @@ -4115,7 +4140,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (av->assoc_id == SCTP_FUTURE_ASSOC) || (av->assoc_id == SCTP_ALL_ASSOC)) { SCTP_INP_WLOCK(inp); - inp->local_strreset_support = set_value; + inp->local_strreset_support = (uint8_t) av->assoc_value; SCTP_INP_WUNLOCK(inp); } if ((av->assoc_id == SCTP_CURRENT_ASSOC) || @@ -4123,7 +4148,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_INP_RLOCK(inp); LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { SCTP_TCB_LOCK(stcb); - stcb->asoc.local_strreset_support = set_value; + stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value; SCTP_TCB_UNLOCK(stcb); } SCTP_INP_RUNLOCK(inp); |