ip_gre.c 40.7 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
#include <linux/capability.h>
Linus Torvalds's avatar
Linus Torvalds committed
14
15
16
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
17
#include <linux/slab.h>
Linus Torvalds's avatar
Linus Torvalds committed
18
19
20
21
22
23
24
25
26
27
28
29
30
#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>
31
#include <linux/etherdevice.h>
32
#include <linux/if_ether.h>
Linus Torvalds's avatar
Linus Torvalds committed
33
34
35
36
37
38
39
40
41
42
43

#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>
44
45
#include <net/net_namespace.h>
#include <net/netns/generic.h>
Herbert Xu's avatar
Herbert Xu committed
46
#include <net/rtnetlink.h>
Linus Torvalds's avatar
Linus Torvalds committed
47

48
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Linus Torvalds's avatar
Linus Torvalds committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#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),
   and silently drop packet when it expires. It is the best
   solution, but it supposes maintaing new variable in ALL
   skb, even if no tunneling is used.

70
   Current solution: HARD_TX_LOCK lock breaks dead loops.
Linus Torvalds's avatar
Linus Torvalds committed
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119



   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,
   taking into account fragmentation. TO be short, tt is not solution at all.

   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
   fastly degrades to value <68, where looping stops.
   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
120
static struct rtnl_link_ops ipgre_link_ops __read_mostly;
Linus Torvalds's avatar
Linus Torvalds committed
121
122
static int ipgre_tunnel_init(struct net_device *dev);
static void ipgre_tunnel_setup(struct net_device *dev);
123
static int ipgre_tunnel_bind_dev(struct net_device *dev);
Linus Torvalds's avatar
Linus Torvalds committed
124
125
126

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

127
128
#define HASH_SIZE  16

129
static int ipgre_net_id __read_mostly;
130
struct ipgre_net {
131
132
	struct ip_tunnel *tunnels[4][HASH_SIZE];

133
	struct net_device *fb_tunnel_dev;
134
135
};

Linus Torvalds's avatar
Linus Torvalds committed
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* 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
154
#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
Linus Torvalds's avatar
Linus Torvalds committed
155

156
157
158
159
#define tunnels_r_l	tunnels[3]
#define tunnels_r	tunnels[2]
#define tunnels_l	tunnels[1]
#define tunnels_wc	tunnels[0]
160
161
162
163
/*
 * Locking : hash tables are protected by RCU and a spinlock
 */
static DEFINE_SPINLOCK(ipgre_lock);
Linus Torvalds's avatar
Linus Torvalds committed
164

165
166
#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
167
168
169

/* Given src, dst and key, find appropriate for input tunnel. */

170
static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
171
172
					      __be32 remote, __be32 local,
					      __be32 key, __be16 gre_proto)
Linus Torvalds's avatar
Linus Torvalds committed
173
{
174
175
	struct net *net = dev_net(dev);
	int link = dev->ifindex;
Linus Torvalds's avatar
Linus Torvalds committed
176
177
	unsigned h0 = HASH(remote);
	unsigned h1 = HASH(key);
Timo Teras's avatar
Timo Teras committed
178
	struct ip_tunnel *t, *cand = NULL;
179
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
180
181
	int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
		       ARPHRD_ETHER : ARPHRD_IPGRE;
Timo Teras's avatar
Timo Teras committed
182
	int score, cand_score = 4;
Linus Torvalds's avatar
Linus Torvalds committed
183

184
	for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) {
185
186
187
188
189
190
191
192
193
194
		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
195
		score = 0;
196
		if (t->parms.link != link)
Timo Teras's avatar
Timo Teras committed
197
			score |= 1;
198
		if (t->dev->type != dev_type)
Timo Teras's avatar
Timo Teras committed
199
200
			score |= 2;
		if (score == 0)
201
			return t;
Timo Teras's avatar
Timo Teras committed
202
203
204
205
206

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

209
	for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) {
210
211
212
213
214
215
216
217
218
		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
219
		score = 0;
220
		if (t->parms.link != link)
Timo Teras's avatar
Timo Teras committed
221
			score |= 1;
222
		if (t->dev->type != dev_type)
Timo Teras's avatar
Timo Teras committed
223
224
			score |= 2;
		if (score == 0)
225
			return t;
Timo Teras's avatar
Timo Teras committed
226
227
228
229
230

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

233
	for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) {
234
235
236
237
238
239
240
241
242
243
244
		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
245
		score = 0;
246
		if (t->parms.link != link)
Timo Teras's avatar
Timo Teras committed
247
			score |= 1;
248
		if (t->dev->type != dev_type)
Timo Teras's avatar
Timo Teras committed
249
250
			score |= 2;
		if (score == 0)
251
			return t;
Timo Teras's avatar
Timo Teras committed
252
253
254
255
256

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

259
	for_each_ip_tunnel_rcu(ign->tunnels_wc[h1]) {
260
261
262
263
264
265
266
267
		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
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
	}

Timo Teras's avatar
Timo Teras committed
282
283
	if (cand != NULL)
		return cand;
284

285
286
287
	dev = ign->fb_tunnel_dev;
	if (dev->flags & IFF_UP)
		return netdev_priv(dev);
288

Linus Torvalds's avatar
Linus Torvalds committed
289
290
291
	return NULL;
}

