ip_gre.c 43.3 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
2
 *	Linux NET3:	GRE over IP protocol decoder.
Linus Torvalds's avatar
Linus Torvalds committed
3
4
5
6
7
8
9
10
11
12
 *
 *	Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 *
 */

13
14
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

15
#include <linux/capability.h>
Linus Torvalds's avatar
Linus Torvalds committed
16
17
18
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
19
#include <linux/slab.h>
Linus Torvalds's avatar
Linus Torvalds committed
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <asm/uaccess.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/in.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/if_arp.h>
#include <linux/mroute.h>
#include <linux/init.h>
#include <linux/in6.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/netfilter_ipv4.h>
33
#include <linux/etherdevice.h>
34
#include <linux/if_ether.h>
Linus Torvalds's avatar
Linus Torvalds committed
35
36
37
38
39
40
41
42
43
44
45

#include <net/sock.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/protocol.h>
#include <net/ipip.h>
#include <net/arp.h>
#include <net/checksum.h>
#include <net/dsfield.h>
#include <net/inet_ecn.h>
#include <net/xfrm.h>
46
47
#include <net/net_namespace.h>
#include <net/netns/generic.h>
Herbert Xu's avatar
Herbert Xu committed
48
#include <net/rtnetlink.h>
49
#include <net/gre.h>
Linus Torvalds's avatar
Linus Torvalds committed
50

51
#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds's avatar
Linus Torvalds committed
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <net/ipv6.h>
#include <net/ip6_fib.h>
#include <net/ip6_route.h>
#endif

/*
   Problems & solutions
   --------------------

   1. The most important issue is detecting local dead loops.
   They would cause complete host lockup in transmit, which
   would be "resolved" by stack overflow or, if queueing is enabled,
   with infinite looping in net_bh.

   We cannot track such dead loops during route installation,
   it is infeasible task. The most general solutions would be
   to keep skb->encapsulation counter (sort of local ttl),
Eric Dumazet's avatar
Eric Dumazet committed
69
   and silently drop packet when it expires. It is a good
70
   solution, but it supposes maintaining new variable in ALL
Linus Torvalds's avatar
Linus Torvalds committed
71
72
   skb, even if no tunneling is used.

Eric Dumazet's avatar
Eric Dumazet committed
73
74
75
   Current solution: xmit_recursion breaks dead loops. This is a percpu
   counter, since when we enter the first ndo_xmit(), cpu migration is
   forbidden. We force an exit if this counter reaches RECURSION_LIMIT
Linus Torvalds's avatar
Linus Torvalds committed
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

   2. Networking dead loops would not kill routers, but would really
   kill network. IP hop limit plays role of "t->recursion" in this case,
   if we copy it from packet being encapsulated to upper header.
   It is very good solution, but it introduces two problems:

   - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
     do not work over tunnels.
   - traceroute does not work. I planned to relay ICMP from tunnel,
     so that this problem would be solved and traceroute output
     would even more informative. This idea appeared to be wrong:
     only Linux complies to rfc1812 now (yes, guys, Linux is the only
     true router now :-)), all routers (at least, in neighbourhood of mine)
     return only 8 bytes of payload. It is the end.

   Hence, if we want that OSPF worked or traceroute said something reasonable,
   we should search for another solution.

   One of them is to parse packet trying to detect inner encapsulation
   made by our node. It is difficult or even impossible, especially,
96
   taking into account fragmentation. TO be short, ttl is not solution at all.
Linus Torvalds's avatar
Linus Torvalds committed
97
98
99
100
101
102

   Current solution: The solution was UNEXPECTEDLY SIMPLE.
   We force DF flag on tunnels with preconfigured hop limit,
   that is ALL. :-) Well, it does not remove the problem completely,
   but exponential growth of network traffic is changed to linear
   (branches, that exceed pmtu are pruned) and tunnel mtu
103
   rapidly degrades to value <68, where looping stops.
Linus Torvalds's avatar
Linus Torvalds committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
   Yes, it is not good if there exists a router in the loop,
   which does not force DF, even when encapsulating packets have DF set.
   But it is not our problem! Nobody could accuse us, we made
   all that we could make. Even if it is your gated who injected
   fatal route to network, even if it were you who configured
   fatal static route: you are innocent. :-)



   3. Really, ipv4/ipip.c, ipv4/ip_gre.c and ipv6/sit.c contain
   practically identical code. It would be good to glue them
   together, but it is not very evident, how to make them modular.
   sit is integral part of IPv6, ipip and gre are naturally modular.
   We could extract common parts (hash table, ioctl etc)
   to a separate module (ip_tunnel.c).

   Alexey Kuznetsov.
 */

Herbert Xu's avatar
Herbert Xu committed
123
static struct rtnl_link_ops ipgre_link_ops __read_mostly;
Linus Torvalds's avatar
Linus Torvalds committed
124
125
static int ipgre_tunnel_init(struct net_device *dev);
static void ipgre_tunnel_setup(struct net_device *dev);
126
static int ipgre_tunnel_bind_dev(struct net_device *dev);
Linus Torvalds's avatar
Linus Torvalds committed
127
128
129

/* Fallback tunnel: no source, no destination, no key, no options */

130
131
#define HASH_SIZE  16

132
static int ipgre_net_id __read_mostly;
133
struct ipgre_net {
Eric Dumazet's avatar
Eric Dumazet committed
134
	struct ip_tunnel __rcu *tunnels[4][HASH_SIZE];
135

136
	struct net_device *fb_tunnel_dev;
137
138
};

Linus Torvalds's avatar
Linus Torvalds committed
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* Tunnel hash table */

/*
   4 hash tables:

   3: (remote,local)
   2: (remote,*)
   1: (*,local)
   0: (*,*)

   We require exact key match i.e. if a key is present in packet
   it will match only tunnel with the same key; if it is not present,
   it will match only keyless tunnel.

   All keysless packets, if not matched configured keyless tunnels
   will match fallback tunnel.
 */

