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

#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>
43
44
#include <net/net_namespace.h>
#include <net/netns/generic.h>
Herbert Xu's avatar
Herbert Xu committed
45
#include <net/rtnetlink.h>
Linus Torvalds's avatar
Linus Torvalds committed
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

#ifdef CONFIG_IPV6
#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.

69
   Current solution: t->recursion lock breaks dead loops. It looks
Linus Torvalds's avatar
Linus Torvalds committed
70
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
120
121
   like dev->tbusy flag, but I preferred new variable, because
   the semantics is different. One day, when hard_start_xmit
   will be multithreaded we will have to use skb->encapsulation.



   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
122
static struct rtnl_link_ops ipgre_link_ops __read_mostly;
Linus Torvalds's avatar
Linus Torvalds committed
123
124
static int ipgre_tunnel_init(struct net_device *dev);
static void ipgre_tunnel_setup(struct net_device *dev);
125
static int ipgre_tunnel_bind_dev(struct net_device *dev);
Linus Torvalds's avatar
Linus Torvalds committed
126
127
128

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

129
130
#define HASH_SIZE  16

131
132
static int ipgre_net_id;
struct ipgre_net {
133
134
	struct ip_tunnel *tunnels[4][HASH_SIZE];

135
	struct net_device *fb_tunnel_dev;
136
137
};

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

158
159
160
161
#define tunnels_r_l	tunnels[3]
#define tunnels_r	tunnels[2]
#define tunnels_l	tunnels[1]
#define tunnels_wc	tunnels[0]
Linus Torvalds's avatar
Linus Torvalds committed
162
163
164
165
166

static DEFINE_RWLOCK(ipgre_lock);

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

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

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

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

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

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

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

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

256
	for (t = ign->tunnels_wc[h1]; t; t = t->next) {
257
258
259
260
261
262
263
264
		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
265
		score = 0;
266
		if (t->parms.link != link)
Timo Teras's avatar
Timo Teras committed
267
			score |= 1;
268
		if (t->dev->type != dev_type)
Timo Teras's avatar
Timo Teras committed
269
270
			score |= 2;
		if (score == 0)
271
			return t;
Timo Teras's avatar
Timo Teras committed
272
273
274
275
276

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

Timo Teras's avatar
Timo Teras committed
279
280
	if (cand != NULL)
		return cand;
281

282
	if (ign->fb_tunnel_dev->flags & IFF_UP)
283
		return netdev_priv(ign->fb_tunnel_dev);
284

Linus Torvalds's avatar
Linus Torvalds committed
285
286
287
	return NULL;
}

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

	if (local)
		prio |= 1;
299
	if (remote && !ipv4_is_multicast(remote)) {
Linus Torvalds's avatar
Linus Torvalds committed
300
301
302
303
		prio |= 2;
		h ^= HASH(remote);
	}

304
	return &ign->tunnels[prio][h];
Linus Torvalds's avatar
Linus Torvalds committed
305
306
}

307
308
static inline struct ip_tunnel **ipgre_bucket(struct ipgre_net *ign,
		struct ip_tunnel *t)
309
{
310
	return __ipgre_bucket(ign, &t->parms);
311
312
}

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

	t->next = *tp;
	write_lock_bh(&ipgre_lock);
	*tp = t;
	write_unlock_bh(&ipgre_lock);
}

323
static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
Linus Torvalds's avatar
Linus Torvalds committed
324
325
326
{
	struct ip_tunnel **tp;

327
	for (tp = ipgre_bucket(ign, t); *tp; tp = &(*tp)->next) {
Linus Torvalds's avatar
Linus Torvalds committed
328
329
330
331
332
333
334
335
336
		if (t == *tp) {
			write_lock_bh(&ipgre_lock);
			*tp = t->next;
			write_unlock_bh(&ipgre_lock);
			break;
		}
	}
}

337
338
339
static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
					   struct ip_tunnel_parm *parms,
					   int type)
