- 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:
Randall Stewart 2009-02-03 11:04:03 +00:00
parent 2f4afd2125
commit a99b67833a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=188067
15 changed files with 865 additions and 771 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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_input_with_port(i_pak, off, port)
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...

View File

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

View File

@ -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 @@ sctp_load_addresses_from_init(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 */
@ -6343,6 +6357,8 @@ sctp_is_vtag_good(struct sctp_inpcb *inp, uint32_t tag, uint16_t lport, uint16_t
/* 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)) {

View File

@ -144,6 +144,7 @@ struct sctp_tagblock {
struct sctp_epinfo {
struct socket *udp_tun_socket;
struct sctpasochead *sctp_asochash;
u_long hashasocmark;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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