Al Viro's avatar
Al Viro committed
157
#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
Linus Torvalds's avatar
Linus Torvalds committed
158

159
160
161
162
#define tunnels_r_l	tunnels[3]
#define tunnels_r	tunnels[2]
#define tunnels_l	tunnels[1]
#define tunnels_wc	tunnels[0]
163
/*
Eric Dumazet's avatar
Eric Dumazet committed
164
 * Locking : hash tables are protected by RCU and RTNL
165
 */
Linus Torvalds's avatar
Linus Torvalds committed
166

167
168
#define for_each_ip_tunnel_rcu(start) \
	for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
Linus Torvalds's avatar
Linus Torvalds committed
169

Eric Dumazet's avatar
Eric Dumazet committed
170
171
/* often modified stats are per cpu, other are shared (netdev->stats) */
struct pcpu_tstats {
172
173
174
175
176
177
	u64	rx_packets;
	u64	rx_bytes;
	u64	tx_packets;
	u64	tx_bytes;
	struct u64_stats_sync	syncp;
};
Eric Dumazet's avatar
Eric Dumazet committed
178

179
180
static struct rtnl_link_stats64 *ipgre_get_stats64(struct net_device *dev,
						   struct rtnl_link_stats64 *tot)
Eric Dumazet's avatar
Eric Dumazet committed
181
182
183
184
185
{
	int i;

	for_each_possible_cpu(i) {
		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
		unsigned int start;

		do {
			start = u64_stats_fetch_begin_bh(&tstats->syncp);
			rx_packets = tstats->rx_packets;
			tx_packets = tstats->tx_packets;
			rx_bytes = tstats->rx_bytes;
			tx_bytes = tstats->tx_bytes;
		} while (u64_stats_fetch_retry_bh(&tstats->syncp, start));

		tot->rx_packets += rx_packets;
		tot->tx_packets += tx_packets;
		tot->rx_bytes   += rx_bytes;
		tot->tx_bytes   += tx_bytes;
Eric Dumazet's avatar
Eric Dumazet committed
201
	}
202
203
204
205
206
207
208
209
210
211
212
213
214

	tot->multicast = dev->stats.multicast;
	tot->rx_crc_errors = dev->stats.rx_crc_errors;
	tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
	tot->rx_length_errors = dev->stats.rx_length_errors;
	tot->rx_errors = dev->stats.rx_errors;
	tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
	tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
	tot->tx_dropped = dev->stats.tx_dropped;
	tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
	tot->tx_errors = dev->stats.tx_errors;

	return tot;
Eric Dumazet's avatar
Eric Dumazet committed
215
216
}

Linus Torvalds's avatar
Linus Torvalds committed
217
218
/* Given src, dst and key, find appropriate for input tunnel. */

Daniel Baluta's avatar
Daniel Baluta committed
219
220
221
static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
					     __be32 remote, __be32 local,
					     __be32 key, __be16 gre_proto)
Linus Torvalds's avatar
Linus Torvalds committed
222
{
223
224
	struct net *net = dev_net(dev);
	int link = dev->ifindex;
Eric Dumazet's avatar
Eric Dumazet committed
225
226
	unsigned int h0 = HASH(remote);
	unsigned int h1 = HASH(key);
Timo Teras's avatar
Timo Teras committed
227
	struct ip_tunnel *t, *cand = NULL;
228
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
229
230
	int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
		       ARPHRD_ETHER : ARPHRD_IPGRE;
Timo Teras's avatar
Timo Teras committed
231
	int score, cand_score = 4;
Linus Torvalds's avatar
Linus Torvalds committed
232

233
	for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) {
234
235
236
237
238
239
240
241
242
243
		if (local != t->parms.iph.saddr ||
		    remote != t->parms.iph.daddr ||
		    key != t->parms.i_key ||
		    !(t->dev->flags & IFF_UP))
			continue;

		if (t->dev->type != ARPHRD_IPGRE &&
		    t->dev->type != dev_type)
			continue;

Timo Teras's avatar
Timo Teras committed
244
		score = 0;
245
		if (t->parms.link != link)
Timo Teras's avatar
Timo Teras committed
246
			score |= 1;
247
		if (t->dev->type != dev_type)
Timo Teras's avatar
Timo Teras committed
248
249
			score |= 2;
		if (score == 0)
250
			return t;
Timo Teras's avatar
Timo Teras committed
251
252
253
254
255

		if (score < cand_score) {
			cand = t;
			cand_score = score;
		}
Linus Torvalds's avatar
Linus Torvalds committed
256
	}
257

258
	for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) {
259
260
261
262
263
264
265
266
267
		if (remote != t->parms.iph.daddr ||
		    key != t->parms.i_key ||
		    !(t->dev->flags & IFF_UP))
			continue;

		if (t->dev->type != ARPHRD_IPGRE &&
		    t->dev->type != dev_type)
			continue;

Timo Teras's avatar
Timo Teras committed
268
		score = 0;
269
		if (t->parms.link != link)
Timo Teras's avatar
Timo Teras committed
270
			score |= 1;
271
		if (t->dev->type != dev_type)
Timo Teras's avatar
Timo Teras committed
272
273
			score |= 2;
		if (score == 0)
274
			return t;
Timo Teras's avatar
Timo Teras committed
275
276
277
278
279

		if (score < cand_score) {
			cand = t;
			cand_score = score;
		}
Linus Torvalds's avatar
Linus Torvalds committed
280
	}
281

282
	for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) {
283
284
285
286
287
288
289
290
291
292
293
		if ((local != t->parms.iph.saddr &&
		     (local != t->parms.iph.daddr ||
		      !ipv4_is_multicast(local))) ||
		    key != t->parms.i_key ||
		    !(t->dev->flags & IFF_UP))
			continue;

		if (t->dev->type != ARPHRD_IPGRE &&
		    t->dev->type != dev_type)
			continue;

Timo Teras's avatar
Timo Teras committed
294
		score = 0;
295
		if (t->parms.link != link)
Timo Teras's avatar
Timo Teras committed
296
			score |= 1;
297
		if (t->dev->type != dev_type)
Timo Teras's avatar
Timo Teras committed
298
299
			score |= 2;
		if (score == 0)
300
			return t;
Timo Teras's avatar
Timo Teras committed
301
302
303
304
305

		if (score < cand_score) {
			cand = t;
			cand_score = score;
		}
Linus Torvalds's avatar
Linus Torvalds committed
306
	}
