blob: 7a7829e839c24ee624a046079f25545e035d5bc7 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Linus Torvalds1da177e2005-04-16 15:20:36 -070052/*
53 Problems & solutions
54 --------------------
55
56 1. The most important issue is detecting local dead loops.
57 They would cause complete host lockup in transmit, which
58 would be "resolved" by stack overflow or, if queueing is enabled,
59 with infinite looping in net_bh.
60
61 We cannot track such dead loops during route installation,
62 it is infeasible task. The most general solutions would be
63 to keep skb->encapsulation counter (sort of local ttl),
Eric Dumazet6d0722a2010-09-29 23:35:10 -070064 and silently drop packet when it expires. It is a good
stephen hemmingerbff52852012-02-24 08:08:20 +000065 solution, but it supposes maintaining new variable in ALL
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 skb, even if no tunneling is used.
67
Eric Dumazet6d0722a2010-09-29 23:35:10 -070068 Current solution: xmit_recursion breaks dead loops. This is a percpu
69 counter, since when we enter the first ndo_xmit(), cpu migration is
70 forbidden. We force an exit if this counter reaches RECURSION_LIMIT
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
72 2. Networking dead loops would not kill routers, but would really
73 kill network. IP hop limit plays role of "t->recursion" in this case,
74 if we copy it from packet being encapsulated to upper header.
75 It is very good solution, but it introduces two problems:
76
77 - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
78 do not work over tunnels.
79 - traceroute does not work. I planned to relay ICMP from tunnel,
80 so that this problem would be solved and traceroute output
81 would even more informative. This idea appeared to be wrong:
82 only Linux complies to rfc1812 now (yes, guys, Linux is the only
83 true router now :-)), all routers (at least, in neighbourhood of mine)
84 return only 8 bytes of payload. It is the end.
85
86 Hence, if we want that OSPF worked or traceroute said something reasonable,
87 we should search for another solution.
88
89 One of them is to parse packet trying to detect inner encapsulation
90 made by our node. It is difficult or even impossible, especially,
stephen hemmingerbff52852012-02-24 08:08:20 +000091 taking into account fragmentation. TO be short, ttl is not solution at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
93 Current solution: The solution was UNEXPECTEDLY SIMPLE.
94 We force DF flag on tunnels with preconfigured hop limit,
95 that is ALL. :-) Well, it does not remove the problem completely,
96 but exponential growth of network traffic is changed to linear
97 (branches, that exceed pmtu are pruned) and tunnel mtu
stephen hemmingerbff52852012-02-24 08:08:20 +000098 rapidly degrades to value <68, where looping stops.
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 Yes, it is not good if there exists a router in the loop,
100 which does not force DF, even when encapsulating packets have DF set.
101 But it is not our problem! Nobody could accuse us, we made
102 all that we could make. Even if it is your gated who injected
103 fatal route to network, even if it were you who configured
104 fatal static route: you are innocent. :-)
105
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 Alexey Kuznetsov.
107 */
108
stephen hemmingereccc1bb2012-09-25 11:02:48 +0000109static bool log_ecn_error = true;
110module_param(log_ecn_error, bool, 0644);
111MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
112
Herbert Xuc19e6542008-10-09 11:59:55 -0700113static struct rtnl_link_ops ipgre_link_ops __read_mostly;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114static int ipgre_tunnel_init(struct net_device *dev);
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700115
Alexey Dobriyanc7d03a02016-11-17 04:58:21 +0300116static unsigned int ipgre_net_id __read_mostly;
117static unsigned int gre_tap_net_id __read_mostly;
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700118
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700119static void ipgre_err(struct sk_buff *skb, u32 info,
120 const struct tnl_ptk_info *tpi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122
Pravin B Shelarc5441932013-03-25 14:49:35 +0000123 /* All the routers (except for Linux) return only
124 8 bytes of packet payload. It means, that precise relaying of
125 ICMP in the real Internet is absolutely infeasible.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
Pravin B Shelarc5441932013-03-25 14:49:35 +0000127 Moreover, Cisco "wise men" put GRE key to the third word
128 in GRE header. It makes impossible maintaining even soft
129 state for keyed GRE tunnels with enabled checksum. Tell
130 them "thank you".
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Pravin B Shelarc5441932013-03-25 14:49:35 +0000132 Well, I wonder, rfc1812 was written by Cisco employee,
133 what the hell these idiots break standards established
134 by themselves???
135 */
136 struct net *net = dev_net(skb->dev);
137 struct ip_tunnel_net *itn;
Eric Dumazet96f5a842013-05-18 08:36:03 +0000138 const struct iphdr *iph;
Arnaldo Carvalho de Melo88c76642007-03-13 14:43:18 -0300139 const int type = icmp_hdr(skb)->type;
140 const int code = icmp_hdr(skb)->code;
Eric Dumazet20e19542016-06-18 21:52:06 -0700141 unsigned int data_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 struct ip_tunnel *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 switch (type) {
145 default:
146 case ICMP_PARAMETERPROB:
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700147 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
149 case ICMP_DEST_UNREACH:
150 switch (code) {
151 case ICMP_SR_FAILED:
152 case ICMP_PORT_UNREACH:
153 /* Impossible event. */
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700154 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 default:
156 /* All others are translated to HOST_UNREACH.
157 rfc2003 contains "deep thoughts" about NET_UNREACH,
158 I believe they are just ether pollution. --ANK
159 */
160 break;
161 }
162 break;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700163
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 case ICMP_TIME_EXCEEDED:
165 if (code != ICMP_EXC_TTL)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700166 return;
Eric Dumazet20e19542016-06-18 21:52:06 -0700167 data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 break;
David S. Miller55be7a92012-07-11 21:27:49 -0700169
170 case ICMP_REDIRECT:
171 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 }
173
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700174 if (tpi->proto == htons(ETH_P_TEB))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000175 itn = net_generic(net, gre_tap_net_id);
176 else
177 itn = net_generic(net, ipgre_net_id);
178
Duan Jiongc0c0c502014-01-28 11:49:43 +0800179 iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700180 t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
181 iph->daddr, iph->saddr, tpi->key);
stephen hemmingerd2083282012-09-24 18:12:23 +0000182
Ian Morris51456b22015-04-03 09:17:26 +0100183 if (!t)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700184 return;
David S. Miller36393392012-06-14 22:21:46 -0700185
Eric Dumazet9b8c6d72016-06-18 21:52:05 -0700186#if IS_ENABLED(CONFIG_IPV6)
187 if (tpi->proto == htons(ETH_P_IPV6) &&
Eric Dumazet20e19542016-06-18 21:52:06 -0700188 !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
189 type, data_len))
Eric Dumazet9b8c6d72016-06-18 21:52:05 -0700190 return;
191#endif
192
David S. Miller36393392012-06-14 22:21:46 -0700193 if (t->parms.iph.daddr == 0 ||
Joe Perchesf97c1e02007-12-16 13:45:43 -0800194 ipv4_is_multicast(t->parms.iph.daddr))
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700195 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
197 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700198 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
Wei Yongjunda6185d82009-02-24 23:34:48 -0800200 if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 t->err_count++;
202 else
203 t->err_count = 1;
204 t->err_time = jiffies;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700205}
206
207static void gre_err(struct sk_buff *skb, u32 info)
208{
209 /* All the routers (except for Linux) return only
210 * 8 bytes of packet payload. It means, that precise relaying of
211 * ICMP in the real Internet is absolutely infeasible.
212 *
213 * Moreover, Cisco "wise men" put GRE key to the third word
214 * in GRE header. It makes impossible maintaining even soft
215 * state for keyed
216 * GRE tunnels with enabled checksum. Tell them "thank you".
217 *
218 * Well, I wonder, rfc1812 was written by Cisco employee,
219 * what the hell these idiots break standards established
220 * by themselves???
221 */
222
Eric Dumazete5826152016-06-15 06:24:00 -0700223 const struct iphdr *iph = (struct iphdr *)skb->data;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700224 const int type = icmp_hdr(skb)->type;
225 const int code = icmp_hdr(skb)->code;
226 struct tnl_ptk_info tpi;
227 bool csum_err = false;
228
Eric Dumazete5826152016-06-15 06:24:00 -0700229 if (gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP),
230 iph->ihl * 4) < 0) {
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700231 if (!csum_err) /* ignore csum errors. */
232 return;
233 }
234
235 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
236 ipv4_update_pmtu(skb, dev_net(skb->dev), info,
237 skb->dev->ifindex, 0, IPPROTO_GRE, 0);
238 return;
239 }
240 if (type == ICMP_REDIRECT) {
241 ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0,
242 IPPROTO_GRE, 0);
243 return;
244 }
245
246 ipgre_err(skb, info, &tpi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247}
248
Jiri Benc125372f2016-05-03 17:10:08 +0200249static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
250 struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700252 struct metadata_dst *tun_dst = NULL;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000253 const struct iphdr *iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 struct ip_tunnel *tunnel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700256 iph = ip_hdr(skb);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700257 tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
258 iph->saddr, iph->daddr, tpi->key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
stephen hemmingerd2083282012-09-24 18:12:23 +0000260 if (tunnel) {
Jiri Benc125372f2016-05-03 17:10:08 +0200261 if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
262 raw_proto, false) < 0)
Jiri Benc244a7972016-05-03 17:10:07 +0200263 goto drop;
264
Jiri Bence271c7b2016-05-11 15:53:57 +0200265 if (tunnel->dev->type != ARPHRD_NONE)
266 skb_pop_mac_header(skb);
267 else
268 skb_reset_mac_header(skb);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700269 if (tunnel->collect_md) {
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700270 __be16 flags;
271 __be64 tun_id;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700272
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700273 flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
Amir Vadaid817f432016-09-08 16:23:45 +0300274 tun_id = key32_to_tunnel_id(tpi->key);
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700275 tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700276 if (!tun_dst)
277 return PACKET_REJECT;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700278 }
279
280 ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700281 return PACKET_RCVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 }
Jiri Benc125372f2016-05-03 17:10:08 +0200283 return PACKET_NEXT;
Jiri Benc244a7972016-05-03 17:10:07 +0200284
285drop:
286 kfree_skb(skb);
287 return PACKET_RCVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288}
289
Jiri Benc125372f2016-05-03 17:10:08 +0200290static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
291 int hdr_len)
292{
293 struct net *net = dev_net(skb->dev);
294 struct ip_tunnel_net *itn;
295 int res;
296
297 if (tpi->proto == htons(ETH_P_TEB))
298 itn = net_generic(net, gre_tap_net_id);
299 else
300 itn = net_generic(net, ipgre_net_id);
301
302 res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
303 if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
304 /* ipgre tunnels in collect metadata mode should receive
305 * also ETH_P_TEB traffic.
306 */
307 itn = net_generic(net, ipgre_net_id);
308 res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
309 }
310 return res;
311}
312
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700313static int gre_rcv(struct sk_buff *skb)
314{
315 struct tnl_ptk_info tpi;
316 bool csum_err = false;
Tom Herbert95f5c642016-04-29 17:12:16 -0700317 int hdr_len;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700318
319#ifdef CONFIG_NET_IPGRE_BROADCAST
320 if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
321 /* Looped back packet, drop it! */
322 if (rt_is_output_route(skb_rtable(skb)))
323 goto drop;
324 }
325#endif
326
Eric Dumazete5826152016-06-15 06:24:00 -0700327 hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
Jiri Bencf132ae72016-05-03 15:00:21 +0200328 if (hdr_len < 0)
Tom Herbert95f5c642016-04-29 17:12:16 -0700329 goto drop;
330
Jiri Benc244a7972016-05-03 17:10:07 +0200331 if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700332 return 0;
333
334 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
335drop:
336 kfree_skb(skb);
337 return 0;
338}
339
Pravin B Shelarc5441932013-03-25 14:49:35 +0000340static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
341 const struct iphdr *tnl_params,
342 __be16 proto)
343{
344 struct ip_tunnel *tunnel = netdev_priv(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000345
Pravin B Shelarc5441932013-03-25 14:49:35 +0000346 if (tunnel->parms.o_flags & TUNNEL_SEQ)
347 tunnel->o_seqno++;
Eric Dumazetcef401d2013-01-25 20:34:37 +0000348
Pravin B Shelarc5441932013-03-25 14:49:35 +0000349 /* Push GRE header. */
Tom Herbert182a3522016-04-29 17:12:19 -0700350 gre_build_header(skb, tunnel->tun_hlen,
351 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
352 htonl(tunnel->o_seqno));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
Nicolas Dichtelbf3d6a82013-05-27 23:48:15 +0000354 ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355}
356
Alexander Duyckaed069d2016-04-14 15:33:37 -0400357static int gre_handle_offloads(struct sk_buff *skb, bool csum)
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -0700358{
Edward Cree6fa79662016-02-11 21:02:31 +0000359 return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -0700360}
361
Pravin B Shelarfc4099f2015-10-22 18:17:16 -0700362static struct rtable *gre_get_rt(struct sk_buff *skb,
363 struct net_device *dev,
364 struct flowi4 *fl,
365 const struct ip_tunnel_key *key)
366{
367 struct net *net = dev_net(dev);
368
369 memset(fl, 0, sizeof(*fl));
370 fl->daddr = key->u.ipv4.dst;
371 fl->saddr = key->u.ipv4.src;
372 fl->flowi4_tos = RT_TOS(key->tos);
373 fl->flowi4_mark = skb->mark;
374 fl->flowi4_proto = IPPROTO_GRE;
375
376 return ip_route_output_key(net, fl);
377}
378
Jiri Benc20907142016-04-27 11:29:07 +0200379static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
380 __be16 proto)
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700381{
382 struct ip_tunnel_info *tun_info;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700383 const struct ip_tunnel_key *key;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100384 struct rtable *rt = NULL;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700385 struct flowi4 fl;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700386 int min_headroom;
387 int tunnel_hlen;
388 __be16 df, flags;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100389 bool use_cache;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700390 int err;
391
Jiri Benc61adedf2015-08-20 13:56:25 +0200392 tun_info = skb_tunnel_info(skb);
Jiri Benc7f9562a2015-08-28 20:48:20 +0200393 if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
394 ip_tunnel_info_af(tun_info) != AF_INET))
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700395 goto err_free_skb;
396
397 key = &tun_info->key;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100398 use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
399 if (use_cache)
400 rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl.saddr);
Paolo Abeni3c1cb4d2016-02-12 15:43:59 +0100401 if (!rt) {
402 rt = gre_get_rt(skb, dev, &fl, key);
403 if (IS_ERR(rt))
404 goto err_free_skb;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100405 if (use_cache)
Paolo Abeni3c1cb4d2016-02-12 15:43:59 +0100406 dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
407 fl.saddr);
408 }
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700409
Tom Herbert95f5c642016-04-29 17:12:16 -0700410 tunnel_hlen = gre_calc_hlen(key->tun_flags);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700411
412 min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
413 + tunnel_hlen + sizeof(struct iphdr);
414 if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
415 int head_delta = SKB_DATA_ALIGN(min_headroom -
416 skb_headroom(skb) +
417 16);
418 err = pskb_expand_head(skb, max_t(int, head_delta, 0),
419 0, GFP_ATOMIC);
420 if (unlikely(err))
421 goto err_free_rt;
422 }
423
424 /* Push Tunnel header. */
Alexander Duyckaed069d2016-04-14 15:33:37 -0400425 if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700426 goto err_free_rt;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700427
428 flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
David S. Millercba653212016-05-04 00:52:29 -0400429 gre_build_header(skb, tunnel_hlen, flags, proto,
Amir Vadaid817f432016-09-08 16:23:45 +0300430 tunnel_id_to_key32(tun_info->key.tun_id), 0);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700431
432 df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
Pravin B Shelar039f5062015-12-24 14:34:54 -0800433
434 iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
435 key->tos, key->ttl, df, false);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700436 return;
437
438err_free_rt:
439 ip_rt_put(rt);
440err_free_skb:
441 kfree_skb(skb);
442 dev->stats.tx_dropped++;
443}
444
Pravin B Shelarfc4099f2015-10-22 18:17:16 -0700445static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
446{
447 struct ip_tunnel_info *info = skb_tunnel_info(skb);
448 struct rtable *rt;
449 struct flowi4 fl4;
450
451 if (ip_tunnel_info_af(info) != AF_INET)
452 return -EINVAL;
453
454 rt = gre_get_rt(skb, dev, &fl4, &info->key);
455 if (IS_ERR(rt))
456 return PTR_ERR(rt);
457
458 ip_rt_put(rt);
459 info->key.u.ipv4.src = fl4.saddr;
460 return 0;
461}
462
Pravin B Shelarc5441932013-03-25 14:49:35 +0000463static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
464 struct net_device *dev)
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800465{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000466 struct ip_tunnel *tunnel = netdev_priv(dev);
467 const struct iphdr *tnl_params;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800468
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700469 if (tunnel->collect_md) {
Jiri Benc20907142016-04-27 11:29:07 +0200470 gre_fb_xmit(skb, dev, skb->protocol);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700471 return NETDEV_TX_OK;
472 }
473
Pravin B Shelarc5441932013-03-25 14:49:35 +0000474 if (dev->header_ops) {
475 /* Need space for new headers */
476 if (skb_cow_head(skb, dev->needed_headroom -
Chen Gang2bac7cb2013-04-22 20:45:42 +0000477 (tunnel->hlen + sizeof(struct iphdr))))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000478 goto free_skb;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800479
Pravin B Shelarc5441932013-03-25 14:49:35 +0000480 tnl_params = (const struct iphdr *)skb->data;
Eric Dumazete985aad2010-09-27 03:57:11 +0000481
Pravin B Shelarc5441932013-03-25 14:49:35 +0000482 /* Pull skb since ip_tunnel_xmit() needs skb->data pointing
483 * to gre header.
484 */
485 skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
Timo Teräs8a0033a2014-12-15 09:24:13 +0200486 skb_reset_mac_header(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000487 } else {
488 if (skb_cow_head(skb, dev->needed_headroom))
489 goto free_skb;
Herbert Xue1a80002008-10-09 12:00:17 -0700490
Pravin B Shelarc5441932013-03-25 14:49:35 +0000491 tnl_params = &tunnel->parms.iph;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800492 }
493
Alexander Duyckaed069d2016-04-14 15:33:37 -0400494 if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
495 goto free_skb;
Timo Teräs8a0033a2014-12-15 09:24:13 +0200496
Pravin B Shelarc5441932013-03-25 14:49:35 +0000497 __gre_xmit(skb, dev, tnl_params, skb->protocol);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000498 return NETDEV_TX_OK;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800499
Pravin B Shelarc5441932013-03-25 14:49:35 +0000500free_skb:
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800501 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000502 dev->stats.tx_dropped++;
503 return NETDEV_TX_OK;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800504}
505
Pravin B Shelarc5441932013-03-25 14:49:35 +0000506static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
507 struct net_device *dev)
508{
509 struct ip_tunnel *tunnel = netdev_priv(dev);
510
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700511 if (tunnel->collect_md) {
Jiri Benc20907142016-04-27 11:29:07 +0200512 gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700513 return NETDEV_TX_OK;
514 }
515
Alexander Duyckaed069d2016-04-14 15:33:37 -0400516 if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
517 goto free_skb;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000518
519 if (skb_cow_head(skb, dev->needed_headroom))
520 goto free_skb;
521
522 __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
Pravin B Shelarc5441932013-03-25 14:49:35 +0000523 return NETDEV_TX_OK;
524
525free_skb:
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800526 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000527 dev->stats.tx_dropped++;
528 return NETDEV_TX_OK;
529}
530
531static int ipgre_tunnel_ioctl(struct net_device *dev,
532 struct ifreq *ifr, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533{
Tom Herbert4565e992014-09-17 12:26:01 -0700534 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 struct ip_tunnel_parm p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Pravin B Shelarc5441932013-03-25 14:49:35 +0000537 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
538 return -EFAULT;
Cong Wang6c734fb2013-06-29 12:02:59 +0800539 if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
540 if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
541 p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
542 ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
543 return -EINVAL;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000544 }
545 p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
546 p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
547
548 err = ip_tunnel_ioctl(dev, &p, cmd);
549 if (err)
550 return err;
551
Tom Herbert95f5c642016-04-29 17:12:16 -0700552 p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
553 p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000554
555 if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
556 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 return 0;
558}
559
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560/* Nice toy. Unfortunately, useless in real life :-)
561 It allows to construct virtual multiprotocol broadcast "LAN"
562 over the Internet, provided multicast routing is tuned.
563
564
565 I have no idea was this bicycle invented before me,
566 so that I had to set ARPHRD_IPGRE to a random value.
567 I have an impression, that Cisco could make something similar,
568 but this feature is apparently missing in IOS<=11.2(8).
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900569
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
571 with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
572
573 ping -t 255 224.66.66.66
574
575 If nobody answers, mbone does not work.
576
577 ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
578 ip addr add 10.66.66.<somewhat>/24 dev Universe
579 ifconfig Universe up
580 ifconfig Universe add fe80::<Your_real_addr>/10
581 ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
582 ftp 10.66.66.66
583 ...
584 ftp fec0:6666:6666::193.233.7.65
585 ...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 */
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700587static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
588 unsigned short type,
Eric Dumazet15078502010-09-15 11:07:53 +0000589 const void *daddr, const void *saddr, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
Patrick McHardy2941a482006-01-08 22:05:26 -0800591 struct ip_tunnel *t = netdev_priv(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000592 struct iphdr *iph;
593 struct gre_base_hdr *greh;
594
Johannes Bergd58ff352017-06-16 14:29:23 +0200595 iph = skb_push(skb, t->hlen + sizeof(*iph));
Pravin B Shelarc5441932013-03-25 14:49:35 +0000596 greh = (struct gre_base_hdr *)(iph+1);
Tom Herbert95f5c642016-04-29 17:12:16 -0700597 greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000598 greh->protocol = htons(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
600 memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
Pravin B Shelarc5441932013-03-25 14:49:35 +0000602 /* Set the source hardware address. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 if (saddr)
604 memcpy(&iph->saddr, saddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +0000605 if (daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 memcpy(&iph->daddr, daddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +0000607 if (iph->daddr)
Timo Teräs77a482b2013-08-06 13:45:43 +0300608 return t->hlen + sizeof(*iph);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900609
Pravin B Shelarc5441932013-03-25 14:49:35 +0000610 return -(t->hlen + sizeof(*iph));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611}
612
Timo Teras6a5f44d2007-10-23 20:31:53 -0700613static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
614{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000615 const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
Timo Teras6a5f44d2007-10-23 20:31:53 -0700616 memcpy(haddr, &iph->saddr, 4);
617 return 4;
618}
619
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700620static const struct header_ops ipgre_header_ops = {
621 .create = ipgre_header,
Timo Teras6a5f44d2007-10-23 20:31:53 -0700622 .parse = ipgre_header_parse,
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700623};
624
Timo Teras6a5f44d2007-10-23 20:31:53 -0700625#ifdef CONFIG_NET_IPGRE_BROADCAST
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626static int ipgre_open(struct net_device *dev)
627{
Patrick McHardy2941a482006-01-08 22:05:26 -0800628 struct ip_tunnel *t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
Joe Perchesf97c1e02007-12-16 13:45:43 -0800630 if (ipv4_is_multicast(t->parms.iph.daddr)) {
David S. Millercbb1e852011-05-04 12:33:34 -0700631 struct flowi4 fl4;
632 struct rtable *rt;
Eric Dumazete985aad2010-09-27 03:57:11 +0000633
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200634 rt = ip_route_output_gre(t->net, &fl4,
David S. Millercbb1e852011-05-04 12:33:34 -0700635 t->parms.iph.daddr,
636 t->parms.iph.saddr,
637 t->parms.o_key,
638 RT_TOS(t->parms.iph.tos),
639 t->parms.link);
David S. Millerb23dd4f2011-03-02 14:31:35 -0800640 if (IS_ERR(rt))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 return -EADDRNOTAVAIL;
Changli Gaod8d1f302010-06-10 23:31:35 -0700642 dev = rt->dst.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 ip_rt_put(rt);
Ian Morris51456b22015-04-03 09:17:26 +0100644 if (!__in_dev_get_rtnl(dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 return -EADDRNOTAVAIL;
646 t->mlink = dev->ifindex;
Herbert Xue5ed6392005-10-03 14:35:55 -0700647 ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 }
649 return 0;
650}
651
652static int ipgre_close(struct net_device *dev)
653{
Patrick McHardy2941a482006-01-08 22:05:26 -0800654 struct ip_tunnel *t = netdev_priv(dev);
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800655
Joe Perchesf97c1e02007-12-16 13:45:43 -0800656 if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
Denis V. Lunev7fee0ca2008-01-21 17:32:38 -0800657 struct in_device *in_dev;
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200658 in_dev = inetdev_by_index(t->net, t->mlink);
Eric Dumazet8723e1b2010-10-19 00:39:26 +0000659 if (in_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 ip_mc_dec_group(in_dev, t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 }
662 return 0;
663}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664#endif
665
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800666static const struct net_device_ops ipgre_netdev_ops = {
667 .ndo_init = ipgre_tunnel_init,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000668 .ndo_uninit = ip_tunnel_uninit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800669#ifdef CONFIG_NET_IPGRE_BROADCAST
670 .ndo_open = ipgre_open,
671 .ndo_stop = ipgre_close,
672#endif
Pravin B Shelarc5441932013-03-25 14:49:35 +0000673 .ndo_start_xmit = ipgre_xmit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800674 .ndo_do_ioctl = ipgre_tunnel_ioctl,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000675 .ndo_change_mtu = ip_tunnel_change_mtu,
676 .ndo_get_stats64 = ip_tunnel_get_stats64,
Nicolas Dichtel1e995842015-04-02 17:07:02 +0200677 .ndo_get_iflink = ip_tunnel_get_iflink,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800678};
679
Eric Dumazet6b78f162012-09-13 21:25:33 +0000680#define GRE_FEATURES (NETIF_F_SG | \
681 NETIF_F_FRAGLIST | \
682 NETIF_F_HIGHDMA | \
683 NETIF_F_HW_CSUM)
684
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685static void ipgre_tunnel_setup(struct net_device *dev)
686{
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800687 dev->netdev_ops = &ipgre_netdev_ops;
Nicolas Dichtel5a455272014-04-11 15:51:18 +0200688 dev->type = ARPHRD_IPGRE;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000689 ip_tunnel_setup(dev, ipgre_net_id);
690}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Pravin B Shelarc5441932013-03-25 14:49:35 +0000692static void __gre_tunnel_init(struct net_device *dev)
693{
694 struct ip_tunnel *tunnel;
Tom Herbert4565e992014-09-17 12:26:01 -0700695 int t_hlen;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000696
697 tunnel = netdev_priv(dev);
Tom Herbert95f5c642016-04-29 17:12:16 -0700698 tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000699 tunnel->parms.iph.protocol = IPPROTO_GRE;
700
Tom Herbert4565e992014-09-17 12:26:01 -0700701 tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
702
703 t_hlen = tunnel->hlen + sizeof(struct iphdr);
704
705 dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
706 dev->mtu = ETH_DATA_LEN - t_hlen - 4;
Eric Dumazet6b78f162012-09-13 21:25:33 +0000707
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200708 dev->features |= GRE_FEATURES;
Eric Dumazet6b78f162012-09-13 21:25:33 +0000709 dev->hw_features |= GRE_FEATURES;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000710
711 if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
Alexander Duycka0ca1532016-04-05 09:13:39 -0700712 /* TCP offload with GRE SEQ is not supported, nor
713 * can we support 2 levels of outer headers requiring
714 * an update.
715 */
716 if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
717 (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
718 dev->features |= NETIF_F_GSO_SOFTWARE;
719 dev->hw_features |= NETIF_F_GSO_SOFTWARE;
720 }
721
Pravin B Shelarc5441932013-03-25 14:49:35 +0000722 /* Can use a lockless transmit, unless we generate
723 * output sequences
724 */
725 dev->features |= NETIF_F_LLTX;
726 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727}
728
729static int ipgre_tunnel_init(struct net_device *dev)
730{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000731 struct ip_tunnel *tunnel = netdev_priv(dev);
732 struct iphdr *iph = &tunnel->parms.iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
Pravin B Shelarc5441932013-03-25 14:49:35 +0000734 __gre_tunnel_init(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
Pravin B Shelarc5441932013-03-25 14:49:35 +0000736 memcpy(dev->dev_addr, &iph->saddr, 4);
737 memcpy(dev->broadcast, &iph->daddr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
Pravin B Shelarc5441932013-03-25 14:49:35 +0000739 dev->flags = IFF_NOARP;
Eric Dumazet02875872014-10-05 18:38:35 -0700740 netif_keep_dst(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000741 dev->addr_len = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
Jiri Benca64b04d2016-04-27 11:29:06 +0200743 if (iph->daddr && !tunnel->collect_md) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744#ifdef CONFIG_NET_IPGRE_BROADCAST
Joe Perchesf97c1e02007-12-16 13:45:43 -0800745 if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 if (!iph->saddr)
747 return -EINVAL;
748 dev->flags = IFF_BROADCAST;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700749 dev->header_ops = &ipgre_header_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 }
751#endif
Jiri Benca64b04d2016-04-27 11:29:06 +0200752 } else if (!tunnel->collect_md) {
Timo Teras6a5f44d2007-10-23 20:31:53 -0700753 dev->header_ops = &ipgre_header_ops;
Jiri Benca64b04d2016-04-27 11:29:06 +0200754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
Pravin B Shelarc5441932013-03-25 14:49:35 +0000756 return ip_tunnel_init(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757}
758
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700759static const struct gre_protocol ipgre_protocol = {
760 .handler = gre_rcv,
761 .err_handler = gre_err,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762};
763
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +0000764static int __net_init ipgre_init_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700765{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000766 return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700767}
768
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +0000769static void __net_exit ipgre_exit_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700770{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000771 struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200772 ip_tunnel_delete_net(itn, &ipgre_link_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700773}
774
775static struct pernet_operations ipgre_net_ops = {
776 .init = ipgre_init_net,
777 .exit = ipgre_exit_net,
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +0000778 .id = &ipgre_net_id,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000779 .size = sizeof(struct ip_tunnel_net),
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700780};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
Matthias Schiffera8b8a8892017-06-25 23:56:01 +0200782static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
783 struct netlink_ext_ack *extack)
Herbert Xuc19e6542008-10-09 11:59:55 -0700784{
785 __be16 flags;
786
787 if (!data)
788 return 0;
789
790 flags = 0;
791 if (data[IFLA_GRE_IFLAGS])
792 flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
793 if (data[IFLA_GRE_OFLAGS])
794 flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
795 if (flags & (GRE_VERSION|GRE_ROUTING))
796 return -EINVAL;
797
Jiri Benc946b6362016-04-27 14:08:01 +0200798 if (data[IFLA_GRE_COLLECT_METADATA] &&
799 data[IFLA_GRE_ENCAP_TYPE] &&
800 nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
801 return -EINVAL;
802
Herbert Xuc19e6542008-10-09 11:59:55 -0700803 return 0;
804}
805
Matthias Schiffera8b8a8892017-06-25 23:56:01 +0200806static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
807 struct netlink_ext_ack *extack)
Herbert Xue1a80002008-10-09 12:00:17 -0700808{
809 __be32 daddr;
810
811 if (tb[IFLA_ADDRESS]) {
812 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
813 return -EINVAL;
814 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
815 return -EADDRNOTAVAIL;
816 }
817
818 if (!data)
819 goto out;
820
821 if (data[IFLA_GRE_REMOTE]) {
822 memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
823 if (!daddr)
824 return -EINVAL;
825 }
826
827out:
Matthias Schiffera8b8a8892017-06-25 23:56:01 +0200828 return ipgre_tunnel_validate(tb, data, extack);
Herbert Xue1a80002008-10-09 12:00:17 -0700829}
830
Philip Prindeville22a59be2016-06-14 15:53:02 -0600831static int ipgre_netlink_parms(struct net_device *dev,
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700832 struct nlattr *data[],
833 struct nlattr *tb[],
Craig Gallek9830ad42017-04-19 12:30:54 -0400834 struct ip_tunnel_parm *parms,
835 __u32 *fwmark)
Herbert Xuc19e6542008-10-09 11:59:55 -0700836{
Philip Prindeville22a59be2016-06-14 15:53:02 -0600837 struct ip_tunnel *t = netdev_priv(dev);
838
Herbert Xu7bb82d92008-10-11 12:20:15 -0700839 memset(parms, 0, sizeof(*parms));
Herbert Xuc19e6542008-10-09 11:59:55 -0700840
841 parms->iph.protocol = IPPROTO_GRE;
842
843 if (!data)
Philip Prindeville22a59be2016-06-14 15:53:02 -0600844 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -0700845
846 if (data[IFLA_GRE_LINK])
847 parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
848
849 if (data[IFLA_GRE_IFLAGS])
Pravin B Shelarc5441932013-03-25 14:49:35 +0000850 parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
Herbert Xuc19e6542008-10-09 11:59:55 -0700851
852 if (data[IFLA_GRE_OFLAGS])
Pravin B Shelarc5441932013-03-25 14:49:35 +0000853 parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
Herbert Xuc19e6542008-10-09 11:59:55 -0700854
855 if (data[IFLA_GRE_IKEY])
856 parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
857
858 if (data[IFLA_GRE_OKEY])
859 parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
860
861 if (data[IFLA_GRE_LOCAL])
Jiri Benc67b61f62015-03-29 16:59:26 +0200862 parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
Herbert Xuc19e6542008-10-09 11:59:55 -0700863
864 if (data[IFLA_GRE_REMOTE])
Jiri Benc67b61f62015-03-29 16:59:26 +0200865 parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
Herbert Xuc19e6542008-10-09 11:59:55 -0700866
867 if (data[IFLA_GRE_TTL])
868 parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
869
870 if (data[IFLA_GRE_TOS])
871 parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
872
Philip Prindeville22a59be2016-06-14 15:53:02 -0600873 if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
874 if (t->ignore_df)
875 return -EINVAL;
Herbert Xuc19e6542008-10-09 11:59:55 -0700876 parms->iph.frag_off = htons(IP_DF);
Philip Prindeville22a59be2016-06-14 15:53:02 -0600877 }
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700878
879 if (data[IFLA_GRE_COLLECT_METADATA]) {
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700880 t->collect_md = true;
Jiri Bence271c7b2016-05-11 15:53:57 +0200881 if (dev->type == ARPHRD_IPGRE)
882 dev->type = ARPHRD_NONE;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700883 }
Philip Prindeville22a59be2016-06-14 15:53:02 -0600884
885 if (data[IFLA_GRE_IGNORE_DF]) {
886 if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
887 && (parms->iph.frag_off & htons(IP_DF)))
888 return -EINVAL;
889 t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
890 }
891
Craig Gallek9830ad42017-04-19 12:30:54 -0400892 if (data[IFLA_GRE_FWMARK])
893 *fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
894
Philip Prindeville22a59be2016-06-14 15:53:02 -0600895 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -0700896}
897
Tom Herbert4565e992014-09-17 12:26:01 -0700898/* This function returns true when ENCAP attributes are present in the nl msg */
899static bool ipgre_netlink_encap_parms(struct nlattr *data[],
900 struct ip_tunnel_encap *ipencap)
901{
902 bool ret = false;
903
904 memset(ipencap, 0, sizeof(*ipencap));
905
906 if (!data)
907 return ret;
908
909 if (data[IFLA_GRE_ENCAP_TYPE]) {
910 ret = true;
911 ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
912 }
913
914 if (data[IFLA_GRE_ENCAP_FLAGS]) {
915 ret = true;
916 ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
917 }
918
919 if (data[IFLA_GRE_ENCAP_SPORT]) {
920 ret = true;
Sabrina Dubroca3e97fa72015-02-06 17:22:22 +0100921 ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
Tom Herbert4565e992014-09-17 12:26:01 -0700922 }
923
924 if (data[IFLA_GRE_ENCAP_DPORT]) {
925 ret = true;
Sabrina Dubroca3e97fa72015-02-06 17:22:22 +0100926 ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
Tom Herbert4565e992014-09-17 12:26:01 -0700927 }
928
929 return ret;
930}
931
Pravin B Shelarc5441932013-03-25 14:49:35 +0000932static int gre_tap_init(struct net_device *dev)
Herbert Xue1a80002008-10-09 12:00:17 -0700933{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000934 __gre_tunnel_init(dev);
stephen hemmingerbec94d42014-12-27 10:01:42 -0800935 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
Herbert Xue1a80002008-10-09 12:00:17 -0700936
Pravin B Shelarc5441932013-03-25 14:49:35 +0000937 return ip_tunnel_init(dev);
Herbert Xue1a80002008-10-09 12:00:17 -0700938}
939
Pravin B Shelarc5441932013-03-25 14:49:35 +0000940static const struct net_device_ops gre_tap_netdev_ops = {
941 .ndo_init = gre_tap_init,
942 .ndo_uninit = ip_tunnel_uninit,
943 .ndo_start_xmit = gre_tap_xmit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800944 .ndo_set_mac_address = eth_mac_addr,
945 .ndo_validate_addr = eth_validate_addr,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000946 .ndo_change_mtu = ip_tunnel_change_mtu,
947 .ndo_get_stats64 = ip_tunnel_get_stats64,
Nicolas Dichtel1e995842015-04-02 17:07:02 +0200948 .ndo_get_iflink = ip_tunnel_get_iflink,
Pravin B Shelarfc4099f2015-10-22 18:17:16 -0700949 .ndo_fill_metadata_dst = gre_fill_metadata_dst,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800950};
951
Herbert Xue1a80002008-10-09 12:00:17 -0700952static void ipgre_tap_setup(struct net_device *dev)
953{
Herbert Xue1a80002008-10-09 12:00:17 -0700954 ether_setup(dev);
Jiri Bencd13b1612016-02-17 15:32:53 +0100955 dev->netdev_ops = &gre_tap_netdev_ops;
956 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
957 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000958 ip_tunnel_setup(dev, gre_tap_net_id);
Herbert Xue1a80002008-10-09 12:00:17 -0700959}
960
Pravin B Shelarc5441932013-03-25 14:49:35 +0000961static int ipgre_newlink(struct net *src_net, struct net_device *dev,
Matthias Schiffer7a3f4a12017-06-25 23:55:59 +0200962 struct nlattr *tb[], struct nlattr *data[],
963 struct netlink_ext_ack *extack)
Herbert Xuc19e6542008-10-09 11:59:55 -0700964{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000965 struct ip_tunnel_parm p;
Tom Herbert4565e992014-09-17 12:26:01 -0700966 struct ip_tunnel_encap ipencap;
Craig Gallek9830ad42017-04-19 12:30:54 -0400967 __u32 fwmark = 0;
Philip Prindeville22a59be2016-06-14 15:53:02 -0600968 int err;
Tom Herbert4565e992014-09-17 12:26:01 -0700969
970 if (ipgre_netlink_encap_parms(data, &ipencap)) {
971 struct ip_tunnel *t = netdev_priv(dev);
Philip Prindeville22a59be2016-06-14 15:53:02 -0600972 err = ip_tunnel_encap_setup(t, &ipencap);
Tom Herbert4565e992014-09-17 12:26:01 -0700973
974 if (err < 0)
975 return err;
976 }
Herbert Xuc19e6542008-10-09 11:59:55 -0700977
Craig Gallek9830ad42017-04-19 12:30:54 -0400978 err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
Philip Prindeville22a59be2016-06-14 15:53:02 -0600979 if (err < 0)
980 return err;
Craig Gallek9830ad42017-04-19 12:30:54 -0400981 return ip_tunnel_newlink(dev, tb, &p, fwmark);
Herbert Xuc19e6542008-10-09 11:59:55 -0700982}
983
984static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
Matthias Schifferad744b22017-06-25 23:56:00 +0200985 struct nlattr *data[],
986 struct netlink_ext_ack *extack)
Herbert Xuc19e6542008-10-09 11:59:55 -0700987{
Craig Gallek9830ad42017-04-19 12:30:54 -0400988 struct ip_tunnel *t = netdev_priv(dev);
Herbert Xuc19e6542008-10-09 11:59:55 -0700989 struct ip_tunnel_parm p;
Tom Herbert4565e992014-09-17 12:26:01 -0700990 struct ip_tunnel_encap ipencap;
Craig Gallek9830ad42017-04-19 12:30:54 -0400991 __u32 fwmark = t->fwmark;
Philip Prindeville22a59be2016-06-14 15:53:02 -0600992 int err;
Tom Herbert4565e992014-09-17 12:26:01 -0700993
994 if (ipgre_netlink_encap_parms(data, &ipencap)) {
Philip Prindeville22a59be2016-06-14 15:53:02 -0600995 err = ip_tunnel_encap_setup(t, &ipencap);
Tom Herbert4565e992014-09-17 12:26:01 -0700996
997 if (err < 0)
998 return err;
999 }
Herbert Xuc19e6542008-10-09 11:59:55 -07001000
Craig Gallek9830ad42017-04-19 12:30:54 -04001001 err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
Philip Prindeville22a59be2016-06-14 15:53:02 -06001002 if (err < 0)
1003 return err;
Craig Gallek9830ad42017-04-19 12:30:54 -04001004 return ip_tunnel_changelink(dev, tb, &p, fwmark);
Herbert Xuc19e6542008-10-09 11:59:55 -07001005}
1006
1007static size_t ipgre_get_size(const struct net_device *dev)
1008{
1009 return
1010 /* IFLA_GRE_LINK */
1011 nla_total_size(4) +
1012 /* IFLA_GRE_IFLAGS */
1013 nla_total_size(2) +
1014 /* IFLA_GRE_OFLAGS */
1015 nla_total_size(2) +
1016 /* IFLA_GRE_IKEY */
1017 nla_total_size(4) +
1018 /* IFLA_GRE_OKEY */
1019 nla_total_size(4) +
1020 /* IFLA_GRE_LOCAL */
1021 nla_total_size(4) +
1022 /* IFLA_GRE_REMOTE */
1023 nla_total_size(4) +
1024 /* IFLA_GRE_TTL */
1025 nla_total_size(1) +
1026 /* IFLA_GRE_TOS */
1027 nla_total_size(1) +
1028 /* IFLA_GRE_PMTUDISC */
1029 nla_total_size(1) +
Tom Herbert4565e992014-09-17 12:26:01 -07001030 /* IFLA_GRE_ENCAP_TYPE */
1031 nla_total_size(2) +
1032 /* IFLA_GRE_ENCAP_FLAGS */
1033 nla_total_size(2) +
1034 /* IFLA_GRE_ENCAP_SPORT */
1035 nla_total_size(2) +
1036 /* IFLA_GRE_ENCAP_DPORT */
1037 nla_total_size(2) +
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001038 /* IFLA_GRE_COLLECT_METADATA */
1039 nla_total_size(0) +
Philip Prindeville22a59be2016-06-14 15:53:02 -06001040 /* IFLA_GRE_IGNORE_DF */
1041 nla_total_size(1) +
Craig Gallek9830ad42017-04-19 12:30:54 -04001042 /* IFLA_GRE_FWMARK */
1043 nla_total_size(4) +
Herbert Xuc19e6542008-10-09 11:59:55 -07001044 0;
1045}
1046
1047static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1048{
1049 struct ip_tunnel *t = netdev_priv(dev);
1050 struct ip_tunnel_parm *p = &t->parms;
1051
David S. Millerf3756b72012-04-01 20:39:02 -04001052 if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
Tom Herbert95f5c642016-04-29 17:12:16 -07001053 nla_put_be16(skb, IFLA_GRE_IFLAGS,
1054 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
1055 nla_put_be16(skb, IFLA_GRE_OFLAGS,
1056 gre_tnl_flags_to_gre_flags(p->o_flags)) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001057 nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1058 nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
Jiri Benc930345e2015-03-29 16:59:25 +02001059 nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1060 nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001061 nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1062 nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1063 nla_put_u8(skb, IFLA_GRE_PMTUDISC,
Craig Gallek9830ad42017-04-19 12:30:54 -04001064 !!(p->iph.frag_off & htons(IP_DF))) ||
1065 nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
David S. Millerf3756b72012-04-01 20:39:02 -04001066 goto nla_put_failure;
Tom Herbert4565e992014-09-17 12:26:01 -07001067
1068 if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
1069 t->encap.type) ||
Sabrina Dubroca3e97fa72015-02-06 17:22:22 +01001070 nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
1071 t->encap.sport) ||
1072 nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
1073 t->encap.dport) ||
Tom Herbert4565e992014-09-17 12:26:01 -07001074 nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
Tom Herberte1b2cb62014-11-05 16:49:38 -08001075 t->encap.flags))
Tom Herbert4565e992014-09-17 12:26:01 -07001076 goto nla_put_failure;
1077
Philip Prindeville22a59be2016-06-14 15:53:02 -06001078 if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
1079 goto nla_put_failure;
1080
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001081 if (t->collect_md) {
1082 if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
1083 goto nla_put_failure;
1084 }
1085
Herbert Xuc19e6542008-10-09 11:59:55 -07001086 return 0;
1087
1088nla_put_failure:
1089 return -EMSGSIZE;
1090}
1091
1092static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1093 [IFLA_GRE_LINK] = { .type = NLA_U32 },
1094 [IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
1095 [IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
1096 [IFLA_GRE_IKEY] = { .type = NLA_U32 },
1097 [IFLA_GRE_OKEY] = { .type = NLA_U32 },
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001098 [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
1099 [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
Herbert Xuc19e6542008-10-09 11:59:55 -07001100 [IFLA_GRE_TTL] = { .type = NLA_U8 },
1101 [IFLA_GRE_TOS] = { .type = NLA_U8 },
1102 [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 },
Tom Herbert4565e992014-09-17 12:26:01 -07001103 [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 },
1104 [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 },
1105 [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 },
1106 [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 },
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001107 [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG },
Philip Prindeville22a59be2016-06-14 15:53:02 -06001108 [IFLA_GRE_IGNORE_DF] = { .type = NLA_U8 },
Craig Gallek9830ad42017-04-19 12:30:54 -04001109 [IFLA_GRE_FWMARK] = { .type = NLA_U32 },
Herbert Xuc19e6542008-10-09 11:59:55 -07001110};
1111
1112static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1113 .kind = "gre",
1114 .maxtype = IFLA_GRE_MAX,
1115 .policy = ipgre_policy,
1116 .priv_size = sizeof(struct ip_tunnel),
1117 .setup = ipgre_tunnel_setup,
1118 .validate = ipgre_tunnel_validate,
1119 .newlink = ipgre_newlink,
1120 .changelink = ipgre_changelink,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001121 .dellink = ip_tunnel_dellink,
Herbert Xuc19e6542008-10-09 11:59:55 -07001122 .get_size = ipgre_get_size,
1123 .fill_info = ipgre_fill_info,
Nicolas Dichtel1728d4f2015-01-15 15:11:17 +01001124 .get_link_net = ip_tunnel_get_link_net,
Herbert Xuc19e6542008-10-09 11:59:55 -07001125};
1126
Herbert Xue1a80002008-10-09 12:00:17 -07001127static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1128 .kind = "gretap",
1129 .maxtype = IFLA_GRE_MAX,
1130 .policy = ipgre_policy,
1131 .priv_size = sizeof(struct ip_tunnel),
1132 .setup = ipgre_tap_setup,
1133 .validate = ipgre_tap_validate,
1134 .newlink = ipgre_newlink,
1135 .changelink = ipgre_changelink,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001136 .dellink = ip_tunnel_dellink,
Herbert Xue1a80002008-10-09 12:00:17 -07001137 .get_size = ipgre_get_size,
1138 .fill_info = ipgre_fill_info,
Nicolas Dichtel1728d4f2015-01-15 15:11:17 +01001139 .get_link_net = ip_tunnel_get_link_net,
Herbert Xue1a80002008-10-09 12:00:17 -07001140};
1141
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001142struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1143 u8 name_assign_type)
1144{
1145 struct nlattr *tb[IFLA_MAX + 1];
1146 struct net_device *dev;
Nicolas Dichtel106da662016-06-13 10:31:04 +02001147 LIST_HEAD(list_kill);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001148 struct ip_tunnel *t;
1149 int err;
1150
1151 memset(&tb, 0, sizeof(tb));
1152
1153 dev = rtnl_create_link(net, name, name_assign_type,
1154 &ipgre_tap_ops, tb);
1155 if (IS_ERR(dev))
1156 return dev;
1157
1158 /* Configure flow based GRE device. */
1159 t = netdev_priv(dev);
1160 t->collect_md = true;
1161
Matthias Schiffer7a3f4a12017-06-25 23:55:59 +02001162 err = ipgre_newlink(net, dev, tb, NULL, NULL);
Nicolas Dichtel106da662016-06-13 10:31:04 +02001163 if (err < 0) {
1164 free_netdev(dev);
1165 return ERR_PTR(err);
1166 }
David Wragg7e059152016-02-10 00:05:58 +00001167
1168 /* openvswitch users expect packet sizes to be unrestricted,
1169 * so set the largest MTU we can.
1170 */
1171 err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
1172 if (err)
1173 goto out;
1174
Nicolas Dichtelda6f1da2016-06-13 10:31:06 +02001175 err = rtnl_configure_link(dev, NULL);
1176 if (err < 0)
1177 goto out;
1178
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001179 return dev;
1180out:
Nicolas Dichtel106da662016-06-13 10:31:04 +02001181 ip_tunnel_dellink(dev, &list_kill);
1182 unregister_netdevice_many(&list_kill);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001183 return ERR_PTR(err);
1184}
1185EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1186
Pravin B Shelarc5441932013-03-25 14:49:35 +00001187static int __net_init ipgre_tap_init_net(struct net *net)
1188{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001189 return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
Pravin B Shelarc5441932013-03-25 14:49:35 +00001190}
1191
1192static void __net_exit ipgre_tap_exit_net(struct net *net)
1193{
1194 struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001195 ip_tunnel_delete_net(itn, &ipgre_tap_ops);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001196}
1197
1198static struct pernet_operations ipgre_tap_net_ops = {
1199 .init = ipgre_tap_init_net,
1200 .exit = ipgre_tap_exit_net,
1201 .id = &gre_tap_net_id,
1202 .size = sizeof(struct ip_tunnel_net),
1203};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
1205static int __init ipgre_init(void)
1206{
1207 int err;
1208
Joe Perches058bd4d2012-03-11 18:36:11 +00001209 pr_info("GRE over IPv4 tunneling driver\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001211 err = register_pernet_device(&ipgre_net_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001212 if (err < 0)
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001213 return err;
1214
Pravin B Shelarc5441932013-03-25 14:49:35 +00001215 err = register_pernet_device(&ipgre_tap_net_ops);
1216 if (err < 0)
1217 goto pnet_tap_faied;
1218
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001219 err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001220 if (err < 0) {
Joe Perches058bd4d2012-03-11 18:36:11 +00001221 pr_info("%s: can't add protocol\n", __func__);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001222 goto add_proto_failed;
1223 }
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001224
Herbert Xuc19e6542008-10-09 11:59:55 -07001225 err = rtnl_link_register(&ipgre_link_ops);
1226 if (err < 0)
1227 goto rtnl_link_failed;
1228
Herbert Xue1a80002008-10-09 12:00:17 -07001229 err = rtnl_link_register(&ipgre_tap_ops);
1230 if (err < 0)
1231 goto tap_ops_failed;
1232
Pravin B Shelarc5441932013-03-25 14:49:35 +00001233 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -07001234
Herbert Xue1a80002008-10-09 12:00:17 -07001235tap_ops_failed:
1236 rtnl_link_unregister(&ipgre_link_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001237rtnl_link_failed:
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001238 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001239add_proto_failed:
Pravin B Shelarc5441932013-03-25 14:49:35 +00001240 unregister_pernet_device(&ipgre_tap_net_ops);
1241pnet_tap_faied:
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001242 unregister_pernet_device(&ipgre_net_ops);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001243 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244}
1245
Alexey Kuznetsovdb445752005-07-30 17:46:44 -07001246static void __exit ipgre_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247{
Herbert Xue1a80002008-10-09 12:00:17 -07001248 rtnl_link_unregister(&ipgre_tap_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001249 rtnl_link_unregister(&ipgre_link_ops);
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001250 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001251 unregister_pernet_device(&ipgre_tap_net_ops);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001252 unregister_pernet_device(&ipgre_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253}
1254
1255module_init(ipgre_init);
1256module_exit(ipgre_fini);
1257MODULE_LICENSE("GPL");
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001258MODULE_ALIAS_RTNL_LINK("gre");
1259MODULE_ALIAS_RTNL_LINK("gretap");
Vasiliy Kulikov8909c9a2011-03-02 00:33:13 +03001260MODULE_ALIAS_NETDEV("gre0");
Pravin B Shelarc5441932013-03-25 14:49:35 +00001261MODULE_ALIAS_NETDEV("gretap0");