linux/include/net/gre.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef __LINUX_GRE_H
   3#define __LINUX_GRE_H
   4
   5#include <linux/skbuff.h>
   6#include <net/ip_tunnels.h>
   7
   8struct gre_base_hdr {
   9        __be16 flags;
  10        __be16 protocol;
  11} __packed;
  12
  13struct gre_full_hdr {
  14        struct gre_base_hdr fixed_header;
  15        __be16 csum;
  16        __be16 reserved1;
  17        __be32 key;
  18        __be32 seq;
  19} __packed;
  20#define GRE_HEADER_SECTION 4
  21
  22#define GREPROTO_CISCO          0
  23#define GREPROTO_PPTP           1
  24#define GREPROTO_MAX            2
  25#define GRE_IP_PROTO_MAX        2
  26
  27struct gre_protocol {
  28        int  (*handler)(struct sk_buff *skb);
  29        void (*err_handler)(struct sk_buff *skb, u32 info);
  30};
  31
  32int gre_add_protocol(const struct gre_protocol *proto, u8 version);
  33int gre_del_protocol(const struct gre_protocol *proto, u8 version);
  34
  35struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
  36                                       u8 name_assign_type);
  37int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
  38                     bool *csum_err, __be16 proto, int nhs);
  39
  40static inline int gre_calc_hlen(__be16 o_flags)
  41{
  42        int addend = 4;
  43
  44        if (o_flags & TUNNEL_CSUM)
  45                addend += 4;
  46        if (o_flags & TUNNEL_KEY)
  47                addend += 4;
  48        if (o_flags & TUNNEL_SEQ)
  49                addend += 4;
  50        return addend;
  51}
  52
  53static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
  54{
  55        __be16 tflags = 0;
  56
  57        if (flags & GRE_CSUM)
  58                tflags |= TUNNEL_CSUM;
  59        if (flags & GRE_ROUTING)
  60                tflags |= TUNNEL_ROUTING;
  61        if (flags & GRE_KEY)
  62                tflags |= TUNNEL_KEY;
  63        if (flags & GRE_SEQ)
  64                tflags |= TUNNEL_SEQ;
  65        if (flags & GRE_STRICT)
  66                tflags |= TUNNEL_STRICT;
  67        if (flags & GRE_REC)
  68                tflags |= TUNNEL_REC;
  69        if (flags & GRE_VERSION)
  70                tflags |= TUNNEL_VERSION;
  71
  72        return tflags;
  73}
  74
  75static inline __be16 gre_tnl_flags_to_gre_flags(__be16 tflags)
  76{
  77        __be16 flags = 0;
  78
  79        if (tflags & TUNNEL_CSUM)
  80                flags |= GRE_CSUM;
  81        if (tflags & TUNNEL_ROUTING)
  82                flags |= GRE_ROUTING;
  83        if (tflags & TUNNEL_KEY)
  84                flags |= GRE_KEY;
  85        if (tflags & TUNNEL_SEQ)
  86                flags |= GRE_SEQ;
  87        if (tflags & TUNNEL_STRICT)
  88                flags |= GRE_STRICT;
  89        if (tflags & TUNNEL_REC)
  90                flags |= GRE_REC;
  91        if (tflags & TUNNEL_VERSION)
  92                flags |= GRE_VERSION;
  93
  94        return flags;
  95}
  96
  97static inline __sum16 gre_checksum(struct sk_buff *skb)
  98{
  99        __wsum csum;
 100
 101        if (skb->ip_summed == CHECKSUM_PARTIAL)
 102                csum = lco_csum(skb);
 103        else
 104                csum = skb_checksum(skb, 0, skb->len, 0);
 105        return csum_fold(csum);
 106}
 107
 108static inline void gre_build_header(struct sk_buff *skb, int hdr_len,
 109                                    __be16 flags, __be16 proto,
 110                                    __be32 key, __be32 seq)
 111{
 112        struct gre_base_hdr *greh;
 113
 114        skb_push(skb, hdr_len);
 115
 116        skb_set_inner_protocol(skb, proto);
 117        skb_reset_transport_header(skb);
 118        greh = (struct gre_base_hdr *)skb->data;
 119        greh->flags = gre_tnl_flags_to_gre_flags(flags);
 120        greh->protocol = proto;
 121
 122        if (flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) {
 123                __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
 124
 125                if (flags & TUNNEL_SEQ) {
 126                        *ptr = seq;
 127                        ptr--;
 128                }
 129                if (flags & TUNNEL_KEY) {
 130                        *ptr = key;
 131                        ptr--;
 132                }
 133                if (flags & TUNNEL_CSUM &&
 134                    !(skb_shinfo(skb)->gso_type &
 135                      (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) {
 136                        *ptr = 0;
 137                        *(__sum16 *)ptr = gre_checksum(skb);
 138                }
 139        }
 140}
 141
 142#endif
 143