307

308
	for_each_ip_tunnel_rcu(ign->tunnels_wc[h1]) {
309
310
311
312
313
314
315
316
		if (t->parms.i_key != key ||
		    !(t->dev->flags & IFF_UP))
			continue;

		if (t->dev->type != ARPHRD_IPGRE &&
		    t->dev->type != dev_type)
			continue;

Timo Teras's avatar
Timo Teras committed
317
		score = 0;
318
		if (t->parms.link != link)
Timo Teras's avatar
Timo Teras committed
319
			score |= 1;
320
		if (t->dev->type != dev_type)
Timo Teras's avatar
Timo Teras committed
321
322
			score |= 2;
		if (score == 0)
323
			return t;
Timo Teras's avatar
Timo Teras committed
324
325
326
327
328

		if (score < cand_score) {
			cand = t;
			cand_score = score;
		}
Linus Torvalds's avatar
Linus Torvalds committed
329
330
	}

Timo Teras's avatar
Timo Teras committed
331
332
	if (cand != NULL)
		return cand;
333

334
335
336
	dev = ign->fb_tunnel_dev;
	if (dev->flags & IFF_UP)
		return netdev_priv(dev);
337

Linus Torvalds's avatar
Linus Torvalds committed
338
339
340
	return NULL;
}

Eric Dumazet's avatar
Eric Dumazet committed
341
static struct ip_tunnel __rcu **__ipgre_bucket(struct ipgre_net *ign,
342
		struct ip_tunnel_parm *parms)
Linus Torvalds's avatar
Linus Torvalds committed
343
{
344
345
346
	__be32 remote = parms->iph.daddr;
	__be32 local = parms->iph.saddr;
	__be32 key = parms->i_key;
Eric Dumazet's avatar
Eric Dumazet committed
347
	unsigned int h = HASH(key);
Linus Torvalds's avatar
Linus Torvalds committed
348
349
350
351
	int prio = 0;

	if (local)
		prio |= 1;
352
	if (remote && !ipv4_is_multicast(remote)) {
Linus Torvalds's avatar
Linus Torvalds committed
353
354
355
356
		prio |= 2;
		h ^= HASH(remote);
	}

357
	return &ign->tunnels[prio][h];
Linus Torvalds's avatar
Linus Torvalds committed
358
359
}

Eric Dumazet's avatar
Eric Dumazet committed
360
static inline struct ip_tunnel __rcu **ipgre_bucket(struct ipgre_net *ign,
361
		struct ip_tunnel *t)
362
{
363
	return __ipgre_bucket(ign, &t->parms);
364
365
}

366
static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t)
Linus Torvalds's avatar
Linus Torvalds committed
367
{
Eric Dumazet's avatar
Eric Dumazet committed
368
	struct ip_tunnel __rcu **tp = ipgre_bucket(ign, t);
Linus Torvalds's avatar
Linus Torvalds committed
369

Eric Dumazet's avatar
Eric Dumazet committed
370
	rcu_assign_pointer(t->next, rtnl_dereference(*tp));
371
	rcu_assign_pointer(*tp, t);
Linus Torvalds's avatar
Linus Torvalds committed
372
373
}

374
static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
Linus Torvalds's avatar
Linus Torvalds committed
375
{
Eric Dumazet's avatar
Eric Dumazet committed
376
377
378
379
380
381
382
383
	struct ip_tunnel __rcu **tp;
	struct ip_tunnel *iter;

	for (tp = ipgre_bucket(ign, t);
	     (iter = rtnl_dereference(*tp)) != NULL;
	     tp = &iter->next) {
		if (t == iter) {
			rcu_assign_pointer(*tp, t->next);
Linus Torvalds's avatar
Linus Torvalds committed
384
385
386
387
388
			break;
		}
	}
}

389
390
391
static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
					   struct ip_tunnel_parm *parms,
					   int type)
Linus Torvalds's avatar
Linus Torvalds committed
392
{
Al Viro's avatar
Al Viro committed
393
394
395
	__be32 remote = parms->iph.daddr;
	__be32 local = parms->iph.saddr;
	__be32 key = parms->i_key;
396
	int link = parms->link;
Eric Dumazet's avatar
Eric Dumazet committed
397
398
	struct ip_tunnel *t;
	struct ip_tunnel __rcu **tp;
399
400
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);

Eric Dumazet's avatar
Eric Dumazet committed
401
402
403
	for (tp = __ipgre_bucket(ign, parms);
	     (t = rtnl_dereference(*tp)) != NULL;
	     tp = &t->next)
404
405
406
		if (local == t->parms.iph.saddr &&
		    remote == t->parms.iph.daddr &&
		    key == t->parms.i_key &&
407
		    link == t->parms.link &&
408
409
410
411
412
413
		    type == t->dev->type)
			break;

	return t;
}

Eric Dumazet's avatar
Eric Dumazet committed
414
static struct ip_tunnel *ipgre_tunnel_locate(struct net *net,
415
416
417
		struct ip_tunnel_parm *parms, int create)
{
	struct ip_tunnel *t, *nt;
Linus Torvalds's avatar
Linus Torvalds committed
418
419
	struct net_device *dev;
	char name[IFNAMSIZ];
420
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
421

422
423
424
	t = ipgre_tunnel_find(net, parms, ARPHRD_IPGRE);
	if (t || !create)
		return t;
Linus Torvalds's avatar
Linus Torvalds committed
425
426
427

	if (parms->name[0])
		strlcpy(name, parms->name, IFNAMSIZ);
428
	else
stephen hemminger's avatar
stephen hemminger committed
429
		strcpy(name, "gre%d");
Linus Torvalds's avatar
Linus Torvalds committed
430
431
432

