- Copyright updates (aka 2007)

- ZONE get now also take a type cast so it does the
  cast like mtod does.
- New macro SCTP_LIST_EMPTY, which in bsd is just
  LIST_EMPTY
- Removal of const in some of the static hmac functions
  (not needed)
- Store length changes to allow for new fields in auth
- Auth code updated to current draft (this should be the
  RFC version we think).
- use uint8_t instead of u_char in LOOPBACK address comparison
- Some u_int32_t converted to uint32_t (in crc code)
- A bug was found in the mib counts for ordered/unordered
  count, this was fixed (was referencing a freed mbuf).
- SCTP_ASOCLOG_OF_TSNS added (code will probably disappear
  after my testing completes. It allows us to keep a
  small log on each assoc of the last 40 TSN's in/out and
  stream assignment. It is NOT in options and so is only
  good for private builds.
- Some CMT changes in prep for Jana fixing his problem
  with reneging when CMT is enabled (Concurrent Multipath
  Transfer = CMT).
- Some missing mib stats added.
- Correction to number of open assoc's count in mib
- Correction to os_bsd.h to get right sha2 macros
- Add of special AUTH_04 flags so you can compile the code
  with the old format (in case the peer does not yet support
  the latest auth code).
- Nonce sum was incorrectly being set in when ecn_nonce was
  NOT on.
- LOR in listen with implicit bind found and fixed.
- Moved away from using mbuf's for socket options to using
  just data pointers. The mbufs were used to harmonize
  NetBSD code since both Net and Open used this method. We
  have decided to move away from that and more conform to
  FreeBSD style (which makes more sense).
- Very very nasty bug found in some of my "debug" code. The
  cookie_how collision case tracking had an endless loop in
  it if you got a second retransmission of a cookie collision
  case. This would lock up  a CPU .. ugly..
- auth function goes to using size_t instead of int which
  conforms to socketapi better
- Found the nasty bug that happens after 9 days of testing.. you
  get the data chunk, deliver it and due to the reference to a ch->
  that every now and then has been deleted (depending on the postion
  in the mbuf) you have an invalid ch->ch.flags.. and thus you don't
  advance the stream sequence number.. so you block the stream
  permanently. The fix is to make local variables of these guys
  and set them up before you have any chance of trimming the
  mbuf.
- style fix in sctp_util.h, not sure how this got bad maybe in
  the last patch? (aka it may not be in the real source).
- Found interesting bug when using the extended snd/rcv info where
  we would get an error on receiving with this. Thats because
  it was NOT padded to the same size as the snd_rcv info. We
  increase (add the pad) so the two structs are the same size
  in sctp_uio.h
- In sctp_usrreq.c one of the most common things we did for
  socket options was to cast the pointer and validate the size.
  This as been macro-ized to help make the code more readable.
- in sctputil.c two things, the socketapi class found a missing
  flag type (the next msg is a notification) and a missing
  scope recovery was also fixed.

Reviewed by:	gnn
This commit is contained in:
Randall Stewart 2007-02-12 23:24:31 +00:00
parent 87aabdc126
commit f42a358a6f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=166675
20 changed files with 1190 additions and 1546 deletions

View File

@ -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

View File

@ -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);
/* append in the AUTH chunks */
if (chunks != NULL)
bcopy(chunks->chunk_types, new_key->key + random_len,
num_chunks);
/* append in the HMACs */
if (hmacs != NULL)
bcopy(hmacs->hmac_ids, new_key->key + random_len + num_chunks,
hmacs_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, new_key->key + keylen,
sizeof(*chunks) + num_chunks);
keylen += sizeof(*chunks) + num_chunks;
}
/* append in the HMACs */
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
}

View File

@ -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 */

View File

@ -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) { \

View File

@ -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)
{

View File

@ -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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
(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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
} 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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
}
/* 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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
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 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
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 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
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 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
* 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 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
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 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
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);

View File

@ -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 @@ sctp_handle_stream_reset(struct sctp_tcb *stcb, struct sctp_stream_reset_out_req
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;

View File

@ -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)
*/

View File

@ -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

View File

@ -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 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
* 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 @@ sctp_lower_sosend(struct socket *so,
(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,

View File

@ -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 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
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 @@ sctp_is_vtag_good(struct sctp_inpcb *inp, uint32_t tag, struct timeval *now)
}
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

View File

@ -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:

View File

@ -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

View File

@ -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)
{

View File

@ -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 */
};

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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 @@ sctp_sorecvmsg(struct socket *so,
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 @@ sctp_sorecvmsg(struct socket *so,
to6 = (struct sockaddr_in6 *)to;
sctp_recover_scope_mac(to6, (&lsa6));
}
#endif
}

View File

@ -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 *);
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 *);

View File

@ -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:
@ -715,7 +715,7 @@ sctp6_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 (ENOTCONN);
@ -789,8 +789,11 @@ sctp6_disconnect(struct socket *so)
/* only send SHUTDOWN the first time */
sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
sctp_chunk_output(stcb->sctp_ep, stcb, 1);
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);