blob: 1d000af7f5617e32e6dd8ec5e034a87fd449ab06 [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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 struct ip_tunnel *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 switch (type) {
144 default:
145 case ICMP_PARAMETERPROB:
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700146 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
148 case ICMP_DEST_UNREACH:
149 switch (code) {
150 case ICMP_SR_FAILED:
151 case ICMP_PORT_UNREACH:
152 /* Impossible event. */
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700153 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 default:
155 /* All others are translated to HOST_UNREACH.
156 rfc2003 contains "deep thoughts" about NET_UNREACH,
157 I believe they are just ether pollution. --ANK
158 */
159 break;
160 }
161 break;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700162
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 case ICMP_TIME_EXCEEDED:
164 if (code != ICMP_EXC_TTL)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700165 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 break;
David S. Miller55be7a92012-07-11 21:27:49 -0700167
168 case ICMP_REDIRECT:
169 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 }
171
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700172 if (tpi->proto == htons(ETH_P_TEB))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000173 itn = net_generic(net, gre_tap_net_id);
174 else
175 itn = net_generic(net, ipgre_net_id);
176
Duan Jiongc0c0c50f2014-01-28 11:49:43 +0800177 iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700178 t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
179 iph->daddr, iph->saddr, tpi->key);
stephen hemmingerd2083282012-09-24 18:12:23 +0000180
Ian Morris51456b22015-04-03 09:17:26 +0100181 if (!t)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700182 return;
David S. Miller36393392012-06-14 22:21:46 -0700183
David S. Miller36393392012-06-14 22:21:46 -0700184 if (t->parms.iph.daddr == 0 ||
Joe Perchesf97c1e02007-12-16 13:45:43 -0800185 ipv4_is_multicast(t->parms.iph.daddr))
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700186 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
188 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700189 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190
Wei Yongjunda6185d82009-02-24 23:34:48 -0800191 if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 t->err_count++;
193 else
194 t->err_count = 1;
195 t->err_time = jiffies;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700196}
197
198static void gre_err(struct sk_buff *skb, u32 info)
199{
200 /* All the routers (except for Linux) return only
201 * 8 bytes of packet payload. It means, that precise relaying of
202 * ICMP in the real Internet is absolutely infeasible.
203 *
204 * Moreover, Cisco "wise men" put GRE key to the third word
205 * in GRE header. It makes impossible maintaining even soft
206 * state for keyed
207 * GRE tunnels with enabled checksum. Tell them "thank you".
208 *
209 * Well, I wonder, rfc1812 was written by Cisco employee,
210 * what the hell these idiots break standards established
211 * by themselves???
212 */
213
Eric Dumazete5826152016-06-15 06:24:00 -0700214 const struct iphdr *iph = (struct iphdr *)skb->data;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700215 const int type = icmp_hdr(skb)->type;
216 const int code = icmp_hdr(skb)->code;
217 struct tnl_ptk_info tpi;
218 bool csum_err = false;
219
Eric Dumazete5826152016-06-15 06:24:00 -0700220 if (gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP),
221 iph->ihl * 4) < 0) {
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700222 if (!csum_err) /* ignore csum errors. */
223 return;
224 }
225
226 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
227 ipv4_update_pmtu(skb, dev_net(skb->dev), info,
228 skb->dev->ifindex, 0, IPPROTO_GRE, 0);
229 return;
230 }
231 if (type == ICMP_REDIRECT) {
232 ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0,
233 IPPROTO_GRE, 0);
234 return;
235 }
236
237 ipgre_err(skb, info, &tpi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238}
239
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700240static __be64 key_to_tunnel_id(__be32 key)
241{
242#ifdef __BIG_ENDIAN
243 return (__force __be64)((__force u32)key);
244#else
245 return (__force __be64)((__force u64)key << 32);
246#endif
247}
248
249/* Returns the least-significant 32 bits of a __be64. */
250static __be32 tunnel_id_to_key(__be64 x)
251{
252#ifdef __BIG_ENDIAN
253 return (__force __be32)x;
254#else
255 return (__force __be32)((__force u64)x >> 32);
256#endif
257}
258
Jiri Benc125372f2016-05-03 17:10:08 +0200259static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
260 struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700262 struct metadata_dst *tun_dst = NULL;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000263 const struct iphdr *iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 struct ip_tunnel *tunnel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700266 iph = ip_hdr(skb);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700267 tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
268 iph->saddr, iph->daddr, tpi->key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
stephen hemmingerd2083282012-09-24 18:12:23 +0000270 if (tunnel) {
Jiri Benc125372f2016-05-03 17:10:08 +0200271 if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
272 raw_proto, false) < 0)
Jiri Benc244a7972016-05-03 17:10:07 +0200273 goto drop;
274
Jiri Bence271c7b2016-05-11 15:53:57 +0200275 if (tunnel->dev->type != ARPHRD_NONE)
276 skb_pop_mac_header(skb);
277 else
278 skb_reset_mac_header(skb);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700279 if (tunnel->collect_md) {
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700280 __be16 flags;
281 __be64 tun_id;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700282
Pravin B Shelarc29a70d2015-08-26 23:46:50 -0700283 flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
284 tun_id = key_to_tunnel_id(tpi->key);
285 tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700286 if (!tun_dst)
287 return PACKET_REJECT;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700288 }
289
290 ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
Pravin B Shelarbda7bb42013-06-17 17:49:38 -0700291 return PACKET_RCVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 }
Jiri Benc125372f2016-05-03 17:10:08 +0200293 return PACKET_NEXT;
Jiri Benc244a7972016-05-03 17:10:07 +0200294
295drop:
296 kfree_skb(skb);
297 return PACKET_RCVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298}
299
Jiri Benc125372f2016-05-03 17:10:08 +0200300static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
301 int hdr_len)
302{
303 struct net *net = dev_net(skb->dev);
304 struct ip_tunnel_net *itn;
305 int res;
306
307 if (tpi->proto == htons(ETH_P_TEB))
308 itn = net_generic(net, gre_tap_net_id);
309 else
310 itn = net_generic(net, ipgre_net_id);
311
312 res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
313 if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
314 /* ipgre tunnels in collect metadata mode should receive
315 * also ETH_P_TEB traffic.
316 */
317 itn = net_generic(net, ipgre_net_id);
318 res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
319 }
320 return res;
321}
322
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700323static int gre_rcv(struct sk_buff *skb)
324{
325 struct tnl_ptk_info tpi;
326 bool csum_err = false;
Tom Herbert95f5c642016-04-29 17:12:16 -0700327 int hdr_len;
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700328
329#ifdef CONFIG_NET_IPGRE_BROADCAST
330 if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
331 /* Looped back packet, drop it! */
332 if (rt_is_output_route(skb_rtable(skb)))
333 goto drop;
334 }
335#endif
336
Eric Dumazete5826152016-06-15 06:24:00 -0700337 hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
Jiri Bencf132ae72016-05-03 15:00:21 +0200338 if (hdr_len < 0)
Tom Herbert95f5c642016-04-29 17:12:16 -0700339 goto drop;
340
Jiri Benc244a7972016-05-03 17:10:07 +0200341 if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700342 return 0;
343
344 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
345drop:
346 kfree_skb(skb);
347 return 0;
348}
349
Pravin B Shelarc5441932013-03-25 14:49:35 +0000350static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
351 const struct iphdr *tnl_params,
352 __be16 proto)
353{
354 struct ip_tunnel *tunnel = netdev_priv(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000355
Pravin B Shelarc5441932013-03-25 14:49:35 +0000356 if (tunnel->parms.o_flags & TUNNEL_SEQ)
357 tunnel->o_seqno++;
Eric Dumazetcef401d2013-01-25 20:34:37 +0000358
Pravin B Shelarc5441932013-03-25 14:49:35 +0000359 /* Push GRE header. */
Tom Herbert182a3522016-04-29 17:12:19 -0700360 gre_build_header(skb, tunnel->tun_hlen,
361 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
362 htonl(tunnel->o_seqno));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700364 skb_set_inner_protocol(skb, proto);
Nicolas Dichtelbf3d6a82013-05-27 23:48:15 +0000365 ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366}
367
Alexander Duyckaed069d2016-04-14 15:33:37 -0400368static int gre_handle_offloads(struct sk_buff *skb, bool csum)
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -0700369{
Edward Cree6fa79662016-02-11 21:02:31 +0000370 return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -0700371}
372
Pravin B Shelarfc4099f2015-10-22 18:17:16 -0700373static struct rtable *gre_get_rt(struct sk_buff *skb,
374 struct net_device *dev,
375 struct flowi4 *fl,
376 const struct ip_tunnel_key *key)
377{
378 struct net *net = dev_net(dev);
379
380 memset(fl, 0, sizeof(*fl));
381 fl->daddr = key->u.ipv4.dst;
382 fl->saddr = key->u.ipv4.src;
383 fl->flowi4_tos = RT_TOS(key->tos);
384 fl->flowi4_mark = skb->mark;
385 fl->flowi4_proto = IPPROTO_GRE;
386
387 return ip_route_output_key(net, fl);
388}
389
Jiri Benc20907142016-04-27 11:29:07 +0200390static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
391 __be16 proto)
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700392{
393 struct ip_tunnel_info *tun_info;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700394 const struct ip_tunnel_key *key;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100395 struct rtable *rt = NULL;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700396 struct flowi4 fl;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700397 int min_headroom;
398 int tunnel_hlen;
399 __be16 df, flags;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100400 bool use_cache;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700401 int err;
402
Jiri Benc61adedf2015-08-20 13:56:25 +0200403 tun_info = skb_tunnel_info(skb);
Jiri Benc7f9562a2015-08-28 20:48:20 +0200404 if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
405 ip_tunnel_info_af(tun_info) != AF_INET))
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700406 goto err_free_skb;
407
408 key = &tun_info->key;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100409 use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
410 if (use_cache)
411 rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl.saddr);
Paolo Abeni3c1cb4d22016-02-12 15:43:59 +0100412 if (!rt) {
413 rt = gre_get_rt(skb, dev, &fl, key);
414 if (IS_ERR(rt))
415 goto err_free_skb;
Daniel Borkmanndb3c6132016-03-04 15:15:07 +0100416 if (use_cache)
Paolo Abeni3c1cb4d22016-02-12 15:43:59 +0100417 dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
418 fl.saddr);
419 }
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700420
Tom Herbert95f5c642016-04-29 17:12:16 -0700421 tunnel_hlen = gre_calc_hlen(key->tun_flags);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700422
423 min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
424 + tunnel_hlen + sizeof(struct iphdr);
425 if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
426 int head_delta = SKB_DATA_ALIGN(min_headroom -
427 skb_headroom(skb) +
428 16);
429 err = pskb_expand_head(skb, max_t(int, head_delta, 0),
430 0, GFP_ATOMIC);
431 if (unlikely(err))
432 goto err_free_rt;
433 }
434
435 /* Push Tunnel header. */
Alexander Duyckaed069d2016-04-14 15:33:37 -0400436 if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700437 goto err_free_rt;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700438
439 flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
David S. Millercba653212016-05-04 00:52:29 -0400440 gre_build_header(skb, tunnel_hlen, flags, proto,
Tom Herbert182a3522016-04-29 17:12:19 -0700441 tunnel_id_to_key(tun_info->key.tun_id), 0);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700442
443 df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
Pravin B Shelar039f5062015-12-24 14:34:54 -0800444
445 iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
446 key->tos, key->ttl, df, false);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700447 return;
448
449err_free_rt:
450 ip_rt_put(rt);
451err_free_skb:
452 kfree_skb(skb);
453 dev->stats.tx_dropped++;
454}
455
Pravin B Shelarfc4099f2015-10-22 18:17:16 -0700456static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
457{
458 struct ip_tunnel_info *info = skb_tunnel_info(skb);
459 struct rtable *rt;
460 struct flowi4 fl4;
461
462 if (ip_tunnel_info_af(info) != AF_INET)
463 return -EINVAL;
464
465 rt = gre_get_rt(skb, dev, &fl4, &info->key);
466 if (IS_ERR(rt))
467 return PTR_ERR(rt);
468
469 ip_rt_put(rt);
470 info->key.u.ipv4.src = fl4.saddr;
471 return 0;
472}
473
Pravin B Shelarc5441932013-03-25 14:49:35 +0000474static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
475 struct net_device *dev)
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800476{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000477 struct ip_tunnel *tunnel = netdev_priv(dev);
478 const struct iphdr *tnl_params;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800479
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700480 if (tunnel->collect_md) {
Jiri Benc20907142016-04-27 11:29:07 +0200481 gre_fb_xmit(skb, dev, skb->protocol);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700482 return NETDEV_TX_OK;
483 }
484
Pravin B Shelarc5441932013-03-25 14:49:35 +0000485 if (dev->header_ops) {
486 /* Need space for new headers */
487 if (skb_cow_head(skb, dev->needed_headroom -
Chen Gang2bac7cb2013-04-22 20:45:42 +0000488 (tunnel->hlen + sizeof(struct iphdr))))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000489 goto free_skb;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800490
Pravin B Shelarc5441932013-03-25 14:49:35 +0000491 tnl_params = (const struct iphdr *)skb->data;
Eric Dumazete985aad2010-09-27 03:57:11 +0000492
Pravin B Shelarc5441932013-03-25 14:49:35 +0000493 /* Pull skb since ip_tunnel_xmit() needs skb->data pointing
494 * to gre header.
495 */
496 skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
Timo Teräs8a0033a2014-12-15 09:24:13 +0200497 skb_reset_mac_header(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000498 } else {
499 if (skb_cow_head(skb, dev->needed_headroom))
500 goto free_skb;
Herbert Xue1a80002008-10-09 12:00:17 -0700501
Pravin B Shelarc5441932013-03-25 14:49:35 +0000502 tnl_params = &tunnel->parms.iph;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800503 }
504
Alexander Duyckaed069d2016-04-14 15:33:37 -0400505 if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
506 goto free_skb;
Timo Teräs8a0033a2014-12-15 09:24:13 +0200507
Pravin B Shelarc5441932013-03-25 14:49:35 +0000508 __gre_xmit(skb, dev, tnl_params, skb->protocol);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000509 return NETDEV_TX_OK;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800510
Pravin B Shelarc5441932013-03-25 14:49:35 +0000511free_skb:
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800512 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000513 dev->stats.tx_dropped++;
514 return NETDEV_TX_OK;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800515}
516
Pravin B Shelarc5441932013-03-25 14:49:35 +0000517static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
518 struct net_device *dev)
519{
520 struct ip_tunnel *tunnel = netdev_priv(dev);
521
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700522 if (tunnel->collect_md) {
Jiri Benc20907142016-04-27 11:29:07 +0200523 gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700524 return NETDEV_TX_OK;
525 }
526
Alexander Duyckaed069d2016-04-14 15:33:37 -0400527 if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
528 goto free_skb;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000529
530 if (skb_cow_head(skb, dev->needed_headroom))
531 goto free_skb;
532
533 __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
Pravin B Shelarc5441932013-03-25 14:49:35 +0000534 return NETDEV_TX_OK;
535
536free_skb:
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800537 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000538 dev->stats.tx_dropped++;
539 return NETDEV_TX_OK;
540}
541
542static int ipgre_tunnel_ioctl(struct net_device *dev,
543 struct ifreq *ifr, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544{
Tom Herbert4565e992014-09-17 12:26:01 -0700545 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 struct ip_tunnel_parm p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Pravin B Shelarc5441932013-03-25 14:49:35 +0000548 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
549 return -EFAULT;
Cong Wang6c734fb2013-06-29 12:02:59 +0800550 if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
551 if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
552 p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
553 ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
554 return -EINVAL;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000555 }
556 p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
557 p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
558
559 err = ip_tunnel_ioctl(dev, &p, cmd);
560 if (err)
561 return err;
562
Tom Herbert95f5c642016-04-29 17:12:16 -0700563 p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
564 p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000565
566 if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
567 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 return 0;
569}
570
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571/* Nice toy. Unfortunately, useless in real life :-)
572 It allows to construct virtual multiprotocol broadcast "LAN"
573 over the Internet, provided multicast routing is tuned.
574
575
576 I have no idea was this bicycle invented before me,
577 so that I had to set ARPHRD_IPGRE to a random value.
578 I have an impression, that Cisco could make something similar,
579 but this feature is apparently missing in IOS<=11.2(8).
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900580
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
582 with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
583
584 ping -t 255 224.66.66.66
585
586 If nobody answers, mbone does not work.
587
588 ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
589 ip addr add 10.66.66.<somewhat>/24 dev Universe
590 ifconfig Universe up
591 ifconfig Universe add fe80::<Your_real_addr>/10
592 ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
593 ftp 10.66.66.66
594 ...
595 ftp fec0:6666:6666::193.233.7.65
596 ...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 */
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700598static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
599 unsigned short type,
Eric Dumazet15078502010-09-15 11:07:53 +0000600 const void *daddr, const void *saddr, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601{
Patrick McHardy2941a482006-01-08 22:05:26 -0800602 struct ip_tunnel *t = netdev_priv(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000603 struct iphdr *iph;
604 struct gre_base_hdr *greh;
605
606 iph = (struct iphdr *)skb_push(skb, t->hlen + sizeof(*iph));
607 greh = (struct gre_base_hdr *)(iph+1);
Tom Herbert95f5c642016-04-29 17:12:16 -0700608 greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000609 greh->protocol = htons(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
611 memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Pravin B Shelarc5441932013-03-25 14:49:35 +0000613 /* Set the source hardware address. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 if (saddr)
615 memcpy(&iph->saddr, saddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +0000616 if (daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 memcpy(&iph->daddr, daddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +0000618 if (iph->daddr)
Timo Teräs77a482b2013-08-06 13:45:43 +0300619 return t->hlen + sizeof(*iph);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900620
Pravin B Shelarc5441932013-03-25 14:49:35 +0000621 return -(t->hlen + sizeof(*iph));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622}
623
Timo Teras6a5f44d2007-10-23 20:31:53 -0700624static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
625{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000626 const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
Timo Teras6a5f44d2007-10-23 20:31:53 -0700627 memcpy(haddr, &iph->saddr, 4);
628 return 4;
629}
630
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700631static const struct header_ops ipgre_header_ops = {
632 .create = ipgre_header,
Timo Teras6a5f44d2007-10-23 20:31:53 -0700633 .parse = ipgre_header_parse,
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700634};
635
Timo Teras6a5f44d2007-10-23 20:31:53 -0700636#ifdef CONFIG_NET_IPGRE_BROADCAST
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637static int ipgre_open(struct net_device *dev)
638{
Patrick McHardy2941a482006-01-08 22:05:26 -0800639 struct ip_tunnel *t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Joe Perchesf97c1e02007-12-16 13:45:43 -0800641 if (ipv4_is_multicast(t->parms.iph.daddr)) {
David S. Millercbb1e852011-05-04 12:33:34 -0700642 struct flowi4 fl4;
643 struct rtable *rt;
Eric Dumazete985aad2010-09-27 03:57:11 +0000644
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200645 rt = ip_route_output_gre(t->net, &fl4,
David S. Millercbb1e852011-05-04 12:33:34 -0700646 t->parms.iph.daddr,
647 t->parms.iph.saddr,
648 t->parms.o_key,
649 RT_TOS(t->parms.iph.tos),
650 t->parms.link);
David S. Millerb23dd4f2011-03-02 14:31:35 -0800651 if (IS_ERR(rt))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 return -EADDRNOTAVAIL;
Changli Gaod8d1f302010-06-10 23:31:35 -0700653 dev = rt->dst.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 ip_rt_put(rt);
Ian Morris51456b22015-04-03 09:17:26 +0100655 if (!__in_dev_get_rtnl(dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 return -EADDRNOTAVAIL;
657 t->mlink = dev->ifindex;
Herbert Xue5ed6392005-10-03 14:35:55 -0700658 ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 }
660 return 0;
661}
662
663static int ipgre_close(struct net_device *dev)
664{
Patrick McHardy2941a482006-01-08 22:05:26 -0800665 struct ip_tunnel *t = netdev_priv(dev);
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800666
Joe Perchesf97c1e02007-12-16 13:45:43 -0800667 if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
Denis V. Lunev7fee0ca2008-01-21 17:32:38 -0800668 struct in_device *in_dev;
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200669 in_dev = inetdev_by_index(t->net, t->mlink);
Eric Dumazet8723e1b2010-10-19 00:39:26 +0000670 if (in_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 ip_mc_dec_group(in_dev, t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 }
673 return 0;
674}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675#endif
676
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800677static const struct net_device_ops ipgre_netdev_ops = {
678 .ndo_init = ipgre_tunnel_init,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000679 .ndo_uninit = ip_tunnel_uninit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800680#ifdef CONFIG_NET_IPGRE_BROADCAST
681 .ndo_open = ipgre_open,
682 .ndo_stop = ipgre_close,
683#endif
Pravin B Shelarc5441932013-03-25 14:49:35 +0000684 .ndo_start_xmit = ipgre_xmit,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800685 .ndo_do_ioctl = ipgre_tunnel_ioctl,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000686 .ndo_change_mtu = ip_tunnel_change_mtu,
687 .ndo_get_stats64 = ip_tunnel_get_stats64,
Nicolas Dichtel1e995842015-04-02 17:07:02 +0200688 .ndo_get_iflink = ip_tunnel_get_iflink,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800689};
690
Eric Dumazet6b78f162012-09-13 21:25:33 +0000691#define GRE_FEATURES (NETIF_F_SG | \
692 NETIF_F_FRAGLIST | \
693 NETIF_F_HIGHDMA | \
694 NETIF_F_HW_CSUM)
695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696static void ipgre_tunnel_setup(struct net_device *dev)
697{
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -0800698 dev->netdev_ops = &ipgre_netdev_ops;
Nicolas Dichtel5a455272014-04-11 15:51:18 +0200699 dev->type = ARPHRD_IPGRE;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000700 ip_tunnel_setup(dev, ipgre_net_id);
701}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
Pravin B Shelarc5441932013-03-25 14:49:35 +0000703static void __gre_tunnel_init(struct net_device *dev)
704{
705 struct ip_tunnel *tunnel;
Tom Herbert4565e992014-09-17 12:26:01 -0700706 int t_hlen;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000707
708 tunnel = netdev_priv(dev);
Tom Herbert95f5c642016-04-29 17:12:16 -0700709 tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000710 tunnel->parms.iph.protocol = IPPROTO_GRE;
711
Tom Herbert4565e992014-09-17 12:26:01 -0700712 tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
713
714 t_hlen = tunnel->hlen + sizeof(struct iphdr);
715
716 dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
717 dev->mtu = ETH_DATA_LEN - t_hlen - 4;
Eric Dumazet6b78f162012-09-13 21:25:33 +0000718
Nicolas Dichtelb57708a2014-04-22 10:15:23 +0200719 dev->features |= GRE_FEATURES;
Eric Dumazet6b78f162012-09-13 21:25:33 +0000720 dev->hw_features |= GRE_FEATURES;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000721
722 if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
Alexander Duycka0ca1532016-04-05 09:13:39 -0700723 /* TCP offload with GRE SEQ is not supported, nor
724 * can we support 2 levels of outer headers requiring
725 * an update.
726 */
727 if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
728 (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
729 dev->features |= NETIF_F_GSO_SOFTWARE;
730 dev->hw_features |= NETIF_F_GSO_SOFTWARE;
731 }
732
Pravin B Shelarc5441932013-03-25 14:49:35 +0000733 /* Can use a lockless transmit, unless we generate
734 * output sequences
735 */
736 dev->features |= NETIF_F_LLTX;
737 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738}
739
740static int ipgre_tunnel_init(struct net_device *dev)
741{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000742 struct ip_tunnel *tunnel = netdev_priv(dev);
743 struct iphdr *iph = &tunnel->parms.iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
Pravin B Shelarc5441932013-03-25 14:49:35 +0000745 __gre_tunnel_init(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
Pravin B Shelarc5441932013-03-25 14:49:35 +0000747 memcpy(dev->dev_addr, &iph->saddr, 4);
748 memcpy(dev->broadcast, &iph->daddr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
Pravin B Shelarc5441932013-03-25 14:49:35 +0000750 dev->flags = IFF_NOARP;
Eric Dumazet02875872014-10-05 18:38:35 -0700751 netif_keep_dst(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000752 dev->addr_len = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753
Jiri Benca64b04d2016-04-27 11:29:06 +0200754 if (iph->daddr && !tunnel->collect_md) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755#ifdef CONFIG_NET_IPGRE_BROADCAST
Joe Perchesf97c1e02007-12-16 13:45:43 -0800756 if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 if (!iph->saddr)
758 return -EINVAL;
759 dev->flags = IFF_BROADCAST;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -0700760 dev->header_ops = &ipgre_header_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 }
762#endif
Jiri Benca64b04d2016-04-27 11:29:06 +0200763 } else if (!tunnel->collect_md) {
Timo Teras6a5f44d2007-10-23 20:31:53 -0700764 dev->header_ops = &ipgre_header_ops;
Jiri Benca64b04d2016-04-27 11:29:06 +0200765 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766
Pravin B Shelarc5441932013-03-25 14:49:35 +0000767 return ip_tunnel_init(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768}
769
Pravin B Shelar9f57c672015-08-07 23:51:52 -0700770static const struct gre_protocol ipgre_protocol = {
771 .handler = gre_rcv,
772 .err_handler = gre_err,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773};
774
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +0000775static int __net_init ipgre_init_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700776{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000777 return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700778}
779
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +0000780static void __net_exit ipgre_exit_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700781{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000782 struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200783 ip_tunnel_delete_net(itn, &ipgre_link_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700784}
785
786static struct pernet_operations ipgre_net_ops = {
787 .init = ipgre_init_net,
788 .exit = ipgre_exit_net,
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +0000789 .id = &ipgre_net_id,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000790 .size = sizeof(struct ip_tunnel_net),
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700791};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Herbert Xuc19e6542008-10-09 11:59:55 -0700793static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
794{
795 __be16 flags;
796
797 if (!data)
798 return 0;
799
800 flags = 0;
801 if (data[IFLA_GRE_IFLAGS])
802 flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
803 if (data[IFLA_GRE_OFLAGS])
804 flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
805 if (flags & (GRE_VERSION|GRE_ROUTING))
806 return -EINVAL;
807
Jiri Benc946b6362016-04-27 14:08:01 +0200808 if (data[IFLA_GRE_COLLECT_METADATA] &&
809 data[IFLA_GRE_ENCAP_TYPE] &&
810 nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
811 return -EINVAL;
812
Herbert Xuc19e6542008-10-09 11:59:55 -0700813 return 0;
814}
815
Herbert Xue1a80002008-10-09 12:00:17 -0700816static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
817{
818 __be32 daddr;
819
820 if (tb[IFLA_ADDRESS]) {
821 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
822 return -EINVAL;
823 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
824 return -EADDRNOTAVAIL;
825 }
826
827 if (!data)
828 goto out;
829
830 if (data[IFLA_GRE_REMOTE]) {
831 memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
832 if (!daddr)
833 return -EINVAL;
834 }
835
836out:
837 return ipgre_tunnel_validate(tb, data);
838}
839
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700840static void ipgre_netlink_parms(struct net_device *dev,
841 struct nlattr *data[],
842 struct nlattr *tb[],
843 struct ip_tunnel_parm *parms)
Herbert Xuc19e6542008-10-09 11:59:55 -0700844{
Herbert Xu7bb82d92008-10-11 12:20:15 -0700845 memset(parms, 0, sizeof(*parms));
Herbert Xuc19e6542008-10-09 11:59:55 -0700846
847 parms->iph.protocol = IPPROTO_GRE;
848
849 if (!data)
850 return;
851
852 if (data[IFLA_GRE_LINK])
853 parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
854
855 if (data[IFLA_GRE_IFLAGS])
Pravin B Shelarc5441932013-03-25 14:49:35 +0000856 parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
Herbert Xuc19e6542008-10-09 11:59:55 -0700857
858 if (data[IFLA_GRE_OFLAGS])
Pravin B Shelarc5441932013-03-25 14:49:35 +0000859 parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
Herbert Xuc19e6542008-10-09 11:59:55 -0700860
861 if (data[IFLA_GRE_IKEY])
862 parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
863
864 if (data[IFLA_GRE_OKEY])
865 parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
866
867 if (data[IFLA_GRE_LOCAL])
Jiri Benc67b61f62015-03-29 16:59:26 +0200868 parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
Herbert Xuc19e6542008-10-09 11:59:55 -0700869
870 if (data[IFLA_GRE_REMOTE])
Jiri Benc67b61f62015-03-29 16:59:26 +0200871 parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
Herbert Xuc19e6542008-10-09 11:59:55 -0700872
873 if (data[IFLA_GRE_TTL])
874 parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
875
876 if (data[IFLA_GRE_TOS])
877 parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
878
879 if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC]))
880 parms->iph.frag_off = htons(IP_DF);
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700881
882 if (data[IFLA_GRE_COLLECT_METADATA]) {
883 struct ip_tunnel *t = netdev_priv(dev);
884
885 t->collect_md = true;
Jiri Bence271c7b2016-05-11 15:53:57 +0200886 if (dev->type == ARPHRD_IPGRE)
887 dev->type = ARPHRD_NONE;
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700888 }
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 hemmingerbec94d4302014-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;
959
960 if (ipgre_netlink_encap_parms(data, &ipencap)) {
961 struct ip_tunnel *t = netdev_priv(dev);
962 int err = ip_tunnel_encap_setup(t, &ipencap);
963
964 if (err < 0)
965 return err;
966 }
Herbert Xuc19e6542008-10-09 11:59:55 -0700967
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700968 ipgre_netlink_parms(dev, data, tb, &p);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000969 return ip_tunnel_newlink(dev, tb, &p);
Herbert Xuc19e6542008-10-09 11:59:55 -0700970}
971
972static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
973 struct nlattr *data[])
974{
Herbert Xuc19e6542008-10-09 11:59:55 -0700975 struct ip_tunnel_parm p;
Tom Herbert4565e992014-09-17 12:26:01 -0700976 struct ip_tunnel_encap ipencap;
977
978 if (ipgre_netlink_encap_parms(data, &ipencap)) {
979 struct ip_tunnel *t = netdev_priv(dev);
980 int err = ip_tunnel_encap_setup(t, &ipencap);
981
982 if (err < 0)
983 return err;
984 }
Herbert Xuc19e6542008-10-09 11:59:55 -0700985
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700986 ipgre_netlink_parms(dev, data, tb, &p);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000987 return ip_tunnel_changelink(dev, tb, &p);
Herbert Xuc19e6542008-10-09 11:59:55 -0700988}
989
990static size_t ipgre_get_size(const struct net_device *dev)
991{
992 return
993 /* IFLA_GRE_LINK */
994 nla_total_size(4) +
995 /* IFLA_GRE_IFLAGS */
996 nla_total_size(2) +
997 /* IFLA_GRE_OFLAGS */
998 nla_total_size(2) +
999 /* IFLA_GRE_IKEY */
1000 nla_total_size(4) +
1001 /* IFLA_GRE_OKEY */
1002 nla_total_size(4) +
1003 /* IFLA_GRE_LOCAL */
1004 nla_total_size(4) +
1005 /* IFLA_GRE_REMOTE */
1006 nla_total_size(4) +
1007 /* IFLA_GRE_TTL */
1008 nla_total_size(1) +
1009 /* IFLA_GRE_TOS */
1010 nla_total_size(1) +
1011 /* IFLA_GRE_PMTUDISC */
1012 nla_total_size(1) +
Tom Herbert4565e992014-09-17 12:26:01 -07001013 /* IFLA_GRE_ENCAP_TYPE */
1014 nla_total_size(2) +
1015 /* IFLA_GRE_ENCAP_FLAGS */
1016 nla_total_size(2) +
1017 /* IFLA_GRE_ENCAP_SPORT */
1018 nla_total_size(2) +
1019 /* IFLA_GRE_ENCAP_DPORT */
1020 nla_total_size(2) +
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001021 /* IFLA_GRE_COLLECT_METADATA */
1022 nla_total_size(0) +
Herbert Xuc19e6542008-10-09 11:59:55 -07001023 0;
1024}
1025
1026static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1027{
1028 struct ip_tunnel *t = netdev_priv(dev);
1029 struct ip_tunnel_parm *p = &t->parms;
1030
David S. Millerf3756b72012-04-01 20:39:02 -04001031 if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
Tom Herbert95f5c642016-04-29 17:12:16 -07001032 nla_put_be16(skb, IFLA_GRE_IFLAGS,
1033 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
1034 nla_put_be16(skb, IFLA_GRE_OFLAGS,
1035 gre_tnl_flags_to_gre_flags(p->o_flags)) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001036 nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1037 nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
Jiri Benc930345e2015-03-29 16:59:25 +02001038 nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1039 nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001040 nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1041 nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1042 nla_put_u8(skb, IFLA_GRE_PMTUDISC,
1043 !!(p->iph.frag_off & htons(IP_DF))))
1044 goto nla_put_failure;
Tom Herbert4565e992014-09-17 12:26:01 -07001045
1046 if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
1047 t->encap.type) ||
Sabrina Dubroca3e97fa72015-02-06 17:22:22 +01001048 nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
1049 t->encap.sport) ||
1050 nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
1051 t->encap.dport) ||
Tom Herbert4565e992014-09-17 12:26:01 -07001052 nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
Tom Herberte1b2cb62014-11-05 16:49:38 -08001053 t->encap.flags))
Tom Herbert4565e992014-09-17 12:26:01 -07001054 goto nla_put_failure;
1055
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001056 if (t->collect_md) {
1057 if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
1058 goto nla_put_failure;
1059 }
1060
Herbert Xuc19e6542008-10-09 11:59:55 -07001061 return 0;
1062
1063nla_put_failure:
1064 return -EMSGSIZE;
1065}
1066
1067static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1068 [IFLA_GRE_LINK] = { .type = NLA_U32 },
1069 [IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
1070 [IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
1071 [IFLA_GRE_IKEY] = { .type = NLA_U32 },
1072 [IFLA_GRE_OKEY] = { .type = NLA_U32 },
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001073 [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
1074 [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
Herbert Xuc19e6542008-10-09 11:59:55 -07001075 [IFLA_GRE_TTL] = { .type = NLA_U8 },
1076 [IFLA_GRE_TOS] = { .type = NLA_U8 },
1077 [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 },
Tom Herbert4565e992014-09-17 12:26:01 -07001078 [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 },
1079 [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 },
1080 [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 },
1081 [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 },
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001082 [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG },
Herbert Xuc19e6542008-10-09 11:59:55 -07001083};
1084
1085static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1086 .kind = "gre",
1087 .maxtype = IFLA_GRE_MAX,
1088 .policy = ipgre_policy,
1089 .priv_size = sizeof(struct ip_tunnel),
1090 .setup = ipgre_tunnel_setup,
1091 .validate = ipgre_tunnel_validate,
1092 .newlink = ipgre_newlink,
1093 .changelink = ipgre_changelink,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001094 .dellink = ip_tunnel_dellink,
Herbert Xuc19e6542008-10-09 11:59:55 -07001095 .get_size = ipgre_get_size,
1096 .fill_info = ipgre_fill_info,
Nicolas Dichtel1728d4f2015-01-15 15:11:17 +01001097 .get_link_net = ip_tunnel_get_link_net,
Herbert Xuc19e6542008-10-09 11:59:55 -07001098};
1099
Herbert Xue1a80002008-10-09 12:00:17 -07001100static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1101 .kind = "gretap",
1102 .maxtype = IFLA_GRE_MAX,
1103 .policy = ipgre_policy,
1104 .priv_size = sizeof(struct ip_tunnel),
1105 .setup = ipgre_tap_setup,
1106 .validate = ipgre_tap_validate,
1107 .newlink = ipgre_newlink,
1108 .changelink = ipgre_changelink,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001109 .dellink = ip_tunnel_dellink,
Herbert Xue1a80002008-10-09 12:00:17 -07001110 .get_size = ipgre_get_size,
1111 .fill_info = ipgre_fill_info,
Nicolas Dichtel1728d4f2015-01-15 15:11:17 +01001112 .get_link_net = ip_tunnel_get_link_net,
Herbert Xue1a80002008-10-09 12:00:17 -07001113};
1114
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001115struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1116 u8 name_assign_type)
1117{
1118 struct nlattr *tb[IFLA_MAX + 1];
1119 struct net_device *dev;
Nicolas Dichtel106da662016-06-13 10:31:04 +02001120 LIST_HEAD(list_kill);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001121 struct ip_tunnel *t;
1122 int err;
1123
1124 memset(&tb, 0, sizeof(tb));
1125
1126 dev = rtnl_create_link(net, name, name_assign_type,
1127 &ipgre_tap_ops, tb);
1128 if (IS_ERR(dev))
1129 return dev;
1130
1131 /* Configure flow based GRE device. */
1132 t = netdev_priv(dev);
1133 t->collect_md = true;
1134
1135 err = ipgre_newlink(net, dev, tb, NULL);
Nicolas Dichtel106da662016-06-13 10:31:04 +02001136 if (err < 0) {
1137 free_netdev(dev);
1138 return ERR_PTR(err);
1139 }
David Wragg7e059152016-02-10 00:05:58 +00001140
1141 /* openvswitch users expect packet sizes to be unrestricted,
1142 * so set the largest MTU we can.
1143 */
1144 err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
1145 if (err)
1146 goto out;
1147
Nicolas Dichtelda6f1da2016-06-13 10:31:06 +02001148 err = rtnl_configure_link(dev, NULL);
1149 if (err < 0)
1150 goto out;
1151
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001152 return dev;
1153out:
Nicolas Dichtel106da662016-06-13 10:31:04 +02001154 ip_tunnel_dellink(dev, &list_kill);
1155 unregister_netdevice_many(&list_kill);
Pravin B Shelarb2acd1d2015-08-07 23:51:47 -07001156 return ERR_PTR(err);
1157}
1158EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1159
Pravin B Shelarc5441932013-03-25 14:49:35 +00001160static int __net_init ipgre_tap_init_net(struct net *net)
1161{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001162 return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
Pravin B Shelarc5441932013-03-25 14:49:35 +00001163}
1164
1165static void __net_exit ipgre_tap_exit_net(struct net *net)
1166{
1167 struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001168 ip_tunnel_delete_net(itn, &ipgre_tap_ops);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001169}
1170
1171static struct pernet_operations ipgre_tap_net_ops = {
1172 .init = ipgre_tap_init_net,
1173 .exit = ipgre_tap_exit_net,
1174 .id = &gre_tap_net_id,
1175 .size = sizeof(struct ip_tunnel_net),
1176};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
1178static int __init ipgre_init(void)
1179{
1180 int err;
1181
Joe Perches058bd4d2012-03-11 18:36:11 +00001182 pr_info("GRE over IPv4 tunneling driver\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001184 err = register_pernet_device(&ipgre_net_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001185 if (err < 0)
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001186 return err;
1187
Pravin B Shelarc5441932013-03-25 14:49:35 +00001188 err = register_pernet_device(&ipgre_tap_net_ops);
1189 if (err < 0)
1190 goto pnet_tap_faied;
1191
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001192 err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001193 if (err < 0) {
Joe Perches058bd4d2012-03-11 18:36:11 +00001194 pr_info("%s: can't add protocol\n", __func__);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001195 goto add_proto_failed;
1196 }
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001197
Herbert Xuc19e6542008-10-09 11:59:55 -07001198 err = rtnl_link_register(&ipgre_link_ops);
1199 if (err < 0)
1200 goto rtnl_link_failed;
1201
Herbert Xue1a80002008-10-09 12:00:17 -07001202 err = rtnl_link_register(&ipgre_tap_ops);
1203 if (err < 0)
1204 goto tap_ops_failed;
1205
Pravin B Shelarc5441932013-03-25 14:49:35 +00001206 return 0;
Herbert Xuc19e6542008-10-09 11:59:55 -07001207
Herbert Xue1a80002008-10-09 12:00:17 -07001208tap_ops_failed:
1209 rtnl_link_unregister(&ipgre_link_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001210rtnl_link_failed:
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001211 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001212add_proto_failed:
Pravin B Shelarc5441932013-03-25 14:49:35 +00001213 unregister_pernet_device(&ipgre_tap_net_ops);
1214pnet_tap_faied:
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001215 unregister_pernet_device(&ipgre_net_ops);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001216 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217}
1218
Alexey Kuznetsovdb445752005-07-30 17:46:44 -07001219static void __exit ipgre_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220{
Herbert Xue1a80002008-10-09 12:00:17 -07001221 rtnl_link_unregister(&ipgre_tap_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001222 rtnl_link_unregister(&ipgre_link_ops);
Pravin B Shelar9f57c672015-08-07 23:51:52 -07001223 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001224 unregister_pernet_device(&ipgre_tap_net_ops);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001225 unregister_pernet_device(&ipgre_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226}
1227
1228module_init(ipgre_init);
1229module_exit(ipgre_fini);
1230MODULE_LICENSE("GPL");
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001231MODULE_ALIAS_RTNL_LINK("gre");
1232MODULE_ALIAS_RTNL_LINK("gretap");
Vasiliy Kulikov8909c9a2011-03-02 00:33:13 +03001233MODULE_ALIAS_NETDEV("gre0");
Pravin B Shelarc5441932013-03-25 14:49:35 +00001234MODULE_ALIAS_NETDEV("gretap0");