Linus Torvalds's avatar
Linus Torvalds committed
340
{
Al Viro's avatar
Al Viro committed
341
342
343
	__be32 remote = parms->iph.daddr;
	__be32 local = parms->iph.saddr;
	__be32 key = parms->i_key;
344
	int link = parms->link;
345
346
347
348
349
350
351
	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 &&
352
		    link == t->parms.link &&
353
354
355
356
357
358
359
360
361
362
		    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
363
364
	struct net_device *dev;
	char name[IFNAMSIZ];
365
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
366

367
368
369
	t = ipgre_tunnel_find(net, parms, ARPHRD_IPGRE);
	if (t || !create)
		return t;
Linus Torvalds's avatar
Linus Torvalds committed
370
371
372

	if (parms->name[0])
		strlcpy(name, parms->name, IFNAMSIZ);
373
374
	else
		sprintf(name, "gre%%d");
Linus Torvalds's avatar
Linus Torvalds committed
375
376
377
378
379

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

380
381
	dev_net_set(dev, net);

382
383
384
385
386
	if (strchr(name, '%')) {
		if (dev_alloc_name(dev, name) < 0)
			goto failed_free;
	}

387
	nt = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
388
	nt->parms = *parms;
Herbert Xu's avatar
Herbert Xu committed
389
	dev->rtnl_link_ops = &ipgre_link_ops;
Linus Torvalds's avatar
Linus Torvalds committed
390

391
392
	dev->mtu = ipgre_tunnel_bind_dev(dev);

393
394
	if (register_netdevice(dev) < 0)
		goto failed_free;
Linus Torvalds's avatar
Linus Torvalds committed
395
396

	dev_hold(dev);
397
	ipgre_tunnel_link(ign, nt);
Linus Torvalds's avatar
Linus Torvalds committed
398
399
	return nt;

400
401
failed_free:
	free_netdev(dev);
Linus Torvalds's avatar
Linus Torvalds committed
402
403
404
405
406
	return NULL;
}

static void ipgre_tunnel_uninit(struct net_device *dev)
{
407
408
409
410
	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
411
412
413
414
415
416
417
	dev_put(dev);
}


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

418
/* All the routers (except for Linux) return only
Linus Torvalds's avatar
Linus Torvalds committed
419
420
421
422
423
424
425
426
427
428
429
430
   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???
 */

431
	struct iphdr *iph = (struct iphdr *)skb->data;
Al Viro's avatar
Al Viro committed
432
	__be16	     *p = (__be16*)(skb->data+(iph->ihl<<2));
Linus Torvalds's avatar
Linus Torvalds committed
433
	int grehlen = (iph->ihl<<2) + 4;
434
435
	const int type = icmp_hdr(skb)->type;
	const int code = icmp_hdr(skb)->code;
Linus Torvalds's avatar
Linus Torvalds committed
436
	struct ip_tunnel *t;
Al Viro's avatar
Al Viro committed
437
	__be16 flags;
Linus Torvalds's avatar
Linus Torvalds committed
438
439
440
441
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

	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;
	}

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

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

494
	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
Linus Torvalds's avatar
Linus Torvalds committed
495
496
497
498
499
500
501
502
503
504
505
506
507
		t->err_count++;
	else
		t->err_count = 1;
	t->err_time = jiffies;
out:
	read_unlock(&ipgre_lock);
	return;
}

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)) {
508
			IP_ECN_set_ce(ip_hdr(skb));
Linus Torvalds's avatar
Linus Torvalds committed
509
		} else if (skb->protocol == htons(ETH_P_IPV6)) {
510
			IP6_ECN_set_ce(ipv6_hdr(skb));
Linus Torvalds's avatar
Linus Torvalds committed
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
		}
	}
}

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
530
	__be16    flags;
531
	__sum16   csum = 0;
Al Viro's avatar
Al Viro committed
532
	__be32 key = 0;
Linus Torvalds's avatar
Linus Torvalds committed
533
534
535
	u32    seqno = 0;
	struct ip_tunnel *tunnel;
	int    offset = 4;
536
	__be16 gre_proto;
537
	unsigned int len;
Linus Torvalds's avatar
Linus Torvalds committed
538
539
540
541

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

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

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

577
578
	gre_proto = *(__be16 *)(h + 2);

Linus Torvalds's avatar
Linus Torvalds committed
579
	read_lock(&ipgre_lock);
580
	if ((tunnel = ipgre_tunnel_lookup(skb->dev,
581
582
					  iph->saddr, iph->daddr, key,
					  gre_proto))) {
583
584
		struct net_device_stats *stats = &tunnel->dev->stats;

Linus Torvalds's avatar
Linus Torvalds committed
585
586
		secpath_reset(skb);

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

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

		if (((flags&GRE_CSUM) && csum) ||
		    (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) {
614
615
			stats->rx_crc_errors++;
			stats->rx_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
616
617
618
619
620
			goto drop;
		}
		if (tunnel->parms.i_flags&GRE_SEQ) {
			if (!(flags&GRE_SEQ) ||
			    (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) {
621
622
				stats->rx_fifo_errors++;
				stats->rx_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
623
624
625
626
				goto drop;
			}
			tunnel->i_seqno = seqno + 1;
		}
627

628
629
		len = skb->len;

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
		stats->rx_packets++;
644
		stats->rx_bytes += len;
Linus Torvalds's avatar
Linus Torvalds committed
645
		skb->dev = tunnel->dev;
Eric Dumazet's avatar
Eric Dumazet committed
646
		skb_dst_drop(skb);
Linus Torvalds's avatar
Linus Torvalds committed
647
		nf_reset(skb);
648
649

		skb_reset_network_header(skb);
Linus Torvalds's avatar
Linus Torvalds committed
650
		ipgre_ecn_decapsulate(iph, skb);
651

Linus Torvalds's avatar
Linus Torvalds committed
652
653
654
655
		netif_rx(skb);
		read_unlock(&ipgre_lock);
		return(0);
	}
656
	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
Linus Torvalds's avatar
Linus Torvalds committed
657
658
659
660
661
662
663
664

drop:
	read_unlock(&ipgre_lock);
drop_nolock:
	kfree_skb(skb);
	return(0);
}

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

	if (tunnel->recursion++) {
682
		stats->collisions++;
Linus Torvalds's avatar
Linus Torvalds committed
683
684
685
		goto tx_error;
	}

686
687
688
689
	if (dev->type == ARPHRD_ETHER)
		IPCB(skb)->flags = 0;

	if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
Linus Torvalds's avatar
Linus Torvalds committed
690
		gre_hlen = 0;
691
		tiph = (struct iphdr *)skb->data;
Linus Torvalds's avatar
Linus Torvalds committed
692
693
694
695
696
697
698
699
	} else {
		gre_hlen = tunnel->hlen;
		tiph = &tunnel->parms.iph;
	}

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

