sctp_impl.h revision 1d8c40254918b6a58c4b2132dafb3e012ccd66f0
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _INET_SCTP_SCTP_IMPL_H
#define _INET_SCTP_SCTP_IMPL_H
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/inttypes.h>
#include <inet/sctp_itf.h>
/* Streams device identifying info and version */
#define SCTP_DEV_IDINFO "SCTP Streams device 1.0"
/* Default buffer size and flow control wake up threshold. */
#define SCTP_XMIT_LOWATER 8192
#define SCTP_XMIT_HIWATER 102400
#define SCTP_RECV_LOWATER 8192
#define SCTP_RECV_HIWATER 102400
/* SCTP Timer control structure */
typedef struct sctpt_s {
struct sctp_faddr_s *sctpt_faddr;
} sctpt_t;
/*
* faddr timer mblks are not allocated until first use. This macro
* will allocate the timer mblk if necessary, set the faddr, and then
* start the timer.
*/
} \
(int)(intvl))); \
}
#define SCTP_FADDR_TIMER_STOP(fp) \
(fp)->timer_running = 0; \
}
{ \
}
/*
* Maximum number of duplicate TSNs we can report. This is currently
* static, and governs the size of the mblk used to hold the duplicate
* reports. The use of duplcate TSN reports is currently experimental,
* so for now a static limit should suffice.
*/
#define SCTP_DUP_MBLK_SZ 64
extern int sctp_g_num_epriv_ports;
extern uint16_t sctp_g_epriv_ports[];
extern kmutex_t sctp_epriv_port_lock;
extern uint_t sctp_next_port_to_try;
/*
* SCTP parameters
*/
/* Named Dispatch Parameter Management Structure */
typedef struct sctpparam_s {
char *sctp_param_name;
} sctpparam_t;
extern sctpparam_t sctp_param_arr[];
/*
* layer header. It has to be a multiple of 4.
*/
extern sctpparam_t sctp_wroff_xtra_param;
#define SCTP_MAX_HDR_LENGTH 60
#define SCTP_SECRET_LEN 16
#define SCTP_REFHOLD(sctp) { \
(sctp)->sctp_refcnt++; \
}
#define SCTP_REFRELE(sctp) { \
if (--(sctp)->sctp_refcnt == 0) { \
} else { \
} \
}
/*
* Outbound data, flags and macros for per-message, per-chunk info
*/
typedef struct {
#define SCTP_CHUNK_FLAG_SENT 0x01
#define SCTP_CHUNK_FLAG_REXMIT 0x02
#define SCTP_CHUNK_FLAG_ACKED 0x04
#define SCTP_MSG_FLAG_CHUNKED 0x08
#define SCTP_MSG_FLAG_ABANDONED 0x10
#define SCTP_CHUNK_FLAG_ABANDONED 0x20
/*
* If we are transmitting the chunk for the first time we assign the TSN and
* SSN here. The reason we assign the SSN here (as opposed to doing it in
* sctp_chunkify()) is that the chunk may expire, if PRSCTP is enabled, before
* we get a chance to send it out. If we assign the SSN in sctp_chunkify()
* and this happens, then we need to send a Forward TSN to the peer, which
* will be expecting this SSN, assuming ordered. If we assign it here we
* can just take out the chunk from the transmit list without having to
* send a Forward TSN chunk. While assigning the SSN we use (meta)->b_cont
* to determine if it needs a new SSN (i.e. the next SSN for the stream),
* since (meta)->b_cont signifies the first chunk of a message (if the message
* is unordered, then the SSN is 0).
*
*/
if (!SCTP_CHUNK_ISSENT(mp)) { \
} else { \
} \
} \
} else { \
if (SCTP_CHUNK_ISACKED(mp)) { \
} else { \
sizeof (*sdc))); \
sizeof (*sdc)); \
} \
SCTP_CHUNK_SET_SACKCNT(mp, 0); \
} \
}
#define SCTP_CHUNK_CANSEND(mp) \
(!(SCTP_CHUNK_ABANDONED(mp)) && \
#define SCTP_CHUNK_ACKED(mp) \
/* For PR-SCTP */
#define SCTP_CHUNK_ABANDONED(mp) \
#define SCTP_MSG_SET_ABANDONED(mp) \
/*
* Check if a message has expired. A message is expired if
* 1. It has a non-zero time to live value and has not been sent before
* that time expires.
* 2. It is sent using PRSCTP and it has not been SACK'ed before
* its lifetime expires.
*/
/* SCTP association hash function. */
#define SCTP_CONN_HASH(ports) \
/*
* Bind hash array size and hash function. The size must be a power
* of 2 and lport must be in host byte order.
*/
#define SCTP_BIND_FANOUT_SIZE 2048
/* options that SCTP negotiates during association establishment */
#define SCTP_PRSCTP_OPTION 0x01
/*
* Listener hash array size and hash function. The size must be a power
* of 2 and lport must be in host byte order.
*/
#define SCTP_LISTEN_FANOUT_SIZE 512
typedef struct sctp_tf_s {
} sctp_tf_t;
/* SCTP association hash list */
extern sctp_tf_t *sctp_conn_fanout;
/* Size of sctp_conn_fanout */
extern uint_t sctp_conn_hash_size;
/* SCTP bind hash list - all sctp_t with state >= BOUND. */
extern sctp_tf_t sctp_bind_fanout[];
/* SCTP listener hash list - all sctp_t with state == LISTEN. */
extern sctp_tf_t sctp_listen_fanout[];
/* Round up the value to the nearest mss. */
/*
* Object to represent database of options to search passed to
* {sock,tpi}optcom_req() interface routine to take care of option
* management and associated methods.
* XXX These and other externs should ideally move to a SCTP header
*/
extern optdb_obj_t sctp_opt_obj;
extern uint_t sctp_max_optbuf_len;
/* Data structure used to track received TSNs */
typedef struct sctp_set_s {
struct sctp_set_s *next;
struct sctp_set_s *prev;
} sctp_set_t;
/* Data structure used to track TSNs for PR-SCTP */
typedef struct sctp_ftsn_set_s {
struct sctp_ftsn_set_s *next;
/* Data structure used to track incoming SCTP streams */
typedef struct sctp_instr_s {
int istr_nmsgs;
} sctp_instr_t;
/* Reassembly data structure (per-stream) */
typedef struct sctp_reass_s {
} sctp_reass_t;
/* debugging */
extern int sctpdebug;
#else /* define(DEBUG) && !defined(lint) */
#endif /* defined(DEBUG) && !defined(lint) */
/* Peer address tracking */
/*
* States for peer addresses
*
* SCTP_FADDRS_UNCONFIRMED: we have not communicated with this peer address
* before, mark it as unconfirmed so that we will not send data to it.
* All addresses initially are in unconfirmed state and required
* validation. SCTP sends a heartbeat to each of them and when it gets
* back a heartbeat ACK, the address will be marked as alive. This
* validation fixes a security issue with multihoming. If an attacker
* establishes an association with us and tells us that it has addresses
* belonging to another host A, this will prevent A from communicating
* with us. This is fixed by peer address validation. In the above case,
* A will respond with an abort.
*
* SCTP_FADDRS_ALIVE: this peer address is alive and we can communicate with
* it with no problem.
*
* SCTP_FADDRS_DOWN: we have exceeded the retransmission limit to this
* peer address. Once an address is marked down, we will only send
* a heartbeat to it every hb_interval in case it becomes alive now.
*
* SCTP_FADDRS_UNREACH: there is no suitable source address to send to
* this peer address. For example, the peer address is v6 but we only
* have v4 addresses. It is marked unreachable until there is an
* address configuration change. At that time, mark these addresses
* as unconfirmed and try again to see if those unreachable addresses
* are OK as we may have more source addresses.
*/
typedef enum {
typedef struct sctp_faddr_s {
struct sctp_faddr_s *next;
int rto; /* RTO in tick */
int srtt; /* Smoothed RTT in tick */
int rttvar; /* RTT variance in tick */
int strikes;
int max_retr;
hb_pending : 1,
timer_running : 1,
df : 1,
pmtu_discovered : 1,
rc_timer_running : 1,
isv4 : 1;
} sctp_faddr_t;
/* Flags to indicate supported address type in the PARM_SUP_ADDRS. */
#define PARM_SUPP_V6 0x1
#define PARM_SUPP_V4 0x2
/*
* Set heartbeat interval plus jitter. The jitter is supposed to be random,
* up to +/- 50% of the RTO. We use gethrtime() here for performance reason
* as the jitter does not really need to be "very" random.
*/
#define SET_HB_INTVL(fp) \
#define SCTP_IPIF_HASH 16
typedef struct sctp_ipif_hash_s {
int ipif_count;
struct sctp_s;
/*
* Control structure for each open SCTP stream,
* defined only within the kernel or for a kmem user.
* NOTE: sctp_reinit_values MUST have a line for each field in this structure!
*/
typedef struct sctp_s {
/*
* The following is shared with (and duplicated) in IP, so if you
* make changes, make sure you also change things in ip_sctp.c.
*/
struct sctp_s *sctp_conn_hash_next;
struct sctp_s *sctp_conn_hash_prev;
struct sctp_s *sctp_listen_hash_next;
struct sctp_s *sctp_listen_hash_prev;
/* Global list of sctp */
int sctp_nfaddrs;
int sctp_nsaddrs;
/*
* These fields contain the same information as sctp_sctph->th_*port.
* However, the lookup functions can not use the header fields
* since during IP option manipulation the sctp_sctph pointer
* changes.
*/
union {
struct {
} sctpu_ports1;
/* local port */
/* Used for SCTP_MATCH performance */
} sctp_sctpu;
void *sctp_ulpd; /* SCTP upper layer desc. */
/* Peer address tracking */
/* Outbound data tracking */
/* sendmsg() default parameters */
/* Inbound data tracking */
/* RTT calculation */
/* Stats */
/* Outbound flow control */
/* Inbound flow control */
/* Pre-initialized composite headers */
char *sctp_iphc6; /* v6 sctp/ip hdr template buffer */
/* Path MTU Discovery */
/* structs sctp_bits, sctp_events are for clearing all bits at once */
struct {
sctp_force_sack : 1,
sctp_bound_to_all : 1,
} sctp_bits;
struct {
sctp_recvsndrcvinfo : 1,
sctp_recvassocevnt : 1,
sctp_recvpathevnt : 1,
sctp_recvpeererr : 1,
sctp_recvpdevnt : 1,
sctp_recvalevnt : 1;
} sctp_events;
/* Retransmit info */
/*
* Address family that app wishes returned addrsses to be in.
* Currently taken from address family used in T_BIND_REQ, but
* should really come from family used in original socket() call.
* Value can be AF_INET or AF_INET6.
*/
/* Bind hash tables */
struct sctp_s *sctp_bind_hash;
struct sctp_s **sctp_ptpbhn;
/* Shutdown / cleanup */
int sctp_lingertime; /* Close linger time (in seconds) */
/* Misc */
/* Reliable control chunks */
/* Per association receive queue */
/* Send queue to IP */
/* IPv6 ancillary data */
/* Stats */
} sctp_t;
extern kmutex_t sctp_g_lock;
#endif /* (defined(_KERNEL) || defined(_KMEMUSER)) */
/* Padding mblk for SCTP chunks. */
extern mblk_t *sctp_pad_mp;
extern void sctp_ack_timer(sctp_t *);
extern void sctp_adaption_event(sctp_t *);
int *);
sctp_chunk_hdr_t *);
extern void sctp_bind_hash_remove(sctp_t *);
extern int sctp_build_hdrs(sctp_t *);
extern void sctp_chunkify(sctp_t *, int, int);
extern void sctp_clean_death(sctp_t *, int);
extern void sctp_close_eager(sctp_t *);
extern void sctp_congest_reset(sctp_t *);
extern void sctp_conn_hash_remove(sctp_t *);
zoneid_t);
sctp_init_chunk_t *, mblk_t *);
int *);
extern char *sctp_display(sctp_t *, char *);
extern void sctp_display_all();
extern void sctp_faddr_fini();
extern void sctp_faddr_init();
extern void sctp_fast_rexmit(sctp_t *);
extern void sctp_fill_sack(sctp_t *, unsigned char *, int);
extern void sctp_free_faddr_timers(sctp_t *);
extern void sctp_free_ftsn_set(sctp_ftsn_set_t *);
extern void sctp_free_msg(mblk_t *);
extern void sctp_free_reass(sctp_instr_t *);
extern void sctp_free_set(sctp_set_t *);
extern void sctp_ftsn_sets_fini(void);
extern void sctp_ftsn_sets_init(void);
sctp_chunk_hdr_t *, uint_t *);
extern in_port_t sctp_get_next_priv_port();
mblk_t *);
extern void sctp_hash_destroy(void);
extern void sctp_hash_init(void);
extern int sctp_header_init_ipv4(sctp_t *, int);
extern int sctp_header_init_ipv6(sctp_t *, int);
extern void sctp_heartbeat_timer(sctp_t *);
extern void sctp_inc_taskq(void);
extern int sctp_is_a_faddr_clean(sctp_t *);
extern void sctp_kstat_init(void);
extern void sctp_kstat_fini(void);
extern void sctp_listen_hash_remove(sctp_t *);
int);
sctp_faddr_t *, uint32_t *);
extern void sctp_maxpsz_set(sctp_t *);
extern void sctp_nd_free();
extern boolean_t sctp_nd_init();
extern void sctp_partial_delivery_event(sctp_t *);
extern void sctp_process_sendq(sctp_t *);
extern void sctp_process_timer(sctp_t *);
extern void sctp_redo_faddr_srcs(sctp_t *);
extern void sctp_regift_xmitlist(sctp_t *);
uint32_t, int);
extern void sctp_send_cookie_ack(sctp_t *);
extern void sctp_send_shutdown(sctp_t *, int);
extern void sctp_set_hdraddrs(sctp_t *);
extern void sctp_sets_init();
extern void sctp_sets_fini();
extern void sctp_shutdown_event(sctp_t *);
extern void sctp_stop_faddr_timers(sctp_t *);
extern void sctp_shutdown_complete(sctp_t *);
extern void sctp_set_if_mtu(sctp_t *);
extern void sctp_set_ulp_prop(sctp_t *);
extern void sctp_timer_free(mblk_t *);
extern void sctp_timer_stop(mblk_t *);
extern void sctp_validate_peer(sctp_t *);
extern void sctp_zap_addrs(sctp_t *);
extern void sctp_zap_faddrs(sctp_t *, int);
/* Contract private interface between SCTP and Clustering - PSARC/2005/602 */
/* Send a mp to IP. */
{ \
if ((isv4)) \
else \
}
{ \
while ((sctp)->sctp_running) \
}
/* Wake up recvq taskq */
{ \
}
#ifdef __cplusplus
}
#endif
#endif /* _INET_SCTP_SCTP_IMPL_H */