blob: b57532d4742c7cccc95a05dd641bfc47875b4717 [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>
27#include <linux/mroute.h>
28#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>
40#include <net/ipip.h>
41#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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Eric Dumazetdfd56b82011-12-10 09:48:31 +000051#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <net/ipv6.h>
53#include <net/ip6_fib.h>
54#include <net/ip6_route.h>
55#endif
56
57/*
58 Problems & solutions
59 --------------------
60
61 1. The most important issue is detecting local dead loops.
62 They would cause complete host lockup in transmit, which
63 would be "resolved" by stack overflow or, if queueing is enabled,
64 with infinite looping in net_bh.
65
66 We cannot track such dead loops during route installation,
67 it is infeasible task. The most general solutions would be
68 to keep skb->encapsulation counter (sort of local ttl),
Eric Dumazet6d0722a2010-09-29 23:35:10 -070069 and silently drop packet when it expires. It is a good
stephen hemmingerbff52852012-02-24 08:08:20 +000070 solution, but it supposes maintaining new variable in ALL
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 skb, even if no tunneling is used.
72
Eric Dumazet6d0722a2010-09-29 23:35:10 -070073 Current solution: xmit_recursion breaks dead loops. This is a percpu
74 counter, since when we enter the first ndo_xmit(), cpu migration is
75 forbidden. We force an exit if this counter reaches RECURSION_LIMIT
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77 2. Networking dead loops would not kill routers, but would really
78 kill network. IP hop limit plays role of "t->recursion" in this case,
79 if we copy it from packet being encapsulated to upper header.
80 It is very good solution, but it introduces two problems:
81
82 - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
83 do not work over tunnels.
84 - traceroute does not work. I planned to relay ICMP from tunnel,
85 so that this problem would be solved and traceroute output
86 would even more informative. This idea appeared to be wrong:
87 only Linux complies to rfc1812 now (yes, guys, Linux is the only
88 true router now :-)), all routers (at least, in neighbourhood of mine)
89 return only 8 bytes of payload. It is the end.
90
91 Hence, if we want that OSPF worked or traceroute said something reasonable,
92 we should search for another solution.
93
94 One of them is to parse packet trying to detect inner encapsulation
95 made by our node. It is difficult or even impossible, especially,
stephen hemmingerbff52852012-02-24 08:08:20 +000096 taking into account fragmentation. TO be short, ttl is not solution at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
98 Current solution: The solution was UNEXPECTEDLY SIMPLE.
99 We force DF flag on tunnels with preconfigured hop limit,
100 that is ALL. :-) Well, it does not remove the problem completely,
101 but exponential growth of network traffic is changed to linear
102 (branches, that exceed pmtu are pruned) and tunnel mtu
stephen hemmingerbff52852012-02-24 08:08:20 +0000103 rapidly degrades to value <68, where looping stops.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 Yes, it is not good if there exists a router in the loop,
105 which does not force DF, even when encapsulating packets have DF set.
106 But it is not our problem! Nobody could accuse us, we made
107 all that we could make. Even if it is your gated who injected
108 fatal route to network, even if it were you who configured
109 fatal static route: you are innocent. :-)
110
111
112
113 3. Really, ipv4/ipip.c, ipv4/ip_gre.c and ipv6/sit.c contain
114 practically identical code. It would be good to glue them
115 together, but it is not very evident, how to make them modular.
116 sit is integral part of IPv6, ipip and gre are naturally modular.
117 We could extract common parts (hash table, ioctl etc)
118 to a separate module (ip_tunnel.c).
119
120 Alexey Kuznetsov.
121 */
122
Herbert Xuc19e6542008-10-09 11:59:55 -0700123static struct rtnl_link_ops ipgre_link_ops __read_mostly;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124static int ipgre_tunnel_init(struct net_device *dev);
125static void ipgre_tunnel_setup(struct net_device *dev);
Herbert Xu42aa9162008-10-09 11:59:32 -0700126static int ipgre_tunnel_bind_dev(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
128/* Fallback tunnel: no source, no destination, no key, no options */
129
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700130#define HASH_SIZE 16
131
Eric Dumazetf99189b2009-11-17 10:42:49 +0000132static int ipgre_net_id __read_mostly;
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700133struct ipgre_net {
Eric Dumazet15078502010-09-15 11:07:53 +0000134 struct ip_tunnel __rcu *tunnels[4][HASH_SIZE];
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700135
Pavel Emelyanov7daa0002008-04-16 01:10:05 -0700136 struct net_device *fb_tunnel_dev;
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700137};
138
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139/* Tunnel hash table */
140
141/*
142 4 hash tables:
143
144 3: (remote,local)
145 2: (remote,*)
146 1: (*,local)
147 0: (*,*)
148
149 We require exact key match i.e. if a key is present in packet
150 it will match only tunnel with the same key; if it is not present,
151 it will match only keyless tunnel.
152
153 All keysless packets, if not matched configured keyless tunnels
154 will match fallback tunnel.
155 */
156
Al Virod5a0a1e2006-11-08 00:23:14 -0800157#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700159#define tunnels_r_l tunnels[3]
160#define tunnels_r tunnels[2]
161#define tunnels_l tunnels[1]
162#define tunnels_wc tunnels[0]
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000163/*
Eric Dumazet15078502010-09-15 11:07:53 +0000164 * Locking : hash tables are protected by RCU and RTNL
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000165 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000167#define for_each_ip_tunnel_rcu(start) \
168 for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169
Eric Dumazete985aad2010-09-27 03:57:11 +0000170/* often modified stats are per cpu, other are shared (netdev->stats) */
171struct pcpu_tstats {
172 unsigned long rx_packets;
173 unsigned long rx_bytes;
174 unsigned long tx_packets;
175 unsigned long tx_bytes;
Eric Dumazet8ce120f2011-11-04 23:19:28 +0000176} __attribute__((aligned(4*sizeof(unsigned long))));
Eric Dumazete985aad2010-09-27 03:57:11 +0000177
178static struct net_device_stats *ipgre_get_stats(struct net_device *dev)
179{
180 struct pcpu_tstats sum = { 0 };
181 int i;
182
183 for_each_possible_cpu(i) {
184 const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
185
186 sum.rx_packets += tstats->rx_packets;
187 sum.rx_bytes += tstats->rx_bytes;
188 sum.tx_packets += tstats->tx_packets;
189 sum.tx_bytes += tstats->tx_bytes;
190 }
191 dev->stats.rx_packets = sum.rx_packets;
192 dev->stats.rx_bytes = sum.rx_bytes;
193 dev->stats.tx_packets = sum.tx_packets;
194 dev->stats.tx_bytes = sum.tx_bytes;
195 return &dev->stats;
196}
197
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198/* Given src, dst and key, find appropriate for input tunnel. */
199
Timo Teras749c10f2009-01-19 17:22:12 -0800200static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
Herbert Xue1a80002008-10-09 12:00:17 -0700201 __be32 remote, __be32 local,
202 __be32 key, __be16 gre_proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203{
Timo Teras749c10f2009-01-19 17:22:12 -0800204 struct net *net = dev_net(dev);
205 int link = dev->ifindex;
Eric Dumazet15078502010-09-15 11:07:53 +0000206 unsigned int h0 = HASH(remote);
207 unsigned int h1 = HASH(key);
Timo Terasafcf1242009-01-26 20:56:10 -0800208 struct ip_tunnel *t, *cand = NULL;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -0700209 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Herbert Xue1a80002008-10-09 12:00:17 -0700210 int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
211 ARPHRD_ETHER : ARPHRD_IPGRE;
Timo Terasafcf1242009-01-26 20:56:10 -0800212 int score, cand_score = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000214 for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) {
Timo Teras749c10f2009-01-19 17:22:12 -0800215 if (local != t->parms.iph.saddr ||
216 remote != t->parms.iph.daddr ||
217 key != t->parms.i_key ||
218 !(t->dev->flags & IFF_UP))
219 continue;
220
221 if (t->dev->type != ARPHRD_IPGRE &&
222 t->dev->type != dev_type)
223 continue;
224
Timo Terasafcf1242009-01-26 20:56:10 -0800225 score = 0;
Timo Teras749c10f2009-01-19 17:22:12 -0800226 if (t->parms.link != link)
Timo Terasafcf1242009-01-26 20:56:10 -0800227 score |= 1;
Timo Teras749c10f2009-01-19 17:22:12 -0800228 if (t->dev->type != dev_type)
Timo Terasafcf1242009-01-26 20:56:10 -0800229 score |= 2;
230 if (score == 0)
Timo Teras749c10f2009-01-19 17:22:12 -0800231 return t;
Timo Terasafcf1242009-01-26 20:56:10 -0800232
233 if (score < cand_score) {
234 cand = t;
235 cand_score = score;
236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 }
Herbert Xue1a80002008-10-09 12:00:17 -0700238
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000239 for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) {
Timo Teras749c10f2009-01-19 17:22:12 -0800240 if (remote != t->parms.iph.daddr ||
241 key != t->parms.i_key ||
242 !(t->dev->flags & IFF_UP))
243 continue;
244
245 if (t->dev->type != ARPHRD_IPGRE &&
246 t->dev->type != dev_type)
247 continue;
248
Timo Terasafcf1242009-01-26 20:56:10 -0800249 score = 0;
Timo Teras749c10f2009-01-19 17:22:12 -0800250 if (t->parms.link != link)
Timo Terasafcf1242009-01-26 20:56:10 -0800251 score |= 1;
Timo Teras749c10f2009-01-19 17:22:12 -0800252 if (t->dev->type != dev_type)
Timo Terasafcf1242009-01-26 20:56:10 -0800253 score |= 2;
254 if (score == 0)
Timo Teras749c10f2009-01-19 17:22:12 -0800255 return t;
Timo Terasafcf1242009-01-26 20:56:10 -0800256
257 if (score < cand_score) {
258 cand = t;
259 cand_score = score;
260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 }
Herbert Xue1a80002008-10-09 12:00:17 -0700262
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000263 for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) {
Timo Teras749c10f2009-01-19 17:22:12 -0800264 if ((local != t->parms.iph.saddr &&
265 (local != t->parms.iph.daddr ||
266 !ipv4_is_multicast(local))) ||
267 key != t->parms.i_key ||
268 !(t->dev->flags & IFF_UP))
269 continue;
270
271 if (t->dev->type != ARPHRD_IPGRE &&
272 t->dev->type != dev_type)
273 continue;
274
Timo Terasafcf1242009-01-26 20:56:10 -0800275 score = 0;
Timo Teras749c10f2009-01-19 17:22:12 -0800276 if (t->parms.link != link)
Timo Terasafcf1242009-01-26 20:56:10 -0800277 score |= 1;
Timo Teras749c10f2009-01-19 17:22:12 -0800278 if (t->dev->type != dev_type)
Timo Terasafcf1242009-01-26 20:56:10 -0800279 score |= 2;
280 if (score == 0)
Timo Teras749c10f2009-01-19 17:22:12 -0800281 return t;
Timo Terasafcf1242009-01-26 20:56:10 -0800282
283 if (score < cand_score) {
284 cand = t;
285 cand_score = score;
286 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 }
Herbert Xue1a80002008-10-09 12:00:17 -0700288
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000289 for_each_ip_tunnel_rcu(ign->tunnels_wc[h1]) {
Timo Teras749c10f2009-01-19 17:22:12 -0800290 if (t->parms.i_key != key ||
291 !(t->dev->flags & IFF_UP))
292 continue;
293
294 if (t->dev->type != ARPHRD_IPGRE &&
295 t->dev->type != dev_type)
296 continue;
297
Timo Terasafcf1242009-01-26 20:56:10 -0800298 score = 0;
Timo Teras749c10f2009-01-19 17:22:12 -0800299 if (t->parms.link != link)
Timo Terasafcf1242009-01-26 20:56:10 -0800300 score |= 1;
Timo Teras749c10f2009-01-19 17:22:12 -0800301 if (t->dev->type != dev_type)
Timo Terasafcf1242009-01-26 20:56:10 -0800302 score |= 2;
303 if (score == 0)
Timo Teras749c10f2009-01-19 17:22:12 -0800304 return t;
Timo Terasafcf1242009-01-26 20:56:10 -0800305
306 if (score < cand_score) {
307 cand = t;
308 cand_score = score;
309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 }
311
Timo Terasafcf1242009-01-26 20:56:10 -0800312 if (cand != NULL)
313 return cand;
Herbert Xue1a80002008-10-09 12:00:17 -0700314
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000315 dev = ign->fb_tunnel_dev;
316 if (dev->flags & IFF_UP)
317 return netdev_priv(dev);
Timo Teras749c10f2009-01-19 17:22:12 -0800318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 return NULL;
320}
321
Eric Dumazet15078502010-09-15 11:07:53 +0000322static struct ip_tunnel __rcu **__ipgre_bucket(struct ipgre_net *ign,
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700323 struct ip_tunnel_parm *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
YOSHIFUJI Hideaki5056a1e2007-04-24 20:44:48 +0900325 __be32 remote = parms->iph.daddr;
326 __be32 local = parms->iph.saddr;
327 __be32 key = parms->i_key;
Eric Dumazet15078502010-09-15 11:07:53 +0000328 unsigned int h = HASH(key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 int prio = 0;
330
331 if (local)
332 prio |= 1;
Joe Perchesf97c1e02007-12-16 13:45:43 -0800333 if (remote && !ipv4_is_multicast(remote)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 prio |= 2;
335 h ^= HASH(remote);
336 }
337
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700338 return &ign->tunnels[prio][h];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339}
340
Eric Dumazet15078502010-09-15 11:07:53 +0000341static inline struct ip_tunnel __rcu **ipgre_bucket(struct ipgre_net *ign,
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700342 struct ip_tunnel *t)
YOSHIFUJI Hideaki5056a1e2007-04-24 20:44:48 +0900343{
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700344 return __ipgre_bucket(ign, &t->parms);
YOSHIFUJI Hideaki5056a1e2007-04-24 20:44:48 +0900345}
346
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700347static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348{
Eric Dumazet15078502010-09-15 11:07:53 +0000349 struct ip_tunnel __rcu **tp = ipgre_bucket(ign, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
Eric Dumazet15078502010-09-15 11:07:53 +0000351 rcu_assign_pointer(t->next, rtnl_dereference(*tp));
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000352 rcu_assign_pointer(*tp, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353}
354
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700355static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356{
Eric Dumazet15078502010-09-15 11:07:53 +0000357 struct ip_tunnel __rcu **tp;
358 struct ip_tunnel *iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Eric Dumazet15078502010-09-15 11:07:53 +0000360 for (tp = ipgre_bucket(ign, t);
361 (iter = rtnl_dereference(*tp)) != NULL;
362 tp = &iter->next) {
363 if (t == iter) {
364 rcu_assign_pointer(*tp, t->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 break;
366 }
367 }
368}
369
Herbert Xue1a80002008-10-09 12:00:17 -0700370static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
371 struct ip_tunnel_parm *parms,
372 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
Al Virod5a0a1e2006-11-08 00:23:14 -0800374 __be32 remote = parms->iph.daddr;
375 __be32 local = parms->iph.saddr;
376 __be32 key = parms->i_key;
Timo Teras749c10f2009-01-19 17:22:12 -0800377 int link = parms->link;
Eric Dumazet15078502010-09-15 11:07:53 +0000378 struct ip_tunnel *t;
379 struct ip_tunnel __rcu **tp;
Herbert Xue1a80002008-10-09 12:00:17 -0700380 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
381
Eric Dumazet15078502010-09-15 11:07:53 +0000382 for (tp = __ipgre_bucket(ign, parms);
383 (t = rtnl_dereference(*tp)) != NULL;
384 tp = &t->next)
Herbert Xue1a80002008-10-09 12:00:17 -0700385 if (local == t->parms.iph.saddr &&
386 remote == t->parms.iph.daddr &&
387 key == t->parms.i_key &&
Timo Teras749c10f2009-01-19 17:22:12 -0800388 link == t->parms.link &&
Herbert Xue1a80002008-10-09 12:00:17 -0700389 type == t->dev->type)
390 break;
391
392 return t;
393}
394
Eric Dumazet15078502010-09-15 11:07:53 +0000395static struct ip_tunnel *ipgre_tunnel_locate(struct net *net,
Herbert Xue1a80002008-10-09 12:00:17 -0700396 struct ip_tunnel_parm *parms, int create)
397{
398 struct ip_tunnel *t, *nt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 char name[IFNAMSIZ];
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700401 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
Herbert Xue1a80002008-10-09 12:00:17 -0700403 t = ipgre_tunnel_find(net, parms, ARPHRD_IPGRE);
404 if (t || !create)
405 return t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
407 if (parms->name[0])
408 strlcpy(name, parms->name, IFNAMSIZ);
Pavel Emelyanov34cc7ba2008-02-23 20:19:20 -0800409 else
stephen hemminger407d6fc2010-11-29 09:47:47 +0000410 strcpy(name, "gre%d");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
412 dev = alloc_netdev(sizeof(*t), name, ipgre_tunnel_setup);
413 if (!dev)
stephen hemminger407d6fc2010-11-29 09:47:47 +0000414 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Pavel Emelyanov0b67ece2008-04-16 01:11:13 -0700416 dev_net_set(dev, net);
417
Patrick McHardy2941a482006-01-08 22:05:26 -0800418 nt = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 nt->parms = *parms;
Herbert Xuc19e6542008-10-09 11:59:55 -0700420 dev->rtnl_link_ops = &ipgre_link_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Herbert Xu42aa9162008-10-09 11:59:32 -0700422 dev->mtu = ipgre_tunnel_bind_dev(dev);
423
Pavel Emelyanovb37d428b2008-02-26 23:51:04 -0800424 if (register_netdevice(dev) < 0)
425 goto failed_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
Willem de Bruijnf2b3ee92012-01-26 10:34:35 +0000427 /* Can use a lockless transmit, unless we generate output sequences */
428 if (!(nt->parms.o_flags & GRE_SEQ))
429 dev->features |= NETIF_F_LLTX;
430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 dev_hold(dev);
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700432 ipgre_tunnel_link(ign, nt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 return nt;
434
Pavel Emelyanovb37d428b2008-02-26 23:51:04 -0800435failed_free:
436 free_netdev(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 return NULL;
438}
439
440static void ipgre_tunnel_uninit(struct net_device *dev)
441{
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700442 struct net *net = dev_net(dev);
443 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
444
445 ipgre_tunnel_unlink(ign, netdev_priv(dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 dev_put(dev);
447}
448
449
450static void ipgre_err(struct sk_buff *skb, u32 info)
451{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
Rami Rosen071f92d2008-05-21 17:47:54 -0700453/* All the routers (except for Linux) return only
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 8 bytes of packet payload. It means, that precise relaying of
455 ICMP in the real Internet is absolutely infeasible.
456
457 Moreover, Cisco "wise men" put GRE key to the third word
458 in GRE header. It makes impossible maintaining even soft state for keyed
459 GRE tunnels with enabled checksum. Tell them "thank you".
460
461 Well, I wonder, rfc1812 was written by Cisco employee,
stephen hemmingerbff52852012-02-24 08:08:20 +0000462 what the hell these idiots break standards established
463 by themselves???
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 */
465
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000466 const struct iphdr *iph = (const struct iphdr *)skb->data;
Al Virod5a0a1e2006-11-08 00:23:14 -0800467 __be16 *p = (__be16*)(skb->data+(iph->ihl<<2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 int grehlen = (iph->ihl<<2) + 4;
Arnaldo Carvalho de Melo88c76642007-03-13 14:43:18 -0300469 const int type = icmp_hdr(skb)->type;
470 const int code = icmp_hdr(skb)->code;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 struct ip_tunnel *t;
Al Virod5a0a1e2006-11-08 00:23:14 -0800472 __be16 flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
474 flags = p[0];
475 if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
476 if (flags&(GRE_VERSION|GRE_ROUTING))
477 return;
478 if (flags&GRE_KEY) {
479 grehlen += 4;
480 if (flags&GRE_CSUM)
481 grehlen += 4;
482 }
483 }
484
485 /* If only 8 bytes returned, keyed message will be dropped here */
486 if (skb_headlen(skb) < grehlen)
487 return;
488
489 switch (type) {
490 default:
491 case ICMP_PARAMETERPROB:
492 return;
493
494 case ICMP_DEST_UNREACH:
495 switch (code) {
496 case ICMP_SR_FAILED:
497 case ICMP_PORT_UNREACH:
498 /* Impossible event. */
499 return;
500 case ICMP_FRAG_NEEDED:
501 /* Soft state for pmtu is maintained by IP core. */
502 return;
503 default:
504 /* All others are translated to HOST_UNREACH.
505 rfc2003 contains "deep thoughts" about NET_UNREACH,
506 I believe they are just ether pollution. --ANK
507 */
508 break;
509 }
510 break;
511 case ICMP_TIME_EXCEEDED:
512 if (code != ICMP_EXC_TTL)
513 return;
514 break;
515 }
516
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000517 rcu_read_lock();
Timo Teras749c10f2009-01-19 17:22:12 -0800518 t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
Herbert Xue1a80002008-10-09 12:00:17 -0700519 flags & GRE_KEY ?
520 *(((__be32 *)p) + (grehlen / 4) - 1) : 0,
521 p[1]);
Joe Perchesf97c1e02007-12-16 13:45:43 -0800522 if (t == NULL || t->parms.iph.daddr == 0 ||
523 ipv4_is_multicast(t->parms.iph.daddr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 goto out;
525
526 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
527 goto out;
528
Wei Yongjunda6185d82009-02-24 23:34:48 -0800529 if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 t->err_count++;
531 else
532 t->err_count = 1;
533 t->err_time = jiffies;
534out:
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000535 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536}
537
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000538static inline void ipgre_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539{
540 if (INET_ECN_is_ce(iph->tos)) {
541 if (skb->protocol == htons(ETH_P_IP)) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700542 IP_ECN_set_ce(ip_hdr(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 } else if (skb->protocol == htons(ETH_P_IPV6)) {
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -0700544 IP6_ECN_set_ce(ipv6_hdr(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 }
546 }
547}
548
549static inline u8
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000550ipgre_ecn_encapsulate(u8 tos, const struct iphdr *old_iph, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551{
552 u8 inner = 0;
553 if (skb->protocol == htons(ETH_P_IP))
554 inner = old_iph->tos;
555 else if (skb->protocol == htons(ETH_P_IPV6))
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000556 inner = ipv6_get_dsfield((const struct ipv6hdr *)old_iph);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 return INET_ECN_encapsulate(tos, inner);
558}
559
560static int ipgre_rcv(struct sk_buff *skb)
561{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000562 const struct iphdr *iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 u8 *h;
Al Virod5a0a1e2006-11-08 00:23:14 -0800564 __be16 flags;
Al Virod3bc23e2006-11-14 21:24:49 -0800565 __sum16 csum = 0;
Al Virod5a0a1e2006-11-08 00:23:14 -0800566 __be32 key = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 u32 seqno = 0;
568 struct ip_tunnel *tunnel;
569 int offset = 4;
Herbert Xue1a80002008-10-09 12:00:17 -0700570 __be16 gre_proto;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571
572 if (!pskb_may_pull(skb, 16))
573 goto drop_nolock;
574
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700575 iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 h = skb->data;
Al Virod5a0a1e2006-11-08 00:23:14 -0800577 flags = *(__be16*)h;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
579 if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) {
580 /* - Version must be 0.
581 - We do not support routing headers.
582 */
583 if (flags&(GRE_VERSION|GRE_ROUTING))
584 goto drop_nolock;
585
586 if (flags&GRE_CSUM) {
Herbert Xufb286bb2005-11-10 13:01:24 -0800587 switch (skb->ip_summed) {
Patrick McHardy84fa7932006-08-29 16:44:56 -0700588 case CHECKSUM_COMPLETE:
Al Virod3bc23e2006-11-14 21:24:49 -0800589 csum = csum_fold(skb->csum);
Herbert Xufb286bb2005-11-10 13:01:24 -0800590 if (!csum)
591 break;
592 /* fall through */
593 case CHECKSUM_NONE:
594 skb->csum = 0;
595 csum = __skb_checksum_complete(skb);
Patrick McHardy84fa7932006-08-29 16:44:56 -0700596 skb->ip_summed = CHECKSUM_COMPLETE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 }
598 offset += 4;
599 }
600 if (flags&GRE_KEY) {
Al Virod5a0a1e2006-11-08 00:23:14 -0800601 key = *(__be32*)(h + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 offset += 4;
603 }
604 if (flags&GRE_SEQ) {
Al Virod5a0a1e2006-11-08 00:23:14 -0800605 seqno = ntohl(*(__be32*)(h + offset));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 offset += 4;
607 }
608 }
609
Herbert Xue1a80002008-10-09 12:00:17 -0700610 gre_proto = *(__be16 *)(h + 2);
611
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000612 rcu_read_lock();
Timo Teras749c10f2009-01-19 17:22:12 -0800613 if ((tunnel = ipgre_tunnel_lookup(skb->dev,
Herbert Xue1a80002008-10-09 12:00:17 -0700614 iph->saddr, iph->daddr, key,
615 gre_proto))) {
Eric Dumazete985aad2010-09-27 03:57:11 +0000616 struct pcpu_tstats *tstats;
Pavel Emelyanovaddd68e2008-05-21 14:14:22 -0700617
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 secpath_reset(skb);
619
Herbert Xue1a80002008-10-09 12:00:17 -0700620 skb->protocol = gre_proto;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 /* WCCP version 1 and 2 protocol decoding.
622 * - Change protocol to IP
623 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
624 */
Herbert Xue1a80002008-10-09 12:00:17 -0700625 if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) {
YOSHIFUJI Hideaki496c98d2006-10-10 19:41:21 -0700626 skb->protocol = htons(ETH_P_IP);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900627 if ((*(h + offset) & 0xF0) != 0x40)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 offset += 4;
629 }
630
Timo Teras1d069162007-12-20 00:10:33 -0800631 skb->mac_header = skb->network_header;
Arnaldo Carvalho de Melo4209fb62007-03-10 18:42:03 -0300632 __pskb_pull(skb, offset);
Arnaldo Carvalho de Melo9c702202007-04-25 18:04:18 -0700633 skb_postpull_rcsum(skb, skb_transport_header(skb), offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 skb->pkt_type = PACKET_HOST;
635#ifdef CONFIG_NET_IPGRE_BROADCAST
Joe Perchesf97c1e02007-12-16 13:45:43 -0800636 if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 /* Looped back packet, drop it! */
David S. Millerc7537962010-11-11 17:07:48 -0800638 if (rt_is_output_route(skb_rtable(skb)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 goto drop;
Eric Dumazete985aad2010-09-27 03:57:11 +0000640 tunnel->dev->stats.multicast++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 skb->pkt_type = PACKET_BROADCAST;
642 }
643#endif
644
645 if (((flags&GRE_CSUM) && csum) ||
646 (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) {
Eric Dumazete985aad2010-09-27 03:57:11 +0000647 tunnel->dev->stats.rx_crc_errors++;
648 tunnel->dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 goto drop;
650 }
651 if (tunnel->parms.i_flags&GRE_SEQ) {
652 if (!(flags&GRE_SEQ) ||
653 (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) {
Eric Dumazete985aad2010-09-27 03:57:11 +0000654 tunnel->dev->stats.rx_fifo_errors++;
655 tunnel->dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 goto drop;
657 }
658 tunnel->i_seqno = seqno + 1;
659 }
Herbert Xue1a80002008-10-09 12:00:17 -0700660
661 /* Warning: All skb pointers will be invalidated! */
662 if (tunnel->dev->type == ARPHRD_ETHER) {
663 if (!pskb_may_pull(skb, ETH_HLEN)) {
Eric Dumazete985aad2010-09-27 03:57:11 +0000664 tunnel->dev->stats.rx_length_errors++;
665 tunnel->dev->stats.rx_errors++;
Herbert Xue1a80002008-10-09 12:00:17 -0700666 goto drop;
667 }
668
669 iph = ip_hdr(skb);
670 skb->protocol = eth_type_trans(skb, tunnel->dev);
671 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
672 }
673
Eric Dumazete985aad2010-09-27 03:57:11 +0000674 tstats = this_cpu_ptr(tunnel->dev->tstats);
675 tstats->rx_packets++;
676 tstats->rx_bytes += skb->len;
677
678 __skb_tunnel_rx(skb, tunnel->dev);
Herbert Xue1a80002008-10-09 12:00:17 -0700679
680 skb_reset_network_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 ipgre_ecn_decapsulate(iph, skb);
Herbert Xue1a80002008-10-09 12:00:17 -0700682
Eric Dumazetcaf586e2010-09-30 21:06:55 +0000683 netif_rx(skb);
Eric Dumazet8990f462010-09-20 00:12:11 +0000684
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000685 rcu_read_unlock();
Eric Dumazet8990f462010-09-20 00:12:11 +0000686 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 }
Herbert Xu45af08b2006-04-05 22:31:19 -0700688 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
690drop:
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000691 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692drop_nolock:
693 kfree_skb(skb);
Eric Dumazeta02cec22010-09-22 20:43:57 +0000694 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695}
696
Stephen Hemminger6fef4c02009-08-31 19:50:41 +0000697static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698{
Patrick McHardy2941a482006-01-08 22:05:26 -0800699 struct ip_tunnel *tunnel = netdev_priv(dev);
Eric Dumazete985aad2010-09-27 03:57:11 +0000700 struct pcpu_tstats *tstats;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000701 const struct iphdr *old_iph = ip_hdr(skb);
702 const struct iphdr *tiph;
David S. Millercbb1e852011-05-04 12:33:34 -0700703 struct flowi4 fl4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 u8 tos;
Al Virod5a0a1e2006-11-08 00:23:14 -0800705 __be16 df;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 struct rtable *rt; /* Route to the other host */
Eric Dumazet15078502010-09-15 11:07:53 +0000707 struct net_device *tdev; /* Device to other host */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 struct iphdr *iph; /* Our new IP header */
Chuck Leverc2636b42007-10-23 21:07:32 -0700709 unsigned int max_headroom; /* The extra header space needed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 int gre_hlen;
Al Virod5a0a1e2006-11-08 00:23:14 -0800711 __be32 dst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 int mtu;
713
Herbert Xue1a80002008-10-09 12:00:17 -0700714 if (dev->type == ARPHRD_ETHER)
715 IPCB(skb)->flags = 0;
716
717 if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 gre_hlen = 0;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000719 tiph = (const struct iphdr *)skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 } else {
721 gre_hlen = tunnel->hlen;
722 tiph = &tunnel->parms.iph;
723 }
724
725 if ((dst = tiph->daddr) == 0) {
726 /* NBMA tunnel */
727
Eric Dumazetadf30902009-06-02 05:19:30 +0000728 if (skb_dst(skb) == NULL) {
Eric Dumazete985aad2010-09-27 03:57:11 +0000729 dev->stats.tx_fifo_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 goto tx_error;
731 }
732
David S. Miller61d57f82012-01-24 18:23:30 -0500733 if (skb->protocol == htons(ETH_P_IP)) {
Eric Dumazet511c3f92009-06-02 05:14:27 +0000734 rt = skb_rtable(skb);
David S. Miller61d57f82012-01-24 18:23:30 -0500735 dst = rt->rt_gateway;
736 }
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000737#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 else if (skb->protocol == htons(ETH_P_IPV6)) {
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000739 const struct in6_addr *addr6;
David S. Miller0ec88662012-01-27 15:01:08 -0800740 struct neighbour *neigh;
741 bool do_tx_error_icmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 int addr_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
David S. Miller0ec88662012-01-27 15:01:08 -0800744 neigh = dst_neigh_lookup(skb_dst(skb), &ipv6_hdr(skb)->daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 if (neigh == NULL)
746 goto tx_error;
747
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000748 addr6 = (const struct in6_addr *)&neigh->primary_key;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 addr_type = ipv6_addr_type(addr6);
750
751 if (addr_type == IPV6_ADDR_ANY) {
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -0700752 addr6 = &ipv6_hdr(skb)->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 addr_type = ipv6_addr_type(addr6);
754 }
755
756 if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
David S. Miller0ec88662012-01-27 15:01:08 -0800757 do_tx_error_icmp = true;
758 else {
759 do_tx_error_icmp = false;
760 dst = addr6->s6_addr32[3];
761 }
762 neigh_release(neigh);
763 if (do_tx_error_icmp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 goto tx_error_icmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 }
766#endif
767 else
768 goto tx_error;
769 }
770
771 tos = tiph->tos;
Andreas Jaggiee686ca2009-07-14 09:35:59 -0700772 if (tos == 1) {
773 tos = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 if (skb->protocol == htons(ETH_P_IP))
775 tos = old_iph->tos;
Stephen Hemmingerdd4ba832010-07-08 21:35:58 -0700776 else if (skb->protocol == htons(ETH_P_IPV6))
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000777 tos = ipv6_get_dsfield((const struct ipv6hdr *)old_iph);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 }
779
David S. Millercbb1e852011-05-04 12:33:34 -0700780 rt = ip_route_output_gre(dev_net(dev), &fl4, dst, tiph->saddr,
David S. Miller78fbfd82011-03-12 00:00:52 -0500781 tunnel->parms.o_key, RT_TOS(tos),
782 tunnel->parms.link);
783 if (IS_ERR(rt)) {
784 dev->stats.tx_carrier_errors++;
785 goto tx_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 }
Changli Gaod8d1f302010-06-10 23:31:35 -0700787 tdev = rt->dst.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
789 if (tdev == dev) {
790 ip_rt_put(rt);
Eric Dumazete985aad2010-09-27 03:57:11 +0000791 dev->stats.collisions++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 goto tx_error;
793 }
794
795 df = tiph->frag_off;
796 if (df)
Changli Gaod8d1f302010-06-10 23:31:35 -0700797 mtu = dst_mtu(&rt->dst) - dev->hard_header_len - tunnel->hlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 else
Eric Dumazetadf30902009-06-02 05:19:30 +0000799 mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
Eric Dumazetadf30902009-06-02 05:19:30 +0000801 if (skb_dst(skb))
802 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803
804 if (skb->protocol == htons(ETH_P_IP)) {
805 df |= (old_iph->frag_off&htons(IP_DF));
806
807 if ((old_iph->frag_off&htons(IP_DF)) &&
808 mtu < ntohs(old_iph->tot_len)) {
809 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
810 ip_rt_put(rt);
811 goto tx_error;
812 }
813 }
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000814#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 else if (skb->protocol == htons(ETH_P_IPV6)) {
Eric Dumazetadf30902009-06-02 05:19:30 +0000816 struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817
Eric Dumazetadf30902009-06-02 05:19:30 +0000818 if (rt6 && mtu < dst_mtu(skb_dst(skb)) && mtu >= IPV6_MIN_MTU) {
Joe Perchesf97c1e02007-12-16 13:45:43 -0800819 if ((tunnel->parms.iph.daddr &&
820 !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 rt6->rt6i_dst.plen == 128) {
822 rt6->rt6i_flags |= RTF_MODIFIED;
David S. Millerdefb3512010-12-08 21:16:57 -0800823 dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 }
825 }
826
827 if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) {
Alexey Dobriyan3ffe5332010-02-18 08:25:24 +0000828 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 ip_rt_put(rt);
830 goto tx_error;
831 }
832 }
833#endif
834
835 if (tunnel->err_count > 0) {
Wei Yongjunda6185d82009-02-24 23:34:48 -0800836 if (time_before(jiffies,
837 tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 tunnel->err_count--;
839
840 dst_link_failure(skb);
841 } else
842 tunnel->err_count = 0;
843 }
844
Changli Gaod8d1f302010-06-10 23:31:35 -0700845 max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + rt->dst.header_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Patrick McHardycfbba492007-07-09 15:33:40 -0700847 if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
848 (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
Herbert Xu805dc1d2011-11-18 02:20:06 +0000850 if (max_headroom > dev->needed_headroom)
851 dev->needed_headroom = max_headroom;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 if (!new_skb) {
853 ip_rt_put(rt);
Eric Dumazete985aad2010-09-27 03:57:11 +0000854 dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000856 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 }
858 if (skb->sk)
859 skb_set_owner_w(new_skb, skb->sk);
860 dev_kfree_skb(skb);
861 skb = new_skb;
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700862 old_iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 }
864
Herbert Xu64194c32008-10-09 12:03:17 -0700865 skb_reset_transport_header(skb);
Arnaldo Carvalho de Meloe2d1bca2007-04-10 20:46:21 -0700866 skb_push(skb, gre_hlen);
867 skb_reset_network_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
Patrick McHardy48d5cad2006-02-15 15:10:22 -0800869 IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
870 IPSKB_REROUTED);
Eric Dumazetadf30902009-06-02 05:19:30 +0000871 skb_dst_drop(skb);
Changli Gaod8d1f302010-06-10 23:31:35 -0700872 skb_dst_set(skb, &rt->dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
874 /*
875 * Push down and install the IPIP header.
876 */
877
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700878 iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 iph->version = 4;
880 iph->ihl = sizeof(struct iphdr) >> 2;
881 iph->frag_off = df;
882 iph->protocol = IPPROTO_GRE;
883 iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb);
David S. Millercbb1e852011-05-04 12:33:34 -0700884 iph->daddr = fl4.daddr;
885 iph->saddr = fl4.saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 if ((iph->ttl = tiph->ttl) == 0) {
888 if (skb->protocol == htons(ETH_P_IP))
889 iph->ttl = old_iph->ttl;
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000890#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 else if (skb->protocol == htons(ETH_P_IPV6))
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000892 iph->ttl = ((const struct ipv6hdr *)old_iph)->hop_limit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893#endif
894 else
David S. Miller323e1262010-12-12 21:55:08 -0800895 iph->ttl = ip4_dst_hoplimit(&rt->dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 }
897
Herbert Xue1a80002008-10-09 12:00:17 -0700898 ((__be16 *)(iph + 1))[0] = tunnel->parms.o_flags;
899 ((__be16 *)(iph + 1))[1] = (dev->type == ARPHRD_ETHER) ?
900 htons(ETH_P_TEB) : skb->protocol;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902 if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) {
Al Virod5a0a1e2006-11-08 00:23:14 -0800903 __be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
905 if (tunnel->parms.o_flags&GRE_SEQ) {
906 ++tunnel->o_seqno;
907 *ptr = htonl(tunnel->o_seqno);
908 ptr--;
909 }
910 if (tunnel->parms.o_flags&GRE_KEY) {
911 *ptr = tunnel->parms.o_key;
912 ptr--;
913 }
914 if (tunnel->parms.o_flags&GRE_CSUM) {
915 *ptr = 0;
Al Viro5f92a732006-11-14 21:36:54 -0800916 *(__sum16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 }
918 }
919
920 nf_reset(skb);
Eric Dumazete985aad2010-09-27 03:57:11 +0000921 tstats = this_cpu_ptr(dev->tstats);
922 __IPTUNNEL_XMIT(tstats, &dev->stats);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000923 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
David S. Miller496053f2012-01-11 16:46:32 -0800925#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926tx_error_icmp:
927 dst_link_failure(skb);
David S. Miller496053f2012-01-11 16:46:32 -0800928#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929tx_error:
Eric Dumazete985aad2010-09-27 03:57:11 +0000930 dev->stats.tx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000932 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933}
934
Herbert Xu42aa9162008-10-09 11:59:32 -0700935static int ipgre_tunnel_bind_dev(struct net_device *dev)
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800936{
937 struct net_device *tdev = NULL;
938 struct ip_tunnel *tunnel;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000939 const struct iphdr *iph;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800940 int hlen = LL_MAX_HEADER;
941 int mtu = ETH_DATA_LEN;
942 int addend = sizeof(struct iphdr) + 4;
943
944 tunnel = netdev_priv(dev);
945 iph = &tunnel->parms.iph;
946
Herbert Xuc95b8192008-10-09 11:58:54 -0700947 /* Guess output device to choose reasonable mtu and needed_headroom */
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800948
949 if (iph->daddr) {
David S. Millercbb1e852011-05-04 12:33:34 -0700950 struct flowi4 fl4;
951 struct rtable *rt;
Eric Dumazete985aad2010-09-27 03:57:11 +0000952
David S. Millercbb1e852011-05-04 12:33:34 -0700953 rt = ip_route_output_gre(dev_net(dev), &fl4,
954 iph->daddr, iph->saddr,
955 tunnel->parms.o_key,
956 RT_TOS(iph->tos),
957 tunnel->parms.link);
David S. Millerb23dd4f2011-03-02 14:31:35 -0800958 if (!IS_ERR(rt)) {
Changli Gaod8d1f302010-06-10 23:31:35 -0700959 tdev = rt->dst.dev;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800960 ip_rt_put(rt);
961 }
Herbert Xue1a80002008-10-09 12:00:17 -0700962
963 if (dev->type != ARPHRD_ETHER)
964 dev->flags |= IFF_POINTOPOINT;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800965 }
966
967 if (!tdev && tunnel->parms.link)
Pavel Emelyanov96635522008-04-16 01:10:44 -0700968 tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800969
970 if (tdev) {
Herbert Xuc95b8192008-10-09 11:58:54 -0700971 hlen = tdev->hard_header_len + tdev->needed_headroom;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800972 mtu = tdev->mtu;
973 }
974 dev->iflink = tunnel->parms.link;
975
976 /* Precalculate GRE options length */
977 if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
978 if (tunnel->parms.o_flags&GRE_CSUM)
979 addend += 4;
980 if (tunnel->parms.o_flags&GRE_KEY)
981 addend += 4;
982 if (tunnel->parms.o_flags&GRE_SEQ)
983 addend += 4;
984 }
Herbert Xuc95b8192008-10-09 11:58:54 -0700985 dev->needed_headroom = addend + hlen;
Tom Goff8cdb0452009-08-14 16:33:56 -0700986 mtu -= dev->hard_header_len + addend;
Herbert Xu42aa9162008-10-09 11:59:32 -0700987
988 if (mtu < 68)
989 mtu = 68;
990
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800991 tunnel->hlen = addend;
992
Herbert Xu42aa9162008-10-09 11:59:32 -0700993 return mtu;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800994}
995
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996static int
997ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
998{
999 int err = 0;
1000 struct ip_tunnel_parm p;
1001 struct ip_tunnel *t;
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001002 struct net *net = dev_net(dev);
1003 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
1005 switch (cmd) {
1006 case SIOCGETTUNNEL:
1007 t = NULL;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001008 if (dev == ign->fb_tunnel_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
1010 err = -EFAULT;
1011 break;
1012 }
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001013 t = ipgre_tunnel_locate(net, &p, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 }
1015 if (t == NULL)
Patrick McHardy2941a482006-01-08 22:05:26 -08001016 t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 memcpy(&p, &t->parms, sizeof(p));
1018 if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
1019 err = -EFAULT;
1020 break;
1021
1022 case SIOCADDTUNNEL:
1023 case SIOCCHGTUNNEL:
1024 err = -EPERM;
1025 if (!capable(CAP_NET_ADMIN))
1026 goto done;
1027
1028 err = -EFAULT;
1029 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
1030 goto done;
1031
1032 err = -EINVAL;
1033 if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
1034 p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
1035 ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
1036 goto done;
1037 if (p.iph.ttl)
1038 p.iph.frag_off |= htons(IP_DF);
1039
1040 if (!(p.i_flags&GRE_KEY))
1041 p.i_key = 0;
1042 if (!(p.o_flags&GRE_KEY))
1043 p.o_key = 0;
1044
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001045 t = ipgre_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001047 if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 if (t != NULL) {
1049 if (t->dev != dev) {
1050 err = -EEXIST;
1051 break;
1052 }
1053 } else {
Eric Dumazet15078502010-09-15 11:07:53 +00001054 unsigned int nflags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Patrick McHardy2941a482006-01-08 22:05:26 -08001056 t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
Joe Perchesf97c1e02007-12-16 13:45:43 -08001058 if (ipv4_is_multicast(p.iph.daddr))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 nflags = IFF_BROADCAST;
1060 else if (p.iph.daddr)
1061 nflags = IFF_POINTOPOINT;
1062
1063 if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
1064 err = -EINVAL;
1065 break;
1066 }
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001067 ipgre_tunnel_unlink(ign, t);
Pavel Emelyanov74b0b852010-10-27 05:43:53 +00001068 synchronize_net();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 t->parms.iph.saddr = p.iph.saddr;
1070 t->parms.iph.daddr = p.iph.daddr;
1071 t->parms.i_key = p.i_key;
1072 t->parms.o_key = p.o_key;
1073 memcpy(dev->dev_addr, &p.iph.saddr, 4);
1074 memcpy(dev->broadcast, &p.iph.daddr, 4);
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001075 ipgre_tunnel_link(ign, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 netdev_state_change(dev);
1077 }
1078 }
1079
1080 if (t) {
1081 err = 0;
1082 if (cmd == SIOCCHGTUNNEL) {
1083 t->parms.iph.ttl = p.iph.ttl;
1084 t->parms.iph.tos = p.iph.tos;
1085 t->parms.iph.frag_off = p.iph.frag_off;
Michal Schmidtee34c1e2007-12-13 09:46:32 -08001086 if (t->parms.link != p.link) {
1087 t->parms.link = p.link;
Herbert Xu42aa9162008-10-09 11:59:32 -07001088 dev->mtu = ipgre_tunnel_bind_dev(dev);
Michal Schmidtee34c1e2007-12-13 09:46:32 -08001089 netdev_state_change(dev);
1090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 }
1092 if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
1093 err = -EFAULT;
1094 } else
1095 err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
1096 break;
1097
1098 case SIOCDELTUNNEL:
1099 err = -EPERM;
1100 if (!capable(CAP_NET_ADMIN))
1101 goto done;
1102
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001103 if (dev == ign->fb_tunnel_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 err = -EFAULT;
1105 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
1106 goto done;
1107 err = -ENOENT;
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001108 if ((t = ipgre_tunnel_locate(net, &p, 0)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 goto done;
1110 err = -EPERM;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001111 if (t == netdev_priv(ign->fb_tunnel_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 goto done;
1113 dev = t->dev;
1114 }
Stephen Hemminger22f8cde2007-02-07 00:09:58 -08001115 unregister_netdevice(dev);
1116 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 break;
1118
1119 default:
1120 err = -EINVAL;
1121 }
1122
1123done:
1124 return err;
1125}
1126
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
1128{
Patrick McHardy2941a482006-01-08 22:05:26 -08001129 struct ip_tunnel *tunnel = netdev_priv(dev);
Herbert Xuc95b8192008-10-09 11:58:54 -07001130 if (new_mtu < 68 ||
1131 new_mtu > 0xFFF8 - dev->hard_header_len - tunnel->hlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 return -EINVAL;
1133 dev->mtu = new_mtu;
1134 return 0;
1135}
1136
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137/* Nice toy. Unfortunately, useless in real life :-)
1138 It allows to construct virtual multiprotocol broadcast "LAN"
1139 over the Internet, provided multicast routing is tuned.
1140
1141
1142 I have no idea was this bicycle invented before me,
1143 so that I had to set ARPHRD_IPGRE to a random value.
1144 I have an impression, that Cisco could make something similar,
1145 but this feature is apparently missing in IOS<=11.2(8).
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001146
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
1148 with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
1149
1150 ping -t 255 224.66.66.66
1151
1152 If nobody answers, mbone does not work.
1153
1154 ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
1155 ip addr add 10.66.66.<somewhat>/24 dev Universe
1156 ifconfig Universe up
1157 ifconfig Universe add fe80::<Your_real_addr>/10
1158 ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
1159 ftp 10.66.66.66
1160 ...
1161 ftp fec0:6666:6666::193.233.7.65
1162 ...
1163
1164 */
1165
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001166static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
1167 unsigned short type,
Eric Dumazet15078502010-09-15 11:07:53 +00001168 const void *daddr, const void *saddr, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169{
Patrick McHardy2941a482006-01-08 22:05:26 -08001170 struct ip_tunnel *t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen);
Al Virod5a0a1e2006-11-08 00:23:14 -08001172 __be16 *p = (__be16*)(iph+1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
1174 memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
1175 p[0] = t->parms.o_flags;
1176 p[1] = htons(type);
1177
1178 /*
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001179 * Set the source hardware address.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 */
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001181
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 if (saddr)
1183 memcpy(&iph->saddr, saddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +00001184 if (daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 memcpy(&iph->daddr, daddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +00001186 if (iph->daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 return t->hlen;
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001188
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 return -t->hlen;
1190}
1191
Timo Teras6a5f44d2007-10-23 20:31:53 -07001192static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
1193{
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001194 const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
Timo Teras6a5f44d2007-10-23 20:31:53 -07001195 memcpy(haddr, &iph->saddr, 4);
1196 return 4;
1197}
1198
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001199static const struct header_ops ipgre_header_ops = {
1200 .create = ipgre_header,
Timo Teras6a5f44d2007-10-23 20:31:53 -07001201 .parse = ipgre_header_parse,
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001202};
1203
Timo Teras6a5f44d2007-10-23 20:31:53 -07001204#ifdef CONFIG_NET_IPGRE_BROADCAST
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205static int ipgre_open(struct net_device *dev)
1206{
Patrick McHardy2941a482006-01-08 22:05:26 -08001207 struct ip_tunnel *t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
Joe Perchesf97c1e02007-12-16 13:45:43 -08001209 if (ipv4_is_multicast(t->parms.iph.daddr)) {
David S. Millercbb1e852011-05-04 12:33:34 -07001210 struct flowi4 fl4;
1211 struct rtable *rt;
Eric Dumazete985aad2010-09-27 03:57:11 +00001212
David S. Millercbb1e852011-05-04 12:33:34 -07001213 rt = ip_route_output_gre(dev_net(dev), &fl4,
1214 t->parms.iph.daddr,
1215 t->parms.iph.saddr,
1216 t->parms.o_key,
1217 RT_TOS(t->parms.iph.tos),
1218 t->parms.link);
David S. Millerb23dd4f2011-03-02 14:31:35 -08001219 if (IS_ERR(rt))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 return -EADDRNOTAVAIL;
Changli Gaod8d1f302010-06-10 23:31:35 -07001221 dev = rt->dst.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 ip_rt_put(rt);
Herbert Xue5ed6392005-10-03 14:35:55 -07001223 if (__in_dev_get_rtnl(dev) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 return -EADDRNOTAVAIL;
1225 t->mlink = dev->ifindex;
Herbert Xue5ed6392005-10-03 14:35:55 -07001226 ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 }
1228 return 0;
1229}
1230
1231static int ipgre_close(struct net_device *dev)
1232{
Patrick McHardy2941a482006-01-08 22:05:26 -08001233 struct ip_tunnel *t = netdev_priv(dev);
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001234
Joe Perchesf97c1e02007-12-16 13:45:43 -08001235 if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
Denis V. Lunev7fee0ca2008-01-21 17:32:38 -08001236 struct in_device *in_dev;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09001237 in_dev = inetdev_by_index(dev_net(dev), t->mlink);
Eric Dumazet8723e1b2010-10-19 00:39:26 +00001238 if (in_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 ip_mc_dec_group(in_dev, t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 }
1241 return 0;
1242}
1243
1244#endif
1245
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001246static const struct net_device_ops ipgre_netdev_ops = {
1247 .ndo_init = ipgre_tunnel_init,
1248 .ndo_uninit = ipgre_tunnel_uninit,
1249#ifdef CONFIG_NET_IPGRE_BROADCAST
1250 .ndo_open = ipgre_open,
1251 .ndo_stop = ipgre_close,
1252#endif
1253 .ndo_start_xmit = ipgre_tunnel_xmit,
1254 .ndo_do_ioctl = ipgre_tunnel_ioctl,
1255 .ndo_change_mtu = ipgre_tunnel_change_mtu,
Eric Dumazete985aad2010-09-27 03:57:11 +00001256 .ndo_get_stats = ipgre_get_stats,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001257};
1258
Eric Dumazete985aad2010-09-27 03:57:11 +00001259static void ipgre_dev_free(struct net_device *dev)
1260{
1261 free_percpu(dev->tstats);
1262 free_netdev(dev);
1263}
1264
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265static void ipgre_tunnel_setup(struct net_device *dev)
1266{
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001267 dev->netdev_ops = &ipgre_netdev_ops;
Eric Dumazete985aad2010-09-27 03:57:11 +00001268 dev->destructor = ipgre_dev_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
1270 dev->type = ARPHRD_IPGRE;
Herbert Xuc95b8192008-10-09 11:58:54 -07001271 dev->needed_headroom = LL_MAX_HEADER + sizeof(struct iphdr) + 4;
Kris Katterjohn46f25df2006-01-05 16:35:42 -08001272 dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 dev->flags = IFF_NOARP;
1274 dev->iflink = 0;
1275 dev->addr_len = 4;
Pavel Emelyanov0b67ece2008-04-16 01:11:13 -07001276 dev->features |= NETIF_F_NETNS_LOCAL;
Eric Dumazet108bfa82009-05-28 22:35:10 +00001277 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278}
1279
1280static int ipgre_tunnel_init(struct net_device *dev)
1281{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 struct ip_tunnel *tunnel;
1283 struct iphdr *iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
Patrick McHardy2941a482006-01-08 22:05:26 -08001285 tunnel = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 iph = &tunnel->parms.iph;
1287
1288 tunnel->dev = dev;
1289 strcpy(tunnel->parms.name, dev->name);
1290
1291 memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
1292 memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
1293
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 if (iph->daddr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295#ifdef CONFIG_NET_IPGRE_BROADCAST
Joe Perchesf97c1e02007-12-16 13:45:43 -08001296 if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 if (!iph->saddr)
1298 return -EINVAL;
1299 dev->flags = IFF_BROADCAST;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001300 dev->header_ops = &ipgre_header_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 }
1302#endif
Michal Schmidtee34c1e2007-12-13 09:46:32 -08001303 } else
Timo Teras6a5f44d2007-10-23 20:31:53 -07001304 dev->header_ops = &ipgre_header_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
Eric Dumazete985aad2010-09-27 03:57:11 +00001306 dev->tstats = alloc_percpu(struct pcpu_tstats);
1307 if (!dev->tstats)
1308 return -ENOMEM;
1309
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 return 0;
1311}
1312
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001313static void ipgre_fb_tunnel_init(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314{
Patrick McHardy2941a482006-01-08 22:05:26 -08001315 struct ip_tunnel *tunnel = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 struct iphdr *iph = &tunnel->parms.iph;
1317
1318 tunnel->dev = dev;
1319 strcpy(tunnel->parms.name, dev->name);
1320
1321 iph->version = 4;
1322 iph->protocol = IPPROTO_GRE;
1323 iph->ihl = 5;
1324 tunnel->hlen = sizeof(struct iphdr) + 4;
1325
1326 dev_hold(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327}
1328
1329
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001330static const struct gre_protocol ipgre_protocol = {
1331 .handler = ipgre_rcv,
1332 .err_handler = ipgre_err,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333};
1334
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001335static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -07001336{
1337 int prio;
1338
1339 for (prio = 0; prio < 4; prio++) {
1340 int h;
1341 for (h = 0; h < HASH_SIZE; h++) {
Eric Dumazet15078502010-09-15 11:07:53 +00001342 struct ip_tunnel *t;
1343
1344 t = rtnl_dereference(ign->tunnels[prio][h]);
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001345
1346 while (t != NULL) {
1347 unregister_netdevice_queue(t->dev, head);
Eric Dumazet15078502010-09-15 11:07:53 +00001348 t = rtnl_dereference(t->next);
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001349 }
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -07001350 }
1351 }
1352}
1353
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001354static int __net_init ipgre_init_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001355{
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001356 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001357 int err;
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001358
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001359 ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0",
1360 ipgre_tunnel_setup);
1361 if (!ign->fb_tunnel_dev) {
1362 err = -ENOMEM;
1363 goto err_alloc_dev;
1364 }
Alexey Dobriyanbe77e592008-11-23 17:26:26 -08001365 dev_net_set(ign->fb_tunnel_dev, net);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001366
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001367 ipgre_fb_tunnel_init(ign->fb_tunnel_dev);
Herbert Xuc19e6542008-10-09 11:59:55 -07001368 ign->fb_tunnel_dev->rtnl_link_ops = &ipgre_link_ops;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001369
1370 if ((err = register_netdev(ign->fb_tunnel_dev)))
1371 goto err_reg_dev;
1372
Eric Dumazet3285ee32010-10-30 16:21:28 -07001373 rcu_assign_pointer(ign->tunnels_wc[0],
1374 netdev_priv(ign->fb_tunnel_dev));
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001375 return 0;
1376
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001377err_reg_dev:
Eric Dumazet3285ee32010-10-30 16:21:28 -07001378 ipgre_dev_free(ign->fb_tunnel_dev);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001379err_alloc_dev:
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001380 return err;
1381}
1382
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001383static void __net_exit ipgre_exit_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001384{
1385 struct ipgre_net *ign;
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001386 LIST_HEAD(list);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001387
1388 ign = net_generic(net, ipgre_net_id);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001389 rtnl_lock();
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001390 ipgre_destroy_tunnels(ign, &list);
1391 unregister_netdevice_many(&list);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001392 rtnl_unlock();
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001393}
1394
1395static struct pernet_operations ipgre_net_ops = {
1396 .init = ipgre_init_net,
1397 .exit = ipgre_exit_net,
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001398 .id = &ipgre_net_id,
1399 .size = sizeof(struct ipgre_net),
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001400};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Herbert Xuc19e6542008-10-09 11:59:55 -07001402static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
1403{
1404 __be16 flags;
1405
1406 if (!data)
1407 return 0;
1408
1409 flags = 0;
1410 if (data[IFLA_GRE_IFLAGS])
1411 flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1412 if (data[IFLA_GRE_OFLAGS])
1413 flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1414 if (flags & (GRE_VERSION|GRE_ROUTING))
1415 return -EINVAL;
1416
1417 return 0;
1418}
1419
Herbert Xue1a80002008-10-09 12:00:17 -07001420static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
1421{
1422 __be32 daddr;
1423
1424 if (tb[IFLA_ADDRESS]) {
1425 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1426 return -EINVAL;
1427 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1428 return -EADDRNOTAVAIL;
1429 }
1430
1431 if (!data)
1432 goto out;
1433
1434 if (data[IFLA_GRE_REMOTE]) {
1435 memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1436 if (!daddr)
1437 return -EINVAL;
1438 }
1439
1440out:
1441 return ipgre_tunnel_validate(tb, data);
1442}
1443
Herbert Xuc19e6542008-10-09 11:59:55 -07001444static void ipgre_netlink_parms(struct nlattr *data[],
1445 struct ip_tunnel_parm *parms)
1446{
Herbert Xu7bb82d92008-10-11 12:20:15 -07001447 memset(parms, 0, sizeof(*parms));
Herbert Xuc19e6542008-10-09 11:59:55 -07001448
1449 parms->iph.protocol = IPPROTO_GRE;
1450
1451 if (!data)
1452 return;
1453
1454 if (data[IFLA_GRE_LINK])
1455 parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1456
1457 if (data[IFLA_GRE_IFLAGS])
1458 parms->i_flags = nla_get_be16(data[IFLA_GRE_IFLAGS]);
1459
1460 if (data[IFLA_GRE_OFLAGS])
1461 parms->o_flags = nla_get_be16(data[IFLA_GRE_OFLAGS]);
1462
1463 if (data[IFLA_GRE_IKEY])
1464 parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1465
1466 if (data[IFLA_GRE_OKEY])
1467 parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1468
1469 if (data[IFLA_GRE_LOCAL])
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001470 parms->iph.saddr = nla_get_be32(data[IFLA_GRE_LOCAL]);
Herbert Xuc19e6542008-10-09 11:59:55 -07001471
1472 if (data[IFLA_GRE_REMOTE])
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001473 parms->iph.daddr = nla_get_be32(data[IFLA_GRE_REMOTE]);
Herbert Xuc19e6542008-10-09 11:59:55 -07001474
1475 if (data[IFLA_GRE_TTL])
1476 parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1477
1478 if (data[IFLA_GRE_TOS])
1479 parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1480
1481 if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC]))
1482 parms->iph.frag_off = htons(IP_DF);
1483}
1484
Herbert Xue1a80002008-10-09 12:00:17 -07001485static int ipgre_tap_init(struct net_device *dev)
1486{
1487 struct ip_tunnel *tunnel;
1488
1489 tunnel = netdev_priv(dev);
1490
1491 tunnel->dev = dev;
1492 strcpy(tunnel->parms.name, dev->name);
1493
1494 ipgre_tunnel_bind_dev(dev);
1495
Eric Dumazete985aad2010-09-27 03:57:11 +00001496 dev->tstats = alloc_percpu(struct pcpu_tstats);
1497 if (!dev->tstats)
1498 return -ENOMEM;
1499
Herbert Xue1a80002008-10-09 12:00:17 -07001500 return 0;
1501}
1502
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001503static const struct net_device_ops ipgre_tap_netdev_ops = {
1504 .ndo_init = ipgre_tap_init,
1505 .ndo_uninit = ipgre_tunnel_uninit,
1506 .ndo_start_xmit = ipgre_tunnel_xmit,
1507 .ndo_set_mac_address = eth_mac_addr,
1508 .ndo_validate_addr = eth_validate_addr,
1509 .ndo_change_mtu = ipgre_tunnel_change_mtu,
Eric Dumazete985aad2010-09-27 03:57:11 +00001510 .ndo_get_stats = ipgre_get_stats,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001511};
1512
Herbert Xue1a80002008-10-09 12:00:17 -07001513static void ipgre_tap_setup(struct net_device *dev)
1514{
1515
1516 ether_setup(dev);
1517
Herbert Xu2e9526b2009-10-30 05:51:48 +00001518 dev->netdev_ops = &ipgre_tap_netdev_ops;
Eric Dumazete985aad2010-09-27 03:57:11 +00001519 dev->destructor = ipgre_dev_free;
Herbert Xue1a80002008-10-09 12:00:17 -07001520
1521 dev->iflink = 0;
1522 dev->features |= NETIF_F_NETNS_LOCAL;
1523}
1524
Eric W. Biederman81adee42009-11-08 00:53:51 -08001525static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[],
Herbert Xuc19e6542008-10-09 11:59:55 -07001526 struct nlattr *data[])
1527{
1528 struct ip_tunnel *nt;
1529 struct net *net = dev_net(dev);
1530 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
1531 int mtu;
1532 int err;
1533
1534 nt = netdev_priv(dev);
1535 ipgre_netlink_parms(data, &nt->parms);
1536
Herbert Xue1a80002008-10-09 12:00:17 -07001537 if (ipgre_tunnel_find(net, &nt->parms, dev->type))
Herbert Xuc19e6542008-10-09 11:59:55 -07001538 return -EEXIST;
1539
Herbert Xue1a80002008-10-09 12:00:17 -07001540 if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
Danny Kukawkaf2cedb62012-02-15 06:45:39 +00001541 eth_hw_addr_random(dev);
Herbert Xue1a80002008-10-09 12:00:17 -07001542
Herbert Xuc19e6542008-10-09 11:59:55 -07001543 mtu = ipgre_tunnel_bind_dev(dev);
1544 if (!tb[IFLA_MTU])
1545 dev->mtu = mtu;
1546
Eric Dumazetb790e012010-09-27 23:05:47 +00001547 /* Can use a lockless transmit, unless we generate output sequences */
1548 if (!(nt->parms.o_flags & GRE_SEQ))
1549 dev->features |= NETIF_F_LLTX;
1550
Herbert Xuc19e6542008-10-09 11:59:55 -07001551 err = register_netdevice(dev);
1552 if (err)
1553 goto out;
1554
1555 dev_hold(dev);
1556 ipgre_tunnel_link(ign, nt);
1557
1558out:
1559 return err;
1560}
1561
1562static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1563 struct nlattr *data[])
1564{
1565 struct ip_tunnel *t, *nt;
1566 struct net *net = dev_net(dev);
1567 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
1568 struct ip_tunnel_parm p;
1569 int mtu;
1570
1571 if (dev == ign->fb_tunnel_dev)
1572 return -EINVAL;
1573
1574 nt = netdev_priv(dev);
1575 ipgre_netlink_parms(data, &p);
1576
1577 t = ipgre_tunnel_locate(net, &p, 0);
1578
1579 if (t) {
1580 if (t->dev != dev)
1581 return -EEXIST;
1582 } else {
Herbert Xuc19e6542008-10-09 11:59:55 -07001583 t = nt;
1584
Herbert Xu2e9526b2009-10-30 05:51:48 +00001585 if (dev->type != ARPHRD_ETHER) {
Eric Dumazet15078502010-09-15 11:07:53 +00001586 unsigned int nflags = 0;
Herbert Xuc19e6542008-10-09 11:59:55 -07001587
Herbert Xu2e9526b2009-10-30 05:51:48 +00001588 if (ipv4_is_multicast(p.iph.daddr))
1589 nflags = IFF_BROADCAST;
1590 else if (p.iph.daddr)
1591 nflags = IFF_POINTOPOINT;
1592
1593 if ((dev->flags ^ nflags) &
1594 (IFF_POINTOPOINT | IFF_BROADCAST))
1595 return -EINVAL;
1596 }
Herbert Xuc19e6542008-10-09 11:59:55 -07001597
1598 ipgre_tunnel_unlink(ign, t);
1599 t->parms.iph.saddr = p.iph.saddr;
1600 t->parms.iph.daddr = p.iph.daddr;
1601 t->parms.i_key = p.i_key;
Herbert Xu2e9526b2009-10-30 05:51:48 +00001602 if (dev->type != ARPHRD_ETHER) {
1603 memcpy(dev->dev_addr, &p.iph.saddr, 4);
1604 memcpy(dev->broadcast, &p.iph.daddr, 4);
1605 }
Herbert Xuc19e6542008-10-09 11:59:55 -07001606 ipgre_tunnel_link(ign, t);
1607 netdev_state_change(dev);
1608 }
1609
1610 t->parms.o_key = p.o_key;
1611 t->parms.iph.ttl = p.iph.ttl;
1612 t->parms.iph.tos = p.iph.tos;
1613 t->parms.iph.frag_off = p.iph.frag_off;
1614
1615 if (t->parms.link != p.link) {
1616 t->parms.link = p.link;
1617 mtu = ipgre_tunnel_bind_dev(dev);
1618 if (!tb[IFLA_MTU])
1619 dev->mtu = mtu;
1620 netdev_state_change(dev);
1621 }
1622
1623 return 0;
1624}
1625
1626static size_t ipgre_get_size(const struct net_device *dev)
1627{
1628 return
1629 /* IFLA_GRE_LINK */
1630 nla_total_size(4) +
1631 /* IFLA_GRE_IFLAGS */
1632 nla_total_size(2) +
1633 /* IFLA_GRE_OFLAGS */
1634 nla_total_size(2) +
1635 /* IFLA_GRE_IKEY */
1636 nla_total_size(4) +
1637 /* IFLA_GRE_OKEY */
1638 nla_total_size(4) +
1639 /* IFLA_GRE_LOCAL */
1640 nla_total_size(4) +
1641 /* IFLA_GRE_REMOTE */
1642 nla_total_size(4) +
1643 /* IFLA_GRE_TTL */
1644 nla_total_size(1) +
1645 /* IFLA_GRE_TOS */
1646 nla_total_size(1) +
1647 /* IFLA_GRE_PMTUDISC */
1648 nla_total_size(1) +
1649 0;
1650}
1651
1652static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1653{
1654 struct ip_tunnel *t = netdev_priv(dev);
1655 struct ip_tunnel_parm *p = &t->parms;
1656
1657 NLA_PUT_U32(skb, IFLA_GRE_LINK, p->link);
1658 NLA_PUT_BE16(skb, IFLA_GRE_IFLAGS, p->i_flags);
1659 NLA_PUT_BE16(skb, IFLA_GRE_OFLAGS, p->o_flags);
Patrick McHardyba9e64b2008-10-10 12:10:30 -07001660 NLA_PUT_BE32(skb, IFLA_GRE_IKEY, p->i_key);
1661 NLA_PUT_BE32(skb, IFLA_GRE_OKEY, p->o_key);
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001662 NLA_PUT_BE32(skb, IFLA_GRE_LOCAL, p->iph.saddr);
1663 NLA_PUT_BE32(skb, IFLA_GRE_REMOTE, p->iph.daddr);
Herbert Xuc19e6542008-10-09 11:59:55 -07001664 NLA_PUT_U8(skb, IFLA_GRE_TTL, p->iph.ttl);
1665 NLA_PUT_U8(skb, IFLA_GRE_TOS, p->iph.tos);
1666 NLA_PUT_U8(skb, IFLA_GRE_PMTUDISC, !!(p->iph.frag_off & htons(IP_DF)));
1667
1668 return 0;
1669
1670nla_put_failure:
1671 return -EMSGSIZE;
1672}
1673
1674static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1675 [IFLA_GRE_LINK] = { .type = NLA_U32 },
1676 [IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
1677 [IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
1678 [IFLA_GRE_IKEY] = { .type = NLA_U32 },
1679 [IFLA_GRE_OKEY] = { .type = NLA_U32 },
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001680 [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
1681 [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
Herbert Xuc19e6542008-10-09 11:59:55 -07001682 [IFLA_GRE_TTL] = { .type = NLA_U8 },
1683 [IFLA_GRE_TOS] = { .type = NLA_U8 },
1684 [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 },
1685};
1686
1687static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1688 .kind = "gre",
1689 .maxtype = IFLA_GRE_MAX,
1690 .policy = ipgre_policy,
1691 .priv_size = sizeof(struct ip_tunnel),
1692 .setup = ipgre_tunnel_setup,
1693 .validate = ipgre_tunnel_validate,
1694 .newlink = ipgre_newlink,
1695 .changelink = ipgre_changelink,
1696 .get_size = ipgre_get_size,
1697 .fill_info = ipgre_fill_info,
1698};
1699
Herbert Xue1a80002008-10-09 12:00:17 -07001700static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1701 .kind = "gretap",
1702 .maxtype = IFLA_GRE_MAX,
1703 .policy = ipgre_policy,
1704 .priv_size = sizeof(struct ip_tunnel),
1705 .setup = ipgre_tap_setup,
1706 .validate = ipgre_tap_validate,
1707 .newlink = ipgre_newlink,
1708 .changelink = ipgre_changelink,
1709 .get_size = ipgre_get_size,
1710 .fill_info = ipgre_fill_info,
1711};
1712
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713/*
1714 * And now the modules code and kernel interface.
1715 */
1716
1717static int __init ipgre_init(void)
1718{
1719 int err;
1720
Joe Perches058bd4d2012-03-11 18:36:11 +00001721 pr_info("GRE over IPv4 tunneling driver\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001723 err = register_pernet_device(&ipgre_net_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001724 if (err < 0)
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001725 return err;
1726
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001727 err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001728 if (err < 0) {
Joe Perches058bd4d2012-03-11 18:36:11 +00001729 pr_info("%s: can't add protocol\n", __func__);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001730 goto add_proto_failed;
1731 }
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001732
Herbert Xuc19e6542008-10-09 11:59:55 -07001733 err = rtnl_link_register(&ipgre_link_ops);
1734 if (err < 0)
1735 goto rtnl_link_failed;
1736
Herbert Xue1a80002008-10-09 12:00:17 -07001737 err = rtnl_link_register(&ipgre_tap_ops);
1738 if (err < 0)
1739 goto tap_ops_failed;
1740
Herbert Xuc19e6542008-10-09 11:59:55 -07001741out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 return err;
Herbert Xuc19e6542008-10-09 11:59:55 -07001743
Herbert Xue1a80002008-10-09 12:00:17 -07001744tap_ops_failed:
1745 rtnl_link_unregister(&ipgre_link_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001746rtnl_link_failed:
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001747 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001748add_proto_failed:
1749 unregister_pernet_device(&ipgre_net_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001750 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751}
1752
Alexey Kuznetsovdb445752005-07-30 17:46:44 -07001753static void __exit ipgre_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754{
Herbert Xue1a80002008-10-09 12:00:17 -07001755 rtnl_link_unregister(&ipgre_tap_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001756 rtnl_link_unregister(&ipgre_link_ops);
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001757 if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0)
Joe Perches058bd4d2012-03-11 18:36:11 +00001758 pr_info("%s: can't remove protocol\n", __func__);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001759 unregister_pernet_device(&ipgre_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760}
1761
1762module_init(ipgre_init);
1763module_exit(ipgre_fini);
1764MODULE_LICENSE("GPL");
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001765MODULE_ALIAS_RTNL_LINK("gre");
1766MODULE_ALIAS_RTNL_LINK("gretap");
Vasiliy Kulikov8909c9a2011-03-02 00:33:13 +03001767MODULE_ALIAS_NETDEV("gre0");