Eric Dumazet's avatar
Eric Dumazet committed
700
		if (skb_dst(skb) == NULL) {
701
			stats->tx_fifo_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
702
703
704
705
			goto tx_error;
		}

		if (skb->protocol == htons(ETH_P_IP)) {
Eric Dumazet's avatar
Eric Dumazet committed
706
			rt = skb_rtable(skb);
Linus Torvalds's avatar
Linus Torvalds committed
707
708
709
710
711
712
713
			if ((dst = rt->rt_gateway) == 0)
				goto tx_error_icmp;
		}
#ifdef CONFIG_IPV6
		else if (skb->protocol == htons(ETH_P_IPV6)) {
			struct in6_addr *addr6;
			int addr_type;
Eric Dumazet's avatar
Eric Dumazet committed
714
			struct neighbour *neigh = skb_dst(skb)->neighbour;
Linus Torvalds's avatar
Linus Torvalds committed
715
716
717
718

			if (neigh == NULL)
				goto tx_error;

719
			addr6 = (struct in6_addr *)&neigh->primary_key;
Linus Torvalds's avatar
Linus Torvalds committed
720
721
722
			addr_type = ipv6_addr_type(addr6);

			if (addr_type == IPV6_ADDR_ANY) {
723
				addr6 = &ipv6_hdr(skb)->daddr;
Linus Torvalds's avatar
Linus Torvalds committed
724
725
726
727
728
729
730
731
732
733
734
735
736
737
				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;
738
739
	if (tos == 1) {
		tos = 0;
Linus Torvalds's avatar
Linus Torvalds committed
740
741
742
743
744
745
746
747
748
749
750
		if (skb->protocol == htons(ETH_P_IP))
			tos = old_iph->tos;
	}

	{
		struct flowi fl = { .oif = tunnel->parms.link,
				    .nl_u = { .ip4_u =
					      { .daddr = dst,
						.saddr = tiph->saddr,
						.tos = RT_TOS(tos) } },
				    .proto = IPPROTO_GRE };
751
		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
752
			stats->tx_carrier_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
753
754
755
756
757
758
759
			goto tx_error;
		}
	}
	tdev = rt->u.dst.dev;

	if (tdev == dev) {
		ip_rt_put(rt);
760
		stats->collisions++;
Linus Torvalds's avatar
Linus Torvalds committed
761
762
763
764
765
		goto tx_error;
	}

	df = tiph->frag_off;
	if (df)
Herbert Xu's avatar
Herbert Xu committed
766
		mtu = dst_mtu(&rt->u.dst) - dev->hard_header_len - tunnel->hlen;
Linus Torvalds's avatar
Linus Torvalds committed
767
	else
Eric Dumazet's avatar
Eric Dumazet committed
768
		mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
Linus Torvalds's avatar
Linus Torvalds committed
769

Eric Dumazet's avatar
Eric Dumazet committed
770
771
	if (skb_dst(skb))
		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
Linus Torvalds's avatar
Linus Torvalds committed
772
773
774
775
776
777
778
779
780
781
782
783
784

	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;
		}
	}
