ip_gre.c 40.5 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: HARD_TX_LOCK lock breaks dead loops.
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



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

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

126
127
#define HASH_SIZE  16

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

132
	struct net_device *fb_tunnel_dev;
133
134
};

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

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

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

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

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

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

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

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

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

232
	for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) {
233
234
235
236
237
238
239
240
241
242
243
		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
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_wc[h1]) {
259
260
261
262
263
264
265
266
		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
267
		score = 0;
268
		if (t->parms.link != link)
Timo Teras's avatar
Timo Teras committed
269
			score |= 1;
270
		if (t->dev->type != dev_type)
Timo Teras's avatar
Timo Teras committed
271
272
			score |= 2;
		if (score == 0)
273
			return t;
Timo Teras's avatar
Timo Teras committed
274
275
276
277
278

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

383
384
	dev_net_set(dev, net);

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

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

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

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

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

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

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


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

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

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

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

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

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

497
	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
Linus Torvalds's avatar
Linus Torvalds committed
498
499
500
501
502
		t->err_count++;
	else
		t->err_count = 1;
	t->err_time = jiffies;
out:
503
	rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
504
505
506
507
508
509
510
	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)) {
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;
540
	unsigned int len;
Linus Torvalds's avatar
Linus Torvalds committed
541
542
543
544

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

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

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

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

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

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

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

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

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

631
632
		len = skb->len;

633
634
635
636
637
638
639
640
641
642
643
644
645
		/* 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);
		}

646
		stats->rx_packets++;
647
		stats->rx_bytes += len;
Linus Torvalds's avatar
Linus Torvalds committed
648
		skb->dev = tunnel->dev;
Eric Dumazet's avatar
Eric Dumazet committed
649
		skb_dst_drop(skb);
Linus Torvalds's avatar
Linus Torvalds committed
650
		nf_reset(skb);
651
652

		skb_reset_network_header(skb);
Linus Torvalds's avatar
Linus Torvalds committed
653
		ipgre_ecn_decapsulate(iph, skb);
654

Linus Torvalds's avatar
Linus Torvalds committed
655
		netif_rx(skb);
656
		rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
657
658
		return(0);
	}
659
	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
Linus Torvalds's avatar
Linus Torvalds committed
660
661

drop:
662
	rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
663
664
665
666
667
drop_nolock:
	kfree_skb(skb);
	return(0);
}

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

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

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

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

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

		if (skb->protocol == htons(ETH_P_IP)) {
Eric Dumazet's avatar
Eric Dumazet committed
705
			rt = skb_rtable(skb);
Linus Torvalds's avatar
Linus Torvalds committed
706
707
708
709
710
711
712
			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
713
			struct neighbour *neigh = skb_dst(skb)->neighbour;
Linus Torvalds's avatar
Linus Torvalds committed
714
715
716
717

			if (neigh == NULL)
				goto tx_error;

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

			if (addr_type == IPV6_ADDR_ANY) {
722
				addr6 = &ipv6_hdr(skb)->daddr;
Linus Torvalds's avatar
Linus Torvalds committed
723
724
725
726
727
728
729
730
731
732
733
734
735
736
				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;
737
738
	if (tos == 1) {
		tos = 0;
Linus Torvalds's avatar
Linus Torvalds committed
739
740
741
742
743
744
745
746
747
748
749
		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 };
750
		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
751
			stats->tx_carrier_errors++;
Linus Torvalds's avatar
Linus Torvalds committed
752
753
754
755
756
757
758
			goto tx_error;
		}
	}
	tdev = rt->u.dst.dev;

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

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

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

	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
784
		struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
Linus Torvalds's avatar
Linus Torvalds committed
785

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

		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) {
804
805
		if (time_before(jiffies,
				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
Linus Torvalds's avatar
Linus Torvalds committed
806
807
808
809
810
811
812
813
814
			tunnel->err_count--;

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

	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen;

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

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

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

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

864
865
866
	((__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
867
868

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

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

	nf_reset(skb);

	IPTUNNEL_XMIT();
889
	return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
890
891
892
893
894
895
896

tx_error_icmp:
	dst_link_failure(skb);

tx_error:
	stats->tx_errors++;
	dev_kfree_skb(skb);
897
	return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
898
899
}

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

	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;
922
		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
923
924
925
			tdev = rt->u.dst.dev;
			ip_rt_put(rt);
		}
926
927
928

		if (dev->type != ARPHRD_ETHER)
			dev->flags |= IFF_POINTOPOINT;
929
930
931
	}

	if (!tdev && tunnel->parms.link)
932
		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
933
934

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

	if (mtu < 68)
		mtu = 68;

955
956
	tunnel->hlen = addend;

957
	return mtu;
958
959
}

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

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