	dev = alloc_netdev(sizeof(*t), name, ipgre_tunnel_setup);
	if (!dev)
stephen hemminger's avatar
stephen hemminger committed
433
		return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
434

435
436
	dev_net_set(dev, net);

437
	nt = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
438
	nt->parms = *parms;
Herbert Xu's avatar
Herbert Xu committed
439
	dev->rtnl_link_ops = &ipgre_link_ops;
Linus Torvalds's avatar
Linus Torvalds committed
440

441
442
	dev->mtu = ipgre_tunnel_bind_dev(dev);

443
444
	if (register_netdevice(dev) < 0)
		goto failed_free;
Linus Torvalds's avatar
Linus Torvalds committed
445

446
447
448
449
	/* Can use a lockless transmit, unless we generate output sequences */
	if (!(nt->parms.o_flags & GRE_SEQ))
		dev->features |= NETIF_F_LLTX;

Linus Torvalds's avatar
Linus Torvalds committed
450
	dev_hold(dev);
451
	ipgre_tunnel_link(ign, nt);
Linus Torvalds's avatar
Linus Torvalds committed
452
453
	return nt;

454
455
failed_free:
	free_netdev(dev);
Linus Torvalds's avatar
Linus Torvalds committed
456
457
458
459
460
	return NULL;
}

static void ipgre_tunnel_uninit(struct net_device *dev)
{
461
462
463
464
	struct net *net = dev_net(dev);
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);

	ipgre_tunnel_unlink(ign, netdev_priv(dev));
Linus Torvalds's avatar
Linus Torvalds committed
465
466
467
468
469
470
471
	dev_put(dev);
}


static void ipgre_err(struct sk_buff *skb, u32 info)
{

472
/* All the routers (except for Linux) return only
Linus Torvalds's avatar
Linus Torvalds committed
473
474
475
476
477
478
479
480
   8 bytes of packet payload. It means, that precise relaying of
   ICMP in the real Internet is absolutely infeasible.

   Moreover, Cisco "wise men" put GRE key to the third word
   in GRE header. It makes impossible maintaining even soft state for keyed
   GRE tunnels with enabled checksum. Tell them "thank you".

   Well, I wonder, rfc1812 was written by Cisco employee,
481
482
   what the hell these idiots break standards established
   by themselves???
Linus Torvalds's avatar
Linus Torvalds committed
483
484
 */

485
	const struct iphdr *iph = (const struct iphdr *)skb->data;
Daniel Baluta's avatar
Daniel Baluta committed
486
	__be16	     *p = (__be16 *)(skb->data+(iph->ihl<<2));
Linus Torvalds's avatar
Linus Torvalds committed
487
	int grehlen = (iph->ihl<<2) + 4;
488
489
	const int type = icmp_hdr(skb)->type;
	const int code = icmp_hdr(skb)->code;
Linus Torvalds's avatar
Linus Torvalds committed
490
	struct ip_tunnel *t;
Al Viro's avatar
Al Viro committed
491
	__be16 flags;
Linus Torvalds's avatar
Linus Torvalds committed
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532

	flags = p[0];
	if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
		if (flags&(GRE_VERSION|GRE_ROUTING))
			return;
		if (flags&GRE_KEY) {
			grehlen += 4;
			if (flags&GRE_CSUM)
				grehlen += 4;
		}
	}

	/* If only 8 bytes returned, keyed message will be dropped here */
	if (skb_headlen(skb) < grehlen)
		return;

	switch (type) {
	default:
	case ICMP_PARAMETERPROB:
		return;

	case ICMP_DEST_UNREACH:
		switch (code) {
		case ICMP_SR_FAILED:
		case ICMP_PORT_UNREACH:
			/* Impossible event. */
			return;
		default:
			/* All others are translated to HOST_UNREACH.
			   rfc2003 contains "deep thoughts" about NET_UNREACH,
			   I believe they are just ether pollution. --ANK
			 */
			break;
		}
		break;
	case ICMP_TIME_EXCEEDED:
		if (code != ICMP_EXC_TTL)
			return;
		break;
	}

533
	rcu_read_lock();
534
	t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
535
536
537
				flags & GRE_KEY ?
				*(((__be32 *)p) + (grehlen / 4) - 1) : 0,
				p[1]);
538
539
540
541
542
543
544
545
546
547
	if (t == NULL)
		goto out;

	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
				 t->parms.link, 0, IPPROTO_GRE, 0);
		goto out;
	}

	if (t->parms.iph.daddr == 0 ||
548
	    ipv4_is_multicast(t->parms.iph.daddr))
Linus Torvalds's avatar
Linus Torvalds committed
549
550
551
552
553
		goto out;

	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
		goto out;

554
	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
Linus Torvalds's avatar
Linus Torvalds committed
555
556
557
558
559
		t->err_count++;
	else
		t->err_count = 1;
	t->err_time = jiffies;
out:
560
	rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
561
562
}

563
static inline void ipgre_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
564
565
566
{
	if (INET_ECN_is_ce(iph->tos)) {
		if (skb->protocol == htons(ETH_P_IP)) {
567
			IP_ECN_set_ce(ip_hdr(skb));
Linus Torvalds's avatar
Linus Torvalds committed
568
		} else if (skb->protocol == htons(ETH_P_IPV6)) {
569
			IP6_ECN_set_ce(ipv6_hdr(skb));
Linus Torvalds's avatar
Linus Torvalds committed
570
571
572
573
574
		}
	}
}

