blob: 5190c0be2787bef822357fc289d2872c47519642 [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 Emelyanovb37d4282008-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 Emelyanovb37d4282008-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 Dumazet8a533662012-02-09 16:13:19 -0500739 struct neighbour *neigh = dst_get_neighbour(skb_dst(skb));
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000740 const struct in6_addr *addr6;
David S. Miller0ec88662012-01-27 15:01:08 -0800741 struct neighbour *neigh;
742 bool do_tx_error_icmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 int addr_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
David S. Miller0ec88662012-01-27 15:01:08 -0800745 neigh = dst_neigh_lookup(skb_dst(skb), &ipv6_hdr(skb)->daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 if (neigh == NULL)
747 goto tx_error;
748
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000749 addr6 = (const struct in6_addr *)&neigh->primary_key;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 addr_type = ipv6_addr_type(addr6);
751
752 if (addr_type == IPV6_ADDR_ANY) {
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -0700753 addr6 = &ipv6_hdr(skb)->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 addr_type = ipv6_addr_type(addr6);
755 }
756
757 if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
David S. Miller0ec88662012-01-27 15:01:08 -0800758 do_tx_error_icmp = true;
759 else {
760 do_tx_error_icmp = false;
761 dst = addr6->s6_addr32[3];
762 }
763 neigh_release(neigh);
764 if (do_tx_error_icmp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 goto tx_error_icmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 }
767#endif
768 else
769 goto tx_error;
770 }
771
772 tos = tiph->tos;
Andreas Jaggiee686ca2009-07-14 09:35:59 -0700773 if (tos == 1) {
774 tos = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 if (skb->protocol == htons(ETH_P_IP))
776 tos = old_iph->tos;
Stephen Hemmingerdd4ba832010-07-08 21:35:58 -0700777 else if (skb->protocol == htons(ETH_P_IPV6))
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000778 tos = ipv6_get_dsfield((const struct ipv6hdr *)old_iph);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 }
780
David S. Millercbb1e852011-05-04 12:33:34 -0700781 rt = ip_route_output_gre(dev_net(dev), &fl4, dst, tiph->saddr,
David S. Miller78fbfd82011-03-12 00:00:52 -0500782 tunnel->parms.o_key, RT_TOS(tos),
783 tunnel->parms.link);
784 if (IS_ERR(rt)) {
785 dev->stats.tx_carrier_errors++;
786 goto tx_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 }
Changli Gaod8d1f302010-06-10 23:31:35 -0700788 tdev = rt->dst.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
790 if (tdev == dev) {
791 ip_rt_put(rt);
Eric Dumazete985aad2010-09-27 03:57:11 +0000792 dev->stats.collisions++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 goto tx_error;
794 }
795
796 df = tiph->frag_off;
797 if (df)
Changli Gaod8d1f302010-06-10 23:31:35 -0700798 mtu = dst_mtu(&rt->dst) - dev->hard_header_len - tunnel->hlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 else
Eric Dumazetadf30902009-06-02 05:19:30 +0000800 mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
Eric Dumazetadf30902009-06-02 05:19:30 +0000802 if (skb_dst(skb))
803 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
805 if (skb->protocol == htons(ETH_P_IP)) {
806 df |= (old_iph->frag_off&htons(IP_DF));
807
808 if ((old_iph->frag_off&htons(IP_DF)) &&
809 mtu < ntohs(old_iph->tot_len)) {
810 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
811 ip_rt_put(rt);
812 goto tx_error;
813 }
814 }
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000815#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 else if (skb->protocol == htons(ETH_P_IPV6)) {
Eric Dumazetadf30902009-06-02 05:19:30 +0000817 struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
Eric Dumazetadf30902009-06-02 05:19:30 +0000819 if (rt6 && mtu < dst_mtu(skb_dst(skb)) && mtu >= IPV6_MIN_MTU) {
Joe Perchesf97c1e02007-12-16 13:45:43 -0800820 if ((tunnel->parms.iph.daddr &&
821 !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 rt6->rt6i_dst.plen == 128) {
823 rt6->rt6i_flags |= RTF_MODIFIED;
David S. Millerdefb3512010-12-08 21:16:57 -0800824 dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
826 }
827
828 if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) {
Alexey Dobriyan3ffe5332010-02-18 08:25:24 +0000829 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 ip_rt_put(rt);
831 goto tx_error;
832 }
833 }
834#endif
835
836 if (tunnel->err_count > 0) {
Wei Yongjunda6185d82009-02-24 23:34:48 -0800837 if (time_before(jiffies,
838 tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 tunnel->err_count--;
840
841 dst_link_failure(skb);
842 } else
843 tunnel->err_count = 0;
844 }
845
Changli Gaod8d1f302010-06-10 23:31:35 -0700846 max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + rt->dst.header_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847
Patrick McHardycfbba492007-07-09 15:33:40 -0700848 if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
849 (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
Herbert Xu805dc1d2011-11-18 02:20:06 +0000851 if (max_headroom > dev->needed_headroom)
852 dev->needed_headroom = max_headroom;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 if (!new_skb) {
854 ip_rt_put(rt);
Eric Dumazete985aad2010-09-27 03:57:11 +0000855 dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000857 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 }
859 if (skb->sk)
860 skb_set_owner_w(new_skb, skb->sk);
861 dev_kfree_skb(skb);
862 skb = new_skb;
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700863 old_iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 }
865
Herbert Xu64194c32008-10-09 12:03:17 -0700866 skb_reset_transport_header(skb);
Arnaldo Carvalho de Meloe2d1bca2007-04-10 20:46:21 -0700867 skb_push(skb, gre_hlen);
868 skb_reset_network_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
Patrick McHardy48d5cad2006-02-15 15:10:22 -0800870 IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
871 IPSKB_REROUTED);
Eric Dumazetadf30902009-06-02 05:19:30 +0000872 skb_dst_drop(skb);
Changli Gaod8d1f302010-06-10 23:31:35 -0700873 skb_dst_set(skb, &rt->dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
875 /*
876 * Push down and install the IPIP header.
877 */
878
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700879 iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 iph->version = 4;
881 iph->ihl = sizeof(struct iphdr) >> 2;
882 iph->frag_off = df;
883 iph->protocol = IPPROTO_GRE;
884 iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb);
David S. Millercbb1e852011-05-04 12:33:34 -0700885 iph->daddr = fl4.daddr;
886 iph->saddr = fl4.saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
888 if ((iph->ttl = tiph->ttl) == 0) {
889 if (skb->protocol == htons(ETH_P_IP))
890 iph->ttl = old_iph->ttl;
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000891#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 else if (skb->protocol == htons(ETH_P_IPV6))
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000893 iph->ttl = ((const struct ipv6hdr *)old_iph)->hop_limit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894#endif
895 else
David S. Miller323e1262010-12-12 21:55:08 -0800896 iph->ttl = ip4_dst_hoplimit(&rt->dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 }
898
Herbert Xue1a80002008-10-09 12:00:17 -0700899 ((__be16 *)(iph + 1))[0] = tunnel->parms.o_flags;
900 ((__be16 *)(iph + 1))[1] = (dev->type == ARPHRD_ETHER) ?
901 htons(ETH_P_TEB) : skb->protocol;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
903 if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) {
Al Virod5a0a1e2006-11-08 00:23:14 -0800904 __be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
906 if (tunnel->parms.o_flags&GRE_SEQ) {
907 ++tunnel->o_seqno;
908 *ptr = htonl(tunnel->o_seqno);
909 ptr--;
910 }
911 if (tunnel->parms.o_flags&GRE_KEY) {
912 *ptr = tunnel->parms.o_key;
913 ptr--;
914 }
915 if (tunnel->parms.o_flags&GRE_CSUM) {
916 *ptr = 0;
Al Viro5f92a732006-11-14 21:36:54 -0800917 *(__sum16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919 }
920
921 nf_reset(skb);
Eric Dumazete985aad2010-09-27 03:57:11 +0000922 tstats = this_cpu_ptr(dev->tstats);
923 __IPTUNNEL_XMIT(tstats, &dev->stats);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000924 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
David S. Miller496053f2012-01-11 16:46:32 -0800926#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927tx_error_icmp:
928 dst_link_failure(skb);
David S. Miller496053f2012-01-11 16:46:32 -0800929#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930tx_error:
Eric Dumazete985aad2010-09-27 03:57:11 +0000931 dev->stats.tx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000933 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934}
935
Herbert Xu42aa9162008-10-09 11:59:32 -0700936static int ipgre_tunnel_bind_dev(struct net_device *dev)
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800937{
938 struct net_device *tdev = NULL;
939 struct ip_tunnel *tunnel;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000940 const struct iphdr *iph;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800941 int hlen = LL_MAX_HEADER;
942 int mtu = ETH_DATA_LEN;
943 int addend = sizeof(struct iphdr) + 4;
944
945 tunnel = netdev_priv(dev);
946 iph = &tunnel->parms.iph;
947
Herbert Xuc95b8192008-10-09 11:58:54 -0700948 /* Guess output device to choose reasonable mtu and needed_headroom */
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800949
950 if (iph->daddr) {
David S. Millercbb1e852011-05-04 12:33:34 -0700951 struct flowi4 fl4;
952 struct rtable *rt;
Eric Dumazete985aad2010-09-27 03:57:11 +0000953
David S. Millercbb1e852011-05-04 12:33:34 -0700954 rt = ip_route_output_gre(dev_net(dev), &fl4,
955 iph->daddr, iph->saddr,
956 tunnel->parms.o_key,
957 RT_TOS(iph->tos),
958 tunnel->parms.link);
David S. Millerb23dd4f2011-03-02 14:31:35 -0800959 if (!IS_ERR(rt)) {
Changli Gaod8d1f302010-06-10 23:31:35 -0700960 tdev = rt->dst.dev;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800961 ip_rt_put(rt);
962 }
Herbert Xue1a80002008-10-09 12:00:17 -0700963
964 if (dev->type != ARPHRD_ETHER)
965 dev->flags |= IFF_POINTOPOINT;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800966 }
967
968 if (!tdev && tunnel->parms.link)
Pavel Emelyanov96635522008-04-16 01:10:44 -0700969 tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800970
971 if (tdev) {
Herbert Xuc95b8192008-10-09 11:58:54 -0700972 hlen = tdev->hard_header_len + tdev->needed_headroom;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800973 mtu = tdev->mtu;
974 }
975 dev->iflink = tunnel->parms.link;
976
977 /* Precalculate GRE options length */
978 if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
979 if (tunnel->parms.o_flags&GRE_CSUM)
980 addend += 4;
981 if (tunnel->parms.o_flags&GRE_KEY)
982 addend += 4;
983 if (tunnel->parms.o_flags&GRE_SEQ)
984 addend += 4;
985 }
Herbert Xuc95b8192008-10-09 11:58:54 -0700986 dev->needed_headroom = addend + hlen;
Tom Goff8cdb0452009-08-14 16:33:56 -0700987 mtu -= dev->hard_header_len + addend;
Herbert Xu42aa9162008-10-09 11:59:32 -0700988
989 if (mtu < 68)
990 mtu = 68;
991
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800992 tunnel->hlen = addend;
993
Herbert Xu42aa9162008-10-09 11:59:32 -0700994 return mtu;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800995}
996
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997static int
998ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
999{
1000 int err = 0;
1001 struct ip_tunnel_parm p;
1002 struct ip_tunnel *t;
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001003 struct net *net = dev_net(dev);
1004 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
1006 switch (cmd) {
1007 case SIOCGETTUNNEL:
1008 t = NULL;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001009 if (dev == ign->fb_tunnel_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
1011 err = -EFAULT;
1012 break;
1013 }
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001014 t = ipgre_tunnel_locate(net, &p, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 }
1016 if (t == NULL)
Patrick McHardy2941a482006-01-08 22:05:26 -08001017 t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 memcpy(&p, &t->parms, sizeof(p));
1019 if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
1020 err = -EFAULT;
1021 break;
1022
1023 case SIOCADDTUNNEL:
1024 case SIOCCHGTUNNEL:
1025 err = -EPERM;
1026 if (!capable(CAP_NET_ADMIN))
1027 goto done;
1028
1029 err = -EFAULT;
1030 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
1031 goto done;
1032
1033 err = -EINVAL;
1034 if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
1035 p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
1036 ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
1037 goto done;
1038 if (p.iph.ttl)
1039 p.iph.frag_off |= htons(IP_DF);
1040
1041 if (!(p.i_flags&GRE_KEY))
1042 p.i_key = 0;
1043 if (!(p.o_flags&GRE_KEY))
1044 p.o_key = 0;
1045
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001046 t = ipgre_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001048 if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 if (t != NULL) {
1050 if (t->dev != dev) {
1051 err = -EEXIST;
1052 break;
1053 }
1054 } else {
Eric Dumazet15078502010-09-15 11:07:53 +00001055 unsigned int nflags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
Patrick McHardy2941a482006-01-08 22:05:26 -08001057 t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
Joe Perchesf97c1e02007-12-16 13:45:43 -08001059 if (ipv4_is_multicast(p.iph.daddr))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 nflags = IFF_BROADCAST;
1061 else if (p.iph.daddr)
1062 nflags = IFF_POINTOPOINT;
1063
1064 if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
1065 err = -EINVAL;
1066 break;
1067 }
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001068 ipgre_tunnel_unlink(ign, t);
Pavel Emelyanov74b0b852010-10-27 05:43:53 +00001069 synchronize_net();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 t->parms.iph.saddr = p.iph.saddr;
1071 t->parms.iph.daddr = p.iph.daddr;
1072 t->parms.i_key = p.i_key;
1073 t->parms.o_key = p.o_key;
1074 memcpy(dev->dev_addr, &p.iph.saddr, 4);
1075 memcpy(dev->broadcast, &p.iph.daddr, 4);
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001076 ipgre_tunnel_link(ign, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 netdev_state_change(dev);
1078 }
1079 }
1080
1081 if (t) {
1082 err = 0;
1083 if (cmd == SIOCCHGTUNNEL) {
1084 t->parms.iph.ttl = p.iph.ttl;
1085 t->parms.iph.tos = p.iph.tos;
1086 t->parms.iph.frag_off = p.iph.frag_off;
Michal Schmidtee34c1e2007-12-13 09:46:32 -08001087 if (t->parms.link != p.link) {
1088 t->parms.link = p.link;
Herbert Xu42aa9162008-10-09 11:59:32 -07001089 dev->mtu = ipgre_tunnel_bind_dev(dev);
Michal Schmidtee34c1e2007-12-13 09:46:32 -08001090 netdev_state_change(dev);
1091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 }
1093 if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
1094 err = -EFAULT;
1095 } else
1096 err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
1097 break;
1098
1099 case SIOCDELTUNNEL:
1100 err = -EPERM;
1101 if (!capable(CAP_NET_ADMIN))
1102 goto done;
1103
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001104 if (dev == ign->fb_tunnel_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 err = -EFAULT;
1106 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
1107 goto done;
1108 err = -ENOENT;
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001109 if ((t = ipgre_tunnel_locate(net, &p, 0)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 goto done;
1111 err = -EPERM;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001112 if (t == netdev_priv(ign->fb_tunnel_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 goto done;
1114 dev = t->dev;
1115 }
Stephen Hemminger22f8cde2007-02-07 00:09:58 -08001116 unregister_netdevice(dev);
1117 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 break;
1119
1120 default:
1121 err = -EINVAL;
1122 }
1123
1124done:
1125 return err;
1126}
1127
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
1129{
Patrick McHardy2941a482006-01-08 22:05:26 -08001130 struct ip_tunnel *tunnel = netdev_priv(dev);
Herbert Xuc95b8192008-10-09 11:58:54 -07001131 if (new_mtu < 68 ||
1132 new_mtu > 0xFFF8 - dev->hard_header_len - tunnel->hlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 return -EINVAL;
1134 dev->mtu = new_mtu;
1135 return 0;
1136}
1137
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138/* Nice toy. Unfortunately, useless in real life :-)
1139 It allows to construct virtual multiprotocol broadcast "LAN"
1140 over the Internet, provided multicast routing is tuned.
1141
1142
1143 I have no idea was this bicycle invented before me,
1144 so that I had to set ARPHRD_IPGRE to a random value.
1145 I have an impression, that Cisco could make something similar,
1146 but this feature is apparently missing in IOS<=11.2(8).
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
1149 with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
1150
1151 ping -t 255 224.66.66.66
1152
1153 If nobody answers, mbone does not work.
1154
1155 ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
1156 ip addr add 10.66.66.<somewhat>/24 dev Universe
1157 ifconfig Universe up
1158 ifconfig Universe add fe80::<Your_real_addr>/10
1159 ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
1160 ftp 10.66.66.66
1161 ...
1162 ftp fec0:6666:6666::193.233.7.65
1163 ...
1164
1165 */
1166
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001167static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
1168 unsigned short type,
Eric Dumazet15078502010-09-15 11:07:53 +00001169 const void *daddr, const void *saddr, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170{
Patrick McHardy2941a482006-01-08 22:05:26 -08001171 struct ip_tunnel *t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen);
Al Virod5a0a1e2006-11-08 00:23:14 -08001173 __be16 *p = (__be16*)(iph+1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
1175 memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
1176 p[0] = t->parms.o_flags;
1177 p[1] = htons(type);
1178
1179 /*
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001180 * Set the source hardware address.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 */
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001182
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 if (saddr)
1184 memcpy(&iph->saddr, saddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +00001185 if (daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 memcpy(&iph->daddr, daddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +00001187 if (iph->daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 return t->hlen;
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001189
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 return -t->hlen;
1191}
1192
Timo Teras6a5f44d2007-10-23 20:31:53 -07001193static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
1194{
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001195 const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
Timo Teras6a5f44d2007-10-23 20:31:53 -07001196 memcpy(haddr, &iph->saddr, 4);
1197 return 4;
1198}
1199
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001200static const struct header_ops ipgre_header_ops = {
1201 .create = ipgre_header,
Timo Teras6a5f44d2007-10-23 20:31:53 -07001202 .parse = ipgre_header_parse,
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001203};
1204
Timo Teras6a5f44d2007-10-23 20:31:53 -07001205#ifdef CONFIG_NET_IPGRE_BROADCAST
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206static int ipgre_open(struct net_device *dev)
1207{
Patrick McHardy2941a482006-01-08 22:05:26 -08001208 struct ip_tunnel *t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
Joe Perchesf97c1e02007-12-16 13:45:43 -08001210 if (ipv4_is_multicast(t->parms.iph.daddr)) {
David S. Millercbb1e852011-05-04 12:33:34 -07001211 struct flowi4 fl4;
1212 struct rtable *rt;
Eric Dumazete985aad2010-09-27 03:57:11 +00001213
David S. Millercbb1e852011-05-04 12:33:34 -07001214 rt = ip_route_output_gre(dev_net(dev), &fl4,
1215 t->parms.iph.daddr,
1216 t->parms.iph.saddr,
1217 t->parms.o_key,
1218 RT_TOS(t->parms.iph.tos),
1219 t->parms.link);
David S. Millerb23dd4f2011-03-02 14:31:35 -08001220 if (IS_ERR(rt))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 return -EADDRNOTAVAIL;
Changli Gaod8d1f302010-06-10 23:31:35 -07001222 dev = rt->dst.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 ip_rt_put(rt);
Herbert Xue5ed6392005-10-03 14:35:55 -07001224 if (__in_dev_get_rtnl(dev) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 return -EADDRNOTAVAIL;
1226 t->mlink = dev->ifindex;
Herbert Xue5ed6392005-10-03 14:35:55 -07001227 ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 }
1229 return 0;
1230}
1231
1232static int ipgre_close(struct net_device *dev)
1233{
Patrick McHardy2941a482006-01-08 22:05:26 -08001234 struct ip_tunnel *t = netdev_priv(dev);
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001235
Joe Perchesf97c1e02007-12-16 13:45:43 -08001236 if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
Denis V. Lunev7fee0ca2008-01-21 17:32:38 -08001237 struct in_device *in_dev;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09001238 in_dev = inetdev_by_index(dev_net(dev), t->mlink);
Eric Dumazet8723e1b2010-10-19 00:39:26 +00001239 if (in_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 ip_mc_dec_group(in_dev, t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 }
1242 return 0;
1243}
1244
1245#endif
1246
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001247static const struct net_device_ops ipgre_netdev_ops = {
1248 .ndo_init = ipgre_tunnel_init,
1249 .ndo_uninit = ipgre_tunnel_uninit,
1250#ifdef CONFIG_NET_IPGRE_BROADCAST
1251 .ndo_open = ipgre_open,
1252 .ndo_stop = ipgre_close,
1253#endif
1254 .ndo_start_xmit = ipgre_tunnel_xmit,
1255 .ndo_do_ioctl = ipgre_tunnel_ioctl,
1256 .ndo_change_mtu = ipgre_tunnel_change_mtu,
Eric Dumazete985aad2010-09-27 03:57:11 +00001257 .ndo_get_stats = ipgre_get_stats,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001258};
1259
Eric Dumazete985aad2010-09-27 03:57:11 +00001260static void ipgre_dev_free(struct net_device *dev)
1261{
1262 free_percpu(dev->tstats);
1263 free_netdev(dev);
1264}
1265
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266static void ipgre_tunnel_setup(struct net_device *dev)
1267{
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001268 dev->netdev_ops = &ipgre_netdev_ops;
Eric Dumazete985aad2010-09-27 03:57:11 +00001269 dev->destructor = ipgre_dev_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
1271 dev->type = ARPHRD_IPGRE;
Herbert Xuc95b8192008-10-09 11:58:54 -07001272 dev->needed_headroom = LL_MAX_HEADER + sizeof(struct iphdr) + 4;
Kris Katterjohn46f25df2006-01-05 16:35:42 -08001273 dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 dev->flags = IFF_NOARP;
1275 dev->iflink = 0;
1276 dev->addr_len = 4;
Pavel Emelyanov0b67ece2008-04-16 01:11:13 -07001277 dev->features |= NETIF_F_NETNS_LOCAL;
Eric Dumazet108bfa82009-05-28 22:35:10 +00001278 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279}
1280
1281static int ipgre_tunnel_init(struct net_device *dev)
1282{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 struct ip_tunnel *tunnel;
1284 struct iphdr *iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285
Patrick McHardy2941a482006-01-08 22:05:26 -08001286 tunnel = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 iph = &tunnel->parms.iph;
1288
1289 tunnel->dev = dev;
1290 strcpy(tunnel->parms.name, dev->name);
1291
1292 memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
1293 memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
1294
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 if (iph->daddr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296#ifdef CONFIG_NET_IPGRE_BROADCAST
Joe Perchesf97c1e02007-12-16 13:45:43 -08001297 if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 if (!iph->saddr)
1299 return -EINVAL;
1300 dev->flags = IFF_BROADCAST;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001301 dev->header_ops = &ipgre_header_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 }
1303#endif
Michal Schmidtee34c1e2007-12-13 09:46:32 -08001304 } else
Timo Teras6a5f44d2007-10-23 20:31:53 -07001305 dev->header_ops = &ipgre_header_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Eric Dumazete985aad2010-09-27 03:57:11 +00001307 dev->tstats = alloc_percpu(struct pcpu_tstats);
1308 if (!dev->tstats)
1309 return -ENOMEM;
1310
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 return 0;
1312}
1313
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001314static void ipgre_fb_tunnel_init(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315{
Patrick McHardy2941a482006-01-08 22:05:26 -08001316 struct ip_tunnel *tunnel = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 struct iphdr *iph = &tunnel->parms.iph;
1318
1319 tunnel->dev = dev;
1320 strcpy(tunnel->parms.name, dev->name);
1321
1322 iph->version = 4;
1323 iph->protocol = IPPROTO_GRE;
1324 iph->ihl = 5;
1325 tunnel->hlen = sizeof(struct iphdr) + 4;
1326
1327 dev_hold(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328}
1329
1330
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001331static const struct gre_protocol ipgre_protocol = {
1332 .handler = ipgre_rcv,
1333 .err_handler = ipgre_err,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334};
1335
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001336static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -07001337{
1338 int prio;
1339
1340 for (prio = 0; prio < 4; prio++) {
1341 int h;
1342 for (h = 0; h < HASH_SIZE; h++) {
Eric Dumazet15078502010-09-15 11:07:53 +00001343 struct ip_tunnel *t;
1344
1345 t = rtnl_dereference(ign->tunnels[prio][h]);
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001346
1347 while (t != NULL) {
1348 unregister_netdevice_queue(t->dev, head);
Eric Dumazet15078502010-09-15 11:07:53 +00001349 t = rtnl_dereference(t->next);
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001350 }
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -07001351 }
1352 }
1353}
1354
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001355static int __net_init ipgre_init_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001356{
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001357 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001358 int err;
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001359
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001360 ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0",
1361 ipgre_tunnel_setup);
1362 if (!ign->fb_tunnel_dev) {
1363 err = -ENOMEM;
1364 goto err_alloc_dev;
1365 }
Alexey Dobriyanbe77e592008-11-23 17:26:26 -08001366 dev_net_set(ign->fb_tunnel_dev, net);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001367
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001368 ipgre_fb_tunnel_init(ign->fb_tunnel_dev);
Herbert Xuc19e6542008-10-09 11:59:55 -07001369 ign->fb_tunnel_dev->rtnl_link_ops = &ipgre_link_ops;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001370
1371 if ((err = register_netdev(ign->fb_tunnel_dev)))
1372 goto err_reg_dev;
1373
Eric Dumazet3285ee32010-10-30 16:21:28 -07001374 rcu_assign_pointer(ign->tunnels_wc[0],
1375 netdev_priv(ign->fb_tunnel_dev));
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001376 return 0;
1377
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001378err_reg_dev:
Eric Dumazet3285ee32010-10-30 16:21:28 -07001379 ipgre_dev_free(ign->fb_tunnel_dev);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001380err_alloc_dev:
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001381 return err;
1382}
1383
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001384static void __net_exit ipgre_exit_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001385{
1386 struct ipgre_net *ign;
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001387 LIST_HEAD(list);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001388
1389 ign = net_generic(net, ipgre_net_id);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001390 rtnl_lock();
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001391 ipgre_destroy_tunnels(ign, &list);
1392 unregister_netdevice_many(&list);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001393 rtnl_unlock();
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001394}
1395
1396static struct pernet_operations ipgre_net_ops = {
1397 .init = ipgre_init_net,
1398 .exit = ipgre_exit_net,
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001399 .id = &ipgre_net_id,
1400 .size = sizeof(struct ipgre_net),
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001401};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Herbert Xuc19e6542008-10-09 11:59:55 -07001403static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
1404{
1405 __be16 flags;
1406
1407 if (!data)
1408 return 0;
1409
1410 flags = 0;
1411 if (data[IFLA_GRE_IFLAGS])
1412 flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1413 if (data[IFLA_GRE_OFLAGS])
1414 flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1415 if (flags & (GRE_VERSION|GRE_ROUTING))
1416 return -EINVAL;
1417
1418 return 0;
1419}
1420
Herbert Xue1a80002008-10-09 12:00:17 -07001421static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
1422{
1423 __be32 daddr;
1424
1425 if (tb[IFLA_ADDRESS]) {
1426 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1427 return -EINVAL;
1428 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1429 return -EADDRNOTAVAIL;
1430 }
1431
1432 if (!data)
1433 goto out;
1434
1435 if (data[IFLA_GRE_REMOTE]) {
1436 memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1437 if (!daddr)
1438 return -EINVAL;
1439 }
1440
1441out:
1442 return ipgre_tunnel_validate(tb, data);
1443}
1444
Herbert Xuc19e6542008-10-09 11:59:55 -07001445static void ipgre_netlink_parms(struct nlattr *data[],
1446 struct ip_tunnel_parm *parms)
1447{
Herbert Xu7bb82d92008-10-11 12:20:15 -07001448 memset(parms, 0, sizeof(*parms));
Herbert Xuc19e6542008-10-09 11:59:55 -07001449
1450 parms->iph.protocol = IPPROTO_GRE;
1451
1452 if (!data)
1453 return;
1454
1455 if (data[IFLA_GRE_LINK])
1456 parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1457
1458 if (data[IFLA_GRE_IFLAGS])
1459 parms->i_flags = nla_get_be16(data[IFLA_GRE_IFLAGS]);
1460
1461 if (data[IFLA_GRE_OFLAGS])
1462 parms->o_flags = nla_get_be16(data[IFLA_GRE_OFLAGS]);
1463
1464 if (data[IFLA_GRE_IKEY])
1465 parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1466
1467 if (data[IFLA_GRE_OKEY])
1468 parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1469
1470 if (data[IFLA_GRE_LOCAL])
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001471 parms->iph.saddr = nla_get_be32(data[IFLA_GRE_LOCAL]);
Herbert Xuc19e6542008-10-09 11:59:55 -07001472
1473 if (data[IFLA_GRE_REMOTE])
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001474 parms->iph.daddr = nla_get_be32(data[IFLA_GRE_REMOTE]);
Herbert Xuc19e6542008-10-09 11:59:55 -07001475
1476 if (data[IFLA_GRE_TTL])
1477 parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1478
1479 if (data[IFLA_GRE_TOS])
1480 parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1481
1482 if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC]))
1483 parms->iph.frag_off = htons(IP_DF);
1484}
1485
Herbert Xue1a80002008-10-09 12:00:17 -07001486static int ipgre_tap_init(struct net_device *dev)
1487{
1488 struct ip_tunnel *tunnel;
1489
1490 tunnel = netdev_priv(dev);
1491
1492 tunnel->dev = dev;
1493 strcpy(tunnel->parms.name, dev->name);
1494
1495 ipgre_tunnel_bind_dev(dev);
1496
Eric Dumazete985aad2010-09-27 03:57:11 +00001497 dev->tstats = alloc_percpu(struct pcpu_tstats);
1498 if (!dev->tstats)
1499 return -ENOMEM;
1500
Herbert Xue1a80002008-10-09 12:00:17 -07001501 return 0;
1502}
1503
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001504static const struct net_device_ops ipgre_tap_netdev_ops = {
1505 .ndo_init = ipgre_tap_init,
1506 .ndo_uninit = ipgre_tunnel_uninit,
1507 .ndo_start_xmit = ipgre_tunnel_xmit,
1508 .ndo_set_mac_address = eth_mac_addr,
1509 .ndo_validate_addr = eth_validate_addr,
1510 .ndo_change_mtu = ipgre_tunnel_change_mtu,
Eric Dumazete985aad2010-09-27 03:57:11 +00001511 .ndo_get_stats = ipgre_get_stats,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001512};
1513
Herbert Xue1a80002008-10-09 12:00:17 -07001514static void ipgre_tap_setup(struct net_device *dev)
1515{
1516
1517 ether_setup(dev);
1518
Herbert Xu2e9526b2009-10-30 05:51:48 +00001519 dev->netdev_ops = &ipgre_tap_netdev_ops;
Eric Dumazete985aad2010-09-27 03:57:11 +00001520 dev->destructor = ipgre_dev_free;
Herbert Xue1a80002008-10-09 12:00:17 -07001521
1522 dev->iflink = 0;
1523 dev->features |= NETIF_F_NETNS_LOCAL;
1524}
1525
Eric W. Biederman81adee42009-11-08 00:53:51 -08001526static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[],
Herbert Xuc19e6542008-10-09 11:59:55 -07001527 struct nlattr *data[])
1528{
1529 struct ip_tunnel *nt;
1530 struct net *net = dev_net(dev);
1531 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
1532 int mtu;
1533 int err;
1534
1535 nt = netdev_priv(dev);
1536 ipgre_netlink_parms(data, &nt->parms);
1537
Herbert Xue1a80002008-10-09 12:00:17 -07001538 if (ipgre_tunnel_find(net, &nt->parms, dev->type))
Herbert Xuc19e6542008-10-09 11:59:55 -07001539 return -EEXIST;
1540
Herbert Xue1a80002008-10-09 12:00:17 -07001541 if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
Danny Kukawkaf2cedb62012-02-15 06:45:39 +00001542 eth_hw_addr_random(dev);
Herbert Xue1a80002008-10-09 12:00:17 -07001543
Herbert Xuc19e6542008-10-09 11:59:55 -07001544 mtu = ipgre_tunnel_bind_dev(dev);
1545 if (!tb[IFLA_MTU])
1546 dev->mtu = mtu;
1547
Eric Dumazetb790e012010-09-27 23:05:47 +00001548 /* Can use a lockless transmit, unless we generate output sequences */
1549 if (!(nt->parms.o_flags & GRE_SEQ))
1550 dev->features |= NETIF_F_LLTX;
1551
Herbert Xuc19e6542008-10-09 11:59:55 -07001552 err = register_netdevice(dev);
1553 if (err)
1554 goto out;
1555
1556 dev_hold(dev);
1557 ipgre_tunnel_link(ign, nt);
1558
1559out:
1560 return err;
1561}
1562
1563static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1564 struct nlattr *data[])
1565{
1566 struct ip_tunnel *t, *nt;
1567 struct net *net = dev_net(dev);
1568 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
1569 struct ip_tunnel_parm p;
1570 int mtu;
1571
1572 if (dev == ign->fb_tunnel_dev)
1573 return -EINVAL;
1574
1575 nt = netdev_priv(dev);
1576 ipgre_netlink_parms(data, &p);
1577
1578 t = ipgre_tunnel_locate(net, &p, 0);
1579
1580 if (t) {
1581 if (t->dev != dev)
1582 return -EEXIST;
1583 } else {
Herbert Xuc19e6542008-10-09 11:59:55 -07001584 t = nt;
1585
Herbert Xu2e9526b2009-10-30 05:51:48 +00001586 if (dev->type != ARPHRD_ETHER) {
Eric Dumazet15078502010-09-15 11:07:53 +00001587 unsigned int nflags = 0;
Herbert Xuc19e6542008-10-09 11:59:55 -07001588
Herbert Xu2e9526b2009-10-30 05:51:48 +00001589 if (ipv4_is_multicast(p.iph.daddr))
1590 nflags = IFF_BROADCAST;
1591 else if (p.iph.daddr)
1592 nflags = IFF_POINTOPOINT;
1593
1594 if ((dev->flags ^ nflags) &
1595 (IFF_POINTOPOINT | IFF_BROADCAST))
1596 return -EINVAL;
1597 }
Herbert Xuc19e6542008-10-09 11:59:55 -07001598
1599 ipgre_tunnel_unlink(ign, t);
1600 t->parms.iph.saddr = p.iph.saddr;
1601 t->parms.iph.daddr = p.iph.daddr;
1602 t->parms.i_key = p.i_key;
Herbert Xu2e9526b2009-10-30 05:51:48 +00001603 if (dev->type != ARPHRD_ETHER) {
1604 memcpy(dev->dev_addr, &p.iph.saddr, 4);
1605 memcpy(dev->broadcast, &p.iph.daddr, 4);
1606 }
Herbert Xuc19e6542008-10-09 11:59:55 -07001607 ipgre_tunnel_link(ign, t);
1608 netdev_state_change(dev);
1609 }
1610
1611 t->parms.o_key = p.o_key;
1612 t->parms.iph.ttl = p.iph.ttl;
1613 t->parms.iph.tos = p.iph.tos;
1614 t->parms.iph.frag_off = p.iph.frag_off;
1615
1616 if (t->parms.link != p.link) {
1617 t->parms.link = p.link;
1618 mtu = ipgre_tunnel_bind_dev(dev);
1619 if (!tb[IFLA_MTU])
1620 dev->mtu = mtu;
1621 netdev_state_change(dev);
1622 }
1623
1624 return 0;
1625}
1626
1627static size_t ipgre_get_size(const struct net_device *dev)
1628{
1629 return
1630 /* IFLA_GRE_LINK */
1631 nla_total_size(4) +
1632 /* IFLA_GRE_IFLAGS */
1633 nla_total_size(2) +
1634 /* IFLA_GRE_OFLAGS */
1635 nla_total_size(2) +
1636 /* IFLA_GRE_IKEY */
1637 nla_total_size(4) +
1638 /* IFLA_GRE_OKEY */
1639 nla_total_size(4) +
1640 /* IFLA_GRE_LOCAL */
1641 nla_total_size(4) +
1642 /* IFLA_GRE_REMOTE */
1643 nla_total_size(4) +
1644 /* IFLA_GRE_TTL */
1645 nla_total_size(1) +
1646 /* IFLA_GRE_TOS */
1647 nla_total_size(1) +
1648 /* IFLA_GRE_PMTUDISC */
1649 nla_total_size(1) +
1650 0;
1651}
1652
1653static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1654{
1655 struct ip_tunnel *t = netdev_priv(dev);
1656 struct ip_tunnel_parm *p = &t->parms;
1657
1658 NLA_PUT_U32(skb, IFLA_GRE_LINK, p->link);
1659 NLA_PUT_BE16(skb, IFLA_GRE_IFLAGS, p->i_flags);
1660 NLA_PUT_BE16(skb, IFLA_GRE_OFLAGS, p->o_flags);
Patrick McHardyba9e64b2008-10-10 12:10:30 -07001661 NLA_PUT_BE32(skb, IFLA_GRE_IKEY, p->i_key);
1662 NLA_PUT_BE32(skb, IFLA_GRE_OKEY, p->o_key);
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001663 NLA_PUT_BE32(skb, IFLA_GRE_LOCAL, p->iph.saddr);
1664 NLA_PUT_BE32(skb, IFLA_GRE_REMOTE, p->iph.daddr);
Herbert Xuc19e6542008-10-09 11:59:55 -07001665 NLA_PUT_U8(skb, IFLA_GRE_TTL, p->iph.ttl);
1666 NLA_PUT_U8(skb, IFLA_GRE_TOS, p->iph.tos);
1667 NLA_PUT_U8(skb, IFLA_GRE_PMTUDISC, !!(p->iph.frag_off & htons(IP_DF)));
1668
1669 return 0;
1670
1671nla_put_failure:
1672 return -EMSGSIZE;
1673}
1674
1675static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1676 [IFLA_GRE_LINK] = { .type = NLA_U32 },
1677 [IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
1678 [IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
1679 [IFLA_GRE_IKEY] = { .type = NLA_U32 },
1680 [IFLA_GRE_OKEY] = { .type = NLA_U32 },
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001681 [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
1682 [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
Herbert Xuc19e6542008-10-09 11:59:55 -07001683 [IFLA_GRE_TTL] = { .type = NLA_U8 },
1684 [IFLA_GRE_TOS] = { .type = NLA_U8 },
1685 [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 },
1686};
1687
1688static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1689 .kind = "gre",
1690 .maxtype = IFLA_GRE_MAX,
1691 .policy = ipgre_policy,
1692 .priv_size = sizeof(struct ip_tunnel),
1693 .setup = ipgre_tunnel_setup,
1694 .validate = ipgre_tunnel_validate,
1695 .newlink = ipgre_newlink,
1696 .changelink = ipgre_changelink,
1697 .get_size = ipgre_get_size,
1698 .fill_info = ipgre_fill_info,
1699};
1700
Herbert Xue1a80002008-10-09 12:00:17 -07001701static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1702 .kind = "gretap",
1703 .maxtype = IFLA_GRE_MAX,
1704 .policy = ipgre_policy,
1705 .priv_size = sizeof(struct ip_tunnel),
1706 .setup = ipgre_tap_setup,
1707 .validate = ipgre_tap_validate,
1708 .newlink = ipgre_newlink,
1709 .changelink = ipgre_changelink,
1710 .get_size = ipgre_get_size,
1711 .fill_info = ipgre_fill_info,
1712};
1713
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714/*
1715 * And now the modules code and kernel interface.
1716 */
1717
1718static int __init ipgre_init(void)
1719{
1720 int err;
1721
Joe Perches058bd4d2012-03-11 18:36:11 +00001722 pr_info("GRE over IPv4 tunneling driver\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001724 err = register_pernet_device(&ipgre_net_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001725 if (err < 0)
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001726 return err;
1727
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001728 err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001729 if (err < 0) {
Joe Perches058bd4d2012-03-11 18:36:11 +00001730 pr_info("%s: can't add protocol\n", __func__);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001731 goto add_proto_failed;
1732 }
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001733
Herbert Xuc19e6542008-10-09 11:59:55 -07001734 err = rtnl_link_register(&ipgre_link_ops);
1735 if (err < 0)
1736 goto rtnl_link_failed;
1737
Herbert Xue1a80002008-10-09 12:00:17 -07001738 err = rtnl_link_register(&ipgre_tap_ops);
1739 if (err < 0)
1740 goto tap_ops_failed;
1741
Herbert Xuc19e6542008-10-09 11:59:55 -07001742out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 return err;
Herbert Xuc19e6542008-10-09 11:59:55 -07001744
Herbert Xue1a80002008-10-09 12:00:17 -07001745tap_ops_failed:
1746 rtnl_link_unregister(&ipgre_link_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001747rtnl_link_failed:
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001748 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001749add_proto_failed:
1750 unregister_pernet_device(&ipgre_net_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001751 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752}
1753
Alexey Kuznetsovdb445752005-07-30 17:46:44 -07001754static void __exit ipgre_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755{
Herbert Xue1a80002008-10-09 12:00:17 -07001756 rtnl_link_unregister(&ipgre_tap_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001757 rtnl_link_unregister(&ipgre_link_ops);
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001758 if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0)
Joe Perches058bd4d2012-03-11 18:36:11 +00001759 pr_info("%s: can't remove protocol\n", __func__);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001760 unregister_pernet_device(&ipgre_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761}
1762
1763module_init(ipgre_init);
1764module_exit(ipgre_fini);
1765MODULE_LICENSE("GPL");
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001766MODULE_ALIAS_RTNL_LINK("gre");
1767MODULE_ALIAS_RTNL_LINK("gretap");
Vasiliy Kulikov8909c9a2011-03-02 00:33:13 +03001768MODULE_ALIAS_NETDEV("gre0");