2005-08-10 07:14:34 +04:00
# ifndef _DCCP_H
# define _DCCP_H
/*
* net / dccp / dccp . h
*
* An implementation of the DCCP protocol
2005-08-20 07:23:43 +04:00
* Copyright ( c ) 2005 Arnaldo Carvalho de Melo < acme @ conectiva . com . br >
* Copyright ( c ) 2005 Ian McDonald < iam4 @ cs . waikato . ac . nz >
2005-08-10 07:14:34 +04:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
2005-08-14 03:35:39 +04:00
# include <linux/config.h>
2005-08-10 07:14:34 +04:00
# include <linux/dccp.h>
# include <net/snmp.h>
# include <net/sock.h>
# include <net/tcp.h>
2005-09-18 11:17:51 +04:00
# include "ackvec.h"
2005-08-10 07:14:34 +04:00
2005-08-14 03:35:39 +04:00
# ifdef CONFIG_IP_DCCP_DEBUG
2005-08-10 07:14:34 +04:00
extern int dccp_debug ;
# define dccp_pr_debug(format, a...) \
do { if ( dccp_debug ) \
printk ( KERN_DEBUG " %s: " format , __FUNCTION__ , # # a ) ; \
} while ( 0 )
2005-08-14 03:34:54 +04:00
# define dccp_pr_debug_cat(format, a...) do { if (dccp_debug) \
printk ( format , # # a ) ; } while ( 0 )
2005-08-10 07:14:34 +04:00
# else
# define dccp_pr_debug(format, a...)
# define dccp_pr_debug_cat(format, a...)
# endif
extern struct inet_hashinfo dccp_hashinfo ;
extern atomic_t dccp_orphan_count ;
extern int dccp_tw_count ;
extern void dccp_tw_deschedule ( struct inet_timewait_sock * tw ) ;
extern void dccp_time_wait ( struct sock * sk , int state , int timeo ) ;
/* FIXME: Right size this */
# define DCCP_MAX_OPT_LEN 128
# define DCCP_MAX_PACKET_HDR 32
# define MAX_DCCP_HEADER (DCCP_MAX_PACKET_HDR + DCCP_MAX_OPT_LEN + MAX_HEADER)
# define DCCP_TIMEWAIT_LEN (60 * HZ) / * how long to wait to destroy TIME-WAIT
* state , about 60 seconds */
/* draft-ietf-dccp-spec-11.txt initial RTO value */
# define DCCP_TIMEOUT_INIT ((unsigned)(3 * HZ))
/* Maximal interval between probes for local resources. */
# define DCCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ / 2U))
# define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */
/* is seq1 < seq2 ? */
2005-08-15 04:05:53 +04:00
static inline int before48 ( const u64 seq1 , const u64 seq2 )
2005-08-10 07:14:34 +04:00
{
2005-08-15 04:05:53 +04:00
return ( s64 ) ( ( seq1 < < 16 ) - ( seq2 < < 16 ) ) < 0 ;
2005-08-10 07:14:34 +04:00
}
/* is seq1 > seq2 ? */
2005-08-15 04:05:53 +04:00
static inline int after48 ( const u64 seq1 , const u64 seq2 )
2005-08-10 07:14:34 +04:00
{
2005-08-15 04:05:53 +04:00
return ( s64 ) ( ( seq2 < < 16 ) - ( seq1 < < 16 ) ) < 0 ;
2005-08-10 07:14:34 +04:00
}
/* is seq2 <= seq1 <= seq3 ? */
2005-08-15 04:05:53 +04:00
static inline int between48 ( const u64 seq1 , const u64 seq2 , const u64 seq3 )
2005-08-10 07:14:34 +04:00
{
return ( seq3 < < 16 ) - ( seq2 < < 16 ) > = ( seq1 < < 16 ) - ( seq2 < < 16 ) ;
}
static inline u64 max48 ( const u64 seq1 , const u64 seq2 )
{
return after48 ( seq1 , seq2 ) ? seq1 : seq2 ;
}
enum {
DCCP_MIB_NUM = 0 ,
DCCP_MIB_ACTIVEOPENS , /* ActiveOpens */
DCCP_MIB_ESTABRESETS , /* EstabResets */
DCCP_MIB_CURRESTAB , /* CurrEstab */
DCCP_MIB_OUTSEGS , /* OutSegs */
DCCP_MIB_OUTRSTS ,
DCCP_MIB_ABORTONTIMEOUT ,
DCCP_MIB_TIMEOUTS ,
DCCP_MIB_ABORTFAILED ,
DCCP_MIB_PASSIVEOPENS ,
DCCP_MIB_ATTEMPTFAILS ,
DCCP_MIB_OUTDATAGRAMS ,
DCCP_MIB_INERRS ,
DCCP_MIB_OPTMANDATORYERROR ,
DCCP_MIB_INVALIDOPT ,
__DCCP_MIB_MAX
} ;
# define DCCP_MIB_MAX __DCCP_MIB_MAX
struct dccp_mib {
unsigned long mibs [ DCCP_MIB_MAX ] ;
} __SNMP_MIB_ALIGN__ ;
DECLARE_SNMP_STAT ( struct dccp_mib , dccp_statistics ) ;
2005-08-14 03:34:54 +04:00
# define DCCP_INC_STATS(field) SNMP_INC_STATS(dccp_statistics, field)
# define DCCP_INC_STATS_BH(field) SNMP_INC_STATS_BH(dccp_statistics, field)
# define DCCP_INC_STATS_USER(field) SNMP_INC_STATS_USER(dccp_statistics, field)
# define DCCP_DEC_STATS(field) SNMP_DEC_STATS(dccp_statistics, field)
# define DCCP_ADD_STATS_BH(field, val) \
SNMP_ADD_STATS_BH ( dccp_statistics , field , val )
# define DCCP_ADD_STATS_USER(field, val) \
SNMP_ADD_STATS_USER ( dccp_statistics , field , val )
2005-08-10 07:14:34 +04:00
extern int dccp_retransmit_skb ( struct sock * sk , struct sk_buff * skb ) ;
extern void dccp_send_ack ( struct sock * sk ) ;
extern void dccp_send_delayed_ack ( struct sock * sk ) ;
2005-08-17 10:10:59 +04:00
extern void dccp_send_sync ( struct sock * sk , const u64 seq ,
const enum dccp_pkt_type pkt_type ) ;
2005-08-10 07:14:34 +04:00
2005-08-27 10:06:35 +04:00
extern int dccp_write_xmit ( struct sock * sk , struct sk_buff * skb , long * timeo ) ;
2005-08-29 09:15:54 +04:00
extern void dccp_write_space ( struct sock * sk ) ;
2005-08-10 07:30:56 +04:00
2005-08-10 07:14:34 +04:00
extern void dccp_init_xmit_timers ( struct sock * sk ) ;
static inline void dccp_clear_xmit_timers ( struct sock * sk )
{
inet_csk_clear_xmit_timers ( sk ) ;
}
extern unsigned int dccp_sync_mss ( struct sock * sk , u32 pmtu ) ;
extern const char * dccp_packet_name ( const int type ) ;
extern const char * dccp_state_name ( const int state ) ;
2006-03-21 08:58:56 +03:00
extern void dccp_set_state ( struct sock * sk , const int state ) ;
extern void dccp_done ( struct sock * sk ) ;
2005-08-10 07:14:34 +04:00
static inline void dccp_openreq_init ( struct request_sock * req ,
struct dccp_sock * dp ,
struct sk_buff * skb )
{
/*
* FIXME : fill in the other req fields from the DCCP options
* received
*/
inet_rsk ( req ) - > rmt_port = dccp_hdr ( skb ) - > dccph_sport ;
inet_rsk ( req ) - > acked = 0 ;
req - > rcv_wnd = 0 ;
}
extern int dccp_v4_conn_request ( struct sock * sk , struct sk_buff * skb ) ;
extern struct sock * dccp_create_openreq_child ( struct sock * sk ,
const struct request_sock * req ,
const struct sk_buff * skb ) ;
extern int dccp_v4_do_rcv ( struct sock * sk , struct sk_buff * skb ) ;
extern struct sock * dccp_v4_request_recv_sock ( struct sock * sk ,
struct sk_buff * skb ,
struct request_sock * req ,
struct dst_entry * dst ) ;
extern struct sock * dccp_check_req ( struct sock * sk , struct sk_buff * skb ,
struct request_sock * req ,
struct request_sock * * prev ) ;
extern int dccp_child_process ( struct sock * parent , struct sock * child ,
struct sk_buff * skb ) ;
extern int dccp_rcv_state_process ( struct sock * sk , struct sk_buff * skb ,
struct dccp_hdr * dh , unsigned len ) ;
extern int dccp_rcv_established ( struct sock * sk , struct sk_buff * skb ,
const struct dccp_hdr * dh , const unsigned len ) ;
2006-03-21 09:00:37 +03:00
extern int dccp_init_sock ( struct sock * sk , const __u8 ctl_sock_initialized ) ;
2006-03-21 08:23:15 +03:00
extern int dccp_destroy_sock ( struct sock * sk ) ;
2005-12-14 10:24:16 +03:00
2005-08-10 07:14:34 +04:00
extern void dccp_close ( struct sock * sk , long timeout ) ;
extern struct sk_buff * dccp_make_response ( struct sock * sk ,
struct dst_entry * dst ,
struct request_sock * req ) ;
extern int dccp_connect ( struct sock * sk ) ;
extern int dccp_disconnect ( struct sock * sk , int flags ) ;
2006-03-21 08:23:39 +03:00
extern void dccp_hash ( struct sock * sk ) ;
2005-12-14 10:24:16 +03:00
extern void dccp_unhash ( struct sock * sk ) ;
2005-08-10 07:14:34 +04:00
extern int dccp_getsockopt ( struct sock * sk , int level , int optname ,
2005-08-14 05:42:25 +04:00
char __user * optval , int __user * optlen ) ;
extern int dccp_setsockopt ( struct sock * sk , int level , int optname ,
char __user * optval , int optlen ) ;
2005-08-10 07:14:34 +04:00
extern int dccp_ioctl ( struct sock * sk , int cmd , unsigned long arg ) ;
2005-08-14 03:34:54 +04:00
extern int dccp_sendmsg ( struct kiocb * iocb , struct sock * sk ,
struct msghdr * msg , size_t size ) ;
2005-08-10 07:14:34 +04:00
extern int dccp_recvmsg ( struct kiocb * iocb , struct sock * sk ,
struct msghdr * msg , size_t len , int nonblock ,
int flags , int * addr_len ) ;
extern void dccp_shutdown ( struct sock * sk , int how ) ;
2005-12-14 10:24:16 +03:00
extern int inet_dccp_listen ( struct socket * sock , int backlog ) ;
extern unsigned int dccp_poll ( struct file * file , struct socket * sock ,
poll_table * wait ) ;
extern void dccp_v4_send_check ( struct sock * sk , int len ,
struct sk_buff * skb ) ;
extern int dccp_v4_connect ( struct sock * sk , struct sockaddr * uaddr ,
int addr_len ) ;
2005-08-10 07:14:34 +04:00
2005-08-10 07:15:35 +04:00
extern int dccp_v4_checksum ( const struct sk_buff * skb ,
2006-03-21 06:23:32 +03:00
const __be32 saddr , const __be32 daddr ) ;
2005-08-10 07:14:34 +04:00
2006-03-21 06:25:24 +03:00
extern int dccp_send_reset ( struct sock * sk , enum dccp_reset_codes code ) ;
2005-08-24 08:50:06 +04:00
extern void dccp_send_close ( struct sock * sk , const int active ) ;
2005-12-14 10:24:16 +03:00
extern int dccp_invalid_packet ( struct sk_buff * skb ) ;
static inline int dccp_bad_service_code ( const struct sock * sk ,
2006-03-21 06:23:32 +03:00
const __be32 service )
2005-12-14 10:24:16 +03:00
{
const struct dccp_sock * dp = dccp_sk ( sk ) ;
if ( dp - > dccps_service = = service )
return 0 ;
return ! dccp_list_has_service ( dp - > dccps_service_list , service ) ;
}
2005-08-10 07:14:34 +04:00
struct dccp_skb_cb {
2005-09-17 03:58:40 +04:00
__u8 dccpd_type : 4 ;
__u8 dccpd_ccval : 4 ;
__u8 dccpd_reset_code ;
__u16 dccpd_opt_len ;
2005-08-10 07:14:34 +04:00
__u64 dccpd_seq ;
__u64 dccpd_ack_seq ;
} ;
# define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0]))
static inline int dccp_non_data_packet ( const struct sk_buff * skb )
{
const __u8 type = DCCP_SKB_CB ( skb ) - > dccpd_type ;
return type = = DCCP_PKT_ACK | |
type = = DCCP_PKT_CLOSE | |
type = = DCCP_PKT_CLOSEREQ | |
type = = DCCP_PKT_RESET | |
type = = DCCP_PKT_SYNC | |
type = = DCCP_PKT_SYNCACK ;
}
static inline int dccp_packet_without_ack ( const struct sk_buff * skb )
{
const __u8 type = DCCP_SKB_CB ( skb ) - > dccpd_type ;
return type = = DCCP_PKT_DATA | | type = = DCCP_PKT_REQUEST ;
}
# define DCCP_MAX_SEQNO ((((u64)1) << 48) - 1)
# define DCCP_PKT_WITHOUT_ACK_SEQ (DCCP_MAX_SEQNO << 2)
static inline void dccp_set_seqno ( u64 * seqno , u64 value )
{
if ( value > DCCP_MAX_SEQNO )
value - = DCCP_MAX_SEQNO + 1 ;
* seqno = value ;
}
static inline u64 dccp_delta_seqno ( u64 seqno1 , u64 seqno2 )
{
return ( ( seqno2 < < 16 ) - ( seqno1 < < 16 ) ) > > 16 ;
}
static inline void dccp_inc_seqno ( u64 * seqno )
{
if ( + + * seqno > DCCP_MAX_SEQNO )
* seqno = 0 ;
}
static inline void dccp_hdr_set_seq ( struct dccp_hdr * dh , const u64 gss )
{
2005-08-14 03:34:54 +04:00
struct dccp_hdr_ext * dhx = ( struct dccp_hdr_ext * ) ( ( void * ) dh +
sizeof ( * dh ) ) ;
2006-03-21 06:23:32 +03:00
dh - > dccph_seq2 = 0 ;
dh - > dccph_seq = htons ( ( gss > > 32 ) & 0xfffff ) ;
2005-08-10 07:14:34 +04:00
dhx - > dccph_seq_low = htonl ( gss & 0xffffffff ) ;
}
2005-08-14 03:34:54 +04:00
static inline void dccp_hdr_set_ack ( struct dccp_hdr_ack_bits * dhack ,
const u64 gsr )
2005-08-10 07:14:34 +04:00
{
2006-03-21 06:23:32 +03:00
dhack - > dccph_reserved1 = 0 ;
dhack - > dccph_ack_nr_high = htons ( gsr > > 32 ) ;
2005-08-10 07:14:34 +04:00
dhack - > dccph_ack_nr_low = htonl ( gsr & 0xffffffff ) ;
}
static inline void dccp_update_gsr ( struct sock * sk , u64 seq )
{
struct dccp_sock * dp = dccp_sk ( sk ) ;
2005-08-21 12:36:45 +04:00
dp - > dccps_gsr = seq ;
dccp_set_seqno ( & dp - > dccps_swl ,
2005-08-14 03:34:54 +04:00
( dp - > dccps_gsr + 1 -
( dp - > dccps_options . dccpo_sequence_window / 4 ) ) ) ;
2005-08-10 07:14:34 +04:00
dccp_set_seqno ( & dp - > dccps_swh ,
2005-08-14 03:34:54 +04:00
( dp - > dccps_gsr +
( 3 * dp - > dccps_options . dccpo_sequence_window ) / 4 ) ) ;
2005-08-10 07:14:34 +04:00
}
static inline void dccp_update_gss ( struct sock * sk , u64 seq )
{
struct dccp_sock * dp = dccp_sk ( sk ) ;
2005-08-21 12:36:45 +04:00
dp - > dccps_awh = dp - > dccps_gss = seq ;
dccp_set_seqno ( & dp - > dccps_awl ,
2005-08-14 03:34:54 +04:00
( dp - > dccps_gss -
dp - > dccps_options . dccpo_sequence_window + 1 ) ) ;
2005-08-10 07:14:34 +04:00
}
2005-09-18 11:17:51 +04:00
static inline int dccp_ack_pending ( const struct sock * sk )
{
const struct dccp_sock * dp = dccp_sk ( sk ) ;
return dp - > dccps_timestamp_echo ! = 0 | |
# ifdef CONFIG_IP_DCCP_ACKVEC
( dp - > dccps_options . dccpo_send_ack_vector & &
dccp_ackvec_pending ( dp - > dccps_hc_rx_ackvec ) ) | |
# endif
inet_csk_ack_scheduled ( sk ) ;
}
2005-08-10 07:14:34 +04:00
2006-03-21 09:32:06 +03:00
extern int dccp_insert_options ( struct sock * sk , struct sk_buff * skb ) ;
extern int dccp_insert_option_elapsed_time ( struct sock * sk ,
2005-08-10 07:14:34 +04:00
struct sk_buff * skb ,
u32 elapsed_time ) ;
2006-03-21 09:32:06 +03:00
extern int dccp_insert_option_timestamp ( struct sock * sk ,
2005-08-24 08:51:36 +04:00
struct sk_buff * skb ) ;
2006-03-21 09:32:06 +03:00
extern int dccp_insert_option ( struct sock * sk , struct sk_buff * skb ,
2005-08-10 07:14:34 +04:00
unsigned char option ,
const void * value , unsigned char len ) ;
2005-09-09 09:38:35 +04:00
extern void dccp_timestamp ( const struct sock * sk , struct timeval * tv ) ;
2005-08-28 01:18:18 +04:00
static inline suseconds_t timeval_usecs ( const struct timeval * tv )
{
return tv - > tv_sec * USEC_PER_SEC + tv - > tv_usec ;
}
static inline suseconds_t timeval_delta ( const struct timeval * large ,
const struct timeval * small )
{
time_t secs = large - > tv_sec - small - > tv_sec ;
suseconds_t usecs = large - > tv_usec - small - > tv_usec ;
if ( usecs < 0 ) {
secs - - ;
usecs + = USEC_PER_SEC ;
}
return secs * USEC_PER_SEC + usecs ;
}
static inline void timeval_add_usecs ( struct timeval * tv ,
const suseconds_t usecs )
{
tv - > tv_usec + = usecs ;
while ( tv - > tv_usec > = USEC_PER_SEC ) {
tv - > tv_sec + + ;
tv - > tv_usec - = USEC_PER_SEC ;
}
}
static inline void timeval_sub_usecs ( struct timeval * tv ,
const suseconds_t usecs )
{
tv - > tv_usec - = usecs ;
while ( tv - > tv_usec < 0 ) {
tv - > tv_sec - - ;
tv - > tv_usec + = USEC_PER_SEC ;
}
}
2006-03-21 06:25:02 +03:00
# ifdef CONFIG_SYSCTL
extern int dccp_sysctl_init ( void ) ;
extern void dccp_sysctl_exit ( void ) ;
# else
static inline int dccp_sysctl_init ( void )
{
return 0 ;
}
static inline void dccp_sysctl_exit ( void )
{
}
# endif
2005-08-10 07:14:34 +04:00
# endif /* _DCCP_H */