diff options
author | rrs <rrs@FreeBSD.org> | 2008-12-06 13:19:54 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2008-12-06 13:19:54 +0000 |
commit | 0f2b9dafa358fb3b64efed4842cd31650ceea672 (patch) | |
tree | 773b646ae7f5af08e1421071f2aa493698537042 /sys/netinet/sctp_usrreq.c | |
parent | f4594595d3de298d45caf389d9cee0d893cedfc0 (diff) | |
download | FreeBSD-src-0f2b9dafa358fb3b64efed4842cd31650ceea672.zip FreeBSD-src-0f2b9dafa358fb3b64efed4842cd31650ceea672.tar.gz |
Code from the hack-session known as the IETF (and a
bit of debugging afterwards):
- Fix protection code for notification generation.
- Decouple associd from vtag
- Allow vtags to have less strigent requirements in non-uniqueness.
o don't pre-hash them when you issue one in a cookie.
o Allow duplicates and use addresses and ports to
discriminate amongst the duplicates during lookup.
- Add support for the NAT draft draft-ietf-behave-sctpnat-00, this
is still experimental and needs more extensive testing with the
Jason Butt ipfw changes.
- Support for the SENDER_DRY event to get DTLS in OpenSSL working
with a set of patches from Michael Tuexen (hopefully heading to OpenSSL soon).
- Update the support of SCTP-AUTH by Peter Lei.
- Use macros for refcounting.
- Fix MTU for UDP encapsulation.
- Fix reporting back of unsent data.
- Update assoc send counter handling to be consistent with endpoint sent counter.
- Fix a bug in PR-SCTP.
- Fix so we only send another FWD-TSN when a SACK arrives IF and only
if the adv-peer-ack point progressed. However we still make sure
a timer is running if we do have an adv_peer_ack point.
- Fix PR-SCTP bug where chunks were retransmitted if they are sent
unreliable but not abandoned yet.
With the help of: Michael Teuxen and Peter Lei :-)
MFC after: 4 weeks
Diffstat (limited to 'sys/netinet/sctp_usrreq.c')
-rw-r--r-- | sys/netinet/sctp_usrreq.c | 139 |
1 files changed, 123 insertions, 16 deletions
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 058415e..c642762 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_auth.h> #include <netinet/sctp_bsd_addr.h> #include <netinet/sctp_cc_functions.h> +#include <netinet/udp.h> @@ -201,6 +202,9 @@ sctp_notify_mbuf(struct sctp_inpcb *inp, /* Adjust destination size limit */ if (net->mtu > nxtsz) { net->mtu = nxtsz; + if (net->port) { + net->mtu -= sizeof(struct udphdr); + } } /* now what about the ep? */ if (stcb->asoc.smallest_mtu > nxtsz) { @@ -507,8 +511,10 @@ sctp_attach(struct socket *so, int proto, struct thread *p) struct inpcb *ip_inp; int error; uint32_t vrf_id = SCTP_DEFAULT_VRFID; + #ifdef IPSEC uint32_t flags; + #endif inp = (struct sctp_inpcb *)so->so_pcb; @@ -1704,6 +1710,29 @@ flags_out: *optsize = sizeof(*av); } break; + /* EY - set socket option for nr_sacks */ + case SCTP_NR_SACK_ON_OFF: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); + if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) { + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + if (stcb) { + av->assoc_value = stcb->asoc.sctp_nr_sack_on_off; + SCTP_TCB_UNLOCK(stcb); + + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN); + error = ENOTCONN; + } + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT); + error = ENOPROTOOPT; + } + *optsize = sizeof(*av); + } + break; /* JRS - Get socket option for pluggable congestion control */ case SCTP_PLUGGABLE_CC: { @@ -1767,7 +1796,7 @@ flags_out: SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize); at = 0; - limit = *optsize / sizeof(sctp_assoc_t); + limit = (*optsize - sizeof(uint32_t)) / sizeof(sctp_assoc_t); SCTP_INP_RLOCK(inp); LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { if (at < limit) { @@ -1779,7 +1808,8 @@ flags_out: } } SCTP_INP_RUNLOCK(inp); - *optsize = at * sizeof(sctp_assoc_t); + ids->gaids_number_of_ids = at; + *optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t)); } break; case SCTP_CONTEXT: @@ -1961,6 +1991,9 @@ flags_out: if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT)) events->sctp_authentication_event = 1; + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT)) + events->sctp_sender_dry_event = 1; + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT)) events->sctp_stream_reset_events = 1; SCTP_INP_RUNLOCK(inp); @@ -2532,7 +2565,7 @@ flags_out: if (stcb) { /* get the active key on the assoc */ - scact->scact_keynumber = stcb->asoc.authinfo.assoc_keyid; + scact->scact_keynumber = stcb->asoc.authinfo.active_keyid; SCTP_TCB_UNLOCK(stcb); } else { /* get the endpoint active key */ @@ -2789,6 +2822,27 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } } break; + /* EY nr_sack_on_off socket option */ + case SCTP_NR_SACK_ON_OFF: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); + if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) { + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + if (stcb) { + stcb->asoc.sctp_nr_sack_on_off = (uint8_t) av->assoc_value; + SCTP_TCB_UNLOCK(stcb); + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN); + error = ENOTCONN; + } + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT); + error = ENOPROTOOPT; + } + } + break; /* JRS - Set socket option for pluggable congestion control */ case SCTP_PLUGGABLE_CC: { @@ -3012,7 +3066,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } shared_key->key = key; shared_key->keyid = sca->sca_keynumber; - sctp_insert_sharedkey(shared_keys, shared_key); + error = sctp_insert_sharedkey(shared_keys, shared_key); SCTP_TCB_UNLOCK(stcb); } else { /* set it on the endpoint */ @@ -3046,7 +3100,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } shared_key->key = key; shared_key->keyid = sca->sca_keynumber; - sctp_insert_sharedkey(shared_keys, shared_key); + error = sctp_insert_sharedkey(shared_keys, shared_key); SCTP_INP_WUNLOCK(inp); } break; @@ -3108,22 +3162,29 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, { struct sctp_authkeyid *scact; - SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize); + SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, + optsize); SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id); /* set the active key on the right place */ if (stcb) { /* set the active key on the assoc */ - if (sctp_auth_setactivekey(stcb, scact->scact_keynumber)) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + if (sctp_auth_setactivekey(stcb, + scact->scact_keynumber)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, + SCTP_FROM_SCTP_USRREQ, + EINVAL); error = EINVAL; } SCTP_TCB_UNLOCK(stcb); } else { /* set the active key on the endpoint */ SCTP_INP_WLOCK(inp); - if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + if (sctp_auth_setactivekey_ep(inp, + scact->scact_keynumber)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, + SCTP_FROM_SCTP_USRREQ, + EINVAL); error = EINVAL; } SCTP_INP_WUNLOCK(inp); @@ -3134,20 +3195,58 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, { struct sctp_authkeyid *scdel; - SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize); + SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, + optsize); SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id); /* delete the key from the right place */ if (stcb) { - if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + if (sctp_delete_sharedkey(stcb, + scdel->scact_keynumber)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, + SCTP_FROM_SCTP_USRREQ, + EINVAL); error = EINVAL; } SCTP_TCB_UNLOCK(stcb); } else { SCTP_INP_WLOCK(inp); - if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + if (sctp_delete_sharedkey_ep(inp, + scdel->scact_keynumber)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, + SCTP_FROM_SCTP_USRREQ, + EINVAL); + error = EINVAL; + } + SCTP_INP_WUNLOCK(inp); + } + break; + } + case SCTP_AUTH_DEACTIVATE_KEY: + { + struct sctp_authkeyid *keyid; + + SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, + optsize); + SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id); + + /* deactivate the key from the right place */ + if (stcb) { + if (sctp_deact_sharedkey(stcb, + keyid->scact_keynumber)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, + SCTP_FROM_SCTP_USRREQ, + EINVAL); + error = EINVAL; + } + SCTP_TCB_UNLOCK(stcb); + } else { + SCTP_INP_WLOCK(inp); + if (sctp_deact_sharedkey_ep(inp, + keyid->scact_keynumber)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, + SCTP_FROM_SCTP_USRREQ, + EINVAL); error = EINVAL; } SCTP_INP_WUNLOCK(inp); @@ -3414,6 +3513,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT); } + if (events->sctp_sender_dry_event) { + sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT); + } else { + sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT); + } + if (events->sctp_stream_reset_events) { sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT); } else { @@ -4123,6 +4228,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p) #ifdef INET6 if (addr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6p; + if (addr->sa_len != sizeof(struct sockaddr_in6)) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); return (EINVAL); @@ -4136,6 +4242,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p) #endif if (addr->sa_family == AF_INET) { struct sockaddr_in *sinp; + if (addr->sa_len != sizeof(struct sockaddr_in)) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); return (EINVAL); |