static inline u8
575
ipgre_ecn_encapsulate(u8 tos, const struct iphdr *old_iph, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
576
577
578
579
580
{
	u8 inner = 0;
	if (skb->protocol == htons(ETH_P_IP))
		inner = old_iph->tos;
	else if (skb->protocol == htons(ETH_P_IPV6))
581
		inner = ipv6_get_dsfield((const struct ipv6hdr *)old_iph);
Linus Torvalds's avatar
Linus Torvalds committed
582
583
584
585
586
	return INET_ECN_encapsulate(tos, inner);
}

static int ipgre_rcv(struct sk_buff *skb)
{
587
	const struct iphdr *iph;
Linus Torvalds's avatar
Linus Torvalds committed
588
	u8     *h;
Al Viro's avatar
Al Viro committed
589
	__be16    flags;
590
	__sum16   csum = 0;
Al Viro's avatar
Al Viro committed
591
	__be32 key = 0;
Linus Torvalds's avatar
Linus Torvalds committed
592
593
594
	u32    seqno = 0;
	struct ip_tunnel *tunnel;
	int    offset = 4;
595
	__be16 gre_proto;
Linus Torvalds's avatar
Linus Torvalds committed
596
597
598
599

	if (!pskb_may_pull(skb, 16))
		goto drop_nolock;

600
	iph = ip_hdr(skb);
Linus Torvalds's avatar
Linus Torvalds committed
601
	h = skb->data;
Daniel Baluta's avatar
Daniel Baluta committed
602
	flags = *(__be16 *)h;
Linus Torvalds's avatar
Linus Torvalds committed
603
604
605
606
607
608
609
610
611

	if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) {
		/* - Version must be 0.
		   - We do not support routing headers.
		 */
		if (flags&(GRE_VERSION|GRE_ROUTING))
			goto drop_nolock;

		if (flags&GRE_CSUM) {
612
			switch (skb->ip_summed) {
613
			case CHECKSUM_COMPLETE:
614
				csum = csum_fold(skb->csum);
615
616
617
618
619
620
				if (!csum)
					break;
				/* fall through */
			case CHECKSUM_NONE:
				skb->csum = 0;
				csum = __skb_checksum_complete(skb);
621
				skb->ip_summed = CHECKSUM_COMPLETE;
Linus Torvalds's avatar
Linus Torvalds committed
622
623
624
625
			}
			offset += 4;
		}
		if (flags&GRE_KEY) {
Daniel Baluta's avatar
Daniel Baluta committed
626
			key = *(__be32 *)(h + offset);
Linus Torvalds's avatar
Linus Torvalds committed
627
628
629
			offset += 4;
		}
		if (flags&GRE_SEQ) {
Daniel Baluta's avatar
Daniel Baluta committed
630
			seqno = ntohl(*(__be32 *)(h + offset));
Linus Torvalds's avatar
Linus Torvalds committed
631
632
633
634
			offset += 4;
		}
	}

635
636
	gre_proto = *(__be16 *)(h + 2);

637
	rcu_read_lock();
638
	if ((tunnel = ipgre_tunnel_lookup(skb->dev,
639
640
					  iph->saddr, iph->daddr, key,
					  gre_proto))) {
Eric Dumazet's avatar
Eric Dumazet committed
641
		struct pcpu_tstats *tstats;
642

Linus Torvalds's avatar
Linus Torvalds committed
643
644
		secpath_reset(skb);

645
		skb->protocol = gre_proto;
Linus Torvalds's avatar
Linus Torvalds committed
646
647
648
649
		/* WCCP version 1 and 2 protocol decoding.
		 * - Change protocol to IP
		 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
		 */
650
		if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) {
651
			skb->protocol = htons(ETH_P_IP);
652
			if ((*(h + offset) & 0xF0) != 0x40)
Linus Torvalds's avatar
Linus Torvalds committed
653
654
655
				offset += 4;
		}

656
		skb->mac_header = skb->network_header;
657
		__pskb_pull(skb, offset);
658
		skb_postpull_rcsum(skb, skb_transport_header(skb), offset);
Linus Torvalds's avatar
Linus Torvalds committed
659
660
		skb->pkt_type = PACKET_HOST;
#ifdef CONFIG_NET_IPGRE_BROADCAST
661
		if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds's avatar
Linus Torvalds committed
662
			/* Looped back packet, drop it! */
663
			if (rt_is_output_route(skb_rtable(skb)))
Linus Torvalds's avatar
Linus Torvalds committed
664
				goto drop;
Eric Dumazet's avatar
Eric Dumazet committed
665
			tunnel->dev->stats.multicast++;
Linus Torvalds's avatar
Linus Torvalds committed
666
667
668
669
670
671
			skb->pkt_type = PACKET_BROADCAST;
		}
#endif

		if (((flags&GRE_CSUM) && csum) ||
		    (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) {
Eric Dumazet's avatar
Eric Dumazet committed
672
673
			tunnel->dev->stats.rx_crc_errors++;
			tunnel->dev->stats.rx_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
674
675
676
677
678
			goto drop;
		}
		if (tunnel->parms.i_flags&GRE_SEQ) {
			if (!(flags&GRE_SEQ) ||
			    (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) {
Eric Dumazet's avatar
Eric Dumazet committed
679
680
				tunnel->dev->stats.rx_fifo_errors++;
				tunnel->dev->stats.rx_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
681
682
683
684
				goto drop;
			}
			tunnel->i_seqno = seqno + 1;
		}
685
686
687
688

		/* Warning: All skb pointers will be invalidated! */
		if (tunnel->dev->type == ARPHRD_ETHER) {
			if (!pskb_may_pull(skb, ETH_HLEN)) {
Eric Dumazet's avatar
Eric Dumazet committed
689
690
				tunnel->dev->stats.rx_length_errors++;
				tunnel->dev->stats.rx_errors++;
691
692
693
694
695
696
697
698
				goto drop;
			}

			iph = ip_hdr(skb);
			skb->protocol = eth_type_trans(skb, tunnel->dev);
			skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
		}

Eric Dumazet's avatar
Eric Dumazet committed
699
		tstats = this_cpu_ptr(tunnel->dev->tstats);
700
		u64_stats_update_begin(&tstats->syncp);
Eric Dumazet's avatar
Eric Dumazet committed
701
702
		tstats->rx_packets++;
		tstats->rx_bytes += skb->len;
703
		u64_stats_update_end(&tstats->syncp);
Eric Dumazet's avatar
Eric Dumazet committed
704
705

		__skb_tunnel_rx(skb, tunnel->dev);
706
707

		skb_reset_network_header(skb);
Linus Torvalds's avatar
Linus Torvalds committed
708
		ipgre_ecn_decapsulate(iph, skb);
709

710
		netif_rx(skb);
Eric Dumazet's avatar
Eric Dumazet committed
711

712
		rcu_read_unlock();
Eric Dumazet's avatar
Eric Dumazet committed
713
		return 0;
Linus Torvalds's avatar
Linus Torvalds committed
714
	}
715
	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
Linus Torvalds's avatar
Linus Torvalds committed
716
717

drop:
718
	rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
719
720
drop_nolock:
	kfree_skb(skb);
Eric Dumazet's avatar
Eric Dumazet committed
721
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
722
723
}