292
293
static struct ip_tunnel **__ipgre_bucket(struct ipgre_net *ign,
		struct ip_tunnel_parm *parms)
Linus Torvalds's avatar
Linus Torvalds committed
294
{
295
296
297
	__be32 remote = parms->iph.daddr;
	__be32 local = parms->iph.saddr;
	__be32 key = parms->i_key;
Linus Torvalds's avatar
Linus Torvalds committed
298
299
300
301
302
	unsigned h = HASH(key);
	int prio = 0;

	if (local)
		prio |= 1;
303
	if (remote && !ipv4_is_multicast(remote)) {
Linus Torvalds's avatar
Linus Torvalds committed
304
305
306
307
		prio |= 2;
		h ^= HASH(remote);
	}

308
	return &ign->tunnels[prio][h];
Linus Torvalds's avatar
Linus Torvalds committed
309
310
}

311
312
static inline struct ip_tunnel **ipgre_bucket(struct ipgre_net *ign,
		struct ip_tunnel *t)
313
{
314
	return __ipgre_bucket(ign, &t->parms);
315
316
}

317
static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t)
Linus Torvalds's avatar
Linus Torvalds committed
318
{
319
	struct ip_tunnel **tp = ipgre_bucket(ign, t);
Linus Torvalds's avatar
Linus Torvalds committed
320

321
	spin_lock_bh(&ipgre_lock);
Linus Torvalds's avatar
Linus Torvalds committed
322
	t->next = *tp;
323
324
	rcu_assign_pointer(*tp, t);
	spin_unlock_bh(&ipgre_lock);
Linus Torvalds's avatar
Linus Torvalds committed
325
326
}

327
static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
Linus Torvalds's avatar
Linus Torvalds committed
328
329
330
{
	struct ip_tunnel **tp;

331
	for (tp = ipgre_bucket(ign, t); *tp; tp = &(*tp)->next) {
Linus Torvalds's avatar
Linus Torvalds committed
332
		if (t == *tp) {
333
			spin_lock_bh(&ipgre_lock);
Linus Torvalds's avatar
Linus Torvalds committed
334
			*tp = t->next;
335
			spin_unlock_bh(&ipgre_lock);
Linus Torvalds's avatar
Linus Torvalds committed
336
337
338
339
340
			break;
		}
	}
}

341
342
343
static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
					   struct ip_tunnel_parm *parms,
					   int type)
Linus Torvalds's avatar
Linus Torvalds committed
344
{
Al Viro's avatar
Al Viro committed
345
346
347
	__be32 remote = parms->iph.daddr;
	__be32 local = parms->iph.saddr;
	__be32 key = parms->i_key;
348
	int link = parms->link;
349
350
351
352
353
354
355
	struct ip_tunnel *t, **tp;
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);

	for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next)
		if (local == t->parms.iph.saddr &&
		    remote == t->parms.iph.daddr &&
		    key == t->parms.i_key &&
356
		    link == t->parms.link &&
357
358
359
360
361
362
363
364
365
366
		    type == t->dev->type)
			break;

	return t;
}

