2005-04-16 15:20:36 -07: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 IP module .
*
* Version : @ ( # ) ip . h 1.0 .2 05 / 07 / 93
*
2005-05-05 16:16:16 -07:00
* Authors : Ross Biro
2005-04-16 15:20:36 -07:00
* Fred N . van Kempen , < waltje @ uWalt . NL . Mugnet . ORG >
* Alan Cox , < gw4pts @ gw4pts . ampr . org >
*
* Changes :
* Mike McLagan : Routing by source
*
* 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 _IP_H
# define _IP_H
# include <linux/types.h>
# include <linux/ip.h>
# include <linux/in.h>
2007-03-12 20:09:15 -03:00
# include <linux/skbuff.h>
2005-12-27 02:43:12 -02:00
# include <net/inet_sock.h>
2013-09-24 15:43:09 +02:00
# include <net/route.h>
2005-04-16 15:20:36 -07:00
# include <net/snmp.h>
2008-10-01 07:44:42 -07:00
# include <net/flow.h>
2005-04-16 15:20:36 -07:00
struct sock ;
2009-11-03 03:26:03 +00:00
struct inet_skb_parm {
2005-04-16 15:20:36 -07:00
struct ip_options opt ; /* Compiled IP options */
unsigned char flags ;
2006-01-06 23:04:01 -08:00
# define IPSKB_FORWARDED 1
# define IPSKB_XFRM_TUNNEL_SIZE 2
2006-01-06 23:04:54 -08:00
# define IPSKB_XFRM_TRANSFORMED 4
# define IPSKB_FRAG_COMPLETE 8
2006-02-15 15:10:22 -08:00
# define IPSKB_REROUTED 16
2012-08-26 19:13:55 +02:00
u16 frag_max_size ;
2005-04-16 15:20:36 -07:00
} ;
2007-03-12 20:09:15 -03:00
static inline unsigned int ip_hdrlen ( const struct sk_buff * skb )
{
2007-04-20 22:47:35 -07:00
return ip_hdr ( skb ) - > ihl * 4 ;
2007-03-12 20:09:15 -03:00
}
2009-11-03 03:26:03 +00:00
struct ipcm_cookie {
2006-09-27 18:28:28 -07:00
__be32 addr ;
2005-04-16 15:20:36 -07:00
int oif ;
2011-04-21 09:45:37 +00:00
struct ip_options_rcu * opt ;
2010-08-17 08:59:14 +00:00
__u8 tx_flags ;
2013-09-24 15:43:08 +02:00
__u8 ttl ;
__s16 tos ;
char priority ;
2005-04-16 15:20:36 -07:00
} ;
# define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
2014-01-20 03:43:08 +01:00
# define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
2005-04-16 15:20:36 -07:00
2009-11-03 03:26:03 +00:00
struct ip_ra_chain {
2010-10-25 03:32:44 +00:00
struct ip_ra_chain __rcu * next ;
2005-04-16 15:20:36 -07:00
struct sock * sk ;
2010-06-09 16:21:07 +00:00
union {
void ( * destructor ) ( struct sock * ) ;
struct sock * saved_sk ;
} ;
2010-06-07 03:12:08 +00:00
struct rcu_head rcu ;
2005-04-16 15:20:36 -07:00
} ;
2010-10-25 03:32:44 +00:00
extern struct ip_ra_chain __rcu * ip_ra_chain ;
2005-04-16 15:20:36 -07:00
/* IP flags. */
# define IP_CE 0x8000 /* Flag: "Congestion" */
# define IP_DF 0x4000 /* Flag: "Don't Fragment" */
# define IP_MF 0x2000 /* Flag: "More Fragments" */
# define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
# define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */
2005-12-27 02:43:12 -02:00
struct msghdr ;
struct net_device ;
struct packet_type ;
struct rtable ;
struct sockaddr ;
2014-01-10 16:09:45 -08:00
int igmp_mc_init ( void ) ;
2005-04-16 15:20:36 -07:00
/*
* Functions provided by ip . c
*/
2013-09-21 10:22:42 -07:00
int ip_build_and_send_pkt ( struct sk_buff * skb , struct sock * sk ,
__be32 saddr , __be32 daddr ,
struct ip_options_rcu * opt ) ;
int ip_rcv ( struct sk_buff * skb , struct net_device * dev , struct packet_type * pt ,
struct net_device * orig_dev ) ;
int ip_local_deliver ( struct sk_buff * skb ) ;
int ip_mr_input ( struct sk_buff * skb ) ;
2014-04-15 13:47:15 -04:00
int ip_output ( struct sock * sk , struct sk_buff * skb ) ;
int ip_mc_output ( struct sock * sk , struct sk_buff * skb ) ;
2013-09-21 10:22:42 -07:00
int ip_fragment ( struct sk_buff * skb , int ( * output ) ( struct sk_buff * ) ) ;
int ip_do_nat ( struct sk_buff * skb ) ;
void ip_send_check ( struct iphdr * ip ) ;
int __ip_local_out ( struct sk_buff * skb ) ;
2014-04-15 13:47:15 -04:00
int ip_local_out_sk ( struct sock * sk , struct sk_buff * skb ) ;
static inline int ip_local_out ( struct sk_buff * skb )
{
return ip_local_out_sk ( skb - > sk , skb ) ;
}
2014-04-15 12:58:34 -04:00
int ip_queue_xmit ( struct sock * sk , struct sk_buff * skb , struct flowi * fl ) ;
2013-09-21 10:22:42 -07:00
void ip_init ( void ) ;
int ip_append_data ( struct sock * sk , struct flowi4 * fl4 ,
int getfrag ( void * from , char * to , int offset , int len ,
int odd , struct sk_buff * skb ) ,
void * from , int len , int protolen ,
struct ipcm_cookie * ipc ,
struct rtable * * rt ,
unsigned int flags ) ;
int ip_generic_getfrag ( void * from , char * to , int offset , int len , int odd ,
struct sk_buff * skb ) ;
ssize_t ip_append_page ( struct sock * sk , struct flowi4 * fl4 , struct page * page ,
int offset , size_t size , int flags ) ;
struct sk_buff * __ip_make_skb ( struct sock * sk , struct flowi4 * fl4 ,
struct sk_buff_head * queue ,
struct inet_cork * cork ) ;
int ip_send_skb ( struct net * net , struct sk_buff * skb ) ;
int ip_push_pending_frames ( struct sock * sk , struct flowi4 * fl4 ) ;
void ip_flush_pending_frames ( struct sock * sk ) ;
struct sk_buff * ip_make_skb ( struct sock * sk , struct flowi4 * fl4 ,
int getfrag ( void * from , char * to , int offset ,
int len , int odd , struct sk_buff * skb ) ,
void * from , int length , int transhdrlen ,
struct ipcm_cookie * ipc , struct rtable * * rtp ,
unsigned int flags ) ;
2011-03-01 02:36:47 +00:00
2011-05-08 17:12:19 -07:00
static inline struct sk_buff * ip_finish_skb ( struct sock * sk , struct flowi4 * fl4 )
2011-03-01 02:36:47 +00:00
{
2011-05-08 17:12:19 -07:00
return __ip_make_skb ( sk , fl4 , & sk - > sk_write_queue , & inet_sk ( sk ) - > cork . base ) ;
2011-03-01 02:36:47 +00:00
}
2005-04-16 15:20:36 -07:00
2013-09-24 15:43:09 +02:00
static inline __u8 get_rttos ( struct ipcm_cookie * ipc , struct inet_sock * inet )
{
return ( ipc - > tos ! = - 1 ) ? RT_TOS ( ipc - > tos ) : RT_TOS ( inet - > tos ) ;
}
static inline __u8 get_rtconn_flags ( struct ipcm_cookie * ipc , struct sock * sk )
{
return ( ipc - > tos ! = - 1 ) ? RT_CONN_FLAGS_TOS ( sk , ipc - > tos ) : RT_CONN_FLAGS ( sk ) ;
}
2005-04-16 15:20:36 -07:00
/* datagram.c */
2013-09-21 10:22:42 -07:00
int ip4_datagram_connect ( struct sock * sk , struct sockaddr * uaddr , int addr_len ) ;
2005-04-16 15:20:36 -07:00
2013-09-21 10:22:42 -07:00
void ip4_datagram_release_cb ( struct sock * sk ) ;
2013-01-21 02:00:03 +00:00
2005-04-16 15:20:36 -07:00
struct ip_reply_arg {
struct kvec iov [ 1 ] ;
2008-10-01 07:41:00 -07:00
int flags ;
2006-11-14 21:26:08 -08:00
__wsum csum ;
2005-04-16 15:20:36 -07:00
int csumoffset ; /* u16 offset of csum in iov[0].iov_base */
/* -1 if not needed */
2007-06-04 21:32:46 -07:00
int bound_dev_if ;
2011-10-24 03:06:21 -04:00
u8 tos ;
2005-04-16 15:20:36 -07:00
} ;
2008-10-01 07:41:00 -07:00
# define IP_REPLY_ARG_NOSRCCHECK 1
2008-10-01 07:44:42 -07:00
static inline __u8 ip_reply_arg_flowi_flags ( const struct ip_reply_arg * arg )
{
return ( arg - > flags & IP_REPLY_ARG_NOSRCCHECK ) ? FLOWI_FLAG_ANYSRC : 0 ;
}
2012-07-19 07:34:03 +00:00
void ip_send_unicast_reply ( struct net * net , struct sk_buff * skb , __be32 daddr ,
2012-06-28 03:21:41 -07:00
__be32 saddr , const struct ip_reply_arg * arg ,
unsigned int len ) ;
2005-04-16 15:20:36 -07:00
2010-06-30 13:31:19 -07:00
# define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field)
# define IP_INC_STATS_BH(net, field) SNMP_INC_STATS64_BH((net)->mib.ip_statistics, field)
# define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
# define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS64_BH((net)->mib.ip_statistics, field, val)
# define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
# define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS64_BH((net)->mib.ip_statistics, field, val)
2008-07-18 04:03:08 -07:00
# define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field)
# define NET_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field)
# define NET_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->mib.net_statistics, field)
2014-03-06 15:03:17 -05:00
# define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd)
2008-07-18 04:03:08 -07:00
# define NET_ADD_STATS_BH(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd)
# define NET_ADD_STATS_USER(net, field, adnd) SNMP_ADD_STATS_USER((net)->mib.net_statistics, field, adnd)
2005-04-16 15:20:36 -07:00
2014-05-05 15:55:55 -07:00
unsigned long snmp_fold_field ( void __percpu * mib , int offt ) ;
2010-06-30 13:31:19 -07:00
# if BITS_PER_LONG==32
2014-05-05 15:55:55 -07:00
u64 snmp_fold_field64 ( void __percpu * mib , int offt , size_t sync_off ) ;
2010-06-30 13:31:19 -07:00
# else
2014-05-05 15:55:55 -07:00
static inline u64 snmp_fold_field64 ( void __percpu * mib , int offt , size_t syncp_off )
2010-06-30 13:31:19 -07:00
{
return snmp_fold_field ( mib , offt ) ;
}
# endif
2007-04-20 15:57:15 -07:00
2013-09-28 14:10:59 -07:00
void inet_get_local_port_range ( struct net * net , int * low , int * high ) ;
2007-10-10 17:30:46 -07:00
2014-05-15 13:43:14 -04:00
# ifdef CONFIG_SYSCTL
2014-05-12 16:04:53 -07:00
static inline int inet_is_local_reserved_port ( struct net * net , int port )
2010-05-05 00:27:06 +00:00
{
2014-05-12 16:04:53 -07:00
if ( ! net - > ipv4 . sysctl_local_reserved_ports )
return 0 ;
return test_bit ( port , net - > ipv4 . sysctl_local_reserved_ports ) ;
2010-05-05 00:27:06 +00:00
}
2014-05-12 16:04:53 -07:00
# else
static inline int inet_is_local_reserved_port ( struct net * net , int port )
{
return 0 ;
}
# endif
2010-05-05 00:27:06 +00:00
2005-06-13 15:12:33 -07:00
extern int sysctl_ip_nonlocal_bind ;
2005-04-16 15:20:36 -07:00
2005-08-16 02:18:02 -03:00
/* From inetpeer.c */
extern int inet_peer_threshold ;
extern int inet_peer_minttl ;
extern int inet_peer_maxttl ;
2012-06-21 13:58:31 +00:00
/* From ip_input.c */
extern int sysctl_ip_early_demux ;
2005-08-16 02:18:02 -03:00
/* From ip_output.c */
extern int sysctl_ip_dynaddr ;
2013-09-21 10:22:42 -07:00
void ipfrag_init ( void ) ;
2005-08-16 02:18:02 -03:00
2013-09-21 10:22:42 -07:00
void ip_static_sysctl_init ( void ) ;
2008-07-15 16:00:59 -04:00
2014-05-13 10:17:33 -07:00
# define IP4_REPLY_MARK(net, mark) \
( ( net ) - > ipv4 . sysctl_fwmark_reflect ? ( mark ) : 0 )
2011-06-23 21:28:52 -07:00
static inline bool ip_is_fragment ( const struct iphdr * iph )
{
return ( iph - > frag_off & htons ( IP_MF | IP_OFFSET ) ) ! = 0 ;
}
2005-04-16 15:20:36 -07:00
# ifdef CONFIG_INET
2005-12-27 02:43:12 -02:00
# include <net/dst.h>
2005-04-16 15:20:36 -07:00
/* The function in 2.2 was invalid, producing wrong result for
* check = 0xFEFF . It was noticed by Arthur Skawina _year_ ago . - - ANK ( 000625 ) */
static inline
int ip_decrease_ttl ( struct iphdr * iph )
{
2006-11-14 21:42:26 -08:00
u32 check = ( __force u32 ) iph - > check ;
check + = ( __force u32 ) htons ( 0x0100 ) ;
iph - > check = ( __force __sum16 ) ( check + ( check > = 0xFFFF ) ) ;
2005-04-16 15:20:36 -07:00
return - - iph - > ttl ;
}
static inline
int ip_dont_fragment ( struct sock * sk , struct dst_entry * dst )
{
2010-09-22 20:43:57 +00:00
return inet_sk ( sk ) - > pmtudisc = = IP_PMTUDISC_DO | |
2005-04-16 15:20:36 -07:00
( inet_sk ( sk ) - > pmtudisc = = IP_PMTUDISC_WANT & &
2010-09-22 20:43:57 +00:00
! ( dst_metric_locked ( dst , RTAX_MTU ) ) ) ;
2005-04-16 15:20:36 -07:00
}
2014-01-09 10:01:15 +01:00
static inline bool ip_sk_accept_pmtu ( const struct sock * sk )
{
2014-02-26 01:20:42 +01:00
return inet_sk ( sk ) - > pmtudisc ! = IP_PMTUDISC_INTERFACE & &
inet_sk ( sk ) - > pmtudisc ! = IP_PMTUDISC_OMIT ;
2014-01-09 10:01:15 +01:00
}
static inline bool ip_sk_use_pmtu ( const struct sock * sk )
{
return inet_sk ( sk ) - > pmtudisc < IP_PMTUDISC_PROBE ;
}
2014-05-04 16:39:18 -07:00
static inline bool ip_sk_ignore_df ( const struct sock * sk )
2014-02-26 01:20:42 +01:00
{
return inet_sk ( sk ) - > pmtudisc < IP_PMTUDISC_DO | |
inet_sk ( sk ) - > pmtudisc = = IP_PMTUDISC_OMIT ;
}
2014-01-09 10:01:15 +01:00
static inline unsigned int ip_dst_mtu_maybe_forward ( const struct dst_entry * dst ,
bool forwarding )
{
struct net * net = dev_net ( dst - > dev ) ;
if ( net - > ipv4 . sysctl_ip_fwd_use_pmtu | |
dst_metric_locked ( dst , RTAX_MTU ) | |
! forwarding )
return dst_mtu ( dst ) ;
return min ( dst - > dev - > mtu , IP_MAX_MTU ) ;
}
static inline unsigned int ip_skb_dst_mtu ( const struct sk_buff * skb )
{
if ( ! skb - > sk | | ip_sk_use_pmtu ( skb - > sk ) ) {
bool forwarding = IPCB ( skb ) - > flags & IPSKB_FORWARDED ;
return ip_dst_mtu_maybe_forward ( skb_dst ( skb ) , forwarding ) ;
} else {
return min ( skb_dst ( skb ) - > dev - > mtu , IP_MAX_MTU ) ;
}
}
inetpeer: get rid of ip_id_count
Ideally, we would need to generate IP ID using a per destination IP
generator.
linux kernels used inet_peer cache for this purpose, but this had a huge
cost on servers disabling MTU discovery.
1) each inet_peer struct consumes 192 bytes
2) inetpeer cache uses a binary tree of inet_peer structs,
with a nominal size of ~66000 elements under load.
3) lookups in this tree are hitting a lot of cache lines, as tree depth
is about 20.
4) If server deals with many tcp flows, we have a high probability of
not finding the inet_peer, allocating a fresh one, inserting it in
the tree with same initial ip_id_count, (cf secure_ip_id())
5) We garbage collect inet_peer aggressively.
IP ID generation do not have to be 'perfect'
Goal is trying to avoid duplicates in a short period of time,
so that reassembly units have a chance to complete reassembly of
fragments belonging to one message before receiving other fragments
with a recycled ID.
We simply use an array of generators, and a Jenkin hash using the dst IP
as a key.
ipv6_select_ident() is put back into net/ipv6/ip6_output.c where it
belongs (it is only used from this file)
secure_ip_id() and secure_ipv6_id() no longer are needed.
Rename ip_select_ident_more() to ip_select_ident_segs() to avoid
unnecessary decrement/increment of the number of segments.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-06-02 05:26:03 -07:00
# define IP_IDENTS_SZ 2048u
extern atomic_t * ip_idents ;
2005-04-16 15:20:36 -07:00
inetpeer: get rid of ip_id_count
Ideally, we would need to generate IP ID using a per destination IP
generator.
linux kernels used inet_peer cache for this purpose, but this had a huge
cost on servers disabling MTU discovery.
1) each inet_peer struct consumes 192 bytes
2) inetpeer cache uses a binary tree of inet_peer structs,
with a nominal size of ~66000 elements under load.
3) lookups in this tree are hitting a lot of cache lines, as tree depth
is about 20.
4) If server deals with many tcp flows, we have a high probability of
not finding the inet_peer, allocating a fresh one, inserting it in
the tree with same initial ip_id_count, (cf secure_ip_id())
5) We garbage collect inet_peer aggressively.
IP ID generation do not have to be 'perfect'
Goal is trying to avoid duplicates in a short period of time,
so that reassembly units have a chance to complete reassembly of
fragments belonging to one message before receiving other fragments
with a recycled ID.
We simply use an array of generators, and a Jenkin hash using the dst IP
as a key.
ipv6_select_ident() is put back into net/ipv6/ip6_output.c where it
belongs (it is only used from this file)
secure_ip_id() and secure_ipv6_id() no longer are needed.
Rename ip_select_ident_more() to ip_select_ident_segs() to avoid
unnecessary decrement/increment of the number of segments.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-06-02 05:26:03 -07:00
static inline u32 ip_idents_reserve ( u32 hash , int segs )
{
atomic_t * id_ptr = ip_idents + hash % IP_IDENTS_SZ ;
return atomic_add_return ( segs , id_ptr ) - segs ;
}
void __ip_select_ident ( struct iphdr * iph , int segs ) ;
static inline void ip_select_ident_segs ( struct sk_buff * skb , struct sock * sk , int segs )
2005-04-16 15:20:36 -07:00
{
2013-09-18 15:29:53 -07:00
struct iphdr * iph = ip_hdr ( skb ) ;
2014-05-04 16:39:18 -07:00
if ( ( iph - > frag_off & htons ( IP_DF ) ) & & ! skb - > ignore_df ) {
2005-04-16 15:20:36 -07:00
/* This is only to work around buggy Windows95/2000
* VJ compression implementations . If the ID field
* does not change , they drop every other packet in
* a TCP stream using header compression .
*/
2009-10-15 06:30:45 +00:00
if ( sk & & inet_sk ( sk ) - > inet_daddr ) {
iph - > id = htons ( inet_sk ( sk ) - > inet_id ) ;
inetpeer: get rid of ip_id_count
Ideally, we would need to generate IP ID using a per destination IP
generator.
linux kernels used inet_peer cache for this purpose, but this had a huge
cost on servers disabling MTU discovery.
1) each inet_peer struct consumes 192 bytes
2) inetpeer cache uses a binary tree of inet_peer structs,
with a nominal size of ~66000 elements under load.
3) lookups in this tree are hitting a lot of cache lines, as tree depth
is about 20.
4) If server deals with many tcp flows, we have a high probability of
not finding the inet_peer, allocating a fresh one, inserting it in
the tree with same initial ip_id_count, (cf secure_ip_id())
5) We garbage collect inet_peer aggressively.
IP ID generation do not have to be 'perfect'
Goal is trying to avoid duplicates in a short period of time,
so that reassembly units have a chance to complete reassembly of
fragments belonging to one message before receiving other fragments
with a recycled ID.
We simply use an array of generators, and a Jenkin hash using the dst IP
as a key.
ipv6_select_ident() is put back into net/ipv6/ip6_output.c where it
belongs (it is only used from this file)
secure_ip_id() and secure_ipv6_id() no longer are needed.
Rename ip_select_ident_more() to ip_select_ident_segs() to avoid
unnecessary decrement/increment of the number of segments.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-06-02 05:26:03 -07:00
inet_sk ( sk ) - > inet_id + = segs ;
} else {
2005-04-16 15:20:36 -07:00
iph - > id = 0 ;
inetpeer: get rid of ip_id_count
Ideally, we would need to generate IP ID using a per destination IP
generator.
linux kernels used inet_peer cache for this purpose, but this had a huge
cost on servers disabling MTU discovery.
1) each inet_peer struct consumes 192 bytes
2) inetpeer cache uses a binary tree of inet_peer structs,
with a nominal size of ~66000 elements under load.
3) lookups in this tree are hitting a lot of cache lines, as tree depth
is about 20.
4) If server deals with many tcp flows, we have a high probability of
not finding the inet_peer, allocating a fresh one, inserting it in
the tree with same initial ip_id_count, (cf secure_ip_id())
5) We garbage collect inet_peer aggressively.
IP ID generation do not have to be 'perfect'
Goal is trying to avoid duplicates in a short period of time,
so that reassembly units have a chance to complete reassembly of
fragments belonging to one message before receiving other fragments
with a recycled ID.
We simply use an array of generators, and a Jenkin hash using the dst IP
as a key.
ipv6_select_ident() is put back into net/ipv6/ip6_output.c where it
belongs (it is only used from this file)
secure_ip_id() and secure_ipv6_id() no longer are needed.
Rename ip_select_ident_more() to ip_select_ident_segs() to avoid
unnecessary decrement/increment of the number of segments.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-06-02 05:26:03 -07:00
}
} else {
__ip_select_ident ( iph , segs ) ;
}
}
static inline void ip_select_ident ( struct sk_buff * skb , struct sock * sk )
{
ip_select_ident_segs ( skb , sk , 1 ) ;
2005-04-16 15:20:36 -07:00
}
2014-05-02 16:29:38 -07:00
static inline __wsum inet_compute_pseudo ( struct sk_buff * skb , int proto )
{
return csum_tcpudp_nofold ( ip_hdr ( skb ) - > saddr , ip_hdr ( skb ) - > daddr ,
skb - > len , proto , 0 ) ;
}
2005-04-16 15:20:36 -07:00
/*
* Map a multicast IP onto multicast MAC for type ethernet .
*/
2006-11-14 20:51:49 -08:00
static inline void ip_eth_mc_map ( __be32 naddr , char * buf )
2005-04-16 15:20:36 -07:00
{
2006-11-14 20:51:49 -08:00
__u32 addr = ntohl ( naddr ) ;
2005-04-16 15:20:36 -07:00
buf [ 0 ] = 0x01 ;
buf [ 1 ] = 0x00 ;
buf [ 2 ] = 0x5e ;
buf [ 5 ] = addr & 0xFF ;
addr > > = 8 ;
buf [ 4 ] = addr & 0xFF ;
addr > > = 8 ;
buf [ 3 ] = addr & 0x7F ;
}
/*
* Map a multicast IP onto multicast MAC for type IP - over - InfiniBand .
* Leave P_Key as 0 to be filled in by driver .
*/
2007-12-10 13:38:41 -07:00
static inline void ip_ib_mc_map ( __be32 naddr , const unsigned char * broadcast , char * buf )
2005-04-16 15:20:36 -07:00
{
2006-11-14 20:51:49 -08:00
__u32 addr ;
2007-12-10 13:38:41 -07:00
unsigned char scope = broadcast [ 5 ] & 0xF ;
2005-04-16 15:20:36 -07:00
buf [ 0 ] = 0 ; /* Reserved */
buf [ 1 ] = 0xff ; /* Multicast QPN */
buf [ 2 ] = 0xff ;
buf [ 3 ] = 0xff ;
2006-11-14 20:51:49 -08:00
addr = ntohl ( naddr ) ;
2005-04-16 15:20:36 -07:00
buf [ 4 ] = 0xff ;
2007-12-10 13:38:41 -07:00
buf [ 5 ] = 0x10 | scope ; /* scope from broadcast address */
2005-04-16 15:20:36 -07:00
buf [ 6 ] = 0x40 ; /* IPv4 signature */
buf [ 7 ] = 0x1b ;
2007-12-10 13:38:41 -07:00
buf [ 8 ] = broadcast [ 8 ] ; /* P_Key */
buf [ 9 ] = broadcast [ 9 ] ;
2005-04-16 15:20:36 -07:00
buf [ 10 ] = 0 ;
buf [ 11 ] = 0 ;
buf [ 12 ] = 0 ;
buf [ 13 ] = 0 ;
buf [ 14 ] = 0 ;
buf [ 15 ] = 0 ;
buf [ 19 ] = addr & 0xff ;
addr > > = 8 ;
buf [ 18 ] = addr & 0xff ;
addr > > = 8 ;
buf [ 17 ] = addr & 0xff ;
addr > > = 8 ;
buf [ 16 ] = addr & 0x0f ;
}
2011-03-28 22:40:53 +00:00
static inline void ip_ipgre_mc_map ( __be32 naddr , const unsigned char * broadcast , char * buf )
{
if ( ( broadcast [ 0 ] | broadcast [ 1 ] | broadcast [ 2 ] | broadcast [ 3 ] ) ! = 0 )
memcpy ( buf , broadcast , 4 ) ;
else
memcpy ( buf , & naddr , sizeof ( naddr ) ) ;
}
2011-12-10 09:48:31 +00:00
# if IS_ENABLED(CONFIG_IPV6)
2005-04-16 15:20:36 -07:00
# include <linux/ipv6.h>
# endif
static __inline__ void inet_reset_saddr ( struct sock * sk )
{
2009-10-15 06:30:45 +00:00
inet_sk ( sk ) - > inet_rcv_saddr = inet_sk ( sk ) - > inet_saddr = 0 ;
2011-12-10 09:48:31 +00:00
# if IS_ENABLED(CONFIG_IPV6)
2005-04-16 15:20:36 -07:00
if ( sk - > sk_family = = PF_INET6 ) {
struct ipv6_pinfo * np = inet6_sk ( sk ) ;
memset ( & np - > saddr , 0 , sizeof ( np - > saddr ) ) ;
ipv6: make lookups simpler and faster
TCP listener refactoring, part 4 :
To speed up inet lookups, we moved IPv4 addresses from inet to struct
sock_common
Now is time to do the same for IPv6, because it permits us to have fast
lookups for all kind of sockets, including upcoming SYN_RECV.
Getting IPv6 addresses in TCP lookups currently requires two extra cache
lines, plus a dereference (and memory stall).
inet6_sk(sk) does the dereference of inet_sk(__sk)->pinet6
This patch is way bigger than its IPv4 counter part, because for IPv4,
we could add aliases (inet_daddr, inet_rcv_saddr), while on IPv6,
it's not doable easily.
inet6_sk(sk)->daddr becomes sk->sk_v6_daddr
inet6_sk(sk)->rcv_saddr becomes sk->sk_v6_rcv_saddr
And timewait socket also have tw->tw_v6_daddr & tw->tw_v6_rcv_saddr
at the same offset.
We get rid of INET6_TW_MATCH() as INET6_MATCH() is now the generic
macro.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-10-03 15:42:29 -07:00
memset ( & sk - > sk_v6_rcv_saddr , 0 , sizeof ( sk - > sk_v6_rcv_saddr ) ) ;
2005-04-16 15:20:36 -07:00
}
# endif
}
# endif
2010-01-06 20:37:01 -08:00
static inline int sk_mc_loop ( struct sock * sk )
{
if ( ! sk )
return 1 ;
switch ( sk - > sk_family ) {
case AF_INET :
return inet_sk ( sk ) - > mc_loop ;
2011-12-10 09:48:31 +00:00
# if IS_ENABLED(CONFIG_IPV6)
2010-01-06 20:37:01 -08:00
case AF_INET6 :
return inet6_sk ( sk ) - > mc_loop ;
# endif
}
2010-01-13 18:10:36 -08:00
WARN_ON ( 1 ) ;
2010-01-06 20:37:01 -08:00
return 1 ;
}
2013-09-21 10:22:42 -07:00
bool ip_call_ra_chain ( struct sk_buff * skb ) ;
2005-04-16 15:20:36 -07:00
/*
2008-01-01 21:13:09 -08:00
* Functions provided by ip_fragment . c
2005-04-16 15:20:36 -07:00
*/
2009-11-03 03:26:03 +00:00
enum ip_defrag_users {
2005-04-16 15:20:36 -07:00
IP_DEFRAG_LOCAL_DELIVER ,
IP_DEFRAG_CALL_RA_CHAIN ,
IP_DEFRAG_CONNTRACK_IN ,
2010-05-24 14:33:03 -07:00
__IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHRT_MAX ,
2005-04-16 15:20:36 -07:00
IP_DEFRAG_CONNTRACK_OUT ,
2010-05-24 14:33:03 -07:00
__IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHRT_MAX ,
2009-12-15 16:59:59 +01:00
IP_DEFRAG_CONNTRACK_BRIDGE_IN ,
2010-05-24 14:33:03 -07:00
__IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX ,
2005-04-16 15:20:36 -07:00
IP_DEFRAG_VS_IN ,
IP_DEFRAG_VS_OUT ,
2011-07-05 01:05:48 -07:00
IP_DEFRAG_VS_FWD ,
IP_DEFRAG_AF_PACKET ,
2011-10-06 10:28:31 +00:00
IP_DEFRAG_MACVLAN ,
2005-04-16 15:20:36 -07:00
} ;
2007-10-14 00:38:32 -07:00
int ip_defrag ( struct sk_buff * skb , u32 user ) ;
2011-10-06 10:28:31 +00:00
# ifdef CONFIG_INET
struct sk_buff * ip_check_defrag ( struct sk_buff * skb , u32 user ) ;
# else
static inline struct sk_buff * ip_check_defrag ( struct sk_buff * skb , u32 user )
{
return skb ;
}
# endif
2008-01-22 06:07:25 -08:00
int ip_frag_mem ( struct net * net ) ;
2008-01-22 06:06:23 -08:00
int ip_frag_nqueues ( struct net * net ) ;
2005-04-16 15:20:36 -07:00
/*
* Functions provided by ip_forward . c
*/
2013-09-21 10:22:42 -07:00
int ip_forward ( struct sk_buff * skb ) ;
2005-04-16 15:20:36 -07:00
/*
* Functions provided by ip_options . c
*/
2013-09-21 10:22:42 -07:00
void ip_options_build ( struct sk_buff * skb , struct ip_options * opt ,
__be32 daddr , struct rtable * rt , int is_frag ) ;
int ip_options_echo ( struct ip_options * dopt , struct sk_buff * skb ) ;
void ip_options_fragment ( struct sk_buff * skb ) ;
int ip_options_compile ( struct net * net , struct ip_options * opt ,
struct sk_buff * skb ) ;
int ip_options_get ( struct net * net , struct ip_options_rcu * * optp ,
unsigned char * data , int optlen ) ;
int ip_options_get_from_user ( struct net * net , struct ip_options_rcu * * optp ,
unsigned char __user * data , int optlen ) ;
void ip_options_undo ( struct ip_options * opt ) ;
void ip_forward_options ( struct sk_buff * skb ) ;
int ip_options_rcv_srr ( struct sk_buff * skb ) ;
2005-04-16 15:20:36 -07:00
/*
* Functions provided by ip_sockglue . c
*/
2013-10-07 11:01:40 -05:00
void ipv4_pktinfo_prepare ( const struct sock * sk , struct sk_buff * skb ) ;
2013-09-21 10:22:42 -07:00
void ip_cmsg_recv ( struct msghdr * msg , struct sk_buff * skb ) ;
2014-02-18 21:38:08 +01:00
int ip_cmsg_send ( struct net * net , struct msghdr * msg ,
struct ipcm_cookie * ipc , bool allow_ipv6 ) ;
2013-09-21 10:22:42 -07:00
int ip_setsockopt ( struct sock * sk , int level , int optname , char __user * optval ,
unsigned int optlen ) ;
int ip_getsockopt ( struct sock * sk , int level , int optname , char __user * optval ,
int __user * optlen ) ;
int compat_ip_setsockopt ( struct sock * sk , int level , int optname ,
char __user * optval , unsigned int optlen ) ;
int compat_ip_getsockopt ( struct sock * sk , int level , int optname ,
char __user * optval , int __user * optlen ) ;
int ip_ra_control ( struct sock * sk , unsigned char on ,
void ( * destructor ) ( struct sock * ) ) ;
2013-11-23 00:46:12 +01:00
int ip_recv_error ( struct sock * sk , struct msghdr * msg , int len , int * addr_len ) ;
2013-09-21 10:22:42 -07:00
void ip_icmp_error ( struct sock * sk , struct sk_buff * skb , int err , __be16 port ,
u32 info , u8 * payload ) ;
void ip_local_error ( struct sock * sk , int err , __be32 daddr , __be16 dport ,
u32 info ) ;
2005-04-16 15:20:36 -07:00
2005-08-16 02:18:02 -03:00
# ifdef CONFIG_PROC_FS
2013-09-21 10:22:42 -07:00
int ip_misc_proc_init ( void ) ;
2005-08-16 02:18:02 -03:00
# endif
2005-04-16 15:20:36 -07:00
# endif /* _IP_H */