#ifdef CONFIG_IPV6
	else if (skb->protocol == htons(ETH_P_IPV6)) {
Eric Dumazet's avatar
Eric Dumazet committed
785
		struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
Linus Torvalds's avatar
Linus Torvalds committed
786

Eric Dumazet's avatar
Eric Dumazet committed
787
		if (rt6 && mtu < dst_mtu(skb_dst(skb)) && mtu >= IPV6_MIN_MTU) {
788
789
			if ((tunnel->parms.iph.daddr &&
			     !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
Linus Torvalds's avatar
Linus Torvalds committed
790
791
			    rt6->rt6i_dst.plen == 128) {
				rt6->rt6i_flags |= RTF_MODIFIED;
Eric Dumazet's avatar
Eric Dumazet committed
792
				skb_dst(skb)->metrics[RTAX_MTU-1] = mtu;
Linus Torvalds's avatar
Linus Torvalds committed
793
794
795
796
797
798
799
800
801
802
803
804
			}
		}

		if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) {
			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
			ip_rt_put(rt);
			goto tx_error;
		}
	}
#endif

	if (tunnel->err_count > 0) {
805
806
		if (time_before(jiffies,
				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
Linus Torvalds's avatar
Linus Torvalds committed
807
808
809
810
811
812
813
814
815
			tunnel->err_count--;

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

	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen;

816
817
	if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
Linus Torvalds's avatar
Linus Torvalds committed
818
819
820
		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
		if (!new_skb) {
			ip_rt_put(rt);
821
			stats->tx_dropped++;
Linus Torvalds's avatar
Linus Torvalds committed
822
823
			dev_kfree_skb(skb);
			tunnel->recursion--;
824
			return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
825
826
827
828
829
		}
		if (skb->sk)
			skb_set_owner_w(new_skb, skb->sk);
		dev_kfree_skb(skb);
		skb = new_skb;
830
		old_iph = ip_hdr(skb);
Linus Torvalds's avatar
Linus Torvalds committed
831
832
	}

833
	skb_reset_transport_header(skb);
834
835
	skb_push(skb, gre_hlen);
	skb_reset_network_header(skb);
Linus Torvalds's avatar
Linus Torvalds committed
836
	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
837
838
	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
			      IPSKB_REROUTED);
Eric Dumazet's avatar
Eric Dumazet committed
839
840
	skb_dst_drop(skb);
	skb_dst_set(skb, &rt->u.dst);
Linus Torvalds's avatar
Linus Torvalds committed
841
842
843
844
845

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

846
	iph 			=	ip_hdr(skb);
Linus Torvalds's avatar
Linus Torvalds committed
847
848
849
850
851
852
853
854
855
856
857
858
859
	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;
#ifdef CONFIG_IPV6
		else if (skb->protocol == htons(ETH_P_IPV6))
860
			iph->ttl = ((struct ipv6hdr *)old_iph)->hop_limit;
Linus Torvalds's avatar
Linus Torvalds committed
861
862
863
864
865
#endif
		else
			iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT);
	}

866
867
868
	((__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
869
870

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

		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;
884
			*(__sum16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr));
Linus Torvalds's avatar
Linus Torvalds committed
885
886
887
888
889
890
891
		}
	}

	nf_reset(skb);

	IPTUNNEL_XMIT();
	tunnel->recursion--;
892
	return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
893
894
895
896
897
898
899
900

tx_error_icmp:
	dst_link_failure(skb);

tx_error:
	stats->tx_errors++;
	dev_kfree_skb(skb);
	tunnel->recursion--;
901
	return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
902
903
}

904
static int ipgre_tunnel_bind_dev(struct net_device *dev)
905
906
907
908
909
910
911
912
913
914
915
{
	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
916
	/* Guess output device to choose reasonable mtu and needed_headroom */
917
918
919
920
921
922
923
924
925

	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;
926
		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
927
928
929
			tdev = rt->u.dst.dev;
			ip_rt_put(rt);
		}
930
931
932

		if (dev->type != ARPHRD_ETHER)
			dev->flags |= IFF_POINTOPOINT;
933
934
935
	}

	if (!tdev && tunnel->parms.link)
936
		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
937
938

	if (tdev) {
Herbert Xu's avatar
Herbert Xu committed
939
		hlen = tdev->hard_header_len + tdev->needed_headroom;
940
941
942
943
944
945
946
947
948
949
950
951
952
		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
953
	dev->needed_headroom = addend + hlen;
954
955
956
957
958
	mtu -= dev->hard_header_len - addend;

	if (mtu < 68)
		mtu = 68;

959
960
	tunnel->hlen = addend;

961
	return mtu;
962
963
}

Linus Torvalds's avatar
Linus Torvalds committed
964
965
966
967
968
969
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;
970
971
	struct net *net = dev_net(dev);
	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
972
973
974
975

	switch (cmd) {
	case SIOCGETTUNNEL:
		t = NULL;
976
		if (dev == ign->fb_tunnel_dev) {
Linus Torvalds's avatar
Linus Torvalds committed
977
978
979
980
			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
				err = -EFAULT;
				break;
			}
981
			t = ipgre_tunnel_locate(net, &p, 0);
Linus Torvalds's avatar
Linus Torvalds committed
982
983
		}
		if (t == NULL)
984
			t = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
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;