/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (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
 * or http://www.opensolaris.org/os/licensing.
 * 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 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_NETINET_SCTP_H
#define	_NETINET_SCTP_H

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/types.h>

/*
 * This file contains the structure defintions and function prototypes
 * described in the IETF SCTP socket API document.
 */

/* SCTP association ID type. */
typedef int	sctp_assoc_t;
typedef int32_t	sctp_assoc32_t;

/*
 * SCTP socket options
 */
#define	SCTP_RTOINFO			1
#define	SCTP_ASSOCINFO			2
#define	SCTP_INITMSG			3
#define	SCTP_NODELAY			4
#define	SCTP_AUTOCLOSE			5
#define	SCTP_SET_PEER_PRIMARY_ADDR	6
#define	SCTP_PRIMARY_ADDR		7
#define	SCTP_ADAPTATION_LAYER		8
#define	SCTP_DISABLE_FRAGMENTS		9
#define	SCTP_PEER_ADDR_PARAMS		10
#define	SCTP_DEFAULT_SEND_PARAM		11
#define	SCTP_EVENTS			12
#define	SCTP_I_WANT_MAPPED_V4_ADDR	13
#define	SCTP_MAXSEG			14
#define	SCTP_STATUS			15
#define	SCTP_GET_PEER_ADDR_INFO		16

/*
 * Private socket options
 */
#define	SCTP_GET_NLADDRS		17
#define	SCTP_GET_LADDRS			18
#define	SCTP_GET_NPADDRS		19
#define	SCTP_GET_PADDRS			20
#define	SCTP_ADD_ADDR			21
#define	SCTP_REM_ADDR			22

/*
 * Additional SCTP socket options. This socket option is used to enable or
 * disable PR-SCTP support prior to establishing an association. By default,
 * PR-SCTP support is disabled.
 */
#define	SCTP_PRSCTP			23

/*
 * SCTP socket option used to read per endpoint association statistics.
 */
#define	SCTP_GET_ASSOC_STATS		24

/*
 * Ancillary data identifiers
 */
#define	SCTP_SNDRCV		0x100
#define	SCTP_INIT		0x101

/*
 * Notification types
 */
#define	SCTP_ASSOC_CHANGE		1
#define	SCTP_PEER_ADDR_CHANGE		2
#define	SCTP_REMOTE_ERROR		3
#define	SCTP_SEND_FAILED		4
#define	SCTP_SHUTDOWN_EVENT		5
#define	SCTP_ADAPTATION_INDICATION	6
#define	SCTP_PARTIAL_DELIVERY_EVENT	7

/*
 * SCTP Ancillary Data Definitions
 */

/*
 * sctp_initmsg structure provides information for initializing new SCTP
 * associations with sendmsg().  The SCTP_INITMSG socket option uses
 * this same data structure.
 */
struct sctp_initmsg {
	uint16_t	sinit_num_ostreams;
	uint16_t	sinit_max_instreams;
	uint16_t	sinit_max_attempts;
	uint16_t	sinit_max_init_timeo;
};

/*
 * sctp_sndrcvinfo structure specifies SCTP options for sendmsg() and
 * describes SCTP header information about a received message through
 * recvmsg().
 */
struct sctp_sndrcvinfo {
	uint16_t	sinfo_stream;
	uint16_t	sinfo_ssn;
	uint16_t	sinfo_flags;
	uint32_t	sinfo_ppid;
	uint32_t	sinfo_context;
	uint32_t	sinfo_timetolive;
	uint32_t	sinfo_tsn;
	uint32_t	sinfo_cumtsn;
	sctp_assoc_t	sinfo_assoc_id;
};

/* sinfo_flags */
#define	MSG_UNORDERED	0x01		/* Unordered data */
#define	MSG_ABORT	0x02		/* Abort the connection */
#define	MSG_EOF		0x04		/* Shutdown the connection */

/*
 * Use destination addr passed as parameter, not the association primary one.
 */
#define	MSG_ADDR_OVER	0x08
/*
 * This flag when set in sinfo_flags is used alongwith sinfo_timetolive to
 * implement the "timed reliability" service discussed in RFC 3758.
 */
#define	MSG_PR_SCTP	0x10
/*
 * SCTP notification definitions
 */

/*
 * To receive any ancillary data or notifications, the application can
 * register it's interest by calling the SCTP_EVENTS setsockopt() with
 * the sctp_event_subscribe structure.
 */
struct sctp_event_subscribe {
	uint8_t	sctp_data_io_event;
	uint8_t sctp_association_event;
	uint8_t sctp_address_event;
	uint8_t sctp_send_failure_event;
	uint8_t sctp_peer_error_event;
	uint8_t sctp_shutdown_event;
	uint8_t sctp_partial_delivery_event;
	uint8_t sctp_adaptation_layer_event;
};

/* Association events used in sctp_assoc_change structure */
#define	SCTP_COMM_UP		0
#define	SCTP_COMM_LOST		1
#define	SCTP_RESTART		2
#define	SCTP_SHUTDOWN_COMP	3
#define	SCTP_CANT_STR_ASSOC	4

/*
 * Association flags. This flags is filled in the sac_flags for a SCTP_COMM_UP
 * event if the association supports PR-SCTP.
 */
#define	SCTP_PRSCTP_CAPABLE	0x01

/*
 * sctp_assoc_change notification informs the socket that an SCTP association
 * has either begun or ended.  The identifier for a new association is
 * provided by this notification.
 */
struct sctp_assoc_change {
	uint16_t	sac_type;
	uint16_t	sac_flags;
	uint32_t	sac_length;
	uint16_t	sac_state;
	uint16_t	sac_error;
	uint16_t	sac_outbound_streams;
	uint16_t	sac_inbound_streams;
	sctp_assoc_t	sac_assoc_id;
	/*
	 * The assoc ID can be followed by the ABORT chunk if available.
	 */
};

/*
 * A remote peer may send an Operational Error message to its peer. This
 * message indicates a variety of error conditions on an association.
 * The entire ERROR chunk as it appears on the wire is included in a
 * SCTP_REMOTE_ERROR event.  Refer to the SCTP specification RFC2960
 * and any extensions for a list of possible error formats.
 */
struct sctp_remote_error {
	uint16_t	sre_type;
	uint16_t	sre_flags;
	uint32_t	sre_length;
	uint16_t	sre_error;
	sctp_assoc_t	sre_assoc_id;
	/*
	 * The assoc ID is followed by the actual error chunk.
	 */
};

/*
 * Note:
 *
 * In order to keep the offsets and size of the structure having a
 * struct sockaddr_storage field the same between a 32-bit application
 * and a 64-bit amd64 kernel, we use a #pragma pack(4) for those
 * structures.
 */
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack(4)
#endif

/* Address change event state */
#define	SCTP_ADDR_AVAILABLE	0
#define	SCTP_ADDR_UNREACHABLE	1
#define	SCTP_ADDR_REMOVED	2
#define	SCTP_ADDR_ADDED		3
#define	SCTP_ADDR_MADE_PRIM	4

/*
 * When a destination address on a multi-homed peer encounters a change,
 * an interface details event, sctp_paddr_change, is sent to the socket.
 */
struct sctp_paddr_change {
	uint16_t	spc_type;
	uint16_t	spc_flags;
	uint32_t	spc_length;
	struct sockaddr_storage spc_aaddr;
	int		spc_state;
	int		spc_error;
	sctp_assoc_t	spc_assoc_id;
};

#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack()
#endif

/* flags used in sctp_send_failed notification. */
#define	SCTP_DATA_UNSENT	1
#define	SCTP_DATA_SENT		2

/*
 * If SCTP cannot deliver a message it may return the message as a
 * notification using the following structure.
 */
struct sctp_send_failed {
	uint16_t	ssf_type;
	uint16_t	ssf_flags;
	uint32_t	ssf_length;
	uint32_t	ssf_error;
	struct sctp_sndrcvinfo ssf_info;
	sctp_assoc_t	ssf_assoc_id;
	/*
	 * The assoc ID is followed by the failed message.
	 */
};

/*
 * When a peer sends a SHUTDOWN, SCTP delivers the sctp_shutdown_event
 * notification to inform the socket user that it should cease sending data.
 */
struct sctp_shutdown_event {
	uint16_t	sse_type;
	uint16_t	sse_flags;
	uint16_t	sse_length;
	sctp_assoc_t	sse_assoc_id;
};

/*
 * When a peer sends an Adaptation Layer Indication parameter, SCTP
 * delivers the sctp_adaptation_event notification to inform the socket
 * user the peer's requested adaptation layer.
 */
struct sctp_adaptation_event {
	uint16_t	sai_type;
	uint16_t	sai_flags;
	uint32_t	sai_length;
	uint32_t	sai_adaptation_ind;
	sctp_assoc_t	sai_assoc_id;
};

/* Possible values in pdapi_indication for sctp_pdapi_event notification. */
#define	SCTP_PARTIAL_DELIVERY_ABORTED	1

/*
 * When a receiver is engaged in a partial delivery of a message the
 * sctp_pdapi_event notification is used to indicate various events.
 */
struct sctp_pdapi_event {
	uint16_t	pdapi_type;
	uint16_t	pdapi_flags;
	uint32_t	pdapi_length;
	uint32_t	pdapi_indication;
	sctp_assoc_t	pdapi_assoc_id;
};

/*
 * The sctp_notification structure is defined as the union of all
 * notification types defined above.
 */
union sctp_notification {
	struct {
		uint16_t		sn_type; /* Notification type. */
		uint16_t		sn_flags;
		uint32_t		sn_length;
	} sn_header;
	struct sctp_assoc_change	sn_assoc_change;
	struct sctp_paddr_change	sn_paddr_change;
	struct sctp_remote_error	sn_remote_error;
	struct sctp_send_failed		sn_send_failed;
	struct sctp_shutdown_event	sn_shutdown_event;
	struct sctp_adaptation_event	sn_adaptation_event;
	struct sctp_pdapi_event		sn_pdapi_event;
};

/*
 * sctp_opt_info() option definitions
 */

/*
 * The protocol parameters used to initialize and bound retransmission
 * timeout (RTO) are tunable.  See RFC2960 for more information on
 * how these parameters are used in RTO calculation.
 *
 * The sctp_rtoinfo structure is used to access and modify these
 * parameters.
 */
struct sctp_rtoinfo {
	sctp_assoc_t	srto_assoc_id;
	uint32_t	srto_initial;
	uint32_t	srto_max;
	uint32_t	srto_min;
};

/*
 * The sctp_assocparams option is used to both examine and set various
 * association and endpoint parameters.  See RFC2960 for more information
 * on how this parameter is used.  The peer address parameter is ignored
 * for one-to-one style socket.
 */
struct sctp_assocparams {
	sctp_assoc_t	sasoc_assoc_id;
	uint16_t	sasoc_asocmaxrxt;
	uint16_t	sasoc_number_peer_destinations;
	uint32_t	sasoc_peer_rwnd;
	uint32_t	sasoc_local_rwnd;
	uint32_t	sasoc_cookie_life;
};

#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack(4)
#endif

/* sctp_paddrinfo reachability state. */
#define	SCTP_INACTIVE	1
#define	SCTP_ACTIVE	2

/*
 * Applications can retrieve information about a specific peer address
 * of an association, including its reachability state, congestion
 * window, and retransmission timer values.  This information is
 * read-only. The sctp_paddrinfo structure is used to access this
 * information:
 */
struct sctp_paddrinfo {
	sctp_assoc_t	spinfo_assoc_id;
	struct sockaddr_storage spinfo_address;
	int32_t		spinfo_state;
	uint32_t	spinfo_cwnd;
	uint32_t	spinfo_srtt;
	uint32_t	spinfo_rto;
	uint32_t	spinfo_mtu;
};

/*
 * Applications can enable or disable heartbeats for any peer address of
 * an association, modify an address's heartbeat interval, force a
 * heartbeat to be sent immediately, and adjust the address's maximum
 * number of retransmissions sent before an address is considered
 * unreachable.  The sctp_paddrparams structure is used to access and modify
 * an address' parameters.
 */
struct sctp_paddrparams {
	sctp_assoc_t		spp_assoc_id;
	struct sockaddr_storage	spp_address;
	uint32_t		spp_hbinterval;
	uint16_t		spp_pathmaxrxt;
};

/*
 * A socket user can request that the peer mark the enclosed address as the
 * association's primary.  The enclosed address must be one of the
 * association's locally bound addresses. The sctp_setpeerprim structure is
 * used to make such request.
 */
struct sctp_setpeerprim {
	sctp_assoc_t		sspp_assoc_id;
	struct sockaddr_storage	sspp_addr;
};

/*
 * A socket user can request that the local SCTP stack use the enclosed peer
 * address as the association primary.  The enclosed address must be one of
 * the association peer's addresses.  The sctp_setprim structure is used to
 * make such request.
 */
struct sctp_setprim {
	sctp_assoc_t		ssp_assoc_id;
	struct sockaddr_storage	ssp_addr;
};

#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack()
#endif

/* SCTP association states */
#define	SCTPS_IDLE		-5	/* idle (opened, but not bound) */
#define	SCTPS_BOUND		-4	/* bound, ready to connect or accept */
#define	SCTPS_LISTEN		-3	/* listening for connection */
#define	SCTPS_COOKIE_WAIT	-2
#define	SCTPS_COOKIE_ECHOED	-1
/* states < SCTPS_ESTABLISHED are those where connections not established */
#define	SCTPS_ESTABLISHED	0	/* established */
#define	SCTPS_SHUTDOWN_PENDING	1
#define	SCTPS_SHUTDOWN_SENT	2
#define	SCTPS_SHUTDOWN_RECEIVED	3
#define	SCTPS_SHUTDOWN_ACK_SENT	4

/*
 * Applications can retrieve current status information about an
 * association, including association state, peer receiver window size,
 * number of unacked data chunks, and number of data chunks pending
 * receipt.  This information is read-only.  The sctp_status structure is
 * used to access this information:
 */
struct sctp_status {
	sctp_assoc_t		sstat_assoc_id;
	int32_t			sstat_state;
	uint32_t		sstat_rwnd;
	uint16_t		sstat_unackdata;
	uint16_t		sstat_penddata;
	uint16_t		sstat_instrms;
	uint16_t		sstat_outstrms;
	uint32_t		sstat_fragmentation_point;
	struct sctp_paddrinfo	sstat_primary;
};

/* Possible values for sstat_state */
#define	SCTP_CLOSED		SCTPS_IDLE
#define	SCTP_BOUND		SCTPS_BOUND
#define	SCTP_LISTEN		SCTPS_LISTEN
#define	SCTP_COOKIE_WAIT	SCTPS_COOKIE_WAIT
#define	SCTP_COOKIE_ECHOED	SCTPS_COOKIE_ECHOED
#define	SCTP_ESTABLISHED	SCTPS_ESTABLISHED
#define	SCTP_SHUTDOWN_PENDING	SCTPS_SHUTDOWN_PENDING
#define	SCTP_SHUTDOWN_SENT	SCTPS_SHUTDOWN_SENT
#define	SCTP_SHUTDOWN_RECEIVED	SCTPS_SHUTDOWN_RECEIVED
#define	SCTP_SHUTDOWN_ACK_SENT	SCTPS_SHUTDOWN_ACK_SENT

/*
 * A socket user can request that the local endpoint set the specified
 * Adaptation Layer Indication parameter for all future INIT and INIT-ACK
 * exchanges.  The sctp_setadaptation structure is used to make such request.
 */
struct sctp_setadaptation {
	uint32_t   ssb_adaptation_ind;
};

/*
 * A socket user request reads local per endpoint association stats.
 * All stats are counts except sas_maxrto, which is the max value
 * since the last user request for stats on this endpoint.
 */
typedef struct sctp_assoc_stats {
	uint64_t	sas_rtxchunks; /* Retransmitted Chunks */
	uint64_t	sas_gapcnt; /* Gap Acknowledgements Received */
	uint64_t	sas_maxrto; /* Maximum Observed RTO this period */
	uint64_t	sas_outseqtsns; /* TSN received > next expected */
	uint64_t	sas_osacks; /* SACKs sent */
	uint64_t	sas_isacks; /* SACKs received */
	uint64_t	sas_octrlchunks; /* Control chunks sent - no dups */
	uint64_t	sas_ictrlchunks; /* Control chunks received - no dups */
	uint64_t	sas_oodchunks; /* Ordered data chunks sent */
	uint64_t	sas_iodchunks; /* Ordered data chunks received */
	uint64_t	sas_ouodchunks; /* Unordered data chunks sent */
	uint64_t	sas_iuodchunks; /* Unordered data chunks received */
	uint64_t	sas_idupchunks; /* Dups received (ordered+unordered) */
} sctp_assoc_stats_t;

/*
 * Private ioctl option structure
 */
struct sctpopt {
	sctp_assoc_t	sopt_aid;
	int		sopt_name;
	uint_t		sopt_len;
	caddr_t		sopt_val;
};

#if defined(_SYSCALL32)
struct sctpopt32 {
	sctp_assoc32_t	sopt_aid;
	int32_t		sopt_name;
	uint32_t	sopt_len;
	caddr32_t	sopt_val;
};
#endif	/* _SYSCALL32 */

/* Forward Cumulative TSN chunk entry. */
typedef struct ftsn_entry_s {
	uint16_t	ftsn_sid;
	uint16_t	ftsn_ssn;
} ftsn_entry_t;

/*
 * New socket functions for SCTP
 */

/* sctp_bindx() operations. */
#define	SCTP_BINDX_ADD_ADDR	1
#define	SCTP_BINDX_REM_ADDR	2

#if !defined(_KERNEL) || defined(_BOOT)
#ifdef	__STDC__
extern int sctp_bindx(int, void *, int, int);
extern void sctp_freeladdrs(void *);
extern void sctp_freepaddrs(void *);
extern int sctp_getladdrs(int, sctp_assoc_t, void **);
extern int sctp_getpaddrs(int, sctp_assoc_t, void **);
extern int sctp_opt_info(int, sctp_assoc_t, int, void *, socklen_t *);
extern int sctp_peeloff(int, sctp_assoc_t);
extern ssize_t sctp_recvmsg(int, void *, size_t, struct sockaddr *,
    socklen_t *, struct sctp_sndrcvinfo *, int *msg_flags);
extern ssize_t sctp_send(int, const void *, size_t,
    const struct sctp_sndrcvinfo *, int);
extern ssize_t sctp_sendmsg(int, const void *, size_t, const struct sockaddr *,
    socklen_t, uint32_t, uint32_t, uint16_t, uint32_t, uint32_t);
#else	/* __STDC__ */
extern int sctp_bindx();
extern void sctp_freeladdrs();
extern void sctp_freepaddrs();
extern int sctp_getladdrs();
extern int sctp_getpaddrs();
extern int sctp_opt_info();
extern int sctp_peeloff();
extern ssize_t sctp_recvmsg();
extern ssize_t sctp_send();
extern ssize_t sctp_sendmsg();
#endif	/* __STDC__ */
#endif	/* !defined(_KERNEL) || defined(_BOOT) */


/*
 * SCTP protocol related elements.
 */

/* All SCTP chunks and parameters are 32-bit aligned */
#define	SCTP_ALIGN	4

/*
 * SCTP association optional parameter handling. The top two bits
 * of the parameter type define how this and further parameters in
 * the received chunk should be handled.
 */
#define	SCTP_UNREC_PARAM_MASK	0xc000
/* Continue processing parameters after an unrecognized optional param? */
#define	SCTP_CONT_PROC_PARAMS	0x8000
/* Report this unreconized optional parameter or silently ignore it? */
#define	SCTP_REPORT_THIS_PARAM	0x4000

/*
 * Data chunk bit manipulations
 */
#define	SCTP_DATA_EBIT	0x01
#define	SCTP_TBIT	0x01
#define	SCTP_DATA_BBIT	0x02
#define	SCTP_DATA_UBIT	0x04

#define	SCTP_DATA_GET_BBIT(sdc)	((sdc)->sdh_flags & SCTP_DATA_BBIT)
#define	SCTP_GET_TBIT(cp)	((cp)->sch_flags & SCTP_TBIT)
#define	SCTP_DATA_GET_EBIT(sdc)	((sdc)->sdh_flags & SCTP_DATA_EBIT)
#define	SCTP_DATA_GET_UBIT(sdc)	((sdc)->sdh_flags & SCTP_DATA_UBIT)

#define	SCTP_DATA_SET_BBIT(sdc)	((sdc)->sdh_flags |= SCTP_DATA_BBIT)
#define	SCTP_SET_TBIT(cp)	((cp)->sch_flags |= SCTP_TBIT)
#define	SCTP_DATA_SET_EBIT(sdc)	((sdc)->sdh_flags |= SCTP_DATA_EBIT)
#define	SCTP_DATA_SET_UBIT(sdc)	((sdc)->sdh_flags |=  SCTP_DATA_UBIT)

/* SCTP common header */
typedef struct sctp_hdr {
	uint16_t	sh_sport;
	uint16_t	sh_dport;
	uint32_t	sh_verf;
	uint32_t	sh_chksum;
} sctp_hdr_t;

/* Chunk IDs */
typedef enum {
	CHUNK_DATA,
	CHUNK_INIT,
	CHUNK_INIT_ACK,
	CHUNK_SACK,
	CHUNK_HEARTBEAT,
	CHUNK_HEARTBEAT_ACK,
	CHUNK_ABORT,
	CHUNK_SHUTDOWN,
	CHUNK_SHUTDOWN_ACK,
	CHUNK_ERROR,
	CHUNK_COOKIE,
	CHUNK_COOKIE_ACK,
	CHUNK_ECNE,
	CHUNK_CWR,
	CHUNK_SHUTDOWN_COMPLETE,
	CHUNK_ASCONF_ACK = 128,
	CHUNK_FORWARD_TSN = 192,
	CHUNK_ASCONF = 193
} sctp_chunk_id_t;

/* Common chunk header */
typedef struct sctp_chunk_hdr {
	uint8_t		sch_id;
	uint8_t		sch_flags;
	uint16_t	sch_len;
} sctp_chunk_hdr_t;

/* INIT chunk data definition */
typedef struct sctp_init_chunk {
	uint32_t	sic_inittag;
	uint32_t	sic_a_rwnd;
	uint16_t	sic_outstr;
	uint16_t	sic_instr;
	uint32_t	sic_inittsn;
} sctp_init_chunk_t;

/* SCTP DATA chunk */
typedef struct sctp_data_chunk {
	uint32_t	sdc_tsn;
	uint16_t	sdc_sid;
	uint16_t	sdc_ssn;
	uint32_t	sdc_payload_id;
} sctp_data_chunk_t;

/* sctp_data_hdr includes the SCTP chunk hdr and the DATA chunk */
typedef struct sctp_data_hdr {
	sctp_chunk_hdr_t	sdh_chdr;
	sctp_data_chunk_t	sdh_data;
#define	sdh_id		sdh_chdr.sch_id
#define	sdh_flags	sdh_chdr.sch_flags
#define	sdh_len		sdh_chdr.sch_len
#define	sdh_tsn		sdh_data.sdc_tsn
#define	sdh_sid		sdh_data.sdc_sid
#define	sdh_ssn		sdh_data.sdc_ssn
#define	sdh_payload_id	sdh_data.sdc_payload_id
} sctp_data_hdr_t;

typedef struct sctp_sack_chunk {
	uint32_t	ssc_cumtsn;
	uint32_t	ssc_a_rwnd;
	uint16_t	ssc_numfrags;
	uint16_t	ssc_numdups;
} sctp_sack_chunk_t;

typedef struct sctp_sack_frag {
	uint16_t	ssf_start;
	uint16_t	ssf_end;
} sctp_sack_frag_t;

/* Parameter types */
#define	PARM_UNKNOWN		0
#define	PARM_HBINFO		1
#define	PARM_ADDR4		5
#define	PARM_ADDR6		6
#define	PARM_COOKIE		7
#define	PARM_UNRECOGNIZED	8
#define	PARM_COOKIE_PRESERVE	9
#define	PARM_ADDR_HOST_NAME	11
#define	PARM_SUPP_ADDRS		12
#define	PARM_ECN		0x8000
#define	PARM_ECN_CAPABLE	PARM_ECN
#define	PARM_FORWARD_TSN	0xc000
#define	PARM_ADD_IP		0xc001
#define	PARM_DEL_IP		0xc002
#define	PARM_ERROR_IND		0xc003
#define	PARM_ASCONF_ERROR	PARM_ERROR_IND
#define	PARM_SET_PRIMARY	0xc004
#define	PARM_PRIMARY_ADDR	PARM_SET_PRIMARY
#define	PARM_SUCCESS		0xc005
#define	PARM_ASCONF_SUCCESS	PARM_SUCCESS
#define	PARM_ADAPT_LAYER_IND	0xc006


/* Lengths from SCTP spec */
#define	PARM_ADDR4_LEN		8
#define	PARM_ADDR6_LEN		20

/* Parameter header */
typedef struct sctp_parm_hdr {
	uint16_t	sph_type;
	uint16_t	sph_len;
} sctp_parm_hdr_t;

/*
 * The following extend sctp_parm_hdr_t
 * with cause-specfic content used to fill
 * CAUSE blocks in ABORT or ERROR chunks.
 * The overall size of the CAUSE block will
 * be sizeof (sctp_parm_hdr_t) plus the size
 * of the extended cause structure,
 */

/*
 * Invalid stream-identifier extended cause.
 * SCTP_ERR_BAD_SID
 */
typedef struct sctp_bsc {
	uint16_t	bsc_sid;
	uint16_t	bsc_pad; /* RESV = 0 */
} sctp_bsc_t;

/*
 * Missing parameter extended cause, currently
 * only one missing parameter is supported.
 * SCTP_ERR_MISSING_PARM
 */
typedef struct sctp_mpc {
	uint32_t	mpc_num;
	uint16_t	mpc_param;
	uint16_t	mpc_pad;
} sctp_mpc_t;

/* Error causes */
#define	SCTP_ERR_UNKNOWN		0
#define	SCTP_ERR_BAD_SID		1
#define	SCTP_ERR_MISSING_PARM		2
#define	SCTP_ERR_STALE_COOKIE		3
#define	SCTP_ERR_NO_RESOURCES		4
#define	SCTP_ERR_BAD_ADDR		5
#define	SCTP_ERR_UNREC_CHUNK		6
#define	SCTP_ERR_BAD_MANDPARM		7
#define	SCTP_ERR_UNREC_PARM		8
#define	SCTP_ERR_NO_USR_DATA		9
#define	SCTP_ERR_COOKIE_SHUT		10
#define	SCTP_ERR_RESTART_NEW_ADDRS	11
#define	SCTP_ERR_USER_ABORT		12
#define	SCTP_ERR_DELETE_LASTADDR	256
#define	SCTP_ERR_RESOURCE_SHORTAGE	257
#define	SCTP_ERR_DELETE_SRCADDR		258
#define	SCTP_ERR_AUTH_ERR		260

/*
 * Extensions
 */

/* Extended Chunk Types */
#define	CHUNK_ASCONF		0xc1
#define	CHUNK_ASCONF_ACK	0x80

/* Extension Error Causes */
#define	SCTP_ERR_DEL_LAST_ADDR	0x0100
#define	SCTP_ERR_RES_SHORTAGE	0x0101
#define	SCTP_ERR_DEL_SRC_ADDR	0x0102
#define	SCTP_ERR_ILLEGAL_ACK	0x0103
#define	SCTP_ERR_UNAUTHORIZED	0x0104

typedef struct sctp_addip4 {
	sctp_parm_hdr_t		sad4_addip_ph;
	uint32_t		asconf_req_cid;
	sctp_parm_hdr_t		sad4_addr4_ph;
	ipaddr_t		sad4_addr;
} sctp_addip4_t;

typedef struct sctp_addip6 {
	sctp_parm_hdr_t		sad6_addip_ph;
	uint32_t		asconf_req_cid;
	sctp_parm_hdr_t		sad6_addr6_ph;
	in6_addr_t		sad6_addr;
} sctp_addip6_t;

#ifdef __cplusplus
}
#endif

#endif	/* _NETINET_SCTP_H */