static struct ip_tunnel * ipgre_tunnel_locate(struct net *net,
		struct ip_tunnel_parm *parms, int create)
{
	struct ip_tunnel *t, *nt;
Linus Torvalds's avatar
Linus Torvalds committed
367
368
	struct net_device *dev;
	char name[IFNAMSIZ];
369
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
370

371
372
373
	t = ipgre_tunnel_find(net, parms, ARPHRD_IPGRE);
	if (t || !create)
		return t;
Linus Torvalds's avatar
Linus Torvalds committed
374
375
376

	if (parms->name[0])
		strlcpy(name, parms->name, IFNAMSIZ);
377
378
	else
		sprintf(name, "gre%%d");
Linus Torvalds's avatar
Linus Torvalds committed
379
380
381
382
383

	dev = alloc_netdev(sizeof(*t), name, ipgre_tunnel_setup);
	if (!dev)
	  return NULL;

384
385
	dev_net_set(dev, net);

386
387
388
389
390
	if (strchr(name, '%')) {
		if (dev_alloc_name(dev, name) < 0)
			goto failed_free;
	}

391
	nt = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
392
	nt->parms = *parms;
Herbert Xu's avatar
Herbert Xu committed
393
	dev->rtnl_link_ops = &ipgre_link_ops;
Linus Torvalds's avatar
Linus Torvalds committed
394

395
396
	dev->mtu = ipgre_tunnel_bind_dev(dev);

397
398
	if (register_netdevice(dev) < 0)
		goto failed_free;
Linus Torvalds's avatar
Linus Torvalds committed
399
400

	dev_hold(dev);
401
	ipgre_tunnel_link(ign, nt);
Linus Torvalds's avatar
Linus Torvalds committed
402
403
	return nt;

404
405
failed_free:
	free_netdev(dev);
Linus Torvalds's avatar
Linus Torvalds committed
406
407
408
409
410
	return NULL;
}

static void ipgre_tunnel_uninit(struct net_device *dev)
{
411
412
413
414
	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
415
416
417
418
419
420
421
	dev_put(dev);
}


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

422
/* All the routers (except for Linux) return only
Linus Torvalds's avatar
Linus Torvalds committed
423
424
425
426
427
428
429
430
431
432
433
434
   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,
   what the hell these idiots break standrads established
   by themself???
 */

435
	struct iphdr *iph = (struct iphdr *)skb->data;
Al Viro's avatar
Al Viro committed
436
	__be16	     *p = (__be16*)(skb->data+(iph->ihl<<2));
Linus Torvalds's avatar
Linus Torvalds committed
437
	int grehlen = (iph->ihl<<2) + 4;
438
439
	const int type = icmp_hdr(skb)->type;
	const int code = icmp_hdr(skb)->code;
Linus Torvalds's avatar
Linus Torvalds committed
440
	struct ip_tunnel *t;
Al Viro's avatar
Al Viro committed
441
	__be16 flags;
Linus Torvalds's avatar
Linus Torvalds committed
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485

	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;
		case ICMP_FRAG_NEEDED:
			/* Soft state for pmtu is maintained by IP core. */
			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;
	}

486
	rcu_read_lock();
487
	t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
488
489
490
				flags & GRE_KEY ?
				*(((__be32 *)p) + (grehlen / 4) - 1) : 0,
				p[1]);
491
492
	if (t == NULL || t->parms.iph.daddr == 0 ||
	    ipv4_is_multicast(t->parms.iph.daddr))
Linus Torvalds's avatar
Linus Torvalds committed
493
494
495
496
497
		goto out;

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

498
	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
Linus Torvalds's avatar
Linus Torvalds committed
499
500
501
502
503
		t->err_count++;
	else
		t->err_count = 1;
	t->err_time = jiffies;
out:
504
	rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
505
506
507
508
509
510
}

static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
{
	if (INET_ECN_is_ce(iph->tos)) {
		if (skb->protocol == htons(ETH_P_IP)) {
511
			IP_ECN_set_ce(ip_hdr(skb));
Linus Torvalds's avatar
Linus Torvalds committed
512
		} else if (skb->protocol == htons(ETH_P_IPV6)) {
513
			IP6_ECN_set_ce(ipv6_hdr(skb));
Linus Torvalds's avatar
Linus Torvalds committed
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
		}
	}
}

