blob: fe1801d9f05982eb28ccde2e1d228ef7845a355a [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 Torvalds1da177e2005-04-16 15:20:36 -070020#include <asm/uaccess.h>
21#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
Eric Dumazetf99189b2009-11-17 10:42:49 +0000116static int ipgre_net_id __read_mostly;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000117static 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;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700227
Haishuang Yan53949762018-09-14 12:26:47 +0800228 if (gre_parse_header(skb, &tpi, NULL, htons(ETH_P_IP),
229 iph->ihl * 4) < 0)
230 return;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700231
232 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
233 ipv4_update_pmtu(skb, dev_net(skb->dev), info,
234 skb->dev->ifindex, 0, IPPROTO_GRE, 0);
235 return;
236 }
237 if (type == ICMP_REDIRECT) {
238 ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0,
239 IPPROTO_GRE, 0);
240 return;
241 }
242
243 ipgre_err(skb, info, &tpi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244}
245
Jiri Benc125372f2016-05-03 17:10:08 +0200246static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
247 struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700249 struct metadata_dst *tun_dst = NULL;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000250 const struct iphdr *iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 struct ip_tunnel *tunnel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700253 iph = ip_hdr(skb);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700254 tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
255 iph->saddr, iph->daddr, tpi->key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
stephen hemmingerd2083282012-09-24 18:12:23 +0000257 if (tunnel) {
Jiri Benc125372f2016-05-03 17:10:08 +0200258 if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
259 raw_proto, false) < 0)
Jiri Benc244a7972016-05-03 17:10:07 +0200260 goto drop;
261
Jiri Bence271c7b2016-05-11 15:53:57 +0200262 if (tunnel->dev->type != ARPHRD_NONE)
263 skb_pop_mac_header(skb);
264 else
265 skb_reset_mac_header(skb);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700266 if (tunnel->collect_md) {
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700267 __be16 flags;
268 __be64 tun_id;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700269
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700270 flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
Amir Vadaid817f432016-09-08 16:23:45 +0300271 tun_id = key32_to_tunnel_id(tpi->key);
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700272 tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700273 if (!tun_dst)
274 return PACKET_REJECT;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700275 }
276
277 ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700278 return PACKET_RCVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 }
Jiri Benc125372f2016-05-03 17:10:08 +0200280 return PACKET_NEXT;
Jiri Benc244a7972016-05-03 17:10:07 +0200281
282drop:
283 kfree_skb(skb);
284 return PACKET_RCVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285}
286
Jiri Benc125372f2016-05-03 17:10:08 +0200287static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
288 int hdr_len)
289{
290 struct net *net = dev_net(skb->dev);
291 struct ip_tunnel_net *itn;
292 int res;
293
294 if (tpi->proto == htons(ETH_P_TEB))
295 itn = net_generic(net, gre_tap_net_id);
296 else
297 itn = net_generic(net, ipgre_net_id);
298
299 res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
300 if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
301 /* ipgre tunnels in collect metadata mode should receive
302 * also ETH_P_TEB traffic.
303 */
304 itn = net_generic(net, ipgre_net_id);
305 res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
306 }
307 return res;
308}
309
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700310static int gre_rcv(struct sk_buff *skb)
311{
312 struct tnl_ptk_info tpi;
313 bool csum_err = false;
Tom Herbert95f5c642016-04-29 17:12:16 -0700314 int hdr_len;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700315
316#ifdef CONFIG_NET_IPGRE_BROADCAST
317 if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
318 /* Looped back packet, drop it! */
319 if (rt_is_output_route(skb_rtable(skb)))
320 goto drop;
321 }
322#endif
323
Eric Dumazete5826152016-06-15 06:24:00 -0700324 hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
Jiri Bencf132ae72016-05-03 15:00:21 +0200325 if (hdr_len < 0)
Tom Herbert95f5c642016-04-29 17:12:16 -0700326 goto drop;
327
Jiri Benc244a7972016-05-03 17:10:07 +0200328 if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700329 return 0;
330
331 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
332drop:
333 kfree_skb(skb);
334 return 0;
335}
336
Pravin B Shelarc5441932013-03-25 14:49:35 +0000337static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
338 const struct iphdr *tnl_params,
339 __be16 proto)
340{
341 struct ip_tunnel *tunnel = netdev_priv(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000342
Pravin B Shelarc5441932013-03-25 14:49:35 +0000343 if (tunnel->parms.o_flags & TUNNEL_SEQ)
344 tunnel->o_seqno++;
Eric Dumazetcef401d2013-01-25 20:34:37 +0000345
Pravin B Shelarc5441932013-03-25 14:49:35 +0000346 /* Push GRE header. */
Tom Herbert182a3522016-04-29 17:12:19 -0700347 gre_build_header(skb, tunnel->tun_hlen,
348 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
349 htonl(tunnel->o_seqno));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
Nicolas Dichtelbf3d6a82013-05-27 23:48:15 +0000351 ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352}
353
Alexander Duyckaed069d2016-04-14 15:33:37 -0400354static int gre_handle_offloads(struct sk_buff *skb, bool csum)
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -0700355{
Shreyansh Chouhan4b2937f2021-08-21 12:44:24 +0530356 if (csum && skb_checksum_start(skb) < skb->data)
357 return -EINVAL;
Edward Cree6fa79662016-02-11 21:02:31 +0000358 return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -0700359}
360
Pravin B Shelarfc4099f2015-10-22 18:17:16 -0700361static struct rtable *gre_get_rt(struct sk_buff *skb,
362 struct net_device *dev,
363 struct flowi4 *fl,
364 const struct ip_tunnel_key *key)
365{
366 struct net *net = dev_net(dev);
367
368 memset(fl, 0, sizeof(*fl));
369 fl->daddr = key->u.ipv4.dst;
370 fl->saddr = key->u.ipv4.src;
371 fl->flowi4_tos = RT_TOS(key->tos);
372 fl->flowi4_mark = skb->mark;
373 fl->flowi4_proto = IPPROTO_GRE;
374
375 return ip_route_output_key(net, fl);
376}
377
Jiri Benc20907142016-04-27 11:29:07 +0200378static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
379 __be16 proto)
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700380{
381 struct ip_tunnel_info *tun_info;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700382 const struct ip_tunnel_key *key;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100383 struct rtable *rt = NULL;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700384 struct flowi4 fl;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700385 int min_headroom;
386 int tunnel_hlen;
387 __be16 df, flags;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100388 bool use_cache;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700389 int err;
390
Jiri Benc61adedf2015-08-20 13:56:25 +0200391 tun_info = skb_tunnel_info(skb);
Jiri Benc7f9562a2015-08-28 20:48:20 +0200392 if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
393 ip_tunnel_info_af(tun_info) != AF_INET))
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700394 goto err_free_skb;
395
396 key = &tun_info->key;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100397 use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
398 if (use_cache)
399 rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl.saddr);
Paolo Abeni3c1cb4d2016-02-12 15:43:59 +0100400 if (!rt) {
401 rt = gre_get_rt(skb, dev, &fl, key);
402 if (IS_ERR(rt))
403 goto err_free_skb;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100404 if (use_cache)
Paolo Abeni3c1cb4d2016-02-12 15:43:59 +0100405 dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
406 fl.saddr);
407 }
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700408
Tom Herbert95f5c642016-04-29 17:12:16 -0700409 tunnel_hlen = gre_calc_hlen(key->tun_flags);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700410
411 min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
412 + tunnel_hlen + sizeof(struct iphdr);
413 if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
414 int head_delta = SKB_DATA_ALIGN(min_headroom -
415 skb_headroom(skb) +
416 16);
417 err = pskb_expand_head(skb, max_t(int, head_delta, 0),
418 0, GFP_ATOMIC);
419 if (unlikely(err))
420 goto err_free_rt;
421 }
422
423 /* Push Tunnel header. */
Alexander Duyckaed069d2016-04-14 15:33:37 -0400424 if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700425 goto err_free_rt;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700426
427 flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
David S. Millercba653212016-05-04 00:52:29 -0400428 gre_build_header(skb, tunnel_hlen, flags, proto,
Amir Vadaid817f432016-09-08 16:23:45 +0300429 tunnel_id_to_key32(tun_info->key.tun_id), 0);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700430
431 df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
Pravin B Shelar039f5062015-12-24 14:34:54 -0800432
433 iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
434 key->tos, key->ttl, df, false);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700435 return;
436
437err_free_rt:
438 ip_rt_put(rt);
439err_free_skb:
440 kfree_skb(skb);
441 dev->stats.tx_dropped++;
442}
443
Pravin B Shelarfc4099f2015-10-22 18:17:16 -0700444static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
445{
446 struct ip_tunnel_info *info = skb_tunnel_info(skb);
447 struct rtable *rt;
448 struct flowi4 fl4;
449
450 if (ip_tunnel_info_af(info) != AF_INET)
451 return -EINVAL;
452
453 rt = gre_get_rt(skb, dev, &fl4, &info->key);
454 if (IS_ERR(rt))
455 return PTR_ERR(rt);
456
457 ip_rt_put(rt);
458 info->key.u.ipv4.src = fl4.saddr;
459 return 0;
460}
461
Pravin B Shelarc5441932013-03-25 14:49:35 +0000462static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
463 struct net_device *dev)
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800464{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000465 struct ip_tunnel *tunnel = netdev_priv(dev);
466 const struct iphdr *tnl_params;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800467
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700468 if (tunnel->collect_md) {
Jiri Benc20907142016-04-27 11:29:07 +0200469 gre_fb_xmit(skb, dev, skb->protocol);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700470 return NETDEV_TX_OK;
471 }
472
Pravin B Shelarc5441932013-03-25 14:49:35 +0000473 if (dev->header_ops) {
474 /* Need space for new headers */
475 if (skb_cow_head(skb, dev->needed_headroom -
Chen Gang2bac7cb2013-04-22 20:45:42 +0000476 (tunnel->hlen + sizeof(struct iphdr))))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000477 goto free_skb;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800478
Pravin B Shelarc5441932013-03-25 14:49:35 +0000479 tnl_params = (const struct iphdr *)skb->data;
Eric Dumazete985aad2010-09-27 03:57:11 +0000480
Pravin B Shelarc5441932013-03-25 14:49:35 +0000481 /* Pull skb since ip_tunnel_xmit() needs skb->data pointing
482 * to gre header.
483 */
484 skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
Timo Teräs8a0033a2014-12-15 09:24:13 +0200485 skb_reset_mac_header(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000486 } else {
487 if (skb_cow_head(skb, dev->needed_headroom))
488 goto free_skb;
Herbert Xue1a80002008-10-09 12:00:17 -0700489
Pravin B Shelarc5441932013-03-25 14:49:35 +0000490 tnl_params = &tunnel->parms.iph;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800491 }
492
Alexander Duyckaed069d2016-04-14 15:33:37 -0400493 if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
494 goto free_skb;
Timo Teräs8a0033a2014-12-15 09:24:13 +0200495
Pravin B Shelarc5441932013-03-25 14:49:35 +0000496 __gre_xmit(skb, dev, tnl_params, skb->protocol);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000497 return NETDEV_TX_OK;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800498
Pravin B Shelarc5441932013-03-25 14:49:35 +0000499free_skb:
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800500 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000501 dev->stats.tx_dropped++;
502 return NETDEV_TX_OK;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800503}
504
Pravin B Shelarc5441932013-03-25 14:49:35 +0000505static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
506 struct net_device *dev)
507{
508 struct ip_tunnel *tunnel = netdev_priv(dev);
509
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700510 if (tunnel->collect_md) {
Jiri Benc20907142016-04-27 11:29:07 +0200511 gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700512 return NETDEV_TX_OK;
513 }
514
Alexander Duyckaed069d2016-04-14 15:33:37 -0400515 if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
516 goto free_skb;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000517
518 if (skb_cow_head(skb, dev->needed_headroom))
519 goto free_skb;
520
521 __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
Pravin B Shelarc5441932013-03-25 14:49:35 +0000522 return NETDEV_TX_OK;
523
524free_skb:
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800525 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000526 dev->stats.tx_dropped++;
527 return NETDEV_TX_OK;
528}
529
530static int ipgre_tunnel_ioctl(struct net_device *dev,
531 struct ifreq *ifr, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532{
Tom Herbert4565e992014-09-17 12:26:01 -0700533 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 struct ip_tunnel_parm p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
Pravin B Shelarc5441932013-03-25 14:49:35 +0000536 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
537 return -EFAULT;
Cong Wang6c734fb2013-06-29 12:02:59 +0800538 if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
539 if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
540 p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
541 ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
542 return -EINVAL;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000543 }
544 p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
545 p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
546
547 err = ip_tunnel_ioctl(dev, &p, cmd);
548 if (err)
549 return err;
550
Tom Herbert95f5c642016-04-29 17:12:16 -0700551 p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
552 p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000553
554 if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
555 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 return 0;
557}
558
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559/* Nice toy. Unfortunately, useless in real life :-)
560 It allows to construct virtual multiprotocol broadcast "LAN"
561 over the Internet, provided multicast routing is tuned.
562
563
564 I have no idea was this bicycle invented before me,
565 so that I had to set ARPHRD_IPGRE to a random value.
566 I have an impression, that Cisco could make something similar,
567 but this feature is apparently missing in IOS<=11.2(8).
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900568
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
570 with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
571
572 ping -t 255 224.66.66.66
573
574 If nobody answers, mbone does not work.
575
576 ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
577 ip addr add 10.66.66.<somewhat>/24 dev Universe
578 ifconfig Universe up
579 ifconfig Universe add fe80::<Your_real_addr>/10
580 ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
581 ftp 10.66.66.66
582 ...
583 ftp fec0:6666:6666::193.233.7.65
584 ...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 */
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700586static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
587 unsigned short type,
Eric Dumazet15078502010-09-15 11:07:53 +0000588 const void *daddr, const void *saddr, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589{
Patrick McHardy2941a482006-01-08 22:05:26 -0800590 struct ip_tunnel *t = netdev_priv(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000591 struct iphdr *iph;
592 struct gre_base_hdr *greh;
593
594 iph = (struct iphdr *)skb_push(skb, t->hlen + sizeof(*iph));
595 greh = (struct gre_base_hdr *)(iph+1);
Tom Herbert95f5c642016-04-29 17:12:16 -0700596 greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000597 greh->protocol = htons(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
599 memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Pravin B Shelarc5441932013-03-25 14:49:35 +0000601 /* Set the source hardware address. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 if (saddr)
603 memcpy(&iph->saddr, saddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +0000604 if (daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 memcpy(&iph->daddr, daddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +0000606 if (iph->daddr)
Timo Teräs77a482b2013-08-06 13:45:43 +0300607 return t->hlen + sizeof(*iph);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900608
Pravin B Shelarc5441932013-03-25 14:49:35 +0000609 return -(t->hlen + sizeof(*iph));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610}
611
Timo Teras6a5f44d2007-10-23 20:31:53 -0700612static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
613{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000614 const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
Timo Teras6a5f44d2007-10-23 20:31:53 -0700615 memcpy(haddr, &iph->saddr, 4);
616 return 4;
617}
618
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700619static const struct header_ops ipgre_header_ops = {
620 .create = ipgre_header,
Timo Teras6a5f44d2007-10-23 20:31:53 -0700621 .parse = ipgre_header_parse,
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700622};
623
Timo Teras6a5f44d2007-10-23 20:31:53 -0700624#ifdef CONFIG_NET_IPGRE_BROADCAST
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625static int ipgre_open(struct net_device *dev)
626{
Patrick McHardy2941a482006-01-08 22:05:26 -0800627 struct ip_tunnel *t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
Joe Perchesf97c1e02007-12-16 13:45:43 -0800629 if (ipv4_is_multicast(t->parms.iph.daddr)) {
David S. Millercbb1e852011-05-04 12:33:34 -0700630 struct flowi4 fl4;
631 struct rtable *rt;
Eric Dumazete985aad2010-09-27 03:57:11 +0000632
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200633 rt = ip_route_output_gre(t->net, &fl4,
David S. Millercbb1e852011-05-04 12:33:34 -0700634 t->parms.iph.daddr,
635 t->parms.iph.saddr,
636 t->parms.o_key,
637 RT_TOS(t->parms.iph.tos),
638 t->parms.link);
David S. Millerb23dd4f2011-03-02 14:31:35 -0800639 if (IS_ERR(rt))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 return -EADDRNOTAVAIL;
Changli Gaod8d1f302010-06-10 23:31:35 -0700641 dev = rt->dst.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 ip_rt_put(rt);
Ian Morris51456b22015-04-03 09:17:26 +0100643 if (!__in_dev_get_rtnl(dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 return -EADDRNOTAVAIL;
645 t->mlink = dev->ifindex;
Herbert Xue5ed6392005-10-03 14:35:55 -0700646 ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 }
648 return 0;
649}
650
651static int ipgre_close(struct net_device *dev)
652{
Patrick McHardy2941a482006-01-08 22:05:26 -0800653 struct ip_tunnel *t = netdev_priv(dev);
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800654
Joe Perchesf97c1e02007-12-16 13:45:43 -0800655 if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
Denis V. Lunev7fee0ca2008-01-21 17:32:38 -0800656 struct in_device *in_dev;
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200657 in_dev = inetdev_by_index(t->net, t->mlink);
Eric Dumazet8723e1b2010-10-19 00:39:26 +0000658 if (in_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 ip_mc_dec_group(in_dev, t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 }
661 return 0;
662}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663#endif
664
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800665static const struct net_device_ops ipgre_netdev_ops = {
666 .ndo_init = ipgre_tunnel_init,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000667 .ndo_uninit = ip_tunnel_uninit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800668#ifdef CONFIG_NET_IPGRE_BROADCAST
669 .ndo_open = ipgre_open,
670 .ndo_stop = ipgre_close,
671#endif
Pravin B Shelarc5441932013-03-25 14:49:35 +0000672 .ndo_start_xmit = ipgre_xmit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800673 .ndo_do_ioctl = ipgre_tunnel_ioctl,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000674 .ndo_change_mtu = ip_tunnel_change_mtu,
675 .ndo_get_stats64 = ip_tunnel_get_stats64,
Nicolas Dichtel1e995842015-04-02 17:07:02 +0200676 .ndo_get_iflink = ip_tunnel_get_iflink,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800677};
678
Eric Dumazet6b78f162012-09-13 21:25:33 +0000679#define GRE_FEATURES (NETIF_F_SG | \
680 NETIF_F_FRAGLIST | \
681 NETIF_F_HIGHDMA | \
682 NETIF_F_HW_CSUM)
683
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684static void ipgre_tunnel_setup(struct net_device *dev)
685{
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800686 dev->netdev_ops = &ipgre_netdev_ops;
Nicolas Dichtel5a455272014-04-11 15:51:18 +0200687 dev->type = ARPHRD_IPGRE;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000688 ip_tunnel_setup(dev, ipgre_net_id);
689}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
Pravin B Shelarc5441932013-03-25 14:49:35 +0000691static void __gre_tunnel_init(struct net_device *dev)
692{
693 struct ip_tunnel *tunnel;
Tom Herbert4565e992014-09-17 12:26:01 -0700694 int t_hlen;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000695
696 tunnel = netdev_priv(dev);
Tom Herbert95f5c642016-04-29 17:12:16 -0700697 tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000698 tunnel->parms.iph.protocol = IPPROTO_GRE;
699
Tom Herbert4565e992014-09-17 12:26:01 -0700700 tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
701
702 t_hlen = tunnel->hlen + sizeof(struct iphdr);
703
704 dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
705 dev->mtu = ETH_DATA_LEN - t_hlen - 4;
Eric Dumazet6b78f162012-09-13 21:25:33 +0000706
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200707 dev->features |= GRE_FEATURES;
Eric Dumazet6b78f162012-09-13 21:25:33 +0000708 dev->hw_features |= GRE_FEATURES;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000709
710 if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
Alexander Duycka0ca1532016-04-05 09:13:39 -0700711 /* TCP offload with GRE SEQ is not supported, nor
712 * can we support 2 levels of outer headers requiring
713 * an update.
714 */
715 if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
716 (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
717 dev->features |= NETIF_F_GSO_SOFTWARE;
718 dev->hw_features |= NETIF_F_GSO_SOFTWARE;
719 }
720
Pravin B Shelarc5441932013-03-25 14:49:35 +0000721 /* Can use a lockless transmit, unless we generate
722 * output sequences
723 */
724 dev->features |= NETIF_F_LLTX;
725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726}
727
728static int ipgre_tunnel_init(struct net_device *dev)
729{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000730 struct ip_tunnel *tunnel = netdev_priv(dev);
731 struct iphdr *iph = &tunnel->parms.iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
Pravin B Shelarc5441932013-03-25 14:49:35 +0000733 __gre_tunnel_init(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
Pravin B Shelarc5441932013-03-25 14:49:35 +0000735 memcpy(dev->dev_addr, &iph->saddr, 4);
736 memcpy(dev->broadcast, &iph->daddr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
Pravin B Shelarc5441932013-03-25 14:49:35 +0000738 dev->flags = IFF_NOARP;
Eric Dumazet02875872014-10-05 18:38:35 -0700739 netif_keep_dst(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000740 dev->addr_len = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Jiri Benca64b04d2016-04-27 11:29:06 +0200742 if (iph->daddr && !tunnel->collect_md) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743#ifdef CONFIG_NET_IPGRE_BROADCAST
Joe Perchesf97c1e02007-12-16 13:45:43 -0800744 if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 if (!iph->saddr)
746 return -EINVAL;
747 dev->flags = IFF_BROADCAST;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700748 dev->header_ops = &ipgre_header_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 }
750#endif
Jiri Benca64b04d2016-04-27 11:29:06 +0200751 } else if (!tunnel->collect_md) {
Timo Teras6a5f44d2007-10-23 20:31:53 -0700752 dev->header_ops = &ipgre_header_ops;
Jiri Benca64b04d2016-04-27 11:29:06 +0200753 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
Pravin B Shelarc5441932013-03-25 14:49:35 +0000755 return ip_tunnel_init(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756}
757
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700758static const struct gre_protocol ipgre_protocol = {
759 .handler = gre_rcv,
760 .err_handler = gre_err,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761};
762
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +0000763static int __net_init ipgre_init_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700764{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000765 return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700766}
767
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +0000768static void __net_exit ipgre_exit_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700769{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000770 struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200771 ip_tunnel_delete_net(itn, &ipgre_link_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700772}
773
774static struct pernet_operations ipgre_net_ops = {
775 .init = ipgre_init_net,
776 .exit = ipgre_exit_net,
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +0000777 .id = &ipgre_net_id,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000778 .size = sizeof(struct ip_tunnel_net),
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700779};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
Herbert Xuc19e6542008-10-09 11:59:55 -0700781static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
782{
783 __be16 flags;
784
785 if (!data)
786 return 0;
787
788 flags = 0;
789 if (data[IFLA_GRE_IFLAGS])
790 flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
791 if (data[IFLA_GRE_OFLAGS])
792 flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
793 if (flags & (GRE_VERSION|GRE_ROUTING))
794 return -EINVAL;
795
Jiri Benc946b6362016-04-27 14:08:01 +0200796 if (data[IFLA_GRE_COLLECT_METADATA] &&
797 data[IFLA_GRE_ENCAP_TYPE] &&
798 nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
799 return -EINVAL;
800
Herbert Xuc19e6542008-10-09 11:59:55 -0700801 return 0;
802}
803
Herbert Xue1a80002008-10-09 12:00:17 -0700804static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
805{
806 __be32 daddr;
807
808 if (tb[IFLA_ADDRESS]) {
809 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
810 return -EINVAL;
811 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
812 return -EADDRNOTAVAIL;
813 }
814
815 if (!data)
816 goto out;
817
818 if (data[IFLA_GRE_REMOTE]) {
819 memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
820 if (!daddr)
821 return -EINVAL;
822 }
823
824out:
825 return ipgre_tunnel_validate(tb, data);
826}
827
Philip Prindeville22a59be2016-06-14 15:53:02 -0600828static int ipgre_netlink_parms(struct net_device *dev,
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700829 struct nlattr *data[],
830 struct nlattr *tb[],
831 struct ip_tunnel_parm *parms)
Herbert Xuc19e6542008-10-09 11:59:55 -0700832{
Philip Prindeville22a59be2016-06-14 15:53:02 -0600833 struct ip_tunnel *t = netdev_priv(dev);
834
Herbert Xu7bb82d92008-10-11 12:20:15 -0700835 memset(parms, 0, sizeof(*parms));
Herbert Xuc19e6542008-10-09 11:59:55 -0700836
837 parms->iph.protocol = IPPROTO_GRE;
838
839 if (!data)
Philip Prindeville22a59be2016-06-14 15:53:02 -0600840 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -0700841
842 if (data[IFLA_GRE_LINK])
843 parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
844
845 if (data[IFLA_GRE_IFLAGS])
Pravin B Shelarc5441932013-03-25 14:49:35 +0000846 parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
Herbert Xuc19e6542008-10-09 11:59:55 -0700847
848 if (data[IFLA_GRE_OFLAGS])
Pravin B Shelarc5441932013-03-25 14:49:35 +0000849 parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
Herbert Xuc19e6542008-10-09 11:59:55 -0700850
851 if (data[IFLA_GRE_IKEY])
852 parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
853
854 if (data[IFLA_GRE_OKEY])
855 parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
856
857 if (data[IFLA_GRE_LOCAL])
Jiri Benc67b61f62015-03-29 16:59:26 +0200858 parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
Herbert Xuc19e6542008-10-09 11:59:55 -0700859
860 if (data[IFLA_GRE_REMOTE])
Jiri Benc67b61f62015-03-29 16:59:26 +0200861 parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
Herbert Xuc19e6542008-10-09 11:59:55 -0700862
863 if (data[IFLA_GRE_TTL])
864 parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
865
866 if (data[IFLA_GRE_TOS])
867 parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
868
Philip Prindeville22a59be2016-06-14 15:53:02 -0600869 if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
870 if (t->ignore_df)
871 return -EINVAL;
Herbert Xuc19e6542008-10-09 11:59:55 -0700872 parms->iph.frag_off = htons(IP_DF);
Philip Prindeville22a59be2016-06-14 15:53:02 -0600873 }
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700874
875 if (data[IFLA_GRE_COLLECT_METADATA]) {
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700876 t->collect_md = true;
Jiri Bence271c7b2016-05-11 15:53:57 +0200877 if (dev->type == ARPHRD_IPGRE)
878 dev->type = ARPHRD_NONE;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700879 }
Philip Prindeville22a59be2016-06-14 15:53:02 -0600880
881 if (data[IFLA_GRE_IGNORE_DF]) {
882 if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
883 && (parms->iph.frag_off & htons(IP_DF)))
884 return -EINVAL;
885 t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
886 }
887
888 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -0700889}
890
Tom Herbert4565e992014-09-17 12:26:01 -0700891/* This function returns true when ENCAP attributes are present in the nl msg */
892static bool ipgre_netlink_encap_parms(struct nlattr *data[],
893 struct ip_tunnel_encap *ipencap)
894{
895 bool ret = false;
896
897 memset(ipencap, 0, sizeof(*ipencap));
898
899 if (!data)
900 return ret;
901
902 if (data[IFLA_GRE_ENCAP_TYPE]) {
903 ret = true;
904 ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
905 }
906
907 if (data[IFLA_GRE_ENCAP_FLAGS]) {
908 ret = true;
909 ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
910 }
911
912 if (data[IFLA_GRE_ENCAP_SPORT]) {
913 ret = true;
Sabrina Dubroca3e97fa72015-02-06 17:22:22 +0100914 ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
Tom Herbert4565e992014-09-17 12:26:01 -0700915 }
916
917 if (data[IFLA_GRE_ENCAP_DPORT]) {
918 ret = true;
Sabrina Dubroca3e97fa72015-02-06 17:22:22 +0100919 ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
Tom Herbert4565e992014-09-17 12:26:01 -0700920 }
921
922 return ret;
923}
924
Pravin B Shelarc5441932013-03-25 14:49:35 +0000925static int gre_tap_init(struct net_device *dev)
Herbert Xue1a80002008-10-09 12:00:17 -0700926{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000927 __gre_tunnel_init(dev);
stephen hemmingerbec94d42014-12-27 10:01:42 -0800928 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
Herbert Xue1a80002008-10-09 12:00:17 -0700929
Pravin B Shelarc5441932013-03-25 14:49:35 +0000930 return ip_tunnel_init(dev);
Herbert Xue1a80002008-10-09 12:00:17 -0700931}
932
Pravin B Shelarc5441932013-03-25 14:49:35 +0000933static const struct net_device_ops gre_tap_netdev_ops = {
934 .ndo_init = gre_tap_init,
935 .ndo_uninit = ip_tunnel_uninit,
936 .ndo_start_xmit = gre_tap_xmit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800937 .ndo_set_mac_address = eth_mac_addr,
938 .ndo_validate_addr = eth_validate_addr,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000939 .ndo_change_mtu = ip_tunnel_change_mtu,
940 .ndo_get_stats64 = ip_tunnel_get_stats64,
Nicolas Dichtel1e995842015-04-02 17:07:02 +0200941 .ndo_get_iflink = ip_tunnel_get_iflink,
Pravin B Shelarfc4099f2015-10-22 18:17:16 -0700942 .ndo_fill_metadata_dst = gre_fill_metadata_dst,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800943};
944
Herbert Xue1a80002008-10-09 12:00:17 -0700945static void ipgre_tap_setup(struct net_device *dev)
946{
Herbert Xue1a80002008-10-09 12:00:17 -0700947 ether_setup(dev);
Jiri Bencd13b1612016-02-17 15:32:53 +0100948 dev->netdev_ops = &gre_tap_netdev_ops;
949 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
950 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000951 ip_tunnel_setup(dev, gre_tap_net_id);
Herbert Xue1a80002008-10-09 12:00:17 -0700952}
953
Pravin B Shelarc5441932013-03-25 14:49:35 +0000954static int ipgre_newlink(struct net *src_net, struct net_device *dev,
955 struct nlattr *tb[], struct nlattr *data[])
Herbert Xuc19e6542008-10-09 11:59:55 -0700956{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000957 struct ip_tunnel_parm p;
Tom Herbert4565e992014-09-17 12:26:01 -0700958 struct ip_tunnel_encap ipencap;
Philip Prindeville22a59be2016-06-14 15:53:02 -0600959 int err;
Tom Herbert4565e992014-09-17 12:26:01 -0700960
961 if (ipgre_netlink_encap_parms(data, &ipencap)) {
962 struct ip_tunnel *t = netdev_priv(dev);
Philip Prindeville22a59be2016-06-14 15:53:02 -0600963 err = ip_tunnel_encap_setup(t, &ipencap);
Tom Herbert4565e992014-09-17 12:26:01 -0700964
965 if (err < 0)
966 return err;
967 }
Herbert Xuc19e6542008-10-09 11:59:55 -0700968
Philip Prindeville22a59be2016-06-14 15:53:02 -0600969 err = ipgre_netlink_parms(dev, data, tb, &p);
970 if (err < 0)
971 return err;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000972 return ip_tunnel_newlink(dev, tb, &p);
Herbert Xuc19e6542008-10-09 11:59:55 -0700973}
974
975static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
976 struct nlattr *data[])
977{
Herbert Xuc19e6542008-10-09 11:59:55 -0700978 struct ip_tunnel_parm p;
Tom Herbert4565e992014-09-17 12:26:01 -0700979 struct ip_tunnel_encap ipencap;
Philip Prindeville22a59be2016-06-14 15:53:02 -0600980 int err;
Tom Herbert4565e992014-09-17 12:26:01 -0700981
982 if (ipgre_netlink_encap_parms(data, &ipencap)) {
983 struct ip_tunnel *t = netdev_priv(dev);
Philip Prindeville22a59be2016-06-14 15:53:02 -0600984 err = ip_tunnel_encap_setup(t, &ipencap);
Tom Herbert4565e992014-09-17 12:26:01 -0700985
986 if (err < 0)
987 return err;
988 }
Herbert Xuc19e6542008-10-09 11:59:55 -0700989
Philip Prindeville22a59be2016-06-14 15:53:02 -0600990 err = ipgre_netlink_parms(dev, data, tb, &p);
991 if (err < 0)
992 return err;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000993 return ip_tunnel_changelink(dev, tb, &p);
Herbert Xuc19e6542008-10-09 11:59:55 -0700994}
995
996static size_t ipgre_get_size(const struct net_device *dev)
997{
998 return
999 /* IFLA_GRE_LINK */
1000 nla_total_size(4) +
1001 /* IFLA_GRE_IFLAGS */
1002 nla_total_size(2) +
1003 /* IFLA_GRE_OFLAGS */
1004 nla_total_size(2) +
1005 /* IFLA_GRE_IKEY */
1006 nla_total_size(4) +
1007 /* IFLA_GRE_OKEY */
1008 nla_total_size(4) +
1009 /* IFLA_GRE_LOCAL */
1010 nla_total_size(4) +
1011 /* IFLA_GRE_REMOTE */
1012 nla_total_size(4) +
1013 /* IFLA_GRE_TTL */
1014 nla_total_size(1) +
1015 /* IFLA_GRE_TOS */
1016 nla_total_size(1) +
1017 /* IFLA_GRE_PMTUDISC */
1018 nla_total_size(1) +
Tom Herbert4565e992014-09-17 12:26:01 -07001019 /* IFLA_GRE_ENCAP_TYPE */
1020 nla_total_size(2) +
1021 /* IFLA_GRE_ENCAP_FLAGS */
1022 nla_total_size(2) +
1023 /* IFLA_GRE_ENCAP_SPORT */
1024 nla_total_size(2) +
1025 /* IFLA_GRE_ENCAP_DPORT */
1026 nla_total_size(2) +
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001027 /* IFLA_GRE_COLLECT_METADATA */
1028 nla_total_size(0) +
Philip Prindeville22a59be2016-06-14 15:53:02 -06001029 /* IFLA_GRE_IGNORE_DF */
1030 nla_total_size(1) +
Herbert Xuc19e6542008-10-09 11:59:55 -07001031 0;
1032}
1033
1034static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1035{
1036 struct ip_tunnel *t = netdev_priv(dev);
1037 struct ip_tunnel_parm *p = &t->parms;
1038
David S. Millerf3756b72012-04-01 20:39:02 -04001039 if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
Tom Herbert95f5c642016-04-29 17:12:16 -07001040 nla_put_be16(skb, IFLA_GRE_IFLAGS,
1041 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
1042 nla_put_be16(skb, IFLA_GRE_OFLAGS,
1043 gre_tnl_flags_to_gre_flags(p->o_flags)) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001044 nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1045 nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
Jiri Benc930345e2015-03-29 16:59:25 +02001046 nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1047 nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001048 nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1049 nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1050 nla_put_u8(skb, IFLA_GRE_PMTUDISC,
1051 !!(p->iph.frag_off & htons(IP_DF))))
1052 goto nla_put_failure;
Tom Herbert4565e992014-09-17 12:26:01 -07001053
1054 if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
1055 t->encap.type) ||
Sabrina Dubroca3e97fa72015-02-06 17:22:22 +01001056 nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
1057 t->encap.sport) ||
1058 nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
1059 t->encap.dport) ||
Tom Herbert4565e992014-09-17 12:26:01 -07001060 nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
Tom Herberte1b2cb62014-11-05 16:49:38 -08001061 t->encap.flags))
Tom Herbert4565e992014-09-17 12:26:01 -07001062 goto nla_put_failure;
1063
Philip Prindeville22a59be2016-06-14 15:53:02 -06001064 if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
1065 goto nla_put_failure;
1066
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001067 if (t->collect_md) {
1068 if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
1069 goto nla_put_failure;
1070 }
1071
Herbert Xuc19e6542008-10-09 11:59:55 -07001072 return 0;
1073
1074nla_put_failure:
1075 return -EMSGSIZE;
1076}
1077
1078static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1079 [IFLA_GRE_LINK] = { .type = NLA_U32 },
1080 [IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
1081 [IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
1082 [IFLA_GRE_IKEY] = { .type = NLA_U32 },
1083 [IFLA_GRE_OKEY] = { .type = NLA_U32 },
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001084 [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
1085 [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
Herbert Xuc19e6542008-10-09 11:59:55 -07001086 [IFLA_GRE_TTL] = { .type = NLA_U8 },
1087 [IFLA_GRE_TOS] = { .type = NLA_U8 },
1088 [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 },
Tom Herbert4565e992014-09-17 12:26:01 -07001089 [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 },
1090 [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 },
1091 [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 },
1092 [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 },
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001093 [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG },
Philip Prindeville22a59be2016-06-14 15:53:02 -06001094 [IFLA_GRE_IGNORE_DF] = { .type = NLA_U8 },
Herbert Xuc19e6542008-10-09 11:59:55 -07001095};
1096
1097static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1098 .kind = "gre",
1099 .maxtype = IFLA_GRE_MAX,
1100 .policy = ipgre_policy,
1101 .priv_size = sizeof(struct ip_tunnel),
1102 .setup = ipgre_tunnel_setup,
1103 .validate = ipgre_tunnel_validate,
1104 .newlink = ipgre_newlink,
1105 .changelink = ipgre_changelink,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001106 .dellink = ip_tunnel_dellink,
Herbert Xuc19e6542008-10-09 11:59:55 -07001107 .get_size = ipgre_get_size,
1108 .fill_info = ipgre_fill_info,
Nicolas Dichtel1728d4f2015-01-15 15:11:17 +01001109 .get_link_net = ip_tunnel_get_link_net,
Herbert Xuc19e6542008-10-09 11:59:55 -07001110};
1111
Herbert Xue1a80002008-10-09 12:00:17 -07001112static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1113 .kind = "gretap",
1114 .maxtype = IFLA_GRE_MAX,
1115 .policy = ipgre_policy,
1116 .priv_size = sizeof(struct ip_tunnel),
1117 .setup = ipgre_tap_setup,
1118 .validate = ipgre_tap_validate,
1119 .newlink = ipgre_newlink,
1120 .changelink = ipgre_changelink,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001121 .dellink = ip_tunnel_dellink,
Herbert Xue1a80002008-10-09 12:00:17 -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 Xue1a80002008-10-09 12:00:17 -07001125};
1126
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001127struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1128 u8 name_assign_type)
1129{
1130 struct nlattr *tb[IFLA_MAX + 1];
1131 struct net_device *dev;
Nicolas Dichtel106da662016-06-13 10:31:04 +02001132 LIST_HEAD(list_kill);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001133 struct ip_tunnel *t;
1134 int err;
1135
1136 memset(&tb, 0, sizeof(tb));
1137
1138 dev = rtnl_create_link(net, name, name_assign_type,
1139 &ipgre_tap_ops, tb);
1140 if (IS_ERR(dev))
1141 return dev;
1142
1143 /* Configure flow based GRE device. */
1144 t = netdev_priv(dev);
1145 t->collect_md = true;
1146
1147 err = ipgre_newlink(net, dev, tb, NULL);
Nicolas Dichtel106da662016-06-13 10:31:04 +02001148 if (err < 0) {
1149 free_netdev(dev);
1150 return ERR_PTR(err);
1151 }
David Wragg7e059152016-02-10 00:05:58 +00001152
1153 /* openvswitch users expect packet sizes to be unrestricted,
1154 * so set the largest MTU we can.
1155 */
1156 err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
1157 if (err)
1158 goto out;
1159
Nicolas Dichtelda6f1da2016-06-13 10:31:06 +02001160 err = rtnl_configure_link(dev, NULL);
1161 if (err < 0)
1162 goto out;
1163
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001164 return dev;
1165out:
Nicolas Dichtel106da662016-06-13 10:31:04 +02001166 ip_tunnel_dellink(dev, &list_kill);
1167 unregister_netdevice_many(&list_kill);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001168 return ERR_PTR(err);
1169}
1170EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1171
Pravin B Shelarc5441932013-03-25 14:49:35 +00001172static int __net_init ipgre_tap_init_net(struct net *net)
1173{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001174 return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
Pravin B Shelarc5441932013-03-25 14:49:35 +00001175}
1176
1177static void __net_exit ipgre_tap_exit_net(struct net *net)
1178{
1179 struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001180 ip_tunnel_delete_net(itn, &ipgre_tap_ops);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001181}
1182
1183static struct pernet_operations ipgre_tap_net_ops = {
1184 .init = ipgre_tap_init_net,
1185 .exit = ipgre_tap_exit_net,
1186 .id = &gre_tap_net_id,
1187 .size = sizeof(struct ip_tunnel_net),
1188};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189
1190static int __init ipgre_init(void)
1191{
1192 int err;
1193
Joe Perches058bd4d2012-03-11 18:36:11 +00001194 pr_info("GRE over IPv4 tunneling driver\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001196 err = register_pernet_device(&ipgre_net_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001197 if (err < 0)
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001198 return err;
1199
Pravin B Shelarc5441932013-03-25 14:49:35 +00001200 err = register_pernet_device(&ipgre_tap_net_ops);
1201 if (err < 0)
1202 goto pnet_tap_faied;
1203
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001204 err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001205 if (err < 0) {
Joe Perches058bd4d2012-03-11 18:36:11 +00001206 pr_info("%s: can't add protocol\n", __func__);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001207 goto add_proto_failed;
1208 }
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001209
Herbert Xuc19e6542008-10-09 11:59:55 -07001210 err = rtnl_link_register(&ipgre_link_ops);
1211 if (err < 0)
1212 goto rtnl_link_failed;
1213
Herbert Xue1a80002008-10-09 12:00:17 -07001214 err = rtnl_link_register(&ipgre_tap_ops);
1215 if (err < 0)
1216 goto tap_ops_failed;
1217
Pravin B Shelarc5441932013-03-25 14:49:35 +00001218 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -07001219
Herbert Xue1a80002008-10-09 12:00:17 -07001220tap_ops_failed:
1221 rtnl_link_unregister(&ipgre_link_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001222rtnl_link_failed:
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001223 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001224add_proto_failed:
Pravin B Shelarc5441932013-03-25 14:49:35 +00001225 unregister_pernet_device(&ipgre_tap_net_ops);
1226pnet_tap_faied:
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001227 unregister_pernet_device(&ipgre_net_ops);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001228 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229}
1230
Alexey Kuznetsovdb445752005-07-30 17:46:44 -07001231static void __exit ipgre_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232{
Herbert Xue1a80002008-10-09 12:00:17 -07001233 rtnl_link_unregister(&ipgre_tap_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001234 rtnl_link_unregister(&ipgre_link_ops);
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001235 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001236 unregister_pernet_device(&ipgre_tap_net_ops);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001237 unregister_pernet_device(&ipgre_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238}
1239
1240module_init(ipgre_init);
1241module_exit(ipgre_fini);
1242MODULE_LICENSE("GPL");
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001243MODULE_ALIAS_RTNL_LINK("gre");
1244MODULE_ALIAS_RTNL_LINK("gretap");
Vasiliy Kulikov8909c9a2011-03-02 00:33:13 +03001245MODULE_ALIAS_NETDEV("gre0");
Pravin B Shelarc5441932013-03-25 14:49:35 +00001246MODULE_ALIAS_NETDEV("gretap0");