2010-08-22 10:05:39 +04:00
# ifndef __LINUX_GRE_H
# define __LINUX_GRE_H
# include <linux/skbuff.h>
2013-03-25 18:49:35 +04:00
# include <net/ip_tunnels.h>
2010-08-22 10:05:39 +04:00
2015-08-08 09:51:52 +03:00
struct gre_base_hdr {
__be16 flags ;
__be16 protocol ;
2016-08-09 07:38:24 +03:00
} __packed ;
struct gre_full_hdr {
struct gre_base_hdr fixed_header ;
__be16 csum ;
__be16 reserved1 ;
__be32 key ;
__be32 seq ;
} __packed ;
2015-08-08 09:51:52 +03:00
# define GRE_HEADER_SECTION 4
2010-08-22 10:05:39 +04:00
# define GREPROTO_CISCO 0
# define GREPROTO_PPTP 1
# define GREPROTO_MAX 2
2013-06-18 04:49:38 +04:00
# define GRE_IP_PROTO_MAX 2
2010-08-22 10:05:39 +04:00
struct gre_protocol {
int ( * handler ) ( struct sk_buff * skb ) ;
void ( * err_handler ) ( struct sk_buff * skb , u32 info ) ;
} ;
int gre_add_protocol ( const struct gre_protocol * proto , u8 version ) ;
int gre_del_protocol ( const struct gre_protocol * proto , u8 version ) ;
2015-08-08 09:51:47 +03:00
struct net_device * gretap_fb_dev_create ( struct net * net , const char * name ,
u8 name_assign_type ) ;
2016-04-30 03:12:16 +03:00
int gre_parse_header ( struct sk_buff * skb , struct tnl_ptk_info * tpi ,
2016-06-15 16:24:00 +03:00
bool * csum_err , __be16 proto , int nhs ) ;
2016-04-30 03:12:16 +03:00
static inline int gre_calc_hlen ( __be16 o_flags )
{
int addend = 4 ;
if ( o_flags & TUNNEL_CSUM )
addend + = 4 ;
if ( o_flags & TUNNEL_KEY )
addend + = 4 ;
if ( o_flags & TUNNEL_SEQ )
addend + = 4 ;
return addend ;
}
static inline __be16 gre_flags_to_tnl_flags ( __be16 flags )
{
__be16 tflags = 0 ;
if ( flags & GRE_CSUM )
tflags | = TUNNEL_CSUM ;
if ( flags & GRE_ROUTING )
tflags | = TUNNEL_ROUTING ;
if ( flags & GRE_KEY )
tflags | = TUNNEL_KEY ;
if ( flags & GRE_SEQ )
tflags | = TUNNEL_SEQ ;
if ( flags & GRE_STRICT )
tflags | = TUNNEL_STRICT ;
if ( flags & GRE_REC )
tflags | = TUNNEL_REC ;
if ( flags & GRE_VERSION )
tflags | = TUNNEL_VERSION ;
return tflags ;
}
static inline __be16 gre_tnl_flags_to_gre_flags ( __be16 tflags )
{
__be16 flags = 0 ;
if ( tflags & TUNNEL_CSUM )
flags | = GRE_CSUM ;
if ( tflags & TUNNEL_ROUTING )
flags | = GRE_ROUTING ;
if ( tflags & TUNNEL_KEY )
flags | = GRE_KEY ;
if ( tflags & TUNNEL_SEQ )
flags | = GRE_SEQ ;
if ( tflags & TUNNEL_STRICT )
flags | = GRE_STRICT ;
if ( tflags & TUNNEL_REC )
flags | = GRE_REC ;
if ( tflags & TUNNEL_VERSION )
flags | = GRE_VERSION ;
return flags ;
}
2016-04-30 03:12:19 +03:00
static inline __sum16 gre_checksum ( struct sk_buff * skb )
{
__wsum csum ;
if ( skb - > ip_summed = = CHECKSUM_PARTIAL )
csum = lco_csum ( skb ) ;
else
csum = skb_checksum ( skb , 0 , skb - > len , 0 ) ;
return csum_fold ( csum ) ;
}
static inline void gre_build_header ( struct sk_buff * skb , int hdr_len ,
__be16 flags , __be16 proto ,
__be32 key , __be32 seq )
{
struct gre_base_hdr * greh ;
skb_push ( skb , hdr_len ) ;
2016-08-15 14:06:24 +03:00
skb_set_inner_protocol ( skb , proto ) ;
2016-04-30 03:12:19 +03:00
skb_reset_transport_header ( skb ) ;
greh = ( struct gre_base_hdr * ) skb - > data ;
greh - > flags = gre_tnl_flags_to_gre_flags ( flags ) ;
greh - > protocol = proto ;
if ( flags & ( TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ ) ) {
__be32 * ptr = ( __be32 * ) ( ( ( u8 * ) greh ) + hdr_len - 4 ) ;
if ( flags & TUNNEL_SEQ ) {
* ptr = seq ;
ptr - - ;
}
if ( flags & TUNNEL_KEY ) {
* ptr = key ;
ptr - - ;
}
if ( flags & TUNNEL_CSUM & &
! ( skb_shinfo ( skb ) - > gso_type &
( SKB_GSO_GRE | SKB_GSO_GRE_CSUM ) ) ) {
* ptr = 0 ;
* ( __sum16 * ) ptr = gre_checksum ( skb ) ;
}
}
}
2010-08-22 10:05:39 +04:00
# endif