static inline u8
ipgre_ecn_encapsulate(u8 tos, struct iphdr *old_iph, struct sk_buff *skb)
{
	u8 inner = 0;
	if (skb->protocol == htons(ETH_P_IP))
		inner = old_iph->tos;
	else if (skb->protocol == htons(ETH_P_IPV6))
		inner = ipv6_get_dsfield((struct ipv6hdr *)old_iph);
	return INET_ECN_encapsulate(tos, inner);
}

static int ipgre_rcv(struct sk_buff *skb)
{
	struct iphdr *iph;
	u8     *h;
Al Viro's avatar
Al Viro committed
533
	__be16    flags;
534
	__sum16   csum = 0;
Al Viro's avatar
Al Viro committed
535
	__be32 key = 0;
Linus Torvalds's avatar
Linus Torvalds committed
536
537
538
	u32    seqno = 0;
	struct ip_tunnel *tunnel;
	int    offset = 4;
539
	__be16 gre_proto;
Linus Torvalds's avatar
Linus Torvalds committed
540
541
542
543

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

544
	iph = ip_hdr(skb);
Linus Torvalds's avatar
Linus Torvalds committed
545
	h = skb->data;
Al Viro's avatar
Al Viro committed
546
	flags = *(__be16*)h;
Linus Torvalds's avatar
Linus Torvalds committed
547
548
549
550
551
552
553
554
555

	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) {
556
			switch (skb->ip_summed) {
557
			case CHECKSUM_COMPLETE:
558
				csum = csum_fold(skb->csum);
559
560
561
562
563
564
				if (!csum)
					break;
				/* fall through */
			case CHECKSUM_NONE:
				skb->csum = 0;
				csum = __skb_checksum_complete(skb);
565
				skb->ip_summed = CHECKSUM_COMPLETE;
Linus Torvalds's avatar
Linus Torvalds committed
566
567
568
569
			}
			offset += 4;
		}
		if (flags&GRE_KEY) {
Al Viro's avatar
Al Viro committed
570
			key = *(__be32*)(h + offset);
Linus Torvalds's avatar
Linus Torvalds committed
571
572
573
			offset += 4;
		}
		if (flags&GRE_SEQ) {
Al Viro's avatar
Al Viro committed
574
			seqno = ntohl(*(__be32*)(h + offset));
Linus Torvalds's avatar
Linus Torvalds committed
575
576
577
578
			offset += 4;
		}
	}

579
580
	gre_proto = *(__be16 *)(h + 2);

581
	rcu_read_lock();
582
	if ((tunnel = ipgre_tunnel_lookup(skb->dev,
583
584
					  iph->saddr, iph->daddr, key,
					  gre_proto))) {
585
586
		struct net_device_stats *stats = &tunnel->dev->stats;

Linus Torvalds's avatar
Linus Torvalds committed
587
588
		secpath_reset(skb);

589
		skb->protocol = gre_proto;
Linus Torvalds's avatar
Linus Torvalds committed
590
591
592
593
		/* WCCP version 1 and 2 protocol decoding.
		 * - Change protocol to IP
		 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
		 */
594
		if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) {
595
			skb->protocol = htons(ETH_P_IP);
596
			if ((*(h + offset) & 0xF0) != 0x40)
Linus Torvalds's avatar
Linus Torvalds committed
597
598
599
				offset += 4;
		}

600
		skb->mac_header = skb->network_header;
601
		__pskb_pull(skb, offset);
602
		skb_postpull_rcsum(skb, skb_transport_header(skb), offset);
Linus Torvalds's avatar
Linus Torvalds committed
603
604
		skb->pkt_type = PACKET_HOST;
#ifdef CONFIG_NET_IPGRE_BROADCAST
605
		if (ipv4_is_multicast(iph->daddr)) {
Linus Torvalds's avatar
Linus Torvalds committed
606
			/* Looped back packet, drop it! */
Eric Dumazet's avatar
Eric Dumazet committed
607
			if (skb_rtable(skb)->fl.iif == 0)
Linus Torvalds's avatar
Linus Torvalds committed
608
				goto drop;
609
			stats->multicast++;
Linus Torvalds's avatar
Linus Torvalds committed
610
611
612
613
614
615
			skb->pkt_type = PACKET_BROADCAST;
		}