724
static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
725
{
726
	struct ip_tunnel *tunnel = netdev_priv(dev);
Eric Dumazet's avatar
Eric Dumazet committed
727
	struct pcpu_tstats *tstats;
728
729
	const struct iphdr  *old_iph = ip_hdr(skb);
	const struct iphdr  *tiph;
730
	struct flowi4 fl4;
Linus Torvalds's avatar
Linus Torvalds committed
731
	u8     tos;
Al Viro's avatar
Al Viro committed
732
	__be16 df;
Linus Torvalds's avatar
Linus Torvalds committed
733
	struct rtable *rt;     			/* Route to the other host */
Eric Dumazet's avatar
Eric Dumazet committed
734
	struct net_device *tdev;		/* Device to other host */
Linus Torvalds's avatar
Linus Torvalds committed
735
	struct iphdr  *iph;			/* Our new IP header */
736
	unsigned int max_headroom;		/* The extra header space needed */
Linus Torvalds's avatar
Linus Torvalds committed
737
	int    gre_hlen;
Al Viro's avatar
Al Viro committed
738
	__be32 dst;
Linus Torvalds's avatar
Linus Torvalds committed
739
740
	int    mtu;

741
742
743
744
	if (dev->type == ARPHRD_ETHER)
		IPCB(skb)->flags = 0;

	if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
Linus Torvalds's avatar
Linus Torvalds committed
745
		gre_hlen = 0;
746
		tiph = (const struct iphdr *)skb->data;
Linus Torvalds's avatar
Linus Torvalds committed
747
748
749
750
751
752
753
754
	} else {
		gre_hlen = tunnel->hlen;
		tiph = &tunnel->parms.iph;
	}

	if ((dst = tiph->daddr) == 0) {
		/* NBMA tunnel */

Eric Dumazet's avatar
Eric Dumazet committed
755
		if (skb_dst(skb) == NULL) {
Eric Dumazet's avatar
Eric Dumazet committed
756
			dev->stats.tx_fifo_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
757
758
759
			goto tx_error;
		}

760
		if (skb->protocol == htons(ETH_P_IP)) {
Eric Dumazet's avatar
Eric Dumazet committed
761
			rt = skb_rtable(skb);
762
763
			dst = rt->rt_gateway;
		}
764
#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds's avatar
Linus Torvalds committed
765
		else if (skb->protocol == htons(ETH_P_IPV6)) {
766
			const struct in6_addr *addr6;
767
768
			struct neighbour *neigh;
			bool do_tx_error_icmp;
Linus Torvalds's avatar
Linus Torvalds committed
769
770
			int addr_type;

771
			neigh = dst_neigh_lookup(skb_dst(skb), &ipv6_hdr(skb)->daddr);
Linus Torvalds's avatar
Linus Torvalds committed
772
773
774
			if (neigh == NULL)
				goto tx_error;

775
			addr6 = (const struct in6_addr *)&neigh->primary_key;
Linus Torvalds's avatar
Linus Torvalds committed
776
777
778
			addr_type = ipv6_addr_type(addr6);

			if (addr_type == IPV6_ADDR_ANY) {
779
				addr6 = &ipv6_hdr(skb)->daddr;
Linus Torvalds's avatar
Linus Torvalds committed
780
781
782
783
				addr_type = ipv6_addr_type(addr6);
			}

			if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
784
785
786
787
788
789
790
				do_tx_error_icmp = true;
			else {
				do_tx_error_icmp = false;
				dst = addr6->s6_addr32[3];
			}
			neigh_release(neigh);
			if (do_tx_error_icmp)
Linus Torvalds's avatar
Linus Torvalds committed
791
792
793
794
795
796
797
798
				goto tx_error_icmp;
		}
#endif
		else
			goto tx_error;
	}

	tos = tiph->tos;
799
800
	if (tos == 1) {
		tos = 0;
Linus Torvalds's avatar
Linus Torvalds committed
801
802
		if (skb->protocol == htons(ETH_P_IP))
			tos = old_iph->tos;
803
		else if (skb->protocol == htons(ETH_P_IPV6))
804
			tos = ipv6_get_dsfield((const struct ipv6hdr *)old_iph);
Linus Torvalds's avatar
Linus Torvalds committed
805
806
	}

807
	rt = ip_route_output_gre(dev_net(dev), &fl4, dst, tiph->saddr,
808
809
810
811
812
				 tunnel->parms.o_key, RT_TOS(tos),
				 tunnel->parms.link);
	if (IS_ERR(rt)) {
		dev->stats.tx_carrier_errors++;
		goto tx_error;
Linus Torvalds's avatar
Linus Torvalds committed
813
	}
814
	tdev = rt->dst.dev;
Linus Torvalds's avatar
Linus Torvalds committed
815
816
817

	if (tdev == dev) {
		ip_rt_put(rt);
Eric Dumazet's avatar
Eric Dumazet committed
818
		dev->stats.collisions++;
Linus Torvalds's avatar
Linus Torvalds committed
819
820
821
822
823
		goto tx_error;
	}

	df = tiph->frag_off;
	if (df)
824
		mtu = dst_mtu(&rt->dst) - dev->hard_header_len - tunnel->hlen;
Linus Torvalds's avatar
Linus Torvalds committed
825
	else
