- Cleanup checksum code.
- Prepare for CRC offloading, add MIB counters (RS/MT). - Bugfix: Disable CRC computation for IPv6 addresses with local scope (MT). - Bugfix: Handle close() with SO_LINGER correctly when notifications are generated during the close() call(MT). - Bugfix: Generate DRY event when sender is dry during subscription. Only for 1-to-1 style sockets (RS/MT) - Bugfix: Put vtags for the correct amount of time into time-wait (MT). - Bugfix: Clear vtag entries correctly on expiration (MT). - Bugfix: shutdown() indicates ENOTCONN when called for unconnected 1-to-1 style sockets (MT). - Bugfix: In sctp Auth code (PL). - Add support for devices that support SCTP csum offload (igb). - Add missing sctp_associd to mib sysctl xsctp_tcb structure (RS) Obtained from: With help from Peter Lei and Michael Tuexen
This commit is contained in:
parent
2688c69180
commit
520c389cb4
@ -1645,8 +1645,10 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
bcopy(p_random->random_data, new_key->key, random_len);
|
||||
}
|
||||
#else
|
||||
keylen = sizeof(*p_random) + random_len + sizeof(*chunks) + num_chunks +
|
||||
sizeof(*hmacs) + hmacs_len;
|
||||
keylen = sizeof(*p_random) + random_len + sizeof(*hmacs) + hmacs_len;
|
||||
if (chunks != NULL) {
|
||||
keylen += sizeof(*chunks) + num_chunks;
|
||||
}
|
||||
new_key = sctp_alloc_key(keylen);
|
||||
if (new_key != NULL) {
|
||||
/* copy in the RANDOM */
|
||||
|
@ -37,8 +37,15 @@ __FBSDID("$FreeBSD$");
|
||||
#define __sctp_constants_h__
|
||||
|
||||
/* IANA assigned port number for SCTP over UDP encapsulation */
|
||||
#define SCTP_OVER_UDP_TUNNELING_PORT 9899
|
||||
|
||||
/* For freebsd we cannot bind the port at
|
||||
* startup. Otherwise what will happen is
|
||||
* we really won't be bound. The user must
|
||||
* put it into the sysctl... or we need
|
||||
* to build a special timer for this to allow
|
||||
* us to wait 1 second or so after the system
|
||||
* comes up.
|
||||
*/
|
||||
#define SCTP_OVER_UDP_TUNNELING_PORT 0
|
||||
/* Number of packets to get before sack sent by default */
|
||||
#define SCTP_DEFAULT_SACK_FREQ 2
|
||||
|
||||
@ -310,10 +317,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define SCTP_PARTIAL_DELIVERY_SHIFT 1
|
||||
|
||||
/* Minimum number of bytes read by user before we
|
||||
* condsider doing a rwnd update
|
||||
*/
|
||||
|
||||
/*
|
||||
* default HMAC for cookies, etc... use one of the AUTH HMAC id's
|
||||
* SCTP_HMAC is the HMAC_ID to use
|
||||
@ -323,21 +326,6 @@ __FBSDID("$FreeBSD$");
|
||||
#define SCTP_SIGNATURE_SIZE SCTP_AUTH_DIGEST_LEN_SHA1
|
||||
#define SCTP_SIGNATURE_ALOC_SIZE SCTP_SIGNATURE_SIZE
|
||||
|
||||
/* DEFINE HERE WHAT CRC YOU WANT TO USE */
|
||||
#define SCTP_USECRC_RFC2960 1
|
||||
/* #define SCTP_USECRC_FLETCHER 1 */
|
||||
/* #define SCTP_USECRC_SSHCRC32 1 */
|
||||
/* #define SCTP_USECRC_FASTCRC32 1 */
|
||||
/* #define SCTP_USECRC_CRC32 1 */
|
||||
/* #define SCTP_USECRC_TCP32 1 */
|
||||
/* #define SCTP_USECRC_CRC16SMAL 1 */
|
||||
/* #define SCTP_USECRC_CRC16 1 */
|
||||
/* #define SCTP_USECRC_MODADLER 1 */
|
||||
|
||||
#ifndef SCTP_ADLER32_BASE
|
||||
#define SCTP_ADLER32_BASE 65521
|
||||
#endif
|
||||
|
||||
/*
|
||||
* the SCTP protocol signature this includes the version number encoded in
|
||||
* the last 4 bits of the signature.
|
||||
@ -619,42 +607,15 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Number of ticks before the soxwakeup() event that is delayed is sent AFTER
|
||||
* the accept() call
|
||||
*/
|
||||
|
||||
/*
|
||||
* Of course we really don't collect stale cookies, being folks of decerning
|
||||
* taste. However we do count them, if we get too many before the association
|
||||
* comes up.. we give up. Below is the constant that dictates when we give it
|
||||
* up...this is a implemenation dependent treatment. In ours we do not ask
|
||||
* for a extension of time, but just retry this many times...
|
||||
*/
|
||||
|
||||
/* max number of TSN's dup'd that I will hold */
|
||||
#define SCTP_MAX_DUP_TSNS 20
|
||||
|
||||
/*
|
||||
* Here we define the types used when setting the retry amounts.
|
||||
*/
|
||||
/* constants for type of set */
|
||||
|
||||
/* Maximum TSN's we will summarize in a drop report */
|
||||
|
||||
/* How many drop re-attempts we make on INIT/COOKIE-ECHO */
|
||||
#define SCTP_RETRY_DROPPED_THRESH 4
|
||||
|
||||
/*
|
||||
* And the max we will keep a history of in the tcb which MUST be lower than
|
||||
* 256.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Here we define the default timers and the default number of attemts we
|
||||
* make for each respective side (send/init).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Maxmium number of chunks a single association can have on it. Note that
|
||||
* this is a squishy number since the count can run over this if the user
|
||||
@ -763,7 +724,7 @@ __FBSDID("$FreeBSD$");
|
||||
#define SCTP_DEBUG_INDATA1 0x01000000
|
||||
#define SCTP_DEBUG_INDATA2 0x02000000 /* unused */
|
||||
#define SCTP_DEBUG_INDATA3 0x04000000 /* unused */
|
||||
#define SCTP_DEBUG_INDATA4 0x08000000 /* unused */
|
||||
#define SCTP_DEBUG_CRCOFFLOAD 0x08000000 /* unused */
|
||||
#define SCTP_DEBUG_USRREQ1 0x10000000 /* unused */
|
||||
#define SCTP_DEBUG_USRREQ2 0x20000000 /* unused */
|
||||
#define SCTP_DEBUG_PEEL1 0x40000000
|
||||
@ -783,7 +744,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define SCTP_INITIAL_CWND 4380
|
||||
|
||||
#define SCTP_DEFAULT_MTU 1500 /* emegency default MTU */
|
||||
#define SCTP_DEFAULT_MTU 1500 /* emergency default MTU */
|
||||
/* amount peer is obligated to have in rwnd or I will abort */
|
||||
#define SCTP_MIN_RWND 1500
|
||||
|
||||
@ -996,13 +957,6 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
#define SCTP_STACK_VTAG_HASH_SIZE 32
|
||||
|
||||
|
||||
/*
|
||||
* If we use the per-endpoint model than we do not have a hash table of
|
||||
* entries but instead have a single head pointer and we must crawl through
|
||||
* the entire list.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Number of seconds of time wait for a vtag.
|
||||
*/
|
||||
|
@ -34,12 +34,16 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/uio.h>
|
||||
#include <netinet/sctp.h>
|
||||
#include <netinet/sctp_os.h>
|
||||
#include <netinet/sctp_crc32.h>
|
||||
#include <netinet/sctp_pcb.h>
|
||||
|
||||
#ifndef SCTP_USE_ADLER32
|
||||
|
||||
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
/**
|
||||
*
|
||||
* Routine Description:
|
||||
@ -80,12 +84,14 @@ __FBSDID("$FreeBSD$");
|
||||
* The following CRC lookup table was generated automagically using the
|
||||
* following model parameters:
|
||||
*
|
||||
* Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
|
||||
* Length = .......... 32 bits Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits Number of Slices =
|
||||
* ..................... 8 slices Slice Lengths = ........................ 8
|
||||
* 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
|
||||
* ............................ 8x256_tables.c
|
||||
* Generator Polynomial = ................. 0x1EDC6F41
|
||||
* Generator Polynomial Length = .......... 32 bits
|
||||
* Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits
|
||||
* Number of Slices = ..................... 8 slices
|
||||
* Slice Lengths = ........................ 8 8 8 8 8 8 8 8
|
||||
* Directory Name = ....................... .\
|
||||
* File Name = ............................ 8x256_tables.c
|
||||
*/
|
||||
|
||||
uint32_t sctp_crc_tableil8_o32[256] =
|
||||
@ -134,12 +140,14 @@ uint32_t sctp_crc_tableil8_o32[256] =
|
||||
* The following CRC lookup table was generated automagically using the
|
||||
* following model parameters:
|
||||
*
|
||||
* Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
|
||||
* Length = .......... 32 bits Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits Number of Slices =
|
||||
* ..................... 8 slices Slice Lengths = ........................ 8
|
||||
* 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
|
||||
* ............................ 8x256_tables.c
|
||||
* Generator Polynomial = ................. 0x1EDC6F41
|
||||
* Generator Polynomial Length = .......... 32 bits
|
||||
* Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits
|
||||
* Number of Slices = ..................... 8 slices
|
||||
* Slice Lengths = ........................ 8 8 8 8 8 8 8 8
|
||||
* Directory Name = ....................... .\
|
||||
* File Name = ............................ 8x256_tables.c
|
||||
*/
|
||||
|
||||
uint32_t sctp_crc_tableil8_o40[256] =
|
||||
@ -188,12 +196,14 @@ uint32_t sctp_crc_tableil8_o40[256] =
|
||||
* The following CRC lookup table was generated automagically using the
|
||||
* following model parameters:
|
||||
*
|
||||
* Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
|
||||
* Length = .......... 32 bits Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits Number of Slices =
|
||||
* ..................... 8 slices Slice Lengths = ........................ 8
|
||||
* 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
|
||||
* ............................ 8x256_tables.c
|
||||
* Generator Polynomial = ................. 0x1EDC6F41
|
||||
* Generator Polynomial Length = .......... 32 bits
|
||||
* Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits
|
||||
* Number of Slices = ..................... 8 slices
|
||||
* Slice Lengths = ........................ 8 8 8 8 8 8 8 8
|
||||
* Directory Name = ....................... .\
|
||||
* File Name = ............................ 8x256_tables.c
|
||||
*/
|
||||
|
||||
uint32_t sctp_crc_tableil8_o48[256] =
|
||||
@ -242,12 +252,14 @@ uint32_t sctp_crc_tableil8_o48[256] =
|
||||
* The following CRC lookup table was generated automagically using the
|
||||
* following model parameters:
|
||||
*
|
||||
* Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
|
||||
* Length = .......... 32 bits Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits Number of Slices =
|
||||
* ..................... 8 slices Slice Lengths = ........................ 8
|
||||
* 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
|
||||
* ............................ 8x256_tables.c
|
||||
* Generator Polynomial = ................. 0x1EDC6F41
|
||||
* Generator Polynomial Length = .......... 32 bits
|
||||
* Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits
|
||||
* Number of Slices = ..................... 8 slices
|
||||
* Slice Lengths = ........................ 8 8 8 8 8 8 8 8
|
||||
* Directory Name = ....................... .\
|
||||
* File Name = ............................ 8x256_tables.c
|
||||
*/
|
||||
|
||||
uint32_t sctp_crc_tableil8_o56[256] =
|
||||
@ -296,12 +308,14 @@ uint32_t sctp_crc_tableil8_o56[256] =
|
||||
* The following CRC lookup table was generated automagically using the
|
||||
* following model parameters:
|
||||
*
|
||||
* Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
|
||||
* Length = .......... 32 bits Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits Number of Slices =
|
||||
* ..................... 8 slices Slice Lengths = ........................ 8
|
||||
* 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
|
||||
* ............................ 8x256_tables.c
|
||||
* Generator Polynomial = ................. 0x1EDC6F41
|
||||
* Generator Polynomial Length = .......... 32 bits
|
||||
* Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits
|
||||
* Number of Slices = ..................... 8 slices
|
||||
* Slice Lengths = ........................ 8 8 8 8 8 8 8 8
|
||||
* Directory Name = ....................... .\
|
||||
* File Name = ............................ 8x256_tables.c
|
||||
*/
|
||||
|
||||
uint32_t sctp_crc_tableil8_o64[256] =
|
||||
@ -350,12 +364,14 @@ uint32_t sctp_crc_tableil8_o64[256] =
|
||||
* The following CRC lookup table was generated automagically using the
|
||||
* following model parameters:
|
||||
*
|
||||
* Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
|
||||
* Length = .......... 32 bits Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits Number of Slices =
|
||||
* ..................... 8 slices Slice Lengths = ........................ 8
|
||||
* 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
|
||||
* ............................ 8x256_tables.c
|
||||
* Generator Polynomial = ................. 0x1EDC6F41
|
||||
* Generator Polynomial Length = .......... 32 bits
|
||||
* Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits
|
||||
* Number of Slices = ..................... 8 slices
|
||||
* Slice Lengths = ........................ 8 8 8 8 8 8 8 8
|
||||
* Directory Name = ....................... .\
|
||||
* File Name = ............................ 8x256_tables.c
|
||||
*/
|
||||
|
||||
uint32_t sctp_crc_tableil8_o72[256] =
|
||||
@ -404,12 +420,14 @@ uint32_t sctp_crc_tableil8_o72[256] =
|
||||
* The following CRC lookup table was generated automagically using the
|
||||
* following model parameters:
|
||||
*
|
||||
* Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
|
||||
* Length = .......... 32 bits Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits Number of Slices =
|
||||
* ..................... 8 slices Slice Lengths = ........................ 8
|
||||
* 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
|
||||
* ............................ 8x256_tables.c
|
||||
* Generator Polynomial = ................. 0x1EDC6F41
|
||||
* Generator Polynomial Length = .......... 32 bits
|
||||
* Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits
|
||||
* Number of Slices = ..................... 8 slices
|
||||
* Slice Lengths = ........................ 8 8 8 8 8 8 8 8
|
||||
* Directory Name = ....................... .\
|
||||
* File Name = ............................ 8x256_tables.c
|
||||
*/
|
||||
|
||||
uint32_t sctp_crc_tableil8_o80[256] =
|
||||
@ -458,12 +476,14 @@ uint32_t sctp_crc_tableil8_o80[256] =
|
||||
* The following CRC lookup table was generated automagically using the
|
||||
* following model parameters:
|
||||
*
|
||||
* Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
|
||||
* Length = .......... 32 bits Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits Number of Slices =
|
||||
* ..................... 8 slices Slice Lengths = ........................ 8
|
||||
* 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
|
||||
* ............................ 8x256_tables.c
|
||||
* Generator Polynomial = ................. 0x1EDC6F41
|
||||
* Generator Polynomial Length = .......... 32 bits
|
||||
* Reflected Bits = ....................... TRUE
|
||||
* Table Generation Offset = .............. 32 bits
|
||||
* Number of Slices = ..................... 8 slices
|
||||
* Slice Lengths = ........................ 8 8 8 8 8 8 8 8
|
||||
* Directory Name = ....................... .\
|
||||
* File Name = ............................ 8x256_tables.c
|
||||
*/
|
||||
|
||||
uint32_t sctp_crc_tableil8_o88[256] =
|
||||
@ -506,6 +526,7 @@ uint32_t sctp_crc_tableil8_o88[256] =
|
||||
* end of the CRC lookup table crc_tableil8_o88
|
||||
*/
|
||||
|
||||
|
||||
static uint32_t
|
||||
sctp_crc32c_sb8_64_bit(uint32_t crc,
|
||||
unsigned char *p_buf,
|
||||
@ -578,7 +599,7 @@ sctp_crc32c_sb8_64_bit(uint32_t crc,
|
||||
*
|
||||
* none
|
||||
*/
|
||||
uint32_t
|
||||
static uint32_t
|
||||
update_crc32(uint32_t crc32c,
|
||||
unsigned char *buffer,
|
||||
unsigned int length)
|
||||
@ -662,7 +683,7 @@ uint32_t sctp_crc_c[256] = {
|
||||
|
||||
#define SCTP_CRC32C(c,d) (c=(c>>8)^sctp_crc_c[(c^(d))&0xFF])
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
old_update_crc32(uint32_t crc32c,
|
||||
unsigned char *buffer,
|
||||
unsigned int length)
|
||||
@ -676,8 +697,8 @@ old_update_crc32(uint32_t crc32c,
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
sctp_csum_finalize(uint32_t crc32c)
|
||||
static uint32_t
|
||||
sctp_finalize_crc32(uint32_t crc32c)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
@ -709,4 +730,88 @@ sctp_csum_finalize(uint32_t crc32c)
|
||||
return (crc32c);
|
||||
}
|
||||
|
||||
#endif /* !defined(SCTP_WITH_NO_CSUM) */
|
||||
|
||||
#if defined(SCTP_WITH_NO_CSUM)
|
||||
uint32_t
|
||||
sctp_calculate_cksum(struct mbuf *m, uint32_t offset)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
#else
|
||||
uint32_t
|
||||
sctp_calculate_cksum(struct mbuf *m, uint32_t offset)
|
||||
{
|
||||
/*
|
||||
* given a mbuf chain with a packetheader offset by 'offset'
|
||||
* pointing at a sctphdr (with csum set to 0) go through the chain
|
||||
* of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also
|
||||
* has a side bonus as it will calculate the total length of the
|
||||
* mbuf chain. Note: if offset is greater than the total mbuf
|
||||
* length, checksum=1, pktlen=0 is returned (ie. no real error code)
|
||||
*/
|
||||
uint32_t base = 0xffffffff;
|
||||
struct mbuf *at;
|
||||
|
||||
at = m;
|
||||
/* find the correct mbuf and offset into mbuf */
|
||||
while ((at != NULL) && (offset > (uint32_t) SCTP_BUF_LEN(at))) {
|
||||
offset -= SCTP_BUF_LEN(at); /* update remaining offset
|
||||
* left */
|
||||
at = SCTP_BUF_NEXT(at);
|
||||
}
|
||||
while (at != NULL) {
|
||||
if ((SCTP_BUF_LEN(at) - offset) > 0) {
|
||||
if ((SCTP_BUF_LEN(at) - offset) < 4) {
|
||||
/* Use old method if less than 4 bytes */
|
||||
base = old_update_crc32(base,
|
||||
(unsigned char *)(SCTP_BUF_AT(at, offset)),
|
||||
(unsigned int)(SCTP_BUF_LEN(at) - offset));
|
||||
} else {
|
||||
base = update_crc32(base,
|
||||
(unsigned char *)(SCTP_BUF_AT(at, offset)),
|
||||
(unsigned int)(SCTP_BUF_LEN(at) - offset));
|
||||
}
|
||||
/* we only offset once into the first mbuf */
|
||||
}
|
||||
if (offset) {
|
||||
if (offset < (uint32_t) SCTP_BUF_LEN(at))
|
||||
offset = 0;
|
||||
else
|
||||
offset -= SCTP_BUF_LEN(at);
|
||||
}
|
||||
at = SCTP_BUF_NEXT(at);
|
||||
}
|
||||
base = sctp_finalize_crc32(base);
|
||||
return (base);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
sctp_delayed_cksum(struct mbuf *m)
|
||||
{
|
||||
struct ip *ip;
|
||||
uint32_t checksum;
|
||||
uint32_t offset;
|
||||
|
||||
ip = mtod(m, struct ip *);
|
||||
offset = ip->ip_hl << 2;
|
||||
checksum = sctp_calculate_cksum(m, offset);
|
||||
SCTP_STAT_DECR(sctps_sendhwcrc);
|
||||
SCTP_STAT_INCR(sctps_sendswcrc);
|
||||
offset += offsetof(struct sctphdr, checksum);
|
||||
|
||||
if (offset + sizeof(uint32_t) > (uint32_t) (m->m_len)) {
|
||||
printf("delayed m_pullup, m->len: %d off: %d p: %d\n",
|
||||
(uint32_t) m->m_len, offset, ip->ip_p);
|
||||
/*
|
||||
* XXX this shouldn't happen, but if it does, the correct
|
||||
* behavior may be to insert the checksum in the appropriate
|
||||
* next mbuf in the chain.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
*(uint32_t *) (m->m_data + offset) = checksum;
|
||||
}
|
||||
|
@ -36,16 +36,10 @@ __FBSDID("$FreeBSD$");
|
||||
#ifndef __crc32c_h__
|
||||
#define __crc32c_h__
|
||||
|
||||
#ifndef SCTP_USE_ADLER32
|
||||
|
||||
#if defined(_KERNEL) || defined(__Userspace__)
|
||||
uint32_t update_crc32(uint32_t, unsigned char *, unsigned int);
|
||||
|
||||
uint32_t old_update_crc32(uint32_t, unsigned char *, unsigned int);
|
||||
|
||||
uint32_t sctp_csum_finalize(uint32_t);
|
||||
|
||||
uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t);
|
||||
void sctp_delayed_cksum(struct mbuf *);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif /* !SCTP_USE_ADLER32 */
|
||||
|
||||
#endif /* __crc32c_h__ */
|
||||
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/sctp_asconf.h>
|
||||
#include <netinet/sctp_bsd_addr.h>
|
||||
#include <netinet/sctp_timer.h>
|
||||
#include <netinet/sctp_crc32.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
|
||||
@ -1384,14 +1385,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
/* FOOBAR */
|
||||
return (NULL);
|
||||
}
|
||||
/* pre-reserve some space */
|
||||
#ifdef INET6
|
||||
SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
|
||||
#else
|
||||
SCTP_BUF_RESV_UF(op_err, sizeof(struct ip));
|
||||
#endif
|
||||
SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
|
||||
SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
|
||||
/* Set the len */
|
||||
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
|
||||
ph = mtod(op_err, struct sctp_paramhdr *);
|
||||
@ -2504,15 +2497,6 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
|
||||
/* FOOBAR */
|
||||
return (NULL);
|
||||
}
|
||||
/* pre-reserve some space */
|
||||
#ifdef INET6
|
||||
SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
|
||||
#else
|
||||
SCTP_BUF_RESV_UF(op_err, sizeof(struct ip));
|
||||
#endif
|
||||
SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
|
||||
SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
|
||||
|
||||
/* Set the len */
|
||||
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg);
|
||||
scm = mtod(op_err, struct sctp_stale_cookie_msg *);
|
||||
@ -2598,9 +2582,9 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (to == NULL)
|
||||
if (to == NULL) {
|
||||
return (NULL);
|
||||
|
||||
}
|
||||
cookie_len -= SCTP_SIGNATURE_SIZE;
|
||||
if (*stcb == NULL) {
|
||||
/* this is the "normal" case... get a new TCB */
|
||||
@ -5594,7 +5578,6 @@ sctp_input_with_port(i_pak, off, port)
|
||||
int refcount_up = 0;
|
||||
int length, mlen, offset;
|
||||
|
||||
|
||||
if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) {
|
||||
SCTP_RELEASE_PKT(i_pak);
|
||||
return;
|
||||
@ -5642,6 +5625,11 @@ sctp_input_with_port(i_pak, off, port)
|
||||
}
|
||||
ip = mtod(m, struct ip *);
|
||||
}
|
||||
/* validate mbuf chain length with IP payload length */
|
||||
if (mlen < (SCTP_GET_IPV4_LENGTH(ip) - iphlen)) {
|
||||
SCTP_STAT_INCR(sctps_hdrops);
|
||||
goto bad;
|
||||
}
|
||||
sh = (struct sctphdr *)((caddr_t)ip + iphlen);
|
||||
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(*sh));
|
||||
SCTPDBG(SCTP_DEBUG_INPUT1,
|
||||
@ -5659,15 +5647,26 @@ sctp_input_with_port(i_pak, off, port)
|
||||
goto bad;
|
||||
}
|
||||
/* validate SCTP checksum */
|
||||
SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
|
||||
"sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
|
||||
m->m_pkthdr.len,
|
||||
if_name(m->m_pkthdr.rcvif),
|
||||
m->m_pkthdr.csum_flags);
|
||||
if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
|
||||
SCTP_STAT_INCR(sctps_recvhwcrc);
|
||||
goto sctp_skip_csum_4;
|
||||
}
|
||||
check = sh->checksum; /* save incoming checksum */
|
||||
if ((check == 0) && (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback)) &&
|
||||
((ip->ip_src.s_addr == ip->ip_dst.s_addr) ||
|
||||
(SCTP_IS_IT_LOOPBACK(m)))
|
||||
) {
|
||||
SCTP_STAT_INCR(sctps_recvnocrc);
|
||||
goto sctp_skip_csum_4;
|
||||
}
|
||||
sh->checksum = 0; /* prepare for calc */
|
||||
calc_check = sctp_calculate_sum(m, &mlen, iphlen);
|
||||
calc_check = sctp_calculate_cksum(m, iphlen);
|
||||
SCTP_STAT_INCR(sctps_recvswcrc);
|
||||
if (calc_check != check) {
|
||||
SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n",
|
||||
calc_check, check, m, mlen, iphlen);
|
||||
@ -5699,11 +5698,6 @@ sctp_skip_csum_4:
|
||||
SCTP_STAT_INCR(sctps_hdrops);
|
||||
goto bad;
|
||||
}
|
||||
/* validate mbuf chain length with IP payload length */
|
||||
if (mlen < (SCTP_GET_IPV4_LENGTH(ip) - iphlen)) {
|
||||
SCTP_STAT_INCR(sctps_hdrops);
|
||||
goto bad;
|
||||
}
|
||||
/*
|
||||
* Locate pcb and tcb for datagram sctp_findassociation_addr() wants
|
||||
* IP/SCTP/first chunk header...
|
||||
|
@ -154,11 +154,8 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT);
|
||||
#define MOD_IPSEC ipsec
|
||||
|
||||
/* then define the macro(s) that hook into the vimage macros */
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 800056
|
||||
#define MODULE_GLOBAL(__MODULE, __SYMBOL) V_ ## __SYMBOL
|
||||
#else
|
||||
#define MODULE_GLOBAL(__MODULE, __SYMBOL) (__SYMBOL)
|
||||
#endif
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2504,7 +2504,9 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
|
||||
/* Pull the tcb from the old association */
|
||||
LIST_REMOVE(stcb, sctp_tcbhash);
|
||||
LIST_REMOVE(stcb, sctp_tcblist);
|
||||
|
||||
if (stcb->asoc.in_asocid_hash) {
|
||||
LIST_REMOVE(stcb, sctp_tcbasocidhash);
|
||||
}
|
||||
/* Now insert the new_inp into the TCP connected hash */
|
||||
head = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport),
|
||||
SCTP_BASE_INFO(hashtcpmark))];
|
||||
@ -2520,7 +2522,13 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
|
||||
* only have one connection? Probably not :> so lets get rid of it
|
||||
* and not suck up any kernel memory in that.
|
||||
*/
|
||||
if (stcb->asoc.in_asocid_hash) {
|
||||
struct sctpasochead *lhd;
|
||||
|
||||
lhd = &new_inp->sctp_asocidhash[SCTP_PCBHASH_ASOC(stcb->asoc.assoc_id,
|
||||
new_inp->hashasocidmark)];
|
||||
LIST_INSERT_HEAD(lhd, stcb, sctp_tcbasocidhash);
|
||||
}
|
||||
/* Ok. Let's restart timer. */
|
||||
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
|
||||
sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, new_inp,
|
||||
@ -4652,7 +4660,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
}
|
||||
/* pull from vtag hash */
|
||||
LIST_REMOVE(stcb, sctp_asocs);
|
||||
sctp_add_vtag_to_timewait(asoc->my_vtag, inp->sctp_lport, stcb->rport, SCTP_TIME_WAIT);
|
||||
sctp_add_vtag_to_timewait(asoc->my_vtag, SCTP_TIME_WAIT, inp->sctp_lport, stcb->rport);
|
||||
|
||||
/*
|
||||
* Now restop the timers to be sure - this is paranoia at is finest!
|
||||
@ -4763,7 +4771,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
}
|
||||
}
|
||||
/*
|
||||
if(ccnt) {
|
||||
if (ccnt) {
|
||||
printf("Freed %d from send_queue\n", ccnt);
|
||||
ccnt = 0;
|
||||
}
|
||||
@ -4788,7 +4796,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
}
|
||||
}
|
||||
/*
|
||||
if(ccnt) {
|
||||
if (ccnt) {
|
||||
printf("Freed %d from sent_queue\n", ccnt);
|
||||
ccnt = 0;
|
||||
}
|
||||
@ -4813,7 +4821,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
}
|
||||
}
|
||||
/*
|
||||
if(ccnt) {
|
||||
if (ccnt) {
|
||||
printf("Freed %d from ctrl_queue\n", ccnt);
|
||||
ccnt = 0;
|
||||
}
|
||||
@ -4839,7 +4847,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
}
|
||||
}
|
||||
/*
|
||||
if(ccnt) {
|
||||
if (ccnt) {
|
||||
printf("Freed %d from asconf_queue\n", ccnt);
|
||||
ccnt = 0;
|
||||
}
|
||||
@ -4863,7 +4871,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
}
|
||||
}
|
||||
/*
|
||||
if(ccnt) {
|
||||
if (ccnt) {
|
||||
printf("Freed %d from reasm_queue\n", ccnt);
|
||||
ccnt = 0;
|
||||
}
|
||||
@ -5776,7 +5784,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
|
||||
/* ok get the v4 address and check/add */
|
||||
phdr = sctp_get_next_param(m, offset,
|
||||
(struct sctp_paramhdr *)&p4_buf, sizeof(p4_buf));
|
||||
(struct sctp_paramhdr *)&p4_buf,
|
||||
sizeof(p4_buf));
|
||||
if (plen != sizeof(struct sctp_ipv4addr_param) ||
|
||||
phdr == NULL) {
|
||||
return (-5);
|
||||
@ -5858,7 +5867,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
struct sctp_ipv6addr_param *p6, p6_buf;
|
||||
|
||||
phdr = sctp_get_next_param(m, offset,
|
||||
(struct sctp_paramhdr *)&p6_buf, sizeof(p6_buf));
|
||||
(struct sctp_paramhdr *)&p6_buf,
|
||||
sizeof(p6_buf));
|
||||
if (plen != sizeof(struct sctp_ipv6addr_param) ||
|
||||
phdr == NULL) {
|
||||
return (-14);
|
||||
@ -5883,8 +5893,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net,
|
||||
local_sa, stcb);
|
||||
atomic_add_int(&stcb->asoc.refcnt, -1);
|
||||
if (stcb_tmp == NULL && (inp == stcb->sctp_ep ||
|
||||
inp == NULL)) {
|
||||
if (stcb_tmp == NULL &&
|
||||
(inp == stcb->sctp_ep || inp == NULL)) {
|
||||
/*
|
||||
* we must validate the state again
|
||||
* here
|
||||
@ -5965,7 +5975,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
return (-23);
|
||||
}
|
||||
phdr = sctp_get_next_param(m, offset,
|
||||
(struct sctp_paramhdr *)&lstore, min(plen, sizeof(lstore)));
|
||||
(struct sctp_paramhdr *)&lstore,
|
||||
min(plen, sizeof(lstore)));
|
||||
if (phdr == NULL) {
|
||||
return (-24);
|
||||
}
|
||||
@ -6154,6 +6165,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
next_param:
|
||||
offset += SCTP_SIZE32(plen);
|
||||
if (offset >= limit) {
|
||||
@ -6206,8 +6218,10 @@ next_param:
|
||||
bcopy(p_random->random_data, new_key->key, random_len);
|
||||
}
|
||||
#else
|
||||
keylen = sizeof(*p_random) + random_len + sizeof(*chunks) + num_chunks +
|
||||
sizeof(*hmacs) + hmacs_len;
|
||||
keylen = sizeof(*p_random) + random_len + sizeof(*hmacs) + hmacs_len;
|
||||
if (chunks != NULL) {
|
||||
keylen += sizeof(*chunks) + num_chunks;
|
||||
}
|
||||
new_key = sctp_alloc_key(keylen);
|
||||
if (new_key != NULL) {
|
||||
/* copy in the RANDOM */
|
||||
@ -6343,6 +6357,8 @@ skip_vtag_check:
|
||||
/* Audit expires this guy */
|
||||
twait_block->vtag_block[i].tv_sec_at_expire = 0;
|
||||
twait_block->vtag_block[i].v_tag = 0;
|
||||
twait_block->vtag_block[i].lport = 0;
|
||||
twait_block->vtag_block[i].rport = 0;
|
||||
} else if ((twait_block->vtag_block[i].v_tag == tag) &&
|
||||
(twait_block->vtag_block[i].lport == lport) &&
|
||||
(twait_block->vtag_block[i].rport == rport)) {
|
||||
|
@ -144,6 +144,7 @@ struct sctp_tagblock {
|
||||
|
||||
|
||||
struct sctp_epinfo {
|
||||
struct socket *udp_tun_socket;
|
||||
struct sctpasochead *sctp_asochash;
|
||||
u_long hashasocmark;
|
||||
|
||||
|
@ -120,6 +120,7 @@ sctp_init_sysctls()
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* It returns an upper limit. No filtering is done here */
|
||||
static unsigned int
|
||||
number_of_addresses(struct sctp_inpcb *inp)
|
||||
@ -408,6 +409,8 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
|
||||
xstcb.primary_addr = stcb->asoc.primary_destination->ro._l_addr;
|
||||
xstcb.heartbeat_interval = stcb->asoc.heart_beat_delay;
|
||||
xstcb.state = SCTP_GET_STATE(&stcb->asoc); /* FIXME */
|
||||
/* 7.0 does not support this */
|
||||
xstcb.assoc_id = sctp_get_associd(stcb);
|
||||
xstcb.in_streams = stcb->asoc.streamincnt;
|
||||
xstcb.out_streams = stcb->asoc.streamoutcnt;
|
||||
xstcb.max_nr_retrans = stcb->asoc.overall_error_count;
|
||||
@ -506,7 +509,6 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define RANGECHK(var, min, max) \
|
||||
if ((var) < (min)) { (var) = (min); } \
|
||||
else if ((var) > (max)) { (var) = (max); }
|
||||
@ -517,10 +519,15 @@ sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS)
|
||||
int error;
|
||||
uint32_t old_sctp_udp_tunneling_port;
|
||||
|
||||
SCTP_INP_INFO_WLOCK();
|
||||
old_sctp_udp_tunneling_port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
|
||||
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
|
||||
if (error == 0) {
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), SCTPCTL_UDP_TUNNELING_PORT_MIN, SCTPCTL_UDP_TUNNELING_PORT_MAX);
|
||||
if (old_sctp_udp_tunneling_port == SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) {
|
||||
error = 0;
|
||||
goto out;
|
||||
}
|
||||
if (old_sctp_udp_tunneling_port) {
|
||||
sctp_over_udp_stop();
|
||||
}
|
||||
@ -530,6 +537,8 @@ sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
SCTP_INP_INFO_WUNLOCK();
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -624,14 +633,15 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
|
||||
static int
|
||||
sysctl_sctp_cleartrace(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log));
|
||||
return (0);
|
||||
return (error);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* sysctl definitions
|
||||
*/
|
||||
|
@ -804,6 +804,10 @@ struct sctpstat {
|
||||
uint32_t sctps_recvexpress; /* total fast path receives all one
|
||||
* chunk */
|
||||
uint32_t sctps_recvexpressm; /* total fast path multi-part data */
|
||||
uint32_t sctps_recvnocrc;
|
||||
uint32_t sctps_recvswcrc;
|
||||
uint32_t sctps_recvhwcrc;
|
||||
|
||||
/* output statistics: */
|
||||
uint32_t sctps_sendpackets; /* total output packets */
|
||||
uint32_t sctps_sendsacks; /* total output SACKs */
|
||||
@ -820,6 +824,9 @@ struct sctpstat {
|
||||
uint32_t sctps_sendecne;/* total output ECNE chunks */
|
||||
uint32_t sctps_sendauth;/* total output AUTH chunks FIXME */
|
||||
uint32_t sctps_senderrors; /* ip_output error counter */
|
||||
uint32_t sctps_sendnocrc;
|
||||
uint32_t sctps_sendswcrc;
|
||||
uint32_t sctps_sendhwcrc;
|
||||
/* PCKDROPREP statistics: */
|
||||
uint32_t sctps_pdrpfmbox; /* Packet drop from middle box */
|
||||
uint32_t sctps_pdrpfehos; /* P-drop from end host */
|
||||
@ -1009,6 +1016,7 @@ struct xsctp_tcb {
|
||||
uint16_t remote_port; /* sctpAssocEntry 4 */
|
||||
struct sctp_timeval start_time; /* sctpAssocEntry 16 */
|
||||
struct sctp_timeval discontinuity_time; /* sctpAssocEntry 17 */
|
||||
sctp_assoc_t assoc_id; /* sctpAssocEntry 1 */
|
||||
};
|
||||
|
||||
struct xsctp_laddr {
|
||||
|
@ -908,6 +908,7 @@ sctp_disconnect(struct socket *so)
|
||||
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
|
||||
}
|
||||
}
|
||||
soisdisconnecting(so);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
return (0);
|
||||
@ -980,6 +981,11 @@ sctp_shutdown(struct socket *so)
|
||||
struct sctp_tcb *stcb;
|
||||
struct sctp_association *asoc;
|
||||
|
||||
if ((so->so_state &
|
||||
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
return (ENOTCONN);
|
||||
}
|
||||
socantsendmore(so);
|
||||
|
||||
stcb = LIST_FIRST(&inp->sctp_asoc_list);
|
||||
@ -3515,6 +3521,22 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
|
||||
if (events->sctp_sender_dry_event) {
|
||||
sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
|
||||
stcb = LIST_FIRST(&inp->sctp_asoc_list);
|
||||
if (stcb) {
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
}
|
||||
if (stcb &&
|
||||
TAILQ_EMPTY(&stcb->asoc.send_queue) &&
|
||||
TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
|
||||
(stcb->asoc.stream_queue_cnt == 0)) {
|
||||
sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
|
||||
}
|
||||
if (stcb) {
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
|
||||
}
|
||||
|
@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/sctp_output.h>
|
||||
#include <netinet/sctp_uio.h>
|
||||
#include <netinet/sctp_timer.h>
|
||||
#include <netinet/sctp_crc32.h>
|
||||
#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
|
||||
#include <netinet/sctp_auth.h>
|
||||
#include <netinet/sctp_asconf.h>
|
||||
@ -53,9 +52,15 @@ __FBSDID("$FreeBSD$");
|
||||
#define NUMBER_OF_MTU_SIZES 18
|
||||
|
||||
|
||||
#if defined(__Windows__) && !defined(SCTP_LOCAL_TRACE_BUF)
|
||||
#include "eventrace_netinet.h"
|
||||
#include "sctputil.tmh" /* this is the file that will be auto
|
||||
* generated */
|
||||
#else
|
||||
#ifndef KTR_SCTP
|
||||
#define KTR_SCTP KTR_SUBSYS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
sctp_sblog(struct sockbuf *sb,
|
||||
@ -2458,48 +2463,6 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SCTP_USE_ADLER32
|
||||
static uint32_t
|
||||
update_adler32(uint32_t adler, uint8_t * buf, int32_t len)
|
||||
{
|
||||
uint32_t s1 = adler & 0xffff;
|
||||
uint32_t s2 = (adler >> 16) & 0xffff;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < len; n++, buf++) {
|
||||
/* s1 = (s1 + buf[n]) % BASE */
|
||||
/* first we add */
|
||||
s1 = (s1 + *buf);
|
||||
/*
|
||||
* now if we need to, we do a mod by subtracting. It seems a
|
||||
* bit faster since I really will only ever do one subtract
|
||||
* at the MOST, since buf[n] is a max of 255.
|
||||
*/
|
||||
if (s1 >= SCTP_ADLER32_BASE) {
|
||||
s1 -= SCTP_ADLER32_BASE;
|
||||
}
|
||||
/* s2 = (s2 + s1) % BASE */
|
||||
/* first we add */
|
||||
s2 = (s2 + s1);
|
||||
/*
|
||||
* again, it is more efficent (it seems) to subtract since
|
||||
* the most s2 will ever be is (BASE-1 + BASE-1) in the
|
||||
* worse case. This would then be (2 * BASE) - 2, which will
|
||||
* still only do one subtract. On Intel this is much better
|
||||
* to do this way and avoid the divide. Have not -pg'd on
|
||||
* sparc.
|
||||
*/
|
||||
if (s2 >= SCTP_ADLER32_BASE) {
|
||||
s2 -= SCTP_ADLER32_BASE;
|
||||
}
|
||||
}
|
||||
/* Return the adler32 of the bytes buf[0..len-1] */
|
||||
return ((s2 << 16) + s1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t
|
||||
sctp_calculate_len(struct mbuf *m)
|
||||
{
|
||||
@ -2514,132 +2477,6 @@ sctp_calculate_len(struct mbuf *m)
|
||||
return (tlen);
|
||||
}
|
||||
|
||||
#if defined(SCTP_WITH_NO_CSUM)
|
||||
|
||||
uint32_t
|
||||
sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset)
|
||||
{
|
||||
/*
|
||||
* given a mbuf chain with a packetheader offset by 'offset'
|
||||
* pointing at a sctphdr (with csum set to 0) go through the chain
|
||||
* of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also
|
||||
* has a side bonus as it will calculate the total length of the
|
||||
* mbuf chain. Note: if offset is greater than the total mbuf
|
||||
* length, checksum=1, pktlen=0 is returned (ie. no real error code)
|
||||
*/
|
||||
if (pktlen == NULL)
|
||||
return (0);
|
||||
*pktlen = sctp_calculate_len(m);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#elif defined(SCTP_USE_INCHKSUM)
|
||||
|
||||
#include <machine/in_cksum.h>
|
||||
|
||||
uint32_t
|
||||
sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset)
|
||||
{
|
||||
/*
|
||||
* given a mbuf chain with a packetheader offset by 'offset'
|
||||
* pointing at a sctphdr (with csum set to 0) go through the chain
|
||||
* of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also
|
||||
* has a side bonus as it will calculate the total length of the
|
||||
* mbuf chain. Note: if offset is greater than the total mbuf
|
||||
* length, checksum=1, pktlen=0 is returned (ie. no real error code)
|
||||
*/
|
||||
int32_t tlen = 0;
|
||||
struct mbuf *at;
|
||||
uint32_t the_sum, retsum;
|
||||
|
||||
at = m;
|
||||
while (at) {
|
||||
tlen += SCTP_BUF_LEN(at);
|
||||
at = SCTP_BUF_NEXT(at);
|
||||
}
|
||||
the_sum = (uint32_t) (in_cksum_skip(m, tlen, offset));
|
||||
if (pktlen != NULL)
|
||||
*pktlen = (tlen - offset);
|
||||
retsum = htons(the_sum);
|
||||
return (the_sum);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
uint32_t
|
||||
sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset)
|
||||
{
|
||||
/*
|
||||
* given a mbuf chain with a packetheader offset by 'offset'
|
||||
* pointing at a sctphdr (with csum set to 0) go through the chain
|
||||
* of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also
|
||||
* has a side bonus as it will calculate the total length of the
|
||||
* mbuf chain. Note: if offset is greater than the total mbuf
|
||||
* length, checksum=1, pktlen=0 is returned (ie. no real error code)
|
||||
*/
|
||||
int32_t tlen = 0;
|
||||
|
||||
#ifdef SCTP_USE_ADLER32
|
||||
uint32_t base = 1L;
|
||||
|
||||
#else
|
||||
uint32_t base = 0xffffffff;
|
||||
|
||||
#endif
|
||||
struct mbuf *at;
|
||||
|
||||
at = m;
|
||||
/* find the correct mbuf and offset into mbuf */
|
||||
while ((at != NULL) && (offset > (uint32_t) SCTP_BUF_LEN(at))) {
|
||||
offset -= SCTP_BUF_LEN(at); /* update remaining offset
|
||||
* left */
|
||||
at = SCTP_BUF_NEXT(at);
|
||||
}
|
||||
while (at != NULL) {
|
||||
if ((SCTP_BUF_LEN(at) - offset) > 0) {
|
||||
#ifdef SCTP_USE_ADLER32
|
||||
base = update_adler32(base,
|
||||
(unsigned char *)(SCTP_BUF_AT(at, offset)),
|
||||
(unsigned int)(SCTP_BUF_LEN(at) - offset));
|
||||
#else
|
||||
if ((SCTP_BUF_LEN(at) - offset) < 4) {
|
||||
/* Use old method if less than 4 bytes */
|
||||
base = old_update_crc32(base,
|
||||
(unsigned char *)(SCTP_BUF_AT(at, offset)),
|
||||
(unsigned int)(SCTP_BUF_LEN(at) - offset));
|
||||
} else {
|
||||
base = update_crc32(base,
|
||||
(unsigned char *)(SCTP_BUF_AT(at, offset)),
|
||||
(unsigned int)(SCTP_BUF_LEN(at) - offset));
|
||||
}
|
||||
#endif
|
||||
tlen += SCTP_BUF_LEN(at) - offset;
|
||||
/* we only offset once into the first mbuf */
|
||||
}
|
||||
if (offset) {
|
||||
if (offset < (uint32_t) SCTP_BUF_LEN(at))
|
||||
offset = 0;
|
||||
else
|
||||
offset -= SCTP_BUF_LEN(at);
|
||||
}
|
||||
at = SCTP_BUF_NEXT(at);
|
||||
}
|
||||
if (pktlen != NULL) {
|
||||
*pktlen = tlen;
|
||||
}
|
||||
#ifdef SCTP_USE_ADLER32
|
||||
/* Adler32 */
|
||||
base = htonl(base);
|
||||
#else
|
||||
/* CRC-32c */
|
||||
base = sctp_csum_finalize(base);
|
||||
#endif
|
||||
return (base);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
sctp_mtu_size_reset(struct sctp_inpcb *inp,
|
||||
struct sctp_association *asoc, uint32_t mtu)
|
||||
@ -3428,7 +3265,6 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
|
||||
}
|
||||
#endif
|
||||
socantsendmore(stcb->sctp_socket);
|
||||
socantrcvmore(stcb->sctp_socket);
|
||||
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
SCTP_SOCKET_UNLOCK(so, 1);
|
||||
#endif
|
||||
@ -3596,6 +3432,9 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
/* If the socket is gone we are out of here */
|
||||
return;
|
||||
}
|
||||
if (stcb->sctp_socket->so_rcv.sb_state & SBS_CANTRCVMORE) {
|
||||
return;
|
||||
}
|
||||
if (stcb && ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) ||
|
||||
(stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED))) {
|
||||
if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) ||
|
||||
@ -6708,14 +6547,163 @@ sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_
|
||||
* so we can do UDP tunneling. In
|
||||
* the mean-time, we return error
|
||||
*/
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
#include <sys/proc.h>
|
||||
#include <netinet6/sctp6_var.h>
|
||||
|
||||
static void
|
||||
sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
|
||||
{
|
||||
struct ip *iph;
|
||||
struct mbuf *sp, *last;
|
||||
struct udphdr *uhdr;
|
||||
uint16_t port = 0, len;
|
||||
int header_size = sizeof(struct udphdr) + sizeof(struct sctphdr);
|
||||
|
||||
/*
|
||||
* Split out the mbuf chain. Leave the IP header in m, place the
|
||||
* rest in the sp.
|
||||
*/
|
||||
if ((m->m_flags & M_PKTHDR) == 0) {
|
||||
/* Can't handle one that is not a pkt hdr */
|
||||
goto out;
|
||||
}
|
||||
/* pull the src port */
|
||||
iph = mtod(m, struct ip *);
|
||||
uhdr = (struct udphdr *)((caddr_t)iph + off);
|
||||
|
||||
port = uhdr->uh_sport;
|
||||
sp = m_split(m, off, M_DONTWAIT);
|
||||
if (sp == NULL) {
|
||||
/* Gak, drop packet, we can't do a split */
|
||||
goto out;
|
||||
}
|
||||
if (sp->m_pkthdr.len < header_size) {
|
||||
/* Gak, packet can't have an SCTP header in it - to small */
|
||||
m_freem(sp);
|
||||
goto out;
|
||||
}
|
||||
/* ok now pull up the UDP header and SCTP header together */
|
||||
sp = m_pullup(sp, header_size);
|
||||
if (sp == NULL) {
|
||||
/* Gak pullup failed */
|
||||
goto out;
|
||||
}
|
||||
/* trim out the UDP header */
|
||||
m_adj(sp, sizeof(struct udphdr));
|
||||
|
||||
/* Now reconstruct the mbuf chain */
|
||||
/* 1) find last one */
|
||||
last = m;
|
||||
while (last->m_next != NULL) {
|
||||
last = last->m_next;
|
||||
}
|
||||
last->m_next = sp;
|
||||
m->m_pkthdr.len += sp->m_pkthdr.len;
|
||||
last = m;
|
||||
while (last != NULL) {
|
||||
last = last->m_next;
|
||||
}
|
||||
/* Now its ready for sctp_input or sctp6_input */
|
||||
iph = mtod(m, struct ip *);
|
||||
switch (iph->ip_v) {
|
||||
case IPVERSION:
|
||||
{
|
||||
/* its IPv4 */
|
||||
len = SCTP_GET_IPV4_LENGTH(iph);
|
||||
len -= sizeof(struct udphdr);
|
||||
SCTP_GET_IPV4_LENGTH(iph) = len;
|
||||
sctp_input_with_port(m, off, port);
|
||||
break;
|
||||
}
|
||||
#ifdef INET6
|
||||
case IPV6_VERSION >> 4:
|
||||
{
|
||||
/* its IPv6 - NOT supported */
|
||||
goto out;
|
||||
break;
|
||||
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
m_freem(m);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
out:
|
||||
m_freem(m);
|
||||
}
|
||||
|
||||
void
|
||||
sctp_over_udp_stop(void)
|
||||
{
|
||||
return;
|
||||
struct socket *sop;
|
||||
|
||||
/*
|
||||
* This function assumes sysctl caller holds sctp_sysctl_info_lock()
|
||||
* for writting!
|
||||
*/
|
||||
if (SCTP_BASE_INFO(udp_tun_socket) == NULL) {
|
||||
/* Nothing to do */
|
||||
return;
|
||||
}
|
||||
sop = SCTP_BASE_INFO(udp_tun_socket);
|
||||
soclose(sop);
|
||||
SCTP_BASE_INFO(udp_tun_socket) = NULL;
|
||||
}
|
||||
int
|
||||
sctp_over_udp_start(void)
|
||||
{
|
||||
return (-1);
|
||||
uint16_t port;
|
||||
int ret;
|
||||
struct sockaddr_in sin;
|
||||
struct socket *sop = NULL;
|
||||
struct thread *th;
|
||||
struct ucred *cred;
|
||||
|
||||
/*
|
||||
* This function assumes sysctl caller holds sctp_sysctl_info_lock()
|
||||
* for writting!
|
||||
*/
|
||||
port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
|
||||
if (port == 0) {
|
||||
/* Must have a port set */
|
||||
return (EINVAL);
|
||||
}
|
||||
if (SCTP_BASE_INFO(udp_tun_socket) != NULL) {
|
||||
/* Already running -- must stop first */
|
||||
return (EALREADY);
|
||||
}
|
||||
th = curthread;
|
||||
cred = th->td_ucred;
|
||||
if ((ret = socreate(PF_INET, &sop,
|
||||
SOCK_DGRAM, IPPROTO_UDP, cred, th))) {
|
||||
return (ret);
|
||||
}
|
||||
SCTP_BASE_INFO(udp_tun_socket) = sop;
|
||||
/* call the special UDP hook */
|
||||
ret = udp_set_kernel_tunneling(sop, sctp_recv_udp_tunneled_packet);
|
||||
if (ret) {
|
||||
goto exit_stage_left;
|
||||
}
|
||||
/* Ok we have a socket, bind it to the port */
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
ret = sobind(sop, (struct sockaddr *)&sin, th);
|
||||
if (ret) {
|
||||
/* Close up we cant get the port */
|
||||
exit_stage_left:
|
||||
sctp_over_udp_stop();
|
||||
return (ret);
|
||||
}
|
||||
/*
|
||||
* Ok we should now get UDP packets directly to our input routine
|
||||
* sctp_recv_upd_tunneled_packet().
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
@ -94,8 +94,6 @@ sctp_timer_stop(int, struct sctp_inpcb *, struct sctp_tcb *,
|
||||
int
|
||||
sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id);
|
||||
|
||||
uint32_t sctp_calculate_sum(struct mbuf *, int32_t *, uint32_t);
|
||||
|
||||
void
|
||||
sctp_mtu_size_reset(struct sctp_inpcb *, struct sctp_association *, uint32_t);
|
||||
|
||||
|
@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/sctp_input.h>
|
||||
#include <netinet/sctp_output.h>
|
||||
#include <netinet/sctp_bsd_addr.h>
|
||||
#include <netinet/sctp_crc32.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#ifdef IPSEC
|
||||
@ -75,7 +76,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
|
||||
uint32_t vrf_id = 0;
|
||||
struct inpcb *in6p_ip;
|
||||
struct sctp_chunkhdr *ch;
|
||||
int length, mlen, offset, iphlen;
|
||||
int length, offset, iphlen;
|
||||
uint8_t ecn_bits;
|
||||
struct sctp_tcb *stcb = NULL;
|
||||
int pkt_len = 0;
|
||||
@ -126,16 +127,28 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
|
||||
/* destination port of 0 is illegal, based on RFC2960. */
|
||||
if (sh->dest_port == 0)
|
||||
goto bad;
|
||||
|
||||
SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
|
||||
"sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
|
||||
m->m_pkthdr.len,
|
||||
if_name(m->m_pkthdr.rcvif),
|
||||
m->m_pkthdr.csum_flags);
|
||||
if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
|
||||
SCTP_STAT_INCR(sctps_recvhwcrc);
|
||||
goto sctp_skip_csum;
|
||||
}
|
||||
check = sh->checksum; /* save incoming checksum */
|
||||
if ((check == 0) && (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback)) &&
|
||||
(IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &ip6->ip6_dst))) {
|
||||
SCTP_STAT_INCR(sctps_recvnocrc);
|
||||
goto sctp_skip_csum;
|
||||
}
|
||||
sh->checksum = 0; /* prepare for calc */
|
||||
calc_check = sctp_calculate_sum(m, &mlen, iphlen);
|
||||
calc_check = sctp_calculate_cksum(m, iphlen);
|
||||
SCTP_STAT_INCR(sctps_recvswcrc);
|
||||
if (calc_check != check) {
|
||||
SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n",
|
||||
calc_check, check, m, mlen, iphlen);
|
||||
SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p phlen:%d\n",
|
||||
calc_check, check, m, iphlen);
|
||||
stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
|
||||
sh, ch, &in6p, &net, vrf_id);
|
||||
if ((net) && (port)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user