Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef __LINUX_GRE_H
0003 #define __LINUX_GRE_H
0004 
0005 #include <linux/skbuff.h>
0006 #include <net/ip_tunnels.h>
0007 
0008 struct gre_base_hdr {
0009     __be16 flags;
0010     __be16 protocol;
0011 } __packed;
0012 
0013 struct gre_full_hdr {
0014     struct gre_base_hdr fixed_header;
0015     __be16 csum;
0016     __be16 reserved1;
0017     __be32 key;
0018     __be32 seq;
0019 } __packed;
0020 #define GRE_HEADER_SECTION 4
0021 
0022 #define GREPROTO_CISCO      0
0023 #define GREPROTO_PPTP       1
0024 #define GREPROTO_MAX        2
0025 #define GRE_IP_PROTO_MAX    2
0026 
0027 struct gre_protocol {
0028     int  (*handler)(struct sk_buff *skb);
0029     void (*err_handler)(struct sk_buff *skb, u32 info);
0030 };
0031 
0032 int gre_add_protocol(const struct gre_protocol *proto, u8 version);
0033 int gre_del_protocol(const struct gre_protocol *proto, u8 version);
0034 
0035 struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
0036                        u8 name_assign_type);
0037 int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
0038              bool *csum_err, __be16 proto, int nhs);
0039 
0040 static inline bool netif_is_gretap(const struct net_device *dev)
0041 {
0042     return dev->rtnl_link_ops &&
0043            !strcmp(dev->rtnl_link_ops->kind, "gretap");
0044 }
0045 
0046 static inline bool netif_is_ip6gretap(const struct net_device *dev)
0047 {
0048     return dev->rtnl_link_ops &&
0049            !strcmp(dev->rtnl_link_ops->kind, "ip6gretap");
0050 }
0051 
0052 static inline int gre_calc_hlen(__be16 o_flags)
0053 {
0054     int addend = 4;
0055 
0056     if (o_flags & TUNNEL_CSUM)
0057         addend += 4;
0058     if (o_flags & TUNNEL_KEY)
0059         addend += 4;
0060     if (o_flags & TUNNEL_SEQ)
0061         addend += 4;
0062     return addend;
0063 }
0064 
0065 static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
0066 {
0067     __be16 tflags = 0;
0068 
0069     if (flags & GRE_CSUM)
0070         tflags |= TUNNEL_CSUM;
0071     if (flags & GRE_ROUTING)
0072         tflags |= TUNNEL_ROUTING;
0073     if (flags & GRE_KEY)
0074         tflags |= TUNNEL_KEY;
0075     if (flags & GRE_SEQ)
0076         tflags |= TUNNEL_SEQ;
0077     if (flags & GRE_STRICT)
0078         tflags |= TUNNEL_STRICT;
0079     if (flags & GRE_REC)
0080         tflags |= TUNNEL_REC;
0081     if (flags & GRE_VERSION)
0082         tflags |= TUNNEL_VERSION;
0083 
0084     return tflags;
0085 }
0086 
0087 static inline __be16 gre_tnl_flags_to_gre_flags(__be16 tflags)
0088 {
0089     __be16 flags = 0;
0090 
0091     if (tflags & TUNNEL_CSUM)
0092         flags |= GRE_CSUM;
0093     if (tflags & TUNNEL_ROUTING)
0094         flags |= GRE_ROUTING;
0095     if (tflags & TUNNEL_KEY)
0096         flags |= GRE_KEY;
0097     if (tflags & TUNNEL_SEQ)
0098         flags |= GRE_SEQ;
0099     if (tflags & TUNNEL_STRICT)
0100         flags |= GRE_STRICT;
0101     if (tflags & TUNNEL_REC)
0102         flags |= GRE_REC;
0103     if (tflags & TUNNEL_VERSION)
0104         flags |= GRE_VERSION;
0105 
0106     return flags;
0107 }
0108 
0109 static inline void gre_build_header(struct sk_buff *skb, int hdr_len,
0110                     __be16 flags, __be16 proto,
0111                     __be32 key, __be32 seq)
0112 {
0113     struct gre_base_hdr *greh;
0114 
0115     skb_push(skb, hdr_len);
0116 
0117     skb_set_inner_protocol(skb, proto);
0118     skb_reset_transport_header(skb);
0119     greh = (struct gre_base_hdr *)skb->data;
0120     greh->flags = gre_tnl_flags_to_gre_flags(flags);
0121     greh->protocol = proto;
0122 
0123     if (flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) {
0124         __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
0125 
0126         if (flags & TUNNEL_SEQ) {
0127             *ptr = seq;
0128             ptr--;
0129         }
0130         if (flags & TUNNEL_KEY) {
0131             *ptr = key;
0132             ptr--;
0133         }
0134         if (flags & TUNNEL_CSUM &&
0135             !(skb_shinfo(skb)->gso_type &
0136               (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) {
0137             *ptr = 0;
0138             if (skb->ip_summed == CHECKSUM_PARTIAL) {
0139                 *(__sum16 *)ptr = csum_fold(lco_csum(skb));
0140             } else {
0141                 skb->ip_summed = CHECKSUM_PARTIAL;
0142                 skb->csum_start = skb_transport_header(skb) - skb->head;
0143                 skb->csum_offset = sizeof(*greh);
0144             }
0145         }
0146     }
0147 }
0148 
0149 #endif