blob: 185e0a75ecec0ad1bd89932a6a636150fd4aef85 [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
Randy Dunlap4fc268d2006-01-11 12:17:47 -080013#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/module.h>
15#include <linux/types.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090017#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <asm/uaccess.h>
19#include <linux/skbuff.h>
20#include <linux/netdevice.h>
21#include <linux/in.h>
22#include <linux/tcp.h>
23#include <linux/udp.h>
24#include <linux/if_arp.h>
25#include <linux/mroute.h>
26#include <linux/init.h>
27#include <linux/in6.h>
28#include <linux/inetdevice.h>
29#include <linux/igmp.h>
30#include <linux/netfilter_ipv4.h>
Herbert Xue1a80002008-10-09 12:00:17 -070031#include <linux/etherdevice.h>
Kris Katterjohn46f25df2006-01-05 16:35:42 -080032#include <linux/if_ether.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34#include <net/sock.h>
35#include <net/ip.h>
36#include <net/icmp.h>
37#include <net/protocol.h>
38#include <net/ipip.h>
39#include <net/arp.h>
40#include <net/checksum.h>
41#include <net/dsfield.h>
42#include <net/inet_ecn.h>
43#include <net/xfrm.h>
Pavel Emelyanov59a4c752008-04-16 01:08:53 -070044#include <net/net_namespace.h>
45#include <net/netns/generic.h>
Herbert Xuc19e6542008-10-09 11:59:55 -070046#include <net/rtnetlink.h>
Dmitry Kozlov00959ad2010-08-21 23:05:39 -070047#include <net/gre.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
Eric Dumazetdfd56b82011-12-10 09:48:31 +000049#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <net/ipv6.h>
51#include <net/ip6_fib.h>
52#include <net/ip6_route.h>
53#endif
54
55/*
56 Problems & solutions
57 --------------------
58
59 1. The most important issue is detecting local dead loops.
60 They would cause complete host lockup in transmit, which
61 would be "resolved" by stack overflow or, if queueing is enabled,
62 with infinite looping in net_bh.
63
64 We cannot track such dead loops during route installation,
65 it is infeasible task. The most general solutions would be
66 to keep skb->encapsulation counter (sort of local ttl),
Eric Dumazet6d0722a2010-09-29 23:35:10 -070067 and silently drop packet when it expires. It is a good
stephen hemmingerbff52852012-02-24 08:08:20 +000068 solution, but it supposes maintaining new variable in ALL
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 skb, even if no tunneling is used.
70
Eric Dumazet6d0722a2010-09-29 23:35:10 -070071 Current solution: xmit_recursion breaks dead loops. This is a percpu
72 counter, since when we enter the first ndo_xmit(), cpu migration is
73 forbidden. We force an exit if this counter reaches RECURSION_LIMIT
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
75 2. Networking dead loops would not kill routers, but would really
76 kill network. IP hop limit plays role of "t->recursion" in this case,
77 if we copy it from packet being encapsulated to upper header.
78 It is very good solution, but it introduces two problems:
79
80 - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
81 do not work over tunnels.
82 - traceroute does not work. I planned to relay ICMP from tunnel,
83 so that this problem would be solved and traceroute output
84 would even more informative. This idea appeared to be wrong:
85 only Linux complies to rfc1812 now (yes, guys, Linux is the only
86 true router now :-)), all routers (at least, in neighbourhood of mine)
87 return only 8 bytes of payload. It is the end.
88
89 Hence, if we want that OSPF worked or traceroute said something reasonable,
90 we should search for another solution.
91
92 One of them is to parse packet trying to detect inner encapsulation
93 made by our node. It is difficult or even impossible, especially,
stephen hemmingerbff52852012-02-24 08:08:20 +000094 taking into account fragmentation. TO be short, ttl is not solution at all.
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
96 Current solution: The solution was UNEXPECTEDLY SIMPLE.
97 We force DF flag on tunnels with preconfigured hop limit,
98 that is ALL. :-) Well, it does not remove the problem completely,
99 but exponential growth of network traffic is changed to linear
100 (branches, that exceed pmtu are pruned) and tunnel mtu
stephen hemmingerbff52852012-02-24 08:08:20 +0000101 rapidly degrades to value <68, where looping stops.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 Yes, it is not good if there exists a router in the loop,
103 which does not force DF, even when encapsulating packets have DF set.
104 But it is not our problem! Nobody could accuse us, we made
105 all that we could make. Even if it is your gated who injected
106 fatal route to network, even if it were you who configured
107 fatal static route: you are innocent. :-)
108
109
110
111 3. Really, ipv4/ipip.c, ipv4/ip_gre.c and ipv6/sit.c contain
112 practically identical code. It would be good to glue them
113 together, but it is not very evident, how to make them modular.
114 sit is integral part of IPv6, ipip and gre are naturally modular.
115 We could extract common parts (hash table, ioctl etc)
116 to a separate module (ip_tunnel.c).
117
118 Alexey Kuznetsov.
119 */
120
Herbert Xuc19e6542008-10-09 11:59:55 -0700121static struct rtnl_link_ops ipgre_link_ops __read_mostly;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122static int ipgre_tunnel_init(struct net_device *dev);
123static void ipgre_tunnel_setup(struct net_device *dev);
Herbert Xu42aa9162008-10-09 11:59:32 -0700124static int ipgre_tunnel_bind_dev(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126/* Fallback tunnel: no source, no destination, no key, no options */
127
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700128#define HASH_SIZE 16
129
Eric Dumazetf99189b2009-11-17 10:42:49 +0000130static int ipgre_net_id __read_mostly;
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700131struct ipgre_net {
Eric Dumazet15078502010-09-15 11:07:53 +0000132 struct ip_tunnel __rcu *tunnels[4][HASH_SIZE];
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700133
Pavel Emelyanov7daa0002008-04-16 01:10:05 -0700134 struct net_device *fb_tunnel_dev;
Pavel Emelyanov59a4c752008-04-16 01:08:53 -0700135};
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137/* Tunnel hash table */
138
139/*
140 4 hash tables:
141
142 3: (remote,local)
143 2: (remote,*)
144 1: (*,local)
145 0: (*,*)
146
147 We require exact key match i.e. if a key is present in packet
148 it will match only tunnel with the same key; if it is not present,
149 it will match only keyless tunnel.
150
151 All keysless packets, if not matched configured keyless tunnels
152 will match fallback tunnel.
153 */
154
Al Virod5a0a1e2006-11-08 00:23:14 -0800155#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700157#define tunnels_r_l tunnels[3]
158#define tunnels_r tunnels[2]
159#define tunnels_l tunnels[1]
160#define tunnels_wc tunnels[0]
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000161/*
Eric Dumazet15078502010-09-15 11:07:53 +0000162 * Locking : hash tables are protected by RCU and RTNL
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000163 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000165#define for_each_ip_tunnel_rcu(start) \
166 for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
Eric Dumazete985aad2010-09-27 03:57:11 +0000168/* often modified stats are per cpu, other are shared (netdev->stats) */
169struct pcpu_tstats {
170 unsigned long rx_packets;
171 unsigned long rx_bytes;
172 unsigned long tx_packets;
173 unsigned long tx_bytes;
Eric Dumazet8ce120f2011-11-04 23:19:28 +0000174} __attribute__((aligned(4*sizeof(unsigned long))));
Eric Dumazete985aad2010-09-27 03:57:11 +0000175
176static struct net_device_stats *ipgre_get_stats(struct net_device *dev)
177{
178 struct pcpu_tstats sum = { 0 };
179 int i;
180
181 for_each_possible_cpu(i) {
182 const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
183
184 sum.rx_packets += tstats->rx_packets;
185 sum.rx_bytes += tstats->rx_bytes;
186 sum.tx_packets += tstats->tx_packets;
187 sum.tx_bytes += tstats->tx_bytes;
188 }
189 dev->stats.rx_packets = sum.rx_packets;
190 dev->stats.rx_bytes = sum.rx_bytes;
191 dev->stats.tx_packets = sum.tx_packets;
192 dev->stats.tx_bytes = sum.tx_bytes;
193 return &dev->stats;
194}
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196/* Given src, dst and key, find appropriate for input tunnel. */
197
Timo Teras749c10f2009-01-19 17:22:12 -0800198static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
Herbert Xue1a80002008-10-09 12:00:17 -0700199 __be32 remote, __be32 local,
200 __be32 key, __be16 gre_proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
Timo Teras749c10f2009-01-19 17:22:12 -0800202 struct net *net = dev_net(dev);
203 int link = dev->ifindex;
Eric Dumazet15078502010-09-15 11:07:53 +0000204 unsigned int h0 = HASH(remote);
205 unsigned int h1 = HASH(key);
Timo Terasafcf1242009-01-26 20:56:10 -0800206 struct ip_tunnel *t, *cand = NULL;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -0700207 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Herbert Xue1a80002008-10-09 12:00:17 -0700208 int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
209 ARPHRD_ETHER : ARPHRD_IPGRE;
Timo Terasafcf1242009-01-26 20:56:10 -0800210 int score, cand_score = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000212 for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) {
Timo Teras749c10f2009-01-19 17:22:12 -0800213 if (local != t->parms.iph.saddr ||
214 remote != t->parms.iph.daddr ||
215 key != t->parms.i_key ||
216 !(t->dev->flags & IFF_UP))
217 continue;
218
219 if (t->dev->type != ARPHRD_IPGRE &&
220 t->dev->type != dev_type)
221 continue;
222
Timo Terasafcf1242009-01-26 20:56:10 -0800223 score = 0;
Timo Teras749c10f2009-01-19 17:22:12 -0800224 if (t->parms.link != link)
Timo Terasafcf1242009-01-26 20:56:10 -0800225 score |= 1;
Timo Teras749c10f2009-01-19 17:22:12 -0800226 if (t->dev->type != dev_type)
Timo Terasafcf1242009-01-26 20:56:10 -0800227 score |= 2;
228 if (score == 0)
Timo Teras749c10f2009-01-19 17:22:12 -0800229 return t;
Timo Terasafcf1242009-01-26 20:56:10 -0800230
231 if (score < cand_score) {
232 cand = t;
233 cand_score = score;
234 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 }
Herbert Xue1a80002008-10-09 12:00:17 -0700236
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000237 for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) {
Timo Teras749c10f2009-01-19 17:22:12 -0800238 if (remote != t->parms.iph.daddr ||
239 key != t->parms.i_key ||
240 !(t->dev->flags & IFF_UP))
241 continue;
242
243 if (t->dev->type != ARPHRD_IPGRE &&
244 t->dev->type != dev_type)
245 continue;
246
Timo Terasafcf1242009-01-26 20:56:10 -0800247 score = 0;
Timo Teras749c10f2009-01-19 17:22:12 -0800248 if (t->parms.link != link)
Timo Terasafcf1242009-01-26 20:56:10 -0800249 score |= 1;
Timo Teras749c10f2009-01-19 17:22:12 -0800250 if (t->dev->type != dev_type)
Timo Terasafcf1242009-01-26 20:56:10 -0800251 score |= 2;
252 if (score == 0)
Timo Teras749c10f2009-01-19 17:22:12 -0800253 return t;
Timo Terasafcf1242009-01-26 20:56:10 -0800254
255 if (score < cand_score) {
256 cand = t;
257 cand_score = score;
258 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 }
Herbert Xue1a80002008-10-09 12:00:17 -0700260
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000261 for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) {
Timo Teras749c10f2009-01-19 17:22:12 -0800262 if ((local != t->parms.iph.saddr &&
263 (local != t->parms.iph.daddr ||
264 !ipv4_is_multicast(local))) ||
265 key != t->parms.i_key ||
266 !(t->dev->flags & IFF_UP))
267 continue;
268
269 if (t->dev->type != ARPHRD_IPGRE &&
270 t->dev->type != dev_type)
271 continue;
272
Timo Terasafcf1242009-01-26 20:56:10 -0800273 score = 0;
Timo Teras749c10f2009-01-19 17:22:12 -0800274 if (t->parms.link != link)
Timo Terasafcf1242009-01-26 20:56:10 -0800275 score |= 1;
Timo Teras749c10f2009-01-19 17:22:12 -0800276 if (t->dev->type != dev_type)
Timo Terasafcf1242009-01-26 20:56:10 -0800277 score |= 2;
278 if (score == 0)
Timo Teras749c10f2009-01-19 17:22:12 -0800279 return t;
Timo Terasafcf1242009-01-26 20:56:10 -0800280
281 if (score < cand_score) {
282 cand = t;
283 cand_score = score;
284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 }
Herbert Xue1a80002008-10-09 12:00:17 -0700286
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000287 for_each_ip_tunnel_rcu(ign->tunnels_wc[h1]) {
Timo Teras749c10f2009-01-19 17:22:12 -0800288 if (t->parms.i_key != key ||
289 !(t->dev->flags & IFF_UP))
290 continue;
291
292 if (t->dev->type != ARPHRD_IPGRE &&
293 t->dev->type != dev_type)
294 continue;
295
Timo Terasafcf1242009-01-26 20:56:10 -0800296 score = 0;
Timo Teras749c10f2009-01-19 17:22:12 -0800297 if (t->parms.link != link)
Timo Terasafcf1242009-01-26 20:56:10 -0800298 score |= 1;
Timo Teras749c10f2009-01-19 17:22:12 -0800299 if (t->dev->type != dev_type)
Timo Terasafcf1242009-01-26 20:56:10 -0800300 score |= 2;
301 if (score == 0)
Timo Teras749c10f2009-01-19 17:22:12 -0800302 return t;
Timo Terasafcf1242009-01-26 20:56:10 -0800303
304 if (score < cand_score) {
305 cand = t;
306 cand_score = score;
307 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 }
309
Timo Terasafcf1242009-01-26 20:56:10 -0800310 if (cand != NULL)
311 return cand;
Herbert Xue1a80002008-10-09 12:00:17 -0700312
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000313 dev = ign->fb_tunnel_dev;
314 if (dev->flags & IFF_UP)
315 return netdev_priv(dev);
Timo Teras749c10f2009-01-19 17:22:12 -0800316
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 return NULL;
318}
319
Eric Dumazet15078502010-09-15 11:07:53 +0000320static struct ip_tunnel __rcu **__ipgre_bucket(struct ipgre_net *ign,
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700321 struct ip_tunnel_parm *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322{
YOSHIFUJI Hideaki5056a1e2007-04-24 20:44:48 +0900323 __be32 remote = parms->iph.daddr;
324 __be32 local = parms->iph.saddr;
325 __be32 key = parms->i_key;
Eric Dumazet15078502010-09-15 11:07:53 +0000326 unsigned int h = HASH(key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 int prio = 0;
328
329 if (local)
330 prio |= 1;
Joe Perchesf97c1e02007-12-16 13:45:43 -0800331 if (remote && !ipv4_is_multicast(remote)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 prio |= 2;
333 h ^= HASH(remote);
334 }
335
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -0700336 return &ign->tunnels[prio][h];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337}
338
Eric Dumazet15078502010-09-15 11:07:53 +0000339static inline struct ip_tunnel __rcu **ipgre_bucket(struct ipgre_net *ign,
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700340 struct ip_tunnel *t)
YOSHIFUJI Hideaki5056a1e2007-04-24 20:44:48 +0900341{
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700342 return __ipgre_bucket(ign, &t->parms);
YOSHIFUJI Hideaki5056a1e2007-04-24 20:44:48 +0900343}
344
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700345static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
Eric Dumazet15078502010-09-15 11:07:53 +0000347 struct ip_tunnel __rcu **tp = ipgre_bucket(ign, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
Eric Dumazet15078502010-09-15 11:07:53 +0000349 rcu_assign_pointer(t->next, rtnl_dereference(*tp));
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000350 rcu_assign_pointer(*tp, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351}
352
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700353static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354{
Eric Dumazet15078502010-09-15 11:07:53 +0000355 struct ip_tunnel __rcu **tp;
356 struct ip_tunnel *iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Eric Dumazet15078502010-09-15 11:07:53 +0000358 for (tp = ipgre_bucket(ign, t);
359 (iter = rtnl_dereference(*tp)) != NULL;
360 tp = &iter->next) {
361 if (t == iter) {
362 rcu_assign_pointer(*tp, t->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 break;
364 }
365 }
366}
367
Herbert Xue1a80002008-10-09 12:00:17 -0700368static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
369 struct ip_tunnel_parm *parms,
370 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371{
Al Virod5a0a1e2006-11-08 00:23:14 -0800372 __be32 remote = parms->iph.daddr;
373 __be32 local = parms->iph.saddr;
374 __be32 key = parms->i_key;
Timo Teras749c10f2009-01-19 17:22:12 -0800375 int link = parms->link;
Eric Dumazet15078502010-09-15 11:07:53 +0000376 struct ip_tunnel *t;
377 struct ip_tunnel __rcu **tp;
Herbert Xue1a80002008-10-09 12:00:17 -0700378 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
379
Eric Dumazet15078502010-09-15 11:07:53 +0000380 for (tp = __ipgre_bucket(ign, parms);
381 (t = rtnl_dereference(*tp)) != NULL;
382 tp = &t->next)
Herbert Xue1a80002008-10-09 12:00:17 -0700383 if (local == t->parms.iph.saddr &&
384 remote == t->parms.iph.daddr &&
385 key == t->parms.i_key &&
Timo Teras749c10f2009-01-19 17:22:12 -0800386 link == t->parms.link &&
Herbert Xue1a80002008-10-09 12:00:17 -0700387 type == t->dev->type)
388 break;
389
390 return t;
391}
392
Eric Dumazet15078502010-09-15 11:07:53 +0000393static struct ip_tunnel *ipgre_tunnel_locate(struct net *net,
Herbert Xue1a80002008-10-09 12:00:17 -0700394 struct ip_tunnel_parm *parms, int create)
395{
396 struct ip_tunnel *t, *nt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 char name[IFNAMSIZ];
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700399 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
Herbert Xue1a80002008-10-09 12:00:17 -0700401 t = ipgre_tunnel_find(net, parms, ARPHRD_IPGRE);
402 if (t || !create)
403 return t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
405 if (parms->name[0])
406 strlcpy(name, parms->name, IFNAMSIZ);
Pavel Emelyanov34cc7ba2008-02-23 20:19:20 -0800407 else
stephen hemminger407d6fc2010-11-29 09:47:47 +0000408 strcpy(name, "gre%d");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
410 dev = alloc_netdev(sizeof(*t), name, ipgre_tunnel_setup);
411 if (!dev)
stephen hemminger407d6fc2010-11-29 09:47:47 +0000412 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Pavel Emelyanov0b67ece2008-04-16 01:11:13 -0700414 dev_net_set(dev, net);
415
Patrick McHardy2941a482006-01-08 22:05:26 -0800416 nt = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 nt->parms = *parms;
Herbert Xuc19e6542008-10-09 11:59:55 -0700418 dev->rtnl_link_ops = &ipgre_link_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Herbert Xu42aa9162008-10-09 11:59:32 -0700420 dev->mtu = ipgre_tunnel_bind_dev(dev);
421
Pavel Emelyanovb37d428b2008-02-26 23:51:04 -0800422 if (register_netdevice(dev) < 0)
423 goto failed_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Willem de Bruijnf2b3ee92012-01-26 10:34:35 +0000425 /* Can use a lockless transmit, unless we generate output sequences */
426 if (!(nt->parms.o_flags & GRE_SEQ))
427 dev->features |= NETIF_F_LLTX;
428
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 dev_hold(dev);
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700430 ipgre_tunnel_link(ign, nt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 return nt;
432
Pavel Emelyanovb37d428b2008-02-26 23:51:04 -0800433failed_free:
434 free_netdev(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 return NULL;
436}
437
438static void ipgre_tunnel_uninit(struct net_device *dev)
439{
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -0700440 struct net *net = dev_net(dev);
441 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
442
443 ipgre_tunnel_unlink(ign, netdev_priv(dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 dev_put(dev);
445}
446
447
448static void ipgre_err(struct sk_buff *skb, u32 info)
449{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Rami Rosen071f92d2008-05-21 17:47:54 -0700451/* All the routers (except for Linux) return only
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 8 bytes of packet payload. It means, that precise relaying of
453 ICMP in the real Internet is absolutely infeasible.
454
455 Moreover, Cisco "wise men" put GRE key to the third word
456 in GRE header. It makes impossible maintaining even soft state for keyed
457 GRE tunnels with enabled checksum. Tell them "thank you".
458
459 Well, I wonder, rfc1812 was written by Cisco employee,
stephen hemmingerbff52852012-02-24 08:08:20 +0000460 what the hell these idiots break standards established
461 by themselves???
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 */
463
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000464 const struct iphdr *iph = (const struct iphdr *)skb->data;
Al Virod5a0a1e2006-11-08 00:23:14 -0800465 __be16 *p = (__be16*)(skb->data+(iph->ihl<<2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 int grehlen = (iph->ihl<<2) + 4;
Arnaldo Carvalho de Melo88c76642007-03-13 14:43:18 -0300467 const int type = icmp_hdr(skb)->type;
468 const int code = icmp_hdr(skb)->code;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 struct ip_tunnel *t;
Al Virod5a0a1e2006-11-08 00:23:14 -0800470 __be16 flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
472 flags = p[0];
473 if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
474 if (flags&(GRE_VERSION|GRE_ROUTING))
475 return;
476 if (flags&GRE_KEY) {
477 grehlen += 4;
478 if (flags&GRE_CSUM)
479 grehlen += 4;
480 }
481 }
482
483 /* If only 8 bytes returned, keyed message will be dropped here */
484 if (skb_headlen(skb) < grehlen)
485 return;
486
487 switch (type) {
488 default:
489 case ICMP_PARAMETERPROB:
490 return;
491
492 case ICMP_DEST_UNREACH:
493 switch (code) {
494 case ICMP_SR_FAILED:
495 case ICMP_PORT_UNREACH:
496 /* Impossible event. */
497 return;
498 case ICMP_FRAG_NEEDED:
499 /* Soft state for pmtu is maintained by IP core. */
500 return;
501 default:
502 /* All others are translated to HOST_UNREACH.
503 rfc2003 contains "deep thoughts" about NET_UNREACH,
504 I believe they are just ether pollution. --ANK
505 */
506 break;
507 }
508 break;
509 case ICMP_TIME_EXCEEDED:
510 if (code != ICMP_EXC_TTL)
511 return;
512 break;
513 }
514
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000515 rcu_read_lock();
Timo Teras749c10f2009-01-19 17:22:12 -0800516 t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
Herbert Xue1a80002008-10-09 12:00:17 -0700517 flags & GRE_KEY ?
518 *(((__be32 *)p) + (grehlen / 4) - 1) : 0,
519 p[1]);
Joe Perchesf97c1e02007-12-16 13:45:43 -0800520 if (t == NULL || t->parms.iph.daddr == 0 ||
521 ipv4_is_multicast(t->parms.iph.daddr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 goto out;
523
524 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
525 goto out;
526
Wei Yongjunda6185d82009-02-24 23:34:48 -0800527 if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 t->err_count++;
529 else
530 t->err_count = 1;
531 t->err_time = jiffies;
532out:
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000533 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534}
535
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000536static inline void ipgre_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537{
538 if (INET_ECN_is_ce(iph->tos)) {
539 if (skb->protocol == htons(ETH_P_IP)) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700540 IP_ECN_set_ce(ip_hdr(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 } else if (skb->protocol == htons(ETH_P_IPV6)) {
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -0700542 IP6_ECN_set_ce(ipv6_hdr(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 }
544 }
545}
546
547static inline u8
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000548ipgre_ecn_encapsulate(u8 tos, const struct iphdr *old_iph, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549{
550 u8 inner = 0;
551 if (skb->protocol == htons(ETH_P_IP))
552 inner = old_iph->tos;
553 else if (skb->protocol == htons(ETH_P_IPV6))
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000554 inner = ipv6_get_dsfield((const struct ipv6hdr *)old_iph);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 return INET_ECN_encapsulate(tos, inner);
556}
557
558static int ipgre_rcv(struct sk_buff *skb)
559{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000560 const struct iphdr *iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 u8 *h;
Al Virod5a0a1e2006-11-08 00:23:14 -0800562 __be16 flags;
Al Virod3bc23e2006-11-14 21:24:49 -0800563 __sum16 csum = 0;
Al Virod5a0a1e2006-11-08 00:23:14 -0800564 __be32 key = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 u32 seqno = 0;
566 struct ip_tunnel *tunnel;
567 int offset = 4;
Herbert Xue1a80002008-10-09 12:00:17 -0700568 __be16 gre_proto;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
570 if (!pskb_may_pull(skb, 16))
571 goto drop_nolock;
572
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700573 iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 h = skb->data;
Al Virod5a0a1e2006-11-08 00:23:14 -0800575 flags = *(__be16*)h;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576
577 if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) {
578 /* - Version must be 0.
579 - We do not support routing headers.
580 */
581 if (flags&(GRE_VERSION|GRE_ROUTING))
582 goto drop_nolock;
583
584 if (flags&GRE_CSUM) {
Herbert Xufb286bb2005-11-10 13:01:24 -0800585 switch (skb->ip_summed) {
Patrick McHardy84fa7932006-08-29 16:44:56 -0700586 case CHECKSUM_COMPLETE:
Al Virod3bc23e2006-11-14 21:24:49 -0800587 csum = csum_fold(skb->csum);
Herbert Xufb286bb2005-11-10 13:01:24 -0800588 if (!csum)
589 break;
590 /* fall through */
591 case CHECKSUM_NONE:
592 skb->csum = 0;
593 csum = __skb_checksum_complete(skb);
Patrick McHardy84fa7932006-08-29 16:44:56 -0700594 skb->ip_summed = CHECKSUM_COMPLETE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 }
596 offset += 4;
597 }
598 if (flags&GRE_KEY) {
Al Virod5a0a1e2006-11-08 00:23:14 -0800599 key = *(__be32*)(h + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 offset += 4;
601 }
602 if (flags&GRE_SEQ) {
Al Virod5a0a1e2006-11-08 00:23:14 -0800603 seqno = ntohl(*(__be32*)(h + offset));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 offset += 4;
605 }
606 }
607
Herbert Xue1a80002008-10-09 12:00:17 -0700608 gre_proto = *(__be16 *)(h + 2);
609
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000610 rcu_read_lock();
Timo Teras749c10f2009-01-19 17:22:12 -0800611 if ((tunnel = ipgre_tunnel_lookup(skb->dev,
Herbert Xue1a80002008-10-09 12:00:17 -0700612 iph->saddr, iph->daddr, key,
613 gre_proto))) {
Eric Dumazete985aad2010-09-27 03:57:11 +0000614 struct pcpu_tstats *tstats;
Pavel Emelyanovaddd68e2008-05-21 14:14:22 -0700615
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 secpath_reset(skb);
617
Herbert Xue1a80002008-10-09 12:00:17 -0700618 skb->protocol = gre_proto;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 /* WCCP version 1 and 2 protocol decoding.
620 * - Change protocol to IP
621 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
622 */
Herbert Xue1a80002008-10-09 12:00:17 -0700623 if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) {
YOSHIFUJI Hideaki496c98d2006-10-10 19:41:21 -0700624 skb->protocol = htons(ETH_P_IP);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900625 if ((*(h + offset) & 0xF0) != 0x40)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 offset += 4;
627 }
628
Timo Teras1d069162007-12-20 00:10:33 -0800629 skb->mac_header = skb->network_header;
Arnaldo Carvalho de Melo4209fb62007-03-10 18:42:03 -0300630 __pskb_pull(skb, offset);
Arnaldo Carvalho de Melo9c702202007-04-25 18:04:18 -0700631 skb_postpull_rcsum(skb, skb_transport_header(skb), offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 skb->pkt_type = PACKET_HOST;
633#ifdef CONFIG_NET_IPGRE_BROADCAST
Joe Perchesf97c1e02007-12-16 13:45:43 -0800634 if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 /* Looped back packet, drop it! */
David S. Millerc7537962010-11-11 17:07:48 -0800636 if (rt_is_output_route(skb_rtable(skb)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 goto drop;
Eric Dumazete985aad2010-09-27 03:57:11 +0000638 tunnel->dev->stats.multicast++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 skb->pkt_type = PACKET_BROADCAST;
640 }
641#endif
642
643 if (((flags&GRE_CSUM) && csum) ||
644 (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) {
Eric Dumazete985aad2010-09-27 03:57:11 +0000645 tunnel->dev->stats.rx_crc_errors++;
646 tunnel->dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 goto drop;
648 }
649 if (tunnel->parms.i_flags&GRE_SEQ) {
650 if (!(flags&GRE_SEQ) ||
651 (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) {
Eric Dumazete985aad2010-09-27 03:57:11 +0000652 tunnel->dev->stats.rx_fifo_errors++;
653 tunnel->dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 goto drop;
655 }
656 tunnel->i_seqno = seqno + 1;
657 }
Herbert Xue1a80002008-10-09 12:00:17 -0700658
659 /* Warning: All skb pointers will be invalidated! */
660 if (tunnel->dev->type == ARPHRD_ETHER) {
661 if (!pskb_may_pull(skb, ETH_HLEN)) {
Eric Dumazete985aad2010-09-27 03:57:11 +0000662 tunnel->dev->stats.rx_length_errors++;
663 tunnel->dev->stats.rx_errors++;
Herbert Xue1a80002008-10-09 12:00:17 -0700664 goto drop;
665 }
666
667 iph = ip_hdr(skb);
668 skb->protocol = eth_type_trans(skb, tunnel->dev);
669 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
670 }
671
Eric Dumazete985aad2010-09-27 03:57:11 +0000672 tstats = this_cpu_ptr(tunnel->dev->tstats);
673 tstats->rx_packets++;
674 tstats->rx_bytes += skb->len;
675
676 __skb_tunnel_rx(skb, tunnel->dev);
Herbert Xue1a80002008-10-09 12:00:17 -0700677
678 skb_reset_network_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 ipgre_ecn_decapsulate(iph, skb);
Herbert Xue1a80002008-10-09 12:00:17 -0700680
Eric Dumazetcaf586e2010-09-30 21:06:55 +0000681 netif_rx(skb);
Eric Dumazet8990f462010-09-20 00:12:11 +0000682
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000683 rcu_read_unlock();
Eric Dumazet8990f462010-09-20 00:12:11 +0000684 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
Herbert Xu45af08b2006-04-05 22:31:19 -0700686 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
688drop:
Eric Dumazet8d5b2c02009-10-23 06:14:38 +0000689 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690drop_nolock:
691 kfree_skb(skb);
Eric Dumazeta02cec22010-09-22 20:43:57 +0000692 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693}
694
Stephen Hemminger6fef4c02009-08-31 19:50:41 +0000695static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696{
Patrick McHardy2941a482006-01-08 22:05:26 -0800697 struct ip_tunnel *tunnel = netdev_priv(dev);
Eric Dumazete985aad2010-09-27 03:57:11 +0000698 struct pcpu_tstats *tstats;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000699 const struct iphdr *old_iph = ip_hdr(skb);
700 const struct iphdr *tiph;
David S. Millercbb1e852011-05-04 12:33:34 -0700701 struct flowi4 fl4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 u8 tos;
Al Virod5a0a1e2006-11-08 00:23:14 -0800703 __be16 df;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 struct rtable *rt; /* Route to the other host */
Eric Dumazet15078502010-09-15 11:07:53 +0000705 struct net_device *tdev; /* Device to other host */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 struct iphdr *iph; /* Our new IP header */
Chuck Leverc2636b42007-10-23 21:07:32 -0700707 unsigned int max_headroom; /* The extra header space needed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 int gre_hlen;
Al Virod5a0a1e2006-11-08 00:23:14 -0800709 __be32 dst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 int mtu;
711
Herbert Xue1a80002008-10-09 12:00:17 -0700712 if (dev->type == ARPHRD_ETHER)
713 IPCB(skb)->flags = 0;
714
715 if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 gre_hlen = 0;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000717 tiph = (const struct iphdr *)skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 } else {
719 gre_hlen = tunnel->hlen;
720 tiph = &tunnel->parms.iph;
721 }
722
723 if ((dst = tiph->daddr) == 0) {
724 /* NBMA tunnel */
725
Eric Dumazetadf30902009-06-02 05:19:30 +0000726 if (skb_dst(skb) == NULL) {
Eric Dumazete985aad2010-09-27 03:57:11 +0000727 dev->stats.tx_fifo_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 goto tx_error;
729 }
730
David S. Miller61d57f82012-01-24 18:23:30 -0500731 if (skb->protocol == htons(ETH_P_IP)) {
Eric Dumazet511c3f92009-06-02 05:14:27 +0000732 rt = skb_rtable(skb);
David S. Miller61d57f82012-01-24 18:23:30 -0500733 dst = rt->rt_gateway;
734 }
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000735#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 else if (skb->protocol == htons(ETH_P_IPV6)) {
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000737 const struct in6_addr *addr6;
David S. Miller0ec88662012-01-27 15:01:08 -0800738 struct neighbour *neigh;
739 bool do_tx_error_icmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 int addr_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
David S. Miller0ec88662012-01-27 15:01:08 -0800742 neigh = dst_neigh_lookup(skb_dst(skb), &ipv6_hdr(skb)->daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 if (neigh == NULL)
744 goto tx_error;
745
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000746 addr6 = (const struct in6_addr *)&neigh->primary_key;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 addr_type = ipv6_addr_type(addr6);
748
749 if (addr_type == IPV6_ADDR_ANY) {
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -0700750 addr6 = &ipv6_hdr(skb)->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 addr_type = ipv6_addr_type(addr6);
752 }
753
754 if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
David S. Miller0ec88662012-01-27 15:01:08 -0800755 do_tx_error_icmp = true;
756 else {
757 do_tx_error_icmp = false;
758 dst = addr6->s6_addr32[3];
759 }
760 neigh_release(neigh);
761 if (do_tx_error_icmp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 goto tx_error_icmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 }
764#endif
765 else
766 goto tx_error;
767 }
768
769 tos = tiph->tos;
Andreas Jaggiee686ca2009-07-14 09:35:59 -0700770 if (tos == 1) {
771 tos = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 if (skb->protocol == htons(ETH_P_IP))
773 tos = old_iph->tos;
Stephen Hemmingerdd4ba832010-07-08 21:35:58 -0700774 else if (skb->protocol == htons(ETH_P_IPV6))
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000775 tos = ipv6_get_dsfield((const struct ipv6hdr *)old_iph);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 }
777
David S. Millercbb1e852011-05-04 12:33:34 -0700778 rt = ip_route_output_gre(dev_net(dev), &fl4, dst, tiph->saddr,
David S. Miller78fbfd82011-03-12 00:00:52 -0500779 tunnel->parms.o_key, RT_TOS(tos),
780 tunnel->parms.link);
781 if (IS_ERR(rt)) {
782 dev->stats.tx_carrier_errors++;
783 goto tx_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 }
Changli Gaod8d1f302010-06-10 23:31:35 -0700785 tdev = rt->dst.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
787 if (tdev == dev) {
788 ip_rt_put(rt);
Eric Dumazete985aad2010-09-27 03:57:11 +0000789 dev->stats.collisions++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 goto tx_error;
791 }
792
793 df = tiph->frag_off;
794 if (df)
Changli Gaod8d1f302010-06-10 23:31:35 -0700795 mtu = dst_mtu(&rt->dst) - dev->hard_header_len - tunnel->hlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 else
Eric Dumazetadf30902009-06-02 05:19:30 +0000797 mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
Eric Dumazetadf30902009-06-02 05:19:30 +0000799 if (skb_dst(skb))
800 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
802 if (skb->protocol == htons(ETH_P_IP)) {
803 df |= (old_iph->frag_off&htons(IP_DF));
804
805 if ((old_iph->frag_off&htons(IP_DF)) &&
806 mtu < ntohs(old_iph->tot_len)) {
807 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
808 ip_rt_put(rt);
809 goto tx_error;
810 }
811 }
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000812#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 else if (skb->protocol == htons(ETH_P_IPV6)) {
Eric Dumazetadf30902009-06-02 05:19:30 +0000814 struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815
Eric Dumazetadf30902009-06-02 05:19:30 +0000816 if (rt6 && mtu < dst_mtu(skb_dst(skb)) && mtu >= IPV6_MIN_MTU) {
Joe Perchesf97c1e02007-12-16 13:45:43 -0800817 if ((tunnel->parms.iph.daddr &&
818 !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 rt6->rt6i_dst.plen == 128) {
820 rt6->rt6i_flags |= RTF_MODIFIED;
David S. Millerdefb3512010-12-08 21:16:57 -0800821 dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 }
823 }
824
825 if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) {
Alexey Dobriyan3ffe5332010-02-18 08:25:24 +0000826 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 ip_rt_put(rt);
828 goto tx_error;
829 }
830 }
831#endif
832
833 if (tunnel->err_count > 0) {
Wei Yongjunda6185d82009-02-24 23:34:48 -0800834 if (time_before(jiffies,
835 tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 tunnel->err_count--;
837
838 dst_link_failure(skb);
839 } else
840 tunnel->err_count = 0;
841 }
842
Changli Gaod8d1f302010-06-10 23:31:35 -0700843 max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + rt->dst.header_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Patrick McHardycfbba492007-07-09 15:33:40 -0700845 if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
846 (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
Herbert Xu805dc1d2011-11-18 02:20:06 +0000848 if (max_headroom > dev->needed_headroom)
849 dev->needed_headroom = max_headroom;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 if (!new_skb) {
851 ip_rt_put(rt);
Eric Dumazete985aad2010-09-27 03:57:11 +0000852 dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000854 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 }
856 if (skb->sk)
857 skb_set_owner_w(new_skb, skb->sk);
858 dev_kfree_skb(skb);
859 skb = new_skb;
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700860 old_iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 }
862
Herbert Xu64194c32008-10-09 12:03:17 -0700863 skb_reset_transport_header(skb);
Arnaldo Carvalho de Meloe2d1bca2007-04-10 20:46:21 -0700864 skb_push(skb, gre_hlen);
865 skb_reset_network_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
Patrick McHardy48d5cad2006-02-15 15:10:22 -0800867 IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
868 IPSKB_REROUTED);
Eric Dumazetadf30902009-06-02 05:19:30 +0000869 skb_dst_drop(skb);
Changli Gaod8d1f302010-06-10 23:31:35 -0700870 skb_dst_set(skb, &rt->dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
872 /*
873 * Push down and install the IPIP header.
874 */
875
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700876 iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 iph->version = 4;
878 iph->ihl = sizeof(struct iphdr) >> 2;
879 iph->frag_off = df;
880 iph->protocol = IPPROTO_GRE;
881 iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb);
David S. Millercbb1e852011-05-04 12:33:34 -0700882 iph->daddr = fl4.daddr;
883 iph->saddr = fl4.saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
885 if ((iph->ttl = tiph->ttl) == 0) {
886 if (skb->protocol == htons(ETH_P_IP))
887 iph->ttl = old_iph->ttl;
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000888#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 else if (skb->protocol == htons(ETH_P_IPV6))
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000890 iph->ttl = ((const struct ipv6hdr *)old_iph)->hop_limit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891#endif
892 else
David S. Miller323e1262010-12-12 21:55:08 -0800893 iph->ttl = ip4_dst_hoplimit(&rt->dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 }
895
Herbert Xue1a80002008-10-09 12:00:17 -0700896 ((__be16 *)(iph + 1))[0] = tunnel->parms.o_flags;
897 ((__be16 *)(iph + 1))[1] = (dev->type == ARPHRD_ETHER) ?
898 htons(ETH_P_TEB) : skb->protocol;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899
900 if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) {
Al Virod5a0a1e2006-11-08 00:23:14 -0800901 __be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
903 if (tunnel->parms.o_flags&GRE_SEQ) {
904 ++tunnel->o_seqno;
905 *ptr = htonl(tunnel->o_seqno);
906 ptr--;
907 }
908 if (tunnel->parms.o_flags&GRE_KEY) {
909 *ptr = tunnel->parms.o_key;
910 ptr--;
911 }
912 if (tunnel->parms.o_flags&GRE_CSUM) {
913 *ptr = 0;
Al Viro5f92a732006-11-14 21:36:54 -0800914 *(__sum16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 }
916 }
917
918 nf_reset(skb);
Eric Dumazete985aad2010-09-27 03:57:11 +0000919 tstats = this_cpu_ptr(dev->tstats);
920 __IPTUNNEL_XMIT(tstats, &dev->stats);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000921 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922
David S. Miller496053f2012-01-11 16:46:32 -0800923#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924tx_error_icmp:
925 dst_link_failure(skb);
David S. Miller496053f2012-01-11 16:46:32 -0800926#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927tx_error:
Eric Dumazete985aad2010-09-27 03:57:11 +0000928 dev->stats.tx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000930 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931}
932
Herbert Xu42aa9162008-10-09 11:59:32 -0700933static int ipgre_tunnel_bind_dev(struct net_device *dev)
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800934{
935 struct net_device *tdev = NULL;
936 struct ip_tunnel *tunnel;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000937 const struct iphdr *iph;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800938 int hlen = LL_MAX_HEADER;
939 int mtu = ETH_DATA_LEN;
940 int addend = sizeof(struct iphdr) + 4;
941
942 tunnel = netdev_priv(dev);
943 iph = &tunnel->parms.iph;
944
Herbert Xuc95b8192008-10-09 11:58:54 -0700945 /* Guess output device to choose reasonable mtu and needed_headroom */
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800946
947 if (iph->daddr) {
David S. Millercbb1e852011-05-04 12:33:34 -0700948 struct flowi4 fl4;
949 struct rtable *rt;
Eric Dumazete985aad2010-09-27 03:57:11 +0000950
David S. Millercbb1e852011-05-04 12:33:34 -0700951 rt = ip_route_output_gre(dev_net(dev), &fl4,
952 iph->daddr, iph->saddr,
953 tunnel->parms.o_key,
954 RT_TOS(iph->tos),
955 tunnel->parms.link);
David S. Millerb23dd4f2011-03-02 14:31:35 -0800956 if (!IS_ERR(rt)) {
Changli Gaod8d1f302010-06-10 23:31:35 -0700957 tdev = rt->dst.dev;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800958 ip_rt_put(rt);
959 }
Herbert Xue1a80002008-10-09 12:00:17 -0700960
961 if (dev->type != ARPHRD_ETHER)
962 dev->flags |= IFF_POINTOPOINT;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800963 }
964
965 if (!tdev && tunnel->parms.link)
Pavel Emelyanov96635522008-04-16 01:10:44 -0700966 tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800967
968 if (tdev) {
Herbert Xuc95b8192008-10-09 11:58:54 -0700969 hlen = tdev->hard_header_len + tdev->needed_headroom;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800970 mtu = tdev->mtu;
971 }
972 dev->iflink = tunnel->parms.link;
973
974 /* Precalculate GRE options length */
975 if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
976 if (tunnel->parms.o_flags&GRE_CSUM)
977 addend += 4;
978 if (tunnel->parms.o_flags&GRE_KEY)
979 addend += 4;
980 if (tunnel->parms.o_flags&GRE_SEQ)
981 addend += 4;
982 }
Herbert Xuc95b8192008-10-09 11:58:54 -0700983 dev->needed_headroom = addend + hlen;
Tom Goff8cdb0452009-08-14 16:33:56 -0700984 mtu -= dev->hard_header_len + addend;
Herbert Xu42aa9162008-10-09 11:59:32 -0700985
986 if (mtu < 68)
987 mtu = 68;
988
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800989 tunnel->hlen = addend;
990
Herbert Xu42aa9162008-10-09 11:59:32 -0700991 return mtu;
Michal Schmidtee34c1e2007-12-13 09:46:32 -0800992}
993
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994static int
995ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
996{
997 int err = 0;
998 struct ip_tunnel_parm p;
999 struct ip_tunnel *t;
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001000 struct net *net = dev_net(dev);
1001 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
1003 switch (cmd) {
1004 case SIOCGETTUNNEL:
1005 t = NULL;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001006 if (dev == ign->fb_tunnel_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
1008 err = -EFAULT;
1009 break;
1010 }
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001011 t = ipgre_tunnel_locate(net, &p, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 }
1013 if (t == NULL)
Patrick McHardy2941a482006-01-08 22:05:26 -08001014 t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 memcpy(&p, &t->parms, sizeof(p));
1016 if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
1017 err = -EFAULT;
1018 break;
1019
1020 case SIOCADDTUNNEL:
1021 case SIOCCHGTUNNEL:
1022 err = -EPERM;
1023 if (!capable(CAP_NET_ADMIN))
1024 goto done;
1025
1026 err = -EFAULT;
1027 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
1028 goto done;
1029
1030 err = -EINVAL;
1031 if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
1032 p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
1033 ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
1034 goto done;
1035 if (p.iph.ttl)
1036 p.iph.frag_off |= htons(IP_DF);
1037
1038 if (!(p.i_flags&GRE_KEY))
1039 p.i_key = 0;
1040 if (!(p.o_flags&GRE_KEY))
1041 p.o_key = 0;
1042
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001043 t = ipgre_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001045 if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 if (t != NULL) {
1047 if (t->dev != dev) {
1048 err = -EEXIST;
1049 break;
1050 }
1051 } else {
Eric Dumazet15078502010-09-15 11:07:53 +00001052 unsigned int nflags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
Patrick McHardy2941a482006-01-08 22:05:26 -08001054 t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Joe Perchesf97c1e02007-12-16 13:45:43 -08001056 if (ipv4_is_multicast(p.iph.daddr))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 nflags = IFF_BROADCAST;
1058 else if (p.iph.daddr)
1059 nflags = IFF_POINTOPOINT;
1060
1061 if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
1062 err = -EINVAL;
1063 break;
1064 }
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001065 ipgre_tunnel_unlink(ign, t);
Pavel Emelyanov74b0b852010-10-27 05:43:53 +00001066 synchronize_net();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 t->parms.iph.saddr = p.iph.saddr;
1068 t->parms.iph.daddr = p.iph.daddr;
1069 t->parms.i_key = p.i_key;
1070 t->parms.o_key = p.o_key;
1071 memcpy(dev->dev_addr, &p.iph.saddr, 4);
1072 memcpy(dev->broadcast, &p.iph.daddr, 4);
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001073 ipgre_tunnel_link(ign, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 netdev_state_change(dev);
1075 }
1076 }
1077
1078 if (t) {
1079 err = 0;
1080 if (cmd == SIOCCHGTUNNEL) {
1081 t->parms.iph.ttl = p.iph.ttl;
1082 t->parms.iph.tos = p.iph.tos;
1083 t->parms.iph.frag_off = p.iph.frag_off;
Michal Schmidtee34c1e2007-12-13 09:46:32 -08001084 if (t->parms.link != p.link) {
1085 t->parms.link = p.link;
Herbert Xu42aa9162008-10-09 11:59:32 -07001086 dev->mtu = ipgre_tunnel_bind_dev(dev);
Michal Schmidtee34c1e2007-12-13 09:46:32 -08001087 netdev_state_change(dev);
1088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 }
1090 if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
1091 err = -EFAULT;
1092 } else
1093 err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
1094 break;
1095
1096 case SIOCDELTUNNEL:
1097 err = -EPERM;
1098 if (!capable(CAP_NET_ADMIN))
1099 goto done;
1100
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001101 if (dev == ign->fb_tunnel_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 err = -EFAULT;
1103 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
1104 goto done;
1105 err = -ENOENT;
Pavel Emelyanovf57e7d52008-04-16 01:09:22 -07001106 if ((t = ipgre_tunnel_locate(net, &p, 0)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 goto done;
1108 err = -EPERM;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001109 if (t == netdev_priv(ign->fb_tunnel_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 goto done;
1111 dev = t->dev;
1112 }
Stephen Hemminger22f8cde2007-02-07 00:09:58 -08001113 unregister_netdevice(dev);
1114 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 break;
1116
1117 default:
1118 err = -EINVAL;
1119 }
1120
1121done:
1122 return err;
1123}
1124
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
1126{
Patrick McHardy2941a482006-01-08 22:05:26 -08001127 struct ip_tunnel *tunnel = netdev_priv(dev);
Herbert Xuc95b8192008-10-09 11:58:54 -07001128 if (new_mtu < 68 ||
1129 new_mtu > 0xFFF8 - dev->hard_header_len - tunnel->hlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 return -EINVAL;
1131 dev->mtu = new_mtu;
1132 return 0;
1133}
1134
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135/* Nice toy. Unfortunately, useless in real life :-)
1136 It allows to construct virtual multiprotocol broadcast "LAN"
1137 over the Internet, provided multicast routing is tuned.
1138
1139
1140 I have no idea was this bicycle invented before me,
1141 so that I had to set ARPHRD_IPGRE to a random value.
1142 I have an impression, that Cisco could make something similar,
1143 but this feature is apparently missing in IOS<=11.2(8).
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001144
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
1146 with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
1147
1148 ping -t 255 224.66.66.66
1149
1150 If nobody answers, mbone does not work.
1151
1152 ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
1153 ip addr add 10.66.66.<somewhat>/24 dev Universe
1154 ifconfig Universe up
1155 ifconfig Universe add fe80::<Your_real_addr>/10
1156 ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
1157 ftp 10.66.66.66
1158 ...
1159 ftp fec0:6666:6666::193.233.7.65
1160 ...
1161
1162 */
1163
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001164static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
1165 unsigned short type,
Eric Dumazet15078502010-09-15 11:07:53 +00001166 const void *daddr, const void *saddr, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167{
Patrick McHardy2941a482006-01-08 22:05:26 -08001168 struct ip_tunnel *t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen);
Al Virod5a0a1e2006-11-08 00:23:14 -08001170 __be16 *p = (__be16*)(iph+1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
1172 memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
1173 p[0] = t->parms.o_flags;
1174 p[1] = htons(type);
1175
1176 /*
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001177 * Set the source hardware address.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 */
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001179
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 if (saddr)
1181 memcpy(&iph->saddr, saddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +00001182 if (daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 memcpy(&iph->daddr, daddr, 4);
Timo Teräs6d55cb92010-03-03 04:01:13 +00001184 if (iph->daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 return t->hlen;
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001186
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 return -t->hlen;
1188}
1189
Timo Teras6a5f44d2007-10-23 20:31:53 -07001190static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
1191{
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001192 const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
Timo Teras6a5f44d2007-10-23 20:31:53 -07001193 memcpy(haddr, &iph->saddr, 4);
1194 return 4;
1195}
1196
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001197static const struct header_ops ipgre_header_ops = {
1198 .create = ipgre_header,
Timo Teras6a5f44d2007-10-23 20:31:53 -07001199 .parse = ipgre_header_parse,
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001200};
1201
Timo Teras6a5f44d2007-10-23 20:31:53 -07001202#ifdef CONFIG_NET_IPGRE_BROADCAST
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203static int ipgre_open(struct net_device *dev)
1204{
Patrick McHardy2941a482006-01-08 22:05:26 -08001205 struct ip_tunnel *t = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
Joe Perchesf97c1e02007-12-16 13:45:43 -08001207 if (ipv4_is_multicast(t->parms.iph.daddr)) {
David S. Millercbb1e852011-05-04 12:33:34 -07001208 struct flowi4 fl4;
1209 struct rtable *rt;
Eric Dumazete985aad2010-09-27 03:57:11 +00001210
David S. Millercbb1e852011-05-04 12:33:34 -07001211 rt = ip_route_output_gre(dev_net(dev), &fl4,
1212 t->parms.iph.daddr,
1213 t->parms.iph.saddr,
1214 t->parms.o_key,
1215 RT_TOS(t->parms.iph.tos),
1216 t->parms.link);
David S. Millerb23dd4f2011-03-02 14:31:35 -08001217 if (IS_ERR(rt))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 return -EADDRNOTAVAIL;
Changli Gaod8d1f302010-06-10 23:31:35 -07001219 dev = rt->dst.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 ip_rt_put(rt);
Herbert Xue5ed6392005-10-03 14:35:55 -07001221 if (__in_dev_get_rtnl(dev) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 return -EADDRNOTAVAIL;
1223 t->mlink = dev->ifindex;
Herbert Xue5ed6392005-10-03 14:35:55 -07001224 ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 }
1226 return 0;
1227}
1228
1229static int ipgre_close(struct net_device *dev)
1230{
Patrick McHardy2941a482006-01-08 22:05:26 -08001231 struct ip_tunnel *t = netdev_priv(dev);
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001232
Joe Perchesf97c1e02007-12-16 13:45:43 -08001233 if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
Denis V. Lunev7fee0ca2008-01-21 17:32:38 -08001234 struct in_device *in_dev;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09001235 in_dev = inetdev_by_index(dev_net(dev), t->mlink);
Eric Dumazet8723e1b2010-10-19 00:39:26 +00001236 if (in_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 ip_mc_dec_group(in_dev, t->parms.iph.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 }
1239 return 0;
1240}
1241
1242#endif
1243
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001244static const struct net_device_ops ipgre_netdev_ops = {
1245 .ndo_init = ipgre_tunnel_init,
1246 .ndo_uninit = ipgre_tunnel_uninit,
1247#ifdef CONFIG_NET_IPGRE_BROADCAST
1248 .ndo_open = ipgre_open,
1249 .ndo_stop = ipgre_close,
1250#endif
1251 .ndo_start_xmit = ipgre_tunnel_xmit,
1252 .ndo_do_ioctl = ipgre_tunnel_ioctl,
1253 .ndo_change_mtu = ipgre_tunnel_change_mtu,
Eric Dumazete985aad2010-09-27 03:57:11 +00001254 .ndo_get_stats = ipgre_get_stats,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001255};
1256
Eric Dumazete985aad2010-09-27 03:57:11 +00001257static void ipgre_dev_free(struct net_device *dev)
1258{
1259 free_percpu(dev->tstats);
1260 free_netdev(dev);
1261}
1262
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263static void ipgre_tunnel_setup(struct net_device *dev)
1264{
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001265 dev->netdev_ops = &ipgre_netdev_ops;
Eric Dumazete985aad2010-09-27 03:57:11 +00001266 dev->destructor = ipgre_dev_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
1268 dev->type = ARPHRD_IPGRE;
Herbert Xuc95b8192008-10-09 11:58:54 -07001269 dev->needed_headroom = LL_MAX_HEADER + sizeof(struct iphdr) + 4;
Kris Katterjohn46f25df2006-01-05 16:35:42 -08001270 dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 dev->flags = IFF_NOARP;
1272 dev->iflink = 0;
1273 dev->addr_len = 4;
Pavel Emelyanov0b67ece2008-04-16 01:11:13 -07001274 dev->features |= NETIF_F_NETNS_LOCAL;
Eric Dumazet108bfa82009-05-28 22:35:10 +00001275 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276}
1277
1278static int ipgre_tunnel_init(struct net_device *dev)
1279{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 struct ip_tunnel *tunnel;
1281 struct iphdr *iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
Patrick McHardy2941a482006-01-08 22:05:26 -08001283 tunnel = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 iph = &tunnel->parms.iph;
1285
1286 tunnel->dev = dev;
1287 strcpy(tunnel->parms.name, dev->name);
1288
1289 memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
1290 memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
1291
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 if (iph->daddr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293#ifdef CONFIG_NET_IPGRE_BROADCAST
Joe Perchesf97c1e02007-12-16 13:45:43 -08001294 if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 if (!iph->saddr)
1296 return -EINVAL;
1297 dev->flags = IFF_BROADCAST;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001298 dev->header_ops = &ipgre_header_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300#endif
Michal Schmidtee34c1e2007-12-13 09:46:32 -08001301 } else
Timo Teras6a5f44d2007-10-23 20:31:53 -07001302 dev->header_ops = &ipgre_header_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Eric Dumazete985aad2010-09-27 03:57:11 +00001304 dev->tstats = alloc_percpu(struct pcpu_tstats);
1305 if (!dev->tstats)
1306 return -ENOMEM;
1307
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 return 0;
1309}
1310
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001311static void ipgre_fb_tunnel_init(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312{
Patrick McHardy2941a482006-01-08 22:05:26 -08001313 struct ip_tunnel *tunnel = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 struct iphdr *iph = &tunnel->parms.iph;
1315
1316 tunnel->dev = dev;
1317 strcpy(tunnel->parms.name, dev->name);
1318
1319 iph->version = 4;
1320 iph->protocol = IPPROTO_GRE;
1321 iph->ihl = 5;
1322 tunnel->hlen = sizeof(struct iphdr) + 4;
1323
1324 dev_hold(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325}
1326
1327
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001328static const struct gre_protocol ipgre_protocol = {
1329 .handler = ipgre_rcv,
1330 .err_handler = ipgre_err,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331};
1332
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001333static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -07001334{
1335 int prio;
1336
1337 for (prio = 0; prio < 4; prio++) {
1338 int h;
1339 for (h = 0; h < HASH_SIZE; h++) {
Eric Dumazet15078502010-09-15 11:07:53 +00001340 struct ip_tunnel *t;
1341
1342 t = rtnl_dereference(ign->tunnels[prio][h]);
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001343
1344 while (t != NULL) {
1345 unregister_netdevice_queue(t->dev, head);
Eric Dumazet15078502010-09-15 11:07:53 +00001346 t = rtnl_dereference(t->next);
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001347 }
Pavel Emelyanoveb8ce742008-04-16 01:10:26 -07001348 }
1349 }
1350}
1351
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001352static int __net_init ipgre_init_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001353{
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001354 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001355 int err;
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001356
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001357 ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0",
1358 ipgre_tunnel_setup);
1359 if (!ign->fb_tunnel_dev) {
1360 err = -ENOMEM;
1361 goto err_alloc_dev;
1362 }
Alexey Dobriyanbe77e592008-11-23 17:26:26 -08001363 dev_net_set(ign->fb_tunnel_dev, net);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001364
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001365 ipgre_fb_tunnel_init(ign->fb_tunnel_dev);
Herbert Xuc19e6542008-10-09 11:59:55 -07001366 ign->fb_tunnel_dev->rtnl_link_ops = &ipgre_link_ops;
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001367
1368 if ((err = register_netdev(ign->fb_tunnel_dev)))
1369 goto err_reg_dev;
1370
Eric Dumazet3285ee32010-10-30 16:21:28 -07001371 rcu_assign_pointer(ign->tunnels_wc[0],
1372 netdev_priv(ign->fb_tunnel_dev));
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001373 return 0;
1374
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001375err_reg_dev:
Eric Dumazet3285ee32010-10-30 16:21:28 -07001376 ipgre_dev_free(ign->fb_tunnel_dev);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001377err_alloc_dev:
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001378 return err;
1379}
1380
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001381static void __net_exit ipgre_exit_net(struct net *net)
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001382{
1383 struct ipgre_net *ign;
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001384 LIST_HEAD(list);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001385
1386 ign = net_generic(net, ipgre_net_id);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001387 rtnl_lock();
Eric Dumazeteef6dd62009-10-27 07:07:16 +00001388 ipgre_destroy_tunnels(ign, &list);
1389 unregister_netdevice_many(&list);
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001390 rtnl_unlock();
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001391}
1392
1393static struct pernet_operations ipgre_net_ops = {
1394 .init = ipgre_init_net,
1395 .exit = ipgre_exit_net,
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001396 .id = &ipgre_net_id,
1397 .size = sizeof(struct ipgre_net),
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001398};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
Herbert Xuc19e6542008-10-09 11:59:55 -07001400static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
1401{
1402 __be16 flags;
1403
1404 if (!data)
1405 return 0;
1406
1407 flags = 0;
1408 if (data[IFLA_GRE_IFLAGS])
1409 flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1410 if (data[IFLA_GRE_OFLAGS])
1411 flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1412 if (flags & (GRE_VERSION|GRE_ROUTING))
1413 return -EINVAL;
1414
1415 return 0;
1416}
1417
Herbert Xue1a80002008-10-09 12:00:17 -07001418static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
1419{
1420 __be32 daddr;
1421
1422 if (tb[IFLA_ADDRESS]) {
1423 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1424 return -EINVAL;
1425 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1426 return -EADDRNOTAVAIL;
1427 }
1428
1429 if (!data)
1430 goto out;
1431
1432 if (data[IFLA_GRE_REMOTE]) {
1433 memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1434 if (!daddr)
1435 return -EINVAL;
1436 }
1437
1438out:
1439 return ipgre_tunnel_validate(tb, data);
1440}
1441
Herbert Xuc19e6542008-10-09 11:59:55 -07001442static void ipgre_netlink_parms(struct nlattr *data[],
1443 struct ip_tunnel_parm *parms)
1444{
Herbert Xu7bb82d92008-10-11 12:20:15 -07001445 memset(parms, 0, sizeof(*parms));
Herbert Xuc19e6542008-10-09 11:59:55 -07001446
1447 parms->iph.protocol = IPPROTO_GRE;
1448
1449 if (!data)
1450 return;
1451
1452 if (data[IFLA_GRE_LINK])
1453 parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1454
1455 if (data[IFLA_GRE_IFLAGS])
1456 parms->i_flags = nla_get_be16(data[IFLA_GRE_IFLAGS]);
1457
1458 if (data[IFLA_GRE_OFLAGS])
1459 parms->o_flags = nla_get_be16(data[IFLA_GRE_OFLAGS]);
1460
1461 if (data[IFLA_GRE_IKEY])
1462 parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1463
1464 if (data[IFLA_GRE_OKEY])
1465 parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1466
1467 if (data[IFLA_GRE_LOCAL])
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001468 parms->iph.saddr = nla_get_be32(data[IFLA_GRE_LOCAL]);
Herbert Xuc19e6542008-10-09 11:59:55 -07001469
1470 if (data[IFLA_GRE_REMOTE])
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001471 parms->iph.daddr = nla_get_be32(data[IFLA_GRE_REMOTE]);
Herbert Xuc19e6542008-10-09 11:59:55 -07001472
1473 if (data[IFLA_GRE_TTL])
1474 parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1475
1476 if (data[IFLA_GRE_TOS])
1477 parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1478
1479 if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC]))
1480 parms->iph.frag_off = htons(IP_DF);
1481}
1482
Herbert Xue1a80002008-10-09 12:00:17 -07001483static int ipgre_tap_init(struct net_device *dev)
1484{
1485 struct ip_tunnel *tunnel;
1486
1487 tunnel = netdev_priv(dev);
1488
1489 tunnel->dev = dev;
1490 strcpy(tunnel->parms.name, dev->name);
1491
1492 ipgre_tunnel_bind_dev(dev);
1493
Eric Dumazete985aad2010-09-27 03:57:11 +00001494 dev->tstats = alloc_percpu(struct pcpu_tstats);
1495 if (!dev->tstats)
1496 return -ENOMEM;
1497
Herbert Xue1a80002008-10-09 12:00:17 -07001498 return 0;
1499}
1500
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001501static const struct net_device_ops ipgre_tap_netdev_ops = {
1502 .ndo_init = ipgre_tap_init,
1503 .ndo_uninit = ipgre_tunnel_uninit,
1504 .ndo_start_xmit = ipgre_tunnel_xmit,
1505 .ndo_set_mac_address = eth_mac_addr,
1506 .ndo_validate_addr = eth_validate_addr,
1507 .ndo_change_mtu = ipgre_tunnel_change_mtu,
Eric Dumazete985aad2010-09-27 03:57:11 +00001508 .ndo_get_stats = ipgre_get_stats,
Stephen Hemmingerb8c26a32008-11-20 20:34:29 -08001509};
1510
Herbert Xue1a80002008-10-09 12:00:17 -07001511static void ipgre_tap_setup(struct net_device *dev)
1512{
1513
1514 ether_setup(dev);
1515
Herbert Xu2e9526b2009-10-30 05:51:48 +00001516 dev->netdev_ops = &ipgre_tap_netdev_ops;
Eric Dumazete985aad2010-09-27 03:57:11 +00001517 dev->destructor = ipgre_dev_free;
Herbert Xue1a80002008-10-09 12:00:17 -07001518
1519 dev->iflink = 0;
1520 dev->features |= NETIF_F_NETNS_LOCAL;
1521}
1522
Eric W. Biederman81adee42009-11-08 00:53:51 -08001523static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[],
Herbert Xuc19e6542008-10-09 11:59:55 -07001524 struct nlattr *data[])
1525{
1526 struct ip_tunnel *nt;
1527 struct net *net = dev_net(dev);
1528 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
1529 int mtu;
1530 int err;
1531
1532 nt = netdev_priv(dev);
1533 ipgre_netlink_parms(data, &nt->parms);
1534
Herbert Xue1a80002008-10-09 12:00:17 -07001535 if (ipgre_tunnel_find(net, &nt->parms, dev->type))
Herbert Xuc19e6542008-10-09 11:59:55 -07001536 return -EEXIST;
1537
Herbert Xue1a80002008-10-09 12:00:17 -07001538 if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
Danny Kukawkaf2cedb62012-02-15 06:45:39 +00001539 eth_hw_addr_random(dev);
Herbert Xue1a80002008-10-09 12:00:17 -07001540
Herbert Xuc19e6542008-10-09 11:59:55 -07001541 mtu = ipgre_tunnel_bind_dev(dev);
1542 if (!tb[IFLA_MTU])
1543 dev->mtu = mtu;
1544
Eric Dumazetb790e012010-09-27 23:05:47 +00001545 /* Can use a lockless transmit, unless we generate output sequences */
1546 if (!(nt->parms.o_flags & GRE_SEQ))
1547 dev->features |= NETIF_F_LLTX;
1548
Herbert Xuc19e6542008-10-09 11:59:55 -07001549 err = register_netdevice(dev);
1550 if (err)
1551 goto out;
1552
1553 dev_hold(dev);
1554 ipgre_tunnel_link(ign, nt);
1555
1556out:
1557 return err;
1558}
1559
1560static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1561 struct nlattr *data[])
1562{
1563 struct ip_tunnel *t, *nt;
1564 struct net *net = dev_net(dev);
1565 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
1566 struct ip_tunnel_parm p;
1567 int mtu;
1568
1569 if (dev == ign->fb_tunnel_dev)
1570 return -EINVAL;
1571
1572 nt = netdev_priv(dev);
1573 ipgre_netlink_parms(data, &p);
1574
1575 t = ipgre_tunnel_locate(net, &p, 0);
1576
1577 if (t) {
1578 if (t->dev != dev)
1579 return -EEXIST;
1580 } else {
Herbert Xuc19e6542008-10-09 11:59:55 -07001581 t = nt;
1582
Herbert Xu2e9526b2009-10-30 05:51:48 +00001583 if (dev->type != ARPHRD_ETHER) {
Eric Dumazet15078502010-09-15 11:07:53 +00001584 unsigned int nflags = 0;
Herbert Xuc19e6542008-10-09 11:59:55 -07001585
Herbert Xu2e9526b2009-10-30 05:51:48 +00001586 if (ipv4_is_multicast(p.iph.daddr))
1587 nflags = IFF_BROADCAST;
1588 else if (p.iph.daddr)
1589 nflags = IFF_POINTOPOINT;
1590
1591 if ((dev->flags ^ nflags) &
1592 (IFF_POINTOPOINT | IFF_BROADCAST))
1593 return -EINVAL;
1594 }
Herbert Xuc19e6542008-10-09 11:59:55 -07001595
1596 ipgre_tunnel_unlink(ign, t);
1597 t->parms.iph.saddr = p.iph.saddr;
1598 t->parms.iph.daddr = p.iph.daddr;
1599 t->parms.i_key = p.i_key;
Herbert Xu2e9526b2009-10-30 05:51:48 +00001600 if (dev->type != ARPHRD_ETHER) {
1601 memcpy(dev->dev_addr, &p.iph.saddr, 4);
1602 memcpy(dev->broadcast, &p.iph.daddr, 4);
1603 }
Herbert Xuc19e6542008-10-09 11:59:55 -07001604 ipgre_tunnel_link(ign, t);
1605 netdev_state_change(dev);
1606 }
1607
1608 t->parms.o_key = p.o_key;
1609 t->parms.iph.ttl = p.iph.ttl;
1610 t->parms.iph.tos = p.iph.tos;
1611 t->parms.iph.frag_off = p.iph.frag_off;
1612
1613 if (t->parms.link != p.link) {
1614 t->parms.link = p.link;
1615 mtu = ipgre_tunnel_bind_dev(dev);
1616 if (!tb[IFLA_MTU])
1617 dev->mtu = mtu;
1618 netdev_state_change(dev);
1619 }
1620
1621 return 0;
1622}
1623
1624static size_t ipgre_get_size(const struct net_device *dev)
1625{
1626 return
1627 /* IFLA_GRE_LINK */
1628 nla_total_size(4) +
1629 /* IFLA_GRE_IFLAGS */
1630 nla_total_size(2) +
1631 /* IFLA_GRE_OFLAGS */
1632 nla_total_size(2) +
1633 /* IFLA_GRE_IKEY */
1634 nla_total_size(4) +
1635 /* IFLA_GRE_OKEY */
1636 nla_total_size(4) +
1637 /* IFLA_GRE_LOCAL */
1638 nla_total_size(4) +
1639 /* IFLA_GRE_REMOTE */
1640 nla_total_size(4) +
1641 /* IFLA_GRE_TTL */
1642 nla_total_size(1) +
1643 /* IFLA_GRE_TOS */
1644 nla_total_size(1) +
1645 /* IFLA_GRE_PMTUDISC */
1646 nla_total_size(1) +
1647 0;
1648}
1649
1650static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1651{
1652 struct ip_tunnel *t = netdev_priv(dev);
1653 struct ip_tunnel_parm *p = &t->parms;
1654
1655 NLA_PUT_U32(skb, IFLA_GRE_LINK, p->link);
1656 NLA_PUT_BE16(skb, IFLA_GRE_IFLAGS, p->i_flags);
1657 NLA_PUT_BE16(skb, IFLA_GRE_OFLAGS, p->o_flags);
Patrick McHardyba9e64b2008-10-10 12:10:30 -07001658 NLA_PUT_BE32(skb, IFLA_GRE_IKEY, p->i_key);
1659 NLA_PUT_BE32(skb, IFLA_GRE_OKEY, p->o_key);
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001660 NLA_PUT_BE32(skb, IFLA_GRE_LOCAL, p->iph.saddr);
1661 NLA_PUT_BE32(skb, IFLA_GRE_REMOTE, p->iph.daddr);
Herbert Xuc19e6542008-10-09 11:59:55 -07001662 NLA_PUT_U8(skb, IFLA_GRE_TTL, p->iph.ttl);
1663 NLA_PUT_U8(skb, IFLA_GRE_TOS, p->iph.tos);
1664 NLA_PUT_U8(skb, IFLA_GRE_PMTUDISC, !!(p->iph.frag_off & htons(IP_DF)));
1665
1666 return 0;
1667
1668nla_put_failure:
1669 return -EMSGSIZE;
1670}
1671
1672static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1673 [IFLA_GRE_LINK] = { .type = NLA_U32 },
1674 [IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
1675 [IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
1676 [IFLA_GRE_IKEY] = { .type = NLA_U32 },
1677 [IFLA_GRE_OKEY] = { .type = NLA_U32 },
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001678 [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
1679 [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
Herbert Xuc19e6542008-10-09 11:59:55 -07001680 [IFLA_GRE_TTL] = { .type = NLA_U8 },
1681 [IFLA_GRE_TOS] = { .type = NLA_U8 },
1682 [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 },
1683};
1684
1685static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1686 .kind = "gre",
1687 .maxtype = IFLA_GRE_MAX,
1688 .policy = ipgre_policy,
1689 .priv_size = sizeof(struct ip_tunnel),
1690 .setup = ipgre_tunnel_setup,
1691 .validate = ipgre_tunnel_validate,
1692 .newlink = ipgre_newlink,
1693 .changelink = ipgre_changelink,
1694 .get_size = ipgre_get_size,
1695 .fill_info = ipgre_fill_info,
1696};
1697
Herbert Xue1a80002008-10-09 12:00:17 -07001698static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1699 .kind = "gretap",
1700 .maxtype = IFLA_GRE_MAX,
1701 .policy = ipgre_policy,
1702 .priv_size = sizeof(struct ip_tunnel),
1703 .setup = ipgre_tap_setup,
1704 .validate = ipgre_tap_validate,
1705 .newlink = ipgre_newlink,
1706 .changelink = ipgre_changelink,
1707 .get_size = ipgre_get_size,
1708 .fill_info = ipgre_fill_info,
1709};
1710
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711/*
1712 * And now the modules code and kernel interface.
1713 */
1714
1715static int __init ipgre_init(void)
1716{
1717 int err;
1718
Joe Perches058bd4d2012-03-11 18:36:11 +00001719 pr_info("GRE over IPv4 tunneling driver\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
Eric W. Biedermancfb8fbf2009-11-29 15:46:13 +00001721 err = register_pernet_device(&ipgre_net_ops);
Pavel Emelyanov59a4c752008-04-16 01:08:53 -07001722 if (err < 0)
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001723 return err;
1724
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001725 err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001726 if (err < 0) {
Joe Perches058bd4d2012-03-11 18:36:11 +00001727 pr_info("%s: can't add protocol\n", __func__);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001728 goto add_proto_failed;
1729 }
Pavel Emelyanov7daa0002008-04-16 01:10:05 -07001730
Herbert Xuc19e6542008-10-09 11:59:55 -07001731 err = rtnl_link_register(&ipgre_link_ops);
1732 if (err < 0)
1733 goto rtnl_link_failed;
1734
Herbert Xue1a80002008-10-09 12:00:17 -07001735 err = rtnl_link_register(&ipgre_tap_ops);
1736 if (err < 0)
1737 goto tap_ops_failed;
1738
Herbert Xuc19e6542008-10-09 11:59:55 -07001739out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 return err;
Herbert Xuc19e6542008-10-09 11:59:55 -07001741
Herbert Xue1a80002008-10-09 12:00:17 -07001742tap_ops_failed:
1743 rtnl_link_unregister(&ipgre_link_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001744rtnl_link_failed:
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001745 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001746add_proto_failed:
1747 unregister_pernet_device(&ipgre_net_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001748 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749}
1750
Alexey Kuznetsovdb445752005-07-30 17:46:44 -07001751static void __exit ipgre_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752{
Herbert Xue1a80002008-10-09 12:00:17 -07001753 rtnl_link_unregister(&ipgre_tap_ops);
Herbert Xuc19e6542008-10-09 11:59:55 -07001754 rtnl_link_unregister(&ipgre_link_ops);
Dmitry Kozlov00959ad2010-08-21 23:05:39 -07001755 if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0)
Joe Perches058bd4d2012-03-11 18:36:11 +00001756 pr_info("%s: can't remove protocol\n", __func__);
Alexey Dobriyanc2892f02010-02-16 07:57:44 +00001757 unregister_pernet_device(&ipgre_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758}
1759
1760module_init(ipgre_init);
1761module_exit(ipgre_fini);
1762MODULE_LICENSE("GPL");
Patrick McHardy4d74f8b2008-10-10 12:11:06 -07001763MODULE_ALIAS_RTNL_LINK("gre");
1764MODULE_ALIAS_RTNL_LINK("gretap");
Vasiliy Kulikov8909c9a2011-03-02 00:33:13 +03001765MODULE_ALIAS_NETDEV("gre0");