Eric Dumazet's avatar
Eric Dumazet committed
826
		mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
Linus Torvalds's avatar
Linus Torvalds committed
827

Eric Dumazet's avatar
Eric Dumazet committed
828
829
	if (skb_dst(skb))
		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
Linus Torvalds's avatar
Linus Torvalds committed
830
831
832
833
834
835
836
837
838
839
840

	if (skb->protocol == htons(ETH_P_IP)) {
		df |= (old_iph->frag_off&htons(IP_DF));

		if ((old_iph->frag_off&htons(IP_DF)) &&
		    mtu < ntohs(old_iph->tot_len)) {
			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
			ip_rt_put(rt);
			goto tx_error;
		}
	}
841
#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds's avatar
Linus Torvalds committed
842
	else if (skb->protocol == htons(ETH_P_IPV6)) {
Eric Dumazet's avatar
Eric Dumazet committed
843
		struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
Linus Torvalds's avatar
Linus Torvalds committed
844

Eric Dumazet's avatar
Eric Dumazet committed
845
		if (rt6 && mtu < dst_mtu(skb_dst(skb)) && mtu >= IPV6_MIN_MTU) {
846
847
			if ((tunnel->parms.iph.daddr &&
			     !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
Linus Torvalds's avatar
Linus Torvalds committed
848
849
			    rt6->rt6i_dst.plen == 128) {
				rt6->rt6i_flags |= RTF_MODIFIED;
850
				dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
Linus Torvalds's avatar
Linus Torvalds committed
851
852
853
854
			}
		}

		if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) {
855
			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
Linus Torvalds's avatar
Linus Torvalds committed
856
857
858
859
860
861
862
			ip_rt_put(rt);
			goto tx_error;
		}
	}
#endif

	if (tunnel->err_count > 0) {
863
864
		if (time_before(jiffies,
				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
Linus Torvalds's avatar
Linus Torvalds committed
865
866
867
868
869
870
871
			tunnel->err_count--;

			dst_link_failure(skb);
		} else
			tunnel->err_count = 0;
	}

872
	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + rt->dst.header_len;
Linus Torvalds's avatar
Linus Torvalds committed
873

874
875
	if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
Linus Torvalds's avatar
Linus Torvalds committed
876
		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
877
878
		if (max_headroom > dev->needed_headroom)
			dev->needed_headroom = max_headroom;
Linus Torvalds's avatar
Linus Torvalds committed
879
880
		if (!new_skb) {
			ip_rt_put(rt);
Eric Dumazet's avatar
Eric Dumazet committed
881
			dev->stats.tx_dropped++;
Linus Torvalds's avatar
Linus Torvalds committed
882
			dev_kfree_skb(skb);
883
			return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
884
885
886
887
888
		}
		if (skb->sk)
			skb_set_owner_w(new_skb, skb->sk);
		dev_kfree_skb(skb);
		skb = new_skb;
889
		old_iph = ip_hdr(skb);
Linus Torvalds's avatar
Linus Torvalds committed
890
891
	}

892
	skb_reset_transport_header(skb);
893
894
	skb_push(skb, gre_hlen);
	skb_reset_network_header(skb);
Linus Torvalds's avatar
Linus Torvalds committed
895
	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
896
897
	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
			      IPSKB_REROUTED);
Eric Dumazet's avatar
Eric Dumazet committed
898
	skb_dst_drop(skb);
899
	skb_dst_set(skb, &rt->dst);
Linus Torvalds's avatar
Linus Torvalds committed
900
901
902
903
904

	/*
	 *	Push down and install the IPIP header.
	 */

905
	iph 			=	ip_hdr(skb);
Linus Torvalds's avatar
Linus Torvalds committed
906
907
908
909
910
	iph->version		=	4;
	iph->ihl		=	sizeof(struct iphdr) >> 2;
	iph->frag_off		=	df;
	iph->protocol		=	IPPROTO_GRE;
	iph->tos		=	ipgre_ecn_encapsulate(tos, old_iph, skb);
911
912
	iph->daddr		=	fl4.daddr;
	iph->saddr		=	fl4.saddr;
Linus Torvalds's avatar
Linus Torvalds committed
913
914
915
916

	if ((iph->ttl = tiph->ttl) == 0) {
		if (skb->protocol == htons(ETH_P_IP))
			iph->ttl = old_iph->ttl;
917
#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds's avatar
Linus Torvalds committed
918
		else if (skb->protocol == htons(ETH_P_IPV6))
919
			iph->ttl = ((const struct ipv6hdr *)old_iph)->hop_limit;
Linus Torvalds's avatar
Linus Torvalds committed
920
921
#endif
		else
922
			iph->ttl = ip4_dst_hoplimit(&rt->dst);
Linus Torvalds's avatar
Linus Torvalds committed
923
924
	}

925
926
927
	((__be16 *)(iph + 1))[0] = tunnel->parms.o_flags;
	((__be16 *)(iph + 1))[1] = (dev->type == ARPHRD_ETHER) ?
				   htons(ETH_P_TEB) : skb->protocol;
Linus Torvalds's avatar
Linus Torvalds committed
928
929

	if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) {
Daniel Baluta's avatar
Daniel Baluta committed
930
		__be32 *ptr = (__be32 *)(((u8 *)iph) + tunnel->hlen - 4);
Linus Torvalds's avatar
Linus Torvalds committed
931
932
933
934
935
936
937
938
939
940
941
942

		if (tunnel->parms.o_flags&GRE_SEQ) {
			++tunnel->o_seqno;
			*ptr = htonl(tunnel->o_seqno);
			ptr--;
		}
		if (tunnel->parms.o_flags&GRE_KEY) {
			*ptr = tunnel->parms.o_key;
			ptr--;
		}
		if (tunnel->parms.o_flags&GRE_CSUM) {
			*ptr = 0;
Daniel Baluta's avatar
Daniel Baluta committed
943
			*(__sum16 *)ptr = ip_compute_csum((void *)(iph+1), skb->len - sizeof(struct iphdr));
Linus Torvalds's avatar
Linus Torvalds committed
944
945
946
947
		}
	}

	nf_reset(skb);
