2005-04-17 02:20:36 +04:00
/*
* INET An implementation of the TCP / IP protocol suite for the LINUX
* operating system . INET is implemented using the BSD Socket
* interface as the means of communication with the user level .
*
* Definitions for the UDP module .
*
* Version : @ ( # ) udp . h 1.0 .2 05 / 07 / 93
*
2005-05-06 03:16:16 +04:00
* Authors : Ross Biro
2005-04-17 02:20:36 +04:00
* Fred N . van Kempen , < waltje @ uWalt . NL . Mugnet . ORG >
*
* Fixes :
* Alan Cox : Turned on udp checksums . I don ' t want to
* chase ' memory corruption ' bugs that aren ' t !
*
* This program is free software ; 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 of the License , or ( at your option ) any later version .
*/
# ifndef _UDP_H
# define _UDP_H
# include <linux/list.h>
2011-11-24 05:12:59 +04:00
# include <linux/bug.h>
2005-12-27 07:43:12 +03:00
# include <net/inet_sock.h>
2005-04-17 02:20:36 +04:00
# include <net/sock.h>
# include <net/snmp.h>
2006-11-27 22:10:57 +03:00
# include <net/ip.h>
# include <linux/ipv6.h>
2005-04-17 02:20:36 +04:00
# include <linux/seq_file.h>
2006-10-20 01:23:57 +04:00
# include <linux/poll.h>
2005-04-17 02:20:36 +04:00
2006-11-27 22:10:57 +03:00
/**
* struct udp_skb_cb - UDP ( - Lite ) private variables
*
* @ header : private variables used by IPv4 / IPv6
* @ cscov : checksum coverage length ( UDP - Lite only )
* @ partial_cov : if set indicates partial csum coverage
*/
struct udp_skb_cb {
union {
struct inet_skb_parm h4 ;
2011-12-10 13:48:31 +04:00
# if IS_ENABLED(CONFIG_IPV6)
2006-11-27 22:10:57 +03:00
struct inet6_skb_parm h6 ;
# endif
} header ;
__u16 cscov ;
__u8 partial_cov ;
} ;
# define UDP_SKB_CB(__skb) ((struct udp_skb_cb *)((__skb)->cb))
2005-04-17 02:20:36 +04:00
2009-11-08 13:17:05 +03:00
/**
* struct udp_hslot - UDP hash slot
*
* @ head : head of list of sockets
* @ count : number of sockets in ' head ' list
* @ lock : spinlock protecting changes to head / count
*/
2008-10-29 11:41:45 +03:00
struct udp_hslot {
2008-11-17 06:39:21 +03:00
struct hlist_nulls_head head ;
2009-11-08 13:17:05 +03:00
int count ;
2008-10-29 11:41:45 +03:00
spinlock_t lock ;
} __attribute__ ( ( aligned ( 2 * sizeof ( long ) ) ) ) ;
2009-10-07 04:37:59 +04:00
2009-11-08 13:17:58 +03:00
/**
* struct udp_table - UDP table
*
* @ hash : hash table , sockets are hashed on ( local port )
* @ hash2 : hash table , sockets are hashed on ( local port , local address )
* @ mask : number of slots in hash tables , minus 1
* @ log : log2 ( number of slots in hash table )
*/
2008-10-29 11:41:45 +03:00
struct udp_table {
2009-10-07 04:37:59 +04:00
struct udp_hslot * hash ;
2009-11-08 13:17:58 +03:00
struct udp_hslot * hash2 ;
unsigned int mask ;
unsigned int log ;
2008-10-29 11:41:45 +03:00
} ;
extern struct udp_table udp_table ;
2013-09-23 22:33:36 +04:00
void udp_table_init ( struct udp_table * , const char * ) ;
2009-10-07 04:37:59 +04:00
static inline struct udp_hslot * udp_hashslot ( struct udp_table * table ,
2012-04-15 09:58:06 +04:00
struct net * net , unsigned int num )
2009-10-07 04:37:59 +04:00
{
return & table - > hash [ udp_hashfn ( net , num , table - > mask ) ] ;
}
2009-11-08 13:17:58 +03:00
/*
* For secondary hash , net_hash_mix ( ) is performed before calling
* udp_hashslot2 ( ) , this explains difference with udp_hashslot ( )
*/
static inline struct udp_hslot * udp_hashslot2 ( struct udp_table * table ,
unsigned int hash )
{
return & table - > hash2 [ hash & table - > mask ] ;
}
2005-04-17 02:20:36 +04:00
/* Note: this must match 'valbool' in sock_setsockopt */
# define UDP_CSUM_NOXMIT 1
/* Used by SunRPC/xprt layer. */
# define UDP_CSUM_NORCV 2
/* Default, as per the RFC, is to always do csums. */
# define UDP_CSUM_DEFAULT 0
extern struct proto udp_prot ;
2010-11-10 02:24:26 +03:00
extern atomic_long_t udp_memory_allocated ;
2007-12-31 11:29:24 +03:00
/* sysctl variables for udp */
2010-11-10 02:24:26 +03:00
extern long sysctl_udp_mem [ 3 ] ;
2007-12-31 11:29:24 +03:00
extern int sysctl_udp_rmem_min ;
extern int sysctl_udp_wmem_min ;
2005-12-27 07:43:12 +03:00
struct sk_buff ;
2005-04-17 02:20:36 +04:00
2006-11-27 22:10:57 +03:00
/*
* Generic checksumming routines for UDP ( - Lite ) v4 and v6
*/
2006-11-15 08:40:42 +03:00
static inline __sum16 __udp_lib_checksum_complete ( struct sk_buff * skb )
2006-11-27 22:10:57 +03:00
{
2007-03-26 07:10:56 +04:00
return __skb_checksum_complete_head ( skb , UDP_SKB_CB ( skb ) - > cscov ) ;
2006-11-27 22:10:57 +03:00
}
2006-11-21 05:06:37 +03:00
static inline int udp_lib_checksum_complete ( struct sk_buff * skb )
2006-11-27 22:10:57 +03:00
{
2007-04-09 22:59:39 +04:00
return ! skb_csum_unnecessary ( skb ) & &
2006-11-27 22:10:57 +03:00
__udp_lib_checksum_complete ( skb ) ;
}
/**
* udp_csum_outgoing - compute UDPv4 / v6 checksum over fragments
* @ sk : socket we are writing to
* @ skb : sk_buff containing the filled - in UDP header
* ( checksum field must be zeroed out )
*/
2006-11-15 08:35:48 +03:00
static inline __wsum udp_csum_outgoing ( struct sock * sk , struct sk_buff * skb )
2006-11-27 22:10:57 +03:00
{
2007-04-26 05:04:18 +04:00
__wsum csum = csum_partial ( skb_transport_header ( skb ) ,
sizeof ( struct udphdr ) , 0 ) ;
2006-11-27 22:10:57 +03:00
skb_queue_walk ( & sk - > sk_write_queue , skb ) {
csum = csum_add ( csum , skb - > csum ) ;
}
return csum ;
}
2011-03-01 05:36:48 +03:00
static inline __wsum udp_csum ( struct sk_buff * skb )
{
__wsum csum = csum_partial ( skb_transport_header ( skb ) ,
sizeof ( struct udphdr ) , skb - > csum ) ;
for ( skb = skb_shinfo ( skb ) - > frag_list ; skb ; skb = skb - > next ) {
csum = csum_add ( csum , skb - > csum ) ;
}
return csum ;
}
2006-11-27 22:10:57 +03:00
/* hash routines shared between UDPv4/6 and UDP-Litev4/6 */
static inline void udp_lib_hash ( struct sock * sk )
{
BUG ( ) ;
}
2013-09-23 22:33:36 +04:00
void udp_lib_unhash ( struct sock * sk ) ;
void udp_lib_rehash ( struct sock * sk , u16 new_hash ) ;
2006-11-27 22:10:57 +03:00
static inline void udp_lib_close ( struct sock * sk , long timeout )
{
sk_common_release ( sk ) ;
}
2013-09-23 22:33:36 +04:00
int udp_lib_get_port ( struct sock * sk , unsigned short snum ,
int ( * ) ( const struct sock * , const struct sock * ) ,
unsigned int hash2_nulladdr ) ;
2006-11-27 22:10:57 +03:00
/* net/ipv4/udp.c */
2013-10-07 20:01:39 +04:00
void udp_v4_early_demux ( struct sk_buff * skb ) ;
2013-09-23 22:33:36 +04:00
int udp_get_port ( struct sock * sk , unsigned short snum ,
int ( * saddr_cmp ) ( const struct sock * ,
const struct sock * ) ) ;
void udp_err ( struct sk_buff * , u32 ) ;
int udp_sendmsg ( struct kiocb * iocb , struct sock * sk , struct msghdr * msg ,
size_t len ) ;
int udp_push_pending_frames ( struct sock * sk ) ;
void udp_flush_pending_frames ( struct sock * sk ) ;
void udp4_hwcsum ( struct sk_buff * skb , __be32 src , __be32 dst ) ;
int udp_rcv ( struct sk_buff * skb ) ;
int udp_ioctl ( struct sock * sk , int cmd , unsigned long arg ) ;
int udp_disconnect ( struct sock * sk , int flags ) ;
unsigned int udp_poll ( struct file * file , struct socket * sock , poll_table * wait ) ;
struct sk_buff * skb_udp_tunnel_segment ( struct sk_buff * skb ,
netdev_features_t features ) ;
int udp_lib_getsockopt ( struct sock * sk , int level , int optname ,
char __user * optval , int __user * optlen ) ;
int udp_lib_setsockopt ( struct sock * sk , int level , int optname ,
char __user * optval , unsigned int optlen ,
int ( * push_pending_frames ) ( struct sock * ) ) ;
struct sock * udp4_lib_lookup ( struct net * net , __be32 saddr , __be16 sport ,
__be32 daddr , __be16 dport , int dif ) ;
struct sock * __udp4_lib_lookup ( struct net * net , __be32 saddr , __be16 sport ,
__be32 daddr , __be16 dport , int dif ,
struct udp_table * tbl ) ;
struct sock * udp6_lib_lookup ( struct net * net ,
const struct in6_addr * saddr , __be16 sport ,
const struct in6_addr * daddr , __be16 dport ,
int dif ) ;
struct sock * __udp6_lib_lookup ( struct net * net ,
const struct in6_addr * saddr , __be16 sport ,
const struct in6_addr * daddr , __be16 dport ,
int dif , struct udp_table * tbl ) ;
2008-10-01 18:48:10 +04:00
2006-11-27 22:10:57 +03:00
/*
* SNMP statistics for UDP and UDP - Lite
*/
2008-07-18 15:03:27 +04:00
# define UDP_INC_STATS_USER(net, field, is_udplite) do { \
2008-07-18 15:03:45 +04:00
if ( is_udplite ) SNMP_INC_STATS_USER ( ( net ) - > mib . udplite_statistics , field ) ; \
2008-07-18 15:03:27 +04:00
else SNMP_INC_STATS_USER ( ( net ) - > mib . udp_statistics , field ) ; } while ( 0 )
# define UDP_INC_STATS_BH(net, field, is_udplite) do { \
2008-07-18 15:03:45 +04:00
if ( is_udplite ) SNMP_INC_STATS_BH ( ( net ) - > mib . udplite_statistics , field ) ; \
2008-07-18 15:03:27 +04:00
else SNMP_INC_STATS_BH ( ( net ) - > mib . udp_statistics , field ) ; } while ( 0 )
2005-04-17 02:20:36 +04:00
2008-10-08 01:49:36 +04:00
# define UDP6_INC_STATS_BH(net, field, is_udplite) do { \
2008-10-08 01:50:06 +04:00
if ( is_udplite ) SNMP_INC_STATS_BH ( ( net ) - > mib . udplite_stats_in6 , field ) ; \
2008-10-08 01:49:36 +04:00
else SNMP_INC_STATS_BH ( ( net ) - > mib . udp_stats_in6 , field ) ; \
} while ( 0 )
2008-10-08 01:50:06 +04:00
# define UDP6_INC_STATS_USER(net, field, __lite) do { \
if ( __lite ) SNMP_INC_STATS_USER ( ( net ) - > mib . udplite_stats_in6 , field ) ; \
else SNMP_INC_STATS_USER ( ( net ) - > mib . udp_stats_in6 , field ) ; \
2008-10-08 01:49:36 +04:00
} while ( 0 )
2007-12-11 22:30:32 +03:00
2011-12-10 13:48:31 +04:00
# if IS_ENABLED(CONFIG_IPV6)
2007-12-11 22:30:32 +03:00
# define UDPX_INC_STATS_BH(sk, field) \
do { \
if ( ( sk ) - > sk_family = = AF_INET ) \
2008-07-06 08:18:48 +04:00
UDP_INC_STATS_BH ( sock_net ( sk ) , field , 0 ) ; \
2007-12-11 22:30:32 +03:00
else \
2008-07-06 08:19:40 +04:00
UDP6_INC_STATS_BH ( sock_net ( sk ) , field , 0 ) ; \
2007-12-11 22:30:32 +03:00
} while ( 0 ) ;
# else
2008-07-06 08:18:48 +04:00
# define UDPX_INC_STATS_BH(sk, field) UDP_INC_STATS_BH(sock_net(sk), field, 0)
2007-12-11 22:30:32 +03:00
# endif
2005-04-17 02:20:36 +04:00
/* /proc */
2011-10-30 10:46:30 +04:00
int udp_seq_open ( struct inode * inode , struct file * file ) ;
2005-04-17 02:20:36 +04:00
struct udp_seq_afinfo {
2011-10-30 10:46:30 +04:00
char * name ;
sa_family_t family ;
struct udp_table * udp_table ;
const struct file_operations * seq_fops ;
struct seq_operations seq_ops ;
2005-04-17 02:20:36 +04:00
} ;
struct udp_iter_state {
2008-03-29 04:23:33 +03:00
struct seq_net_private p ;
2005-04-17 02:20:36 +04:00
sa_family_t family ;
int bucket ;
2008-10-29 11:41:45 +03:00
struct udp_table * udp_table ;
2005-04-17 02:20:36 +04:00
} ;
2005-08-16 09:18:02 +04:00
# ifdef CONFIG_PROC_FS
2013-09-23 22:33:36 +04:00
int udp_proc_register ( struct net * net , struct udp_seq_afinfo * afinfo ) ;
void udp_proc_unregister ( struct net * net , struct udp_seq_afinfo * afinfo ) ;
2005-08-16 09:18:02 +04:00
2013-09-23 22:33:36 +04:00
int udp4_proc_init ( void ) ;
void udp4_proc_exit ( void ) ;
2005-08-16 09:18:02 +04:00
# endif
2007-12-31 11:29:24 +03:00
2013-09-23 22:33:36 +04:00
int udpv4_offload_init ( void ) ;
2013-06-08 14:56:03 +04:00
2013-09-23 22:33:36 +04:00
void udp_init ( void ) ;
2009-07-09 12:09:47 +04:00
2013-09-23 22:33:36 +04:00
void udp_encap_enable ( void ) ;
2012-04-27 12:24:08 +04:00
# if IS_ENABLED(CONFIG_IPV6)
2013-09-23 22:33:36 +04:00
void udpv6_encap_enable ( void ) ;
2012-04-27 12:24:08 +04:00
# endif
2005-04-17 02:20:36 +04:00
# endif /* _UDP_H */