#endif

		if (((flags&GRE_CSUM) && csum) ||
		    (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) {
616
617
			stats->rx_crc_errors++;
			stats->rx_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
618
619
620
621
622
			goto drop;
		}
		if (tunnel->parms.i_flags&GRE_SEQ) {
			if (!(flags&GRE_SEQ) ||
			    (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) {
623
624
				stats->rx_fifo_errors++;
				stats->rx_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
625
626
627
628
				goto drop;
			}
			tunnel->i_seqno = seqno + 1;
		}
629
630
631
632
633
634
635
636
637
638
639
640
641
642

		/* Warning: All skb pointers will be invalidated! */
		if (tunnel->dev->type == ARPHRD_ETHER) {
			if (!pskb_may_pull(skb, ETH_HLEN)) {
				stats->rx_length_errors++;
				stats->rx_errors++;
				goto drop;
			}

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

643
		skb_tunnel_rx(skb, tunnel->dev);
644
645

		skb_reset_network_header(skb);
Linus Torvalds's avatar
Linus Torvalds committed
646
		ipgre_ecn_decapsulate(iph, skb);
647

Linus Torvalds's avatar
Linus Torvalds committed
648
		netif_rx(skb);
649
		rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
650
651
		return(0);
	}
652
	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
Linus Torvalds's avatar
Linus Torvalds committed
653
654

drop:
655
	rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
656
657
658
659
660
drop_nolock:
	kfree_skb(skb);
	return(0);
}

661
static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
662
{
663
	struct ip_tunnel *tunnel = netdev_priv(dev);
Eric Dumazet's avatar
Eric Dumazet committed
664
665
	struct net_device_stats *stats = &dev->stats;
	struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
666
	struct iphdr  *old_iph = ip_hdr(skb);
Linus Torvalds's avatar
Linus Torvalds committed
667
668
	struct iphdr  *tiph;
	u8     tos;
Al Viro's avatar
Al Viro committed
669
	__be16 df;
Linus Torvalds's avatar
Linus Torvalds committed
670
671
672
	struct rtable *rt;     			/* Route to the other host */
	struct net_device *tdev;			/* Device to other host */
	struct iphdr  *iph;			/* Our new IP header */
673
	unsigned int max_headroom;		/* The extra header space needed */
Linus Torvalds's avatar
Linus Torvalds committed
674
	int    gre_hlen;
Al Viro's avatar
Al Viro committed
675
	__be32 dst;
Linus Torvalds's avatar
Linus Torvalds committed
676
677
	int    mtu;

678
679
680
681
	if (dev->type == ARPHRD_ETHER)
		IPCB(skb)->flags = 0;

	if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
Linus Torvalds's avatar
Linus Torvalds committed
682
		gre_hlen = 0;
683
		tiph = (struct iphdr *)skb->data;
Linus Torvalds's avatar
Linus Torvalds committed
684
685
686
687
688
689
690
691
	} else {
		gre_hlen = tunnel->hlen;
		tiph = &tunnel->parms.iph;
	}

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

Eric Dumazet's avatar
Eric Dumazet committed
692
		if (skb_dst(skb) == NULL) {
693
			stats->tx_fifo_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
694
695
696
697
			goto tx_error;
		}

		if (skb->protocol == htons(ETH_P_IP)) {
Eric Dumazet's avatar
Eric Dumazet committed
698
			rt = skb_rtable(skb);
Linus Torvalds's avatar
Linus Torvalds committed
699
700
701
			if ((dst = rt->rt_gateway) == 0)
				goto tx_error_icmp;
		}
702
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Linus Torvalds's avatar
Linus Torvalds committed
703
704
705
		else if (skb->protocol == htons(ETH_P_IPV6)) {
			struct in6_addr *addr6;
			int addr_type;
Eric Dumazet's avatar
Eric Dumazet committed
706
			struct neighbour *neigh = skb_dst(skb)->neighbour;
Linus Torvalds's avatar
Linus Torvalds committed
707
708
709
710

			if (neigh == NULL)
				goto tx_error;

711
			addr6 = (struct in6_addr *)&neigh->primary_key;
Linus Torvalds's avatar
Linus Torvalds committed
712
713
714
			addr_type = ipv6_addr_type(addr6);

			if (addr_type == IPV6_ADDR_ANY) {
715
				addr6 = &ipv6_hdr(skb)->daddr;
Linus Torvalds's avatar
Linus Torvalds committed
716
717
718
719
720
721
722
723
724
725
726
727
728
729
				addr_type = ipv6_addr_type(addr6);
			}

			if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
				goto tx_error_icmp;

			dst = addr6->s6_addr32[3];
		}
#endif
		else
			goto tx_error;
	}

	tos = tiph->tos;