Eric Dumazet's avatar
Eric Dumazet committed
948
949
	tstats = this_cpu_ptr(dev->tstats);
	__IPTUNNEL_XMIT(tstats, &dev->stats);
950
	return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
951

952
#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds's avatar
Linus Torvalds committed
953
954
tx_error_icmp:
	dst_link_failure(skb);
955
#endif
Linus Torvalds's avatar
Linus Torvalds committed
956
tx_error:
Eric Dumazet's avatar
Eric Dumazet committed
957
	dev->stats.tx_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
958
	dev_kfree_skb(skb);
959
	return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
960
961
}

962
static int ipgre_tunnel_bind_dev(struct net_device *dev)
963
964
965
{
	struct net_device *tdev = NULL;
	struct ip_tunnel *tunnel;
966
	const struct iphdr *iph;
967
968
969
970
971
972
973
	int hlen = LL_MAX_HEADER;
	int mtu = ETH_DATA_LEN;
	int addend = sizeof(struct iphdr) + 4;

	tunnel = netdev_priv(dev);
	iph = &tunnel->parms.iph;

Herbert Xu's avatar
Herbert Xu committed
974
	/* Guess output device to choose reasonable mtu and needed_headroom */
975
976

	if (iph->daddr) {
977
978
979
980
981
982
983
984
		struct flowi4 fl4;
		struct rtable *rt;

		rt = ip_route_output_gre(dev_net(dev), &fl4,
					 iph->daddr, iph->saddr,
					 tunnel->parms.o_key,
					 RT_TOS(iph->tos),
					 tunnel->parms.link);
985
		if (!IS_ERR(rt)) {
986
			tdev = rt->dst.dev;
987
988
			ip_rt_put(rt);
		}
989
990
991

		if (dev->type != ARPHRD_ETHER)
			dev->flags |= IFF_POINTOPOINT;
992
993
994
	}

	if (!tdev && tunnel->parms.link)
995
		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
996
997

	if (tdev) {
Herbert Xu's avatar
Herbert Xu committed
998
		hlen = tdev->hard_header_len + tdev->needed_headroom;
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
		mtu = tdev->mtu;
	}
	dev->iflink = tunnel->parms.link;

	/* Precalculate GRE options length */
	if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
		if (tunnel->parms.o_flags&GRE_CSUM)
			addend += 4;
		if (tunnel->parms.o_flags&GRE_KEY)
			addend += 4;
		if (tunnel->parms.o_flags&GRE_SEQ)
			addend += 4;
	}
Herbert Xu's avatar
Herbert Xu committed
1012
	dev->needed_headroom = addend + hlen;
1013
	mtu -= dev->hard_header_len + addend;
1014
1015
1016
1017

	if (mtu < 68)
		mtu = 68;

1018
1019
	tunnel->hlen = addend;

1020
	return mtu;
1021
1022
}

Linus Torvalds's avatar
Linus Torvalds committed
1023
1024
1025
1026
1027
1028
static int
ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
{
	int err = 0;
	struct ip_tunnel_parm p;
	struct ip_tunnel *t;
1029
1030
	struct net *net = dev_net(dev);
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
1031
1032
1033
1034

	switch (cmd) {
	case SIOCGETTUNNEL:
		t = NULL;
1035
		if (dev == ign->fb_tunnel_dev) {
Linus Torvalds's avatar
Linus Torvalds committed
1036
1037
1038
1039
			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
				err = -EFAULT;
				break;
			}
1040
			t = ipgre_tunnel_locate(net, &p, 0);
Linus Torvalds's avatar
Linus Torvalds committed
1041
1042
		}
		if (t == NULL)
1043
			t = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
		memcpy(&p, &t->parms, sizeof(p));
		if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
			err = -EFAULT;
		break;

	case SIOCADDTUNNEL:
	case SIOCCHGTUNNEL:
		err = -EPERM;
		if (!capable(CAP_NET_ADMIN))
			goto done;

		err = -EFAULT;
		if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
			goto done;

		err = -EINVAL;
		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
		    ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
			goto done;
		if (p.iph.ttl)
			p.iph.frag_off |= htons(IP_DF);

		if (!(p.i_flags&GRE_KEY))
			p.i_key = 0;
		if (!(p.o_flags&GRE_KEY))
			p.o_key = 0;

1072
		t = ipgre_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
Linus Torvalds's avatar
Linus Torvalds committed
1073

1074
		if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
Linus Torvalds's avatar
Linus Torvalds committed
1075
1076
1077
1078
1079
1080
			if (t != NULL) {
				if (t->dev != dev) {
					err = -EEXIST;
					break;
				}
			} else {
Eric Dumazet's avatar
Eric Dumazet committed
1081
				unsigned int nflags = 0;
Linus Torvalds's avatar
Linus Torvalds committed
1082

1083
				t = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
1084

1085
				if (ipv4_is_multicast(p.iph.daddr))
Linus Torvalds's avatar
Linus Torvalds committed
1086
1087
1088
1089
1090
1091
1092
1093
					nflags = IFF_BROADCAST;
				else if (p.iph.daddr)
					nflags = IFF_POINTOPOINT;

				if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
					err = -EINVAL;
					break;
				}
1094
				ipgre_tunnel_unlink(ign, t);
1095
				synchronize_net();
Linus Torvalds's avatar
Linus Torvalds committed
1096
1097
1098
1099
1100
1101
				t->parms.iph.saddr = p.iph.saddr;
				t->parms.iph.daddr = p.iph.daddr;
				t->parms.i_key = p.i_key;
				t->parms.o_key = p.o_key;
				memcpy(dev->dev_addr, &p.iph.saddr, 4);
				memcpy(dev->broadcast, &p.iph.daddr, 4);
1102
				ipgre_tunnel_link(ign, t);
Linus Torvalds's avatar
Linus Torvalds committed
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
				netdev_state_change(dev);
			}
		<