1966 lines
86 KiB
C
1966 lines
86 KiB
C
/* ipsctp_h.h - IPNET SCTP header template file */
|
|
|
|
/*
|
|
* Copyright (c) 2007 Wind River Systems, Inc.
|
|
*
|
|
* The right to copy, distribute or otherwise make use of this software
|
|
* may be licensed only pursuant to the terms of an applicable Wind River
|
|
* license agreement. No license to Wind River intellectual property rights
|
|
* is granted herein. All rights not licensed by Wind River are reserved
|
|
* by Wind River.
|
|
*/
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
*/
|
|
#ifndef IPSCTP_H_H
|
|
#define IPSCTP_H_H
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
/* IPSCTP private definitions */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipsctp_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifdef IPNET
|
|
#include <ipnet.h>
|
|
#include <ipnet_h.h>
|
|
#endif
|
|
|
|
#ifdef _WRS_KERNEL
|
|
#include <sys/times.h>
|
|
#endif
|
|
|
|
#ifdef IPCOM_USE_BITARRAY
|
|
#include <ipcom_bitarray.h>
|
|
#endif
|
|
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_time.h>
|
|
#include <ipsctp.h>
|
|
#include <ipsctp_sock.h>
|
|
#include "ipsctp_pkt.h"
|
|
#include "ipsctp_hash.h"
|
|
|
|
#ifdef IPMCRYPTO
|
|
#include <ip/openssl/md5.h>
|
|
#else
|
|
#include <openssl/md5.h>
|
|
#endif
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifdef IPCOM_SYSLOG_PRIORITY
|
|
#undef IPCOM_SYSLOG_PRIORITY
|
|
#endif
|
|
#define IPCOM_SYSLOG_PRIORITY IPSCTP_SYSLOG_PRIORITY
|
|
|
|
#ifdef IPCOM_SYSLOG_FACILITY
|
|
#undef IPCOM_SYSLOG_FACILITY
|
|
#endif
|
|
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPSCTP
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* DEBUG/ASSERT
|
|
*===========================================================================
|
|
*/
|
|
|
|
#ifdef IPSCTP_DEBUG
|
|
#define IPSCTP_DEBUG_LINE(x) x
|
|
#else
|
|
#define IPSCTP_DEBUG_LINE(x) IP_NOOP
|
|
#endif /* IPSCTP_DEBUG */
|
|
|
|
#define IPSCTP_DBG_STATE 0x00000001
|
|
#define IPSCTP_DBG_TIMER 0x00000002
|
|
#define IPSCTP_DBG_INPUT 0x00000004
|
|
#define IPSCTP_DBG_OUTPUT 0x00000008
|
|
#define IPSCTP_DBG_SOCK 0x00000010
|
|
#define IPSCTP_DBG_PKT 0x00000020
|
|
#define IPSCTP_DBG_CC 0x00000040
|
|
#define IPSCTP_DBG_RWND 0x00000080
|
|
#define IPSCTP_DBG_PATH 0x00000100
|
|
#define IPSCTP_DBG_MTU 0x00000200
|
|
#define IPSCTP_DBG_BUF 0x00000400
|
|
#define IPSCTP_DBG_ALL 0xFFFFFFFF
|
|
|
|
#ifdef IPSCTP_DEBUG
|
|
|
|
extern IP_PUBLIC Ip_u32 ipsctp_debug_flags;
|
|
|
|
#define IPSCTP_DBG0(flag, fm) \
|
|
do \
|
|
{ \
|
|
if ((ipsctp_debug_flags & flag) == flag) \
|
|
{ \
|
|
IPCOM_LOG0(DEBUG, fm); \
|
|
} \
|
|
} while(0)
|
|
|
|
#define IPSCTP_DBG1(flag, fm, a) \
|
|
do \
|
|
{ \
|
|
if ((ipsctp_debug_flags & flag) == flag) \
|
|
{ \
|
|
IPCOM_LOG1(DEBUG, (fm), (a)); \
|
|
} \
|
|
} while(0)
|
|
|
|
#define IPSCTP_DBG2(flag, fm, a, b) \
|
|
do \
|
|
{ \
|
|
if ((ipsctp_debug_flags & flag) == flag) \
|
|
{ \
|
|
IPCOM_LOG2(DEBUG, fm, a, b); \
|
|
} \
|
|
} while(0)
|
|
|
|
#define IPSCTP_DBG3(flag, fm, a, b, c) \
|
|
do \
|
|
{ \
|
|
if ((ipsctp_debug_flags & flag) == flag) \
|
|
{ \
|
|
IPCOM_LOG3(DEBUG, fm, a, b, c); \
|
|
} \
|
|
} while(0)
|
|
#define IPSCTP_DBG4(flag, fm, a, b, c, d) \
|
|
do \
|
|
{ \
|
|
if ((ipsctp_debug_flags & flag) == flag) \
|
|
{ \
|
|
IPCOM_LOG4(DEBUG, fm, a, b, c, d); \
|
|
} \
|
|
} while(0)
|
|
#define IPSCTP_DBG5(flag, fm, a, b, c, d, e) \
|
|
do \
|
|
{ \
|
|
if ((ipsctp_debug_flags & flag) == flag) \
|
|
{ \
|
|
IPCOM_LOG5(DEBUG, fm, a, b, c, d, e); \
|
|
} \
|
|
} while(0)
|
|
#define IPSCTP_DBG6(flag, fm, a, b, c, d, e, f) \
|
|
do \
|
|
{ \
|
|
if ((ipsctp_debug_flags & flag) == flag) \
|
|
{ \
|
|
IPCOM_LOG6(DEBUG, fm, a, b, c, d, e, f); \
|
|
} \
|
|
} while(0)
|
|
#define IPSCTP_DBG7(flag, fm, a, b, c, d, e, f, g) \
|
|
do \
|
|
{ \
|
|
if ((ipsctp_debug_flags & flag) == flag) \
|
|
{ \
|
|
IPCOM_LOG7(DEBUG, fm, a, b, c, d, e, f, g); \
|
|
} \
|
|
} while(0)
|
|
#define IPSCTP_DBG8(flag, fm, a, b, c, d, e, f, g, h) \
|
|
do \
|
|
{ \
|
|
if ((ipsctp_debug_flags & flag) == flag) \
|
|
{ \
|
|
IPCOM_LOG8(DEBUG, fm, a, b, c, d, e, f, g, h); \
|
|
} \
|
|
} while(0)
|
|
#define IPSCTP_DBG9(flag, fm, a, b, c, d, e, f, g, h, i) \
|
|
do \
|
|
{ \
|
|
if ((ipsctp_debug_flags & flag) == flag) \
|
|
{ \
|
|
IPCOM_LOG9(DEBUG, fm, a, b, c, d, e, f, g, h, i); \
|
|
} \
|
|
} while(0)
|
|
|
|
#else /* !IPSCTP_DEBUG */
|
|
|
|
#define IPSCTP_DBG0(flag, fm) IP_NOOP
|
|
#define IPSCTP_DBG1(flag, fm, a) IP_NOOP
|
|
#define IPSCTP_DBG2(flag, fm, a, b) IP_NOOP
|
|
#define IPSCTP_DBG3(flag, fm, a, b, c) IP_NOOP
|
|
#define IPSCTP_DBG4(flag, fm, a, b, c, d) IP_NOOP
|
|
#define IPSCTP_DBG5(flag, fm, a, b, c, d, e) IP_NOOP
|
|
#define IPSCTP_DBG6(flag, fm, a, b, c, d, e, f) IP_NOOP
|
|
#define IPSCTP_DBG7(flag, fm, a, b, c, d, e, f, g) IP_NOOP
|
|
#define IPSCTP_DBG8(flag, fm, a, b, c, d, e, f, g, h) IP_NOOP
|
|
#define IPSCTP_DBG9(flag, fm, a, b, c, d, e, f, g, h, i ) IP_NOOP
|
|
|
|
#endif
|
|
|
|
/* Stack specific types */
|
|
#ifdef IPNET
|
|
|
|
#ifndef IP_STACK
|
|
#define IP_STACK(x) ipnet_ ## x
|
|
#endif
|
|
#ifndef IP_STACK_CONST
|
|
#define IP_STACK_CONST(x) IPNET_ ## x
|
|
#endif
|
|
#ifndef ipstack
|
|
#define ipstack ipnet
|
|
#endif
|
|
|
|
#elif defined(IPLITE)
|
|
|
|
#ifndef IP_STACK
|
|
#define IP_STACK(x) iplite_ ## x
|
|
#endif
|
|
|
|
#ifndef IP_STACK_CONST
|
|
#define IP_STACK_CONST(x) IPLITE_ ## x
|
|
#endif
|
|
|
|
#ifndef ipstack
|
|
#define ipstack (&iplite)
|
|
#endif
|
|
#ifndef iplite_conf_max_sockets
|
|
#define iplite_conf_max_sockets IPLITE_CONF_MAX_SOCKETS
|
|
#endif
|
|
|
|
#else
|
|
#error "IPNET or IPLITE must be defined"
|
|
#endif
|
|
|
|
/* NOTE : Ipcom_list next pointer must be the first place in your structure */
|
|
#define ipsctp_list_for_each(head, cur, TYPE) \
|
|
for ((cur) = (TYPE *)ipcom_list_first(head); \
|
|
IP_NULL != (cur); \
|
|
(cur) = (TYPE *)ipcom_list_next((Ipcom_list *)(cur)))
|
|
|
|
/* differ with Ipsctp_list_for_each for you can delete element in this loop */
|
|
#define ipsctp_list_for_each_safe(head, cur, tmp, TYPE) \
|
|
for ((cur) = (TYPE *)ipcom_list_first(head), ((cur) ? (tmp) = (TYPE *)ipcom_list_next((Ipcom_list *)(cur)) : IP_NULL); \
|
|
IP_NULL != (cur); \
|
|
(cur) = (tmp), ((cur) ? (tmp) = (TYPE *)ipcom_list_next((Ipcom_list *)(cur)) : IP_NULL))
|
|
|
|
/* differ with Ipsctp_list_for_each for you can delete element in this loop */
|
|
#define ipsctp_list_for_current_each_safe(cur, tmp, TYPE) \
|
|
for (((cur) ? (tmp) = (TYPE *)ipcom_list_next((Ipcom_list *)(cur)) : IP_NULL); \
|
|
IP_NULL != (cur); \
|
|
(cur) = (tmp), ((cur) ? (tmp) = (TYPE *)ipcom_list_next((Ipcom_list *)(cur)) : IP_NULL))
|
|
|
|
#define Ipsctp_vtag Ip_u32
|
|
|
|
/* SCTP constants */
|
|
/* End-of-file marker */
|
|
/*#define IPSCTP_EOF (-1)*/
|
|
|
|
#define IPSCTP_MAX_STREAMS 2048
|
|
#define IPSCTP_MAX_DUP_TSNS 20
|
|
#define IPSCTP_LARGEST_INIT_ACCEPTED (65535 - 2048)
|
|
#define IPSCTP_INITIAL_TSN_BITMAP_SIZE 16
|
|
#define IPSCTP_MINIMAL_RWND 4960
|
|
#define IPSCTP_MIN_RWND 1500
|
|
#define IPSCTP_MAX_TSN 0xffffffff
|
|
#define IPSCTP_ADDR_IS_CONFIRMED 1
|
|
#define IPSCTP_INITIAL_CWND 4380
|
|
|
|
|
|
#define IPSCTP_MAX_TSN_BITMAP_SIZE 512
|
|
#define IPSCTP_TSN_BITMAP_INCR 32
|
|
|
|
#define IPSCTP_GET_TSN_BITMAP_SIZE_NEXT(oldsize, gap) \
|
|
((oldsize)*2 > ((gap + 7)/8 + IPSCTP_TSN_BITMAP_INCR))?((oldsize)*2):((gap + 7)/8 + IPSCTP_TSN_BITMAP_INCR)
|
|
|
|
/* silly window syndrome */
|
|
#define IPSCTP_SWS_SENDER_DEF 1420
|
|
|
|
#define IPSCTP_SWS_RECEIVER_DEF 3000
|
|
|
|
|
|
|
|
#define ipsctp_memzero(buf, size) (void)ipcom_memset((void *)(buf), 0 , (size))
|
|
|
|
typedef enum Ipsctp_notify_type_enum
|
|
{
|
|
SCTP_NOTIFY_NONE = 0,
|
|
SCTP_NOTIFY_ASSOC_UP = 1,
|
|
SCTP_NOTIFY_ASSOC_DOWN = 2,
|
|
SCTP_NOTIFY_INTERFACE_DOWN = 3,
|
|
SCTP_NOTIFY_INTERFACE_UP = 4,
|
|
SCTP_NOTIFY_SEND_FAIL = 5,
|
|
SCTP_NOTIFY_ASSOC_ABORTED = 6,
|
|
SCTP_NOTIFY_ASSOC_RESTART = 7,
|
|
SCTP_NOTIFY_PEER_SHUTDOWN = 8,
|
|
SCTP_NOTIFY_INTERFACE_CONFIRMED = 9,
|
|
SCTP_NOTIFY_REMOTE_ERROR = 10,
|
|
SCTP_NOTIFY_MAX = 11
|
|
}
|
|
Ipsctp_notify_type;
|
|
|
|
|
|
#define IPSCTP_INVALID_NOTIFY_ERR 0xffffffff
|
|
#define IPSCTP_INVALID_LINGER_TIME 0xffffffff
|
|
#define ipsctp_sock_state(sock, state) \
|
|
IP_BIT_ISSET(sock->sctp_inst->inst_flags, IPSCTP_SOCKET_##state)
|
|
#define ipsctp_list_size(list_head) ((list_head)->head->size)
|
|
#define ipsctp_check_hdr_len(stru, ch_hdr) (sizeof(stru) != ip_ntohs((ch_hdr)->length))
|
|
|
|
#define IPSCTP_GET_ASSOCID(tcb) ((tcb)->my_vtag)
|
|
|
|
/* Socket Event Options for sctp_event_subscribe */
|
|
#define IPSCTP_EVNT_FLAGS_DATA_IO (1u << 1)
|
|
#define IPSCTP_EVNT_FLAGS_ASSOCIATION (1u << 2)
|
|
#define IPSCTP_EVNT_FLAGS_ADDRESS (1u << 3)
|
|
#define IPSCTP_EVNT_FLAGS_SEND_FAILURE (1u << 4)
|
|
#define IPSCTP_EVNT_FLAGS_PEER_ERROR (1u << 5)
|
|
#define IPSCTP_EVNT_FLAGS_SHUTDOWN (1u << 6)
|
|
#define IPSCTP_EVNT_FLAGS_PARTIAL_DELIVERY (1u << 7)
|
|
#define IPSCTP_EVNT_FLAGS_ADAPTATION_LAYER (1u << 8)
|
|
#define IPSCTP_EVNT_FLAGS_AUTHENTICATION (1u << 9)
|
|
#define IPSCTP_INST_FLAG_HB_DISABLED (1u << 10)
|
|
#define IPSCTP_INST_FLAG_EXPLICIT_EOR (1u << 11)
|
|
#define IPSCTP_INST_FLAG_FRAG_INTERLEAVE (1u << 12)
|
|
#define IPSCTP_INST_FLAG_INTERLEAVE_STRMS (1u << 13)
|
|
#define IPSCTP_INST_FLAG_EXT_RCVINFO (1u << 14)
|
|
#define IPSCTP_INST_FLAG_WANT_MAPPED_V4 (1u << 15)
|
|
#define IPSCTP_INST_FLAGS_NO_FRAGMENT (1u << 16)
|
|
#define IPSCTP_INST_FLAGS_NODELAY (1u << 17)
|
|
|
|
|
|
|
|
|
|
|
|
/* Socket stack specific defines */
|
|
#ifdef IPNET
|
|
#define IPSCTP_STACK_BIND(s, n, l, r) (s)->ops->bind(s, n, l, r)
|
|
#define IPSCTP_SOCK_VR(s) ((s)->vr_index)
|
|
#define IPSCTP_SOCK_TYPE(sk) ((sk)->ipcom.type)
|
|
#define IPSCTP_SOCK_DOMAIN(sk) ((sk)->ipcom.domain)
|
|
#define IPSCTP_IS_SOCK_TYPE(sk, type) (type == ((sk)->ipcom.type))
|
|
#else /* IPLITE */
|
|
#define IPSCTP_STACK_BIND(s, n, l, r) iplite_do_bind(s, n, l, r)
|
|
#define IPSCTP_SOCK_VR(s) 0
|
|
#endif
|
|
|
|
/* socket other MACROS */
|
|
#define IPSCTP_SIZE_LADDR_ENTRY (sizeof(Ipsctp_laddr_entry))
|
|
#define IPSCTP_SIZE_TCB_ENTRY (sizeof(Ipsctp_tcb))
|
|
#define IPSCTP_SIZE_LADDR (sizeof(Ipsctp_addr))
|
|
#define IPSCTP_SIZE_TCB (sizeof(Ipsctp_tcb))
|
|
#define IPSCTP_SIZE_SNDRCVINFO (sizeof(Ipsctp_sctp_sndrcvinfo))
|
|
|
|
/* SCTP tcb control flags */
|
|
#define IPSCTP_TCBC_FLAG_ASSOC_UP_SENT (1 << 0) /* */
|
|
#define IPSCTP_TCBC_FLAG_ASSOC_RESTART (1 << 1) /* */
|
|
#define IPSCTP_TCBC_FLAG_SAW_GAP_SACK (1 << 2) /* Is previous ack gap? used to revoke the sack */
|
|
#define IPSCTP_TCBC_FLAG_HAD_ENOBUF (1 << 3)
|
|
#define IPSCTP_TCBC_FLAG_DELAY_CONNECT (1 << 4) /* delayed connection flag */
|
|
#define IPSCTP_TCBC_FLAG_HB_DISABLED (1 << 5) /* heartbeat disabled */
|
|
#define IPSCTP_TCBC_FLAG_NEED_SEND_ACK (1 << 6) /* whether it is in partial delivery? */
|
|
#define IPSCTP_TCBC_FLAG_LISTEN (1 << 7) /* This is a dummy TCB for listening socket */
|
|
#define IPSCTP_TCBC_FLAG_DACK_PENDING (1 << 8) /* delay ack timer is running */
|
|
#define IPSCTP_TCBC_FLAG_HB_PENDING (1 << 9) /* heartbeat timer is running */
|
|
#define IPSCTP_TCBC_FLAG_FAST_RECOVERY (1 << 10) /* RFC2582 fast recovery */
|
|
#define IPSCTP_TCBC_FLAG_SAT_T3_LOSS_RECOVERY (1 << 11) /* set this flag in t3 timer */
|
|
|
|
#define IPSCTP_TCBC_FLAG_IPV4_ALLOW (1 << 12) /* allow bound ipv4 address */
|
|
#define IPSCTP_TCBC_FLAG_IPV6_ALLOW (1 << 13) /* allow bound ipv6 address */
|
|
#define IPSCTP_TCBC_FLAG_SCOPE_V6LOCAL (1 << 14) /* ipv6 local address */
|
|
#define IPSCTP_TCBC_FLAG_SCOPE_V6SITE (1 << 15) /* ipv6 site address */
|
|
#define IPSCTP_TCBC_FLAG_SCOPE_V4LOCAL (1 << 16) /* ipv4 private address */
|
|
#define IPSCTP_TCBC_FLAG_SCOPE_V4LOOPBACK (1 << 17) /* ipv4 loopback address */
|
|
|
|
#define IPSCTP_TCBC_FLAG_CONNECTING (1 << 18) /* TCB is connecting */
|
|
#define IPSCTP_TCBC_FLAG_CONNECTED (1 << 19) /* TCB is connected */
|
|
|
|
#define IPSCTP_TCBC_FLAG_ABORT (1 << 20) /* TCB has aborted */
|
|
|
|
|
|
#define IPSCTP_IS_LISTEN_INSTANCE(inst) (IP_BIT_ISSET((inst)->inst_flags, IPSCTP_SOCKET_LISTENING))
|
|
#define IPSCTP_IS_LISTEN_TCB(tcb) (IP_BIT_ISSET((tcb)->tcb_flags, IPSCTP_TCBC_FLAG_LISTEN))
|
|
|
|
|
|
#define IPSCTP_GET_STATE(tcb) (tcb)->state
|
|
#define IPSCTP_SET_STATE(tcb, tcb_state) (tcb)->state = tcb_state
|
|
|
|
#if 0
|
|
#define IPSCTP_ZERO_SUB(a,b) (((a) > (b)) ? ((a) - (b)) : 0)
|
|
#else
|
|
|
|
#define IPSCTP_UNSIGNED_SUB(a,b) (((a) > (b)) ? ((a) - (b)) : 0)
|
|
|
|
#define IPSCTP_ZERO_SUB(a,b) (((a) >= (b)) ? ((a) - (b))\
|
|
: (ipsctp_log3int(IPCOM_LOG_ERR, 0, "FILE "__FILE__" LINE %d IPSCTP_ZERO_SUB abnormal a %u b %u\n",\
|
|
__LINE__, a, b)\
|
|
,0))
|
|
#endif
|
|
|
|
#if 0
|
|
#define IPSCTP_ATOMIC_ZERO_SUB(a,b)\
|
|
((ipcom_atomic_get((Ipcom_atomic_t *)&a) > (b)) ? \
|
|
ipcom_atomic_sub((Ipcom_atomic_t *)&a,(b))\
|
|
: ipcom_atomic_set((Ipcom_atomic_t *)&a, 0))
|
|
|
|
#else
|
|
#define IPSCTP_ATOMIC_ZERO_SUB(a,b)\
|
|
((ipcom_atomic_get((Ipcom_atomic_t *)&a) >= (b)) ? \
|
|
ipcom_atomic_sub((Ipcom_atomic_t *)&a,(b))\
|
|
: ((void)ipsctp_log3int(IPCOM_LOG_ERR, 0, "FILE "__FILE__" LINE %d IPSCTP_ATOMIC_ZERO_SUB abnormal a %d b %d\n",\
|
|
__LINE__, ipcom_atomic_get((Ipcom_atomic_t *)&a),b)\
|
|
,ipcom_atomic_set((Ipcom_atomic_t *)&a, 0)))
|
|
#endif
|
|
|
|
#if 0
|
|
#define IPSCTP_ZERO_SUB_ASSIGN(a,b) ((a) = (((a) > (b)) ? ((a) - (b)) : 0))
|
|
#else
|
|
#define IPSCTP_ZERO_SUB_ASSIGN(a,b) ((a) = (((a) >= (b)) ? ((a) - (b))\
|
|
: (ipsctp_log3int(IPCOM_LOG_ERR, 0, "FILE "__FILE__" LINE %d IPSCTP_ZERO_SUB_ASSIGN abnormal a %d b %d\n",\
|
|
__LINE__, a, b)\
|
|
,0)))
|
|
#define IPSCTP_UNSIGNED_SUB_ASSIGN(a,b) ((a) = (((a) >= (b)) ? ((a) - (b)) : 0))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define IPSCTP_TSN_SUB(a, b) (((a) > (b)) ? ((a) - (b)) : (IPSCTP_MAX_TSN - (b) + (a) + 1))
|
|
|
|
#define IPSCTP_IS_GT_16(s1, s2) ((Ip_s16) ((s1) - (s2)) > 0)
|
|
#define IPSCTP_IS_GEQ_16(s1, s2) ((Ip_s16) ((s1) - (s2)) >= 0)
|
|
#define IPSCTP_IS_LT_16(s1, s2) ((Ip_s16) ((s1) - (s2)) < 0)
|
|
#define IPSCTP_IS_LEQ_16(s1, s2) ((Ip_s16) ((s1) - (s2)) <= 0)
|
|
|
|
#define ipsctp_copy_to_user(sock,s1,s2,n) ( IPCOM_UNUSED_ARG(sock), ipcom_copy_to_user(s1,s2,n) )
|
|
#define ipsctp_copy_from_user(sock,s1,s2,n) ( IPCOM_UNUSED_ARG(sock), ipcom_copy_from_user(s1,s2,n) )
|
|
|
|
#define IPSCTP_DATA_LEN_ALIGN(len) (((len) + 3) & ~0x3)
|
|
|
|
|
|
/* SCTP tcb peer control flags */
|
|
#define IPSCTP_TCBC_FLAG_SUPPORT_PKT_DROP (1 << 0) /* support packet drop draft */
|
|
#define IPSCTP_TCBC_FLAG_SUPPORT_STREAM_RESET (1 << 0) /* support stream reset draft */
|
|
#define IPSCTP_TCBC_FLAG_SUPPORT_AUTH (1 << 0) /* support auth rfc */
|
|
#define IPSCTP_TCBC_FLAG_SUPPORT_PRSCTP (1 << 0) /* support prsctp */
|
|
#define IPSCTP_TCBC_FLAG_SUPPORT_ASCONF (1 << 0) /* support acconf */
|
|
|
|
/* SCTP chunk control flag, for receive or send status of chunks */
|
|
|
|
/* the lower 4 bits store the chunk send state, like IPSCTP_CHUNK_FLAG_SEND_STATE_XXX */
|
|
|
|
#define IPSCTP_CHUNK_FLAG_SEND_STATE_UNSENT 0
|
|
#define IPSCTP_CHUNK_FLAG_SEND_STATE_SENT 1
|
|
#define IPSCTP_CHUNK_FLAG_SEND_STATE_RESEND 4
|
|
#define IPSCTP_CHUNK_FLAG_SEND_STATE_ACKED 5 /* has been acked */
|
|
#define IPSCTP_CHUNK_FLAG_SEND_STATE_MARKED 6 /* SACKED by SACK GAP in current SACK chunk */
|
|
|
|
|
|
#define IPSCTP_CHUNK_FLAG_GET_SEND_STATE(flag) ((flag) & 0x000f)
|
|
#define IPSCTP_CHUNK_FLAG_SET_SEND_STATE(flag, state) ((flag) = ((flag) & 0xfff0) | ((state) & 0x0f))
|
|
#define IPSCTP_CHUNK_FLAG_INC_SEND_STATE(flag) ((flag) = ((flag) & 0xfff0) | ((((flag) & 0x0f) + 1) & 0x0f))
|
|
|
|
|
|
#define IPSCTP_CHUNK_FLAG_SEND (1 << 4) /* chunks in receive queue */
|
|
#define IPSCTP_CHUNK_FLAG_SEND_REVOKED (1 << 5) /* this chunk was revoked */
|
|
#define IPSCTP_CHUNK_FLAG_SEND_DO_RTT (1 << 6) /* this chunk will do rtt */
|
|
#define IPSCTP_CHUNK_FLAG_SEND_DO_FR (1 << 7) /* this chunk is doing fast retransmitting */
|
|
|
|
#define IPSCTP_CHUNK_FLAG_SEND_END (1 << 8) /* The (E)nding fragment bit, if set, indicates
|
|
the last fragment of a user message.*/
|
|
#define IPSCTP_CHUNK_FLAG_SEND_BEGIN (1 << 9) /* The (B)eginning fragment bit, if set, indicates
|
|
the first fragment of a user message. */
|
|
|
|
#define IPSCTP_CHUNK_FLAG_SEND_WIN_PROBE (1 << 10) /* this chunk is doing window probe */
|
|
#define IPSCTP_CHUNK_FLAG_SEND_ND_ADJUST (1 << 11) /* The Start and End position should be adjust
|
|
* for retransmission. */
|
|
|
|
#define IPSCTP_CHUNK_FLAG_RECV (1 << 4) /* chunks in send queue */
|
|
#define IPSCTP_CHUNK_FLAG_RECV_FRAGMENT (1 << 5) /* the fragment flag in socket receive buffer
|
|
* or input stream queue */
|
|
|
|
#define IPSCTP_CHUNK_FLAG_USR_RECV_IN (1 << 6) /* in the process of user receiving */
|
|
#define IPSCTP_CHUNK_FLAG_RECV_FIN (1 << 7) /* the whole chunk has been delivered to
|
|
* socket receive buffer or input stream queue completely.
|
|
* For fragmented chunk, this flag means all chunk fragments
|
|
* are received; for unfragmented chunk, this flag is not
|
|
* applicable. */
|
|
|
|
#define IPSCTP_CHUNK_FLAG_RECV_NOTIFICATION (1 << 8)
|
|
|
|
#define IPSCTP_IS_FIRST_FRAGMENT(chunk) \
|
|
((((chunk)->sndrcv_info.sinfo_flags >> 8) & IPSCTP_FLAG_DATA_FRAG_MASK) == IPSCTP_FLAG_DATA_FIRST_FRAG)
|
|
|
|
#define IPSCTP_IS_MIDDLE_FRAGMENT(chunk) \
|
|
((((chunk)->sndrcv_info.sinfo_flags >> 8) & IPSCTP_FLAG_DATA_FRAG_MASK) == IPSCTP_FLAG_DATA_MIDDLE_FRAG)
|
|
|
|
#define IPSCTP_IS_LAST_FRAGMENT(chunk) \
|
|
((((chunk)->sndrcv_info.sinfo_flags >> 8) & IPSCTP_FLAG_DATA_FRAG_MASK) == IPSCTP_FLAG_DATA_LAST_FRAG)
|
|
|
|
|
|
|
|
#if 0 /* defined in ipsctp_pkt.h*/
|
|
/*
|
|
* SCTP error cause, RFC4960
|
|
*/
|
|
#define IPSCTP_CAUSE_NO_ERROR 0x0000
|
|
#define IPSCTP_CAUSE_INVALID_STREAM 0x0001
|
|
#define IPSCTP_CAUSE_MISSING_PARAM 0x0002
|
|
#define IPSCTP_CAUSE_STALE_COOKIE 0x0003
|
|
#define IPSCTP_CAUSE_OUT_OF_RESC 0x0004
|
|
#define IPSCTP_CAUSE_UNRESOLVABLE_ADDR 0x0005
|
|
#define IPSCTP_CAUSE_UNRECOG_CHUNK 0x0006
|
|
#define IPSCTP_CAUSE_INVALID_PARAM 0x0007
|
|
#define IPSCTP_CAUSE_UNRECOG_PARAM 0x0008
|
|
#define IPSCTP_CAUSE_NO_USER_DATA 0x0009
|
|
#define IPSCTP_CAUSE_COOKIE_IN_SHUTDOWN 0x000a
|
|
#define IPSCTP_CAUSE_RESTART_W_NEWADDR 0x000b
|
|
#define IPSCTP_CAUSE_USER_INITIATED_ABT 0x000c
|
|
#define IPSCTP_CAUSE_PROTOCOL_VIOLATION 0x000d
|
|
|
|
#define IPSCTP_CAUSE_SET(flag, cause) IP_BIT_SET(flag, (1 << cause) )
|
|
#endif
|
|
|
|
/*The action when returning from input processing */
|
|
#define IPSCTP_ACTION_SEND_ABORT (1 << 0)
|
|
#define IPSCTP_ACTION_SEND_COOKIE_ECHO (1 << 1)
|
|
|
|
|
|
|
|
#ifdef IPNET_STATISTICS
|
|
#define IPSCTP_STATISTICS
|
|
#endif
|
|
|
|
#define IPSCTP_INPUT_DONE 0
|
|
#define IPSCTP_INPUT_STOP_PROCESSING 1 /* Drop the packet, no internal state must change */
|
|
#define IPSCTP_INPUT_IN_ORDER_SUCCESS 2 /* Packet delivered successfully */
|
|
#define IPSCTP_INPUT_CONT 3
|
|
#define IPSCTP_INPUT_IGNORE_CHUNK 4
|
|
#define IPSCTP_INPUT_NOTIFY_USER_READ 5
|
|
|
|
/* hmac definition */
|
|
#define IPSCTP_SIG_MAX_SIZE MD5_LBLOCK
|
|
|
|
#define IPSCTP_BLK_MAX_SIZE MD5_CBLOCK
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP code lock
|
|
*===========================================================================
|
|
*/
|
|
#ifdef IPNET
|
|
# define IPSCTP_CODE_LOCK_READ() IPNET_CODE_LOCK_READ()
|
|
# define IPSCTP_CODE_LOCK_WRITE() IPNET_CODE_LOCK_WRITE()
|
|
# define IPSCTP_CODE_LOCK() IPSCTP_CODE_LOCK_WRITE()
|
|
# define IPSCTP_CODE_UNLOCK() IPNET_CODE_UNLOCK()
|
|
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
#define IPSCTP_DATA_TCBLOCK(sl) do {} while(0)
|
|
#define IPSCTP_DATA_TCBUNLOCK(sl) do {} while(0)
|
|
#define IPSCTP_DATA_LOCK(sl) ipcom_enter_critical_region()
|
|
#define IPSCTP_DATA_UNLOCK(sl) ipcom_exit_critical_region()
|
|
#else
|
|
#define IPSCTP_DATA_TCBLOCK(sl) IPNET_DATA_LOCK(sl)
|
|
#define IPSCTP_DATA_TCBUNLOCK(sl) IPNET_DATA_UNLOCK(sl)
|
|
#define IPSCTP_DATA_LOCK(sl) IPNET_DATA_LOCK(sl)
|
|
#define IPSCTP_DATA_UNLOCK(sl) IPNET_DATA_UNLOCK(sl)
|
|
#endif
|
|
|
|
# define IPSCTP_DATA_ISLOCKED(sl) IPNET_DATA_ISLOCKED(sl)
|
|
# define IPSCTP_DATA_ISLOCKED_ASSERT(sl) IPNET_DATA_ISLOCKED_ASSERT(sl)
|
|
# ifdef IPNET_SMP_OPTIMIZED
|
|
# define IPSCTP_SMP_OPTIMIZED
|
|
# endif
|
|
#else /* IPLITE */
|
|
# define IPSCTP_CODE_LOCK_READ() IPLITE_CODE_LOCK()
|
|
# define IPSCTP_CODE_LOCK_WRITE() IPLITE_CODE_LOCK()
|
|
# define IPSCTP_CODE_LOCK() IPSCTP_CODE_LOCK_WRITE()
|
|
# define IPSCTP_CODE_UNLOCK() IPLITE_CODE_UNLOCK()
|
|
# define IPSCTP_DATA_LOCK(x) IP_NOOP
|
|
# define IPSCTP_DATA_UNLOCK(x) IP_NOOP
|
|
# define IPSCTP_DATA_ISLOCKED(x) IP_FALSE
|
|
# define IPSCTP_DATA_ISLOCKED_ASSERT(sl) IP_NOOP
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP association states
|
|
*===========================================================================
|
|
* Current state information for an association.
|
|
*/
|
|
typedef enum
|
|
{
|
|
IPSCTP_STATE_LISTEN = 0,
|
|
IPSCTP_STATE_CLOSED = 1,
|
|
IPSCTP_STATE_COOKIE_WAIT,
|
|
IPSCTP_STATE_COOKIE_ECHOED,
|
|
IPSCTP_STATE_ESTABLISHED,
|
|
IPSCTP_STATE_SHUTDOWN_PENDING,
|
|
IPSCTP_STATE_SHUTDOWN_RECEIVED,
|
|
IPSCTP_STATE_SHUTDOWN_SENT,
|
|
IPSCTP_STATE_SHUTDOWN_ACK_SENT,
|
|
IPSCTP_STATE_MAX
|
|
}
|
|
Ipsctp_state;
|
|
|
|
/* SCTP reachability state for each remote address */
|
|
#define IPSCTP_ADDR_REACHABLE 0x001
|
|
#define IPSCTP_ADDR_NOHB 0x004
|
|
#define IPSCTP_ADDR_BEING_DELETED 0x008
|
|
#define IPSCTP_ADDR_NOT_IN_ASSOC 0x010
|
|
#define IPSCTP_ADDR_USER_PRIMARY 0x040 /* specified as primary by user, \
|
|
* or as primary during connection establishment. \
|
|
*/
|
|
#define IPSCTP_ADDR_OUT_OF_SCOPE 0x080
|
|
#define IPSCTP_ADDR_DOUBLE_SWITCH 0x100
|
|
#define IPSCTP_ADDR_UNCONFIRMED 0x200
|
|
#define IPSCTP_ADDR_REQ_PRIMARY 0x400 /* request for being primary,but now maybe UNCONFIRMED */
|
|
#define IPSCTP_ADDR_RXT_PENDING 0x800 /* T3 timer running */
|
|
#define IPSCTP_ADDR_FR_PENDING 0x1000 /* FR timer running */
|
|
#define IPSCTP_ADDR_FLAG_NO_SMDE 0x2000 /* No Smooth mean deviation estimator calculated yet */
|
|
#define IPSCTP_ADDR_FLAG_RTT 0x4000 /* Flag to track if one of the DATA chunks
|
|
* sent to this address is currently being
|
|
* used to compute an RTT. If this flag is 0,
|
|
* the next DATA chunk sent to this
|
|
* destination should be used to compute an
|
|
* RTT and this flag should be set. Every
|
|
* time the RTT calculation completes (i.e.,
|
|
* the DATA chunk is SACK'd), the flag is
|
|
* cleared.
|
|
*/
|
|
|
|
#define IPSCTP_ADDR_SRC_SELECTED 0x8000 /* selected source address for peer */
|
|
#define IPSCTP_ADDR_WINDOW_PROBE 0x10000 /* doing a window probe */
|
|
#define IPSCTP_ADDR_DATA_SENT 0x20000 /* some data sent during heartbeat interval.
|
|
* Set when data is sent and clear in heartbeat timer
|
|
*/
|
|
#define IPSCTP_ADDR_NOT_IN_RT 0x40000 /* the selected source address doesn't belong to rt_entry */
|
|
#define IPSCTP_ADDR_EVER_SELECTED 0x80000 /* this transport has ever been selected */
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP local address parameters
|
|
*===========================================================================
|
|
* This union are defined for handling SCTP socket address.
|
|
*/
|
|
typedef union Ip_sockaddr_union Ipsctp_addr;
|
|
/*#define Ipsctp_addr Ip_sockaddr_union*/
|
|
|
|
#if 0
|
|
#define IPSCTP_ADDR_SET_PORT(sctp_addr, port)
|
|
#define IPSCTP_GET_PORT_FROM_SCTP_ADDR(addr) (((addr)->sa.sa_family == IP_AF_INET)?\
|
|
((addr)->sin.sin_port):((addr)->sin6.sin6_port)
|
|
|
|
|
|
#define IPSCTP_SET_PORT_FOR_SOADDRESS(soaddr, port) (((soaddr)->sa_family == IP_AF_INET)?\
|
|
(((Ip_sockaddr_in *)(soaddr))->sin_port = (port)):(((Ip_sockaddr_in6 *)(soaddr))->sin6_port = (port))
|
|
#endif
|
|
|
|
typedef struct Ipsctp_af_ops_struct
|
|
{
|
|
Ipcom_list list;
|
|
/* compare two sctp addresses */
|
|
Ip_bool (*cmp_addr)(const Ipsctp_addr *addr1, const Ipsctp_addr *addr2);
|
|
|
|
/* compare lookup key with sctp address*/
|
|
Ip_bool (*cmp_addr_key)(IP_CONST Ipsctp_addr *addr, IP_CONST union Ip_in_addr_union *key, Ip_u16 domain);
|
|
|
|
/* get internet address from input buffer */
|
|
void (*load_in_addr)(IP_CONST void *addr, union Ip_in_addr_union * in_address);
|
|
/* get in_addr from sctp address */
|
|
void * (*get_in_addr)(IP_CONST Ipsctp_addr *addr);
|
|
Ip_u32 (*get_scope_id)(IP_CONST Ipsctp_addr *addr);
|
|
void (*ip_transmit)(IP_CONST void *dst, IP_CONST void *src, Ipcom_pkt *pkt);
|
|
void (*load_soaddr)(IP_CONST void *addr, IP_CONST Ip_u16 port, Ipsctp_addr *sock_addr);
|
|
void (*get_mtu_and_mss)(struct Ipsctp_tcb_struct *tcb,\
|
|
struct Ipsctp_transport_struct *transport,\
|
|
Ipnet_route_entry **rt_ret);
|
|
void (*addr_set_port)(Ipsctp_addr *sctp_addr, IP_CONST Ip_u16 port);
|
|
int (*src_addr_selection)(struct Ipsctp_tcb_struct *tcb, Ipnet_route_entry *rt,\
|
|
Ip_u16 lport, struct Ipsctp_transport_struct *transport);
|
|
void (*rotate_src_addr)(struct Ipsctp_tcb_struct *tcb, struct Ipsctp_transport_struct *transport);
|
|
void (*set_addr_for_socket)(struct Ipsctp_transport_struct *transport, Ipsctp_socket *sock);
|
|
Ip_sa_family_t sa_family;
|
|
}Ipsctp_af_ops;
|
|
|
|
typedef enum Ipsctp_laddr_state_enum
|
|
{
|
|
IPSCTP_LADDR_NORMAL = 1 /* normal state local IP address */
|
|
/* need to extend... */
|
|
}
|
|
Ipsctp_laddr_state;
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP local address entry parameters
|
|
*===========================================================================
|
|
* The structure are defined for the entry of list(laddrs_list) in structure
|
|
* Ipsctp_instance_struct.
|
|
*/
|
|
typedef struct Ipsctp_laddrs_entry_struct
|
|
{
|
|
Ipcom_list next; /* Keep list entry first */
|
|
Ipsctp_addr laddr; /* Local sctp bind address */
|
|
Ipsctp_laddr_state state; /* Local IP address state */
|
|
Ip_u32 start_time; /* sctpAssocLocalAddrStartTime, mib*/
|
|
}
|
|
Ipsctp_laddr_entry;
|
|
|
|
|
|
#ifdef IPSCTP_MIB
|
|
|
|
#define IPSCTP_MIB_STATS(xvar) ipsctp->mib_stats.xvar
|
|
|
|
#define IPSCTP_MIB_STAT_LINE(xline) xline
|
|
|
|
#else /* No SCTP mib stats */
|
|
#define IPSCTP_MIB_STATS(xvar) IP_NOOP
|
|
#define IPSCTP_MIB_STAT_LINE(xline) IP_NOOP
|
|
#endif /* ifdef IPSCTP_MIB */
|
|
|
|
#if defined(IPSCTP_DEBUG) || defined(IPSCTP_STATISTICS)
|
|
typedef struct Ipsctp_stats_struct
|
|
{
|
|
/* Other Statistics */
|
|
Ip_u32 sctp_input;
|
|
Ip_u32 sctp_input_hdr_trunc;
|
|
Ip_u32 sctp_input_tcb_nomatch;
|
|
Ip_u32 sctp_input_tcb_match;
|
|
Ip_u32 sctp_input_bad_vtag;
|
|
Ip_u32 sctp_input_dup_chunks;
|
|
Ip_u32 sctp_tsn_bitmap_expand;
|
|
Ip_u32 sctp_input_drop_chunks_bitmap;
|
|
Ip_u32 sctp_input_drop_chunks_invalid_sid;
|
|
Ip_u32 sctp_input_drop_chunks_no_buf;
|
|
|
|
Ip_u32 sctp_input_chunks_express;
|
|
Ip_u32 sctp_input_chunks_express_pd;
|
|
Ip_u32 sctp_input_chunks_queue2buf;
|
|
Ip_u32 sctp_input_chunks_queue2pd;
|
|
Ip_u32 sctp_input_chunks_pd;
|
|
Ip_u32 sctp_input_chunks_fragment;
|
|
Ip_u32 sctp_input_chunks_queued_fragment;
|
|
Ip_u32 sctp_input_chunks_not_fragment; /* all input non-fragment chunks*/
|
|
Ip_u32 sctp_input_chunks_queued_not_fragment; /* all input non-fragment chunks
|
|
* queued in input stream queue.
|
|
*/
|
|
Ip_u32 sctp_input_msgs_reasm_queued;
|
|
|
|
Ip_u32 sctp_input_chunks_buf2user;
|
|
Ip_u32 sctp_input_chunks_fragment2user;
|
|
|
|
Ip_u32 sctp_input_msgs_reasm_2user;
|
|
|
|
Ip_u32 sctp_output_window_update;
|
|
|
|
Ip_u32 sctp_read_peeks;
|
|
|
|
Ip_u32 sctp_output_data; /* number of usr send data times(all) */
|
|
Ip_u32 sctp_output_data_err; /* number of usr send data times(failure) */
|
|
Ip_u32 sctp_output_data_chunk; /* number of the output data chunks(all) */
|
|
Ip_u32 sctp_output_data_chunk_err; /* number of the output data chunks(failure) */
|
|
Ip_u32 sctp_output_data_chunk_retr; /* number of the retransmit data chunks(all) */
|
|
Ip_u32 sctp_output_data_chunk_retr_err; /* number of the retransmit data chunks(failure) */
|
|
Ip_u32 sctp_output_ctrl_chunk; /* number of the output control chunks(all) */
|
|
Ip_u32 sctp_output_ctrl_chunk_err; /* number of the output control chunks(failure) */
|
|
Ip_u32 sctp_output_pkt; /* number of output sctp packets(all) */
|
|
Ip_u32 sctp_output_pkt_err; /* number of output sctp packets(failure) */
|
|
Ip_u32 sctp_output_data_chunk_cwnd; /* number of output new data not allowed by cwnd */
|
|
Ip_u32 sctp_output_data_chunk_cwnd_retr; /* number of output retransmit data not allowed by cwnd */
|
|
Ip_u32 sctp_output_data_chunk_nagle; /* number of output retransmit data not allowed by Nagle */
|
|
Ip_u32 sctp_output_data_chunk_mult_owner; /* number of output retransmit data not allowed by Multi_owner */
|
|
|
|
}
|
|
Ipsctp_stats;
|
|
|
|
#define IPSCTP_STATS(xvar) ipsctp->stats.xvar
|
|
|
|
#define IPSCTP_STAT_LINE(xline) xline
|
|
|
|
#else /* No SCTP stats */
|
|
#define IPSCTP_STATS(xvar) IP_NOOP
|
|
#define IPSCTP_STAT_LINE(xline) IP_NOOP
|
|
#endif /* defined(IPSCTP_DEBUG) || defined(IPSCTP_STATISTICS) */
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP DATA CONTROL (IPSCTP DATA)
|
|
*===========================================================================
|
|
|
|
*/
|
|
typedef struct Ipsctp_data_struct
|
|
{
|
|
Ipcom_list address_families; /* address families list*/
|
|
|
|
Ipcom_list free_chunk_list; /* List of free SCTP chunk structures */
|
|
Ip_u32 msec_last_sock_create; /* The time a socket was last created */
|
|
|
|
Ipsctp_hash *tcb_hashtable; /* indexed by vtag
|
|
* All sctp assocation in hash table
|
|
* size hidden in Ipsctp_hash
|
|
* hash key(v-tag) */
|
|
Ipsctp_hash *tcb_hashtable_port; /* indexed by local port and remote port
|
|
* All sctp assocation in hash table
|
|
* size hidden in Ipsctp_hash
|
|
* hash key(local port and remote port) */
|
|
Ipsctp_hash *vtag_timewait;
|
|
Ipcom_list vtag_timers;
|
|
Ip_u32 cnt_tcb; /* Current count of TCB */
|
|
#ifndef IPCOM_FORWARDER_NAE
|
|
/*
|
|
* List of active socket instances. All of the sockets in this list must be
|
|
* checked for timeouts each tick.
|
|
*/
|
|
Ipcom_list active_head;
|
|
#endif
|
|
#if defined(IPSCTP_DEBUG) || defined(IPSCTP_STATISTICS)
|
|
Ipsctp_stats stats; /* Statistics */
|
|
#endif
|
|
#ifdef IPSCTP_MIB
|
|
Ipsctp_mib_stats mib_stats; /* Statistics */
|
|
#endif
|
|
int opt_tcb_lookup; /* optimize tcb lookup */
|
|
Ip_u32 max_chunks_on_queue; /* max chunks on queue per association */
|
|
#ifdef IPSCTP_FAST_RETRANSMITE
|
|
Ip_bool early_fr; /* early fast retransmission */
|
|
#endif
|
|
}
|
|
Ipsctp_data;
|
|
|
|
IP_EXTERN Ipsctp_data *ipsctp;
|
|
IP_EXTERN Ipcom_pkt *ipsctp_tx_list; /* List of SCTP finished segments that are
|
|
waiting to be transmitted. This list
|
|
points to the last SCTP segment to be
|
|
sent */
|
|
|
|
#define IPSCTP_RTO_ALPHA (3)
|
|
#define IPSCTP_RTO_BETA (2)
|
|
#define IPSCTP_CLOCK_GRANULARITY (1)
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP peer transport parameters
|
|
*===========================================================================
|
|
* One instance of this structure exists for each destination transport
|
|
* address in the sctp association's address list derived from the INIT
|
|
* or INIT ACK chunk.
|
|
* TODO: Considerations for alignment
|
|
* Whether or not to have more seperate timers or only one handler?
|
|
* rto_pending not clear yet?
|
|
pmtu_timer(mtu increase periodically?) need more investigation
|
|
fr_timer need more investigation
|
|
hb_timer per association or per transport? what is heartbeat random?
|
|
*/
|
|
typedef struct Ipsctp_transport_struct
|
|
{
|
|
Ipcom_list trans_next; /* next transport in list */
|
|
Ipsctp_addr paddr; /* the address to which this info belongs */
|
|
Ipsctp_addr saddr; /* the selected source address */
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
Ip_sa_family_t address_family; /* just save the address family */
|
|
#else
|
|
Ipsctp_af_ops *af_ops; /* address family specific operations*/
|
|
#endif
|
|
int ops_handle; /* handle to socket family specific operations*/
|
|
/* Following is from rfc 13.3. Per Transport Address Data */
|
|
Ip_u32 err_cnt; /* The current error count for this destination */
|
|
Ip_u32 err_thresh; /* Current error threshold for this destination, i.e.,
|
|
* what value marks the destination down if error count
|
|
* reaches this value. sctpAssocRemAddrMaxPathRtx */
|
|
Ip_u32 cwnd; /* The current congestion window */
|
|
Ip_u32 ssthresh; /* The current ssthresh value */
|
|
Ip_u32 rto; /* The current retransmission timeout value */
|
|
Ip_u32 srtt; /* The current smoothed round-trip time */
|
|
Ip_u32 rttvar; /* The current RTT variation */
|
|
Ip_u32 pt_bytes_acked; /* The tracking method for increase of cwnd when in
|
|
* bytes acked : congestion avoidance mode (see Section 7.2.2).*/
|
|
Ip_u32 flight_size; /* bytes of sent and not acked chunks */
|
|
Ip_u32 net_ack; /* The total byte count acked */
|
|
Ip_u32 net_ack2; /* track the total bytes acked that are unambiguous and were never retransmitted*/
|
|
|
|
Ip_u32 state; /* The current state of this destination, i.e., DOWN, UP,
|
|
* ALLOW-HB, NO-HEARTBEAT, etc. See IPSCTP_ADDR_XXX */
|
|
Ip_u32 pmtu; /* The current known path MTU */
|
|
Ip_u32 mss; /* The current known mss, incluing chunk header */
|
|
Ipsctp_timer rxt_timer;
|
|
/* Timer used by each destination */
|
|
|
|
Ip_u32 tos_flowlabel;
|
|
struct Ip_timeval last_sent_time; /* The time to which this destination was last sent.
|
|
* This can be to determine if a HEARTBEAT is needed. */
|
|
Ip_u32 hbinterval; /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
|
|
* the destination address every heartbeat interval.*/
|
|
/* Remote Address Statistic in RFC3873. */
|
|
Ip_u32 start_time; /* sctpAssocRemAddrStartTime.
|
|
* The value of sysUpTime at the time that this row was
|
|
* created. */
|
|
#ifdef IPSCTP_MIB
|
|
Ip_u32 marked_retrans; /* sctpAssocRemAddrRtx.
|
|
* Number of DATA chunks retransmissions to this specific IP
|
|
* address. When T3-rtx expires, the DATA chunk that triggered
|
|
* the T3 timer will be re-sent according to the retransmissions
|
|
* rules. Every DATA chunk that is included in a SCTP packet and
|
|
* was transmitted to this specific IP address before, will be
|
|
* included in this counter */
|
|
#endif
|
|
Ip_u32 cur_marked_retrans_bytes; /* Bytes of DATA chunk marked for retransmission now to this
|
|
* specific IP address, 4B-aligned including data chunk hdr
|
|
*/
|
|
Ip_u32 unsent_bytes; /* all the 4B-aligned unsent data including data chunk hdr to this transport(bytes) */
|
|
Ip_u8 hb_responded; /* check if need backoff */
|
|
Ipsctp_timer hb_timer; /* HB timer */
|
|
Ipsctp_timer fr_timer; /* FR timer */
|
|
Ip_u32 random_v1; /* random value1 number used for heartbeat */
|
|
Ip_u32 random_v2; /* random value1 number used for heartbeat */
|
|
}
|
|
Ipsctp_transport;
|
|
|
|
#ifdef IPSCTP_USE_SLAB_MEMORY
|
|
|
|
#else
|
|
|
|
/* get the data chunk length including payload and data chunk hdr */
|
|
#define IPSCTP_GET_DATA_CHUNK_TRANS_LEN(chunk_send)\
|
|
((chunk_send)->length + sizeof(Ipsctp_data_chunk_hdr))
|
|
|
|
/* get the data chunk length including payload and data chunk hdr (4B-aligned) */
|
|
#define IPSCTP_GET_DATA_CHUNK_TRANS_ALIGN_LEN(chunk_send)\
|
|
(IP_ROUNDUP(IPSCTP_GET_DATA_CHUNK_TRANS_LEN(chunk_send),4))
|
|
|
|
/* get the chunk length for cc window related calculation(only payload) */
|
|
#define IPSCTP_GET_DATA_CHUNK_WIND_LEN(chunk_send) (chunk_send)->length
|
|
|
|
/* get the control chunk length */
|
|
#define IPSCTP_GET_CRTL_CHUNK_TRANS_LEN(chunk_send) (chunk_send)->length
|
|
|
|
/* get the control chunk length (4B-aligned) */
|
|
#define IPSCTP_GET_CRTL_CHUNK_TRANS_ALIGN_LEN(chunk_send)\
|
|
(IP_ROUNDUP(IPSCTP_GET_CRTL_CHUNK_TRANS_LEN(chunk_send),4))
|
|
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
|
|
#define IPSCTP_GET_SEND_CHUNK ipcom_shm_malloc(sizeof(Ipsctp_chunk_send))
|
|
|
|
#define IPSCTP_FREE_SEND_CHUNK(chunk_send) \
|
|
do {\
|
|
if(chunk_send->chunk.pkt)\
|
|
ipcom_pkt_free(chunk_send->chunk.pkt);\
|
|
ipcom_shm_free(chunk_send);\
|
|
}while(0)
|
|
|
|
|
|
#define IPSCTP_GET_RECV_CHUNK ipcom_shm_malloc(sizeof(Ipsctp_chunk_recv))
|
|
#define IPSCTP_FREE_RECV_CHUNK(recv_chunk) \
|
|
do {\
|
|
if(recv_chunk->chunk.pkt)\
|
|
ipcom_pkt_free(recv_chunk->chunk.pkt);\
|
|
ipcom_shm_free(recv_chunk);\
|
|
}while(0)
|
|
|
|
|
|
#else /* !IPCOM_FORWARDER_NAE */
|
|
#define IPSCTP_GET_SEND_CHUNK ipcom_malloc(sizeof(Ipsctp_chunk_send))
|
|
|
|
#define IPSCTP_FREE_SEND_CHUNK(chunk_send) \
|
|
do {\
|
|
if(chunk_send->chunk.pkt)\
|
|
ipcom_pkt_free(chunk_send->chunk.pkt);\
|
|
ipcom_free(chunk_send);\
|
|
}while(0)
|
|
|
|
|
|
#define IPSCTP_GET_RECV_CHUNK ipcom_malloc(sizeof(Ipsctp_chunk_recv))
|
|
#if 0
|
|
#define IPSCTP_FREE_RECV_CHUNK(recv_chunk) \
|
|
do {\
|
|
Ipsctp_chunk_recv *cur_frag, *next_frag;\
|
|
next_frag = recv_chunk->next_fragment;\
|
|
while(next_frag)\
|
|
{\
|
|
cur_frag = next_frag;\
|
|
next_frag = cur_frag->next_fragment;\
|
|
if(cur_frag->chunk.pkt)\
|
|
ipcom_pkt_free(cur_frag->chunk.pkt);\
|
|
ipcom_free(cur_frag);\
|
|
}\
|
|
if(recv_chunk->chunk.pkt)\
|
|
ipcom_pkt_free(recv_chunk->chunk.pkt);\
|
|
ipcom_free(recv_chunk);\
|
|
}while(0)
|
|
#else
|
|
#define IPSCTP_FREE_RECV_CHUNK(recv_chunk) \
|
|
do {\
|
|
if(recv_chunk->chunk.pkt)\
|
|
ipcom_pkt_free(recv_chunk->chunk.pkt);\
|
|
ipcom_free(recv_chunk);\
|
|
}while(0)
|
|
|
|
#endif
|
|
#endif /* end IPCOM_FORWARDER_NAE */
|
|
|
|
#endif /* IPSCTP_USE_SLAB_MEMORY*/
|
|
|
|
#define IPSCTP_INIT_RECV_CHUNK(tcb1, transport1, pkt1, chunk_type1, chunk_start1, length1,\
|
|
sid, ssn, chunk_flags, ppid, tsn, chunk_recv) \
|
|
do {\
|
|
ip_assert(IP_NULL != chunk_recv); \
|
|
chunk_recv->chunk.pkt = pkt1;\
|
|
chunk_recv->chunk.tcb = tcb1;\
|
|
chunk_recv->chunk.transport = transport1;\
|
|
chunk_recv->chunk.flag = 0;\
|
|
IP_BIT_SET(chunk_recv->chunk.flag, IPSCTP_CHUNK_FLAG_RECV);\
|
|
chunk_recv->chunk.chunk_type = chunk_type1;\
|
|
chunk_recv->chunk.chunk_start = chunk_start1;\
|
|
chunk_recv->chunk.chunk_end = (chunk_start1 + length1);\
|
|
/*chunk_recv->next_fragment = NULL;*/\
|
|
chunk_recv->length = length1;\
|
|
/*chunk_recv->chunk_cnt = 1;*/\
|
|
chunk_recv->sndrcv_info.sinfo_context = tcb1->context;\
|
|
chunk_recv->sndrcv_info.sinfo_cumtsn = tcb1->cumulative_tsn; /* ? */\
|
|
chunk_recv->sndrcv_info.sinfo_flags = chunk_flags;\
|
|
chunk_recv->sndrcv_info.sinfo_ppid = ppid;\
|
|
chunk_recv->sndrcv_info.sinfo_pr_policy = 0;\
|
|
chunk_recv->sndrcv_info.sinfo_pr_value = 0;\
|
|
chunk_recv->sndrcv_info.sinfo_ssn = ssn;\
|
|
chunk_recv->sndrcv_info.sinfo_stream = sid;\
|
|
chunk_recv->sndrcv_info.sinfo_tsn = tsn;\
|
|
chunk_recv->sndrcv_info.sinfo_assoc_id = tcb1->my_vtag;\
|
|
chunk_recv->from_addr = transport1->paddr;\
|
|
}while(0)
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP Transmission Chunk (IPSCTP CHUNK for send)
|
|
*===========================================================================
|
|
Ipsctp_chunk is the list element in stream queue, control queue, transmitted queue.
|
|
TODO: we can use next_fragment in Ipcom_pkt?
|
|
statistics should be added
|
|
*/
|
|
|
|
typedef struct Ipsctp_chunk_struct
|
|
{
|
|
Ipcom_list chunk_next; /* Chunk entry in list*/
|
|
Ipcom_pkt *pkt; /* Pkt in this list ,transform
|
|
* The buffer in pkt to each type of chunk per chunk_type */
|
|
int chunk_start; /* The start location of this chunk's data ,specially for receive */
|
|
int chunk_end; /* The end location of this chunk's data , specially for receive */
|
|
|
|
Ip_u16 chunk_type; /* Chunk Type */
|
|
|
|
struct Ipsctp_tcb_struct *tcb; /* Which association does this belong to */
|
|
Ipsctp_transport *transport; /* The destination this chunk sent to, or received from */
|
|
|
|
Ip_u16 flag; /* The send status, or receive control flag, see IPSCTP_CHUNK_FLAG_XXX.
|
|
* the lower 4 bits of send staus refer to IPSCTP_CHUNK_FLAG_SEND_STATE_XX
|
|
*/
|
|
}
|
|
Ipsctp_chunk;
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Ipsctp_chunk_recv
|
|
*===========================================================================
|
|
* Ipsctp_chunk_recv is the list element in recv queue.
|
|
*/
|
|
|
|
typedef struct Ipsctp_chunk_recv_struct
|
|
{
|
|
Ipsctp_chunk chunk;
|
|
struct Ipsctp_sndrcvinfo sndrcv_info;
|
|
Ipsctp_addr from_addr;
|
|
#if 0
|
|
struct Ipsctp_chunk_recv_struct *next_fragment; /* next fragment of the chunk */
|
|
Ip_u32 chunk_cnt; /* the count of all chunk frgments */
|
|
#endif
|
|
Ip_u32 length; /* length of all chunk fragments */
|
|
}
|
|
Ipsctp_chunk_recv;
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Ipsctp_chunk_send
|
|
*===========================================================================
|
|
* Ipsctp_chunk_snd is the list element in send queue.
|
|
*/
|
|
|
|
typedef struct Ipsctp_chunk_send_struct
|
|
{
|
|
Ipsctp_chunk chunk;
|
|
struct Ipsctp_sndrcvinfo sndrcv_info;
|
|
Ip_u16 snd_count; /* number of times sent */
|
|
Ip_u32 fr_tsn; /* sending tsn at the time of FR */
|
|
struct Ip_timeval snd_time;
|
|
Ip_u32 length; /* for DATA type: actual payload length(no alignment) excluding data chunk header
|
|
* for CONTROL type: chunk length(no alignment) including Ipsctp_chunk_hdr.
|
|
*/
|
|
}
|
|
Ipsctp_chunk_send;
|
|
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP INPUT PARA (IPSCTP INPUT PARAMETER)
|
|
*===========================================================================
|
|
|
|
*/
|
|
|
|
#define IPSCTP_STREAM_IN_FLAG_DELIVERY_STARTED (1 << 0) /* Set when in the process of delivering a record with socket */
|
|
#if 0
|
|
#define IPSCTP_STREAM_IN_FLAG_INIT (1 << 1) /* Set when this stream receives first chunk */
|
|
#endif
|
|
|
|
typedef struct Ipsctp_stream_in_struct
|
|
{
|
|
Ip_u16 stream_number;
|
|
Ip_u16 last_ssn_delivered; /* used for re-order;
|
|
* for unordered chunk, don't update last_ssn_delivered
|
|
*/
|
|
Ip_u32 last_tsn_delivered; /* last tsn delivered to socket buffer;
|
|
* for unordered chunk, don't update last_tsn_delivered
|
|
*/
|
|
Ipcom_list queue_chunks; /* Chunks received to be re-order or reassemble */
|
|
#if 0
|
|
Ip_u8 delivery_started;
|
|
#endif
|
|
Ip_u8 flag; /* see IPSCTP_STREAM_IN_FLAG_XXX */
|
|
#ifdef IPSCTP_USE_PARTIAL_DELIVERY
|
|
Ipsctp_chunk_recv *chunk_pd_first; /* partial delivery chunk */
|
|
Ipsctp_chunk_recv *chunk_pd_end; /* latest fragment of partial delivery chunk */
|
|
#endif
|
|
}
|
|
Ipsctp_stream_in;
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP Transmission Stream (IPSCTP STREAM)
|
|
*===========================================================================
|
|
|
|
*/
|
|
typedef struct Ipsctp_stream_out_struct
|
|
{
|
|
Ipcom_list stream_next; /* stream entry in list */
|
|
Ipcom_list chunk_list; /* chunk queue head */
|
|
Ip_u16 stream_number; /* stream number */
|
|
Ip_u16 next_ssn_sent; /* next one I expect to send out */
|
|
Ip_u8 last_msg_incomplete; /* last msg in this stream is incomplete.
|
|
* if the following part of this msg arrives,
|
|
* complete this msg.
|
|
* may have to fragment if the whole msg too big */
|
|
Ipsctp_chunk *selected_chunk; /* by now the selected chunk to send in this stream */
|
|
}
|
|
Ipsctp_stream_out;
|
|
|
|
/* Congestion control modules for pluggable
|
|
* congestion control.
|
|
* By now only IPSCTP_CC_RFC2581 is supported.
|
|
*/
|
|
typedef enum Ipsctp_cc_module_enum {
|
|
|
|
IPSCTP_CC_RFC2581 = 0 , /* Standard TCP Congestion Control */
|
|
IPSCTP_CC_HSTCP, /* High Speed TCP Congestion Control (Floyd) */
|
|
IPSCTP_CC_HTCP, /* HTCP Congestion Control */
|
|
IPSCTP_CC_MAX
|
|
}Ipsctp_cc_module;
|
|
|
|
typedef struct Ipsctp_cc_functions_struct {
|
|
|
|
void (*init)(struct Ipsctp_tcb_struct *tcb,
|
|
Ipsctp_transport *transport);
|
|
void (*cwnd_update_sack)(struct Ipsctp_tcb_struct *tcb,
|
|
Ip_bool cum_ack_moved,
|
|
Ip_bool will_exit_fast_recovery);
|
|
void (*cwnd_update_fr)(struct Ipsctp_tcb_struct *tcb);
|
|
void (*cwnd_update_tmo)(struct Ipsctp_tcb_struct *tcb,
|
|
Ipsctp_transport *transport);
|
|
|
|
void (*cwnd_update_output)(struct Ipsctp_tcb_struct *tcb,
|
|
Ipsctp_transport *transport);
|
|
|
|
#if 0
|
|
void (*sctp_cwnd_update_after_ecn_echo) (struct Ipsctp_tcb_struct *stcb,
|
|
Ipsctp_transport *transport);
|
|
|
|
|
|
void (*sctp_cwnd_update_after_packet_dropped) (struct Ipsctp_tcb_struct *stcb,
|
|
Ipsctp_transport *transport,
|
|
struct sctp_pktdrop_chunk *cp,
|
|
uint32_t * bottle_bw,
|
|
uint32_t * on_queue);
|
|
|
|
void (*sctp_cwnd_update_after_fr_timer) (struct sctp_inpcb *inp,
|
|
struct sctp_tcb *stcb, struct sctp_nets *net);
|
|
#endif
|
|
|
|
}Ipsctp_cc_functions;
|
|
|
|
/* sock->ipcom.rcv_bytes: bytes of all TCBs' chunks in the socket */
|
|
|
|
#ifdef IPSCTP_USE_MULTIBUF
|
|
|
|
#define IPSCTP_RECVBUF_MAX(tcb) tcb->sock->recv_max_bytes /*tcb->recv_max_bytes*/
|
|
#define IPSCTP_RECVBUF_LEN(tcb) tcb->recv_bytes
|
|
#define IPSCTP_RECVBUF_LEN_ADD(tcb, len) \
|
|
do {\
|
|
tcb->recv_bytes += (len);\
|
|
tcb->sock->ipcom.rcv_bytes += (len);\
|
|
}while(0)
|
|
|
|
#define IPSCTP_RECVBUF_LEN_SUB(sock, tcb, len) \
|
|
do {\
|
|
if (tcb)\
|
|
{\
|
|
tcb->recv_bytes -= (len);\
|
|
tcb->sock->ipcom.rcv_bytes -= (len);\
|
|
}\
|
|
}while(0)
|
|
|
|
#define IPSCTP_RECVBUF_CNT(sock, tcb) tcb->recv_chunks_cnt
|
|
#define IPSCTP_RECVBUF_CNT_SUB(sock, tcb, len) \
|
|
do {\
|
|
if (tcb)\
|
|
tcb->recv_chunks_cnt -= (len);\
|
|
}while(0)
|
|
|
|
#define IPSCTP_RECVBUF_QUEUE_LEN(tcb) tcb->size_on_in_queue
|
|
#define IPSCTP_RECVBUF_QUEUE_CNT(tcb) tcb->cnt_on_in_queue
|
|
|
|
|
|
#define IPSCTP_SENDBUF_LEN(tcb) tcb->sock->snd_bytes /*tcb->send_bytes*/
|
|
#define IPSCTP_SENDBUF_MAX(tcb) tcb->sock->send_max_bytes
|
|
|
|
#define IPSCTP_SENDBUF_CNT(tcb) tcb->send_chunks_cnt
|
|
|
|
#else
|
|
|
|
#define IPSCTP_RECVBUF_MAX(tcb) tcb->sock->recv_max_bytes
|
|
#define IPSCTP_RECVBUF_LEN(tcb) tcb->sock->ipcom.rcv_bytes
|
|
#define IPSCTP_RECVBUF_LEN_ADD(tcb, len) tcb->sock->ipcom.rcv_bytes += (len) \
|
|
, ipsctp_log3int(IPCOM_LOG_DEBUG, IPSCTP_DBG_BUF, "FILE "__FILE__" LINE %d BufSize: %d, add: %d\n",\
|
|
__LINE__, tcb->sock->ipcom.rcv_bytes, len)
|
|
#define IPSCTP_RECVBUF_LEN_SUB(sock, tcb, len) sock->ipcom.rcv_bytes -= (len)\
|
|
, ipsctp_log3int(IPCOM_LOG_DEBUG, IPSCTP_DBG_BUF, "FILE "__FILE__" LINE %d BufSize: %d, sub: %d\n",\
|
|
__LINE__, sock->ipcom.rcv_bytes, len)
|
|
#define IPSCTP_RECVBUF_CNT(sock, tcb) sock->sctp_inst->recv_chunks_cnt
|
|
#define IPSCTP_RECVBUF_CNT_SUB(sock, tcb, len) sock->sctp_inst->recv_chunks_cnt -= (len)
|
|
|
|
#define IPSCTP_RECVBUF_QUEUE_LEN(tcb) tcb->instance->size_on_in_queue
|
|
#define IPSCTP_RECVBUF_QUEUE_CNT(tcb) tcb->instance->cnt_on_in_queue
|
|
|
|
#define IPSCTP_SENDBUF_LEN(tcb) tcb->sock->snd_bytes /* only user data length */
|
|
#define IPSCTP_SENDBUF_MAX(tcb) tcb->sock->send_max_bytes
|
|
#define IPSCTP_SENDBUF_CNT(tcb) tcb->instance->send_chunks_cnt
|
|
|
|
|
|
#endif
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
|
|
#define IPSCTP_APPEND_RECV_CHUNK(tcb, chunk_recv) ipsctp_append_recv_chunk(tcb,chunk_recv)
|
|
IP_INLINE int ipsctp_append_recv_chunk( struct Ipsctp_tcb_struct * tcb,Ipsctp_chunk_recv* chunk_recv);
|
|
|
|
#define IPSCTP_INSERT_RECV_CHUNK(tcb, chunk_recv_pre, chunk_recv) \
|
|
do {\
|
|
Ipcom_socket_eventcb event_cb = tcb->sock->ipcom.event_cb;\
|
|
/* add the chunk to socket receive buffer */\
|
|
IPSCTP_DATA_LOCK(tcb->sock->rcv_lock);\
|
|
ipcom_list_insert_after(&chunk_recv_pre->chunk.chunk_next, &chunk_recv->chunk.chunk_next);\
|
|
IPSCTP_RECVBUF_CNT(tcb->sock, tcb)++;\
|
|
IPSCTP_RECVBUF_LEN_ADD(tcb, chunk_recv->length);\
|
|
IPSCTP_DATA_UNLOCK(tcb->sock->rcv_lock);\
|
|
if (event_cb != IP_NULL)\
|
|
{\
|
|
(void)event_cb(&tcb->sock->ipcom, (Ipcom_pkt *)chunk_recv, IP_SOEVENT_CB_INPKT);\
|
|
}\
|
|
}while(0)
|
|
|
|
#else
|
|
|
|
#define IPSCTP_APPEND_RECV_CHUNK(tcb, chunk_recv)\
|
|
do {\
|
|
Ipcom_socket_eventcb event_cb = tcb->sock->ipcom.event_cb;\
|
|
/* add the chunk to socket receive buffer */\
|
|
IPSCTP_DATA_LOCK(tcb->sock->rcv_lock);\
|
|
ipcom_list_insert_last(&tcb->instance->recv_list, &chunk_recv->chunk.chunk_next);\
|
|
IPSCTP_RECVBUF_CNT(tcb->sock, tcb)++;\
|
|
IPSCTP_RECVBUF_LEN_ADD(tcb, chunk_recv->length);\
|
|
IPSCTP_DATA_UNLOCK(tcb->sock->rcv_lock);\
|
|
if (event_cb != IP_NULL)\
|
|
{\
|
|
(void)event_cb(&tcb->sock->ipcom, (Ipcom_pkt *)chunk_recv, IP_SOEVENT_CB_INPKT);\
|
|
}\
|
|
}while(0)
|
|
|
|
#define IPSCTP_INSERT_RECV_CHUNK(tcb, chunk_recv_pre, chunk_recv) \
|
|
do {\
|
|
Ipcom_socket_eventcb event_cb = tcb->sock->ipcom.event_cb;\
|
|
/* add the chunk to socket receive buffer */\
|
|
IPSCTP_DATA_LOCK(tcb->sock->rcv_lock);\
|
|
ipcom_list_insert_after(&chunk_recv_pre->chunk.chunk_next, &chunk_recv->chunk.chunk_next);\
|
|
IPSCTP_RECVBUF_CNT(tcb->sock, tcb)++;\
|
|
IPSCTP_RECVBUF_LEN_ADD(tcb, chunk_recv->length);\
|
|
IPSCTP_DATA_UNLOCK(tcb->sock->rcv_lock);\
|
|
if (event_cb != IP_NULL)\
|
|
{\
|
|
(void)event_cb(&tcb->sock->ipcom, (Ipcom_pkt *)chunk_recv, IP_SOEVENT_CB_INPKT);\
|
|
}\
|
|
}while(0)
|
|
#endif
|
|
|
|
#define IPSCTP_FREE_PKT_LIST(pkt_list)\
|
|
do {\
|
|
Ipcom_pkt *free_pkt = IP_NULL;\
|
|
Ipcom_pkt *free_pkt_next = IP_NULL;\
|
|
free_pkt = pkt_list;\
|
|
while (IP_NULL != free_pkt)\
|
|
{\
|
|
free_pkt_next = free_pkt->next;\
|
|
ipcom_pkt_free(free_pkt);\
|
|
free_pkt = free_pkt_next;\
|
|
}\
|
|
} while(0)
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP Transmission Control Block (IPSCTP TCB)
|
|
*===========================================================================
|
|
* The members of this structure are defined partially per recommendation in
|
|
* Section 13 of RFC4960 and partially per Iptcp_tcb definitions.
|
|
* Notes: sctpAssocPrimProcess in RFC3873 is not supported, should be zero.
|
|
*/
|
|
typedef struct Ipsctp_tcb_struct
|
|
{
|
|
Ipcom_list next; /* next pointer in the same instance */
|
|
Ipsctp_instance *instance; /* points back to the IPSCTP instance owning this TCB */
|
|
|
|
Ipsctp_socket *sock; /* Points to the socket this TCb is bound to */
|
|
|
|
Ip_u32 tcb_flags; /* IPSCTP_TCBC_FLAG_XXX*/
|
|
Ip_u32 tcb_peer_flags; /* IPSCTP_TCBC_FLAG_XXX*/
|
|
|
|
int tcb_errno; /* Socket errno (IP_ERRNO_xxx) */
|
|
|
|
Ipsctp_vtag peer_vtag; /* peer verification tag value (transmitted in all
|
|
* packets, recieved from INIT/INIT ACK chunks. */
|
|
Ipsctp_vtag my_vtag; /* verification tag value (expected in all recieved
|
|
* packets and trnasmitted in INIT/INIT ACK chunks.
|
|
* Also as association id, sctpAssocId.
|
|
*/
|
|
Ip_u32 my_vtag_nonce;
|
|
Ip_u32 peer_vtag_nonce;
|
|
|
|
/* Configurable variable */
|
|
Ip_u16 max_init_times;
|
|
Ip_u16 max_send_times; /* Mib: sctpAssocMaxRetr */
|
|
Ip_u16 max_transport_retrans; /* max retransmissions */
|
|
Ip_u32 initial_init_rto_max; /* initial RTO for INIT's */
|
|
Ip_u32 initial_rto; /* initial send RTO */
|
|
Ip_u32 min_rto; /* per assoc RTO-MIN */
|
|
Ip_u32 max_rto; /* per assoc RTO-MAX */
|
|
#ifdef IPCOM_USE_INET6
|
|
Ip_u32 ipv6_flowlabel; /* flow label */
|
|
#endif
|
|
#ifdef IPCOM_USE_INET
|
|
Ip_u8 ipv4_tos;
|
|
#endif
|
|
Ip_u32 context; /* Set or get by SCTP_CONTEXT */
|
|
|
|
Ipsctp_state state; /* association state: assumes all state values except
|
|
* IPSCTP_STATE_CLOSED as there is no TCB in IPSCTP_STATE_CLOSED state */
|
|
|
|
Ipcom_list transport_list; /* peer addresses and parameters struct list*/
|
|
Ipsctp_transport *primary_transport; /* points to the primary path info */
|
|
|
|
Ipsctp_transport *last_ctrl_from;
|
|
Ipsctp_transport *last_data_from;
|
|
Ip_u32 pmtu; /* smallest PMTU discovered for all of peer addresses. */
|
|
Ip_u32 mss;
|
|
Ip_u32 frag_point; /* size to do fragments */
|
|
Ip_u16 rport; /* remote port, in host order */
|
|
|
|
Ipsctp_sctp_sndrcvinfo def_send; /* default send info */
|
|
Ip_u32 oa_err_cnt; /* overall error count on this association*/
|
|
|
|
Ip_u32 total_flight; /* amount of data (bytes) currently in flight (on all destinations)
|
|
* Total book size in flight, excluding any acked(cumulative and gap) data
|
|
*/
|
|
Ip_u32 max_burst; /* maximum burst of packets
|
|
* that can be emitted by this association
|
|
*/
|
|
#if 0 /* we can get this value from transmitted_chunk_list's size */
|
|
Ip_u32 total_flight_count; /* count of chunks used with book total */
|
|
Ip_u32 send_max_bytes;
|
|
Ip_u32 recv_max_bytes; /* max receive buffer size for this association */
|
|
|
|
#endif
|
|
Ip_u32 sent_queue_retran_cnt; /* Number on sent queue that are marked for retran until this value
|
|
* is 0 we only send one packet of retran'ed data.
|
|
??*/
|
|
#ifdef IPSCTP_USE_MULTIBUF
|
|
Ipcom_atomic_t send_bytes; /* all the data bytes in send queue,including all unsent and unacked. */
|
|
Ip_u32 send_chunks_cnt;
|
|
|
|
|
|
Ip_u32 recv_bytes; /* chunks bytes in receive buffer,
|
|
= size_on_in_queue? */
|
|
Ip_u32 recv_chunks_cnt; /* chunks count in receive buffer */
|
|
|
|
Ip_u32 size_on_in_queue; /* chunk bytes in input stream's chunk queue,
|
|
haven't been delivered to socket receive buffer.*/
|
|
Ip_u32 cnt_on_in_queue; /* chunk count in input stream's chunk queue,
|
|
haven't been delivered to socket receive buffer.*/
|
|
#endif
|
|
#if 0
|
|
Ip_u32 size_on_reasm_queue;
|
|
Ip_u32 cnt_on_reasm_queue;
|
|
#endif
|
|
|
|
/* window state information */
|
|
Ip_u32 peers_rwnd;
|
|
Ip_u32 my_last_reported_rwnd;
|
|
Ipsctp_cc_functions cc_functions; /* value to store the currently loaded congestion control module */
|
|
|
|
|
|
Ip_u32 congestion_control_module;
|
|
|
|
Ipcom_bitarray *recv_tsn_bitmap; /* array of bits indicating which out-of-order
|
|
* TSNs have been received */
|
|
Ip_u16 recv_tsn_bitmap_size;
|
|
Ip_u32 recv_tsn_bitmap_base; /* Used to track the tsn bitmap and its offset bits. This MAY be
|
|
* lower then cumulative_tsn.*/
|
|
Ip_u32 cumulative_tsn; /* The highest consequetive TSN at the bottom of the mapping array
|
|
* (for his sends).*/
|
|
Ip_u32 highest_tsn_inside_map; /* used to track highest TSN we have received
|
|
* and is listed in the mapping array.*/
|
|
|
|
Ip_u32 numduptsns;
|
|
Ip_u32 dup_tsns[IPSCTP_MAX_DUP_TSNS]; /* Duplicated TSN packets received */
|
|
Ip_u32 tsn_last_delivered; /* need it? */
|
|
|
|
|
|
Ip_u32 init_tsn_number; /* Original tsn number I used */
|
|
Ip_u32 tsn_next; /* next TSN number to be assigned to a
|
|
* new DATA chunk. Sent in INIT/INIT ACK
|
|
* chunk to peer and incremented each time
|
|
* DATA chunk is assigned a TSN. */
|
|
Ip_u32 fast_recovery_tsn; /* set when fast retransmit */
|
|
Ip_u32 sat_t3_recovery_tsn; /* set in t3 timer */
|
|
|
|
Ip_u32 this_sack_highest_gap; /* Special hook for Fast retransmit, allows us to track the highest
|
|
* TSN that is NEW in this SACK if gap ack blocks are present.*/
|
|
Ip_u32 last_acked_tsn; /* The highest consecutive TSN that has been acked by peer on my sends */
|
|
#if 0
|
|
Ipsctp_chunk_recv *chunk_pd; /* chunk in partial delivery */
|
|
Ip_u16 ssn_pd; /* stream sequence number for partial delivery */
|
|
Ip_u16 sid_pd; /* stream id for partial delivery */
|
|
Ip_u32 tsn_pd; /* tsn of partial delivery chunk */
|
|
Ip_u16 fragment_flags;
|
|
#endif
|
|
Ip_u32 sack_freq; /*to control the sack*/
|
|
Ip_u32 data_pkts_seen; /*to control the sack, if data_pkts_seen > sack_freq, send sack*/
|
|
|
|
Ipsctp_stream_in *streams_in; /* tracks inbound streams */
|
|
Ipsctp_stream_out *streams_out; /* Out stream queue head,list all streams */
|
|
Ipcom_list streams_out_sched_list; /* Out sched for stream schedule,
|
|
* e.g. for Round-robin the list link all streams who have packets */
|
|
|
|
Ipcom_list control_chunk_list; /* Control chunk queue list head */
|
|
Ipcom_list transmitted_chunk_list; /* Transmitted chunk queue */
|
|
|
|
Ip_u16 streamincnt; /* sctpAssocInStreams */
|
|
Ip_u16 streamoutcnt; /* sctpAssocOutStreams */
|
|
Ip_u16 max_inbound_streams; /* How many streams I support coming into me */
|
|
Ip_u16 pre_open_streams; /* how many preopen streams we have */
|
|
|
|
Ip_u32 total_sends;
|
|
Ip_u32 total_recvs;
|
|
|
|
struct Ip_timeval time_entered; /* time we entered state */
|
|
struct Ip_timeval time_last_rcvd;
|
|
struct Ip_timeval time_last_sent;
|
|
Ip_u32 start_time; /* time we start the association*/
|
|
Ip_u32 discontinuity_time; /* sctpAssocDiscontinuityTime */
|
|
|
|
Ip_u32 hb_interval; /* Heart Beat interval in MSEC, sctpAssocHeartBeatInterval*/
|
|
Ip_u32 autoclose_time; /* autoclose time, im MSEC */
|
|
Ip_u32 delayed_ack; /*time of delay ack timer */
|
|
|
|
/* timer */
|
|
Ipsctp_timer dack_timer; /* Delayed ack timer */
|
|
Ipsctp_timer asconf_timer; /* asconf */
|
|
Ipsctp_timer shut_guard_timer; /* shutdown guard */
|
|
Ipsctp_timer autoclose_timer; /* automatic close timer */
|
|
Ipsctp_timer delayed_event_timer; /* timer for delayed events */
|
|
Ipsctp_timer delete_prim_timer; /* deleting primary dst */
|
|
|
|
Ip_u32 cookie_life;
|
|
Ip_u8 cookie_how[8]; /*record different accasions in cookie_existing,yjg*/
|
|
Ip_u16 stale_cookie_count;
|
|
Ip_u32 cookie_preserve_req; /*required cookie time*/
|
|
|
|
/* Mib in RFC3872 */
|
|
#ifdef IPSCTP_MIB
|
|
Ip_u32 marked_retrans; /* sctpAssocRtxChunks */
|
|
Ip_u32 cnt_timo_init; /* sctpAssocT1expireds = cnt_timo_init + cnt_timo_cookie */
|
|
Ip_u32 cnt_timo_cookie;
|
|
Ip_u32 cnt_timo_shutdown; /* sctpAssocT2expireds = cnt_timo_shutdown+ cnt_timo_shutdownack */
|
|
Ip_u32 cnt_timo_shutdownack;
|
|
#endif
|
|
}
|
|
Ipsctp_tcb;
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Ipsctp_tcb_lookup_key
|
|
*===========================================================================
|
|
*/
|
|
typedef struct Ipsctp_tcb_lookup_key_struct
|
|
{
|
|
Ip_u32 vr; /* The virtual router */
|
|
Ip_u16 domain; /* The domain */
|
|
Ip_u16 strict_match; /* Whether match port and address or not */
|
|
Ip_u16 local_port; /* The local port */
|
|
Ip_u16 peer_port; /* The peer port */
|
|
union Ip_in_addr_union local_addr; /* The local address */
|
|
union Ip_in_addr_union peer_addr; /* The peer address */
|
|
Ip_u32 vtag; /* if zero, lookup using ports and addresses,
|
|
if non-zero, lookup using vtag */
|
|
Ipsctp_transport **transport; /* return matching transport */
|
|
Ipsctp_af_ops *af_ops; /* address family related operations */
|
|
}
|
|
Ipsctp_tcb_lookup_key;
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Ipsctp_tag_timewait
|
|
*===========================================================================
|
|
*/
|
|
typedef struct Ipsctp_vtag_timewait_struct
|
|
{
|
|
Ip_u32 vtag;
|
|
Ipsctp_timer timer;
|
|
}
|
|
Ipsctp_vtag_timewait;
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPSCTP INPUT PARA (IPSCTP INPUT PARAMETER)
|
|
*===========================================================================
|
|
|
|
*/
|
|
|
|
#define IPSCTP_MAX_CHUNK_IN_ONE_PKT 256 /*IPSCTP_MAX_BUNDLING*/
|
|
/* Parameters used when processing incoming SCTP packets */
|
|
typedef struct Ipsctp_input_param_struct
|
|
{
|
|
Ipcom_pkt *pkt;
|
|
Ipsctp_tcb *tcb;
|
|
Ipsctp_transport *transport; /* points to the path info of this packet */
|
|
Ipsctp_af_ops *af_ops; /* address family related operations */
|
|
Ip_u16 pkt_len;
|
|
Ip_u16 remain_len;
|
|
Ip_u8 *error_cause;
|
|
Ip_u32 error_cause_len; /* actual error data length in error_cause */
|
|
Ip_u32 error_data_len; /* total buffer length of error_cause */
|
|
Ip_u32 error_code; /* error code notified to ULP */
|
|
Ip_u32 action; /* the action when return from input processing,
|
|
* see IPSCTP_ACTION_SEND_ABORT */
|
|
IP_CONST void * dst_addr;
|
|
IP_CONST void * src_addr;
|
|
|
|
Ip_u16 src_port; /* Source (peer) TCP port */
|
|
Ip_u16 dst_port; /* Destination (local) TCP port */
|
|
Ip_bool free_packet; /* IP_TRUE if the packet should be freed */
|
|
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
Ipcom_pkt *nae_rx_pkt[IPSCTP_MAX_CHUNK_IN_ONE_PKT]; /* [IPSCTP_MAX_BUNDLING]; */
|
|
/* Packet that should be
|
|
delivered to the
|
|
action/notifier */
|
|
int chunk_start[IPSCTP_MAX_CHUNK_IN_ONE_PKT];
|
|
int chunk_end[IPSCTP_MAX_CHUNK_IN_ONE_PKT];
|
|
int position;
|
|
#endif
|
|
}
|
|
Ipsctp_input_param;
|
|
|
|
#ifdef IPSCTP_DBGSTAT
|
|
/* NOTE : please add string in ipsctp_dbgstat_ctl_str */
|
|
enum Ipsctp_debug_statistics_enmu
|
|
{
|
|
IPSCTP_DBGSTAT_BASE = 0, /* NOTE : please add string in ipsctp_dbgstat_ctl_str */
|
|
IPSCTP_DBGSTAT_SYS_SEND_INIT,
|
|
IPSCTP_DBGSTAT_RESTART_AND_OPEN,
|
|
IPSCTP_DBGSTAT_SEND_INIT_PIPE,
|
|
IPSCTP_DBGSTAT_COOKIE_TIMER,
|
|
IPSCTP_DBGSTAT_SEND_INIT_ERR,
|
|
IPSCTP_DBGSTAT_RECV_INIT,
|
|
IPSCTP_DBGSTAT_SEND_INIT_ACK,
|
|
IPSCTP_DBGSTAT_RECV_INIT_ACK,
|
|
IPSCTP_DBGSTAT_SEND_COOKIE_ECHO,
|
|
IPSCTP_DBGSTAT_RECV_COOKIE_ECHO,
|
|
IPSCTP_DBGSTAT_SEND_COOKIE_ACK,
|
|
IPSCTP_DBGSTAT_RECV_COOKIE_ACK,
|
|
IPSCTP_DBGSTAT_MAX /* NOTE : please add string in ipsctp_dbgstat_ctl_str */
|
|
};
|
|
|
|
IP_EXTERN IP_PUBLIC Ip_u32 ipsctp_debug_statistics[IPSCTP_DBGSTAT_MAX];
|
|
/* NOTE : no valid paremeter check. */
|
|
#define IPSCTP_DBGSTAT_INIT(enum_num) (ipsctp_debug_statistics[(Ip_u32)enum_num] = 0)
|
|
#define IPSCTP_DBGSTAT_INC(enum_num) (ipsctp_debug_statistics[(Ip_u32)enum_num]++)
|
|
#define IPSCTP_DBGSTAT_DEC(enum_num) (ipsctp_debug_statistics[(Ip_u32)enum_num]--)
|
|
#define IPSCTP_DBGSTAT_GET(enum_num) (ipsctp_debug_statistics[(Ip_u32)enum_num])
|
|
#else
|
|
#define IPSCTP_DBGSTAT_INIT(enum_num) IP_NOOP
|
|
#define IPSCTP_DBGSTAT_INC(enum_num) IP_NOOP
|
|
#define IPSCTP_DBGSTAT_DEC(enum_num) IP_NOOP
|
|
#define IPSCTP_DBGSTAT_GET(enum_num) IP_NOOP
|
|
#endif
|
|
typedef struct Ipsctp_init_para_val_struct
|
|
{
|
|
Ip_u32 cookie_lifetime_inc;
|
|
} Ipsctp_init_para_val;
|
|
/*
|
|
****************************************************************************
|
|
* 6 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_PUBLIC unsigned
|
|
ipsctp_tcb_obj_hash(Ipsctp_tcb *tcb);
|
|
|
|
IP_PUBLIC unsigned
|
|
ipsctp_tcb_key_hash(Ipsctp_tcb_lookup_key *key);
|
|
|
|
IP_PUBLIC Ip_bool
|
|
ipsctp_tcb_hash_cmp(Ipsctp_tcb *tcb, Ipsctp_tcb_lookup_key *key);
|
|
|
|
IP_PUBLIC unsigned
|
|
ipsctp_tcb_port_obj_hash(Ipsctp_tcb *tcb);
|
|
|
|
IP_PUBLIC unsigned
|
|
ipsctp_tcb_port_key_hash(Ipsctp_tcb_lookup_key *key);
|
|
|
|
IP_PUBLIC Ip_bool
|
|
ipsctp_tcb_port_hash_cmp(Ipsctp_tcb *tcb, Ipsctp_tcb_lookup_key *key);
|
|
|
|
IP_PUBLIC unsigned
|
|
ipsctp_vtag_timewait_obj_hash(Ipsctp_vtag_timewait *vtag_timewait);
|
|
|
|
IP_PUBLIC unsigned
|
|
ipsctp_vtag_timewait_key_hash(Ip_u32* vtag);
|
|
|
|
IP_PUBLIC Ip_bool
|
|
ipsctp_vtag_timewait_hash_cmp(Ipsctp_vtag_timewait *vtag_timewait, Ip_u32* vtag);
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipsctp_tcb_lookup
|
|
*===========================================================================
|
|
* Description: Look up SCTP TCB based on given criteria. If vtag is non-zero,
|
|
* search the hash table using vtag, and also check the local&peer
|
|
* ports and addresses if necessary (TCB lookup optimization is off).
|
|
* If vtag is zero, search the hash table using local&peer ports and
|
|
* addresses.
|
|
* Parameters:
|
|
* Returns: Matched SCTP TCB and transport if existing, or NULL.
|
|
*
|
|
*/
|
|
IP_PUBLIC Ipsctp_tcb *
|
|
ipsctp_tcb_lookup(
|
|
Ip_u32 vtag, /* local's verification tag */
|
|
Ip_u16 vr, /* the using virtual router */
|
|
int proto, /* protocol type */
|
|
IP_CONST void *local_addr, /* The local IPv4 address in network order, IP_NULL for any address */
|
|
Ip_u16 local_port, /* port in host order, 0 for any port.*/
|
|
IP_CONST void *peer_addr, /* The peer IPv4 address in network order, IP_NULL for any address */
|
|
Ip_u16 peer_port, /* port in host order, 0 for any port.*/
|
|
Ipsctp_af_ops *af_ops, /* Address Family related operations. */
|
|
Ipsctp_transport **transport /* transport matching the peer address, don't return transport if NULL */
|
|
);
|
|
|
|
IP_PUBLIC Ip_bool ipsctp_address_equal(IP_CONST Ipsctp_addr *addr1, IP_CONST Ipsctp_addr *addr2);
|
|
IP_PUBLIC Ip_u32 ipsctp_select_tag(Ipsctp_tcb *tcb, Ip_u32 save_timewait);
|
|
IP_PUBLIC Ip_s32 ipsctp_add_remote_addr(Ipsctp_tcb *tcb,
|
|
IP_CONST Ipsctp_addr *addr,
|
|
Ip_u32 addr_state,
|
|
Ipsctp_transport **newtransport);
|
|
IP_PUBLIC Ipsctp_param_hdr * ipsctp_get_next_param(Ip_u8 **inputbuf,Ip_u16 *remain_len);
|
|
IP_PUBLIC Ipsctp_af_ops *ipsctp_get_af_ops(Ip_sa_family_t family);
|
|
IP_PUBLIC int ipsctp_src_addr_selection(Ipsctp_tcb *tcb,
|
|
Ipsctp_addr *dstaddr,
|
|
Ipnet_route_entry *rt,
|
|
Ip_u16 lport,
|
|
Ipsctp_addr *srcaddr);
|
|
IP_PUBLIC Ip_u32 ipsctp_addr_match_len(void *addr1, void *addr2, Ip_u32 lenofint);
|
|
#ifdef IPSCTP_DEBUG
|
|
IP_GLOBAL IP_CONST char * ipsctp_timer_to_str(Ipsctp_timo type);
|
|
IP_GLOBAL IP_CONST char * ipsctp_notification_to_str(Ipsctp_notify_type type);
|
|
#endif
|
|
|
|
IP_PUBLIC void
|
|
ipsctp_send_init_ack(Ipsctp_input_param *param,
|
|
Ipsctp_chunk_hdr *init,
|
|
Ipsctp_sctp_hdr *sctp_hdr_init);
|
|
|
|
IP_PUBLIC void
|
|
ipsctp_send_err(Ipsctp_input_param *param,
|
|
Ip_u32 error_type,
|
|
Ip_u8 *error_cause,
|
|
Ip_u32 error_cause_len);
|
|
|
|
IP_PUBLIC void
|
|
ipsctp_notify_ulp(Ipsctp_notify_type type,
|
|
Ipsctp_tcb *tcb,
|
|
Ip_u32 err,
|
|
void *cookie);
|
|
|
|
IP_PUBLIC void
|
|
ipsctp_init_para_processing(Ipsctp_input_param *param,
|
|
Ip_u32 chunk_type,
|
|
Ipsctp_init_chunk_hdr *init_chunk,
|
|
Ipsctp_init_para_val *pval);
|
|
|
|
|
|
IP_PUBLIC Ip_s32
|
|
ipsctp_send_cookie_echo(Ipsctp_tcb *stcb,
|
|
Ipsctp_state_cookie *state_cookie,
|
|
Ip_u32 state_cookie_len,
|
|
Ipsctp_transport *transport);
|
|
|
|
IP_PUBLIC Ip_s32
|
|
ipsctp_hmac(Ip_u16 mac_type,
|
|
Ip_u8 *key,
|
|
Ip_u16 key_size,
|
|
void *data,
|
|
Ip_u32 data_size,
|
|
void *signature);
|
|
|
|
IP_PUBLIC Ip_s32
|
|
ipsctp_hmac_get_sig_size(Ip_u16 mac_id);
|
|
|
|
IP_PUBLIC Ip_s32
|
|
ipsctp_hmac_get_blk_size(Ip_u16 mac_id);
|
|
|
|
IP_PUBLIC Ipsctp_socket *
|
|
ipsctp_server_socket_new(Ipsctp_socket *listen_sock,
|
|
IP_CONST void *local_addr,
|
|
Ip_u16 local_port,
|
|
IP_CONST void *peer_addr,
|
|
Ip_u16 peer_port,
|
|
Ipsctp_netif *netif,
|
|
Ip_u16 vr,
|
|
Ip_sa_family_t sa_family);
|
|
|
|
IP_PUBLIC int
|
|
ipsctp_set_primary_addr(Ipsctp_tcb *tcb,
|
|
Ipsctp_addr *addr,
|
|
Ipsctp_transport *transport,
|
|
Ip_bool if_user,
|
|
Ip_bool if_init);
|
|
|
|
IP_PUBLIC int
|
|
ipsctp_alloc_tcb(Ipsctp_instance* instance, /* pointer to instance */
|
|
Ipsctp_addr * addr, /* add this address to new created tcb */
|
|
Ip_u32 tag, /* choose a tag if 0, and use specified tag for non-0*/
|
|
Ipsctp_tcb **newtcb, /* TCB of the new created association */
|
|
Ipsctp_transport **newtransport /* the new created transport */
|
|
);
|
|
|
|
IP_PUBLIC void
|
|
ipsctp_report_all_outbound(Ipsctp_tcb *tcb);
|
|
IP_PUBLIC int
|
|
ipsctp_free_tcb(Ipsctp_tcb *tcb /* TCB to be freed */
|
|
);
|
|
|
|
IP_PUBLIC Ipsctp_tcb *
|
|
ipsctp_tcb_lookup_by_instance(
|
|
Ipsctp_instance* instance, /* pointer to instance */
|
|
Ip_u32 vtag, /* local's verification tag, 0 for unspecified */
|
|
IP_CONST Ipsctp_addr *peer_soaddr,/* The peer socket address, IP_NULL for unspecified */
|
|
Ipsctp_transport **transport_ret /* transport matching the peer address, don't return transport if NULL */
|
|
);
|
|
|
|
IP_PUBLIC Ipsctp_chunk *
|
|
ipsctp_alloc_chunk(Ipsctp_tcb *tcb, Ip_u32 len);
|
|
|
|
IP_PUBLIC void
|
|
ipsctp_set_error(Ipsctp_input_param *param,
|
|
Ip_u16 error_type,
|
|
void *error_info);
|
|
|
|
|
|
IP_PUBLIC int
|
|
ipsctp_send_abort(Ipcom_pkt *pkt_in,
|
|
Ipsctp_sctp_hdr *hdr,
|
|
Ipsctp_vtag vtag,
|
|
Ip_u8 *error_cause,
|
|
Ip_u32 error_cause_len);
|
|
IP_PUBLIC int
|
|
ipsctp_send_OOTB_shutcompl(Ipcom_pkt *pkt_in,
|
|
Ipsctp_sctp_hdr *hdr);
|
|
IP_PUBLIC int ipsctp_send_shutdown(Ipsctp_tcb *tcb, Ipsctp_transport *tp);
|
|
IP_PUBLIC int ipsctp_send_shutdown_complete(Ipsctp_tcb *tcb);
|
|
IP_PUBLIC int ipsctp_send_shutdown_ack(Ipsctp_tcb *tcb, Ipsctp_transport *tp);
|
|
IP_PUBLIC int ipsctp_handle_abort(Ipsctp_input_param *param, Ipsctp_chunk_hdr *ch);
|
|
IP_PUBLIC int ipsctp_handle_abort_for_icmp(Ipsctp_tcb *tcb);
|
|
|
|
#if 0/* no use in SCTP */
|
|
IP_PUBLIC void ipsctp_abort_assoc(Ipcom_pkt *pkt_in,
|
|
Ipsctp_sctp_hdr *hdr,
|
|
Ip_u8 *error_cause,
|
|
Ip_u32 error_cause_len);
|
|
#endif
|
|
IP_PUBLIC void ipsctp_abort_assoc_tcb(Ipsctp_tcb *tcb,
|
|
int ab_err,
|
|
Ip_u8 *error_cause,
|
|
Ip_u32 error_cause_len);
|
|
IP_PUBLIC void
|
|
ipsctp_abort_assoc_tcb_with_err(Ipsctp_tcb *tcb,
|
|
int ab_err,
|
|
Ip_u16 ca_type,
|
|
Ip_u32 ca_data);
|
|
IP_PUBLIC Ip_s32 ipsctp_create_output_seg(Ipsctp_tcb *tcb, Ip_bool msg_more);
|
|
IP_PUBLIC void ipsctp_send_sack(Ipsctp_tcb *tcb);
|
|
IP_PUBLIC int ipsctp_send_heartbeat(Ipsctp_tcb *tcb, Ipsctp_transport *tp);
|
|
IP_PUBLIC int ipsctp_send_heartbeat_ack(Ipsctp_tcb *tcb, Ipsctp_transport *tp, Ipsctp_hb_chunk_hdr *in_ch);
|
|
|
|
IP_PUBLIC Ip_u32 ipsctp_calc_rto(Ipsctp_tcb *tcb,
|
|
Ipsctp_transport *transport,
|
|
struct Ip_timeval *tv);
|
|
IP_PUBLIC Ip_u8 * ipsctp_get_error_cause_space(Ipsctp_input_param *param, Ip_u16 len);
|
|
IP_PUBLIC void ipsctp_stop_timers_for_shutdown(Ipsctp_tcb *tcb);
|
|
IP_PUBLIC int ipsctp_change_state(Ipsctp_tcb *tcb, Ipsctp_state new_state);
|
|
IP_PUBLIC void ipsctp_timer_add(Ipsctp_instance *inst,
|
|
Ipsctp_tcb *tcb,
|
|
Ipsctp_transport *transport,
|
|
Ipsctp_timo type);
|
|
IP_PUBLIC void ipsctp_timer_remove(Ipsctp_instance *inst,
|
|
Ipsctp_tcb *tcb,
|
|
Ipsctp_transport *transport,
|
|
Ipsctp_timo type);
|
|
IP_PUBLIC void ipsctp_stop_all_cookie_timers(Ipsctp_tcb *tcb);
|
|
IP_PUBLIC Ipsctp_chunk_hdr * ipsctp_get_next_ctrl_chunk(void ** inputbuf, Ip_u16 *remain_len);
|
|
IP_PUBLIC Ipsctp_chunk_hdr * ipsctp_get_next_chunk(void ** inputbuf, Ip_u16 *remain_len);
|
|
|
|
IP_PUBLIC int ipsctp_queue_chunk_op_err(Ipsctp_tcb *tcb,
|
|
Ip_u16 param_type,
|
|
Ip_u8 *data,
|
|
Ip_u16 data_len);
|
|
IP_PUBLIC void
|
|
ipsctp_queue_chunk_mult_errs(Ipsctp_tcb *stcb,
|
|
void *errs_buf,
|
|
Ip_u32 errs_buf_len);
|
|
IP_PUBLIC Ip_u32 ipsctp_calc_rwnd(Ipsctp_tcb *tcb);
|
|
IP_PUBLIC Ip_bool ipsctp_is_known_chunk(Ip_u8 type);
|
|
IP_PUBLIC int ipsctp_sack_check(Ipsctp_tcb *tcb, Ip_bool gap_existed, Ip_bool send_sack);
|
|
IP_PUBLIC void ipsctp_v4_init(void);
|
|
IP_PUBLIC void ipsctp_register_af(Ipsctp_af_ops *sctp_af);
|
|
IP_PUBLIC Ipsctp_transport *
|
|
ipsctp_transport_lookup(Ipsctp_tcb * tcb, /* TCB of the association */
|
|
IP_CONST Ipsctp_addr *peer_soaddr); /* The peer socket address */
|
|
|
|
IP_PUBLIC Ipsctp_transport *
|
|
ipsctp_alt_transport_lookup(
|
|
Ipsctp_tcb * tcb, /* TCB of the association */
|
|
Ipsctp_transport *transport /* The SCTP transport */
|
|
);
|
|
IP_PUBLIC void
|
|
ipsctp_send_cookie_ack(Ipsctp_tcb *stcb);
|
|
IP_PUBLIC void ipsctp_v6_init(void);
|
|
IP_PUBLIC void ipsctp_free_in_stream(Ipsctp_tcb *tcb, Ipsctp_stream_in *streams_in);
|
|
IP_PUBLIC void ipsctp_free_out_stream(Ipsctp_tcb *tcb, Ipsctp_stream_out *streams_out);
|
|
IP_PUBLIC void ipsctp_init_in_stream(Ipsctp_tcb *tcb, Ipsctp_stream_in *streams_out, Ip_u16 stream_number);
|
|
IP_PUBLIC int ipsctp_threshold_management(Ipsctp_tcb *tcb, Ipsctp_transport *transport, Ip_u16 threshold);
|
|
IP_PUBLIC Ip_s32 ipsctp_send_init(Ipsctp_tcb *stcb);
|
|
IP_PUBLIC void
|
|
ipsctp_sin_v4_map_v6(void *v4, void *v6);
|
|
IP_PUBLIC Ip_bool
|
|
ipsctp_is_output_queue_empty(Ipsctp_tcb *tcb);
|
|
#ifdef IPSCTP_DEBUG
|
|
IP_PUBLIC const char *
|
|
ipsctp_addr_ntop(Ipsctp_addr *addr,
|
|
char *dst,
|
|
int len);
|
|
#endif
|
|
IP_PUBLIC int ipsctp_alloc_dummy_tcb(Ipsctp_instance* instance, Ipsctp_tcb **newtcb);
|
|
IP_PUBLIC Ip_u32 ipsctp_log3int(Ip_u32 priority, Ip_u32 debug_flag, const char *format, int line, int a, int b);
|
|
IP_PUBLIC void ipsctp_notify_cb(Ipsctp_tcb *tcb, Ipsctp_transport *transport, int event);
|
|
IP_PUBLIC Ip_u32 ipsctp_time_now(void);
|
|
|
|
IP_PUBLIC void
|
|
ipsctp_tx_segments(Ipsctp_tcb *tcb);
|
|
|
|
IP_PUBLIC int
|
|
ipsctp_handle_sendall(Ipsctp_tcb *tcb,
|
|
struct Ipsctp_sndrcvinfo *sndrcv,
|
|
Ipcom_pkt *pkt,
|
|
Ip_bool snd_btypes_check_flag);
|
|
|
|
/*+++++++++ ipsctp_sock.c +++++++++*/
|
|
IP_PUBLIC void
|
|
ipsctp_server_remove_from_backlog(Ipsctp_socket *listen_sock,
|
|
Ipsctp_socket *sock,
|
|
Ip_bool from_done);
|
|
IP_PUBLIC void
|
|
ipsctp_server_handshake_done(Ipsctp_socket *sock);
|
|
IP_PUBLIC void
|
|
ipsctp_sock_cleanup(Ipsctp_socket *sock);
|
|
IP_PUBLIC void
|
|
ipsctp_sock_kclose(Ipsctp_socket *sock);
|
|
IP_GLOBAL int ipsctp_drop_tcb(Ipsctp_tcb *tcb, int error_code);
|
|
IP_PUBLIC void
|
|
ipsctp_close_association(Ipsctp_tcb *tcb);
|
|
IP_PUBLIC Ipsctp_tcb *
|
|
ipsctp_sock_lookup_da(Ipsctp_socket *sock,
|
|
struct Ip_sockaddr *dst_addr);
|
|
|
|
/*+++++++++ ipsctp_debug.c +++++++++*/
|
|
#ifdef IPSCTP_DEBUG
|
|
IP_PUBLIC void
|
|
ipsctp_print_hex(void *buf,
|
|
const char *prompt,
|
|
Ip_u32 len);
|
|
IP_GLOBAL IP_CONST char *
|
|
ipsctp_state_to_str(int state);
|
|
IP_PUBLIC Ip_u32 ipsctp_show_buffer(Ipsctp_socket *sock);
|
|
|
|
#endif
|
|
#ifdef IPNET_DEBUG
|
|
IP_GLOBAL int ipsctp_tick_to_string(void *unused, char *buf, Ip_size_t buf_len);
|
|
#endif
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* IPSCTP_H_H */
|
|
|