730
731
	if (tos == 1) {
		tos = 0;
Linus Torvalds's avatar
Linus Torvalds committed
732
733
		if (skb->protocol == htons(ETH_P_IP))
			tos = old_iph->tos;
734
735
		else if (skb->protocol == htons(ETH_P_IPV6))
			tos = ipv6_get_dsfield((struct ipv6hdr *)old_iph);
Linus Torvalds's avatar
Linus Torvalds committed
736
737
738
739
740
741
742
743
744
	}

	{
		struct flowi fl = { .oif = tunnel->parms.link,
				    .nl_u = { .ip4_u =
					      { .daddr = dst,
						.saddr = tiph->saddr,
						.tos = RT_TOS(tos) } },
				    .proto = IPPROTO_GRE };
745
		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
746
			stats->tx_carrier_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
747
748
749
			goto tx_error;
		}
	}
750
	tdev = rt->dst.dev;
Linus Torvalds's avatar
Linus Torvalds committed
751
752
753

	if (tdev == dev) {
		ip_rt_put(rt);
754
		stats->collisions++;
Linus Torvalds's avatar
Linus Torvalds committed
755
756
757
758
759
		goto tx_error;
	}

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

Eric Dumazet's avatar
Eric Dumazet committed
764
765
	if (skb_dst(skb))
		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
Linus Torvalds's avatar
Linus Torvalds committed
766
767
768
769
770
771
772
773
774
775
776

	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;
		}
	}
777
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Linus Torvalds's avatar
Linus Torvalds committed
778
	else if (skb->protocol == htons(ETH_P_IPV6)) {
Eric Dumazet's avatar
Eric Dumazet committed
779
		struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
Linus Torvalds's avatar
Linus Torvalds committed
780

Eric Dumazet's avatar
Eric Dumazet committed
781
		if (rt6 && mtu < dst_mtu(skb_dst(skb)) && mtu >= IPV6_MIN_MTU) {
782
783
			if ((tunnel->parms.iph.daddr &&
			     !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
Linus Torvalds's avatar
Linus Torvalds committed
784
785
			    rt6->rt6i_dst.plen == 128) {
				rt6->rt6i_flags |= RTF_MODIFIED;
Eric Dumazet's avatar
Eric Dumazet committed
786
				skb_dst(skb)->metrics[RTAX_MTU-1] = mtu;
Linus Torvalds's avatar
Linus Torvalds committed
787
788
789
790
			}
		}

		if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) {
791
			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
Linus Torvalds's avatar
Linus Torvalds committed
792
793
794
795
796
797
798
			ip_rt_put(rt);
			goto tx_error;
		}
	}
