]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
00959ade DK |
2 | #ifndef __LINUX_GRE_H |
3 | #define __LINUX_GRE_H | |
4 | ||
5 | #include <linux/skbuff.h> | |
c5441932 | 6 | #include <net/ip_tunnels.h> |
00959ade | 7 | |
9f57c67c PS |
8 | struct gre_base_hdr { |
9 | __be16 flags; | |
10 | __be16 protocol; | |
ab10dccb GF |
11 | } __packed; |
12 | ||
13 | struct gre_full_hdr { | |
14 | struct gre_base_hdr fixed_header; | |
15 | __be16 csum; | |
16 | __be16 reserved1; | |
17 | __be32 key; | |
18 | __be32 seq; | |
19 | } __packed; | |
9f57c67c PS |
20 | #define GRE_HEADER_SECTION 4 |
21 | ||
00959ade DK |
22 | #define GREPROTO_CISCO 0 |
23 | #define GREPROTO_PPTP 1 | |
24 | #define GREPROTO_MAX 2 | |
bda7bb46 | 25 | #define GRE_IP_PROTO_MAX 2 |
00959ade DK |
26 | |
27 | struct gre_protocol { | |
28 | int (*handler)(struct sk_buff *skb); | |
29 | void (*err_handler)(struct sk_buff *skb, u32 info); | |
30 | }; | |
31 | ||
32 | int gre_add_protocol(const struct gre_protocol *proto, u8 version); | |
33 | int gre_del_protocol(const struct gre_protocol *proto, u8 version); | |
34 | ||
b2acd1dc PS |
35 | struct net_device *gretap_fb_dev_create(struct net *net, const char *name, |
36 | u8 name_assign_type); | |
95f5c64c | 37 | int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, |
e582615a | 38 | bool *csum_err, __be16 proto, int nhs); |
95f5c64c | 39 | |
0621e6fc OS |
40 | static inline bool netif_is_gretap(const struct net_device *dev) |
41 | { | |
42 | return dev->rtnl_link_ops && | |
43 | !strcmp(dev->rtnl_link_ops->kind, "gretap"); | |
44 | } | |
45 | ||
46 | static inline bool netif_is_ip6gretap(const struct net_device *dev) | |
47 | { | |
48 | return dev->rtnl_link_ops && | |
49 | !strcmp(dev->rtnl_link_ops->kind, "ip6gretap"); | |
50 | } | |
d1b2a6c4 | 51 | |
5832c4a7 | 52 | static inline int gre_calc_hlen(const unsigned long *o_flags) |
95f5c64c TH |
53 | { |
54 | int addend = 4; | |
55 | ||
5832c4a7 | 56 | if (test_bit(IP_TUNNEL_CSUM_BIT, o_flags)) |
95f5c64c | 57 | addend += 4; |
5832c4a7 | 58 | if (test_bit(IP_TUNNEL_KEY_BIT, o_flags)) |
95f5c64c | 59 | addend += 4; |
5832c4a7 | 60 | if (test_bit(IP_TUNNEL_SEQ_BIT, o_flags)) |
95f5c64c TH |
61 | addend += 4; |
62 | return addend; | |
63 | } | |
64 | ||
5832c4a7 | 65 | static inline void gre_flags_to_tnl_flags(unsigned long *dst, __be16 flags) |
95f5c64c | 66 | { |
5832c4a7 AL |
67 | IP_TUNNEL_DECLARE_FLAGS(res) = { }; |
68 | ||
69 | __assign_bit(IP_TUNNEL_CSUM_BIT, res, flags & GRE_CSUM); | |
70 | __assign_bit(IP_TUNNEL_ROUTING_BIT, res, flags & GRE_ROUTING); | |
71 | __assign_bit(IP_TUNNEL_KEY_BIT, res, flags & GRE_KEY); | |
72 | __assign_bit(IP_TUNNEL_SEQ_BIT, res, flags & GRE_SEQ); | |
73 | __assign_bit(IP_TUNNEL_STRICT_BIT, res, flags & GRE_STRICT); | |
74 | __assign_bit(IP_TUNNEL_REC_BIT, res, flags & GRE_REC); | |
75 | __assign_bit(IP_TUNNEL_VERSION_BIT, res, flags & GRE_VERSION); | |
76 | ||
77 | ip_tunnel_flags_copy(dst, res); | |
95f5c64c TH |
78 | } |
79 | ||
5832c4a7 | 80 | static inline __be16 gre_tnl_flags_to_gre_flags(const unsigned long *tflags) |
95f5c64c TH |
81 | { |
82 | __be16 flags = 0; | |
83 | ||
5832c4a7 | 84 | if (test_bit(IP_TUNNEL_CSUM_BIT, tflags)) |
95f5c64c | 85 | flags |= GRE_CSUM; |
5832c4a7 | 86 | if (test_bit(IP_TUNNEL_ROUTING_BIT, tflags)) |
95f5c64c | 87 | flags |= GRE_ROUTING; |
5832c4a7 | 88 | if (test_bit(IP_TUNNEL_KEY_BIT, tflags)) |
95f5c64c | 89 | flags |= GRE_KEY; |
5832c4a7 | 90 | if (test_bit(IP_TUNNEL_SEQ_BIT, tflags)) |
95f5c64c | 91 | flags |= GRE_SEQ; |
5832c4a7 | 92 | if (test_bit(IP_TUNNEL_STRICT_BIT, tflags)) |
95f5c64c | 93 | flags |= GRE_STRICT; |
5832c4a7 | 94 | if (test_bit(IP_TUNNEL_REC_BIT, tflags)) |
95f5c64c | 95 | flags |= GRE_REC; |
5832c4a7 | 96 | if (test_bit(IP_TUNNEL_VERSION_BIT, tflags)) |
95f5c64c TH |
97 | flags |= GRE_VERSION; |
98 | ||
99 | return flags; | |
100 | } | |
101 | ||
182a352d | 102 | static inline void gre_build_header(struct sk_buff *skb, int hdr_len, |
5832c4a7 | 103 | const unsigned long *flags, __be16 proto, |
182a352d TH |
104 | __be32 key, __be32 seq) |
105 | { | |
5832c4a7 | 106 | IP_TUNNEL_DECLARE_FLAGS(cond) = { }; |
182a352d TH |
107 | struct gre_base_hdr *greh; |
108 | ||
109 | skb_push(skb, hdr_len); | |
110 | ||
3d7b3320 | 111 | skb_set_inner_protocol(skb, proto); |
182a352d TH |
112 | skb_reset_transport_header(skb); |
113 | greh = (struct gre_base_hdr *)skb->data; | |
114 | greh->flags = gre_tnl_flags_to_gre_flags(flags); | |
115 | greh->protocol = proto; | |
116 | ||
5832c4a7 AL |
117 | __set_bit(IP_TUNNEL_KEY_BIT, cond); |
118 | __set_bit(IP_TUNNEL_CSUM_BIT, cond); | |
119 | __set_bit(IP_TUNNEL_SEQ_BIT, cond); | |
120 | ||
121 | if (ip_tunnel_flags_intersect(flags, cond)) { | |
182a352d TH |
122 | __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4); |
123 | ||
5832c4a7 | 124 | if (test_bit(IP_TUNNEL_SEQ_BIT, flags)) { |
182a352d TH |
125 | *ptr = seq; |
126 | ptr--; | |
127 | } | |
5832c4a7 | 128 | if (test_bit(IP_TUNNEL_KEY_BIT, flags)) { |
182a352d TH |
129 | *ptr = key; |
130 | ptr--; | |
131 | } | |
5832c4a7 | 132 | if (test_bit(IP_TUNNEL_CSUM_BIT, flags) && |
182a352d TH |
133 | !(skb_shinfo(skb)->gso_type & |
134 | (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) { | |
135 | *ptr = 0; | |
efa1a65c XL |
136 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
137 | *(__sum16 *)ptr = csum_fold(lco_csum(skb)); | |
138 | } else { | |
139 | skb->ip_summed = CHECKSUM_PARTIAL; | |
140 | skb->csum_start = skb_transport_header(skb) - skb->head; | |
141 | skb->csum_offset = sizeof(*greh); | |
142 | } | |
182a352d TH |
143 | } |
144 | } | |
145 | } | |
146 | ||
00959ade | 147 | #endif |