summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/sctp_usrreq.c')
-rw-r--r--sys/netinet/sctp_usrreq.c139
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);
OpenPOWER on IntegriCloud