blob: 38befe829caf51c56f9661abe71f3dc4a030bd86 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09002 * Linux NET3: GRE over IP protocol decoder.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Joe Perchesafd465032012-03-12 07:03:32 +000013#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14
Randy Dunlap4fc268d2006-01-11 12:17:47 -080015#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/module.h>
17#include <linux/types.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090019#include <linux/slab.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080020#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/skbuff.h>
22#include <linux/netdevice.h>
23#include <linux/in.h>
24#include <linux/tcp.h>
25#include <linux/udp.h>
26#include <linux/if_arp.h>
Pravin B Shelar2e15ea32015-08-07 23:51:42 -070027#include <linux/if_vlan.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/init.h>
29#include <linux/in6.h>
30#include <linux/inetdevice.h>
31#include <linux/igmp.h>
32#include <linux/netfilter_ipv4.h>
Herbert Xue1a80002008-10-09 12:00:17 -070033#include <linux/etherdevice.h>
Kris Katterjohn46f25df2006-01-05 16:35:42 -080034#include <linux/if_ether.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36#include <net/sock.h>
37#include <net/ip.h>
38#include <net/icmp.h>
39#include <net/protocol.h>
Pravin B Shelarc5441932013-03-25 14:49:35 +000040#include <net/ip_tunnels.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <net/arp.h>
42#include <net/checksum.h>
43#include <net/dsfield.h>
44#include <net/inet_ecn.h>
45#include <net/xfrm.h>
Pavel Emelyanov59a4c752008-04-16 01:08:53 -070046#include <net/net_namespace.h>
47#include <net/netns/generic.h>
Herbert Xuc19e6542008-10-09 11:59:55 -070048#include <net/rtnetlink.h>
Dmitry Kozlov00959ad2010-08-21 23:05:39 -070049#include <net/gre.h>
Pravin B Shelar2e15ea32015-08-07 23:51:42 -070050#include <net/dst_metadata.h>
William Tu84e54fe2017-08-22 09:40:28 -070051#include <net/erspan.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
Linus Torvalds1da177e2005-04-16 15:20:36 -070053/*
54 Problems & solutions
55 --------------------
56
57 1. The most important issue is detecting local dead loops.
58 They would cause complete host lockup in transmit, which
59 would be "resolved" by stack overflow or, if queueing is enabled,
60 with infinite looping in net_bh.
61
62 We cannot track such dead loops during route installation,
63 it is infeasible task. The most general solutions would be
64 to keep skb->encapsulation counter (sort of local ttl),
Eric Dumazet6d0722a2010-09-29 23:35:10 -070065 and silently drop packet when it expires. It is a good
stephen hemmingerbff52852012-02-24 08:08:20 +000066 solution, but it supposes maintaining new variable in ALL
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 skb, even if no tunneling is used.
68
Eric Dumazet6d0722a2010-09-29 23:35:10 -070069 Current solution: xmit_recursion breaks dead loops. This is a percpu
70 counter, since when we enter the first ndo_xmit(), cpu migration is
71 forbidden. We force an exit if this counter reaches RECURSION_LIMIT
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73 2. Networking dead loops would not kill routers, but would really
74 kill network. IP hop limit plays role of "t->recursion" in this case,
75 if we copy it from packet being encapsulated to upper header.
76 It is very good solution, but it introduces two problems:
77
78 - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
79 do not work over tunnels.
80 - traceroute does not work. I planned to relay ICMP from tunnel,
81 so that this problem would be solved and traceroute output
82 would even more informative. This idea appeared to be wrong:
83 only Linux complies to rfc1812 now (yes, guys, Linux is the only
84 true router now :-)), all routers (at least, in neighbourhood of mine)
85 return only 8 bytes of payload. It is the end.
86
87 Hence, if we want that OSPF worked or traceroute said something reasonable,
88 we should search for another solution.
89
90 One of them is to parse packet trying to detect inner encapsulation
91 made by our node. It is difficult or even impossible, especially,
stephen hemmingerbff52852012-02-24 08:08:20 +000092 taking into account fragmentation. TO be short, ttl is not solution at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
94 Current solution: The solution was UNEXPECTEDLY SIMPLE.
95 We force DF flag on tunnels with preconfigured hop limit,
96 that is ALL. :-) Well, it does not remove the problem completely,
97 but exponential growth of network traffic is changed to linear
98 (branches, that exceed pmtu are pruned) and tunnel mtu
stephen hemmingerbff52852012-02-24 08:08:20 +000099 rapidly degrades to value <68, where looping stops.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 Yes, it is not good if there exists a router in the loop,
101 which does not force DF, even when encapsulating packets have DF set.
102 But it is not our problem! Nobody could accuse us, we made
103 all that we could make. Even if it is your gated who injected
104 fatal route to network, even if it were you who configured
105 fatal static route: you are innocent. :-)
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 Alexey Kuznetsov.
108 */
109
stephen hemmingereccc1bb2012-09-25 11:02:48 +0000110static bool log_ecn_error = true;
111module_param(log_ecn_error, bool, 0644);
112MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
113
Herbert Xuc19e6542008-10-09 11:59:55 -0700114static struct rtnl_link_ops ipgre_link_ops __read_mostly;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115static int ipgre_tunnel_init(struct net_device *dev);
William Tu1a66a832017-08-25 09:21:28 -0700116static void erspan_build_header(struct sk_buff *skb,
William Tuc69de582018-01-25 13:20:09 -0800117 u32 id, u32 index,
William Tua3222dc2017-11-30 11:51:27 -0800118 bool truncate, bool is_ipv4);
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700119
Alexey Dobriyanc7d03a02016-11-17 04:58:21 +0300120static unsigned int ipgre_net_id __read_mostly;
121static unsigned int gre_tap_net_id __read_mostly;
William Tu84e54fe2017-08-22 09:40:28 -0700122static unsigned int erspan_net_id __read_mostly;
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700123
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700124static void ipgre_err(struct sk_buff *skb, u32 info,
125 const struct tnl_ptk_info *tpi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Pravin B Shelarc5441932013-03-25 14:49:35 +0000128 /* All the routers (except for Linux) return only
129 8 bytes of packet payload. It means, that precise relaying of
130 ICMP in the real Internet is absolutely infeasible.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Pravin B Shelarc5441932013-03-25 14:49:35 +0000132 Moreover, Cisco "wise men" put GRE key to the third word
133 in GRE header. It makes impossible maintaining even soft
134 state for keyed GRE tunnels with enabled checksum. Tell
135 them "thank you".
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
Pravin B Shelarc5441932013-03-25 14:49:35 +0000137 Well, I wonder, rfc1812 was written by Cisco employee,
138 what the hell these idiots break standards established
139 by themselves???
140 */
141 struct net *net = dev_net(skb->dev);
142 struct ip_tunnel_net *itn;
Eric Dumazet96f5a842013-05-18 08:36:03 +0000143 const struct iphdr *iph;
Arnaldo Carvalho de Melo88c76642007-03-13 14:43:18 -0300144 const int type = icmp_hdr(skb)->type;
145 const int code = icmp_hdr(skb)->code;
Eric Dumazet20e19542016-06-18 21:52:06 -0700146 unsigned int data_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 struct ip_tunnel *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 switch (type) {
150 default:
151 case ICMP_PARAMETERPROB:
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700152 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
154 case ICMP_DEST_UNREACH:
155 switch (code) {
156 case ICMP_SR_FAILED:
157 case ICMP_PORT_UNREACH:
158 /* Impossible event. */
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700159 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 default:
161 /* All others are translated to HOST_UNREACH.
162 rfc2003 contains "deep thoughts" about NET_UNREACH,
163 I believe they are just ether pollution. --ANK
164 */
165 break;
166 }
167 break;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 case ICMP_TIME_EXCEEDED:
170 if (code != ICMP_EXC_TTL)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700171 return;
Eric Dumazet20e19542016-06-18 21:52:06 -0700172 data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 break;
David S. Miller55be7a92012-07-11 21:27:49 -0700174
175 case ICMP_REDIRECT:
176 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 }
178
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700179 if (tpi->proto == htons(ETH_P_TEB))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000180 itn = net_generic(net, gre_tap_net_id);
Haishuang Yan51dc63e2018-09-10 22:19:48 +0800181 else if (tpi->proto == htons(ETH_P_ERSPAN) ||
182 tpi->proto == htons(ETH_P_ERSPAN2))
183 itn = net_generic(net, erspan_net_id);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000184 else
185 itn = net_generic(net, ipgre_net_id);
186
Duan Jiongc0c0c502014-01-28 11:49:43 +0800187 iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700188 t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
189 iph->daddr, iph->saddr, tpi->key);
stephen hemmingerd2083282012-09-24 18:12:23 +0000190
Ian Morris51456b22015-04-03 09:17:26 +0100191 if (!t)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700192 return;
David S. Miller36393392012-06-14 22:21:46 -0700193
Eric Dumazet9b8c6d72016-06-18 21:52:05 -0700194#if IS_ENABLED(CONFIG_IPV6)
195 if (tpi->proto == htons(ETH_P_IPV6) &&
Eric Dumazet20e19542016-06-18 21:52:06 -0700196 !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
197 type, data_len))
Eric Dumazet9b8c6d72016-06-18 21:52:05 -0700198 return;
199#endif
200
David S. Miller36393392012-06-14 22:21:46 -0700201 if (t->parms.iph.daddr == 0 ||
Joe Perchesf97c1e02007-12-16 13:45:43 -0800202 ipv4_is_multicast(t->parms.iph.daddr))
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700203 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
205 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700206 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
Wei Yongjunda6185d82009-02-24 23:34:48 -0800208 if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 t->err_count++;
210 else
211 t->err_count = 1;
212 t->err_time = jiffies;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700213}
214
215static void gre_err(struct sk_buff *skb, u32 info)
216{
217 /* All the routers (except for Linux) return only
218 * 8 bytes of packet payload. It means, that precise relaying of
219 * ICMP in the real Internet is absolutely infeasible.
220 *
221 * Moreover, Cisco "wise men" put GRE key to the third word
222 * in GRE header. It makes impossible maintaining even soft
223 * state for keyed
224 * GRE tunnels with enabled checksum. Tell them "thank you".
225 *
226 * Well, I wonder, rfc1812 was written by Cisco employee,
227 * what the hell these idiots break standards established
228 * by themselves???
229 */
230
Eric Dumazete582615ad2016-06-15 06:24:00 -0700231 const struct iphdr *iph = (struct iphdr *)skb->data;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700232 const int type = icmp_hdr(skb)->type;
233 const int code = icmp_hdr(skb)->code;
234 struct tnl_ptk_info tpi;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700235
Haishuang Yanb0350d52018-09-14 12:26:47 +0800236 if (gre_parse_header(skb, &tpi, NULL, htons(ETH_P_IP),
237 iph->ihl * 4) < 0)
238 return;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700239
240 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
241 ipv4_update_pmtu(skb, dev_net(skb->dev), info,
Maciej Żenczykowskid888f392018-09-25 20:56:26 -0700242 skb->dev->ifindex, IPPROTO_GRE);
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700243 return;
244 }
245 if (type == ICMP_REDIRECT) {
Maciej Żenczykowski1042caa2018-09-25 20:56:27 -0700246 ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex,
247 IPPROTO_GRE);
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700248 return;
249 }
250
251 ipgre_err(skb, info, &tpi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252}
253
William Tu84e54fe2017-08-22 09:40:28 -0700254static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
255 int gre_hdr_len)
256{
257 struct net *net = dev_net(skb->dev);
258 struct metadata_dst *tun_dst = NULL;
William Tu1d7e2ed2017-12-13 16:38:55 -0800259 struct erspan_base_hdr *ershdr;
260 struct erspan_metadata *pkt_md;
William Tu84e54fe2017-08-22 09:40:28 -0700261 struct ip_tunnel_net *itn;
262 struct ip_tunnel *tunnel;
William Tu84e54fe2017-08-22 09:40:28 -0700263 const struct iphdr *iph;
William Tu3df192832018-02-05 13:35:34 -0800264 struct erspan_md2 *md2;
William Tu1d7e2ed2017-12-13 16:38:55 -0800265 int ver;
William Tu84e54fe2017-08-22 09:40:28 -0700266 int len;
267
268 itn = net_generic(net, erspan_net_id);
William Tu84e54fe2017-08-22 09:40:28 -0700269 len = gre_hdr_len + sizeof(*ershdr);
270
William Tu1d7e2ed2017-12-13 16:38:55 -0800271 /* Check based hdr len */
William Tu84e54fe2017-08-22 09:40:28 -0700272 if (unlikely(!pskb_may_pull(skb, len)))
Haishuang Yanc05fad52017-12-15 10:46:16 +0800273 return PACKET_REJECT;
William Tu84e54fe2017-08-22 09:40:28 -0700274
275 iph = ip_hdr(skb);
William Tu1d7e2ed2017-12-13 16:38:55 -0800276 ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
William Tuc69de582018-01-25 13:20:09 -0800277 ver = ershdr->ver;
William Tu84e54fe2017-08-22 09:40:28 -0700278
279 /* The original GRE header does not have key field,
280 * Use ERSPAN 10-bit session ID as key.
281 */
William Tuc69de582018-01-25 13:20:09 -0800282 tpi->key = cpu_to_be32(get_session_id(ershdr));
William Tu84e54fe2017-08-22 09:40:28 -0700283 tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
284 tpi->flags | TUNNEL_KEY,
285 iph->saddr, iph->daddr, tpi->key);
286
287 if (tunnel) {
William Tu1d7e2ed2017-12-13 16:38:55 -0800288 len = gre_hdr_len + erspan_hdr_len(ver);
289 if (unlikely(!pskb_may_pull(skb, len)))
William Tuae3e1332017-12-15 14:27:43 -0800290 return PACKET_REJECT;
William Tu1d7e2ed2017-12-13 16:38:55 -0800291
William Tud91e8db52017-12-15 14:27:44 -0800292 ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
293 pkt_md = (struct erspan_metadata *)(ershdr + 1);
294
William Tu84e54fe2017-08-22 09:40:28 -0700295 if (__iptunnel_pull_header(skb,
William Tu1d7e2ed2017-12-13 16:38:55 -0800296 len,
William Tu84e54fe2017-08-22 09:40:28 -0700297 htons(ETH_P_TEB),
298 false, false) < 0)
299 goto drop;
300
William Tu1a66a832017-08-25 09:21:28 -0700301 if (tunnel->collect_md) {
302 struct ip_tunnel_info *info;
303 struct erspan_metadata *md;
304 __be64 tun_id;
305 __be16 flags;
306
307 tpi->flags |= TUNNEL_KEY;
308 flags = tpi->flags;
309 tun_id = key32_to_tunnel_id(tpi->key);
310
311 tun_dst = ip_tun_rx_dst(skb, flags,
312 tun_id, sizeof(*md));
313 if (!tun_dst)
314 return PACKET_REJECT;
315
316 md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
William Tuf551c912017-12-13 16:38:56 -0800317 md->version = ver;
William Tu3df192832018-02-05 13:35:34 -0800318 md2 = &md->u.md2;
319 memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE :
320 ERSPAN_V2_MDSIZE);
William Tuf551c912017-12-13 16:38:56 -0800321
William Tu1a66a832017-08-25 09:21:28 -0700322 info = &tun_dst->u.tun_info;
323 info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
324 info->options_len = sizeof(*md);
William Tu1a66a832017-08-25 09:21:28 -0700325 }
326
William Tu84e54fe2017-08-22 09:40:28 -0700327 skb_reset_mac_header(skb);
328 ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
329 return PACKET_RCVD;
330 }
Haishuang Yan5a645062018-09-10 22:19:47 +0800331 return PACKET_REJECT;
332
William Tu84e54fe2017-08-22 09:40:28 -0700333drop:
334 kfree_skb(skb);
335 return PACKET_RCVD;
336}
337
Jiri Benc125372f2016-05-03 17:10:08 +0200338static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
339 struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700341 struct metadata_dst *tun_dst = NULL;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000342 const struct iphdr *iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 struct ip_tunnel *tunnel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700345 iph = ip_hdr(skb);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700346 tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
347 iph->saddr, iph->daddr, tpi->key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
stephen hemmingerd2083282012-09-24 18:12:23 +0000349 if (tunnel) {
Jiri Benc125372f2016-05-03 17:10:08 +0200350 if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
351 raw_proto, false) < 0)
Jiri Benc244a7972016-05-03 17:10:07 +0200352 goto drop;
353
Jiri Bence271c7b2016-05-11 15:53:57 +0200354 if (tunnel->dev->type != ARPHRD_NONE)
355 skb_pop_mac_header(skb);
356 else
357 skb_reset_mac_header(skb);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700358 if (tunnel->collect_md) {
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700359 __be16 flags;
360 __be64 tun_id;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700361
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700362 flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
Amir Vadaid817f432016-09-08 16:23:45 +0300363 tun_id = key32_to_tunnel_id(tpi->key);
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700364 tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700365 if (!tun_dst)
366 return PACKET_REJECT;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700367 }
368
369 ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700370 return PACKET_RCVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 }
Jiri Benc125372f2016-05-03 17:10:08 +0200372 return PACKET_NEXT;
Jiri Benc244a7972016-05-03 17:10:07 +0200373
374drop:
375 kfree_skb(skb);
376 return PACKET_RCVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377}
378
Jiri Benc125372f2016-05-03 17:10:08 +0200379static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
380 int hdr_len)
381{
382 struct net *net = dev_net(skb->dev);
383 struct ip_tunnel_net *itn;
384 int res;
385
386 if (tpi->proto == htons(ETH_P_TEB))
387 itn = net_generic(net, gre_tap_net_id);
388 else
389 itn = net_generic(net, ipgre_net_id);
390
391 res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
392 if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
393 /* ipgre tunnels in collect metadata mode should receive
394 * also ETH_P_TEB traffic.
395 */
396 itn = net_generic(net, ipgre_net_id);
397 res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
398 }
399 return res;
400}
401
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700402static int gre_rcv(struct sk_buff *skb)
403{
404 struct tnl_ptk_info tpi;
405 bool csum_err = false;
Tom Herbert95f5c642016-04-29 17:12:16 -0700406 int hdr_len;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700407
408#ifdef CONFIG_NET_IPGRE_BROADCAST
409 if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
410 /* Looped back packet, drop it! */
411 if (rt_is_output_route(skb_rtable(skb)))
412 goto drop;
413 }
414#endif
415
Eric Dumazete582615ad2016-06-15 06:24:00 -0700416 hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
Jiri Bencf132ae72016-05-03 15:00:21 +0200417 if (hdr_len < 0)
Tom Herbert95f5c642016-04-29 17:12:16 -0700418 goto drop;
419
William Tuf551c912017-12-13 16:38:56 -0800420 if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
421 tpi.proto == htons(ETH_P_ERSPAN2))) {
William Tu84e54fe2017-08-22 09:40:28 -0700422 if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
423 return 0;
Haishuang Yandd8d5b82017-12-20 10:21:46 +0800424 goto out;
William Tu84e54fe2017-08-22 09:40:28 -0700425 }
426
Jiri Benc244a7972016-05-03 17:10:07 +0200427 if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700428 return 0;
429
Haishuang Yandd8d5b82017-12-20 10:21:46 +0800430out:
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700431 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
432drop:
433 kfree_skb(skb);
434 return 0;
435}
436
Pravin B Shelarc5441932013-03-25 14:49:35 +0000437static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
438 const struct iphdr *tnl_params,
439 __be16 proto)
440{
441 struct ip_tunnel *tunnel = netdev_priv(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000442
Pravin B Shelarc5441932013-03-25 14:49:35 +0000443 if (tunnel->parms.o_flags & TUNNEL_SEQ)
444 tunnel->o_seqno++;
Eric Dumazetcef401d2013-01-25 20:34:37 +0000445
Pravin B Shelarc5441932013-03-25 14:49:35 +0000446 /* Push GRE header. */
Tom Herbert182a3522016-04-29 17:12:19 -0700447 gre_build_header(skb, tunnel->tun_hlen,
448 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
449 htonl(tunnel->o_seqno));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Nicolas Dichtelbf3d6a82013-05-27 23:48:15 +0000451 ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452}
453
Alexander Duyckaed069d2016-04-14 15:33:37 -0400454static int gre_handle_offloads(struct sk_buff *skb, bool csum)
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -0700455{
Edward Cree6fa79662016-02-11 21:02:31 +0000456 return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -0700457}
458
Pravin B Shelarfc4099f2015-10-22 18:17:16 -0700459static struct rtable *gre_get_rt(struct sk_buff *skb,
460 struct net_device *dev,
461 struct flowi4 *fl,
462 const struct ip_tunnel_key *key)
463{
464 struct net *net = dev_net(dev);
465
466 memset(fl, 0, sizeof(*fl));
467 fl->daddr = key->u.ipv4.dst;
468 fl->saddr = key->u.ipv4.src;
469 fl->flowi4_tos = RT_TOS(key->tos);
470 fl->flowi4_mark = skb->mark;
471 fl->flowi4_proto = IPPROTO_GRE;
472
473 return ip_route_output_key(net, fl);
474}
475
William Tu862a03c2017-08-25 09:21:27 -0700476static struct rtable *prepare_fb_xmit(struct sk_buff *skb,
477 struct net_device *dev,
478 struct flowi4 *fl,
479 int tunnel_hlen)
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700480{
481 struct ip_tunnel_info *tun_info;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700482 const struct ip_tunnel_key *key;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100483 struct rtable *rt = NULL;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700484 int min_headroom;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100485 bool use_cache;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700486 int err;
487
Jiri Benc61adedf2015-08-20 13:56:25 +0200488 tun_info = skb_tunnel_info(skb);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700489 key = &tun_info->key;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100490 use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
William Tu862a03c2017-08-25 09:21:27 -0700491
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100492 if (use_cache)
William Tu862a03c2017-08-25 09:21:27 -0700493 rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl->saddr);
Paolo Abeni3c1cb4d22016-02-12 15:43:59 +0100494 if (!rt) {
William Tu862a03c2017-08-25 09:21:27 -0700495 rt = gre_get_rt(skb, dev, fl, key);
Paolo Abeni3c1cb4d22016-02-12 15:43:59 +0100496 if (IS_ERR(rt))
William Tu862a03c2017-08-25 09:21:27 -0700497 goto err_free_skb;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100498 if (use_cache)
Paolo Abeni3c1cb4d22016-02-12 15:43:59 +0100499 dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
William Tu862a03c2017-08-25 09:21:27 -0700500 fl->saddr);
Paolo Abeni3c1cb4d22016-02-12 15:43:59 +0100501 }
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700502
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700503 min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
504 + tunnel_hlen + sizeof(struct iphdr);
505 if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
506 int head_delta = SKB_DATA_ALIGN(min_headroom -
507 skb_headroom(skb) +
508 16);
509 err = pskb_expand_head(skb, max_t(int, head_delta, 0),
510 0, GFP_ATOMIC);
511 if (unlikely(err))
512 goto err_free_rt;
513 }
William Tu862a03c2017-08-25 09:21:27 -0700514 return rt;
515
516err_free_rt:
517 ip_rt_put(rt);
518err_free_skb:
519 kfree_skb(skb);
520 dev->stats.tx_dropped++;
521 return NULL;
522}
523
524static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
525 __be16 proto)
526{
William Tu77a51962018-03-01 13:49:57 -0800527 struct ip_tunnel *tunnel = netdev_priv(dev);
William Tu862a03c2017-08-25 09:21:27 -0700528 struct ip_tunnel_info *tun_info;
529 const struct ip_tunnel_key *key;
530 struct rtable *rt = NULL;
531 struct flowi4 fl;
532 int tunnel_hlen;
533 __be16 df, flags;
534
535 tun_info = skb_tunnel_info(skb);
536 if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
537 ip_tunnel_info_af(tun_info) != AF_INET))
538 goto err_free_skb;
539
540 key = &tun_info->key;
541 tunnel_hlen = gre_calc_hlen(key->tun_flags);
542
543 rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
544 if (!rt)
545 return;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700546
547 /* Push Tunnel header. */
Alexander Duyckaed069d2016-04-14 15:33:37 -0400548 if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700549 goto err_free_rt;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700550
William Tu77a51962018-03-01 13:49:57 -0800551 flags = tun_info->key.tun_flags &
552 (TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ);
David S. Millercba653212016-05-04 00:52:29 -0400553 gre_build_header(skb, tunnel_hlen, flags, proto,
William Tu77a51962018-03-01 13:49:57 -0800554 tunnel_id_to_key32(tun_info->key.tun_id),
Colin Ian King15746392018-03-21 19:34:58 +0000555 (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) : 0);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700556
557 df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
Pravin B Shelar039f5062015-12-24 14:34:54 -0800558
559 iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
560 key->tos, key->ttl, df, false);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700561 return;
562
563err_free_rt:
564 ip_rt_put(rt);
565err_free_skb:
566 kfree_skb(skb);
567 dev->stats.tx_dropped++;
568}
569
William Tu1a66a832017-08-25 09:21:28 -0700570static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
571 __be16 proto)
572{
573 struct ip_tunnel *tunnel = netdev_priv(dev);
574 struct ip_tunnel_info *tun_info;
575 const struct ip_tunnel_key *key;
576 struct erspan_metadata *md;
577 struct rtable *rt = NULL;
578 bool truncate = false;
579 struct flowi4 fl;
580 int tunnel_hlen;
William Tuf551c912017-12-13 16:38:56 -0800581 int version;
William Tu1a66a832017-08-25 09:21:28 -0700582 __be16 df;
William Tu1baf5eb2018-04-27 14:16:32 -0700583 int nhoff;
William Tud5db21a2018-05-11 05:49:47 -0700584 int thoff;
William Tu1a66a832017-08-25 09:21:28 -0700585
586 tun_info = skb_tunnel_info(skb);
587 if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
588 ip_tunnel_info_af(tun_info) != AF_INET))
589 goto err_free_skb;
590
591 key = &tun_info->key;
Pieter Jansen van Vuuren256c87c2018-06-26 21:39:36 -0700592 if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
593 goto err_free_rt;
William Tuf551c912017-12-13 16:38:56 -0800594 md = ip_tunnel_info_opts(tun_info);
595 if (!md)
596 goto err_free_rt;
William Tu1a66a832017-08-25 09:21:28 -0700597
598 /* ERSPAN has fixed 8 byte GRE header */
William Tuf551c912017-12-13 16:38:56 -0800599 version = md->version;
600 tunnel_hlen = 8 + erspan_hdr_len(version);
William Tu1a66a832017-08-25 09:21:28 -0700601
602 rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
603 if (!rt)
604 return;
605
606 if (gre_handle_offloads(skb, false))
607 goto err_free_rt;
608
William Tuf1929702017-10-05 12:07:12 -0700609 if (skb->len > dev->mtu + dev->hard_header_len) {
610 pskb_trim(skb, dev->mtu + dev->hard_header_len);
William Tu1a66a832017-08-25 09:21:28 -0700611 truncate = true;
612 }
613
William Tu1baf5eb2018-04-27 14:16:32 -0700614 nhoff = skb_network_header(skb) - skb_mac_header(skb);
615 if (skb->protocol == htons(ETH_P_IP) &&
616 (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
617 truncate = true;
618
William Tud5db21a2018-05-11 05:49:47 -0700619 thoff = skb_transport_header(skb) - skb_mac_header(skb);
620 if (skb->protocol == htons(ETH_P_IPV6) &&
621 (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff))
622 truncate = true;
623
William Tuf551c912017-12-13 16:38:56 -0800624 if (version == 1) {
William Tuc69de582018-01-25 13:20:09 -0800625 erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
William Tuf551c912017-12-13 16:38:56 -0800626 ntohl(md->u.index), truncate, true);
627 } else if (version == 2) {
William Tuc69de582018-01-25 13:20:09 -0800628 erspan_build_header_v2(skb,
629 ntohl(tunnel_id_to_key32(key->tun_id)),
630 md->u.md2.dir,
631 get_hwid(&md->u.md2),
632 truncate, true);
William Tuf551c912017-12-13 16:38:56 -0800633 } else {
634 goto err_free_rt;
635 }
William Tu1a66a832017-08-25 09:21:28 -0700636
637 gre_build_header(skb, 8, TUNNEL_SEQ,
638 htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
639
640 df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
641
642 iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
643 key->tos, key->ttl, df, false);
644 return;
645
646err_free_rt:
647 ip_rt_put(rt);
648err_free_skb:
649 kfree_skb(skb);
650 dev->stats.tx_dropped++;
651}
652
Pravin B Shelarfc4099f2015-10-22 18:17:16 -0700653static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
654{
655 struct ip_tunnel_info *info = skb_tunnel_info(skb);
656 struct rtable *rt;
657 struct flowi4 fl4;
658
659 if (ip_tunnel_info_af(info) != AF_INET)
660 return -EINVAL;
661
662 rt = gre_get_rt(skb, dev, &fl4, &info->key);
663 if (IS_ERR(rt))
664 return PTR_ERR(rt);
665
666 ip_rt_put(rt);
667 info->key.u.ipv4.src = fl4.saddr;
668 return 0;
669}
670
Pravin B Shelarc5441932013-03-25 14:49:35 +0000671static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
672 struct net_device *dev)
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800673{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000674 struct ip_tunnel *tunnel = netdev_priv(dev);
675 const struct iphdr *tnl_params;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800676
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700677 if (tunnel->collect_md) {
Jiri Benc20907142016-04-27 11:29:07 +0200678 gre_fb_xmit(skb, dev, skb->protocol);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700679 return NETDEV_TX_OK;
680 }
681
Pravin B Shelarc5441932013-03-25 14:49:35 +0000682 if (dev->header_ops) {
683 /* Need space for new headers */
684 if (skb_cow_head(skb, dev->needed_headroom -
Chen Gang2bac7cb2013-04-22 20:45:42 +0000685 (tunnel->hlen + sizeof(struct iphdr))))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000686 goto free_skb;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800687
Pravin B Shelarc5441932013-03-25 14:49:35 +0000688 tnl_params = (const struct iphdr *)skb->data;
Eric Dumazete985aad2010-09-27 03:57:11 +0000689
Pravin B Shelarc5441932013-03-25 14:49:35 +0000690 /* Pull skb since ip_tunnel_xmit() needs skb->data pointing
691 * to gre header.
692 */
693 skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
Timo Teräs8a0033a2014-12-15 09:24:13 +0200694 skb_reset_mac_header(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000695 } else {
696 if (skb_cow_head(skb, dev->needed_headroom))
697 goto free_skb;
Herbert Xue1a80002008-10-09 12:00:17 -0700698
Pravin B Shelarc5441932013-03-25 14:49:35 +0000699 tnl_params = &tunnel->parms.iph;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800700 }
701
Alexander Duyckaed069d2016-04-14 15:33:37 -0400702 if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
703 goto free_skb;
Timo Teräs8a0033a2014-12-15 09:24:13 +0200704
Pravin B Shelarc5441932013-03-25 14:49:35 +0000705 __gre_xmit(skb, dev, tnl_params, skb->protocol);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000706 return NETDEV_TX_OK;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800707
Pravin B Shelarc5441932013-03-25 14:49:35 +0000708free_skb:
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800709 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000710 dev->stats.tx_dropped++;
711 return NETDEV_TX_OK;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800712}
713
William Tu84e54fe2017-08-22 09:40:28 -0700714static netdev_tx_t erspan_xmit(struct sk_buff *skb,
715 struct net_device *dev)
716{
717 struct ip_tunnel *tunnel = netdev_priv(dev);
718 bool truncate = false;
719
William Tu1a66a832017-08-25 09:21:28 -0700720 if (tunnel->collect_md) {
721 erspan_fb_xmit(skb, dev, skb->protocol);
722 return NETDEV_TX_OK;
723 }
724
William Tu84e54fe2017-08-22 09:40:28 -0700725 if (gre_handle_offloads(skb, false))
726 goto free_skb;
727
728 if (skb_cow_head(skb, dev->needed_headroom))
729 goto free_skb;
730
William Tuf1929702017-10-05 12:07:12 -0700731 if (skb->len > dev->mtu + dev->hard_header_len) {
732 pskb_trim(skb, dev->mtu + dev->hard_header_len);
William Tu84e54fe2017-08-22 09:40:28 -0700733 truncate = true;
734 }
735
736 /* Push ERSPAN header */
William Tuf551c912017-12-13 16:38:56 -0800737 if (tunnel->erspan_ver == 1)
William Tuc69de582018-01-25 13:20:09 -0800738 erspan_build_header(skb, ntohl(tunnel->parms.o_key),
739 tunnel->index,
William Tuf551c912017-12-13 16:38:56 -0800740 truncate, true);
William Tu02f99df2018-05-16 17:24:32 -0700741 else if (tunnel->erspan_ver == 2)
William Tuc69de582018-01-25 13:20:09 -0800742 erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
William Tuf551c912017-12-13 16:38:56 -0800743 tunnel->dir, tunnel->hwid,
744 truncate, true);
William Tu02f99df2018-05-16 17:24:32 -0700745 else
746 goto free_skb;
William Tuf551c912017-12-13 16:38:56 -0800747
William Tu84e54fe2017-08-22 09:40:28 -0700748 tunnel->parms.o_flags &= ~TUNNEL_KEY;
749 __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
750 return NETDEV_TX_OK;
751
752free_skb:
753 kfree_skb(skb);
754 dev->stats.tx_dropped++;
755 return NETDEV_TX_OK;
756}
757
Pravin B Shelarc5441932013-03-25 14:49:35 +0000758static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
759 struct net_device *dev)
760{
761 struct ip_tunnel *tunnel = netdev_priv(dev);
762
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700763 if (tunnel->collect_md) {
Jiri Benc20907142016-04-27 11:29:07 +0200764 gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700765 return NETDEV_TX_OK;
766 }
767
Alexander Duyckaed069d2016-04-14 15:33:37 -0400768 if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
769 goto free_skb;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000770
771 if (skb_cow_head(skb, dev->needed_headroom))
772 goto free_skb;
773
774 __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
Pravin B Shelarc5441932013-03-25 14:49:35 +0000775 return NETDEV_TX_OK;
776
777free_skb:
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800778 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000779 dev->stats.tx_dropped++;
780 return NETDEV_TX_OK;
781}
782
Xin Longdd9d5982017-11-07 16:33:08 +0800783static void ipgre_link_update(struct net_device *dev, bool set_mtu)
784{
785 struct ip_tunnel *tunnel = netdev_priv(dev);
786 int len;
787
788 len = tunnel->tun_hlen;
789 tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
790 len = tunnel->tun_hlen - len;
791 tunnel->hlen = tunnel->hlen + len;
792
793 dev->needed_headroom = dev->needed_headroom + len;
794 if (set_mtu)
795 dev->mtu = max_t(int, dev->mtu - len, 68);
796
797 if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
798 if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
799 tunnel->encap.type == TUNNEL_ENCAP_NONE) {
800 dev->features |= NETIF_F_GSO_SOFTWARE;
801 dev->hw_features |= NETIF_F_GSO_SOFTWARE;
Sabrina Dubroca1cc59542018-04-10 12:57:18 +0200802 } else {
803 dev->features &= ~NETIF_F_GSO_SOFTWARE;
804 dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
Xin Longdd9d5982017-11-07 16:33:08 +0800805 }
806 dev->features |= NETIF_F_LLTX;
Sabrina Dubroca1cc59542018-04-10 12:57:18 +0200807 } else {
808 dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
809 dev->features &= ~(NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE);
Xin Longdd9d5982017-11-07 16:33:08 +0800810 }
811}
812
Pravin B Shelarc5441932013-03-25 14:49:35 +0000813static int ipgre_tunnel_ioctl(struct net_device *dev,
814 struct ifreq *ifr, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 struct ip_tunnel_parm p;
Xin Longa0efab62017-11-07 16:33:09 +0800817 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
Pravin B Shelarc5441932013-03-25 14:49:35 +0000819 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
820 return -EFAULT;
Xin Longa0efab62017-11-07 16:33:09 +0800821
Cong Wang6c734fb2013-06-29 12:02:59 +0800822 if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
823 if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
Xin Longa0efab62017-11-07 16:33:09 +0800824 p.iph.ihl != 5 || (p.iph.frag_off & htons(~IP_DF)) ||
825 ((p.i_flags | p.o_flags) & (GRE_VERSION | GRE_ROUTING)))
Cong Wang6c734fb2013-06-29 12:02:59 +0800826 return -EINVAL;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000827 }
Xin Longa0efab62017-11-07 16:33:09 +0800828
Pravin B Shelarc5441932013-03-25 14:49:35 +0000829 p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
830 p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
831
832 err = ip_tunnel_ioctl(dev, &p, cmd);
833 if (err)
834 return err;
835
Xin Longa0efab62017-11-07 16:33:09 +0800836 if (cmd == SIOCCHGTUNNEL) {
837 struct ip_tunnel *t = netdev_priv(dev);
838
839 t->parms.i_flags = p.i_flags;
840 t->parms.o_flags = p.o_flags;
841
842 if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
843 ipgre_link_update(dev, true);
844 }
845
Tom Herbert95f5c642016-04-29 17:12:16 -0700846 p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
847 p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000848
849 if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
850 return -EFAULT;
Xin Longa0efab62017-11-07 16:33:09 +0800851
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 return 0;
853}
854
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855/* Nice toy. Unfortunately, useless in real life :-)
856 It allows to construct virtual multiprotocol broadcast "LAN"
857 over the Internet, provided multicast routing is tuned.
858
859
860 I have no idea was this bicycle invented before me,
861 so that I had to set ARPHRD_IPGRE to a random value.
862 I have an impression, that Cisco could make something similar,
863 but this feature is apparently missing in IOS<=11.2(8).
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900864
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
866 with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
867
868 ping -t 255 224.66.66.66
869
870 If nobody answers, mbone does not work.
871
872 ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
873 ip addr add 10.66.66.<somewhat>/24 dev Universe
874 ifconfig Universe up
875 ifconfig Universe add fe80::<Your_real_addr>/10
876 ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
877 ftp 10.66.66.66
878 ...
879 ftp fec0:6666:6666::193.233.7.65
880 ...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 */
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700882static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
883 unsigned short type,
Eric Dumazet15078502010-09-15 11:07:53 +0000884 const void *daddr, const void *saddr, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885{
Patrick McHardy2941a482006-01-08 22:05:26 -0800886 struct ip_tunnel *t = netdev_priv(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000887 struct iphdr *iph;
888 struct gre_base_hdr *greh;
889
Johannes Bergd58ff352017-06-16 14:29:23 +0200890 iph = skb_push(skb, t->hlen + sizeof(*iph));
Pravin B Shelarc5441932013-03-25 14:49:35 +0000891 greh = (struct gre_base_hdr *)(iph+1);
Tom Herbert95f5c642016-04-29 17:12:16 -0700892 greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000893 greh->protocol = htons(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894
895 memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
Pravin B Shelarc5441932013-03-25 14:49:35 +0000897 /* Set the source hardware address. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 if (saddr)
899 memcpy(&iph->saddr, saddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +0000900 if (daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 memcpy(&iph->daddr, daddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +0000902 if (iph->daddr)
Timo Teräs77a482b2013-08-06 13:45:43 +0300903 return t->hlen + sizeof(*iph);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900904
Pravin B Shelarc5441932013-03-25 14:49:35 +0000905 return -(t->hlen + sizeof(*iph));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906}
907
Timo Teras6a5f44d2007-10-23 20:31:53 -0700908static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
909{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000910 const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
Timo Teras6a5f44d2007-10-23 20:31:53 -0700911 memcpy(haddr, &iph->saddr, 4);
912 return 4;
913}
914
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700915static const struct header_ops ipgre_header_ops = {
916 .create = ipgre_header,
Timo Teras6a5f44d2007-10-23 20:31:53 -0700917 .parse = ipgre_header_parse,
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700918};
919
Timo Teras6a5f44d2007-10-23 20:31:53 -0700920#ifdef CONFIG_NET_IPGRE_BROADCAST
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921static int ipgre_open(struct net_device *dev)
922{
Patrick McHardy2941a482006-01-08 22:05:26 -0800923 struct ip_tunnel *t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
Joe Perchesf97c1e02007-12-16 13:45:43 -0800925 if (ipv4_is_multicast(t->parms.iph.daddr)) {
David S. Millercbb1e852011-05-04 12:33:34 -0700926 struct flowi4 fl4;
927 struct rtable *rt;
Eric Dumazete985aad2010-09-27 03:57:11 +0000928
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200929 rt = ip_route_output_gre(t->net, &fl4,
David S. Millercbb1e852011-05-04 12:33:34 -0700930 t->parms.iph.daddr,
931 t->parms.iph.saddr,
932 t->parms.o_key,
933 RT_TOS(t->parms.iph.tos),
934 t->parms.link);
David S. Millerb23dd4f2011-03-02 14:31:35 -0800935 if (IS_ERR(rt))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 return -EADDRNOTAVAIL;
Changli Gaod8d1f302010-06-10 23:31:35 -0700937 dev = rt->dst.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 ip_rt_put(rt);
Ian Morris51456b22015-04-03 09:17:26 +0100939 if (!__in_dev_get_rtnl(dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 return -EADDRNOTAVAIL;
941 t->mlink = dev->ifindex;
Herbert Xue5ed6392005-10-03 14:35:55 -0700942 ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 }
944 return 0;
945}
946
947static int ipgre_close(struct net_device *dev)
948{
Patrick McHardy2941a482006-01-08 22:05:26 -0800949 struct ip_tunnel *t = netdev_priv(dev);
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800950
Joe Perchesf97c1e02007-12-16 13:45:43 -0800951 if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
Denis V. Lunev7fee0ca2008-01-21 17:32:38 -0800952 struct in_device *in_dev;
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200953 in_dev = inetdev_by_index(t->net, t->mlink);
Eric Dumazet8723e1b2010-10-19 00:39:26 +0000954 if (in_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 ip_mc_dec_group(in_dev, t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 }
957 return 0;
958}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959#endif
960
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800961static const struct net_device_ops ipgre_netdev_ops = {
962 .ndo_init = ipgre_tunnel_init,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000963 .ndo_uninit = ip_tunnel_uninit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800964#ifdef CONFIG_NET_IPGRE_BROADCAST
965 .ndo_open = ipgre_open,
966 .ndo_stop = ipgre_close,
967#endif
Pravin B Shelarc5441932013-03-25 14:49:35 +0000968 .ndo_start_xmit = ipgre_xmit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800969 .ndo_do_ioctl = ipgre_tunnel_ioctl,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000970 .ndo_change_mtu = ip_tunnel_change_mtu,
971 .ndo_get_stats64 = ip_tunnel_get_stats64,
Nicolas Dichtel1e995842015-04-02 17:07:02 +0200972 .ndo_get_iflink = ip_tunnel_get_iflink,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800973};
974
Eric Dumazet6b78f162012-09-13 21:25:33 +0000975#define GRE_FEATURES (NETIF_F_SG | \
976 NETIF_F_FRAGLIST | \
977 NETIF_F_HIGHDMA | \
978 NETIF_F_HW_CSUM)
979
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980static void ipgre_tunnel_setup(struct net_device *dev)
981{
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800982 dev->netdev_ops = &ipgre_netdev_ops;
Nicolas Dichtel5a455272014-04-11 15:51:18 +0200983 dev->type = ARPHRD_IPGRE;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000984 ip_tunnel_setup(dev, ipgre_net_id);
985}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
Pravin B Shelarc5441932013-03-25 14:49:35 +0000987static void __gre_tunnel_init(struct net_device *dev)
988{
989 struct ip_tunnel *tunnel;
990
991 tunnel = netdev_priv(dev);
Tom Herbert95f5c642016-04-29 17:12:16 -0700992 tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000993 tunnel->parms.iph.protocol = IPPROTO_GRE;
994
Tom Herbert4565e992014-09-17 12:26:01 -0700995 tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
996
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200997 dev->features |= GRE_FEATURES;
Eric Dumazet6b78f162012-09-13 21:25:33 +0000998 dev->hw_features |= GRE_FEATURES;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000999
1000 if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
Alexander Duycka0ca1532016-04-05 09:13:39 -07001001 /* TCP offload with GRE SEQ is not supported, nor
1002 * can we support 2 levels of outer headers requiring
1003 * an update.
1004 */
1005 if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
1006 (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
1007 dev->features |= NETIF_F_GSO_SOFTWARE;
1008 dev->hw_features |= NETIF_F_GSO_SOFTWARE;
1009 }
1010
Pravin B Shelarc5441932013-03-25 14:49:35 +00001011 /* Can use a lockless transmit, unless we generate
1012 * output sequences
1013 */
1014 dev->features |= NETIF_F_LLTX;
1015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016}
1017
1018static int ipgre_tunnel_init(struct net_device *dev)
1019{
Pravin B Shelarc5441932013-03-25 14:49:35 +00001020 struct ip_tunnel *tunnel = netdev_priv(dev);
1021 struct iphdr *iph = &tunnel->parms.iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Pravin B Shelarc5441932013-03-25 14:49:35 +00001023 __gre_tunnel_init(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024
Pravin B Shelarc5441932013-03-25 14:49:35 +00001025 memcpy(dev->dev_addr, &iph->saddr, 4);
1026 memcpy(dev->broadcast, &iph->daddr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
Pravin B Shelarc5441932013-03-25 14:49:35 +00001028 dev->flags = IFF_NOARP;
Eric Dumazet02875872014-10-05 18:38:35 -07001029 netif_keep_dst(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001030 dev->addr_len = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031
Jiri Benca64b04d2016-04-27 11:29:06 +02001032 if (iph->daddr && !tunnel->collect_md) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033#ifdef CONFIG_NET_IPGRE_BROADCAST
Joe Perchesf97c1e02007-12-16 13:45:43 -08001034 if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (!iph->saddr)
1036 return -EINVAL;
1037 dev->flags = IFF_BROADCAST;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001038 dev->header_ops = &ipgre_header_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 }
1040#endif
Jiri Benca64b04d2016-04-27 11:29:06 +02001041 } else if (!tunnel->collect_md) {
Timo Teras6a5f44d2007-10-23 20:31:53 -07001042 dev->header_ops = &ipgre_header_ops;
Jiri Benca64b04d2016-04-27 11:29:06 +02001043 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
Pravin B Shelarc5441932013-03-25 14:49:35 +00001045 return ip_tunnel_init(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046}
1047
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001048static const struct gre_protocol ipgre_protocol = {
1049 .handler = gre_rcv,
1050 .err_handler = gre_err,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051};
1052
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001053static int __net_init ipgre_init_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001054{
Pravin B Shelarc5441932013-03-25 14:49:35 +00001055 return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001056}
1057
Eric Dumazet64bc1782017-09-19 16:27:09 -07001058static void __net_exit ipgre_exit_batch_net(struct list_head *list_net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001059{
Eric Dumazet64bc1782017-09-19 16:27:09 -07001060 ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001061}
1062
1063static struct pernet_operations ipgre_net_ops = {
1064 .init = ipgre_init_net,
Eric Dumazet64bc1782017-09-19 16:27:09 -07001065 .exit_batch = ipgre_exit_batch_net,
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001066 .id = &ipgre_net_id,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001067 .size = sizeof(struct ip_tunnel_net),
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001068};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Matthias Schiffera8b8a8892017-06-25 23:56:01 +02001070static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
1071 struct netlink_ext_ack *extack)
Herbert Xuc19e6542008-10-09 11:59:55 -07001072{
1073 __be16 flags;
1074
1075 if (!data)
1076 return 0;
1077
1078 flags = 0;
1079 if (data[IFLA_GRE_IFLAGS])
1080 flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1081 if (data[IFLA_GRE_OFLAGS])
1082 flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1083 if (flags & (GRE_VERSION|GRE_ROUTING))
1084 return -EINVAL;
1085
Jiri Benc946b6362016-04-27 14:08:01 +02001086 if (data[IFLA_GRE_COLLECT_METADATA] &&
1087 data[IFLA_GRE_ENCAP_TYPE] &&
1088 nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
1089 return -EINVAL;
1090
Herbert Xuc19e6542008-10-09 11:59:55 -07001091 return 0;
1092}
1093
Matthias Schiffera8b8a8892017-06-25 23:56:01 +02001094static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
1095 struct netlink_ext_ack *extack)
Herbert Xue1a80002008-10-09 12:00:17 -07001096{
1097 __be32 daddr;
1098
1099 if (tb[IFLA_ADDRESS]) {
1100 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1101 return -EINVAL;
1102 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1103 return -EADDRNOTAVAIL;
1104 }
1105
1106 if (!data)
1107 goto out;
1108
1109 if (data[IFLA_GRE_REMOTE]) {
1110 memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1111 if (!daddr)
1112 return -EINVAL;
1113 }
1114
1115out:
Matthias Schiffera8b8a8892017-06-25 23:56:01 +02001116 return ipgre_tunnel_validate(tb, data, extack);
Herbert Xue1a80002008-10-09 12:00:17 -07001117}
1118
William Tu84e54fe2017-08-22 09:40:28 -07001119static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
1120 struct netlink_ext_ack *extack)
1121{
1122 __be16 flags = 0;
1123 int ret;
1124
1125 if (!data)
1126 return 0;
1127
1128 ret = ipgre_tap_validate(tb, data, extack);
1129 if (ret)
1130 return ret;
1131
1132 /* ERSPAN should only have GRE sequence and key flag */
William Tu1a66a832017-08-25 09:21:28 -07001133 if (data[IFLA_GRE_OFLAGS])
1134 flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1135 if (data[IFLA_GRE_IFLAGS])
1136 flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1137 if (!data[IFLA_GRE_COLLECT_METADATA] &&
1138 flags != (GRE_SEQ | GRE_KEY))
William Tu84e54fe2017-08-22 09:40:28 -07001139 return -EINVAL;
1140
1141 /* ERSPAN Session ID only has 10-bit. Since we reuse
1142 * 32-bit key field as ID, check it's range.
1143 */
1144 if (data[IFLA_GRE_IKEY] &&
1145 (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
1146 return -EINVAL;
1147
1148 if (data[IFLA_GRE_OKEY] &&
1149 (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
1150 return -EINVAL;
1151
1152 return 0;
1153}
1154
Philip Prindeville22a59be2016-06-14 15:53:02 -06001155static int ipgre_netlink_parms(struct net_device *dev,
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001156 struct nlattr *data[],
1157 struct nlattr *tb[],
Craig Gallek9830ad42017-04-19 12:30:54 -04001158 struct ip_tunnel_parm *parms,
1159 __u32 *fwmark)
Herbert Xuc19e6542008-10-09 11:59:55 -07001160{
Philip Prindeville22a59be2016-06-14 15:53:02 -06001161 struct ip_tunnel *t = netdev_priv(dev);
1162
Herbert Xu7bb82d92008-10-11 12:20:15 -07001163 memset(parms, 0, sizeof(*parms));
Herbert Xuc19e6542008-10-09 11:59:55 -07001164
1165 parms->iph.protocol = IPPROTO_GRE;
1166
1167 if (!data)
Philip Prindeville22a59be2016-06-14 15:53:02 -06001168 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -07001169
1170 if (data[IFLA_GRE_LINK])
1171 parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1172
1173 if (data[IFLA_GRE_IFLAGS])
Pravin B Shelarc5441932013-03-25 14:49:35 +00001174 parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
Herbert Xuc19e6542008-10-09 11:59:55 -07001175
1176 if (data[IFLA_GRE_OFLAGS])
Pravin B Shelarc5441932013-03-25 14:49:35 +00001177 parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
Herbert Xuc19e6542008-10-09 11:59:55 -07001178
1179 if (data[IFLA_GRE_IKEY])
1180 parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1181
1182 if (data[IFLA_GRE_OKEY])
1183 parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1184
1185 if (data[IFLA_GRE_LOCAL])
Jiri Benc67b61f62015-03-29 16:59:26 +02001186 parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
Herbert Xuc19e6542008-10-09 11:59:55 -07001187
1188 if (data[IFLA_GRE_REMOTE])
Jiri Benc67b61f62015-03-29 16:59:26 +02001189 parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
Herbert Xuc19e6542008-10-09 11:59:55 -07001190
1191 if (data[IFLA_GRE_TTL])
1192 parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1193
1194 if (data[IFLA_GRE_TOS])
1195 parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1196
Philip Prindeville22a59be2016-06-14 15:53:02 -06001197 if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
1198 if (t->ignore_df)
1199 return -EINVAL;
Herbert Xuc19e6542008-10-09 11:59:55 -07001200 parms->iph.frag_off = htons(IP_DF);
Philip Prindeville22a59be2016-06-14 15:53:02 -06001201 }
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001202
1203 if (data[IFLA_GRE_COLLECT_METADATA]) {
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001204 t->collect_md = true;
Jiri Bence271c7b2016-05-11 15:53:57 +02001205 if (dev->type == ARPHRD_IPGRE)
1206 dev->type = ARPHRD_NONE;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001207 }
Philip Prindeville22a59be2016-06-14 15:53:02 -06001208
1209 if (data[IFLA_GRE_IGNORE_DF]) {
1210 if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
1211 && (parms->iph.frag_off & htons(IP_DF)))
1212 return -EINVAL;
1213 t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
1214 }
1215
Craig Gallek9830ad42017-04-19 12:30:54 -04001216 if (data[IFLA_GRE_FWMARK])
1217 *fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
1218
William Tuf551c912017-12-13 16:38:56 -08001219 if (data[IFLA_GRE_ERSPAN_VER]) {
1220 t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
William Tu84e54fe2017-08-22 09:40:28 -07001221
William Tuf551c912017-12-13 16:38:56 -08001222 if (t->erspan_ver != 1 && t->erspan_ver != 2)
William Tu84e54fe2017-08-22 09:40:28 -07001223 return -EINVAL;
1224 }
1225
William Tuf551c912017-12-13 16:38:56 -08001226 if (t->erspan_ver == 1) {
1227 if (data[IFLA_GRE_ERSPAN_INDEX]) {
1228 t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
1229 if (t->index & ~INDEX_MASK)
1230 return -EINVAL;
1231 }
1232 } else if (t->erspan_ver == 2) {
1233 if (data[IFLA_GRE_ERSPAN_DIR]) {
1234 t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
1235 if (t->dir & ~(DIR_MASK >> DIR_OFFSET))
1236 return -EINVAL;
1237 }
1238 if (data[IFLA_GRE_ERSPAN_HWID]) {
1239 t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
1240 if (t->hwid & ~(HWID_MASK >> HWID_OFFSET))
1241 return -EINVAL;
1242 }
1243 }
1244
Philip Prindeville22a59be2016-06-14 15:53:02 -06001245 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -07001246}
1247
Tom Herbert4565e992014-09-17 12:26:01 -07001248/* This function returns true when ENCAP attributes are present in the nl msg */
1249static bool ipgre_netlink_encap_parms(struct nlattr *data[],
1250 struct ip_tunnel_encap *ipencap)
1251{
1252 bool ret = false;
1253
1254 memset(ipencap, 0, sizeof(*ipencap));
1255
1256 if (!data)
1257 return ret;
1258
1259 if (data[IFLA_GRE_ENCAP_TYPE]) {
1260 ret = true;
1261 ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
1262 }
1263
1264 if (data[IFLA_GRE_ENCAP_FLAGS]) {
1265 ret = true;
1266 ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
1267 }
1268
1269 if (data[IFLA_GRE_ENCAP_SPORT]) {
1270 ret = true;
Sabrina Dubroca3e97fa72015-02-06 17:22:22 +01001271 ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
Tom Herbert4565e992014-09-17 12:26:01 -07001272 }
1273
1274 if (data[IFLA_GRE_ENCAP_DPORT]) {
1275 ret = true;
Sabrina Dubroca3e97fa72015-02-06 17:22:22 +01001276 ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
Tom Herbert4565e992014-09-17 12:26:01 -07001277 }
1278
1279 return ret;
1280}
1281
Pravin B Shelarc5441932013-03-25 14:49:35 +00001282static int gre_tap_init(struct net_device *dev)
Herbert Xue1a80002008-10-09 12:00:17 -07001283{
Pravin B Shelarc5441932013-03-25 14:49:35 +00001284 __gre_tunnel_init(dev);
stephen hemmingerbec94d4302014-12-27 10:01:42 -08001285 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
Xin Longd51711c2017-09-28 13:23:31 +08001286 netif_keep_dst(dev);
Herbert Xue1a80002008-10-09 12:00:17 -07001287
Pravin B Shelarc5441932013-03-25 14:49:35 +00001288 return ip_tunnel_init(dev);
Herbert Xue1a80002008-10-09 12:00:17 -07001289}
1290
Pravin B Shelarc5441932013-03-25 14:49:35 +00001291static const struct net_device_ops gre_tap_netdev_ops = {
1292 .ndo_init = gre_tap_init,
1293 .ndo_uninit = ip_tunnel_uninit,
1294 .ndo_start_xmit = gre_tap_xmit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001295 .ndo_set_mac_address = eth_mac_addr,
1296 .ndo_validate_addr = eth_validate_addr,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001297 .ndo_change_mtu = ip_tunnel_change_mtu,
1298 .ndo_get_stats64 = ip_tunnel_get_stats64,
Nicolas Dichtel1e995842015-04-02 17:07:02 +02001299 .ndo_get_iflink = ip_tunnel_get_iflink,
Pravin B Shelarfc4099f2015-10-22 18:17:16 -07001300 .ndo_fill_metadata_dst = gre_fill_metadata_dst,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001301};
1302
William Tu84e54fe2017-08-22 09:40:28 -07001303static int erspan_tunnel_init(struct net_device *dev)
1304{
1305 struct ip_tunnel *tunnel = netdev_priv(dev);
William Tu84e54fe2017-08-22 09:40:28 -07001306
1307 tunnel->tun_hlen = 8;
1308 tunnel->parms.iph.protocol = IPPROTO_GRE;
Xin Longc122fda2017-10-01 22:00:55 +08001309 tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
William Tuf551c912017-12-13 16:38:56 -08001310 erspan_hdr_len(tunnel->erspan_ver);
William Tu84e54fe2017-08-22 09:40:28 -07001311
William Tu84e54fe2017-08-22 09:40:28 -07001312 dev->features |= GRE_FEATURES;
1313 dev->hw_features |= GRE_FEATURES;
1314 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
Xin Longc84bed42017-10-01 22:00:56 +08001315 netif_keep_dst(dev);
William Tu84e54fe2017-08-22 09:40:28 -07001316
1317 return ip_tunnel_init(dev);
1318}
1319
1320static const struct net_device_ops erspan_netdev_ops = {
1321 .ndo_init = erspan_tunnel_init,
1322 .ndo_uninit = ip_tunnel_uninit,
1323 .ndo_start_xmit = erspan_xmit,
1324 .ndo_set_mac_address = eth_mac_addr,
1325 .ndo_validate_addr = eth_validate_addr,
1326 .ndo_change_mtu = ip_tunnel_change_mtu,
1327 .ndo_get_stats64 = ip_tunnel_get_stats64,
1328 .ndo_get_iflink = ip_tunnel_get_iflink,
1329 .ndo_fill_metadata_dst = gre_fill_metadata_dst,
1330};
1331
Herbert Xue1a80002008-10-09 12:00:17 -07001332static void ipgre_tap_setup(struct net_device *dev)
1333{
Herbert Xue1a80002008-10-09 12:00:17 -07001334 ether_setup(dev);
Xin Longcfddd4c2017-12-18 14:24:35 +08001335 dev->max_mtu = 0;
Jiri Bencd13b1612016-02-17 15:32:53 +01001336 dev->netdev_ops = &gre_tap_netdev_ops;
1337 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1338 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001339 ip_tunnel_setup(dev, gre_tap_net_id);
Herbert Xue1a80002008-10-09 12:00:17 -07001340}
1341
Petr Machatad1b2a6c2018-02-27 14:53:37 +01001342bool is_gretap_dev(const struct net_device *dev)
1343{
1344 return dev->netdev_ops == &gre_tap_netdev_ops;
1345}
1346EXPORT_SYMBOL_GPL(is_gretap_dev);
1347
Pravin B Shelarc5441932013-03-25 14:49:35 +00001348static int ipgre_newlink(struct net *src_net, struct net_device *dev,
Matthias Schiffer7a3f4a12017-06-25 23:55:59 +02001349 struct nlattr *tb[], struct nlattr *data[],
1350 struct netlink_ext_ack *extack)
Herbert Xuc19e6542008-10-09 11:59:55 -07001351{
Pravin B Shelarc5441932013-03-25 14:49:35 +00001352 struct ip_tunnel_parm p;
Tom Herbert4565e992014-09-17 12:26:01 -07001353 struct ip_tunnel_encap ipencap;
Craig Gallek9830ad42017-04-19 12:30:54 -04001354 __u32 fwmark = 0;
Philip Prindeville22a59be2016-06-14 15:53:02 -06001355 int err;
Tom Herbert4565e992014-09-17 12:26:01 -07001356
1357 if (ipgre_netlink_encap_parms(data, &ipencap)) {
1358 struct ip_tunnel *t = netdev_priv(dev);
Philip Prindeville22a59be2016-06-14 15:53:02 -06001359 err = ip_tunnel_encap_setup(t, &ipencap);
Tom Herbert4565e992014-09-17 12:26:01 -07001360
1361 if (err < 0)
1362 return err;
1363 }
Herbert Xuc19e6542008-10-09 11:59:55 -07001364
Craig Gallek9830ad42017-04-19 12:30:54 -04001365 err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
Philip Prindeville22a59be2016-06-14 15:53:02 -06001366 if (err < 0)
1367 return err;
Craig Gallek9830ad42017-04-19 12:30:54 -04001368 return ip_tunnel_newlink(dev, tb, &p, fwmark);
Herbert Xuc19e6542008-10-09 11:59:55 -07001369}
1370
1371static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
Matthias Schifferad744b22017-06-25 23:56:00 +02001372 struct nlattr *data[],
1373 struct netlink_ext_ack *extack)
Herbert Xuc19e6542008-10-09 11:59:55 -07001374{
Craig Gallek9830ad42017-04-19 12:30:54 -04001375 struct ip_tunnel *t = netdev_priv(dev);
Tom Herbert4565e992014-09-17 12:26:01 -07001376 struct ip_tunnel_encap ipencap;
Craig Gallek9830ad42017-04-19 12:30:54 -04001377 __u32 fwmark = t->fwmark;
Xin Longdd9d5982017-11-07 16:33:08 +08001378 struct ip_tunnel_parm p;
Philip Prindeville22a59be2016-06-14 15:53:02 -06001379 int err;
Tom Herbert4565e992014-09-17 12:26:01 -07001380
1381 if (ipgre_netlink_encap_parms(data, &ipencap)) {
Philip Prindeville22a59be2016-06-14 15:53:02 -06001382 err = ip_tunnel_encap_setup(t, &ipencap);
Tom Herbert4565e992014-09-17 12:26:01 -07001383
1384 if (err < 0)
1385 return err;
1386 }
Herbert Xuc19e6542008-10-09 11:59:55 -07001387
Craig Gallek9830ad42017-04-19 12:30:54 -04001388 err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
Philip Prindeville22a59be2016-06-14 15:53:02 -06001389 if (err < 0)
1390 return err;
Xin Longdd9d5982017-11-07 16:33:08 +08001391
1392 err = ip_tunnel_changelink(dev, tb, &p, fwmark);
1393 if (err < 0)
1394 return err;
1395
1396 t->parms.i_flags = p.i_flags;
1397 t->parms.o_flags = p.o_flags;
1398
1399 if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
1400 ipgre_link_update(dev, !tb[IFLA_MTU]);
1401
1402 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -07001403}
1404
1405static size_t ipgre_get_size(const struct net_device *dev)
1406{
1407 return
1408 /* IFLA_GRE_LINK */
1409 nla_total_size(4) +
1410 /* IFLA_GRE_IFLAGS */
1411 nla_total_size(2) +
1412 /* IFLA_GRE_OFLAGS */
1413 nla_total_size(2) +
1414 /* IFLA_GRE_IKEY */
1415 nla_total_size(4) +
1416 /* IFLA_GRE_OKEY */
1417 nla_total_size(4) +
1418 /* IFLA_GRE_LOCAL */
1419 nla_total_size(4) +
1420 /* IFLA_GRE_REMOTE */
1421 nla_total_size(4) +
1422 /* IFLA_GRE_TTL */
1423 nla_total_size(1) +
1424 /* IFLA_GRE_TOS */
1425 nla_total_size(1) +
1426 /* IFLA_GRE_PMTUDISC */
1427 nla_total_size(1) +
Tom Herbert4565e992014-09-17 12:26:01 -07001428 /* IFLA_GRE_ENCAP_TYPE */
1429 nla_total_size(2) +
1430 /* IFLA_GRE_ENCAP_FLAGS */
1431 nla_total_size(2) +
1432 /* IFLA_GRE_ENCAP_SPORT */
1433 nla_total_size(2) +
1434 /* IFLA_GRE_ENCAP_DPORT */
1435 nla_total_size(2) +
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001436 /* IFLA_GRE_COLLECT_METADATA */
1437 nla_total_size(0) +
Philip Prindeville22a59be2016-06-14 15:53:02 -06001438 /* IFLA_GRE_IGNORE_DF */
1439 nla_total_size(1) +
Craig Gallek9830ad42017-04-19 12:30:54 -04001440 /* IFLA_GRE_FWMARK */
1441 nla_total_size(4) +
William Tu84e54fe2017-08-22 09:40:28 -07001442 /* IFLA_GRE_ERSPAN_INDEX */
1443 nla_total_size(4) +
William Tuf551c912017-12-13 16:38:56 -08001444 /* IFLA_GRE_ERSPAN_VER */
1445 nla_total_size(1) +
1446 /* IFLA_GRE_ERSPAN_DIR */
1447 nla_total_size(1) +
1448 /* IFLA_GRE_ERSPAN_HWID */
1449 nla_total_size(2) +
Herbert Xuc19e6542008-10-09 11:59:55 -07001450 0;
1451}
1452
1453static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1454{
1455 struct ip_tunnel *t = netdev_priv(dev);
1456 struct ip_tunnel_parm *p = &t->parms;
1457
David S. Millerf3756b72012-04-01 20:39:02 -04001458 if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
Tom Herbert95f5c642016-04-29 17:12:16 -07001459 nla_put_be16(skb, IFLA_GRE_IFLAGS,
1460 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
1461 nla_put_be16(skb, IFLA_GRE_OFLAGS,
1462 gre_tnl_flags_to_gre_flags(p->o_flags)) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001463 nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1464 nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
Jiri Benc930345e2015-03-29 16:59:25 +02001465 nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1466 nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001467 nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1468 nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1469 nla_put_u8(skb, IFLA_GRE_PMTUDISC,
Craig Gallek9830ad42017-04-19 12:30:54 -04001470 !!(p->iph.frag_off & htons(IP_DF))) ||
1471 nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
David S. Millerf3756b72012-04-01 20:39:02 -04001472 goto nla_put_failure;
Tom Herbert4565e992014-09-17 12:26:01 -07001473
1474 if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
1475 t->encap.type) ||
Sabrina Dubroca3e97fa72015-02-06 17:22:22 +01001476 nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
1477 t->encap.sport) ||
1478 nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
1479 t->encap.dport) ||
Tom Herbert4565e992014-09-17 12:26:01 -07001480 nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
Tom Herberte1b2cb62014-11-05 16:49:38 -08001481 t->encap.flags))
Tom Herbert4565e992014-09-17 12:26:01 -07001482 goto nla_put_failure;
1483
Philip Prindeville22a59be2016-06-14 15:53:02 -06001484 if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
1485 goto nla_put_failure;
1486
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001487 if (t->collect_md) {
1488 if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
1489 goto nla_put_failure;
1490 }
1491
William Tuf551c912017-12-13 16:38:56 -08001492 if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
1493 goto nla_put_failure;
1494
1495 if (t->erspan_ver == 1) {
William Tu84e54fe2017-08-22 09:40:28 -07001496 if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
1497 goto nla_put_failure;
William Tuf551c912017-12-13 16:38:56 -08001498 } else if (t->erspan_ver == 2) {
1499 if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir))
1500 goto nla_put_failure;
1501 if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid))
1502 goto nla_put_failure;
1503 }
William Tu84e54fe2017-08-22 09:40:28 -07001504
Herbert Xuc19e6542008-10-09 11:59:55 -07001505 return 0;
1506
1507nla_put_failure:
1508 return -EMSGSIZE;
1509}
1510
William Tu84e54fe2017-08-22 09:40:28 -07001511static void erspan_setup(struct net_device *dev)
1512{
Xin Long84581bd2018-08-27 18:41:32 +08001513 struct ip_tunnel *t = netdev_priv(dev);
1514
William Tu84e54fe2017-08-22 09:40:28 -07001515 ether_setup(dev);
1516 dev->netdev_ops = &erspan_netdev_ops;
1517 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1518 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
1519 ip_tunnel_setup(dev, erspan_net_id);
Xin Long84581bd2018-08-27 18:41:32 +08001520 t->erspan_ver = 1;
William Tu84e54fe2017-08-22 09:40:28 -07001521}
1522
Herbert Xuc19e6542008-10-09 11:59:55 -07001523static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1524 [IFLA_GRE_LINK] = { .type = NLA_U32 },
1525 [IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
1526 [IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
1527 [IFLA_GRE_IKEY] = { .type = NLA_U32 },
1528 [IFLA_GRE_OKEY] = { .type = NLA_U32 },
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001529 [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
1530 [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
Herbert Xuc19e6542008-10-09 11:59:55 -07001531 [IFLA_GRE_TTL] = { .type = NLA_U8 },
1532 [IFLA_GRE_TOS] = { .type = NLA_U8 },
1533 [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 },
Tom Herbert4565e992014-09-17 12:26:01 -07001534 [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 },
1535 [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 },
1536 [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 },
1537 [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 },
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001538 [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG },
Philip Prindeville22a59be2016-06-14 15:53:02 -06001539 [IFLA_GRE_IGNORE_DF] = { .type = NLA_U8 },
Craig Gallek9830ad42017-04-19 12:30:54 -04001540 [IFLA_GRE_FWMARK] = { .type = NLA_U32 },
William Tu84e54fe2017-08-22 09:40:28 -07001541 [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 },
William Tuf551c912017-12-13 16:38:56 -08001542 [IFLA_GRE_ERSPAN_VER] = { .type = NLA_U8 },
1543 [IFLA_GRE_ERSPAN_DIR] = { .type = NLA_U8 },
1544 [IFLA_GRE_ERSPAN_HWID] = { .type = NLA_U16 },
Herbert Xuc19e6542008-10-09 11:59:55 -07001545};
1546
1547static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1548 .kind = "gre",
1549 .maxtype = IFLA_GRE_MAX,
1550 .policy = ipgre_policy,
1551 .priv_size = sizeof(struct ip_tunnel),
1552 .setup = ipgre_tunnel_setup,
1553 .validate = ipgre_tunnel_validate,
1554 .newlink = ipgre_newlink,
1555 .changelink = ipgre_changelink,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001556 .dellink = ip_tunnel_dellink,
Herbert Xuc19e6542008-10-09 11:59:55 -07001557 .get_size = ipgre_get_size,
1558 .fill_info = ipgre_fill_info,
Nicolas Dichtel1728d4f2015-01-15 15:11:17 +01001559 .get_link_net = ip_tunnel_get_link_net,
Herbert Xuc19e6542008-10-09 11:59:55 -07001560};
1561
Herbert Xue1a80002008-10-09 12:00:17 -07001562static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1563 .kind = "gretap",
1564 .maxtype = IFLA_GRE_MAX,
1565 .policy = ipgre_policy,
1566 .priv_size = sizeof(struct ip_tunnel),
1567 .setup = ipgre_tap_setup,
1568 .validate = ipgre_tap_validate,
1569 .newlink = ipgre_newlink,
1570 .changelink = ipgre_changelink,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001571 .dellink = ip_tunnel_dellink,
Herbert Xue1a80002008-10-09 12:00:17 -07001572 .get_size = ipgre_get_size,
1573 .fill_info = ipgre_fill_info,
Nicolas Dichtel1728d4f2015-01-15 15:11:17 +01001574 .get_link_net = ip_tunnel_get_link_net,
Herbert Xue1a80002008-10-09 12:00:17 -07001575};
1576
William Tu84e54fe2017-08-22 09:40:28 -07001577static struct rtnl_link_ops erspan_link_ops __read_mostly = {
1578 .kind = "erspan",
1579 .maxtype = IFLA_GRE_MAX,
1580 .policy = ipgre_policy,
1581 .priv_size = sizeof(struct ip_tunnel),
1582 .setup = erspan_setup,
1583 .validate = erspan_validate,
1584 .newlink = ipgre_newlink,
1585 .changelink = ipgre_changelink,
1586 .dellink = ip_tunnel_dellink,
1587 .get_size = ipgre_get_size,
1588 .fill_info = ipgre_fill_info,
1589 .get_link_net = ip_tunnel_get_link_net,
1590};
1591
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001592struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1593 u8 name_assign_type)
1594{
1595 struct nlattr *tb[IFLA_MAX + 1];
1596 struct net_device *dev;
Nicolas Dichtel106da662016-06-13 10:31:04 +02001597 LIST_HEAD(list_kill);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001598 struct ip_tunnel *t;
1599 int err;
1600
1601 memset(&tb, 0, sizeof(tb));
1602
1603 dev = rtnl_create_link(net, name, name_assign_type,
1604 &ipgre_tap_ops, tb);
1605 if (IS_ERR(dev))
1606 return dev;
1607
1608 /* Configure flow based GRE device. */
1609 t = netdev_priv(dev);
1610 t->collect_md = true;
1611
Matthias Schiffer7a3f4a12017-06-25 23:55:59 +02001612 err = ipgre_newlink(net, dev, tb, NULL, NULL);
Nicolas Dichtel106da662016-06-13 10:31:04 +02001613 if (err < 0) {
1614 free_netdev(dev);
1615 return ERR_PTR(err);
1616 }
David Wragg7e059152016-02-10 00:05:58 +00001617
1618 /* openvswitch users expect packet sizes to be unrestricted,
1619 * so set the largest MTU we can.
1620 */
1621 err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
1622 if (err)
1623 goto out;
1624
Nicolas Dichtelda6f1da2016-06-13 10:31:06 +02001625 err = rtnl_configure_link(dev, NULL);
1626 if (err < 0)
1627 goto out;
1628
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001629 return dev;
1630out:
Nicolas Dichtel106da662016-06-13 10:31:04 +02001631 ip_tunnel_dellink(dev, &list_kill);
1632 unregister_netdevice_many(&list_kill);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001633 return ERR_PTR(err);
1634}
1635EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1636
Pravin B Shelarc5441932013-03-25 14:49:35 +00001637static int __net_init ipgre_tap_init_net(struct net *net)
1638{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001639 return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
Pravin B Shelarc5441932013-03-25 14:49:35 +00001640}
1641
Eric Dumazet64bc1782017-09-19 16:27:09 -07001642static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001643{
Eric Dumazet64bc1782017-09-19 16:27:09 -07001644 ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001645}
1646
1647static struct pernet_operations ipgre_tap_net_ops = {
1648 .init = ipgre_tap_init_net,
Eric Dumazet64bc1782017-09-19 16:27:09 -07001649 .exit_batch = ipgre_tap_exit_batch_net,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001650 .id = &gre_tap_net_id,
1651 .size = sizeof(struct ip_tunnel_net),
1652};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653
William Tu84e54fe2017-08-22 09:40:28 -07001654static int __net_init erspan_init_net(struct net *net)
1655{
1656 return ip_tunnel_init_net(net, erspan_net_id,
1657 &erspan_link_ops, "erspan0");
1658}
1659
Eric Dumazet64bc1782017-09-19 16:27:09 -07001660static void __net_exit erspan_exit_batch_net(struct list_head *net_list)
William Tu84e54fe2017-08-22 09:40:28 -07001661{
Eric Dumazet64bc1782017-09-19 16:27:09 -07001662 ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops);
William Tu84e54fe2017-08-22 09:40:28 -07001663}
1664
1665static struct pernet_operations erspan_net_ops = {
1666 .init = erspan_init_net,
Eric Dumazet64bc1782017-09-19 16:27:09 -07001667 .exit_batch = erspan_exit_batch_net,
William Tu84e54fe2017-08-22 09:40:28 -07001668 .id = &erspan_net_id,
1669 .size = sizeof(struct ip_tunnel_net),
1670};
1671
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672static int __init ipgre_init(void)
1673{
1674 int err;
1675
Joe Perches058bd4d2012-03-11 18:36:11 +00001676 pr_info("GRE over IPv4 tunneling driver\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001678 err = register_pernet_device(&ipgre_net_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001679 if (err < 0)
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001680 return err;
1681
Pravin B Shelarc5441932013-03-25 14:49:35 +00001682 err = register_pernet_device(&ipgre_tap_net_ops);
1683 if (err < 0)
William Tue3d03282017-08-22 17:04:05 -07001684 goto pnet_tap_failed;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001685
William Tu84e54fe2017-08-22 09:40:28 -07001686 err = register_pernet_device(&erspan_net_ops);
1687 if (err < 0)
1688 goto pnet_erspan_failed;
1689
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001690 err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001691 if (err < 0) {
Joe Perches058bd4d2012-03-11 18:36:11 +00001692 pr_info("%s: can't add protocol\n", __func__);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001693 goto add_proto_failed;
1694 }
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001695
Herbert Xuc19e6542008-10-09 11:59:55 -07001696 err = rtnl_link_register(&ipgre_link_ops);
1697 if (err < 0)
1698 goto rtnl_link_failed;
1699
Herbert Xue1a80002008-10-09 12:00:17 -07001700 err = rtnl_link_register(&ipgre_tap_ops);
1701 if (err < 0)
1702 goto tap_ops_failed;
1703
William Tu84e54fe2017-08-22 09:40:28 -07001704 err = rtnl_link_register(&erspan_link_ops);
1705 if (err < 0)
1706 goto erspan_link_failed;
1707
Pravin B Shelarc5441932013-03-25 14:49:35 +00001708 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -07001709
William Tu84e54fe2017-08-22 09:40:28 -07001710erspan_link_failed:
1711 rtnl_link_unregister(&ipgre_tap_ops);
Herbert Xue1a80002008-10-09 12:00:17 -07001712tap_ops_failed:
1713 rtnl_link_unregister(&ipgre_link_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001714rtnl_link_failed:
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001715 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001716add_proto_failed:
William Tu84e54fe2017-08-22 09:40:28 -07001717 unregister_pernet_device(&erspan_net_ops);
1718pnet_erspan_failed:
Pravin B Shelarc5441932013-03-25 14:49:35 +00001719 unregister_pernet_device(&ipgre_tap_net_ops);
William Tue3d03282017-08-22 17:04:05 -07001720pnet_tap_failed:
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001721 unregister_pernet_device(&ipgre_net_ops);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001722 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723}
1724
Alexey Kuznetsovdb445752005-07-30 17:46:44 -07001725static void __exit ipgre_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726{
Herbert Xue1a80002008-10-09 12:00:17 -07001727 rtnl_link_unregister(&ipgre_tap_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001728 rtnl_link_unregister(&ipgre_link_ops);
William Tu84e54fe2017-08-22 09:40:28 -07001729 rtnl_link_unregister(&erspan_link_ops);
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001730 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001731 unregister_pernet_device(&ipgre_tap_net_ops);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001732 unregister_pernet_device(&ipgre_net_ops);
William Tu84e54fe2017-08-22 09:40:28 -07001733 unregister_pernet_device(&erspan_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734}
1735
1736module_init(ipgre_init);
1737module_exit(ipgre_fini);
1738MODULE_LICENSE("GPL");
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001739MODULE_ALIAS_RTNL_LINK("gre");
1740MODULE_ALIAS_RTNL_LINK("gretap");
William Tu84e54fe2017-08-22 09:40:28 -07001741MODULE_ALIAS_RTNL_LINK("erspan");
Vasiliy Kulikov8909c9a2011-03-02 00:33:13 +03001742MODULE_ALIAS_NETDEV("gre0");
Pravin B Shelarc5441932013-03-25 14:49:35 +00001743MODULE_ALIAS_NETDEV("gretap0");
William Tu84e54fe2017-08-22 09:40:28 -07001744MODULE_ALIAS_NETDEV("erspan0");