Skip to content
Snippets Groups Projects
structs.h 64.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • /* SCTP kernel implementation
    
    Linus Torvalds's avatar
    Linus Torvalds committed
     * (C) Copyright IBM Corp. 2001, 2004
     * Copyright (c) 1999-2000 Cisco, Inc.
     * Copyright (c) 1999-2001 Motorola, Inc.
     * Copyright (c) 2001 Intel Corp.
     *
    
     * This file is part of the SCTP kernel implementation
    
    Linus Torvalds's avatar
    Linus Torvalds committed
     *
    
     * This SCTP implementation is free software;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
     * you can redistribute it and/or modify it under the terms of
     * the GNU General Public License as published by
     * the Free Software Foundation; either version 2, or (at your option)
     * any later version.
     *
    
     * This SCTP implementation is distributed in the hope that it
    
    Linus Torvalds's avatar
    Linus Torvalds committed
     * will be useful, but WITHOUT ANY WARRANTY; without even the implied
     *		   ************************
     * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     * See the GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with GNU CC; see the file COPYING.  If not, write to
     * the Free Software Foundation, 59 Temple Place - Suite 330,
     * Boston, MA 02111-1307, USA.
     *
     * Please send any bug reports or fixes you make to the
     * email addresses:
     *    lksctp developers <lksctp-developers@lists.sourceforge.net>
     *
     * Or submit a bug report through the following website:
     *    http://www.sf.net/projects/lksctp
     *
     * Written or modified by:
     *    Randall Stewart	    <randall@sctp.chicago.il.us>
     *    Ken Morneau	    <kmorneau@cisco.com>
     *    Qiaobing Xie	    <qxie1@email.mot.com>
     *    La Monte H.P. Yarroll <piggy@acm.org>
     *    Karl Knutson	    <karl@athena.chicago.il.us>
     *    Jon Grimm		    <jgrimm@us.ibm.com>
     *    Xingang Guo	    <xingang.guo@intel.com>
     *    Hui Huang		    <hui.huang@nokia.com>
     *    Sridhar Samudrala	    <sri@us.ibm.com>
     *    Daisy Chang	    <daisyc@us.ibm.com>
     *    Dajiang Zhang	    <dajiang.zhang@nokia.com>
     *    Ardelle Fan	    <ardelle.fan@intel.com>
     *    Ryan Layer	    <rmlayer@us.ibm.com>
     *    Anup Pemmaiah	    <pemmaiah@cc.usu.edu>
     *    Kevin Gao             <kevin.gao@intel.com>
     *
     * Any bugs reported given to us we will try to fix... any fixes shared will
     * be incorporated into the next SCTP release.
     */
    
    #ifndef __sctp_structs_h__
    #define __sctp_structs_h__
    
    #include <linux/time.h>		/* We get struct timespec.    */
    #include <linux/socket.h>	/* linux/in.h needs this!!    */
    #include <linux/in.h>		/* We get struct sockaddr_in. */
    #include <linux/in6.h>		/* We get struct in6_addr     */
    #include <linux/ipv6.h>
    #include <asm/param.h>		/* We get MAXHOSTNAMELEN.     */
    
    #include <linux/atomic.h>		/* This gets us atomic counters.  */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    #include <linux/skbuff.h>	/* We need sk_buff_head. */
    #include <linux/workqueue.h>	/* We need tq_struct.	 */
    #include <linux/sctp.h>		/* We need sctp* header structs.  */
    
    #include <net/sctp/auth.h>	/* We need auth specific structs */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    /* A convenience structure for handling sockaddr structures.
     * We should wean ourselves off this.
     */
    union sctp_addr {
    	struct sockaddr_in v4;
    	struct sockaddr_in6 v6;
    	struct sockaddr sa;
    };
    
    /* Forward declarations for data structures. */
    struct sctp_globals;
    struct sctp_endpoint;
    struct sctp_association;
    struct sctp_transport;
    struct sctp_packet;
    struct sctp_chunk;
    struct sctp_inq;
    struct sctp_outq;
    struct sctp_bind_addr;
    struct sctp_ulpq;
    struct sctp_ep_common;
    struct sctp_ssnmap;
    
    struct crypto_hash;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    #include <net/sctp/tsnmap.h>
    #include <net/sctp/ulpevent.h>
    #include <net/sctp/ulpqueue.h>
    
    /* Structures useful for managing bind/connect. */
    
    struct sctp_bind_bucket {
    	unsigned short	port;
    	unsigned short	fastreuse;
    
    	struct hlist_node	node;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	struct hlist_head	owner;
    };
    
    struct sctp_bind_hashbucket {
    	spinlock_t	lock;
    
    	struct hlist_head	chain;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    };
    
    /* Used for hashing all associations.  */
    struct sctp_hashbucket {
    	rwlock_t	lock;
    
    	struct hlist_head	chain;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    } __attribute__((__aligned__(8)));
    
    
    /* The SCTP globals structure. */
    extern struct sctp_globals {
    	/* RFC2960 Section 14. Suggested SCTP Protocol Parameter Values
    	 *
    	 * The following protocol parameters are RECOMMENDED:
    	 *
    	 * RTO.Initial		    - 3	 seconds
    	 * RTO.Min		    - 1	 second
    	 * RTO.Max		   -  60 seconds
    	 * RTO.Alpha		    - 1/8  (3 when converted to right shifts.)
    	 * RTO.Beta		    - 1/4  (2 when converted to right shifts.)
    	 */
    
    	unsigned int rto_initial;
    	unsigned int rto_min;
    	unsigned int rto_max;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/* Note: rto_alpha and rto_beta are really defined as inverse
    	 * powers of two to facilitate integer operations.
    	 */
    	int rto_alpha;
    	int rto_beta;
    
    	/* Max.Burst		    - 4 */
    	int max_burst;
    
    	/* Whether Cookie Preservative is enabled(1) or not(0) */
    	int cookie_preserve_enable;
    
    
    	/* Valid.Cookie.Life	    - 60  seconds  */
    
    
    	/* Delayed SACK timeout  200ms default*/
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	/* Association.Max.Retrans  - 10 attempts
    	 * Path.Max.Retrans	    - 5	 attempts (per destination address)
    	 * Max.Init.Retransmits	    - 8	 attempts
    	 */
    	int max_retrans_association;
    	int max_retrans_path;
    	int max_retrans_init;
    
    
    	/*
    	 * Policy for preforming sctp/socket accounting
    	 * 0   - do socket level accounting, all assocs share sk_sndbuf
    	 * 1   - do sctp accounting, each asoc may use sk_sndbuf bytes
    	 */
    	int sndbuf_policy;
    
    
    	/*
    	 * Policy for preforming sctp/socket accounting
    	 * 0   - do socket level accounting, all assocs share sk_rcvbuf
    	 * 1   - do sctp accounting, each asoc may use sk_rcvbuf bytes
    	 */
    	int rcvbuf_policy;
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	/* The following variables are implementation specific.	 */
    
    	/* Default initialization values to be applied to new associations. */
    	__u16 max_instreams;
    	__u16 max_outstreams;
    
    	/* This is a list of groups of functions for each address
    	 * family that we support.
    	 */
    	struct list_head address_families;
    
    	/* This is the hash of all endpoints. */
    	int ep_hashsize;
    	struct sctp_hashbucket *ep_hashtable;
    
    	/* This is the hash of all associations. */
    	int assoc_hashsize;
    	struct sctp_hashbucket *assoc_hashtable;
    
    	/* This is the sctp port control hash.	*/
    	int port_hashsize;
    	struct sctp_bind_hashbucket *port_hashtable;
    
    	/* This is the global local address list.
    
    	 * We actively maintain this complete list of addresses on
    	 * the system by catching address add/delete events.
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	 *
    	 * It is a list of sctp_sockaddr_entry.
    	 */
    	struct list_head local_addr_list;
    
    	int default_auto_asconf;
    	struct list_head addr_waitq;
    	struct timer_list addr_wq_timer;
    	struct list_head auto_asconf_splist;
    	spinlock_t addr_wq_lock;
    
    
    	/* Lock that protects the local_addr_list writers */
    	spinlock_t addr_list_lock;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	
    	/* Flag to indicate if addip is enabled. */
    	int addip_enable;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/* Flag to indicate if PR-SCTP is enabled. */
    	int prsctp_enable;
    
    
    	/* Flag to idicate if SCTP-AUTH is enabled */
    	int auth_enable;
    
    	/*
    	 * Policy to control SCTP IPv4 address scoping
    	 * 0   - Disable IPv4 address scoping
    	 * 1   - Enable IPv4 address scoping
    	 * 2   - Selectively allow only IPv4 private addresses
    	 * 3   - Selectively allow only IPv4 link local address
    	 */
    	int ipv4_scope_policy;
    
    
    	/* Flag to indicate whether computing and verifying checksum
    	 * is disabled. */
            int checksum_disable;
    
    
    	/* Threshold for rwnd update SACKS.  Receive buffer shifted this many
    	 * bits is an indicator of when to send and window update SACK.
    	 */
    	int rwnd_update_shift;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    } sctp_globals;
    
    #define sctp_rto_initial		(sctp_globals.rto_initial)
    #define sctp_rto_min			(sctp_globals.rto_min)
    #define sctp_rto_max			(sctp_globals.rto_max)
    #define sctp_rto_alpha			(sctp_globals.rto_alpha)
    #define sctp_rto_beta			(sctp_globals.rto_beta)
    #define sctp_max_burst			(sctp_globals.max_burst)
    #define sctp_valid_cookie_life		(sctp_globals.valid_cookie_life)
    #define sctp_cookie_preserve_enable	(sctp_globals.cookie_preserve_enable)
    #define sctp_max_retrans_association	(sctp_globals.max_retrans_association)
    
    #define sctp_sndbuf_policy	 	(sctp_globals.sndbuf_policy)
    
    #define sctp_rcvbuf_policy	 	(sctp_globals.rcvbuf_policy)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    #define sctp_max_retrans_path		(sctp_globals.max_retrans_path)
    #define sctp_max_retrans_init		(sctp_globals.max_retrans_init)
    
    #define sctp_sack_timeout		(sctp_globals.sack_timeout)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    #define sctp_hb_interval		(sctp_globals.hb_interval)
    #define sctp_max_instreams		(sctp_globals.max_instreams)
    #define sctp_max_outstreams		(sctp_globals.max_outstreams)
    #define sctp_address_families		(sctp_globals.address_families)
    #define sctp_ep_hashsize		(sctp_globals.ep_hashsize)
    #define sctp_ep_hashtable		(sctp_globals.ep_hashtable)
    #define sctp_assoc_hashsize		(sctp_globals.assoc_hashsize)
    #define sctp_assoc_hashtable		(sctp_globals.assoc_hashtable)
    #define sctp_port_hashsize		(sctp_globals.port_hashsize)
    #define sctp_port_hashtable		(sctp_globals.port_hashtable)
    #define sctp_local_addr_list		(sctp_globals.local_addr_list)
    
    #define sctp_local_addr_lock		(sctp_globals.addr_list_lock)
    
    #define sctp_auto_asconf_splist		(sctp_globals.auto_asconf_splist)
    #define sctp_addr_waitq			(sctp_globals.addr_waitq)
    #define sctp_addr_wq_timer		(sctp_globals.addr_wq_timer)
    #define sctp_addr_wq_lock		(sctp_globals.addr_wq_lock)
    #define sctp_default_auto_asconf	(sctp_globals.default_auto_asconf)
    
    #define sctp_scope_policy		(sctp_globals.ipv4_scope_policy)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    #define sctp_addip_enable		(sctp_globals.addip_enable)
    
    #define sctp_addip_noauth		(sctp_globals.addip_noauth_enable)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    #define sctp_prsctp_enable		(sctp_globals.prsctp_enable)
    
    #define sctp_auth_enable		(sctp_globals.auth_enable)
    
    #define sctp_checksum_disable		(sctp_globals.checksum_disable)
    
    #define sctp_rwnd_upd_shift		(sctp_globals.rwnd_update_shift)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    /* SCTP Socket type: UDP or TCP style. */
    typedef enum {
    	SCTP_SOCKET_UDP = 0,
    	SCTP_SOCKET_UDP_HIGH_BANDWIDTH,
    	SCTP_SOCKET_TCP
    } sctp_socket_type_t;
    
    /* Per socket SCTP information. */
    struct sctp_sock {
    	/* inet_sock has to be the first member of sctp_sock */
    	struct inet_sock inet;
    	/* What kind of a socket is this? */
    	sctp_socket_type_t type;
    
    	/* PF_ family specific functions.  */
    	struct sctp_pf *pf;
    
    	/* Access to HMAC transform. */
    
    	struct crypto_hash *hmac;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/* What is our base endpointer? */
    	struct sctp_endpoint *ep;
    
    	struct sctp_bind_bucket *bind_hash;
    	/* Various Socket Options.  */
    	__u16 default_stream;
    	__u32 default_ppid;
    	__u16 default_flags;
    	__u32 default_context;
    	__u32 default_timetolive;
    
    	__u32 default_rcv_context;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
    	 * the destination address every heartbeat interval. This value
    	 * will be inherited by all new associations.
    	 */
    	__u32 hbinterval;
    
    	/* This is the max_retrans value for new associations. */
    	__u16 pathmaxrxt;
    
    	/* The initial Path MTU to use for new associations. */
    	__u32 pathmtu;
    
    	/* The default SACK delay timeout for new associations. */
    	__u32 sackdelay;
    
    	/* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	struct sctp_initmsg initmsg;
    	struct sctp_rtoinfo rtoinfo;
    	struct sctp_paddrparams paddrparam;
    	struct sctp_event_subscribe subscribe;
    	struct sctp_assocparams assocparams;
    	int user_frag;
    	__u32 autoclose;
    	__u8 nodelay;
    	__u8 disable_fragments;
    	__u8 v4mapped;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	/* Receive to here while partial delivery is in effect. */
    	struct sk_buff_head pd_lobby;
    
    	struct list_head auto_asconf_list;
    	int do_auto_asconf;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    };
    
    static inline struct sctp_sock *sctp_sk(const struct sock *sk)
    {
           return (struct sctp_sock *)sk;
    }
    
    static inline struct sock *sctp_opt2sk(const struct sctp_sock *sp)
    {
           return (struct sock *)sp;
    }
    
    
    #if IS_ENABLED(CONFIG_IPV6)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    struct sctp6_sock {
           struct sctp_sock  sctp;
           struct ipv6_pinfo inet6;
    };
    #endif /* CONFIG_IPV6 */
    
    
    /* This is our APPLICATION-SPECIFIC state cookie.
     * THIS IS NOT DICTATED BY THE SPECIFICATION.
     */
    /* These are the parts of an association which we send in the cookie.
     * Most of these are straight out of:
     * RFC2960 12.2 Parameters necessary per association (i.e. the TCB)
     *
     */
    
    struct sctp_cookie {
    
    	/* My	       : Tag expected in every inbound packet and sent
    	 * Verification: in the INIT or INIT ACK chunk.
    	 * Tag	       :
    	 */
    	__u32 my_vtag;
    
    	/* Peer's      : Tag expected in every outbound packet except
    	 * Verification: in the INIT chunk.
    	 * Tag	       :
    	 */
    	__u32 peer_vtag;
    
    	/* The rest of these are not from the spec, but really need to
    	 * be in the cookie.
    	 */
    
    	/* My Tie Tag  : Assist in discovering a restarting association. */
    	__u32 my_ttag;
    
    	/* Peer's Tie Tag: Assist in discovering a restarting association. */
    	__u32 peer_ttag;
    
    	/* When does this cookie expire? */
    	struct timeval expiration;
    
    	/* Number of inbound/outbound streams which are set
    	 * and negotiated during the INIT process.
    	 */
    	__u16 sinit_num_ostreams;
    	__u16 sinit_max_instreams;
    
    	/* This is the first sequence number I used.  */
    	__u32 initial_tsn;
    
    	/* This holds the originating address of the INIT packet.  */
    	union sctp_addr peer_addr;
    
    	/* IG Section 2.35.3 
    	 * Include the source port of the INIT-ACK
    	 */
    	__u16		my_port;
    
    	__u8 prsctp_capable;
    
    	/* Padding for future use */
    	__u8 padding;  		
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	__u8 auth_random[sizeof(sctp_paramhdr_t) + SCTP_AUTH_RANDOM_LENGTH];
    
    	__u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2];
    
    	__u8 auth_chunks[sizeof(sctp_paramhdr_t) + SCTP_AUTH_MAX_CHUNKS];
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/* This is a shim for my peer's INIT packet, followed by
    	 * a copy of the raw address list of the association.
    	 * The length of the raw address list is saved in the
    	 * raw_addr_list_len field, which will be used at the time when
    	 * the association TCB is re-constructed from the cookie.
    	 */
    	__u32 raw_addr_list_len;
    	struct sctp_init_chunk peer_init[0];
    };
    
    
    /* The format of our cookie that we send to our peer. */
    struct sctp_signed_cookie {
    	__u8 signature[SCTP_SECRET_SIZE];
    
    	__u32 __pad;		/* force sctp_cookie alignment to 64 bits */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	struct sctp_cookie c;
    
    } __packed;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    /* This is another convenience type to allocate memory for address
     * params for the maximum size and pass such structures around
     * internally.
     */
    union sctp_addr_param {
    
    	struct sctp_paramhdr p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	struct sctp_ipv4addr_param v4;
    	struct sctp_ipv6addr_param v6;
    };
    
    /* A convenience type to allow walking through the various
     * parameters and avoid casting all over the place.
     */
    union sctp_params {
    	void *v;
    	struct sctp_paramhdr *p;
    	struct sctp_cookie_preserve_param *life;
    	struct sctp_hostname_param *dns;
    	struct sctp_cookie_param *cookie;
    	struct sctp_supported_addrs_param *sat;
    	struct sctp_ipv4addr_param *v4;
    	struct sctp_ipv6addr_param *v6;
    	union sctp_addr_param *addr;
    
    	struct sctp_adaptation_ind_param *aind;
    
    	struct sctp_supported_ext_param *ext;
    
    	struct sctp_random_param *random;
    	struct sctp_chunks_param *chunks;
    	struct sctp_hmac_algo_param *hmac_algo;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    };
    
    /* RFC 2960.  Section 3.3.5 Heartbeat.
     *    Heartbeat Information: variable length
     *    The Sender-specific Heartbeat Info field should normally include
     *    information about the sender's current time when this HEARTBEAT
     *    chunk is sent and the destination transport address to which this
     *    HEARTBEAT is sent (see Section 8.3).
     */
    typedef struct sctp_sender_hb_info {
    	struct sctp_paramhdr param_hdr;
    	union sctp_addr daddr;
    	unsigned long sent_at;
    
    } __packed sctp_sender_hb_info_t;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    /*
     *  RFC 2960 1.3.2 Sequenced Delivery within Streams
     *
     *  The term "stream" is used in SCTP to refer to a sequence of user
     *  messages that are to be delivered to the upper-layer protocol in
     *  order with respect to other messages within the same stream.  This is
     *  in contrast to its usage in TCP, where it refers to a sequence of
     *  bytes (in this document a byte is assumed to be eight bits).
     *  ...
     *
     *  This is the structure we use to track both our outbound and inbound
     *  SSN, or Stream Sequence Numbers.
     */
    
    struct sctp_stream {
    	__u16 *ssn;
    	unsigned int len;
    };
    
    struct sctp_ssnmap {
    	struct sctp_stream in;
    	struct sctp_stream out;
    	int malloced;
    };
    
    
    struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
    
    				    gfp_t gfp);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    void sctp_ssnmap_free(struct sctp_ssnmap *map);
    void sctp_ssnmap_clear(struct sctp_ssnmap *map);
    
    /* What is the current SSN number for this stream? */
    static inline __u16 sctp_ssn_peek(struct sctp_stream *stream, __u16 id)
    {
    	return stream->ssn[id];
    }
    
    /* Return the next SSN number for this stream.	*/
    static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id)
    {
    	return stream->ssn[id]++;
    }
    
    /* Skip over this ssn and all below. */
    static inline void sctp_ssn_skip(struct sctp_stream *stream, __u16 id, 
    				 __u16 ssn)
    {
    	stream->ssn[id] = ssn+1;
    }
                  
    /*
     * Pointers to address related SCTP functions.
     * (i.e. things that depend on the address family.)
     */
    struct sctp_af {
    	int		(*sctp_xmit)	(struct sk_buff *skb,
    
    					 struct sctp_transport *);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	int		(*setsockopt)	(struct sock *sk,
    					 int level,
    					 int optname,
    					 char __user *optval,
    
    					 unsigned int optlen);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	int		(*getsockopt)	(struct sock *sk,
    					 int level,
    					 int optname,
    					 char __user *optval,
    					 int __user *optlen);
    
    	int		(*compat_setsockopt)	(struct sock *sk,
    					 int level,
    					 int optname,
    					 char __user *optval,
    
    					 unsigned int optlen);
    
    	int		(*compat_getsockopt)	(struct sock *sk,
    					 int level,
    					 int optname,
    					 char __user *optval,
    					 int __user *optlen);
    
    	void		(*get_dst)	(struct sctp_transport *t,
    
    					 union sctp_addr *saddr,
    					 struct flowi *fl,
    					 struct sock *sk);
    
    	void		(*get_saddr)	(struct sctp_sock *sk,
    
    					 struct sctp_transport *t,
    					 struct flowi *fl);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	void		(*copy_addrlist) (struct list_head *,
    					  struct net_device *);
    	int		(*cmp_addr)	(const union sctp_addr *addr1,
    					 const union sctp_addr *addr2);
    	void		(*addr_copy)	(union sctp_addr *dst,
    					 union sctp_addr *src);
    	void		(*from_skb)	(union sctp_addr *,
    					 struct sk_buff *skb,
    					 int saddr);
    	void		(*from_sk)	(union sctp_addr *,
    					 struct sock *sk);
    	void		(*to_sk_saddr)	(union sctp_addr *,
    					 struct sock *sk);
    	void		(*to_sk_daddr)	(union sctp_addr *,
    					 struct sock *sk);
    	void		(*from_addr_param) (union sctp_addr *,
    					    union sctp_addr_param *,
    
    					    __be16 port, int iif);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	int		(*to_addr_param) (const union sctp_addr *,
    					  union sctp_addr_param *); 
    	int		(*addr_valid)	(union sctp_addr *,
    
    					 struct sctp_sock *,
    					 const struct sk_buff *);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	sctp_scope_t	(*scope) (union sctp_addr *);
    
    	void		(*inaddr_any)	(union sctp_addr *, __be16);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	int		(*is_any)	(const union sctp_addr *);
    	int		(*available)	(union sctp_addr *,
    					 struct sctp_sock *);
    	int		(*skb_iif)	(const struct sk_buff *sk);
    	int		(*is_ce)	(const struct sk_buff *sk);
    	void		(*seq_dump_addr)(struct seq_file *seq,
    					 union sctp_addr *addr);
    
    	void		(*ecn_capable)(struct sock *sk);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	__u16		net_header_len;
    	int		sockaddr_len;
    	sa_family_t	sa_family;
    	struct list_head list;
    };
    
    struct sctp_af *sctp_get_af_specific(sa_family_t);
    int sctp_register_af(struct sctp_af *);
    
    /* Protocol family functions. */
    struct sctp_pf {
    	void (*event_msgname)(struct sctp_ulpevent *, char *, int *);
    	void (*skb_msgname)  (struct sk_buff *, char *, int *);
    	int  (*af_supported) (sa_family_t, struct sctp_sock *);
    	int  (*cmp_addr) (const union sctp_addr *,
    			  const union sctp_addr *,
    			  struct sctp_sock *);
    	int  (*bind_verify) (struct sctp_sock *, union sctp_addr *);
    	int  (*send_verify) (struct sctp_sock *, union sctp_addr *);
    
    	int  (*supported_addrs)(const struct sctp_sock *, __be16 *);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	struct sock *(*create_accept_sk) (struct sock *sk,
    					  struct sctp_association *asoc);
    	void (*addr_v4map) (struct sctp_sock *, union sctp_addr *);
    	struct sctp_af *af;
    };
    
    
    /* Structure to track chunk fragments that have been acked, but peer
     * fragments of the same message have not.
     */
    struct sctp_datamsg {
    	/* Chunks waiting to be submitted to lower layer. */
    	struct list_head chunks;
    	/* Reference counting. */
    	atomic_t refcnt;
    	/* When is this message no longer interesting to the peer? */
    	unsigned long expires_at;
    	/* Did the messenge fail to send? */
    	int send_error;
    
    	u8 send_failed:1,
    	   can_abandon:1,   /* can chunks from this message can be abandoned. */
    	   can_delay;	    /* should this message be Nagle delayed */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    };
    
    struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *,
    					    struct sctp_sndrcvinfo *,
    					    struct msghdr *, int len);
    
    void sctp_datamsg_free(struct sctp_datamsg *);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    void sctp_datamsg_put(struct sctp_datamsg *);
    void sctp_chunk_fail(struct sctp_chunk *, int error);
    int sctp_chunk_abandoned(struct sctp_chunk *);
    
    /* RFC2960 1.4 Key Terms
     *
     * o Chunk: A unit of information within an SCTP packet, consisting of
     * a chunk header and chunk-specific content.
     *
     * As a matter of convenience, we remember the SCTP common header for
     * each chunk as well as a few other header pointers...
     */
    struct sctp_chunk {
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	atomic_t refcnt;
    
    	/* This is our link to the per-transport transmitted list.  */
    	struct list_head transmitted_list;
    
    	/* This field is used by chunks that hold fragmented data.
    	 * For the first fragment this is the list that holds the rest of
    	 * fragments. For the remaining fragments, this is the link to the
    	 * frag_list maintained in the first fragment.
    	 */
    	struct list_head frag_list;
    
    	/* This points to the sk_buff containing the actual data.  */
    	struct sk_buff *skb;
    
    	/* These are the SCTP headers by reverse order in a packet.
    	 * Note that some of these may happen more than once.  In that
    	 * case, we point at the "current" one, whatever that means
    	 * for that level of header.
    	 */
    
    	/* We point this at the FIRST TLV parameter to chunk_hdr.  */
    	union sctp_params param_hdr;
    	union {
    		__u8 *v;
    		struct sctp_datahdr *data_hdr;
    		struct sctp_inithdr *init_hdr;
    		struct sctp_sackhdr *sack_hdr;
    		struct sctp_heartbeathdr *hb_hdr;
    		struct sctp_sender_hb_info *hbs_hdr;
    		struct sctp_shutdownhdr *shutdown_hdr;
    		struct sctp_signed_cookie *cookie_hdr;
    		struct sctp_ecnehdr *ecne_hdr;
    		struct sctp_cwrhdr *ecn_cwr_hdr;
    		struct sctp_errhdr *err_hdr;
    		struct sctp_addiphdr *addip_hdr;
    		struct sctp_fwdtsn_hdr *fwdtsn_hdr;
    
    		struct sctp_authhdr *auth_hdr;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	} subh;
    
    	__u8 *chunk_end;
    
    	struct sctp_chunkhdr *chunk_hdr;
    	struct sctphdr *sctp_hdr;
    
    	/* This needs to be recoverable for SCTP_SEND_FAILED events. */
    	struct sctp_sndrcvinfo sinfo;
    
    	/* Which association does this belong to?  */
    	struct sctp_association *asoc;
    
    	/* What endpoint received this chunk? */
    	struct sctp_ep_common *rcvr;
    
    	/* We fill this in if we are calculating RTT. */
    	unsigned long sent_at;
    
    	/* What is the origin IP address for this chunk?  */
    	union sctp_addr source;
    	/* Destination address for this chunk. */
    	union sctp_addr dest;
    
    	/* For outbound message, track all fragments for SEND_FAILED. */
    	struct sctp_datamsg *msg;
    
    	/* For an inbound chunk, this tells us where it came from.
    	 * For an outbound chunk, it tells us where we'd like it to
    	 * go.	It is NULL if we have no preference.
    	 */
    	struct sctp_transport *transport;
    
    
    	/* SCTP-AUTH:  For the special case inbound processing of COOKIE-ECHO
    	 * we need save a pointer to the AUTH chunk, since the SCTP-AUTH
    	 * spec violates the principle premis that all chunks are processed
    	 * in order.
    	 */
    	struct sk_buff *auth_chunk;
    
    
    #define SCTP_CAN_FRTX 0x0
    #define SCTP_NEED_FRTX 0x1
    #define SCTP_DONT_FRTX 0x2
    	__u16	rtt_in_progress:1,	/* This chunk used for RTT calc? */
    		has_tsn:1,		/* Does this chunk have a TSN yet? */
    		has_ssn:1,		/* Does this chunk have a SSN yet? */
    		singleton:1,		/* Only chunk in the packet? */
    		end_of_packet:1,	/* Last chunk in the packet? */
    		ecn_ce_done:1,		/* Have we processed the ECN CE bit? */
    		pdiscard:1,		/* Discard the whole packet now? */
    		tsn_gap_acked:1,	/* Is this chunk acked by a GAP ACK? */
    		data_accepted:1,	/* At least 1 chunk accepted */
    		auth:1,			/* IN: was auth'ed | OUT: needs auth */
    		has_asconf:1,		/* IN: have seen an asconf before */
    		tsn_missing_report:2,	/* Data chunk missing counter. */
    		fast_retransmit:2;	/* Is this chunk fast retransmitted? */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    };
    
    void sctp_chunk_hold(struct sctp_chunk *);
    void sctp_chunk_put(struct sctp_chunk *);
    int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
    			  struct iovec *data);
    void sctp_chunk_free(struct sctp_chunk *);
    void  *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
    
    void  *sctp_addto_chunk_fixed(struct sctp_chunk *, int len, const void *data);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    struct sctp_chunk *sctp_chunkify(struct sk_buff *,
    				 const struct sctp_association *,
    				 struct sock *);
    void sctp_init_addrs(struct sctp_chunk *, union sctp_addr *,
    		     union sctp_addr *);
    const union sctp_addr *sctp_source(const struct sctp_chunk *chunk);
    
    
    enum {
    	SCTP_ADDR_NEW,		/* new address added to assoc/ep */
    	SCTP_ADDR_SRC,		/* address can be used as source */
    	SCTP_ADDR_DEL,		/* address about to be deleted */
    };
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    /* This is a structure for holding either an IPv6 or an IPv4 address.  */
    struct sctp_sockaddr_entry {
    	struct list_head list;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	union sctp_addr a;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    };
    
    
    #define SCTP_ADDRESS_TICK_DELAY	500
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *);
    
    /* This structure holds lists of chunks as we are assembling for
     * transmission.
     */
    struct sctp_packet {
    	/* These are the SCTP header values (host order) for the packet. */
    	__u16 source_port;
    	__u16 destination_port;
    	__u32 vtag;
    
    	/* This contains the payload chunks.  */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/* This is the overhead of the sctp and ip headers. */
    	size_t overhead;
    	/* This is the total size of all chunks INCLUDING padding.  */
    	size_t size;
    
    	/* The packet is destined for this transport address.
    	 * The function we finally use to pass down to the next lower
    	 * layer lives in the transport structure.
    	 */
    	struct sctp_transport *transport;
    
    
    	/* pointer to the auth chunk for this packet */
    	struct sctp_chunk *auth;
    
    
    	u8  has_cookie_echo:1,	/* This packet contains a COOKIE-ECHO chunk. */
    	    has_sack:1,		/* This packet contains a SACK chunk. */
    	    has_auth:1,		/* This packet contains an AUTH chunk */
    	    has_data:1,		/* This packet contains at least 1 DATA chunk */
    	    ipfragok:1,		/* So let ip fragment this packet */
    	    malloced:1;		/* Is it malloced? */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    };
    
    struct sctp_packet *sctp_packet_init(struct sctp_packet *,
    				     struct sctp_transport *,
    				     __u16 sport, __u16 dport);
    struct sctp_packet *sctp_packet_config(struct sctp_packet *, __u32 vtag, int);
    sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *,
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *,
                                         struct sctp_chunk *);
    int sctp_packet_transmit(struct sctp_packet *);
    void sctp_packet_free(struct sctp_packet *);
    
    static inline int sctp_packet_empty(struct sctp_packet *packet)
    {
    
    	return packet->size == packet->overhead;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    /* This represents a remote transport address.
     * For local transport addresses, we just use union sctp_addr.
     *
     * RFC2960 Section 1.4 Key Terms
     *
     *   o	Transport address:  A Transport Address is traditionally defined
     *	by Network Layer address, Transport Layer protocol and Transport
     *	Layer port number.  In the case of SCTP running over IP, a
     *	transport address is defined by the combination of an IP address
     *	and an SCTP port number (where SCTP is the Transport protocol).
     *
     * RFC2960 Section 7.1 SCTP Differences from TCP Congestion control
     *
     *   o	The sender keeps a separate congestion control parameter set for
     *	each of the destination addresses it can send to (not each
     *	source-destination pair but for each destination).  The parameters
     *	should decay if the address is not used for a long enough time
     *	period.
     *
     */
    struct sctp_transport {
    	/* A list of transports. */
    	struct list_head transports;
    
    	/* Reference counting. */
    	atomic_t refcnt;
    
    		/* RTO-Pending : A flag used to track if one of the DATA
    		 *		chunks sent to this address is currently being
    		 *		used to compute a RTT. If this flag is 0,
    		 *		the next DATA chunk sent to this destination
    		 *		should be used to compute a RTT and this flag
    		 *		should be set. Every time the RTT
    		 *		calculation completes (i.e. the DATA chunk
    		 *		is SACK'd) clear this flag.
    		 */
    		 rto_pending:1,
    
    		/*
    		 * hb_sent : a flag that signals that we have a pending
    		 * heartbeat.
    		 */
    		hb_sent:1,
    
    		/* Is the Path MTU update pending on this tranport */
    		pmtu_pending:1,
    
    		/* Is this structure kfree()able? */
    		malloced:1;
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/* This is the peer's IP address and port. */
    	union sctp_addr ipaddr;
    
    	/* These are the functions we call to handle LLP stuff.	 */
    	struct sctp_af *af_specific;
    
    	/* Which association do we belong to?  */
    	struct sctp_association *asoc;
    
    	/* RFC2960
    	 *
    	 * 12.3 Per Transport Address Data
    	 *
    	 * For each destination transport address in the peer's
    	 * address list derived from the INIT or INIT ACK chunk, a
    	 * number of data elements needs to be maintained including:
    	 */
    	/* RTO	       : The current retransmission timeout value.  */
    
    
    	__u32 rtt;		/* This is the most recent RTT.	 */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/* RTTVAR      : The current RTT variation.  */
    	__u32 rttvar;
    
    	/* SRTT	       : The current smoothed round trip time.	*/
    	__u32 srtt;
    
    	/*
    	 * These are the congestion stats.
    	 */
    	/* cwnd	       : The current congestion window.	 */
    	__u32 cwnd;		  /* This is the actual cwnd.  */
    
    	/* ssthresh    : The current slow start threshold value.  */
    	__u32 ssthresh;
    
    	/* partial     : The tracking method for increase of cwnd when in
    	 * bytes acked : congestion avoidance mode (see Section 6.2.2)
    	 */
    	__u32 partial_bytes_acked;
    
    	/* Data that has been sent, but not acknowledged. */
    	__u32 flight_size;
    
    
    	__u32 burst_limited;	/* Holds old cwnd when max.burst is applied */
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	/* Destination */
    	struct dst_entry *dst;
    	/* Source address. */
    	union sctp_addr saddr;
    
    	/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
    	 * the destination address every heartbeat interval.
    	 */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/* When was the last time (in jiffies) that we heard from this
    	 * transport?  We use this to pick new active and retran paths.
    	 */
    	unsigned long last_time_heard;
    
    	/* Last time(in jiffies) when cwnd is reduced due to the congestion
    	 * indication based on ECNE chunk.
    	 */
    	unsigned long last_time_ecne_reduced;
    
    
    	/* This is the max_retrans value for the transport and will
    	 * be initialized from the assocs value.  This can be changed
    	 * using SCTP_SET_PEER_ADDR_PARAMS socket option.
    	 */
    	__u16 pathmaxrxt;
    
    	/* PMTU	      : The current known path MTU.  */
    	__u32 pathmtu;
    
    
    	/* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */
    
    	/* The number of times INIT has been sent on this transport. */
    	int init_sent_count;
    
    	/* state       : The current state of this destination,
    
    	 *             : i.e. SCTP_ACTIVE, SCTP_INACTIVE, SCTP_UNKNOWN.