0001
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