summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/sctp_asconf.c8
-rw-r--r--sys/netinet/sctp_auth.c99
-rw-r--r--sys/netinet/sctp_auth.h41
-rw-r--r--sys/netinet/sctp_constants.h32
-rw-r--r--sys/netinet/sctp_crc32.c9
-rw-r--r--sys/netinet/sctp_indata.c158
-rw-r--r--sys/netinet/sctp_input.c60
-rw-r--r--sys/netinet/sctp_os.h5
-rw-r--r--sys/netinet/sctp_os_bsd.h35
-rw-r--r--sys/netinet/sctp_output.c56
-rw-r--r--sys/netinet/sctp_pcb.c77
-rw-r--r--sys/netinet/sctp_peeloff.c2
-rw-r--r--sys/netinet/sctp_structs.h32
-rw-r--r--sys/netinet/sctp_timer.c13
-rw-r--r--sys/netinet/sctp_uio.h52
-rw-r--r--sys/netinet/sctp_usrreq.c1800
-rw-r--r--sys/netinet/sctp_var.h160
-rw-r--r--sys/netinet/sctputil.c40
-rw-r--r--sys/netinet/sctputil.h30
19 files changed, 1175 insertions, 1534 deletions
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index 500d2eb..8abab9d 100644
--- a/sys/netinet/sctp_asconf.c
+++ b/sys/netinet/sctp_asconf.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2001-2007, 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:
@@ -653,7 +653,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
int error = 0; /* did an error occur? */
/* asconf param buffer */
- static uint8_t aparam_buf[DEFAULT_PARAM_BUFFER];
+ uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
/* verify minimum length */
if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) {
@@ -1401,7 +1401,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
struct sctp_asconf_addr *ap;
/* asconf param buffer */
- static uint8_t aparam_buf[DEFAULT_PARAM_BUFFER];
+ uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
/* verify minimum length */
if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) {
@@ -2774,7 +2774,7 @@ sctp_addr_change(struct ifaddr *ifa, int cmd)
{
struct sctp_laddr *wi;
- wi = (struct sctp_laddr *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr);
+ wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
if (wi == NULL) {
/*
* Gak, what can we do? We have lost an address change can
diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c
index 6c7572f..86df162 100644
--- a/sys/netinet/sctp_auth.c
+++ b/sys/netinet/sctp_auth.c
@@ -155,7 +155,7 @@ sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t * list)
return (0);
}
-inline int
+inline size_t
sctp_auth_get_chklist_size(const sctp_auth_chklist_t * list)
{
if (list == NULL)
@@ -543,7 +543,7 @@ sctp_insert_sharedkey(struct sctp_keyhead *shared_keys,
return;
/* insert into an empty list? */
- if (LIST_EMPTY(shared_keys)) {
+ if (SCTP_LIST_EMPTY(shared_keys)) {
LIST_INSERT_HEAD(shared_keys, new_skey, next);
return;
}
@@ -903,7 +903,7 @@ sctp_hmac_init(uint16_t hmac_algo, sctp_hash_context_t * ctx)
static void
sctp_hmac_update(uint16_t hmac_algo, sctp_hash_context_t * ctx,
- const uint8_t * text, uint32_t textlen)
+ uint8_t * text, uint32_t textlen)
{
switch (hmac_algo) {
case SCTP_AUTH_HMAC_ID_SHA1:
@@ -980,7 +980,7 @@ sctp_hmac_final(uint16_t hmac_algo, sctp_hash_context_t * ctx,
*/
uint32_t
sctp_hmac(uint16_t hmac_algo, uint8_t * key, uint32_t keylen,
- const uint8_t * text, uint32_t textlen, uint8_t * digest)
+ uint8_t * text, uint32_t textlen, uint8_t * digest)
{
uint32_t digestlen;
uint32_t blocklen;
@@ -1117,7 +1117,7 @@ sctp_hmac_m(uint16_t hmac_algo, uint8_t * key, uint32_t keylen,
*/
int
sctp_verify_hmac(uint16_t hmac_algo, uint8_t * key, uint32_t keylen,
- const uint8_t * text, uint32_t textlen,
+ uint8_t * text, uint32_t textlen,
uint8_t * digest, uint32_t digestlen)
{
uint32_t len;
@@ -1149,7 +1149,7 @@ sctp_verify_hmac(uint16_t hmac_algo, uint8_t * key, uint32_t keylen,
* the keylen exceeds the HMAC block len).
*/
uint32_t
-sctp_compute_hmac(uint16_t hmac_algo, sctp_key_t * key, const uint8_t * text,
+sctp_compute_hmac(uint16_t hmac_algo, sctp_key_t * key, uint8_t * text,
uint32_t textlen, uint8_t * digest)
{
uint32_t digestlen;
@@ -1413,11 +1413,13 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
{
struct sctp_paramhdr *phdr, tmp_param;
uint16_t plen, ptype;
- uint8_t store[384];
+ uint8_t random_store[SCTP_PARAM_BUFFER_SIZE];
struct sctp_auth_random *random = NULL;
uint16_t random_len = 0;
+ uint8_t hmacs_store[SCTP_PARAM_BUFFER_SIZE];
struct sctp_auth_hmac_algo *hmacs = NULL;
uint16_t hmacs_len = 0;
+ uint8_t chunks_store[SCTP_PARAM_BUFFER_SIZE];
struct sctp_auth_chunk_list *chunks = NULL;
uint16_t num_chunks = 0;
sctp_key_t *new_key;
@@ -1436,10 +1438,10 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
break;
if (ptype == SCTP_RANDOM) {
- if (plen > sizeof(store))
+ if (plen > sizeof(random_store))
break;
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)store, plen);
+ (struct sctp_paramhdr *)random_store, plen);
if (phdr == NULL)
return;
/* save the random and length for the key */
@@ -1449,10 +1451,10 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
int num_hmacs;
int i;
- if (plen > sizeof(store))
+ if (plen > sizeof(hmacs_store))
break;
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)store, plen);
+ (struct sctp_paramhdr *)hmacs_store, plen);
if (phdr == NULL)
return;
/* save the hmacs list and num for the key */
@@ -1471,10 +1473,10 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
} else if (ptype == SCTP_CHUNK_LIST) {
int i;
- if (plen > sizeof(store))
+ if (plen > sizeof(chunks_store))
break;
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)store, plen);
+ (struct sctp_paramhdr *)chunks_store, plen);
if (phdr == NULL)
return;
chunks = (struct sctp_auth_chunk_list *)phdr;
@@ -1497,21 +1499,37 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
(uint8_t *) & tmp_param);
}
/* concatenate the full random key */
- keylen = random_len + num_chunks + hmacs_len;
+#ifdef SCTP_AUTH_DRAFT_04
+ keylen = random_len;
new_key = sctp_alloc_key(keylen);
if (new_key != NULL) {
/* copy in the RANDOM */
if (random != NULL)
bcopy(random->random_data, new_key->key, random_len);
+ }
+#else
+ keylen = sizeof(*random) + random_len + sizeof(*chunks) + num_chunks +
+ sizeof(*hmacs) + hmacs_len;
+ new_key = sctp_alloc_key(keylen);
+ if (new_key != NULL) {
+ /* copy in the RANDOM */
+ if (random != NULL) {
+ keylen = sizeof(*random) + random_len;
+ bcopy(random, new_key->key, keylen);
+ }
/* append in the AUTH chunks */
- if (chunks != NULL)
- bcopy(chunks->chunk_types, new_key->key + random_len,
- num_chunks);
+ if (chunks != NULL) {
+ bcopy(chunks, new_key->key + keylen,
+ sizeof(*chunks) + num_chunks);
+ keylen += sizeof(*chunks) + num_chunks;
+ }
/* append in the HMACs */
- if (hmacs != NULL)
- bcopy(hmacs->hmac_ids, new_key->key + random_len + num_chunks,
- hmacs_len);
+ if (hmacs != NULL) {
+ bcopy(hmacs, new_key->key + keylen,
+ sizeof(*hmacs) + hmacs_len);
+ }
}
+#endif
if (stcb->asoc.authinfo.random != NULL)
sctp_free_key(stcb->asoc.authinfo.random);
stcb->asoc.authinfo.random = new_key;
@@ -1829,7 +1847,7 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
/* A supported extension chunk */
struct sctp_supported_chunk_types_param *pr_supported;
- uint8_t local_store[128];
+ uint8_t local_store[SCTP_PARAM_BUFFER_SIZE];
int num_ent, i;
phdr = sctp_get_next_param(m, offset,
@@ -1865,7 +1883,7 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
return (-1);
}
} else if (ptype == SCTP_HMAC_LIST) {
- uint8_t store[256];
+ uint8_t store[SCTP_PARAM_BUFFER_SIZE];
struct sctp_auth_hmac_algo *hmacs;
int num_hmacs;
@@ -1942,13 +1960,34 @@ sctp_initialize_auth_params(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
stcb->asoc.authinfo.assoc_keyid = inp->sctp_ep.default_keyid;
/* now set the concatenated key (random + chunks + hmacs) */
- keylen = random_len + chunks_len + hmacs_len;
+#ifdef SCTP_AUTH_DRAFT_04
+ /* don't include the chunks and hmacs for draft -04 */
+ keylen = random_len;
+ new_key = sctp_generate_random_key(keylen);
+#else
+ /* key includes parameter headers */
+ keylen = (3 * sizeof(struct sctp_paramhdr)) + random_len + chunks_len +
+ hmacs_len;
new_key = sctp_alloc_key(keylen);
if (new_key != NULL) {
+ struct sctp_paramhdr *ph;
+ int plen;
+
/* generate and copy in the RANDOM */
- SCTP_READ_RANDOM(new_key->key, random_len);
- keylen = random_len;
+ ph = (struct sctp_paramhdr *)new_key->key;
+ ph->param_type = htons(SCTP_RANDOM);
+ plen = sizeof(*ph) + random_len;
+ ph->param_length = htons(plen);
+ SCTP_READ_RANDOM(new_key->key + sizeof(*ph), random_len);
+ keylen = plen;
+
/* append in the AUTH chunks */
+ /* NOTE: currently we always have chunks to list */
+ ph = (struct sctp_paramhdr *)(new_key->key + keylen);
+ ph->param_type = htons(SCTP_CHUNK_LIST);
+ plen = sizeof(*ph) + chunks_len;
+ ph->param_length = htons(plen);
+ keylen += sizeof(*ph);
if (stcb->asoc.local_auth_chunks) {
int i;
@@ -1958,17 +1997,19 @@ sctp_initialize_auth_params(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
}
}
/* append in the HMACs */
+ ph = (struct sctp_paramhdr *)(new_key->key + keylen);
+ ph->param_type = htons(SCTP_HMAC_LIST);
+ plen = sizeof(*ph) + hmacs_len;
+ ph->param_length = htons(plen);
+ keylen += sizeof(*ph);
sctp_serialize_hmaclist(stcb->asoc.local_hmacs,
new_key->key + keylen);
}
+#endif
if (stcb->asoc.authinfo.random != NULL)
sctp_free_key(stcb->asoc.authinfo.random);
stcb->asoc.authinfo.random = new_key;
stcb->asoc.authinfo.random_len = random_len;
-#ifdef SCTP_AUTH_DRAFT_04
- /* don't include the chunks and hmacs for draft -04 */
- stcb->asoc.authinfo.random->keylen = random_len;
-#endif
}
diff --git a/sys/netinet/sctp_auth.h b/sys/netinet/sctp_auth.h
index c6eb88a..5d0f4da 100644
--- a/sys/netinet/sctp_auth.h
+++ b/sys/netinet/sctp_auth.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2001-2007, 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:
@@ -30,33 +30,10 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#define HAVE_SHA2
#ifndef __SCTP_AUTH_H__
#define __SCTP_AUTH_H__
-#include <sys/queue.h>
-#include <sys/mbuf.h>
-
-#ifdef USE_SCTP_SHA1
-#include <netinet/sctp_sha1.h>
-#else
-#include <crypto/sha1.h>
-/* map standard crypto API names */
-#define SHA1_Init SHA1Init
-#define SHA1_Update SHA1Update
-#define SHA1_Final(x,y) SHA1Final((caddr_t)x, y)
-#endif
-
-#if defined(HAVE_SHA2)
-#include <crypto/sha2/sha2.h>
-#endif
-
-#include <sys/md5.h>
-/* map standard crypto API names */
-#define MD5_Init MD5Init
-#define MD5_Update MD5Update
-#define MD5_Final MD5Final
/* digest lengths */
#define SCTP_AUTH_DIGEST_LEN_SHA1 20
@@ -145,11 +122,10 @@ extern void sctp_clear_chunklist(sctp_auth_chklist_t * chklist);
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 int sctp_auth_get_chklist_size(const 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);
+ sctp_serialize_auth_chunks(const sctp_auth_chklist_t * list, uint8_t * ptr);
extern int sctp_pack_auth_chunks(const sctp_auth_chklist_t * list, uint8_t * ptr);
extern int
sctp_unpack_auth_chunks(const uint8_t * ptr, uint8_t num_chunks,
@@ -170,8 +146,7 @@ sctp_compute_hashkey(sctp_key_t * key1, sctp_key_t * key2,
extern sctp_sharedkey_t *sctp_alloc_sharedkey(void);
extern void sctp_free_sharedkey(sctp_sharedkey_t * skey);
extern sctp_sharedkey_t *
-sctp_find_sharedkey(struct sctp_keyhead *shared_keys,
- uint16_t key_id);
+ sctp_find_sharedkey(struct sctp_keyhead *shared_keys, uint16_t key_id);
extern void
sctp_insert_sharedkey(struct sctp_keyhead *shared_keys,
sctp_sharedkey_t * new_skey);
@@ -185,7 +160,7 @@ extern void sctp_free_hmaclist(sctp_hmaclist_t * list);
extern int sctp_auth_add_hmacid(sctp_hmaclist_t * list, uint16_t hmac_id);
extern sctp_hmaclist_t *sctp_copy_hmaclist(sctp_hmaclist_t * list);
extern sctp_hmaclist_t *sctp_default_supported_hmaclist(void);
-extern uint16_t
+extern uint16_t
sctp_negotiate_hmacid(sctp_hmaclist_t * peer,
sctp_hmaclist_t * local);
extern int sctp_serialize_hmaclist(sctp_hmaclist_t * list, uint8_t * ptr);
@@ -201,14 +176,14 @@ extern uint32_t sctp_get_auth_chunk_len(uint16_t hmac_algo);
extern uint32_t sctp_get_hmac_digest_len(uint16_t hmac_algo);
extern uint32_t
sctp_hmac(uint16_t hmac_algo, uint8_t * key, uint32_t keylen,
- const uint8_t * text, uint32_t textlen, uint8_t * digest);
+ uint8_t * text, uint32_t textlen, uint8_t * digest);
extern int
sctp_verify_hmac(uint16_t hmac_algo, uint8_t * key, uint32_t keylen,
- const uint8_t * text, uint32_t textlen, uint8_t * digest,
+ uint8_t * text, uint32_t textlen, uint8_t * digest,
uint32_t digestlen);
extern uint32_t
sctp_compute_hmac(uint16_t hmac_algo, sctp_key_t * key,
- const uint8_t * text, uint32_t textlen, uint8_t * digest);
+ uint8_t * text, uint32_t textlen, uint8_t * digest);
extern int sctp_auth_is_supported_hmac(sctp_hmaclist_t * list, uint16_t id);
/* mbuf versions */
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 9d23e4f..dcb05af 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -36,10 +36,6 @@ __FBSDID("$FreeBSD$");
#ifndef __sctp_constants_h__
#define __sctp_constants_h__
-#if defined(_KERNEL)
-#include <sys/kernel.h>
-#endif
-
#define SCTP_VERSION_STRING "KAME-BSD 1.1"
/* #define SCTP_AUDITING_ENABLED 1 used for debug/auditing */
@@ -556,7 +552,7 @@ __FBSDID("$FreeBSD$");
#define SCTP_ASOC_MAX_CHUNKS_ON_QUEUE 512
#define MSEC_TO_TICKS(x) ((hz == 1000) ? x : (((x) * hz) / 1000))
-#define TICKS_TO_MSEC(x) ((hz == 1000) ? x : (((x) * 1000) / hz));
+#define TICKS_TO_MSEC(x) ((hz == 1000) ? x : (((x) * 1000) / hz))
#define SEC_TO_TICKS(x) ((x) * hz)
#define TICKS_TO_SEC(x) ((x) / hz)
@@ -689,8 +685,8 @@ __FBSDID("$FreeBSD$");
#define SCTP_DEFAULT_MAXSEGMENT 65535
-#define DEFAULT_CHUNK_BUFFER 2048
-#define DEFAULT_PARAM_BUFFER 512
+#define SCTP_CHUNK_BUFFER_SIZE 2048
+#define SCTP_PARAM_BUFFER_SIZE 512
#define SCTP_DEFAULT_MINSEGMENT 512 /* MTU size ... if no mtu disc */
#define SCTP_HOW_MANY_SECRETS 2 /* how many secrets I keep */
@@ -908,20 +904,19 @@ __FBSDID("$FreeBSD$");
#define SCTP_DEF_SYSTEM_RESC_LIMIT 1000
-
#define IN4_ISPRIVATE_ADDRESS(a) \
- ((((u_char *)&(a)->s_addr)[0] == 10) || \
- ((((u_char *)&(a)->s_addr)[0] == 172) && \
- (((u_char *)&(a)->s_addr)[1] >= 16) && \
- (((u_char *)&(a)->s_addr)[1] <= 32)) || \
- ((((u_char *)&(a)->s_addr)[0] == 192) && \
- (((u_char *)&(a)->s_addr)[1] == 168)))
+ ((((uint8_t *)&(a)->s_addr)[0] == 10) || \
+ ((((uint8_t *)&(a)->s_addr)[0] == 172) && \
+ (((uint8_t *)&(a)->s_addr)[1] >= 16) && \
+ (((uint8_t *)&(a)->s_addr)[1] <= 32)) || \
+ ((((uint8_t *)&(a)->s_addr)[0] == 192) && \
+ (((uint8_t *)&(a)->s_addr)[1] == 168)))
#define IN4_ISLOOPBACK_ADDRESS(a) \
- ((((u_char *)&(a)->s_addr)[0] == 127) && \
- (((u_char *)&(a)->s_addr)[1] == 0) && \
- (((u_char *)&(a)->s_addr)[2] == 0) && \
- (((u_char *)&(a)->s_addr)[3] == 1))
+ ((((uint8_t *)&(a)->s_addr)[0] == 127) && \
+ (((uint8_t *)&(a)->s_addr)[1] == 0) && \
+ (((uint8_t *)&(a)->s_addr)[2] == 0) && \
+ (((uint8_t *)&(a)->s_addr)[3] == 1))
#if defined(_KERNEL)
@@ -966,7 +961,6 @@ do { \
} \
} while (0)
-/* FIXME */
#define sctp_sorwakeup_locked(inp, so) \
do { \
if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) { \
diff --git a/sys/netinet/sctp_crc32.c b/sys/netinet/sctp_crc32.c
index 3728ef3..47f5483 100644
--- a/sys/netinet/sctp_crc32.c
+++ b/sys/netinet/sctp_crc32.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2001-2007, 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:
@@ -34,8 +34,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_sctp.h"
-#include <sys/param.h>
+#include <netinet/sctp_os.h>
#include <netinet/sctp_crc32.h>
#ifndef SCTP_USE_ADLER32
@@ -663,8 +662,8 @@ uint32_t sctp_crc_c[256] = {
#define SCTP_CRC32C(c,d) (c=(c>>8)^sctp_crc_c[(c^(d))&0xFF])
-u_int32_t
-old_update_crc32(u_int32_t crc32,
+uint32_t
+old_update_crc32(uint32_t crc32,
unsigned char *buffer,
unsigned int length)
{
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 97dcfab..86945f7 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -321,13 +321,12 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
uint16_t stream_no;
int end = 0;
int cntDel;
-
- cntDel = stream_no = 0;
struct sctp_queued_to_read *control, *ctl, *ctlat;
- if (stcb && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
- (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET))
- ) {
+ cntDel = stream_no = 0;
+ if (stcb &&
+ ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
+ (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET))) {
/* socket above is long gone */
asoc->fragmented_delivery_inprogress = 0;
chk = TAILQ_FIRST(&asoc->reasmqueue);
@@ -1456,9 +1455,15 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
uint16_t strmno, strmseq;
struct mbuf *oper;
struct sctp_queued_to_read *control;
+ int ordered;
+ uint32_t protocol_id;
+ uint8_t chunk_flags;
chk = NULL;
tsn = ntohl(ch->dp.tsn);
+ chunk_flags = ch->ch.chunk_flags;
+ protocol_id = ch->dp.protocol_id;
+ ordered = ((ch->ch.chunk_flags & SCTP_DATA_UNORDERED) == 0);
#ifdef SCTP_MAP_LOGGING
sctp_log_map(0, tsn, asoc->cumulative_tsn, SCTP_MAP_PREPARE_SLIDE);
#endif
@@ -1613,8 +1618,18 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
* only validate the FIRST fragment so the bit must be set.
*/
strmseq = ntohs(ch->dp.stream_sequence);
- if ((ch->ch.chunk_flags & SCTP_DATA_FIRST_FRAG) &&
- (ch->ch.chunk_flags & SCTP_DATA_UNORDERED) == 0 &&
+
+#ifdef SCTP_ASOCLOG_OF_TSNS
+ asoc->in_tsnlog[asoc->tsn_in_at].tsn = tsn;
+ asoc->in_tsnlog[asoc->tsn_in_at].strm = strmno;
+ asoc->in_tsnlog[asoc->tsn_in_at].seq = strmseq;
+ asoc->tsn_in_at++;
+ if (asoc->tsn_in_at >= SCTP_TSN_LOG_SIZE) {
+ asoc->tsn_in_at = 0;
+ }
+#endif
+ if ((chunk_flags & SCTP_DATA_FIRST_FRAG) &&
+ (chunk_flags & SCTP_DATA_UNORDERED) == 0 &&
(compare_with_wrap(asoc->strmin[strmno].last_sequence_delivered,
strmseq, MAX_SEQ) ||
asoc->strmin[strmno].last_sequence_delivered == strmseq)) {
@@ -1655,6 +1670,11 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
*abort_flag = 1;
return (0);
}
+ /************************************
+ * From here down we may find ch-> invalid
+ * so its a good idea NOT to use it.
+ *************************************/
+
the_len = (chk_length - sizeof(struct sctp_data_chunk));
if (last_chunk == 0) {
dmbuf = SCTP_M_COPYM(*m,
@@ -1705,10 +1725,10 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
SCTP_STAT_INCR(sctps_nomem);
return (0);
}
- if ((ch->ch.chunk_flags & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG &&
+ if ((chunk_flags & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG &&
asoc->fragmented_delivery_inprogress == 0 &&
TAILQ_EMPTY(&asoc->resetHead) &&
- ((ch->ch.chunk_flags & SCTP_DATA_UNORDERED) ||
+ ((ordered == 0) ||
((asoc->strmin[strmno].last_sequence_delivered + 1) == strmseq &&
TAILQ_EMPTY(&asoc->strmin[strmno].inqueue)))) {
/* Candidate for express delivery */
@@ -1723,16 +1743,16 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
/* It would be nice to avoid this copy if we could :< */
sctp_alloc_a_readq(stcb, control);
sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn,
- ch->dp.protocol_id,
+ protocol_id,
stcb->asoc.context,
strmno, strmseq,
- ch->ch.chunk_flags,
+ chunk_flags,
dmbuf);
if (control == NULL) {
goto failed_express_del;
}
sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1);
- if ((ch->ch.chunk_flags & SCTP_DATA_UNORDERED) == 0) {
+ if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) {
/* for ordered, bump what we delivered */
asoc->strmin[strmno].last_sequence_delivered++;
}
@@ -1755,7 +1775,7 @@ failed_express_del:
(asoc->ssn_of_pdapi == strmseq)
) {
control = stcb->asoc.control_pdapi;
- if ((ch->ch.chunk_flags & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) {
+ if ((chunk_flags & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) {
/* Can't be another first? */
goto failed_pdapi_express_del;
}
@@ -1764,7 +1784,7 @@ failed_express_del:
int end = 0;
uint32_t cumack;
- if (ch->ch.chunk_flags & SCTP_DATA_LAST_FRAG) {
+ if (chunk_flags & SCTP_DATA_LAST_FRAG) {
end = 1;
}
cumack = asoc->cumulative_tsn;
@@ -1780,15 +1800,15 @@ failed_express_del:
SCTP_STAT_INCR(sctps_recvexpressm);
control->sinfo_tsn = tsn;
asoc->tsn_last_delivered = tsn;
- asoc->fragment_flags = ch->ch.chunk_flags;
+ asoc->fragment_flags = chunk_flags;
asoc->tsn_of_pdapi_last_delivered = tsn;
- asoc->last_flags_delivered = ch->ch.chunk_flags;
+ asoc->last_flags_delivered = chunk_flags;
asoc->last_strm_seq_delivered = strmseq;
asoc->last_strm_no_delivered = strmno;
if (end) {
/* clean up the flags and such */
asoc->fragmented_delivery_inprogress = 0;
- if ((ch->ch.chunk_flags & SCTP_DATA_UNORDERED) == 0) {
+ if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) {
asoc->strmin[strmno].last_sequence_delivered++;
}
stcb->asoc.control_pdapi = NULL;
@@ -1806,7 +1826,7 @@ failed_express_del:
}
failed_pdapi_express_del:
control = NULL;
- if ((ch->ch.chunk_flags & SCTP_DATA_NOT_FRAG) != SCTP_DATA_NOT_FRAG) {
+ if ((chunk_flags & SCTP_DATA_NOT_FRAG) != SCTP_DATA_NOT_FRAG) {
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
/* No memory so we drop the chunk */
@@ -1821,10 +1841,10 @@ failed_pdapi_express_del:
chk->no_fr_allowed = 0;
chk->rec.data.stream_seq = strmseq;
chk->rec.data.stream_number = strmno;
- chk->rec.data.payloadtype = ch->dp.protocol_id;
+ chk->rec.data.payloadtype = protocol_id;
chk->rec.data.context = stcb->asoc.context;
chk->rec.data.doing_fast_retransmit = 0;
- chk->rec.data.rcv_flags = ch->ch.chunk_flags;
+ chk->rec.data.rcv_flags = chunk_flags;
chk->asoc = asoc;
chk->send_size = the_len;
chk->whoTo = net;
@@ -1833,10 +1853,10 @@ failed_pdapi_express_del:
} else {
sctp_alloc_a_readq(stcb, control);
sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn,
- ch->dp.protocol_id,
+ protocol_id,
stcb->asoc.context,
strmno, strmseq,
- ch->ch.chunk_flags,
+ chunk_flags,
dmbuf);
if (control == NULL) {
/* No memory so we drop the chunk */
@@ -1980,7 +2000,7 @@ failed_pdapi_express_del:
}
}
/* ok, if we reach here we have passed the sanity checks */
- if (ch->ch.chunk_flags & SCTP_DATA_UNORDERED) {
+ if (chunk_flags & SCTP_DATA_UNORDERED) {
/* queue directly into socket buffer */
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
@@ -2073,7 +2093,7 @@ finish_express_del:
if (last_chunk) {
*m = NULL;
}
- if ((ch->ch.chunk_flags & SCTP_DATA_UNORDERED) == 0) {
+ if (ordered) {
SCTP_STAT_INCR_COUNTER64(sctps_inorderchunks);
} else {
SCTP_STAT_INCR_COUNTER64(sctps_inunorderchunks);
@@ -2401,9 +2421,8 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
* duplicates.
*/
stcb->asoc.first_ack_sent = 1;
-
+ SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
sctp_send_sack(stcb);
- /* The sending will stop the timer */
}
} else {
sctp_timer_start(SCTP_TIMER_TYPE_RECV,
@@ -2908,7 +2927,7 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
* newly acked.
* update
* this_sack_highest_
- * n ewack if
+ * newack if
* appropriate.
*/
if (tp1->rec.data.chunk_was_revoked == 0)
@@ -2924,7 +2943,7 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
* CMT DAC algo:
* also update
* this_sack_lowest_n
- * e wack
+ * ewack
*/
if (*this_sack_lowest_newack == 0) {
#ifdef SCTP_SACK_LOGGING
@@ -2946,9 +2965,9 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
* acked, then we
* have a new
* (rtx-)pseudo-cumac
- * k . Set
+ * k. Set
* new_(rtx_)pseudo_c
- * u mack to TRUE so
+ * umack to TRUE so
* that the cwnd for
* this dest can be
* updated. Also
@@ -2956,7 +2975,7 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
* for the next
* expected
* (rtx-)pseudo-cumac
- * k . Separate
+ * k. Separate
* pseudo_cumack
* trackers for
* first
@@ -3089,24 +3108,43 @@ sctp_check_for_revoked(struct sctp_association *asoc, uint32_t cumack,
*/
if (tp1->sent == SCTP_DATAGRAM_ACKED) {
/* it has been revoked */
- tp1->sent = SCTP_DATAGRAM_SENT;
- tp1->rec.data.chunk_was_revoked = 1;
- /*
- * We must add this stuff back in to assure
- * timers and such get started.
- */
- tp1->whoTo->flight_size += tp1->book_size;
- asoc->total_flight_count++;
- asoc->total_flight += tp1->book_size;
- tot_revoked++;
+
+ if (sctp_cmt_on_off) {
+ /*
+ * If CMT is ON, leave "sent" at
+ * ACKED. CMT causes reordering of
+ * data and acks (received on
+ * different interfaces) can be
+ * persistently reordered. Acking
+ * followed by apparent revoking and
+ * re-acking causes unexpected weird
+ * behavior. So, at this time, CMT
+ * does not respect renegs. Renegs
+ * cannot be recovered. I will fix
+ * this once I am sure that things
+ * are working right again with CMT.
+ */
+ } else {
+ tp1->sent = SCTP_DATAGRAM_SENT;
+ tp1->rec.data.chunk_was_revoked = 1;
+ /*
+ * We must add this stuff back in to
+ * assure timers and such get
+ * started.
+ */
+ tp1->whoTo->flight_size += tp1->book_size;
+ asoc->total_flight_count++;
+ asoc->total_flight += tp1->book_size;
+ tot_revoked++;
#ifdef SCTP_SACK_LOGGING
- sctp_log_sack(asoc->last_acked_seq,
- cumack,
- tp1->rec.data.TSN_seq,
- 0,
- 0,
- SCTP_LOG_TSN_REVOKED);
+ sctp_log_sack(asoc->last_acked_seq,
+ cumack,
+ tp1->rec.data.TSN_seq,
+ 0,
+ 0,
+ SCTP_LOG_TSN_REVOKED);
#endif
+ }
} else if (tp1->sent == SCTP_DATAGRAM_MARKED) {
/* it has been re-acked in this SACK */
tp1->sent = SCTP_DATAGRAM_ACKED;
@@ -4382,8 +4420,11 @@ again:
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_RESPONSE_TO_USER_REQ, oper);
} else {
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
asoc->state = SCTP_STATE_SHUTDOWN_SENT;
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown(stcb,
stcb->asoc.primary_destination);
@@ -4397,8 +4438,8 @@ again:
if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
goto abort_out_now;
}
- asoc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ asoc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
sctp_send_shutdown_ack(stcb,
stcb->asoc.primary_destination);
@@ -4896,17 +4937,7 @@ done_with_it:
* we had some before and now we have NONE.
*/
- if (sctp_cmt_on_off) {
- /*
- * Don't check for revoked if CMT is ON. CMT causes
- * reordering of data and acks (received on different
- * interfaces) can be persistently reordered. Acking
- * followed by apparent revoking and re-acking causes
- * unexpected weird behavior. So, at this time, CMT does not
- * respect renegs. Renegs will have to be recovered through
- * a timeout. Not a big deal for such a rare event.
- */
- } else if (num_seg)
+ if (num_seg)
sctp_check_for_revoked(asoc, cum_ack, biggest_tsn_acked);
else if (asoc->saw_sack_with_frags) {
int cnt_revoked = 0;
@@ -5020,8 +5051,11 @@ done_with_it:
sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_RESPONSE_TO_USER_REQ, oper);
return;
} else {
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
asoc->state = SCTP_STATE_SHUTDOWN_SENT;
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown(stcb,
stcb->asoc.primary_destination);
@@ -5036,8 +5070,8 @@ done_with_it:
if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
goto abort_out_now;
}
- asoc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ asoc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
sctp_send_shutdown_ack(stcb,
stcb->asoc.primary_destination);
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 0a6fdea..f227c8e 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2001-2007, 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:
@@ -52,7 +52,6 @@ extern uint32_t sctp_debug_on;
-
struct sctp_foo_stuff sctp_logoff[30000];
int sctp_logoff_stuff = 0;
@@ -612,7 +611,8 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
/* send SHUTDOWN-ACK */
sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
/* move to SHUTDOWN-ACK-SENT state */
- if (asoc->state == SCTP_STATE_SHUTDOWN_RECEIVED) {
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
asoc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
@@ -1057,7 +1057,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* I know that the TCB is non-NULL from the caller */
asoc = &stcb->asoc;
- for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); i++) {
+ for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); how_indx++) {
if (asoc->cookie_how[how_indx] == 0)
break;
}
@@ -1160,16 +1160,20 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_12);
/* update current state */
+ if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)
+ SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
+ else
+ SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
- asoc->state = SCTP_STATE_OPEN |
- SCTP_STATE_SHUTDOWN_PENDING;
+ asoc->state = SCTP_STATE_OPEN | SCTP_STATE_SHUTDOWN_PENDING;
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
- } else if ((asoc->state & SCTP_STATE_SHUTDOWN_SENT) == 0) {
+ } else {
/* if ok, move to OPEN state */
asoc->state = SCTP_STATE_OPEN;
}
+ SCTP_STAT_INCR_GAUGE32(sctps_currestab);
sctp_stop_all_cookie_timers(stcb);
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
@@ -1204,6 +1208,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* we're in the OPEN state (or beyond), so peer must
* have simply lost the COOKIE-ACK
*/
+
break;
} /* end switch */
sctp_stop_all_cookie_timers(stcb);
@@ -1331,10 +1336,19 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
SCTP_PCB_FLAGS_CONNECTED;
soisconnected(stcb->sctp_ep->sctp_socket);
}
+ if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)
+ SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
+ else
+ SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
+ SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
+ SCTP_STAT_INCR_GAUGE32(sctps_currestab);
+ } else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
+ SCTP_STAT_INCR_COUNTER32(sctps_restartestab);
+ } else {
+ SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
}
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
- asoc->state = SCTP_STATE_OPEN |
- SCTP_STATE_SHUTDOWN_PENDING;
+ asoc->state = SCTP_STATE_OPEN | SCTP_STATE_SHUTDOWN_PENDING;
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
@@ -1379,6 +1393,16 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* notify upper layer */
*notification = SCTP_NOTIFY_ASSOC_RESTART;
atomic_add_int(&stcb->asoc.refcnt, 1);
+ if ((SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN) &&
+ (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
+ (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) {
+ SCTP_STAT_INCR_GAUGE32(sctps_currestab);
+ }
+ if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
+ SCTP_STAT_INCR_GAUGE32(sctps_restartestab);
+ } else if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
+ SCTP_STAT_INCR_GAUGE32(sctps_collisionestab);
+ }
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
asoc->state = SCTP_STATE_OPEN |
SCTP_STATE_SHUTDOWN_PENDING;
@@ -1509,7 +1533,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
int retval;
int error = 0;
uint32_t old_tag;
- uint8_t chunk_buf[DEFAULT_CHUNK_BUFFER];
+ uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE];
/*
* find and validate the INIT chunk in the cookie (peer's info) the
@@ -1647,7 +1671,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
struct sctp_auth_chunk *auth;
auth = (struct sctp_auth_chunk *)
- sctp_m_getptr(m, auth_offset, auth_len, chunk_buf);
+ sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf);
if (sctp_handle_auth(stcb, auth, m, auth_offset)) {
/* auth HMAC failed, dump the assoc and packet */
#ifdef SCTP_DEBUG
@@ -1812,7 +1836,6 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
sin->sin_port = sh->dest_port;
sin->sin_addr.s_addr = iph->ip_dst.s_addr;
size_of_pkt = SCTP_GET_IPV4_LENGTH(iph);
-
} else if (iph->ip_v == (IPV6_VERSION >> 4)) {
/* its IPv6 */
struct ip6_hdr *ip6;
@@ -1825,7 +1848,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
ip6 = mtod(m, struct ip6_hdr *);
sin6->sin6_port = sh->dest_port;
sin6->sin6_addr = ip6->ip6_dst;
- size_of_pkt = SCTP_GET_IPV6_LENGTH(ip6);
+ size_of_pkt = SCTP_GET_IPV6_LENGTH(ip6) + iphlen;
} else {
return (NULL);
}
@@ -2796,13 +2819,13 @@ static void
sctp_clean_up_stream_reset(struct sctp_tcb *stcb)
{
struct sctp_association *asoc;
-
- asoc = &stcb->asoc;
struct sctp_tmit_chunk *chk = stcb->asoc.str_reset;
if (stcb->asoc.str_reset == NULL) {
return;
}
+ asoc = &stcb->asoc;
+
sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_25);
TAILQ_REMOVE(&asoc->control_send_queue,
chk,
@@ -3104,11 +3127,11 @@ sctp_handle_stream_reset(struct sctp_tcb *stcb, struct sctp_stream_reset_out_req
struct sctp_tmit_chunk *chk;
struct sctp_chunkhdr *ch;
struct sctp_paramhdr *ph;
+ int ret_code = 0;
+ int num_param = 0;
/* now it may be a reset or a reset-response */
chk_length = ntohs(sr_req->ch.chunk_length);
- int ret_code = 0;
- int num_param = 0;
/* setup for adding the response */
sctp_alloc_a_chunk(stcb, chk);
@@ -3144,7 +3167,6 @@ strres_nochunk:
ch->chunk_length = htons(chk->send_size);
SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size);
-
ph = (struct sctp_paramhdr *)&sr_req->sr_req;
while ((size_t)chk_length >= sizeof(struct sctp_stream_reset_tsn_request)) {
param_len = ntohs(ph->param_length);
@@ -3504,7 +3526,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
* d-mtu-ceiling for now (2k) and that should hopefully work ...
* until we get into jumbo grams and such..
*/
- uint8_t chunk_buf[DEFAULT_CHUNK_BUFFER];
+ uint8_t chunk_buf[SCTP_CHUNK_BUFFER_SIZE];
struct sctp_tcb *locked_tcb = stcb;
int got_auth = 0;
uint32_t auth_offset = 0, auth_len = 0;
diff --git a/sys/netinet/sctp_os.h b/sys/netinet/sctp_os.h
index aacf877..15d256e 100644
--- a/sys/netinet/sctp_os.h
+++ b/sys/netinet/sctp_os.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2006, Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2006-2007, 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:
@@ -47,10 +47,11 @@ __FBSDID("$FreeBSD$");
* name = string name of the zone/pool.
* size = size of each zone/pool element.
* number = number of elements in zone/pool.
+ * type = structure type to allocate
*
* sctp_zone_t
* SCTP_ZONE_INIT(zone, name, size, number)
- * SCTP_ZONE_GET(zone)
+ * SCTP_ZONE_GET(zone, type)
* SCTP_ZONE_FREE(zone, element)
* SCTP_ZONE_DESTROY(zone)
*/
diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h
index eb2993e..c95b698 100644
--- a/sys/netinet/sctp_os_bsd.h
+++ b/sys/netinet/sctp_os_bsd.h
@@ -91,6 +91,8 @@ __FBSDID("$FreeBSD$");
#include <netinet6/scope6_var.h>
#endif /* INET6 */
+
+
#include <netinet/ip_options.h>
@@ -104,6 +106,7 @@ __FBSDID("$FreeBSD$");
*
*/
#define USER_ADDR_NULL (NULL) /* FIX ME: temp */
+#define SCTP_LIST_EMPTY(list) LIST_EMPTY(list)
/*
* general memory allocation
@@ -137,8 +140,8 @@ typedef struct uma_zone *sctp_zone_t;
}
/* SCTP_ZONE_GET: allocate element from the zone */
-#define SCTP_ZONE_GET(zone) \
- uma_zalloc(zone, M_NOWAIT);
+#define SCTP_ZONE_GET(zone, type) \
+ (type *)uma_zalloc(zone, M_NOWAIT);
/* SCTP_ZONE_FREE: free element from the zone */
#define SCTP_ZONE_FREE(zone, element) \
@@ -165,7 +168,6 @@ typedef struct callout sctp_os_timer_t;
/*
* Functions
*/
-#define SCTP_READ_RANDOM(buf, len) read_random(buf, len)
/* Mbuf manipulation and access macros */
#define SCTP_BUF_LEN(m) (m->m_len)
@@ -224,4 +226,31 @@ typedef struct callout sctp_os_timer_t;
#define SCTP_IPV6_V6ONLY(inp) (((struct inpcb *)inp)->inp_flags & IN6P_IPV6_V6ONLY)
+/*
+ * SCTP AUTH
+ */
+#define HAVE_SHA2
+
+#define SCTP_READ_RANDOM(buf, len) read_random(buf, len)
+
+#ifdef USE_SCTP_SHA1
+#include <netinet/sctp_sha1.h>
+#else
+#include <crypto/sha1.h>
+/* map standard crypto API names */
+#define SHA1_Init SHA1Init
+#define SHA1_Update SHA1Update
+#define SHA1_Final(x,y) SHA1Final((caddr_t)x, y)
+#endif
+
+#if defined(HAVE_SHA2)
+#include <crypto/sha2/sha2.h>
+#endif
+
+#include <sys/md5.h>
+/* map standard crypto API names */
+#define MD5_Init MD5Init
+#define MD5_Update MD5Update
+#define MD5_Final MD5Final
+
#endif
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index d1ceb6b..7572130 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2001-2007, 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:
@@ -2372,7 +2372,6 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
struct ip6_hdr *ip6h;
struct route_in6 ip6route;
-
struct ifnet *ifp;
u_char flowTop;
uint16_t flowBottom;
@@ -2783,11 +2782,17 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
/* attach RANDOM parameter, if available */
if (stcb->asoc.authinfo.random != NULL) {
random = (struct sctp_auth_random *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
- random->ph.param_type = htons(SCTP_RANDOM);
p_len = sizeof(*random) + stcb->asoc.authinfo.random_len;
+#ifdef SCTP_AUTH_DRAFT_04
+ random->ph.param_type = htons(SCTP_RANDOM);
random->ph.param_length = htons(p_len);
- bcopy(stcb->asoc.authinfo.random->key, random->random_data,
+ bcopy(stcb->asoc.authinfo.random->key,
+ random->random_data,
stcb->asoc.authinfo.random_len);
+#else
+ /* random key already contains the header */
+ bcopy(stcb->asoc.authinfo.random->key, random, p_len);
+#endif
/* zero out any padding required */
bzero((caddr_t)random + p_len, SCTP_SIZE32(p_len) - p_len);
SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
@@ -2900,7 +2905,7 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
struct sctp_paramhdr *phdr, params;
struct mbuf *mat, *op_err;
- char tempbuf[2048];
+ char tempbuf[SCTP_CHUNK_BUFFER_SIZE];
int at, limit, pad_needed;
uint16_t ptype, plen;
int err_at;
@@ -4101,7 +4106,7 @@ sctp_msg_append(struct sctp_tcb *stcb,
error = ECONNRESET;
goto out_now;
}
- sp = (struct sctp_stream_queue_pending *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_strmoq);
+ sp = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_strmoq, struct sctp_stream_queue_pending);
if (sp == NULL) {
error = ENOMEM;
goto out_now;
@@ -4411,8 +4416,10 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
* through
*/
sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
+ if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
asoc->state = SCTP_STATE_SHUTDOWN_SENT;
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb,
asoc->primary_destination);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
@@ -5089,6 +5096,17 @@ out_gu:
* Put the rest of the things in place now. Size was done earlier in
* previous loop prior to padding.
*/
+
+#ifdef SCTP_ASOCLOG_OF_TSNS
+ asoc->out_tsnlog[asoc->tsn_out_at].tsn = chk->rec.data.TSN_seq;
+ asoc->out_tsnlog[asoc->tsn_out_at].strm = chk->rec.data.stream_number;
+ asoc->out_tsnlog[asoc->tsn_out_at].seq = chk->rec.data.stream_seq;
+ asoc->tsn_out_at++;
+ if (asoc->tsn_out_at >= SCTP_TSN_LOG_SIZE) {
+ asoc->tsn_out_at = 0;
+ }
+#endif
+
dchkh->ch.chunk_type = SCTP_DATA;
dchkh->ch.chunk_flags = chk->rec.data.rcv_flags;
dchkh->dp.tsn = htonl(chk->rec.data.TSN_seq);
@@ -5350,15 +5368,14 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
int asconf, cookie, no_out_cnt;
int bundle_at, ctl_cnt, no_data_chunks, cwnd_full_ind, eeor_mode;
unsigned int mtu, r_mtu, omtu, mx_mtu, to_out;
-
- *num_out = 0;
struct sctp_nets *start_at, *old_startat = NULL, *send_start_at;
-
- cwnd_full_ind = 0;
int tsns_sent = 0;
uint32_t auth_offset = 0;
struct sctp_auth_chunk *auth = NULL;
+ *num_out = 0;
+ cwnd_full_ind = 0;
+
if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
(asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED) ||
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) {
@@ -7596,7 +7613,13 @@ sctp_send_sack(struct sctp_tcb *stcb)
sack = mtod(a_chk->data, struct sctp_sack_chunk *);
sack->ch.chunk_type = SCTP_SELECTIVE_ACK;
/* 0x01 is used by nonce for ecn */
- sack->ch.chunk_flags = (asoc->receiver_nonce_sum & SCTP_SACK_NONCE_SUM);
+ if ((sctp_ecn_enable) &&
+ (sctp_ecn_nonce) &&
+ (asoc->peer_supports_ecn_nonce))
+ sack->ch.chunk_flags = (asoc->receiver_nonce_sum & SCTP_SACK_NONCE_SUM);
+ else
+ sack->ch.chunk_flags = 0;
+
if (sctp_cmt_on_off && sctp_cmt_use_dac) {
/*
* CMT DAC algorithm: If 2 (i.e., 0x10) packets have been
@@ -7929,7 +7952,6 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh)
} else if (ip6_out != NULL) {
struct route_in6 ro;
-
bzero(&ro, sizeof(ro));
ip6_output(o_pak, NULL, &ro, 0, NULL, NULL
,NULL
@@ -8789,7 +8811,6 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
} else if (ip6_out != NULL) {
struct route_in6 ro;
-
/* zap the stack pointer to the route */
bzero(&ro, sizeof(ro));
#ifdef SCTP_DEBUG
@@ -8907,7 +8928,6 @@ sctp_send_operr_to(struct mbuf *m, int iphlen,
} else {
/* V6 */
struct route_in6 ro;
-
struct ip6_hdr *out6, *in6;
o_pak = SCTP_GET_HEADER_FOR_OUTPUT(sizeof(struct ip6_hdr));
@@ -9114,7 +9134,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
*errno = ECONNRESET;
goto out_now;
}
- sp = (struct sctp_stream_queue_pending *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_strmoq);
+ sp = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_strmoq, struct sctp_stream_queue_pending);
if (sp == NULL) {
*errno = ENOMEM;
goto out_now;
@@ -10096,8 +10116,10 @@ dataless_eof:
(SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
/* only send SHUTDOWN the first time through */
sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
+ if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
asoc->state = SCTP_STATE_SHUTDOWN_SENT;
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb,
asoc->primary_destination);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index f089616..e68c2b8 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -1326,7 +1326,7 @@ sctp_inpcb_alloc(struct socket *so)
error = 0;
SCTP_INP_INFO_WLOCK();
- inp = (struct sctp_inpcb *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_ep);
+ inp = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_ep, struct sctp_inpcb);
if (inp == NULL) {
printf("Out of SCTP-INPCB structures - no resources\n");
SCTP_INP_INFO_WUNLOCK();
@@ -1504,7 +1504,6 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
SCTP_INP_WLOCK(new_inp);
SCTP_TCB_LOCK(stcb);
-
new_inp->sctp_ep.time_of_secret_change =
old_inp->sctp_ep.time_of_secret_change;
memcpy(new_inp->sctp_ep.secret_key, old_inp->sctp_ep.secret_key,
@@ -1556,8 +1555,7 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
if ((new_inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
/* Subset bound, so copy in the laddr list from the old_inp */
LIST_FOREACH(oladdr, &old_inp->sctp_addr_list, sctp_nxt_addr) {
- laddr = (struct sctp_laddr *)SCTP_ZONE_GET(
- sctppcbinfo.ipi_zone_laddr);
+ laddr = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
if (laddr == NULL) {
/*
* Gak, what can we do? This assoc is really
@@ -2145,8 +2143,11 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* so I send shutdown
*/
sctp_send_shutdown(asoc, asoc->asoc.primary_destination);
+ if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
asoc->asoc.state = SCTP_STATE_SHUTDOWN_SENT;
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, asoc->sctp_ep, asoc,
asoc->asoc.primary_destination);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc,
@@ -2636,12 +2637,13 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
/* not supported family type */
return (-1);
}
- net = (struct sctp_nets *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_net);
+ net = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_net, struct sctp_nets);
if (net == NULL) {
return (-1);
}
SCTP_INCR_RADDR_COUNT();
bzero(net, sizeof(*net));
+ SCTP_GETTIME_TIMEVAL(&net->start_time);
memcpy(&net->ro._l_addr, newaddr, newaddr->sa_len);
if (newaddr->sa_family == AF_INET) {
((struct sockaddr_in *)&net->ro._l_addr)->sin_port = stcb->rport;
@@ -2903,7 +2905,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
return (NULL);
}
}
- stcb = (struct sctp_tcb *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_asoc);
+ stcb = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_asoc, struct sctp_tcb);
if (stcb == NULL) {
/* out of memory? */
*error = ENOMEM;
@@ -3076,7 +3078,7 @@ sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag, uint32_t time)
SCTP_GETTIME_TIMEVAL(&now);
chain = &sctppcbinfo.vtag_timewait[(tag % SCTP_STACK_VTAG_HASH_SIZE)];
set = 0;
- if (!LIST_EMPTY(chain)) {
+ if (!SCTP_LIST_EMPTY(chain)) {
/* Block(s) present, lets find space, and expire on the fly */
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
@@ -3630,7 +3632,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* local addresses, if any */
- while (!LIST_EMPTY(&asoc->sctp_local_addr_list)) {
+ while (!SCTP_LIST_EMPTY(&asoc->sctp_local_addr_list)) {
laddr = LIST_FIRST(&asoc->sctp_local_addr_list);
LIST_REMOVE(laddr, sctp_nxt_addr);
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, laddr);
@@ -3993,7 +3995,7 @@ sctp_insert_laddr(struct sctpladdr *list, struct ifaddr *ifa)
{
struct sctp_laddr *laddr;
- laddr = (struct sctp_laddr *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr);
+ laddr = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
if (laddr == NULL) {
/* out of memory? */
return (EINVAL);
@@ -4152,7 +4154,7 @@ sctp_pcb_init()
sctp_pcb_initialized = 1;
bzero(&sctpstat, sizeof(struct sctpstat));
-
+ SCTP_GETTIME_TIMEVAL(&sctpstat.sctps_discontinuitytime);
/* init the empty list of (All) Endpoints */
LIST_INIT(&sctppcbinfo.listhead);
@@ -4268,11 +4270,13 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
struct sockaddr *local_sa = (struct sockaddr *)&dest_store;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
- uint8_t store[384];
+ uint8_t random_store[SCTP_PARAM_BUFFER_SIZE];
struct sctp_auth_random *random = NULL;
uint16_t random_len = 0;
+ uint8_t hmacs_store[SCTP_PARAM_BUFFER_SIZE];
struct sctp_auth_hmac_algo *hmacs = NULL;
uint16_t hmacs_len = 0;
+ uint8_t chunks_store[SCTP_PARAM_BUFFER_SIZE];
struct sctp_auth_chunk_list *chunks = NULL;
uint16_t num_chunks = 0;
sctp_key_t *new_key;
@@ -4569,7 +4573,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
} else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
/* A supported extension chunk */
struct sctp_supported_chunk_types_param *pr_supported;
- uint8_t local_store[128];
+ uint8_t local_store[SCTP_PARAM_BUFFER_SIZE];
int num_ent, i;
phdr = sctp_get_next_param(m, offset,
@@ -4613,14 +4617,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
stcb->asoc.peer_supports_ecn_nonce = 1;
stcb->asoc.ecn_nonce_allowed = 1;
} else if (ptype == SCTP_RANDOM) {
- if (plen > sizeof(store))
+ if (plen > sizeof(random_store))
break;
if (got_random) {
/* already processed a RANDOM */
goto next_param;
}
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)store,
+ (struct sctp_paramhdr *)random_store,
plen);
if (phdr == NULL)
return (-26);
@@ -4639,14 +4643,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
int num_hmacs;
int i;
- if (plen > sizeof(store))
+ if (plen > sizeof(hmacs_store))
break;
if (got_hmacs) {
/* already processed a HMAC list */
goto next_param;
}
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)store,
+ (struct sctp_paramhdr *)hmacs_store,
plen);
if (phdr == NULL)
return (-28);
@@ -4670,14 +4674,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
} else if (ptype == SCTP_CHUNK_LIST) {
int i;
- if (plen > sizeof(store))
+ if (plen > sizeof(chunks_store))
break;
if (got_chklist) {
/* already processed a Chunks list */
goto next_param;
}
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)store,
+ (struct sctp_paramhdr *)chunks_store,
plen);
if (phdr == NULL)
return (-30);
@@ -4749,21 +4753,38 @@ next_param:
return (-31);
}
/* concatenate the full random key */
- keylen = random_len + num_chunks + hmacs_len;
+#ifdef SCTP_AUTH_DRAFT_04
+ keylen = random_len;
new_key = sctp_alloc_key(keylen);
if (new_key != NULL) {
/* copy in the RANDOM */
if (random != NULL)
bcopy(random->random_data, new_key->key, random_len);
+ }
+#else
+ keylen = sizeof(*random) + random_len + sizeof(*chunks) + num_chunks +
+ sizeof(*hmacs) + hmacs_len;
+ new_key = sctp_alloc_key(keylen);
+ if (new_key != NULL) {
+ /* copy in the RANDOM */
+ if (random != NULL) {
+ keylen = sizeof(*random) + random_len;
+ bcopy(random, new_key->key, keylen);
+ }
/* append in the AUTH chunks */
- if (chunks != NULL)
- bcopy(chunks->chunk_types, new_key->key + random_len,
- num_chunks);
+ if (chunks != NULL) {
+ bcopy(chunks, new_key->key + keylen,
+ sizeof(*chunks) + num_chunks);
+ keylen += sizeof(*chunks) + num_chunks;
+ }
/* append in the HMACs */
- if (hmacs != NULL)
- bcopy(hmacs->hmac_ids, new_key->key + random_len + num_chunks,
- hmacs_len);
- } else {
+ if (hmacs != NULL) {
+ bcopy(hmacs, new_key->key + keylen,
+ sizeof(*hmacs) + hmacs_len);
+ }
+ }
+#endif
+ else {
return (-32);
}
if (stcb->asoc.authinfo.peer_random != NULL)
@@ -4871,7 +4892,7 @@ check_restart:
}
check_time_wait:
/* Now what about timed wait ? */
- if (!LIST_EMPTY(chain)) {
+ if (!SCTP_LIST_EMPTY(chain)) {
/*
* Block(s) are present, lets see if we have this tag in the
* list
diff --git a/sys/netinet/sctp_peeloff.c b/sys/netinet/sctp_peeloff.c
index d621947..88da761 100644
--- a/sys/netinet/sctp_peeloff.c
+++ b/sys/netinet/sctp_peeloff.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2001-2007, 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:
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index d96e7d8..412ee02 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -263,6 +263,10 @@ struct sctp_nets {
#ifdef SCTP_HIGH_SPEED
uint8_t last_hs_used; /* index into the last HS table entry we used */
#endif
+ struct timeval start_time; /* time when this net was created */
+ uint32_t marked_retrans;/* number or DATA chunks marked for timer
+ * based retransmissions */
+ uint32_t marked_fastretrans;
};
@@ -444,6 +448,14 @@ struct sctp_scoping {
uint8_t site_scope;
};
+#define SCTP_TSN_LOG_SIZE 40
+
+struct sctp_tsn_log {
+ uint32_t tsn;
+ uint16_t strm;
+ uint16_t seq;
+};
+
/*
* Here we have information about each individual association that we track.
* We probably in production would be more dynamic. But for ease of
@@ -647,6 +659,16 @@ struct sctp_association {
uint32_t last_reset_action[SCTP_MAX_RESET_PARAMS];
uint32_t last_sending_seq[SCTP_MAX_RESET_PARAMS];
uint32_t last_base_tsnsent[SCTP_MAX_RESET_PARAMS];
+#ifdef SCTP_ASOCLOG_OF_TSNS
+ /*
+ * special log - This adds considerable size to the asoc, but
+ * provides a log that you can use to detect problems via kgdb.
+ */
+ struct sctp_tsn_log in_tsnlog[SCTP_TSN_LOG_SIZE];
+ struct sctp_tsn_log out_tsnlog[SCTP_TSN_LOG_SIZE];
+ uint16_t tsn_in_at;
+ uint16_t tsn_out_at;
+#endif /* SCTP_ASOCLOG_OF_TSNS */
/*
* window state information and smallest MTU that I use to bound
* segmentation
@@ -881,6 +903,16 @@ struct sctp_association {
* trailing locactions out. If I get a TSN above the array
* mappingArraySz, I discard the datagram and let retransmit happen.
*/
+ uint32_t marked_retrans;
+ uint32_t timoinit;
+ uint32_t timodata;
+ uint32_t timosack;
+ uint32_t timoshutdown;
+ uint32_t timoheartbeat;
+ uint32_t timocookie;
+ uint32_t timoshutdownack;
+ struct timeval start_time;
+ struct timeval discontinuity_time;
};
#endif
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index d065dbe..62de925 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2001-2007, 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:
@@ -637,6 +637,8 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
stcb->asoc.total_flight_count--;
chk->sent = SCTP_DATAGRAM_RESEND;
SCTP_STAT_INCR(sctps_markedretrans);
+ net->marked_retrans++;
+ stcb->asoc.marked_retrans++;
#ifdef SCTP_FLIGHT_LOGGING
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
chk->whoTo->flight_size,
@@ -1558,12 +1560,14 @@ sctp_autoclose_timer(struct sctp_inpcb *inp,
* there is nothing queued to send, so I'm
* done...
*/
- if (SCTP_GET_STATE(asoc) !=
- SCTP_STATE_SHUTDOWN_SENT) {
+ if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
/* only send SHUTDOWN 1st time thru */
sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
asoc->state = SCTP_STATE_SHUTDOWN_SENT;
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
stcb->sctp_ep, stcb,
asoc->primary_destination);
@@ -1590,7 +1594,6 @@ sctp_autoclose_timer(struct sctp_inpcb *inp,
}
}
-
void
sctp_iterator_timer(struct sctp_iterator *it)
{
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index 342f02f..89a81cc 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/time.h>
#include <netinet/in.h>
typedef uint32_t sctp_assoc_t;
@@ -83,7 +84,14 @@ struct sctp_initmsg {
* when enabled which is 48 bytes.
*/
+/*
+ * The assoc up needs a verfid
+ * all sendrcvinfo's need a verfid for SENDING only.
+ */
+
+
#define SCTP_ALIGN_RESV_PAD 96
+#define SCTP_ALIGN_RESV_PAD_SHORT 80
struct sctp_sndrcvinfo {
uint16_t sinfo_stream;
@@ -113,12 +121,14 @@ struct sctp_extrcvinfo {
uint32_t next_asocid;
uint32_t next_length;
uint32_t next_ppid;
+ uint8_t __reserve_pad[SCTP_ALIGN_RESV_PAD_SHORT];
};
#define SCTP_NO_NEXT_MSG 0x0000
#define SCTP_NEXT_MSG_AVAIL 0x0001
#define SCTP_NEXT_MSG_ISCOMPLETE 0x0002
#define SCTP_NEXT_MSG_IS_UNORDERED 0x0004
+#define SCTP_NEXT_MSG_IS_NOTIFICATION 0x0008
struct sctp_snd_all_completes {
uint16_t sall_stream;
@@ -734,6 +744,8 @@ struct sctpstat {
/* MIB according to RFC 3873 */
u_long sctps_currestab; /* sctpStats 1 (Gauge32) */
u_long sctps_activeestab; /* sctpStats 2 (Counter32) */
+ u_long sctps_restartestab;
+ u_long sctps_collisionestab;
u_long sctps_passiveestab; /* sctpStats 3 (Counter32) */
u_long sctps_aborted; /* sctpStats 4 (Counter32) */
u_long sctps_shutdown; /* sctpStats 5 (Counter32) */
@@ -749,7 +761,7 @@ struct sctpstat {
u_long sctps_reasmusrmsgs; /* sctpStats 15 (Counter64) */
u_long sctps_outpackets;/* sctpStats 16 (Counter64) */
u_long sctps_inpackets; /* sctpStats 17 (Counter64) */
- u_long sctps_discontinuitytime; /* sctpStats 18 (TimeStamp) */
+ struct timeval sctps_discontinuitytime; /* sctpStats 18 (TimeStamp) */
/* input statistics: */
u_long sctps_recvpackets; /* total input packets */
u_long sctps_recvdatagrams; /* total input datagrams */
@@ -901,12 +913,20 @@ struct xsctp_inpcb {
};
struct xsctp_tcb {
- uint16_t remote_port;
- uint16_t number_local_addresses;
- uint16_t number_remote_addresses;
- uint16_t number_incomming_streams;
- uint16_t number_outgoing_streams;
- uint32_t state;
+ uint16_t LocalPort; /* sctpAssocEntry 3 */
+ uint16_t RemPort; /* sctpAssocEntry 4 */
+ union sctp_sockstore RemPrimAddr; /* sctpAssocEntry 5/6 */
+ uint32_t HeartBeatInterval; /* sctpAssocEntry 7 */
+ uint32_t State; /* sctpAssocEntry 8 */
+ uint32_t InStreams; /* sctpAssocEntry 9 */
+ uint32_t OutStreams; /* sctpAssocEntry 10 */
+ uint32_t MaxRetr; /* sctpAssocEntry 11 */
+ uint32_t PrimProcess; /* sctpAssocEntry 12 */
+ uint32_t T1expireds; /* sctpAssocEntry 13 */
+ uint32_t T2expireds; /* sctpAssocEntry 14 */
+ uint32_t RtxChunks; /* sctpAssocEntry 15 */
+ struct timeval StartTime; /* sctpAssocEntry 16 */
+ struct timeval DiscontinuityTime; /* sctpAssocEntry 17 */
uint32_t total_sends;
uint32_t total_recvs;
uint32_t local_tag;
@@ -916,16 +936,28 @@ struct xsctp_tcb {
uint32_t cumulative_tsn;
uint32_t cumulative_tsn_ack;
/* add more association specific data here */
+ uint16_t number_local_addresses;
+ uint16_t number_remote_addresses;
};
struct xsctp_laddr {
- union sctp_sockstore address;
+ union sctp_sockstore LocalAddr; /* sctpAssocLocalAddrEntry 1/2 */
+ struct timeval LocalStartTime; /* sctpAssocLocalAddrEntry 3 */
/* add more local address specific data */
};
struct xsctp_raddr {
- union sctp_sockstore address;
- uint16_t state;
+ union sctp_sockstore RemAddr; /* sctpAssocLocalRemEntry 1/2 */
+ uint8_t RemAddrActive; /* sctpAssocLocalRemEntry 3 */
+ uint8_t RemAddrConfirmed; /* */
+ uint8_t RemAddrHBActive;/* sctpAssocLocalRemEntry 4 */
+ uint32_t RemAddrRTO; /* sctpAssocLocalRemEntry 5 */
+ uint32_t RemAddrMaxPathRtx; /* sctpAssocLocalRemEntry 6 */
+ uint32_t RemAddrRtx; /* sctpAssocLocalRemEntry 7 */
+ uint32_t RemAddrErrorCounter; /* */
+ uint32_t RemAddrCwnd; /* */
+ uint32_t RemAddrFlightSize; /* */
+ struct timeval RemAddrStartTime; /* sctpAssocLocalRemEntry 8 */
/* add more remote address specific data */
};
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 673e13e..1e0d5b3 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2001-2007, 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:
@@ -104,7 +104,6 @@ int sctp_chunkscale = SCTP_CHUNKQUEUE_SCALE;
unsigned int sctp_cmt_on_off = 0;
unsigned int sctp_cmt_sockopt_on_off = 0;
unsigned int sctp_cmt_use_dac = 0;
-unsigned int sctp_cmt_sockopt_use_dac = 0;
int sctp_L2_abc_variable = 1;
unsigned int sctp_early_fr = 0;
@@ -604,9 +603,9 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
* LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr)
* { error = SYSCTL_OUT(req, &xladdr, sizeof(struct
* xsctp_laddr)); if (error) { #if
- * defined(SCTP_APPLE_FINE_GRAINED_LOCKING)
- * socket_unlock(inp->ip_inp.inp.inp_socket, 1);
- * lck_rw_unlock_shared(sctppcbinfo.ipi_ep_mtx); #endif
+ * defined(SCTP_PER_SOCKET_LOCKING)
+ * SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1);
+ * SCTP_UNLOCK_SHARED(sctppcbinfo.ipi_ep_mtx); #endif
* SCTP_INP_RUNLOCK(inp); SCTP_INP_INFO_RUNLOCK(); return
* error; } }
*/
@@ -625,12 +624,24 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
number_of_remote_addresses++;
}
- xstcb.remote_port = ntohs(stcb->rport);
+ xstcb.LocalPort = ntohs(inp->sctp_lport);
+ xstcb.RemPort = ntohs(stcb->rport);
+ if (stcb->asoc.primary_destination != NULL)
+ xstcb.RemPrimAddr = stcb->asoc.primary_destination->ro._l_addr;
+ xstcb.HeartBeatInterval = stcb->asoc.heart_beat_delay;
+ xstcb.State = SCTP_GET_STATE(&stcb->asoc); /* FIXME */
+ xstcb.InStreams = stcb->asoc.streamincnt;
+ xstcb.OutStreams = stcb->asoc.streamoutcnt;
+ xstcb.MaxRetr = stcb->asoc.overall_error_count;
+ xstcb.PrimProcess = 0; /* not really supported yet */
+ xstcb.T1expireds = stcb->asoc.timoinit + stcb->asoc.timocookie;
+ xstcb.T2expireds = stcb->asoc.timoshutdown + stcb->asoc.timoshutdownack;
+ xstcb.RtxChunks = stcb->asoc.marked_retrans;
+ xstcb.StartTime = stcb->asoc.start_time;
+ xstcb.DiscontinuityTime = stcb->asoc.discontinuity_time;
+
xstcb.number_local_addresses = number_of_local_addresses;
xstcb.number_remote_addresses = number_of_remote_addresses;
- xstcb.number_incomming_streams = 0;
- xstcb.number_outgoing_streams = 0;
- xstcb.state = stcb->asoc.state;
xstcb.total_sends = stcb->total_sends;
xstcb.total_recvs = stcb->total_recvs;
xstcb.local_tag = stcb->asoc.my_vtag;
@@ -652,15 +663,24 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
* &stcb->asoc.sctp_local_addr_list, sctp_nxt_addr)
* { error = SYSCTL_OUT(req, &xladdr, sizeof(struct
* xsctp_laddr)); if (error) { #if
- * defined(SCTP_APPLE_FINE_GRAINED_LOCKING)
- * socket_unlock(inp->ip_inp.inp.inp_socket, 1);
- * lck_rw_unlock_shared(sctppcbinfo.ipi_ep_mtx);
+ * defined(SCTP_PER_SOCKET_LOCKING)
+ * SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1);
+ * SCTP_UNLOCK_SHARED(sctppcbinfo.ipi_ep_mtx);
* #endif SCTP_INP_RUNLOCK(inp);
* SCTP_INP_INFO_RUNLOCK(); return error; }
* */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- xraddr.state = net->dest_state;
- xraddr.address = net->ro._l_addr;
+ xraddr.RemAddr = net->ro._l_addr;
+ xraddr.RemAddrActive = ((net->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE);
+ xraddr.RemAddrConfirmed = ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0);
+ xraddr.RemAddrHBActive = ((net->dest_state & SCTP_ADDR_NOHB) == 0);
+ xraddr.RemAddrRTO = net->RTO;
+ xraddr.RemAddrMaxPathRtx = net->failure_threshold;
+ xraddr.RemAddrRtx = net->marked_retrans;
+ xraddr.RemAddrErrorCounter = net->error_count;
+ xraddr.RemAddrCwnd = net->cwnd;
+ xraddr.RemAddrFlightSize = net->flight_size;
+ xraddr.RemAddrStartTime = net->start_time;
error = SYSCTL_OUT(req, &xraddr, sizeof(struct xsctp_raddr));
if (error) {
atomic_add_int(&stcb->asoc.refcnt, -1);
@@ -1179,7 +1199,7 @@ sctp_disconnect(struct socket *so)
}
SCTP_INP_RLOCK(inp);
if (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
- if (LIST_EMPTY(&inp->sctp_asoc_list)) {
+ if (SCTP_LIST_EMPTY(&inp->sctp_asoc_list)) {
/* No connection */
SCTP_INP_RUNLOCK(inp);
return (0);
@@ -1240,17 +1260,18 @@ sctp_disconnect(struct socket *so)
if (asoc->locked_on_sending) {
goto abort_anyway;
}
- if ((SCTP_GET_STATE(asoc) !=
- SCTP_STATE_SHUTDOWN_SENT) &&
- (SCTP_GET_STATE(asoc) !=
- SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
+ (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
/* only send SHUTDOWN 1st time thru */
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown(stcb,
stcb->asoc.primary_destination);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3);
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
asoc->state = SCTP_STATE_SHUTDOWN_SENT;
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
stcb->sctp_ep, stcb,
asoc->primary_destination);
@@ -1387,8 +1408,11 @@ sctp_shutdown(struct socket *so)
sctp_send_shutdown(stcb,
stcb->asoc.primary_destination);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3);
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
asoc->state = SCTP_STATE_SHUTDOWN_SENT;
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
stcb->sctp_ep, stcb,
asoc->primary_destination);
@@ -1473,15 +1497,16 @@ sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
-static int
+static size_t
sctp_fill_up_addresses(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
- int limit,
+ size_t limit,
struct sockaddr_storage *sas)
{
struct ifnet *ifn;
struct ifaddr *ifa;
- int loopback_scope, ipv4_local_scope, local_scope, site_scope, actual;
+ int loopback_scope, ipv4_local_scope, local_scope, site_scope;
+ size_t actual;
int ipv4_addr_legal, ipv6_addr_legal;
actual = 0;
@@ -1716,19 +1741,17 @@ sctp_count_max_addresses(struct sctp_inpcb *inp)
return (cnt);
}
+
static int
-sctp_do_connect_x(struct socket *so,
- struct sctp_inpcb *inp,
- struct mbuf *m,
- struct thread *p,
- int delay
-)
+sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
+ size_t optsize, void *p, int delay)
{
int error = 0;
int creat_lock_on = 0;
struct sctp_tcb *stcb = NULL;
struct sockaddr *sa;
- int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr, i, incr, at;
+ int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr, i;
+ size_t incr, at;
#ifdef SCTP_DEBUG
if (sctp_debug_on & SCTP_DEBUG_PCB1) {
@@ -1751,7 +1774,6 @@ sctp_do_connect_x(struct socket *so,
}
if (stcb) {
return (EALREADY);
-
}
SCTP_INP_INCR_REF(inp);
SCTP_ASOC_CREATE_LOCK(inp);
@@ -1761,7 +1783,7 @@ sctp_do_connect_x(struct socket *so,
error = EFAULT;
goto out_now;
}
- totaddrp = mtod(m, int *);
+ totaddrp = (int *)optval;
totaddr = *totaddrp;
sa = (struct sockaddr *)(totaddrp + 1);
at = incr = 0;
@@ -1794,7 +1816,7 @@ sctp_do_connect_x(struct socket *so,
error = EALREADY;
goto out_now;
}
- if ((at + incr) > SCTP_BUF_LEN(m)) {
+ if ((at + incr) > optsize) {
totaddr = i;
break;
}
@@ -1892,34 +1914,49 @@ out_now:
return error;
}
+#define SCTP_FIND_STCB(inp, stcb, assoc_id) \
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { \
+ SCTP_INP_RLOCK(inp); \
+ stcb = LIST_FIRST(&inp->sctp_asoc_list); \
+ if (stcb) \
+ SCTP_TCB_LOCK(stcb); \
+ SCTP_INP_RUNLOCK(inp); \
+ } else if (assoc_id != 0) { \
+ stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
+ if (stcb == NULL) { \
+ error = ENOENT; \
+ break; \
+ } \
+ } else { \
+ stcb = NULL; \
+ }
+
+#define SCTP_CHECK_AND_CAST(destp, srcp, type, size) \
+ if (size < sizeof(type)) { \
+ error = EINVAL; \
+ break; \
+ } else { \
+ destp = (type *)srcp; \
+ }
static int
-sctp_optsget(struct socket *so,
- int opt,
- struct mbuf **mp,
- struct thread *p
-)
+sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
+ void *p)
{
struct sctp_inpcb *inp;
- struct mbuf *m;
- int error, optval = 0;
+ int error, val = 0;
struct sctp_tcb *stcb = NULL;
+ if (optval == NULL) {
+ return (EINVAL);
+ }
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0)
return EINVAL;
error = 0;
- if (mp == NULL) {
- return (EINVAL);
- }
- m = *mp;
- if (m == NULL) {
- /* Got to have a mbuf */
- return (EINVAL);
- }
- switch (opt) {
+ switch (optname) {
case SCTP_NODELAY:
case SCTP_AUTOCLOSE:
case SCTP_EXPLICIT_EOR:
@@ -1928,94 +1965,92 @@ sctp_optsget(struct socket *so,
case SCTP_I_WANT_MAPPED_V4_ADDR:
case SCTP_USE_EXT_RCVINFO:
SCTP_INP_RLOCK(inp);
- switch (opt) {
+ switch (optname) {
case SCTP_DISABLE_FRAGMENTS:
- optval = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
+ val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
break;
case SCTP_I_WANT_MAPPED_V4_ADDR:
- optval = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
+ val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
break;
case SCTP_AUTO_ASCONF:
- optval = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
+ val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
break;
case SCTP_EXPLICIT_EOR:
- optval = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
+ val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
break;
case SCTP_NODELAY:
- optval = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
+ val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
break;
case SCTP_USE_EXT_RCVINFO:
- optval = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
+ val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
break;
case SCTP_AUTOCLOSE:
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
- optval = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
+ val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
else
- optval = 0;
+ val = 0;
break;
default:
error = ENOPROTOOPT;
} /* end switch (sopt->sopt_name) */
- if (opt != SCTP_AUTOCLOSE) {
+ if (optname != SCTP_AUTOCLOSE) {
/* make it an "on/off" value */
- optval = (optval != 0);
+ val = (val != 0);
}
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) {
+ if (*optsize < sizeof(val)) {
error = EINVAL;
}
SCTP_INP_RUNLOCK(inp);
if (error == 0) {
/* return the option value */
- *mtod(m, int *)= optval;
- SCTP_BUF_LEN(m) = sizeof(optval);
+ *(int *)optval = val;
+ *optsize = sizeof(val);
}
break;
case SCTP_PARTIAL_DELIVERY_POINT:
{
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(unsigned int)) {
- error = EINVAL;
- break;
- }
- *mtod(m, unsigned int *)= inp->partial_delivery_point;
- SCTP_BUF_LEN(m) = sizeof(unsigned int);
+ uint32_t *value;
+
+ SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
+ *value = inp->partial_delivery_point;
+ *optsize = sizeof(uint32_t);
}
break;
case SCTP_FRAGMENT_INTERLEAVE:
{
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(unsigned int)) {
- error = EINVAL;
- break;
- }
- *mtod(m, unsigned int *)= sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
- SCTP_BUF_LEN(m) = sizeof(unsigned int);
+ uint32_t *value;
+
+ SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
+ *value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
+ *optsize = sizeof(uint32_t);
}
break;
case SCTP_CMT_ON_OFF:
{
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(unsigned int)) {
- error = EINVAL;
- break;
+ struct sctp_assoc_value *av;
+
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+ if (sctp_cmt_on_off) {
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+ if (stcb) {
+ av->assoc_value = stcb->asoc.sctp_cmt_on_off;
+ SCTP_TCB_UNLOCK(stcb);
+
+ } else {
+ error = ENOTCONN;
+ }
+ } else {
+ error = ENOPROTOOPT;
}
- *mtod(m, unsigned int *)= sctp_cmt_sockopt_on_off;
- SCTP_BUF_LEN(m) = sizeof(unsigned int);
- }
- break;
- case SCTP_CMT_USE_DAC:
- {
- *mtod(m, unsigned int *)= sctp_cmt_sockopt_use_dac;
- SCTP_BUF_LEN(m) = sizeof(unsigned int);
+ *optsize = sizeof(*av);
}
break;
case SCTP_GET_ADDR_LEN:
{
struct sctp_assoc_value *av;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) {
- error = EINVAL;
- break;
- }
- av = mtod(m, struct sctp_assoc_value *);
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
error = EINVAL;
#ifdef AF_INET
if (av->assoc_value == AF_INET) {
@@ -2029,6 +2064,7 @@ sctp_optsget(struct socket *so,
error = 0;
}
#endif
+ *optsize = sizeof(*av);
}
break;
case SCTP_GET_ASOC_ID_LIST:
@@ -2037,11 +2073,7 @@ sctp_optsget(struct socket *so,
int cnt, at;
uint16_t orig;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_ids)) {
- error = EINVAL;
- break;
- }
- ids = mtod(m, struct sctp_assoc_ids *);
+ SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
cnt = 0;
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
@@ -2082,192 +2114,112 @@ sctp_optsget(struct socket *so,
break;
case SCTP_CONTEXT:
{
-
struct sctp_assoc_value *av;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) {
- error = EINVAL;
- break;
- }
- av = mtod(m, struct sctp_assoc_value *);
- if (av->assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, av->assoc_id, 1);
- if (stcb == NULL) {
- error = ENOTCONN;
- } else {
- av->assoc_value = stcb->asoc.context;
- SCTP_TCB_UNLOCK(stcb);
- }
+ 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.context;
+ SCTP_TCB_UNLOCK(stcb);
} else {
+ SCTP_INP_RLOCK(inp);
av->assoc_value = inp->sctp_context;
+ SCTP_INP_RUNLOCK(inp);
}
+ *optsize = sizeof(*av);
}
break;
case SCTP_GET_NONCE_VALUES:
{
struct sctp_get_nonce_values *gnv;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_get_nonce_values)) {
- error = EINVAL;
- break;
- }
- gnv = mtod(m, struct sctp_get_nonce_values *);
- stcb = sctp_findassociation_ep_asocid(inp, gnv->gn_assoc_id, 1);
- if (stcb == NULL) {
- error = ENOTCONN;
- } else {
+ SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
+ SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
+
+ if (stcb) {
gnv->gn_peers_tag = stcb->asoc.peer_vtag;
gnv->gn_local_tag = stcb->asoc.my_vtag;
SCTP_TCB_UNLOCK(stcb);
+ } else {
+ error = ENOTCONN;
}
-
+ *optsize = sizeof(*gnv);
}
break;
case SCTP_DELAYED_ACK_TIME:
{
struct sctp_assoc_value *tm;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) {
- error = EINVAL;
- break;
- }
- tm = mtod(m, struct sctp_assoc_value *);
+ SCTP_CHECK_AND_CAST(tm, optval, struct sctp_assoc_value, *optsize);
+ SCTP_FIND_STCB(inp, stcb, tm->assoc_id);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
+ if (stcb) {
+ tm->assoc_value = stcb->asoc.delayed_ack;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- tm->assoc_value = stcb->asoc.delayed_ack;
- SCTP_TCB_UNLOCK(stcb);
- } else {
- tm->assoc_value = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
- }
+ tm->assoc_value = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
SCTP_INP_RUNLOCK(inp);
- } else {
- stcb = sctp_findassociation_ep_asocid(inp, tm->assoc_id, 1);
- if (stcb == NULL) {
- error = ENOTCONN;
- tm->assoc_value = 0;
- } else {
- stcb->asoc.delayed_ack = tm->assoc_value;
- SCTP_TCB_UNLOCK(stcb);
- }
}
+ *optsize = sizeof(*tm);
}
break;
case SCTP_GET_SNDBUF_USE:
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_sockstat)) {
- error = EINVAL;
- } else {
+ {
struct sctp_sockstat *ss;
- struct sctp_tcb *stcb;
- struct sctp_association *asoc;
- ss = mtod(m, struct sctp_sockstat *);
- stcb = sctp_findassociation_ep_asocid(inp, ss->ss_assoc_id, 1);
- if (stcb == NULL) {
- error = ENOTCONN;
- } else {
- asoc = &stcb->asoc;
- ss->ss_total_sndbuf = (uint32_t) asoc->total_output_queue_size;
- ss->ss_total_recv_buf = (uint32_t) (asoc->size_on_reasm_queue +
- asoc->size_on_all_streams);
+ SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
+ SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
+
+ if (stcb) {
+ ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
+ ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
+ stcb->asoc.size_on_all_streams);
SCTP_TCB_UNLOCK(stcb);
- error = 0;
- SCTP_BUF_LEN(m) = sizeof(struct sctp_sockstat);
+ } else {
+ error = ENOTCONN;
}
+ *optsize = sizeof(struct sctp_sockstat);
}
break;
case SCTP_MAXBURST:
{
- uint8_t *burst;
+ uint8_t *value;
+
+ SCTP_CHECK_AND_CAST(value, optval, uint8_t, *optsize);
- burst = mtod(m, uint8_t *);
SCTP_INP_RLOCK(inp);
- *burst = inp->sctp_ep.max_burst;
+ *value = inp->sctp_ep.max_burst;
SCTP_INP_RUNLOCK(inp);
- SCTP_BUF_LEN(m) = sizeof(uint8_t);
+ *optsize = sizeof(uint8_t);
}
break;
-
+ /*
+ * FIXME MT: Should this be done as the association level by
+ * using sctp_get_frag_point?
+ */
case SCTP_MAXSEG:
{
uint32_t *segsize;
- sctp_assoc_t *assoc_id;
int ovh;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(uint32_t)) {
- error = EINVAL;
- break;
- }
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(sctp_assoc_t)) {
- error = EINVAL;
- break;
- }
- assoc_id = mtod(m, sctp_assoc_t *);
- segsize = mtod(m, uint32_t *);
- SCTP_BUF_LEN(m) = sizeof(uint32_t);
-
- if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
- (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) ||
- (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- struct sctp_tcb *stcb;
+ SCTP_CHECK_AND_CAST(segsize, optval, uint32_t, *optsize);
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- *segsize = sctp_get_frag_point(stcb, &stcb->asoc);
- SCTP_TCB_UNLOCK(stcb);
- } else {
- SCTP_INP_RUNLOCK(inp);
- goto skipit;
- }
+ SCTP_INP_RLOCK(inp);
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ ovh = SCTP_MED_OVERHEAD;
} else {
- stcb = sctp_findassociation_ep_asocid(inp, *assoc_id, 1);
- if (stcb) {
- *segsize = sctp_get_frag_point(stcb, &stcb->asoc);
- SCTP_TCB_UNLOCK(stcb);
- break;
- }
- skipit:
- /*
- * default is to get the max, if I can't
- * calculate from an existing association.
- */
- if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- ovh = SCTP_MED_OVERHEAD;
- } else {
- ovh = SCTP_MED_V4_OVERHEAD;
- }
- *segsize = inp->sctp_frag_point - ovh;
- }
- }
- break;
-
- case SCTP_SET_DEBUG_LEVEL:
-#ifdef SCTP_DEBUG
- {
- uint32_t *level;
-
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(uint32_t)) {
- error = EINVAL;
- break;
+ ovh = SCTP_MED_V4_OVERHEAD;
}
- level = mtod(m, uint32_t *);
- error = 0;
- *level = sctp_debug_on;
- SCTP_BUF_LEN(m) = sizeof(uint32_t);
- printf("Returning DEBUG LEVEL %x is set\n",
- (uint32_t) sctp_debug_on);
+ *segsize = inp->sctp_frag_point - ovh;
+ SCTP_INP_RUNLOCK(inp);
+ *optsize = sizeof(uint32_t);
}
-#else /* SCTP_DEBUG */
- error = EOPNOTSUPP;
-#endif
break;
+#if 0
+ /* FIXME MT: How does this work? */
case SCTP_GET_STAT_LOG:
#ifdef SCTP_STAT_LOGGING
error = sctp_fill_stat_log(m);
@@ -2275,15 +2227,12 @@ sctp_optsget(struct socket *so,
error = EOPNOTSUPP;
#endif
break;
+#endif
case SCTP_EVENTS:
{
struct sctp_event_subscribe *events;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_event_subscribe)) {
- error = EINVAL;
- break;
- }
- events = mtod(m, struct sctp_event_subscribe *);
+ SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
memset(events, 0, sizeof(*events));
SCTP_INP_RLOCK(inp);
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
@@ -2316,85 +2265,74 @@ sctp_optsget(struct socket *so,
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
events->sctp_stream_reset_events = 1;
SCTP_INP_RUNLOCK(inp);
- SCTP_BUF_LEN(m) = sizeof(struct sctp_event_subscribe);
-
+ *optsize = sizeof(struct sctp_event_subscribe);
}
break;
case SCTP_ADAPTATION_LAYER:
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) {
- error = EINVAL;
- break;
+ {
+ uint32_t *value;
+
+ SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
+
+ SCTP_INP_RLOCK(inp);
+ *value = inp->sctp_ep.adaptation_layer_indicator;
+ SCTP_INP_RUNLOCK(inp);
+ *optsize = sizeof(uint32_t);
}
- SCTP_INP_RLOCK(inp);
- *mtod(m, int *)= inp->sctp_ep.adaptation_layer_indicator;
- SCTP_INP_RUNLOCK(inp);
- SCTP_BUF_LEN(m) = sizeof(int);
break;
case SCTP_SET_INITIAL_DBG_SEQ:
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) {
- error = EINVAL;
- break;
+ {
+ uint32_t *value;
+
+ SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
+ SCTP_INP_RLOCK(inp);
+ *value = inp->sctp_ep.initial_sequence_debug;
+ SCTP_INP_RUNLOCK(inp);
+ *optsize = sizeof(uint32_t);
}
- SCTP_INP_RLOCK(inp);
- *mtod(m, int *)= inp->sctp_ep.initial_sequence_debug;
- SCTP_INP_RUNLOCK(inp);
- SCTP_BUF_LEN(m) = sizeof(int);
break;
case SCTP_GET_LOCAL_ADDR_SIZE:
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) {
- error = EINVAL;
- break;
+ {
+ uint32_t *value;
+
+ SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
+ SCTP_INP_RLOCK(inp);
+ *value = sctp_count_max_addresses(inp);
+ SCTP_INP_RUNLOCK(inp);
+ *optsize = sizeof(uint32_t);
}
- SCTP_INP_RLOCK(inp);
- *mtod(m, int *)= sctp_count_max_addresses(inp);
- SCTP_INP_RUNLOCK(inp);
- SCTP_BUF_LEN(m) = sizeof(int);
break;
case SCTP_GET_REMOTE_ADDR_SIZE:
{
- sctp_assoc_t *assoc_id;
- uint32_t *val, sz;
+ uint32_t *value;
+ size_t size;
struct sctp_nets *net;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(sctp_assoc_t)) {
- error = EINVAL;
- break;
- }
- stcb = NULL;
- val = mtod(m, uint32_t *);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- }
- if (stcb == NULL) {
- assoc_id = mtod(m, sctp_assoc_t *);
- stcb = sctp_findassociation_ep_asocid(inp, *assoc_id, 1);
- }
- if (stcb == NULL) {
- error = EINVAL;
- break;
- }
- *val = 0;
- sz = 0;
- /* Count the sizes */
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) ||
- (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) {
- sz += sizeof(struct sockaddr_in6);
- } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) {
- sz += sizeof(struct sockaddr_in);
- } else {
- /* huh */
- break;
+ SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
+ /* FIXME MT: change to sctp_assoc_value? */
+ SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
+
+ if (stcb) {
+ size = 0;
+ /* Count the sizes */
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) ||
+ (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) {
+ size += sizeof(struct sockaddr_in6);
+ } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) {
+ size += sizeof(struct sockaddr_in);
+ } else {
+ /* huh */
+ break;
+ }
}
+ SCTP_TCB_UNLOCK(stcb);
+ *value = (uint32_t) size;
+ } else {
+ error = ENOTCONN;
}
- SCTP_TCB_UNLOCK(stcb);
- *val = sz;
- SCTP_BUF_LEN(m) = sizeof(uint32_t);
+ *optsize = sizeof(uint32_t);
}
break;
case SCTP_GET_PEER_ADDRESSES:
@@ -2403,107 +2341,68 @@ sctp_optsget(struct socket *so,
* fill up we pack it.
*/
{
- int cpsz, left;
+ size_t cpsz, left;
struct sockaddr_storage *sas;
struct sctp_nets *net;
struct sctp_getaddresses *saddr;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_getaddresses)) {
- error = EINVAL;
- break;
- }
- left = SCTP_BUF_LEN(m) - sizeof(struct sctp_getaddresses);
- saddr = mtod(m, struct sctp_getaddresses *);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else
- stcb = sctp_findassociation_ep_asocid(inp,
- saddr->sget_assoc_id, 1);
- if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- SCTP_BUF_LEN(m) = sizeof(struct sctp_getaddresses);
- sas = (struct sockaddr_storage *)&saddr->addr[0];
+ SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
+ SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) ||
- (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) {
- cpsz = sizeof(struct sockaddr_in6);
- } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) {
- cpsz = sizeof(struct sockaddr_in);
- } else {
- /* huh */
- break;
- }
- if (left < cpsz) {
- /* not enough room. */
- break;
- }
- if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
- (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
- /* Must map the address */
- in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
- (struct sockaddr_in6 *)sas);
- } else {
- memcpy(sas, &net->ro._l_addr, cpsz);
- }
- ((struct sockaddr_in *)sas)->sin_port = stcb->rport;
+ if (stcb) {
+ left = (*optsize) - sizeof(struct sctp_getaddresses);
+ *optsize = sizeof(struct sctp_getaddresses);
+ sas = (struct sockaddr_storage *)&saddr->addr[0];
- sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
- left -= cpsz;
- SCTP_BUF_LEN(m) += cpsz;
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) ||
+ (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) {
+ cpsz = sizeof(struct sockaddr_in6);
+ } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) {
+ cpsz = sizeof(struct sockaddr_in);
+ } else {
+ /* huh */
+ break;
+ }
+ if (left < cpsz) {
+ /* not enough room. */
+ break;
+ }
+ if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
+ (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
+ /* Must map the address */
+ in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
+ (struct sockaddr_in6 *)sas);
+ } else {
+ memcpy(sas, &net->ro._l_addr, cpsz);
+ }
+ ((struct sockaddr_in *)sas)->sin_port = stcb->rport;
+
+ sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
+ left -= cpsz;
+ *optsize += cpsz;
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ error = ENOENT;
}
- SCTP_TCB_UNLOCK(stcb);
}
break;
case SCTP_GET_LOCAL_ADDRESSES:
{
- int limit, actual;
+ size_t limit, actual;
struct sockaddr_storage *sas;
struct sctp_getaddresses *saddr;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_getaddresses)) {
- error = EINVAL;
- break;
- }
- saddr = mtod(m, struct sctp_getaddresses *);
-
- if (saddr->sget_assoc_id) {
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else
- stcb = sctp_findassociation_ep_asocid(inp, saddr->sget_assoc_id, 1);
+ SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
+ SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
- } else {
- stcb = NULL;
- }
- /*
- * assure that the TCP model does not need a assoc
- * id once connected.
- */
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) &&
- (stcb == NULL)) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- }
sas = (struct sockaddr_storage *)&saddr->addr[0];
- limit = SCTP_BUF_LEN(m) - sizeof(sctp_assoc_t);
+ limit = *optsize - sizeof(sctp_assoc_t);
actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
if (stcb)
SCTP_TCB_UNLOCK(stcb);
- SCTP_BUF_LEN(m) = sizeof(struct sockaddr_storage) + actual;
+ *optsize = sizeof(struct sockaddr_storage) + actual;
}
break;
case SCTP_PEER_ADDR_PARAMS:
@@ -2511,57 +2410,27 @@ sctp_optsget(struct socket *so,
struct sctp_paddrparams *paddrp;
struct sctp_nets *net;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_paddrparams)) {
- error = EINVAL;
- break;
- }
- paddrp = mtod(m, struct sctp_paddrparams *);
+ SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
+ SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
net = NULL;
- if (paddrp->spp_assoc_id) {
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
- }
- SCTP_INP_RLOCK(inp);
- } else {
- stcb = sctp_findassociation_ep_asocid(inp, paddrp->spp_assoc_id, 1);
- }
+ if (stcb) {
+ net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
+ } else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
+ SCTP_INP_INCR_REF(inp);
+ stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
if (stcb == NULL) {
- error = ENOENT;
- break;
+ SCTP_INP_DECR_REF(inp);
}
}
- if ((stcb == NULL) &&
- ((((struct sockaddr *)&paddrp->spp_address)->sa_family == AF_INET) ||
- (((struct sockaddr *)&paddrp->spp_address)->sa_family == AF_INET6))) {
- /* Lookup via address */
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
- }
- SCTP_INP_RUNLOCK(inp);
- } else {
- SCTP_INP_INCR_REF(inp);
- stcb = sctp_findassociation_ep_addr(&inp,
- (struct sockaddr *)&paddrp->spp_address,
- &net, NULL, NULL);
- if (stcb == NULL) {
- SCTP_INP_DECR_REF(inp);
- }
- }
- if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- }
if (stcb) {
/* Applys to the specific association */
paddrp->spp_flags = 0;
@@ -2646,7 +2515,7 @@ sctp_optsget(struct socket *so,
SCTP_INP_RUNLOCK(inp);
}
- SCTP_BUF_LEN(m) = sizeof(struct sctp_paddrparams);
+ *optsize = sizeof(struct sctp_paddrparams);
}
break;
case SCTP_GET_PEER_ADDR_INFO:
@@ -2654,64 +2523,50 @@ sctp_optsget(struct socket *so,
struct sctp_paddrinfo *paddri;
struct sctp_nets *net;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_paddrinfo)) {
- error = EINVAL;
- break;
- }
- paddri = mtod(m, struct sctp_paddrinfo *);
+ SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
+ SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
+
net = NULL;
- if ((((struct sockaddr *)&paddri->spinfo_address)->sa_family == AF_INET) ||
- (((struct sockaddr *)&paddri->spinfo_address)->sa_family == AF_INET6)) {
- /* Lookup via address */
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- net = sctp_findnet(stcb,
- (struct sockaddr *)&paddri->spinfo_address);
- }
- SCTP_INP_RUNLOCK(inp);
- } else {
- SCTP_INP_INCR_REF(inp);
- stcb = sctp_findassociation_ep_addr(&inp,
- (struct sockaddr *)&paddri->spinfo_address,
- &net, NULL, NULL);
- if (stcb == NULL) {
- SCTP_INP_DECR_REF(inp);
- }
+ if (stcb) {
+ net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
+ } else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
+ SCTP_INP_INCR_REF(inp);
+ stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
+ if (stcb == NULL) {
+ SCTP_INP_DECR_REF(inp);
}
+ }
+ if ((stcb) && (net)) {
+ paddri->spinfo_state = net->dest_state & (SCTP_REACHABLE_MASK | SCTP_ADDR_NOHB);
+ paddri->spinfo_cwnd = net->cwnd;
+ paddri->spinfo_srtt = ((net->lastsa >> 2) + net->lastsv) >> 1;
+ paddri->spinfo_rto = net->RTO;
+ paddri->spinfo_assoc_id = sctp_get_associd(stcb);
+ SCTP_TCB_UNLOCK(stcb);
} else {
- stcb = NULL;
- }
- if ((stcb == NULL) || (net == NULL)) {
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
error = ENOENT;
- break;
}
- SCTP_BUF_LEN(m) = sizeof(struct sctp_paddrinfo);
- paddri->spinfo_state = net->dest_state & (SCTP_REACHABLE_MASK | SCTP_ADDR_NOHB);
- paddri->spinfo_cwnd = net->cwnd;
- paddri->spinfo_srtt = ((net->lastsa >> 2) + net->lastsv) >> 1;
- paddri->spinfo_rto = net->RTO;
- paddri->spinfo_assoc_id = sctp_get_associd(stcb);
- SCTP_TCB_UNLOCK(stcb);
+ *optsize = sizeof(struct sctp_paddrinfo);
}
break;
case SCTP_PCB_STATUS:
{
struct sctp_pcbinfo *spcb;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_pcbinfo)) {
- error = EINVAL;
- break;
- }
- spcb = mtod(m, struct sctp_pcbinfo *);
+ SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
sctp_fill_pcbinfo(spcb);
- SCTP_BUF_LEN(m) = sizeof(struct sctp_pcbinfo);
+ *optsize = sizeof(struct sctp_pcbinfo);
}
break;
case SCTP_STATUS:
@@ -2719,20 +2574,8 @@ sctp_optsget(struct socket *so,
struct sctp_nets *net;
struct sctp_status *sstat;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_status)) {
- error = EINVAL;
- break;
- }
- sstat = mtod(m, struct sctp_status *);
-
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else
- stcb = sctp_findassociation_ep_asocid(inp, sstat->sstat_assoc_id, 1);
+ SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
+ SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
if (stcb == NULL) {
error = EINVAL;
@@ -2773,76 +2616,38 @@ sctp_optsget(struct socket *so,
sstat->sstat_primary.spinfo_mtu = net->mtu;
sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
SCTP_TCB_UNLOCK(stcb);
- SCTP_BUF_LEN(m) = sizeof(*sstat);
+ *optsize = sizeof(*sstat);
}
break;
case SCTP_RTOINFO:
{
struct sctp_rtoinfo *srto;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_rtoinfo)) {
- error = EINVAL;
- break;
- }
- srto = mtod(m, struct sctp_rtoinfo *);
- if (srto->srto_assoc_id == 0) {
- /* Endpoint only please */
+ SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
+ SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
+
+ if (stcb) {
+ srto->srto_initial = stcb->asoc.initial_rto;
+ srto->srto_max = stcb->asoc.maxrto;
+ srto->srto_min = stcb->asoc.minrto;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
SCTP_INP_RLOCK(inp);
srto->srto_initial = inp->sctp_ep.initial_rto;
srto->srto_max = inp->sctp_ep.sctp_maxrto;
srto->srto_min = inp->sctp_ep.sctp_minrto;
SCTP_INP_RUNLOCK(inp);
- break;
- }
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else
- stcb = sctp_findassociation_ep_asocid(inp, srto->srto_assoc_id, 1);
-
- if (stcb == NULL) {
- error = EINVAL;
- break;
}
- srto->srto_initial = stcb->asoc.initial_rto;
- srto->srto_max = stcb->asoc.maxrto;
- srto->srto_min = stcb->asoc.minrto;
- SCTP_TCB_UNLOCK(stcb);
- SCTP_BUF_LEN(m) = sizeof(*srto);
+ *optsize = sizeof(*srto);
}
break;
case SCTP_ASSOCINFO:
{
struct sctp_assocparams *sasoc;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assocparams)) {
- error = EINVAL;
- break;
- }
- sasoc = mtod(m, struct sctp_assocparams *);
- stcb = NULL;
+ SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
+ SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
-
- SCTP_TCB_LOCK(stcb);
- }
- SCTP_INP_RUNLOCK(inp);
- } else if (sasoc->sasoc_assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp,
- sasoc->sasoc_assoc_id, 1);
- if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- } else {
- stcb = NULL;
- }
if (stcb) {
sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
@@ -2859,53 +2664,39 @@ sctp_optsget(struct socket *so,
sasoc->sasoc_cookie_life = inp->sctp_ep.def_cookie_life;
SCTP_INP_RUNLOCK(inp);
}
- SCTP_BUF_LEN(m) = sizeof(*sasoc);
+ *optsize = sizeof(*sasoc);
}
break;
case SCTP_DEFAULT_SEND_PARAM:
{
struct sctp_sndrcvinfo *s_info;
- if (SCTP_BUF_LEN(m) != sizeof(struct sctp_sndrcvinfo)) {
- error = EINVAL;
- break;
- }
- s_info = mtod(m, struct sctp_sndrcvinfo *);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
+ SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
+ SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
+
+ if (stcb) {
+ *s_info = stcb->asoc.def_send;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
+ *s_info = inp->def_send;
SCTP_INP_RUNLOCK(inp);
- } else
- stcb = sctp_findassociation_ep_asocid(inp, s_info->sinfo_assoc_id, 1);
-
- if (stcb == NULL) {
- error = ENOENT;
- break;
}
- /* Copy it out */
- *s_info = stcb->asoc.def_send;
- SCTP_TCB_UNLOCK(stcb);
- SCTP_BUF_LEN(m) = sizeof(*s_info);
+ *optsize = sizeof(*s_info);
}
break;
case SCTP_INITMSG:
{
struct sctp_initmsg *sinit;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_initmsg)) {
- error = EINVAL;
- break;
- }
- sinit = mtod(m, struct sctp_initmsg *);
+ SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
SCTP_INP_RLOCK(inp);
sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
SCTP_INP_RUNLOCK(inp);
- SCTP_BUF_LEN(m) = sizeof(*sinit);
+ *optsize = sizeof(*sinit);
}
break;
case SCTP_PRIMARY_ADDR:
@@ -2913,45 +2704,18 @@ sctp_optsget(struct socket *so,
{
struct sctp_setprim *ssp;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_setprim)) {
- error = EINVAL;
- break;
- }
- ssp = mtod(m, struct sctp_setprim *);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
+ SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
+ SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
+
+ if (stcb) {
+ /* simply copy out the sockaddr_storage... */
+ memcpy(&ssp->ssp_addr, &stcb->asoc.primary_destination->ro._l_addr,
+ ((struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr)->sa_len);
+ SCTP_TCB_UNLOCK(stcb);
} else {
- stcb = sctp_findassociation_ep_asocid(inp, ssp->ssp_assoc_id, 1);
- if (stcb == NULL) {
- /*
- * one last shot, try it by the
- * address in
- */
- struct sctp_nets *net;
-
- SCTP_INP_INCR_REF(inp);
- stcb = sctp_findassociation_ep_addr(&inp,
- (struct sockaddr *)&ssp->ssp_addr,
- &net, NULL, NULL);
- if (stcb == NULL) {
- SCTP_INP_DECR_REF(inp);
- }
- }
- if (stcb == NULL) {
- error = EINVAL;
- break;
- }
+ error = EINVAL;
}
- /* simply copy out the sockaddr_storage... */
- memcpy(&ssp->ssp_addr,
- &stcb->asoc.primary_destination->ro._l_addr,
- ((struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr)->sa_len);
- SCTP_TCB_UNLOCK(stcb);
- SCTP_BUF_LEN(m) = sizeof(*ssp);
+ *optsize = sizeof(*ssp);
}
break;
@@ -2962,22 +2726,19 @@ sctp_optsget(struct socket *so,
uint32_t size;
int i;
- if ((size_t)(SCTP_BUF_LEN(m)) < sizeof(*shmac)) {
- error = EINVAL;
- break;
- }
- shmac = mtod(m, struct sctp_hmacalgo *);
+ SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
+
SCTP_INP_RLOCK(inp);
hmaclist = inp->sctp_ep.local_hmacs;
if (hmaclist == NULL) {
/* no HMACs to return */
- SCTP_BUF_LEN(m) = sizeof(*shmac);
+ *optsize = sizeof(*shmac);
break;
}
/* is there room for all of the hmac ids? */
size = sizeof(*shmac) + (hmaclist->num_algo *
sizeof(shmac->shmac_idents[0]));
- if ((size_t)(SCTP_BUF_LEN(m)) < size) {
+ if ((size_t)(*optsize) < size) {
error = EINVAL;
SCTP_INP_RUNLOCK(inp);
break;
@@ -2986,36 +2747,17 @@ sctp_optsget(struct socket *so,
for (i = 0; i < hmaclist->num_algo; i++)
shmac->shmac_idents[i] = hmaclist->hmac[i];
SCTP_INP_RUNLOCK(inp);
- SCTP_BUF_LEN(m) = size;
+ *optsize = size;
break;
}
case SCTP_AUTH_ACTIVE_KEY:
{
struct sctp_authkeyid *scact;
- if ((size_t)(SCTP_BUF_LEN(m)) < sizeof(*scact)) {
- error = EINVAL;
- break;
- }
- scact = mtod(m, struct sctp_authkeyid *);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- /*
- * if one-to-one, get from the connected
- * assoc; else endpoint
- */
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else if (scact->scact_assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, scact->scact_assoc_id, 1);
- if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- }
- if (stcb != NULL) {
+ SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
+ SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
+
+ if (stcb) {
/* get the active key on the assoc */
scact->scact_keynumber = stcb->asoc.authinfo.assoc_keyid;
SCTP_TCB_UNLOCK(stcb);
@@ -3025,131 +2767,79 @@ sctp_optsget(struct socket *so,
scact->scact_keynumber = inp->sctp_ep.default_keyid;
SCTP_INP_RUNLOCK(inp);
}
- SCTP_BUF_LEN(m) = sizeof(*scact);
+ *optsize = sizeof(*scact);
break;
}
case SCTP_LOCAL_AUTH_CHUNKS:
{
struct sctp_authchunks *sac;
sctp_auth_chklist_t *chklist = NULL;
- int size = 0;
+ size_t size = 0;
- if ((size_t)(SCTP_BUF_LEN(m)) < sizeof(*sac)) {
- error = EINVAL;
- break;
- }
- sac = mtod(m, struct sctp_authchunks *);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- /*
- * if one-to-one, get from the connected
- * assoc; else endpoint
- */
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb != NULL)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else if (sac->gauth_assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, sac->gauth_assoc_id, 1);
- if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- }
- if (stcb != NULL) {
+ SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
+ SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
+
+ if (stcb) {
/* get off the assoc */
chklist = stcb->asoc.local_auth_chunks;
- if (chklist == NULL) {
- error = EINVAL;
- SCTP_TCB_UNLOCK(stcb);
- break;
- }
/* is there enough space? */
size = sctp_auth_get_chklist_size(chklist);
- if ((size_t)SCTP_BUF_LEN(m) < (sizeof(struct sctp_authchunks) + size)) {
+ if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
error = EINVAL;
- SCTP_TCB_UNLOCK(stcb);
- break;
+ } else {
+ /* copy in the chunks */
+ sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
}
- /* copy in the chunks */
- sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
SCTP_TCB_UNLOCK(stcb);
} else {
/* get off the endpoint */
SCTP_INP_RLOCK(inp);
chklist = inp->sctp_ep.local_auth_chunks;
- if (chklist == NULL) {
- error = EINVAL;
- SCTP_INP_RUNLOCK(inp);
- break;
- }
/* is there enough space? */
size = sctp_auth_get_chklist_size(chklist);
- if ((size_t)SCTP_BUF_LEN(m) < (sizeof(struct sctp_authchunks) + size)) {
+ if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
error = EINVAL;
- SCTP_INP_RUNLOCK(inp);
- break;
+ } else {
+ /* copy in the chunks */
+ sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
}
- /* copy in the chunks */
- sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
SCTP_INP_RUNLOCK(inp);
}
- SCTP_BUF_LEN(m) = sizeof(struct sctp_authchunks) + size;
+ *optsize = sizeof(struct sctp_authchunks) + size;
break;
}
case SCTP_PEER_AUTH_CHUNKS:
{
struct sctp_authchunks *sac;
sctp_auth_chklist_t *chklist = NULL;
- int size = 0;
+ size_t size = 0;
- if ((size_t)(SCTP_BUF_LEN(m)) < sizeof(*sac)) {
- error = EINVAL;
- break;
- }
- sac = mtod(m, struct sctp_authchunks *);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- /*
- * if one-to-one, get from the connected
- * assoc, else endpoint
- */
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb != NULL)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else if (sac->gauth_assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, sac->gauth_assoc_id, 1);
- }
- if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- /* get off the assoc */
- chklist = stcb->asoc.peer_auth_chunks;
- if (chklist == NULL) {
- error = EINVAL;
- SCTP_TCB_UNLOCK(stcb);
- break;
- }
- /* is there enough space? */
- size = sctp_auth_get_chklist_size(chklist);
- if ((size_t)SCTP_BUF_LEN(m) < (sizeof(struct sctp_authchunks) + size)) {
- error = EINVAL;
+ SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
+ SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
+
+ if (stcb) {
+ /* get off the assoc */
+ chklist = stcb->asoc.peer_auth_chunks;
+ /* is there enough space? */
+ size = sctp_auth_get_chklist_size(chklist);
+ if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
+ error = EINVAL;
+ } else {
+ /* copy in the chunks */
+ sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
+ }
SCTP_TCB_UNLOCK(stcb);
- break;
+ } else {
+ error = ENOENT;
}
- /* copy in the chunks */
- sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
- SCTP_TCB_UNLOCK(stcb);
- SCTP_BUF_LEN(m) = sizeof(struct sctp_authchunks) + size;
+ *optsize = sizeof(struct sctp_authchunks) + size;
break;
}
default:
error = ENOPROTOOPT;
- SCTP_BUF_LEN(m) = 0;
+ *optsize = 0;
break;
} /* end switch (sopt->sopt_name) */
return (error);
@@ -3157,31 +2847,23 @@ sctp_optsget(struct socket *so,
static int
-sctp_optsset(struct socket *so,
- int opt,
- struct mbuf **mp,
- struct thread *p
-)
+sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
+ void *p)
{
- int error, *mopt, set_opt;
- struct mbuf *m;
-
+ int error, set_opt;
+ uint32_t *mopt;
struct sctp_tcb *stcb = NULL;
struct sctp_inpcb *inp;
- if (mp == NULL) {
+ if (optval == NULL) {
return (EINVAL);
}
- m = *mp;
- if (m == NULL)
- return (EINVAL);
-
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0)
return EINVAL;
error = 0;
- switch (opt) {
+ switch (optname) {
case SCTP_NODELAY:
case SCTP_AUTOCLOSE:
case SCTP_AUTO_ASCONF:
@@ -3190,15 +2872,11 @@ sctp_optsset(struct socket *so,
case SCTP_USE_EXT_RCVINFO:
case SCTP_I_WANT_MAPPED_V4_ADDR:
/* copy in the option value */
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) {
- error = EINVAL;
- break;
- }
- mopt = mtod(m, int *);
+ SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
set_opt = 0;
if (error)
break;
- switch (opt) {
+ switch (optname) {
case SCTP_DISABLE_FRAGMENTS:
set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
break;
@@ -3240,25 +2918,19 @@ sctp_optsset(struct socket *so,
break;
case SCTP_PARTIAL_DELIVERY_POINT:
{
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(unsigned int)) {
- error = EINVAL;
- break;
- }
- inp->partial_delivery_point = *mtod(m, unsigned int *);
- SCTP_BUF_LEN(m) = sizeof(unsigned int);
+ uint32_t *value;
+
+ SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
+ inp->partial_delivery_point = *value;
}
break;
case SCTP_FRAGMENT_INTERLEAVE:
/* not yet until we re-write sctp_recvmsg() */
{
- int on_off;
+ uint32_t *on_off;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) {
- error = EINVAL;
- break;
- }
- on_off = *(mtod(m, int *));
- if (on_off) {
+ SCTP_CHECK_AND_CAST(on_off, optval, uint32_t, optsize);
+ if (*on_off) {
sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
} else {
sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
@@ -3269,37 +2941,18 @@ sctp_optsset(struct socket *so,
{
struct sctp_assoc_value *av;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) {
- error = EINVAL;
- break;
- }
- av = mtod(m, struct sctp_assoc_value *);
- stcb = sctp_findassociation_ep_asocid(inp, av->assoc_id, 1);
- if (stcb == NULL) {
- error = ENOTCONN;
- } else {
- if (sctp_cmt_on_off) {
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+ if (sctp_cmt_on_off) {
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+ if (stcb) {
stcb->asoc.sctp_cmt_on_off = (uint8_t) av->assoc_value;
+ SCTP_TCB_UNLOCK(stcb);
} else {
- if ((stcb->asoc.sctp_cmt_on_off) && (av->assoc_value == 0)) {
- stcb->asoc.sctp_cmt_on_off = 0;
- } else {
- error = EACCES;
- }
+ error = ENOTCONN;
}
- SCTP_TCB_UNLOCK(stcb);
- }
- }
- break;
- case SCTP_CMT_USE_DAC:
- {
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(unsigned int)) {
- error = EINVAL;
- break;
+ } else {
+ error = ENOPROTOOPT;
}
- sctp_cmt_sockopt_use_dac = *mtod(m, unsigned int *);
- if (sctp_cmt_sockopt_use_dac != 0)
- sctp_cmt_sockopt_use_dac = 1;
}
break;
case SCTP_CLR_STAT_LOG:
@@ -3311,24 +2964,18 @@ sctp_optsset(struct socket *so,
break;
case SCTP_CONTEXT:
{
-
struct sctp_assoc_value *av;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) {
- error = EINVAL;
- break;
- }
- av = mtod(m, struct sctp_assoc_value *);
- if (av->assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, av->assoc_id, 1);
- if (stcb == NULL) {
- error = ENOTCONN;
- } else {
- stcb->asoc.context = av->assoc_value;
- SCTP_TCB_UNLOCK(stcb);
- }
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+ if (stcb) {
+ stcb->asoc.context = av->assoc_value;
+ SCTP_TCB_UNLOCK(stcb);
} else {
+ SCTP_INP_WLOCK(inp);
inp->sctp_context = av->assoc_value;
+ SCTP_INP_WUNLOCK(inp);
}
}
break;
@@ -3336,53 +2983,29 @@ sctp_optsset(struct socket *so,
{
struct sctp_assoc_value *tm;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) {
- error = EINVAL;
- break;
- }
- tm = mtod(m, struct sctp_assoc_value *);
+ SCTP_CHECK_AND_CAST(tm, optval, struct sctp_assoc_value, optsize);
+ SCTP_FIND_STCB(inp, stcb, tm->assoc_id);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
+ if (stcb) {
+ stcb->asoc.delayed_ack = tm->assoc_value;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
SCTP_INP_WLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- stcb->asoc.delayed_ack = tm->assoc_value;
- SCTP_TCB_UNLOCK(stcb);
- } else {
- inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(tm->assoc_value);
- }
+ inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(tm->assoc_value);
SCTP_INP_WUNLOCK(inp);
- } else {
- if (tm->assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, tm->assoc_id, 1);
- if (stcb == NULL) {
- error = ENOTCONN;
- } else {
- stcb->asoc.delayed_ack = tm->assoc_value;
- SCTP_TCB_UNLOCK(stcb);
- }
- } else {
- SCTP_INP_WLOCK(inp);
- inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(tm->assoc_value);
- SCTP_INP_WUNLOCK(inp);
- }
}
+ break;
}
- break;
-
case SCTP_AUTH_CHUNK:
{
struct sctp_authchunk *sauth;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(*sauth)) {
- error = EINVAL;
- break;
- }
- sauth = mtod(m, struct sctp_authchunk *);
- if (sctp_auth_add_chunk(sauth->sauth_chunk,
- inp->sctp_ep.local_auth_chunks))
+ SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
+
+ SCTP_INP_WLOCK(inp);
+ if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks))
error = EINVAL;
+ SCTP_INP_WUNLOCK(inp);
break;
}
case SCTP_AUTH_KEY:
@@ -3391,32 +3014,13 @@ sctp_optsset(struct socket *so,
struct sctp_keyhead *shared_keys;
sctp_sharedkey_t *shared_key;
sctp_key_t *key = NULL;
- int size;
+ size_t size;
- size = SCTP_BUF_LEN(m) - sizeof(*sca);
- if (size < 0) {
- error = EINVAL;
- break;
- }
- sca = mtod(m, struct sctp_authkey *);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- /*
- * if one-to-one, set it on the connected
- * assoc; else endpoint
- */
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else if (sca->sca_assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, sca->sca_assoc_id, 1);
- if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- }
- if (stcb != NULL) {
+ SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
+ SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id)
+ size = optsize - sizeof(*sca);
+
+ if (stcb) {
/* set it on the assoc */
shared_keys = &stcb->asoc.shared_keys;
/* clear the cached keys for this key id */
@@ -3445,7 +3049,7 @@ sctp_optsset(struct socket *so,
sctp_insert_sharedkey(shared_keys, shared_key);
SCTP_TCB_UNLOCK(stcb);
} else {
- /* ste it on the endpoint */
+ /* set it on the endpoint */
SCTP_INP_WLOCK(inp);
shared_keys = &inp->sctp_ep.shared_keys;
/*
@@ -3484,15 +3088,10 @@ sctp_optsset(struct socket *so,
struct sctp_hmacalgo *shmac;
sctp_hmaclist_t *hmaclist;
uint32_t hmacid;
- int size, i;
+ size_t size, i;
- size = SCTP_BUF_LEN(m) - sizeof(*shmac);
- if (size < 0) {
- error = EINVAL;
- break;
- }
- shmac = mtod(m, struct sctp_hmacalgo *);
- size = size / sizeof(shmac->shmac_idents[0]);
+ SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
+ size = (optsize - sizeof(*shmac)) / sizeof(shmac->shmac_idents[0]);
hmaclist = sctp_alloc_hmaclist(size);
if (hmaclist == NULL) {
error = ENOMEM;
@@ -3520,30 +3119,11 @@ sctp_optsset(struct socket *so,
{
struct sctp_authkeyid *scact;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(*scact)) {
- error = EINVAL;
- break;
- }
- scact = mtod(m, struct sctp_authkeyid *);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- /*
- * if one-to-one, set it on the connected
- * assoc; else endpoint
- */
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else if (scact->scact_assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, scact->scact_assoc_id, 1);
- if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- }
+ 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 != NULL) {
+ if (stcb) {
/* set the active key on the assoc */
if (sctp_auth_setactivekey(stcb, scact->scact_keynumber))
error = EINVAL;
@@ -3561,30 +3141,11 @@ sctp_optsset(struct socket *so,
{
struct sctp_authkeyid *scdel;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(*scdel)) {
- error = EINVAL;
- break;
- }
- scdel = mtod(m, struct sctp_authkeyid *);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- /*
- * if one-to-one, delete from the connected
- * assoc; else endpoint
- */
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else if (scdel->scact_assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, scdel->scact_assoc_id, 1);
- if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- }
+ 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 != NULL) {
+ if (stcb) {
if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber))
error = EINVAL;
SCTP_TCB_UNLOCK(stcb);
@@ -3603,20 +3164,9 @@ sctp_optsset(struct socket *so,
uint8_t send_in = 0, send_tsn = 0, send_out = 0;
int i;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_stream_reset)) {
- error = EINVAL;
- break;
- }
- strrst = mtod(m, struct sctp_stream_reset *);
+ SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_stream_reset, optsize);
+ SCTP_FIND_STCB(inp, stcb, strrst->strrst_assoc_id);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else
- stcb = sctp_findassociation_ep_asocid(inp, strrst->strrst_assoc_id, 1);
if (stcb == NULL) {
error = ENOENT;
break;
@@ -3676,23 +3226,23 @@ sctp_optsset(struct socket *so,
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ);
SCTP_TCB_UNLOCK(stcb);
-
}
break;
+
case SCTP_CONNECT_X:
- if ((size_t)SCTP_BUF_LEN(m) < (sizeof(int) + sizeof(struct sockaddr_in))) {
+ if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
error = EINVAL;
break;
}
- error = sctp_do_connect_x(so, inp, m, p, 0);
+ error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
break;
case SCTP_CONNECT_X_DELAYED:
- if ((size_t)SCTP_BUF_LEN(m) < (sizeof(int) + sizeof(struct sockaddr_in))) {
+ if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
error = EINVAL;
break;
}
- error = sctp_do_connect_x(so, inp, m, p, 1);
+ error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
break;
case SCTP_CONNECT_X_COMPLETE:
@@ -3700,11 +3250,9 @@ sctp_optsset(struct socket *so,
struct sockaddr *sa;
struct sctp_nets *net;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sockaddr_in)) {
- error = EINVAL;
- break;
- }
- sa = mtod(m, struct sockaddr *);
+ /* FIXME MT: check correct? */
+ SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
+
/* find tcb */
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
SCTP_INP_RLOCK(inp);
@@ -3715,6 +3263,13 @@ sctp_optsset(struct socket *so,
}
SCTP_INP_RUNLOCK(inp);
} else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
SCTP_INP_INCR_REF(inp);
stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
if (stcb == NULL) {
@@ -3747,8 +3302,9 @@ sctp_optsset(struct socket *so,
{
uint8_t *burst;
+ SCTP_CHECK_AND_CAST(burst, optval, uint8_t, optsize);
+
SCTP_INP_WLOCK(inp);
- burst = mtod(m, uint8_t *);
if (*burst) {
inp->sctp_ep.max_burst = *burst;
}
@@ -3760,52 +3316,30 @@ sctp_optsset(struct socket *so,
uint32_t *segsize;
int ovh;
+ SCTP_CHECK_AND_CAST(segsize, optval, uint32_t, optsize);
+
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
ovh = SCTP_MED_OVERHEAD;
} else {
ovh = SCTP_MED_V4_OVERHEAD;
}
- segsize = mtod(m, uint32_t *);
- if (*segsize < 1) {
- error = EINVAL;
- break;
- }
SCTP_INP_WLOCK(inp);
- inp->sctp_frag_point = (*segsize + ovh);
- SCTP_INP_WUNLOCK(inp);
- }
- break;
- case SCTP_SET_DEBUG_LEVEL:
-#ifdef SCTP_DEBUG
- {
- uint32_t *level;
-
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(uint32_t)) {
+ /* FIXME MT: Why is this not allowed? */
+ if (*segsize) {
+ inp->sctp_frag_point = (*segsize + ovh);
+ } else {
error = EINVAL;
- break;
}
- level = mtod(m, uint32_t *);
- error = 0;
- sctp_debug_on = (*level & (SCTP_DEBUG_ALL |
- SCTP_DEBUG_NOISY));
- printf("SETTING DEBUG LEVEL to %x\n",
- (uint32_t) sctp_debug_on);
-
+ SCTP_INP_WUNLOCK(inp);
}
-#else
- error = EOPNOTSUPP;
-#endif /* SCTP_DEBUG */
break;
case SCTP_EVENTS:
{
struct sctp_event_subscribe *events;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_event_subscribe)) {
- error = EINVAL;
- break;
- }
+ SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
+
SCTP_INP_WLOCK(inp);
- events = mtod(m, struct sctp_event_subscribe *);
if (events->sctp_data_io_event) {
sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
} else {
@@ -3873,69 +3407,43 @@ sctp_optsset(struct socket *so,
{
struct sctp_setadaptation *adap_bits;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_setadaptation)) {
- error = EINVAL;
- break;
- }
+ SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
SCTP_INP_WLOCK(inp);
- adap_bits = mtod(m, struct sctp_setadaptation *);
inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
SCTP_INP_WUNLOCK(inp);
}
break;
+#ifdef SCTP_DEBUG
case SCTP_SET_INITIAL_DBG_SEQ:
{
uint32_t *vvv;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(uint32_t)) {
- error = EINVAL;
- break;
- }
+ SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
SCTP_INP_WLOCK(inp);
- vvv = mtod(m, uint32_t *);
inp->sctp_ep.initial_sequence_debug = *vvv;
SCTP_INP_WUNLOCK(inp);
}
break;
+#endif
case SCTP_DEFAULT_SEND_PARAM:
{
struct sctp_sndrcvinfo *s_info;
- if (SCTP_BUF_LEN(m) != sizeof(struct sctp_sndrcvinfo)) {
- error = EINVAL;
- break;
- }
- s_info = mtod(m, struct sctp_sndrcvinfo *);
+ SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
+ SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else {
- if (s_info->sinfo_assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, s_info->sinfo_assoc_id, 1);
+ if (stcb) {
+ if (s_info->sinfo_stream <= stcb->asoc.streamoutcnt) {
+ stcb->asoc.def_send = *s_info;
} else {
- stcb = NULL;
+ error = EINVAL;
}
- }
- if ((s_info->sinfo_assoc_id == 0) &&
- (stcb == NULL)) {
- inp->def_send = *s_info;
- } else if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- /* Validate things */
- if (s_info->sinfo_stream > stcb->asoc.streamoutcnt) {
SCTP_TCB_UNLOCK(stcb);
- error = EINVAL;
- break;
+ } else {
+ SCTP_INP_WLOCK(inp);
+ inp->def_send = *s_info;
+ SCTP_INP_WUNLOCK(inp);
}
- /* Copy it in */
- stcb->asoc.def_send = *s_info;
- SCTP_TCB_UNLOCK(stcb);
}
break;
case SCTP_PEER_ADDR_PARAMS:
@@ -3944,52 +3452,29 @@ sctp_optsset(struct socket *so,
struct sctp_paddrparams *paddrp;
struct sctp_nets *net;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_paddrparams)) {
- error = EINVAL;
- break;
- }
- paddrp = mtod(m, struct sctp_paddrparams *);
+ SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
+ SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
net = NULL;
- if (paddrp->spp_assoc_id) {
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
- }
- SCTP_INP_RUNLOCK(inp);
- } else {
- stcb = sctp_findassociation_ep_asocid(inp, paddrp->spp_assoc_id, 1);
- }
+ if (stcb) {
+ net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
+ } else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
+ SCTP_INP_INCR_REF(inp);
+ stcb = sctp_findassociation_ep_addr(&inp,
+ (struct sockaddr *)&paddrp->spp_address,
+ &net, NULL, NULL);
if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- }
- if ((stcb == NULL) &&
- ((((struct sockaddr *)&paddrp->spp_address)->sa_family == AF_INET) ||
- (((struct sockaddr *)&paddrp->spp_address)->sa_family == AF_INET6))) {
- /* Lookup via address */
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- net = sctp_findnet(stcb,
- (struct sockaddr *)&paddrp->spp_address);
- }
- SCTP_INP_RUNLOCK(inp);
- } else {
- SCTP_INP_INCR_REF(inp);
- stcb = sctp_findassociation_ep_addr(&inp,
- (struct sockaddr *)&paddrp->spp_address,
- &net, NULL, NULL);
- if (stcb == NULL) {
- SCTP_INP_DECR_REF(inp);
- }
+ SCTP_INP_DECR_REF(inp);
}
}
+
+
if (stcb) {
/************************TCB SPECIFIC SET ******************/
/* sack delay first */
@@ -4137,12 +3622,19 @@ sctp_optsset(struct socket *so,
{
struct sctp_rtoinfo *srto;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_rtoinfo)) {
- error = EINVAL;
- break;
- }
- srto = mtod(m, struct sctp_rtoinfo *);
- if (srto->srto_assoc_id == 0) {
+ SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
+ SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
+
+ if (stcb) {
+ /* Set in ms we hope :-) */
+ if (srto->srto_initial > 10)
+ stcb->asoc.initial_rto = srto->srto_initial;
+ if (srto->srto_max > 10)
+ stcb->asoc.maxrto = srto->srto_max;
+ if (srto->srto_min > 10)
+ stcb->asoc.minrto = srto->srto_min;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
SCTP_INP_WLOCK(inp);
/*
* If we have a null asoc, its default for
@@ -4155,56 +3647,16 @@ sctp_optsset(struct socket *so,
if (srto->srto_min > 10)
inp->sctp_ep.sctp_minrto = srto->srto_min;
SCTP_INP_WUNLOCK(inp);
- break;
- }
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else
- stcb = sctp_findassociation_ep_asocid(inp, srto->srto_assoc_id, 1);
- if (stcb == NULL) {
- error = EINVAL;
- break;
}
- /* Set in ms we hope :-) */
- if (srto->srto_initial > 10)
- stcb->asoc.initial_rto = srto->srto_initial;
- if (srto->srto_max > 10)
- stcb->asoc.maxrto = srto->srto_max;
- if (srto->srto_min > 10)
- stcb->asoc.minrto = srto->srto_min;
- SCTP_TCB_UNLOCK(stcb);
}
break;
case SCTP_ASSOCINFO:
{
struct sctp_assocparams *sasoc;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assocparams)) {
- error = EINVAL;
- break;
- }
- sasoc = mtod(m, struct sctp_assocparams *);
- if (sasoc->sasoc_assoc_id) {
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else
- stcb = sctp_findassociation_ep_asocid(inp,
- sasoc->sasoc_assoc_id, 1);
- if (stcb == NULL) {
- error = ENOENT;
- break;
- }
- } else {
- stcb = NULL;
- }
+ SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
+ SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
+
if (stcb) {
if (sasoc->sasoc_asocmaxrxt)
stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
@@ -4231,11 +3683,7 @@ sctp_optsset(struct socket *so,
{
struct sctp_initmsg *sinit;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_initmsg)) {
- error = EINVAL;
- break;
- }
- sinit = mtod(m, struct sctp_initmsg *);
+ SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
SCTP_INP_WLOCK(inp);
if (sinit->sinit_num_ostreams)
inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
@@ -4251,6 +3699,7 @@ sctp_optsset(struct socket *so,
* We must be at least a 100ms (we set in
* ticks)
*/
+ /* FIXME MT: What is this? */
inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
SCTP_INP_WUNLOCK(inp);
}
@@ -4260,61 +3709,47 @@ sctp_optsset(struct socket *so,
struct sctp_setprim *spa;
struct sctp_nets *net, *lnet;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_setprim)) {
- error = EINVAL;
- break;
- }
- spa = mtod(m, struct sctp_setprim *);
+ SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
+ SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- } else {
- error = EINVAL;
- break;
- }
- SCTP_INP_RUNLOCK(inp);
- } else
- stcb = sctp_findassociation_ep_asocid(inp, spa->ssp_assoc_id, 1);
- if (stcb == NULL) {
- /* One last shot */
+ net = NULL;
+ if (stcb) {
+ net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
+ } else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
SCTP_INP_INCR_REF(inp);
stcb = sctp_findassociation_ep_addr(&inp,
(struct sockaddr *)&spa->ssp_addr,
&net, NULL, NULL);
if (stcb == NULL) {
SCTP_INP_DECR_REF(inp);
- error = EINVAL;
- break;
- }
- } else {
- /*
- * find the net, associd or connected lookup
- * type
- */
- net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
- if (net == NULL) {
- SCTP_TCB_UNLOCK(stcb);
- error = EINVAL;
- break;
}
}
- if ((net != stcb->asoc.primary_destination) &&
- (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
- /* Ok we need to set it */
- lnet = stcb->asoc.primary_destination;
- if (sctp_set_primary_addr(stcb,
- (struct sockaddr *)NULL,
- net) == 0) {
- if (net->dest_state & SCTP_ADDR_SWITCH_PRIMARY) {
- net->dest_state |= SCTP_ADDR_DOUBLE_SWITCH;
+
+ if ((stcb) && (net)) {
+ if ((net != stcb->asoc.primary_destination) &&
+ (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
+ /* Ok we need to set it */
+ lnet = stcb->asoc.primary_destination;
+ if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
+ if (net->dest_state & SCTP_ADDR_SWITCH_PRIMARY) {
+ net->dest_state |= SCTP_ADDR_DOUBLE_SWITCH;
+ }
+ net->dest_state |= SCTP_ADDR_SWITCH_PRIMARY;
}
- net->dest_state |= SCTP_ADDR_SWITCH_PRIMARY;
}
+ } else {
+ error = EINVAL;
+ }
+ if (stcb) {
+ SCTP_TCB_UNLOCK(stcb);
}
- SCTP_TCB_UNLOCK(stcb);
}
break;
@@ -4322,26 +3757,14 @@ sctp_optsset(struct socket *so,
{
struct sctp_setpeerprim *sspp;
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_setpeerprim)) {
- error = EINVAL;
- break;
- }
- sspp = mtod(m, struct sctp_setpeerprim *);
-
+ SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
+ SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
- SCTP_INP_RLOCK(inp);
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_UNLOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
- } else
- stcb = sctp_findassociation_ep_asocid(inp, sspp->sspp_assoc_id, 1);
- if (stcb == NULL) {
- error = EINVAL;
- break;
- }
- if (sctp_set_primary_ip_address_sa(stcb, (struct sockaddr *)&sspp->sspp_addr) != 0) {
+ if (stcb) {
+ if (sctp_set_primary_ip_address_sa(stcb, (struct sockaddr *)&sspp->sspp_addr) != 0) {
+ error = EINVAL;
+ }
+ } else {
error = EINVAL;
}
SCTP_TCB_UNLOCK(stcb);
@@ -4353,16 +3776,13 @@ sctp_optsset(struct socket *so,
struct sockaddr *addr_touse;
struct sockaddr_in sin;
+ SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
+
/* see if we're bound all already! */
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
error = EINVAL;
break;
}
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_getaddresses)) {
- error = EINVAL;
- break;
- }
- addrs = mtod(m, struct sctp_getaddresses *);
addr_touse = addrs->addr;
if (addrs->addr->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
@@ -4429,16 +3849,12 @@ sctp_optsset(struct socket *so,
struct sockaddr *addr_touse;
struct sockaddr_in sin;
+ SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
/* see if we're bound all already! */
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
error = EINVAL;
break;
}
- if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_getaddresses)) {
- error = EINVAL;
- break;
- }
- addrs = mtod(m, struct sctp_getaddresses *);
addr_touse = addrs->addr;
if (addrs->addr->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
@@ -4480,9 +3896,11 @@ extern int sctp_chatty_mbuf;
int
sctp_ctloutput(struct socket *so, struct sockopt *sopt)
{
- struct mbuf *m = NULL;
+ void *optval = NULL;
+ size_t optsize = 0;
struct sctp_inpcb *inp;
- int error;
+ void *p;
+ int error = 0;
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0) {
@@ -4499,40 +3917,31 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
error = ip_ctloutput(so, sopt);
return (error);
}
- if (sopt->sopt_valsize) {
- if (sopt->sopt_valsize < MLEN) {
- m = sctp_get_mbuf_for_msg(1, 0, M_WAIT, 1, MT_DATA);
- } else {
- m = sctp_get_mbuf_for_msg(sopt->sopt_valsize, 0, M_WAIT, 1, MT_DATA);
- }
- if (m == NULL) {
- sctp_m_freem(m);
+ optsize = sopt->sopt_valsize;
+ if (optsize) {
+ SCTP_MALLOC(optval, void *, optsize, "SCTPSockOpt");
+ if (optval == NULL) {
return (ENOBUFS);
}
- if (sopt->sopt_valsize > M_TRAILINGSPACE(m)) {
- /* Limit to actual size gotten */
- sopt->sopt_valsize = M_TRAILINGSPACE(m);
- }
- error = sooptcopyin(sopt, mtod(m, caddr_t), sopt->sopt_valsize,
- sopt->sopt_valsize);
+ error = sooptcopyin(sopt, optval, optsize, optsize);
if (error) {
- (void)sctp_m_free(m);
+ SCTP_FREE(optval);
goto out;
}
- SCTP_BUF_LEN(m) = sopt->sopt_valsize;
}
+ p = (void *)sopt->sopt_td;
if (sopt->sopt_dir == SOPT_SET) {
- error = sctp_optsset(so, sopt->sopt_name, &m, sopt->sopt_td);
+ error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
} else if (sopt->sopt_dir == SOPT_GET) {
- error = sctp_optsget(so, sopt->sopt_name, &m, sopt->sopt_td);
+ error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
} else {
error = EINVAL;
}
- if ((error == 0) && (m != NULL)) {
- error = sooptcopyout(sopt, mtod(m, caddr_t), SCTP_BUF_LEN(m));
- sctp_m_freem(m);
- } else if (m != NULL) {
- sctp_m_freem(m);
+ if ((error == 0) && (optval != NULL)) {
+ error = sooptcopyout(sopt, optval, optsize);
+ SCTP_FREE(optval);
+ } else if (optval != NULL) {
+ SCTP_FREE(optval);
}
out:
return (error);
@@ -4596,8 +4005,9 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_INP_RUNLOCK(inp);
} else {
/*
- * Raise the count a second time, since on sucess
- * f-a-ep_addr will decrement it.
+ * We increment here since sctp_findassociation_ep_addr()
+ * wil do a decrement if it finds the stcb as long as the
+ * locked tcb (last argument) is NOT a TCB.. aka NULL.
*/
SCTP_INP_INCR_REF(inp);
stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
@@ -4677,12 +4087,13 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
/* We must do a bind. */
+ SOCK_UNLOCK(so);
SCTP_INP_RUNLOCK(inp);
if ((error = sctp_inpcb_bind(so, NULL, p))) {
/* bind error, probably perm */
- SOCK_UNLOCK(so);
return (error);
}
+ SOCK_LOCK(so);
} else {
SCTP_INP_RUNLOCK(inp);
}
@@ -4712,7 +4123,6 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
int error;
-
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0) {
diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h
index 8cfe411..5463673 100644
--- a/sys/netinet/sctp_var.h
+++ b/sys/netinet/sctp_var.h
@@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$");
#ifndef _NETINET_SCTP_VAR_H_
#define _NETINET_SCTP_VAR_H_
-#include <sys/socketvar.h>
+
#include <netinet/sctp_uio.h>
/* SCTP Kernel structures */
@@ -250,77 +250,75 @@ extern uint32_t sctp_system_free_resc_limit;
*/
#define sctp_free_a_readq(_stcb, _readq) { \
- SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_readq, (_readq)); \
- SCTP_DECR_READQ_COUNT(); \
+ SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_readq, (_readq)); \
+ SCTP_DECR_READQ_COUNT(); \
}
#define sctp_alloc_a_readq(_stcb, _readq) { \
- (_readq) = (struct sctp_queued_to_read *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_readq); \
+ (_readq) = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_readq, struct sctp_queued_to_read); \
if ((_readq)) { \
SCTP_INCR_READQ_COUNT(); \
} \
}
-
-
#define sctp_free_a_strmoq(_stcb, _strmoq) { \
- if (((_stcb)->asoc.free_strmoq_cnt > sctp_asoc_free_resc_limit) || \
- (sctppcbinfo.ipi_free_strmoq > sctp_system_free_resc_limit)) { \
+ if (((_stcb)->asoc.free_strmoq_cnt > sctp_asoc_free_resc_limit) || \
+ (sctppcbinfo.ipi_free_strmoq > sctp_system_free_resc_limit)) { \
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_strmoq, (_strmoq)); \
SCTP_DECR_STRMOQ_COUNT(); \
- } else { \
+ } else { \
TAILQ_INSERT_TAIL(&(_stcb)->asoc.free_strmoq, (_strmoq), next); \
- (_stcb)->asoc.free_strmoq_cnt++; \
- atomic_add_int(&sctppcbinfo.ipi_free_strmoq, 1); \
- } \
+ (_stcb)->asoc.free_strmoq_cnt++; \
+ atomic_add_int(&sctppcbinfo.ipi_free_strmoq, 1); \
+ } \
}
#define sctp_alloc_a_strmoq(_stcb, _strmoq) { \
- if(TAILQ_EMPTY(&(_stcb)->asoc.free_strmoq)) { \
- (_strmoq) = (struct sctp_stream_queue_pending *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_strmoq); \
- if ((_strmoq)) { \
- SCTP_INCR_STRMOQ_COUNT(); \
+ if (TAILQ_EMPTY(&(_stcb)->asoc.free_strmoq)) { \
+ (_strmoq) = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_strmoq, struct sctp_stream_queue_pending); \
+ if ((_strmoq)) { \
+ SCTP_INCR_STRMOQ_COUNT(); \
+ } \
+ } else { \
+ (_strmoq) = TAILQ_FIRST(&(_stcb)->asoc.free_strmoq); \
+ TAILQ_REMOVE(&(_stcb)->asoc.free_strmoq, (_strmoq), next); \
+ atomic_subtract_int(&sctppcbinfo.ipi_free_strmoq, 1); \
+ (_stcb)->asoc.free_strmoq_cnt--; \
} \
- } else { \
- (_strmoq) = TAILQ_FIRST(&(_stcb)->asoc.free_strmoq); \
- TAILQ_REMOVE(&(_stcb)->asoc.free_strmoq, (_strmoq), next); \
- atomic_subtract_int(&sctppcbinfo.ipi_free_strmoq, 1); \
- (_stcb)->asoc.free_strmoq_cnt--; \
- } \
}
#define sctp_free_a_chunk(_stcb, _chk) { \
- if (((_stcb)->asoc.free_chunk_cnt > sctp_asoc_free_resc_limit) || \
- (sctppcbinfo.ipi_free_chunks > sctp_system_free_resc_limit)) { \
+ if (((_stcb)->asoc.free_chunk_cnt > sctp_asoc_free_resc_limit) || \
+ (sctppcbinfo.ipi_free_chunks > sctp_system_free_resc_limit)) { \
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, (_chk)); \
SCTP_DECR_CHK_COUNT(); \
- } else { \
+ } else { \
TAILQ_INSERT_TAIL(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \
- (_stcb)->asoc.free_chunk_cnt++; \
- atomic_add_int(&sctppcbinfo.ipi_free_chunks, 1); \
- } \
+ (_stcb)->asoc.free_chunk_cnt++; \
+ atomic_add_int(&sctppcbinfo.ipi_free_chunks, 1); \
+ } \
}
#define sctp_alloc_a_chunk(_stcb, _chk) { \
- if(TAILQ_EMPTY(&(_stcb)->asoc.free_chunks)) { \
- (_chk) = (struct sctp_tmit_chunk *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_chunk); \
- if ((_chk)) { \
- SCTP_INCR_CHK_COUNT(); \
+ if (TAILQ_EMPTY(&(_stcb)->asoc.free_chunks)) { \
+ (_chk) = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_chunk, struct sctp_tmit_chunk); \
+ if ((_chk)) { \
+ SCTP_INCR_CHK_COUNT(); \
+ } \
+ } else { \
+ (_chk) = TAILQ_FIRST(&(_stcb)->asoc.free_chunks); \
+ TAILQ_REMOVE(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \
+ atomic_subtract_int(&sctppcbinfo.ipi_free_chunks, 1); \
+ (_stcb)->asoc.free_chunk_cnt--; \
} \
- } else { \
- (_chk) = TAILQ_FIRST(&(_stcb)->asoc.free_chunks); \
- TAILQ_REMOVE(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \
- atomic_subtract_int(&sctppcbinfo.ipi_free_chunks, 1); \
- (_stcb)->asoc.free_chunk_cnt--; \
- } \
}
#define sctp_free_remote_addr(__net) { \
if ((__net)) { \
- if (atomic_fetchadd_int(&(__net)->ref_count, -1) == 1) { \
+ if (atomic_fetchadd_int(&(__net)->ref_count, -1) == 1) { \
SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \
SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \
SCTP_OS_TIMER_STOP(&(__net)->fr_timer.timer); \
@@ -332,37 +330,37 @@ extern uint32_t sctp_system_free_resc_limit;
}
#define sctp_sbfree(ctl, stcb, sb, m) { \
- uint32_t val; \
- val = atomic_fetchadd_int(&(sb)->sb_cc,-(SCTP_BUF_LEN((m)))); \
- if(val < SCTP_BUF_LEN((m))) { \
- panic("sb_cc goes negative"); \
- } \
- val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-(MSIZE)); \
- if(val < MSIZE) { \
- panic("sb_mbcnt goes negative"); \
- } \
- if (SCTP_BUF_IS_EXTENDED(m)) { \
- val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-(SCTP_BUF_EXTEND_SIZE(m))); \
- if(val < SCTP_BUF_EXTEND_SIZE(m)) { \
- panic("sb_mbcnt goes negative2"); \
- } \
- } \
- if (((ctl)->do_not_ref_stcb == 0) && stcb) {\
- val = atomic_fetchadd_int(&(stcb)->asoc.sb_cc,-(SCTP_BUF_LEN((m)))); \
- if(val < SCTP_BUF_LEN((m))) {\
- panic("stcb->sb_cc goes negative"); \
- } \
- val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-(MSIZE)); \
- if(val < MSIZE) { \
- panic("asoc->mbcnt goes negative"); \
- } \
+ uint32_t val; \
+ val = atomic_fetchadd_int(&(sb)->sb_cc,-(SCTP_BUF_LEN((m)))); \
+ if (val < SCTP_BUF_LEN((m))) { \
+ panic("sb_cc goes negative"); \
+ } \
+ val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-(MSIZE)); \
+ if (val < MSIZE) { \
+ panic("sb_mbcnt goes negative"); \
+ } \
+ if (SCTP_BUF_IS_EXTENDED(m)) { \
+ val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-(SCTP_BUF_EXTEND_SIZE(m))); \
+ if (val < SCTP_BUF_EXTEND_SIZE(m)) { \
+ panic("sb_mbcnt goes negative2"); \
+ } \
+ } \
+ if (((ctl)->do_not_ref_stcb == 0) && stcb) {\
+ val = atomic_fetchadd_int(&(stcb)->asoc.sb_cc,-(SCTP_BUF_LEN((m)))); \
+ if (val < SCTP_BUF_LEN((m))) {\
+ panic("stcb->sb_cc goes negative"); \
+ } \
+ val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-(MSIZE)); \
+ if (val < MSIZE) { \
+ panic("asoc->mbcnt goes negative"); \
+ } \
if (SCTP_BUF_IS_EXTENDED(m)) { \
- val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-(SCTP_BUF_EXTEND_SIZE(m))); \
- if(val < SCTP_BUF_EXTEND_SIZE(m)) { \
+ val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-(SCTP_BUF_EXTEND_SIZE(m))); \
+ if (val < SCTP_BUF_EXTEND_SIZE(m)) { \
panic("assoc stcb->mbcnt would go negative"); \
- } \
- } \
- } \
+ } \
+ } \
+ } \
if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \
SCTP_BUF_TYPE(m) != MT_OOBDATA) \
atomic_subtract_int(&(sb)->sb_ctl,SCTP_BUF_LEN((m))); \
@@ -374,12 +372,12 @@ extern uint32_t sctp_system_free_resc_limit;
atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \
if (SCTP_BUF_IS_EXTENDED(m)) \
atomic_add_int(&(sb)->sb_mbcnt,SCTP_BUF_EXTEND_SIZE(m)); \
- if(stcb) { \
- atomic_add_int(&(stcb)->asoc.sb_cc,SCTP_BUF_LEN((m))); \
- atomic_add_int(&(stcb)->asoc.sb_mbcnt, MSIZE); \
- if (SCTP_BUF_IS_EXTENDED(m)) \
- atomic_add_int(&(stcb)->asoc.sb_mbcnt,SCTP_BUF_EXTEND_SIZE(m)); \
- } \
+ if (stcb) { \
+ atomic_add_int(&(stcb)->asoc.sb_cc,SCTP_BUF_LEN((m))); \
+ atomic_add_int(&(stcb)->asoc.sb_mbcnt, MSIZE); \
+ if (SCTP_BUF_IS_EXTENDED(m)) \
+ atomic_add_int(&(stcb)->asoc.sb_mbcnt,SCTP_BUF_EXTEND_SIZE(m)); \
+ } \
if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \
SCTP_BUF_TYPE(m) != MT_OOBDATA) \
atomic_add_int(&(sb)->sb_ctl,SCTP_BUF_LEN((m))); \
@@ -399,14 +397,14 @@ extern uint32_t sctp_system_free_resc_limit;
}
#define sctp_mbuf_crush(data) do { \
- struct mbuf *_m; \
+ struct mbuf *_m; \
+ _m = (data); \
+ while(_m && (SCTP_BUF_LEN(_m) == 0)) { \
+ (data) = SCTP_BUF_NEXT(_m); \
+ SCTP_BUF_NEXT(_m) = NULL; \
+ sctp_m_free(_m); \
_m = (data); \
- while(_m && (SCTP_BUF_LEN(_m) == 0)) { \
- (data) = SCTP_BUF_NEXT(_m); \
- SCTP_BUF_NEXT(_m) = NULL; \
- sctp_m_free(_m); \
- _m = (data); \
- } \
+ } \
} while (0)
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index bbefbb6..8372ba6 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2001-2007, 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:
@@ -1104,6 +1104,16 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
asoc->authinfo.recv_key = NULL;
asoc->authinfo.recv_keyid = 0;
LIST_INIT(&asoc->shared_keys);
+ asoc->marked_retrans = 0;
+ asoc->timoinit = 0;
+ asoc->timodata = 0;
+ asoc->timosack = 0;
+ asoc->timoshutdown = 0;
+ asoc->timoheartbeat = 0;
+ asoc->timocookie = 0;
+ asoc->timoshutdownack = 0;
+ SCTP_GETTIME_TIMEVAL(&asoc->start_time);
+ SCTP_GETTIME_TIMEVAL(&asoc->discontinuity_time);
return (0);
}
@@ -1146,7 +1156,7 @@ sctp_handle_addr_wq(void)
return;
}
LIST_REMOVE(wi, sctp_nxt_addr);
- if (!LIST_EMPTY(&sctppcbinfo.addr_wq)) {
+ if (!SCTP_LIST_EMPTY(&sctppcbinfo.addr_wq)) {
sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
(struct sctp_inpcb *)NULL,
(struct sctp_tcb *)NULL,
@@ -1281,6 +1291,7 @@ sctp_timeout_handler(void *t)
break;
case SCTP_TIMER_TYPE_SEND:
SCTP_STAT_INCR(sctps_timodata);
+ stcb->asoc.timodata++;
stcb->asoc.num_send_timers_up--;
if (stcb->asoc.num_send_timers_up < 0) {
stcb->asoc.num_send_timers_up = 0;
@@ -1312,6 +1323,7 @@ sctp_timeout_handler(void *t)
break;
case SCTP_TIMER_TYPE_INIT:
SCTP_STAT_INCR(sctps_timoinit);
+ stcb->asoc.timoinit++;
if (sctp_t1init_timer(inp, stcb, net)) {
/* no need to unlock on tcb its gone */
goto out_decr;
@@ -1321,6 +1333,7 @@ sctp_timeout_handler(void *t)
break;
case SCTP_TIMER_TYPE_RECV:
SCTP_STAT_INCR(sctps_timosack);
+ stcb->asoc.timosack++;
sctp_send_sack(stcb);
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
@@ -1333,6 +1346,7 @@ sctp_timeout_handler(void *t)
goto out_decr;
}
SCTP_STAT_INCR(sctps_timoshutdown);
+ stcb->asoc.timoshutdown++;
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
@@ -1344,6 +1358,7 @@ sctp_timeout_handler(void *t)
int cnt_of_unconf = 0;
SCTP_STAT_INCR(sctps_timoheartbeat);
+ stcb->asoc.timoheartbeat++;
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
(net->dest_state & SCTP_ADDR_REACHABLE)) {
@@ -1370,6 +1385,7 @@ sctp_timeout_handler(void *t)
goto out_decr;
}
SCTP_STAT_INCR(sctps_timocookie);
+ stcb->asoc.timocookie++;
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
@@ -1416,6 +1432,7 @@ sctp_timeout_handler(void *t)
goto out_decr;
}
SCTP_STAT_INCR(sctps_timoshutdownack);
+ stcb->asoc.timoshutdownack++;
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
@@ -2265,7 +2282,7 @@ sctp_mtu_size_reset(struct sctp_inpcb *inp,
/*
* given an association and starting time of the current RTT period return
- * RTO in number of usecs net should point to the current network
+ * RTO in number of msecs net should point to the current network
*/
uint32_t
sctp_calculate_rto(struct sctp_tcb *stcb,
@@ -2275,7 +2292,7 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
{
/*
* given an association and the starting time of the current RTT
- * period (in value1/value2) return RTO in number of usecs.
+ * period (in value1/value2) return RTO in number of msecs.
*/
int calc_time = 0;
int o_calctime;
@@ -2610,7 +2627,15 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
if (sa->sa_family == AF_INET) {
memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
} else {
+ struct sockaddr_in6 *sin6;
+
memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
+
+ /* recover scope_id for user */
+ sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
+ if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
+ (void)sa6_recoverscope(sin6);
+ }
}
spc->spc_state = state;
spc->spc_error = error;
@@ -3458,7 +3483,6 @@ sctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2)
struct sockaddr_in6 *
sctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store)
{
-
/* check and strip embedded scope junk */
if (addr->sin6_family == AF_INET6) {
if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) {
@@ -3468,7 +3492,9 @@ sctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store)
/* use the recovered scope */
addr = store;
}
+ } else {
/* else, return the original "to" addr */
+ in6_clearscope(&addr->sin6_addr);
}
}
}
@@ -4507,6 +4533,9 @@ found_one:
if (nxt->sinfo_flags & SCTP_UNORDERED) {
s_extra->next_flags |= SCTP_NEXT_MSG_IS_UNORDERED;
}
+ if (nxt->spec_flags & M_NOTIFICATION) {
+ s_extra->next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION;
+ }
s_extra->next_asocid = nxt->sinfo_assoc_id;
s_extra->next_length = nxt->length;
s_extra->next_ppid = nxt->sinfo_ppid;
@@ -4581,7 +4610,6 @@ found_one:
to6 = (struct sockaddr_in6 *)to;
sctp_recover_scope_mac(to6, (&lsa6));
-
}
#endif
}
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index b6dd2b4..82cd432 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -149,24 +149,24 @@ sctp_handle_ootb(struct mbuf *, int, int, struct sctphdr *,
int sctp_is_there_an_abort_here(struct mbuf *, int, uint32_t *);
uint32_t sctp_is_same_scope(struct sockaddr_in6 *, struct sockaddr_in6 *);
-struct sockaddr_in6 *
-sctp_recover_scope(struct sockaddr_in6 *,
- struct sockaddr_in6 *);
-
-
+struct sockaddr_in6 *
+ sctp_recover_scope(struct sockaddr_in6 *, struct sockaddr_in6 *);
#define sctp_recover_scope_mac(addr, store) do { \
- if ((addr->sin6_family == AF_INET6) && \
- (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) && \
- (addr->sin6_scope_id == 0)) { \
- *store = *addr; \
- if (!sa6_recoverscope(store)) { \
- addr = store; \
- } \
- } \
- } while (0)
-
+ if ((addr->sin6_family == AF_INET6) && \
+ (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr))) { \
+ *store = *addr; \
+ if (addr->sin6_scope_id == 0) { \
+ if (!sa6_recoverscope(store)) { \
+ addr = store; \
+ } \
+ } else { \
+ in6_clearscope(&addr->sin6_addr); \
+ addr = store; \
+ } \
+ } \
+} while (0)
int sctp_cmpaddr(struct sockaddr *, struct sockaddr *);
OpenPOWER on IntegriCloud