#endif

	if (tunnel->err_count > 0) {
799
800
		if (time_before(jiffies,
				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
Linus Torvalds's avatar
Linus Torvalds committed
801
802
803
804
805
806
807
			tunnel->err_count--;

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

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

810
811
	if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
Linus Torvalds's avatar
Linus Torvalds committed
812
		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
813
814
		if (max_headroom > dev->needed_headroom)
			dev->needed_headroom = max_headroom;
Linus Torvalds's avatar
Linus Torvalds committed
815
816
		if (!new_skb) {
			ip_rt_put(rt);
Eric Dumazet's avatar
Eric Dumazet committed
817
			txq->tx_dropped++;
Linus Torvalds's avatar
Linus Torvalds committed
818
			dev_kfree_skb(skb);
819
			return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
820
821
822
823
824
		}
		if (skb->sk)
			skb_set_owner_w(new_skb, skb->sk);
		dev_kfree_skb(skb);
		skb = new_skb;
825
		old_iph = ip_hdr(skb);
Linus Torvalds's avatar
Linus Torvalds committed
826
827
	}

828
	skb_reset_transport_header(skb);
829
830
	skb_push(skb, gre_hlen);
	skb_reset_network_header(skb);
Linus Torvalds's avatar
Linus Torvalds committed
831
	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
832
833
	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
			      IPSKB_REROUTED);
Eric Dumazet's avatar
Eric Dumazet committed
834
	skb_dst_drop(skb);
835
	skb_dst_set(skb, &rt->dst);
Linus Torvalds's avatar
Linus Torvalds committed
836
837
838
839
840

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

841
	iph 			=	ip_hdr(skb);
Linus Torvalds's avatar
Linus Torvalds committed
842
843
844
845
846
847
848
849
850
851
852
	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);
	iph->daddr		=	rt->rt_dst;
	iph->saddr		=	rt->rt_src;

	if ((iph->ttl = tiph->ttl) == 0) {
		if (skb->protocol == htons(ETH_P_IP))
			iph->ttl = old_iph->ttl;
853
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Linus Torvalds's avatar
Linus Torvalds committed
854
		else if (skb->protocol == htons(ETH_P_IPV6))
855
			iph->ttl = ((struct ipv6hdr *)old_iph)->hop_limit;
Linus Torvalds's avatar
Linus Torvalds committed
856
857
#endif
		else
858
			iph->ttl = dst_metric(&rt->dst, RTAX_HOPLIMIT);
Linus Torvalds's avatar
Linus Torvalds committed
859
860
	}

861
862
863
	((__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
864
865

	if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) {
Al Viro's avatar
Al Viro committed
866
		__be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4);
Linus Torvalds's avatar
Linus Torvalds committed
867
868
869
870
871
872
873
874
875
876
877
878

		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;
879
			*(__sum16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr));
Linus Torvalds's avatar
Linus Torvalds committed
880
881
882
883
884
885
		}
	}

	nf_reset(skb);

	IPTUNNEL_XMIT();
886
	return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
887
888
889
890
891
892
893

tx_error_icmp:
	dst_link_failure(skb);

tx_error:
	stats->tx_errors++;
	dev_kfree_skb(skb);
894
	return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
895
896
}

897
static int ipgre_tunnel_bind_dev(struct net_device *dev)
898
899
900
901
902
903
904
905
906
907
908
{
	struct net_device *tdev = NULL;
	struct ip_tunnel *tunnel;
	struct iphdr *iph;
	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
909
	/* Guess output device to choose reasonable mtu and needed_headroom */
910
911
912
913
914
915
916
917
918

	if (iph->daddr) {
		struct flowi fl = { .oif = tunnel->parms.link,
				    .nl_u = { .ip4_u =
					      { .daddr = iph->daddr,
						.saddr = iph->saddr,
						.tos = RT_TOS(iph->tos) } },
				    .proto = IPPROTO_GRE };
		struct rtable *rt;
919
		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
920
			tdev = rt->dst.dev;
921
922
			ip_rt_put(rt);
		}
923
924
925

		if (dev->type != ARPHRD_ETHER)
			dev->flags |= IFF_POINTOPOINT;
926
927
928
	}

	if (!tdev && tunnel->parms.link)
929
		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
930
931

	if (tdev) {
Herbert Xu's avatar
Herbert Xu committed
932
		hlen = tdev->hard_header_len + tdev->needed_headroom;
933
934
935
936
937
938
939
940
941
942
943
944
945
		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
946
	dev->needed_headroom = addend + hlen;
947
	mtu -= dev->hard_header_len + addend;
948
949
950
951

	if (mtu < 68)
		mtu = 68;

952
953
	tunnel->hlen = addend;

954
	return mtu;
955
956
}

Linus Torvalds's avatar
Linus Torvalds committed
957
958
959
960
961
962
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;
963
964
	struct net *net = dev_net(dev);
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
965
966
967
968

	switch (cmd) {
	case SIOCGETTUNNEL:
		t = NULL;
969
		if (dev == ign->fb_tunnel_dev) {
Linus Torvalds's avatar
Linus Torvalds committed
970
971
972
973
			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
				err = -EFAULT;
				break;
			}
974
			t = ipgre_tunnel_locate(net, &p, 0);
Linus Torvalds's avatar
Linus Torvalds committed
975
976
		}
		if (t == NULL)
977
			t = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
		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);