xref: /linux/net/ipv4/ipip.c (revision 26d94b46d09c97adb3c78c744c195e74ede699b2)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *	Linux NET3:	IP/IP protocol decoder.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *	Authors:
51da177e4SLinus Torvalds  *		Sam Lantinga (slouken@cs.ucdavis.edu)  02/01/95
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *	Fixes:
81da177e4SLinus Torvalds  *		Alan Cox	:	Merged and made usable non modular (its so tiny its silly as
91da177e4SLinus Torvalds  *					a module taking up 2 pages).
101da177e4SLinus Torvalds  *		Alan Cox	: 	Fixed bug with 1.3.18 and IPIP not working (now needs to set skb->h.iph)
111da177e4SLinus Torvalds  *					to keep ip_forward happy.
121da177e4SLinus Torvalds  *		Alan Cox	:	More fixes for 1.3.21, and firewall fix. Maybe this will work soon 8).
131da177e4SLinus Torvalds  *		Kai Schulte	:	Fixed #defines for IP_FIREWALL->FIREWALL
141da177e4SLinus Torvalds  *              David Woodhouse :       Perform some basic ICMP handling.
151da177e4SLinus Torvalds  *                                      IPIP Routing without decapsulation.
161da177e4SLinus Torvalds  *              Carlos Picoto   :       GRE over IP support
171da177e4SLinus Torvalds  *		Alexey Kuznetsov:	Reworked. Really, now it is truncated version of ipv4/ip_gre.c.
181da177e4SLinus Torvalds  *					I do not want to merge them together.
191da177e4SLinus Torvalds  *
201da177e4SLinus Torvalds  *	This program is free software; you can redistribute it and/or
211da177e4SLinus Torvalds  *	modify it under the terms of the GNU General Public License
221da177e4SLinus Torvalds  *	as published by the Free Software Foundation; either version
231da177e4SLinus Torvalds  *	2 of the License, or (at your option) any later version.
241da177e4SLinus Torvalds  *
251da177e4SLinus Torvalds  */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds /* tunnel.c: an IP tunnel driver
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds 	The purpose of this driver is to provide an IP tunnel through
301da177e4SLinus Torvalds 	which you can tunnel network traffic transparently across subnets.
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds 	This was written by looking at Nick Holloway's dummy driver
331da177e4SLinus Torvalds 	Thanks for the great code!
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds 		-Sam Lantinga	(slouken@cs.ucdavis.edu)  02/01/95
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds 	Minor tweaks:
381da177e4SLinus Torvalds 		Cleaned up the code a little and added some pre-1.3.0 tweaks.
391da177e4SLinus Torvalds 		dev->hard_header/hard_header_len changed to use no headers.
401da177e4SLinus Torvalds 		Comments/bracketing tweaked.
411da177e4SLinus Torvalds 		Made the tunnels use dev->name not tunnel: when error reporting.
421da177e4SLinus Torvalds 		Added tx_dropped stat
431da177e4SLinus Torvalds 
44113aa838SAlan Cox 		-Alan Cox	(alan@lxorguk.ukuu.org.uk) 21 March 95
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds 	Reworked:
471da177e4SLinus Torvalds 		Changed to tunnel to destination gateway in addition to the
481da177e4SLinus Torvalds 			tunnel's pointopoint address
491da177e4SLinus Torvalds 		Almost completely rewritten
501da177e4SLinus Torvalds 		Note:  There is currently no firewall or ICMP handling done.
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds 		-Sam Lantinga	(slouken@cs.ucdavis.edu) 02/13/96
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds */
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds /* Things I wish I had known when writing the tunnel driver:
571da177e4SLinus Torvalds 
581da177e4SLinus Torvalds 	When the tunnel_xmit() function is called, the skb contains the
591da177e4SLinus Torvalds 	packet to be sent (plus a great deal of extra info), and dev
601da177e4SLinus Torvalds 	contains the tunnel device that _we_ are.
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds 	When we are passed a packet, we are expected to fill in the
631da177e4SLinus Torvalds 	source address with our source IP address.
641da177e4SLinus Torvalds 
651da177e4SLinus Torvalds 	What is the proper way to allocate, copy and free a buffer?
661da177e4SLinus Torvalds 	After you allocate it, it is a "0 length" chunk of memory
671da177e4SLinus Torvalds 	starting at zero.  If you want to add headers to the buffer
681da177e4SLinus Torvalds 	later, you'll have to call "skb_reserve(skb, amount)" with
691da177e4SLinus Torvalds 	the amount of memory you want reserved.  Then, you call
701da177e4SLinus Torvalds 	"skb_put(skb, amount)" with the amount of space you want in
711da177e4SLinus Torvalds 	the buffer.  skb_put() returns a pointer to the top (#0) of
721da177e4SLinus Torvalds 	that buffer.  skb->len is set to the amount of space you have
731da177e4SLinus Torvalds 	"allocated" with skb_put().  You can then write up to skb->len
741da177e4SLinus Torvalds 	bytes to that buffer.  If you need more, you can call skb_put()
751da177e4SLinus Torvalds 	again with the additional amount of space you need.  You can
761da177e4SLinus Torvalds 	find out how much more space you can allocate by calling
771da177e4SLinus Torvalds 	"skb_tailroom(skb)".
781da177e4SLinus Torvalds 	Now, to add header space, call "skb_push(skb, header_len)".
791da177e4SLinus Torvalds 	This creates space at the beginning of the buffer and returns
801da177e4SLinus Torvalds 	a pointer to this new space.  If later you need to strip a
811da177e4SLinus Torvalds 	header from a buffer, call "skb_pull(skb, header_len)".
821da177e4SLinus Torvalds 	skb_headroom() will return how much space is left at the top
831da177e4SLinus Torvalds 	of the buffer (before the main data).  Remember, this headroom
841da177e4SLinus Torvalds 	space must be reserved before the skb_put() function is called.
851da177e4SLinus Torvalds 	*/
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds /*
881da177e4SLinus Torvalds    This version of net/ipv4/ipip.c is cloned of net/ipv4/ip_gre.c
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds    For comments look at net/ipv4/ip_gre.c --ANK
911da177e4SLinus Torvalds  */
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds 
944fc268d2SRandy Dunlap #include <linux/capability.h>
951da177e4SLinus Torvalds #include <linux/module.h>
961da177e4SLinus Torvalds #include <linux/types.h>
971da177e4SLinus Torvalds #include <linux/kernel.h>
981da177e4SLinus Torvalds #include <asm/uaccess.h>
991da177e4SLinus Torvalds #include <linux/skbuff.h>
1001da177e4SLinus Torvalds #include <linux/netdevice.h>
1011da177e4SLinus Torvalds #include <linux/in.h>
1021da177e4SLinus Torvalds #include <linux/tcp.h>
1031da177e4SLinus Torvalds #include <linux/udp.h>
1041da177e4SLinus Torvalds #include <linux/if_arp.h>
1051da177e4SLinus Torvalds #include <linux/mroute.h>
1061da177e4SLinus Torvalds #include <linux/init.h>
1071da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h>
10846f25dffSKris Katterjohn #include <linux/if_ether.h>
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds #include <net/sock.h>
1111da177e4SLinus Torvalds #include <net/ip.h>
1121da177e4SLinus Torvalds #include <net/icmp.h>
1131da177e4SLinus Torvalds #include <net/ipip.h>
1141da177e4SLinus Torvalds #include <net/inet_ecn.h>
1151da177e4SLinus Torvalds #include <net/xfrm.h>
11610dc4c7bSPavel Emelyanov #include <net/net_namespace.h>
11710dc4c7bSPavel Emelyanov #include <net/netns/generic.h>
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds #define HASH_SIZE  16
120d5a0a1e3SAl Viro #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
1211da177e4SLinus Torvalds 
12210dc4c7bSPavel Emelyanov static int ipip_net_id;
12310dc4c7bSPavel Emelyanov struct ipip_net {
12444d3c299SPavel Emelyanov 	struct ip_tunnel *tunnels_r_l[HASH_SIZE];
12544d3c299SPavel Emelyanov 	struct ip_tunnel *tunnels_r[HASH_SIZE];
12644d3c299SPavel Emelyanov 	struct ip_tunnel *tunnels_l[HASH_SIZE];
12744d3c299SPavel Emelyanov 	struct ip_tunnel *tunnels_wc[1];
12844d3c299SPavel Emelyanov 	struct ip_tunnel **tunnels[4];
12944d3c299SPavel Emelyanov 
130b9855c54SPavel Emelyanov 	struct net_device *fb_tunnel_dev;
13110dc4c7bSPavel Emelyanov };
13210dc4c7bSPavel Emelyanov 
13323a12b14SStephen Hemminger static void ipip_fb_tunnel_init(struct net_device *dev);
13423a12b14SStephen Hemminger static void ipip_tunnel_init(struct net_device *dev);
1351da177e4SLinus Torvalds static void ipip_tunnel_setup(struct net_device *dev);
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds static DEFINE_RWLOCK(ipip_lock);
1381da177e4SLinus Torvalds 
139b9fae5c9SPavel Emelyanov static struct ip_tunnel * ipip_tunnel_lookup(struct net *net,
140b9fae5c9SPavel Emelyanov 		__be32 remote, __be32 local)
1411da177e4SLinus Torvalds {
1421da177e4SLinus Torvalds 	unsigned h0 = HASH(remote);
1431da177e4SLinus Torvalds 	unsigned h1 = HASH(local);
1441da177e4SLinus Torvalds 	struct ip_tunnel *t;
14544d3c299SPavel Emelyanov 	struct ipip_net *ipn = net_generic(net, ipip_net_id);
1461da177e4SLinus Torvalds 
14744d3c299SPavel Emelyanov 	for (t = ipn->tunnels_r_l[h0^h1]; t; t = t->next) {
1481da177e4SLinus Torvalds 		if (local == t->parms.iph.saddr &&
1491da177e4SLinus Torvalds 		    remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
1501da177e4SLinus Torvalds 			return t;
1511da177e4SLinus Torvalds 	}
15244d3c299SPavel Emelyanov 	for (t = ipn->tunnels_r[h0]; t; t = t->next) {
1531da177e4SLinus Torvalds 		if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
1541da177e4SLinus Torvalds 			return t;
1551da177e4SLinus Torvalds 	}
15644d3c299SPavel Emelyanov 	for (t = ipn->tunnels_l[h1]; t; t = t->next) {
1571da177e4SLinus Torvalds 		if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
1581da177e4SLinus Torvalds 			return t;
1591da177e4SLinus Torvalds 	}
16044d3c299SPavel Emelyanov 	if ((t = ipn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
1611da177e4SLinus Torvalds 		return t;
1621da177e4SLinus Torvalds 	return NULL;
1631da177e4SLinus Torvalds }
1641da177e4SLinus Torvalds 
165b9fae5c9SPavel Emelyanov static struct ip_tunnel **__ipip_bucket(struct ipip_net *ipn,
166b9fae5c9SPavel Emelyanov 		struct ip_tunnel_parm *parms)
1671da177e4SLinus Torvalds {
16887d1a164SYOSHIFUJI Hideaki 	__be32 remote = parms->iph.daddr;
16987d1a164SYOSHIFUJI Hideaki 	__be32 local = parms->iph.saddr;
1701da177e4SLinus Torvalds 	unsigned h = 0;
1711da177e4SLinus Torvalds 	int prio = 0;
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds 	if (remote) {
1741da177e4SLinus Torvalds 		prio |= 2;
1751da177e4SLinus Torvalds 		h ^= HASH(remote);
1761da177e4SLinus Torvalds 	}
1771da177e4SLinus Torvalds 	if (local) {
1781da177e4SLinus Torvalds 		prio |= 1;
1791da177e4SLinus Torvalds 		h ^= HASH(local);
1801da177e4SLinus Torvalds 	}
18144d3c299SPavel Emelyanov 	return &ipn->tunnels[prio][h];
1821da177e4SLinus Torvalds }
1831da177e4SLinus Torvalds 
184b9fae5c9SPavel Emelyanov static inline struct ip_tunnel **ipip_bucket(struct ipip_net *ipn,
185b9fae5c9SPavel Emelyanov 		struct ip_tunnel *t)
18687d1a164SYOSHIFUJI Hideaki {
187b9fae5c9SPavel Emelyanov 	return __ipip_bucket(ipn, &t->parms);
18887d1a164SYOSHIFUJI Hideaki }
1891da177e4SLinus Torvalds 
190b9fae5c9SPavel Emelyanov static void ipip_tunnel_unlink(struct ipip_net *ipn, struct ip_tunnel *t)
1911da177e4SLinus Torvalds {
1921da177e4SLinus Torvalds 	struct ip_tunnel **tp;
1931da177e4SLinus Torvalds 
194b9fae5c9SPavel Emelyanov 	for (tp = ipip_bucket(ipn, t); *tp; tp = &(*tp)->next) {
1951da177e4SLinus Torvalds 		if (t == *tp) {
1961da177e4SLinus Torvalds 			write_lock_bh(&ipip_lock);
1971da177e4SLinus Torvalds 			*tp = t->next;
1981da177e4SLinus Torvalds 			write_unlock_bh(&ipip_lock);
1991da177e4SLinus Torvalds 			break;
2001da177e4SLinus Torvalds 		}
2011da177e4SLinus Torvalds 	}
2021da177e4SLinus Torvalds }
2031da177e4SLinus Torvalds 
204b9fae5c9SPavel Emelyanov static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t)
2051da177e4SLinus Torvalds {
206b9fae5c9SPavel Emelyanov 	struct ip_tunnel **tp = ipip_bucket(ipn, t);
2071da177e4SLinus Torvalds 
2081da177e4SLinus Torvalds 	t->next = *tp;
2091da177e4SLinus Torvalds 	write_lock_bh(&ipip_lock);
2101da177e4SLinus Torvalds 	*tp = t;
2111da177e4SLinus Torvalds 	write_unlock_bh(&ipip_lock);
2121da177e4SLinus Torvalds }
2131da177e4SLinus Torvalds 
214b9fae5c9SPavel Emelyanov static struct ip_tunnel * ipip_tunnel_locate(struct net *net,
215b9fae5c9SPavel Emelyanov 		struct ip_tunnel_parm *parms, int create)
2161da177e4SLinus Torvalds {
217d5a0a1e3SAl Viro 	__be32 remote = parms->iph.daddr;
218d5a0a1e3SAl Viro 	__be32 local = parms->iph.saddr;
2191da177e4SLinus Torvalds 	struct ip_tunnel *t, **tp, *nt;
2201da177e4SLinus Torvalds 	struct net_device *dev;
2211da177e4SLinus Torvalds 	char name[IFNAMSIZ];
222b9fae5c9SPavel Emelyanov 	struct ipip_net *ipn = net_generic(net, ipip_net_id);
2231da177e4SLinus Torvalds 
224b9fae5c9SPavel Emelyanov 	for (tp = __ipip_bucket(ipn, parms); (t = *tp) != NULL; tp = &t->next) {
2251da177e4SLinus Torvalds 		if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr)
2261da177e4SLinus Torvalds 			return t;
2271da177e4SLinus Torvalds 	}
2281da177e4SLinus Torvalds 	if (!create)
2291da177e4SLinus Torvalds 		return NULL;
2301da177e4SLinus Torvalds 
2311da177e4SLinus Torvalds 	if (parms->name[0])
2321da177e4SLinus Torvalds 		strlcpy(name, parms->name, IFNAMSIZ);
23334cc7ba6SPavel Emelyanov 	else
23434cc7ba6SPavel Emelyanov 		sprintf(name, "tunl%%d");
2351da177e4SLinus Torvalds 
2361da177e4SLinus Torvalds 	dev = alloc_netdev(sizeof(*t), name, ipip_tunnel_setup);
2371da177e4SLinus Torvalds 	if (dev == NULL)
2381da177e4SLinus Torvalds 		return NULL;
2391da177e4SLinus Torvalds 
2400a826406SPavel Emelyanov 	dev_net_set(dev, net);
2410a826406SPavel Emelyanov 
242b37d428bSPavel Emelyanov 	if (strchr(name, '%')) {
243b37d428bSPavel Emelyanov 		if (dev_alloc_name(dev, name) < 0)
244b37d428bSPavel Emelyanov 			goto failed_free;
245b37d428bSPavel Emelyanov 	}
246b37d428bSPavel Emelyanov 
2472941a486SPatrick McHardy 	nt = netdev_priv(dev);
2481da177e4SLinus Torvalds 	nt->parms = *parms;
2491da177e4SLinus Torvalds 
25023a12b14SStephen Hemminger 	ipip_tunnel_init(dev);
25123a12b14SStephen Hemminger 
252b37d428bSPavel Emelyanov 	if (register_netdevice(dev) < 0)
253b37d428bSPavel Emelyanov 		goto failed_free;
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds 	dev_hold(dev);
256b9fae5c9SPavel Emelyanov 	ipip_tunnel_link(ipn, nt);
2571da177e4SLinus Torvalds 	return nt;
2581da177e4SLinus Torvalds 
259b37d428bSPavel Emelyanov failed_free:
260b37d428bSPavel Emelyanov 	free_netdev(dev);
2611da177e4SLinus Torvalds 	return NULL;
2621da177e4SLinus Torvalds }
2631da177e4SLinus Torvalds 
2641da177e4SLinus Torvalds static void ipip_tunnel_uninit(struct net_device *dev)
2651da177e4SLinus Torvalds {
266b9855c54SPavel Emelyanov 	struct net *net = dev_net(dev);
267b9855c54SPavel Emelyanov 	struct ipip_net *ipn = net_generic(net, ipip_net_id);
268b9855c54SPavel Emelyanov 
269b9855c54SPavel Emelyanov 	if (dev == ipn->fb_tunnel_dev) {
2701da177e4SLinus Torvalds 		write_lock_bh(&ipip_lock);
27144d3c299SPavel Emelyanov 		ipn->tunnels_wc[0] = NULL;
2721da177e4SLinus Torvalds 		write_unlock_bh(&ipip_lock);
2731da177e4SLinus Torvalds 	} else
274b9fae5c9SPavel Emelyanov 		ipip_tunnel_unlink(ipn, netdev_priv(dev));
2751da177e4SLinus Torvalds 	dev_put(dev);
2761da177e4SLinus Torvalds }
2771da177e4SLinus Torvalds 
278d2acc347SHerbert Xu static int ipip_err(struct sk_buff *skb, u32 info)
2791da177e4SLinus Torvalds {
2801da177e4SLinus Torvalds 
281071f92d0SRami Rosen /* All the routers (except for Linux) return only
2821da177e4SLinus Torvalds    8 bytes of packet payload. It means, that precise relaying of
2831da177e4SLinus Torvalds    ICMP in the real Internet is absolutely infeasible.
2841da177e4SLinus Torvalds  */
2851da177e4SLinus Torvalds 	struct iphdr *iph = (struct iphdr *)skb->data;
28688c7664fSArnaldo Carvalho de Melo 	const int type = icmp_hdr(skb)->type;
28788c7664fSArnaldo Carvalho de Melo 	const int code = icmp_hdr(skb)->code;
2881da177e4SLinus Torvalds 	struct ip_tunnel *t;
289d2acc347SHerbert Xu 	int err;
2901da177e4SLinus Torvalds 
2911da177e4SLinus Torvalds 	switch (type) {
2921da177e4SLinus Torvalds 	default:
2931da177e4SLinus Torvalds 	case ICMP_PARAMETERPROB:
294d2acc347SHerbert Xu 		return 0;
2951da177e4SLinus Torvalds 
2961da177e4SLinus Torvalds 	case ICMP_DEST_UNREACH:
2971da177e4SLinus Torvalds 		switch (code) {
2981da177e4SLinus Torvalds 		case ICMP_SR_FAILED:
2991da177e4SLinus Torvalds 		case ICMP_PORT_UNREACH:
3001da177e4SLinus Torvalds 			/* Impossible event. */
301d2acc347SHerbert Xu 			return 0;
3021da177e4SLinus Torvalds 		case ICMP_FRAG_NEEDED:
3031da177e4SLinus Torvalds 			/* Soft state for pmtu is maintained by IP core. */
304d2acc347SHerbert Xu 			return 0;
3051da177e4SLinus Torvalds 		default:
3061da177e4SLinus Torvalds 			/* All others are translated to HOST_UNREACH.
3071da177e4SLinus Torvalds 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
3081da177e4SLinus Torvalds 			   I believe they are just ether pollution. --ANK
3091da177e4SLinus Torvalds 			 */
3101da177e4SLinus Torvalds 			break;
3111da177e4SLinus Torvalds 		}
3121da177e4SLinus Torvalds 		break;
3131da177e4SLinus Torvalds 	case ICMP_TIME_EXCEEDED:
3141da177e4SLinus Torvalds 		if (code != ICMP_EXC_TTL)
315d2acc347SHerbert Xu 			return 0;
3161da177e4SLinus Torvalds 		break;
3171da177e4SLinus Torvalds 	}
3181da177e4SLinus Torvalds 
319d2acc347SHerbert Xu 	err = -ENOENT;
320d2acc347SHerbert Xu 
3211da177e4SLinus Torvalds 	read_lock(&ipip_lock);
322cec3ffaeSPavel Emelyanov 	t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr);
3231da177e4SLinus Torvalds 	if (t == NULL || t->parms.iph.daddr == 0)
3241da177e4SLinus Torvalds 		goto out;
325d2acc347SHerbert Xu 
326d2acc347SHerbert Xu 	err = 0;
3271da177e4SLinus Torvalds 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
3281da177e4SLinus Torvalds 		goto out;
3291da177e4SLinus Torvalds 
330*26d94b46SWei Yongjun 	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
3311da177e4SLinus Torvalds 		t->err_count++;
3321da177e4SLinus Torvalds 	else
3331da177e4SLinus Torvalds 		t->err_count = 1;
3341da177e4SLinus Torvalds 	t->err_time = jiffies;
3351da177e4SLinus Torvalds out:
3361da177e4SLinus Torvalds 	read_unlock(&ipip_lock);
337d2acc347SHerbert Xu 	return err;
3381da177e4SLinus Torvalds }
3391da177e4SLinus Torvalds 
340eddc9ec5SArnaldo Carvalho de Melo static inline void ipip_ecn_decapsulate(const struct iphdr *outer_iph,
341eddc9ec5SArnaldo Carvalho de Melo 					struct sk_buff *skb)
3421da177e4SLinus Torvalds {
343eddc9ec5SArnaldo Carvalho de Melo 	struct iphdr *inner_iph = ip_hdr(skb);
3441da177e4SLinus Torvalds 
3451da177e4SLinus Torvalds 	if (INET_ECN_is_ce(outer_iph->tos))
3461da177e4SLinus Torvalds 		IP_ECN_set_ce(inner_iph);
3471da177e4SLinus Torvalds }
3481da177e4SLinus Torvalds 
3491da177e4SLinus Torvalds static int ipip_rcv(struct sk_buff *skb)
3501da177e4SLinus Torvalds {
3511da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
352eddc9ec5SArnaldo Carvalho de Melo 	const struct iphdr *iph = ip_hdr(skb);
3531da177e4SLinus Torvalds 
3541da177e4SLinus Torvalds 	read_lock(&ipip_lock);
355cec3ffaeSPavel Emelyanov 	if ((tunnel = ipip_tunnel_lookup(dev_net(skb->dev),
356b9fae5c9SPavel Emelyanov 					iph->saddr, iph->daddr)) != NULL) {
3571da177e4SLinus Torvalds 		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
3581da177e4SLinus Torvalds 			read_unlock(&ipip_lock);
3591da177e4SLinus Torvalds 			kfree_skb(skb);
3601da177e4SLinus Torvalds 			return 0;
3611da177e4SLinus Torvalds 		}
3621da177e4SLinus Torvalds 
3631da177e4SLinus Torvalds 		secpath_reset(skb);
3641da177e4SLinus Torvalds 
365b0e380b1SArnaldo Carvalho de Melo 		skb->mac_header = skb->network_header;
366c1d2bbe1SArnaldo Carvalho de Melo 		skb_reset_network_header(skb);
3671da177e4SLinus Torvalds 		skb->protocol = htons(ETH_P_IP);
3681da177e4SLinus Torvalds 		skb->pkt_type = PACKET_HOST;
3691da177e4SLinus Torvalds 
37050f59ceaSPavel Emelyanov 		tunnel->dev->stats.rx_packets++;
37150f59ceaSPavel Emelyanov 		tunnel->dev->stats.rx_bytes += skb->len;
3721da177e4SLinus Torvalds 		skb->dev = tunnel->dev;
3731da177e4SLinus Torvalds 		dst_release(skb->dst);
3741da177e4SLinus Torvalds 		skb->dst = NULL;
3751da177e4SLinus Torvalds 		nf_reset(skb);
3761da177e4SLinus Torvalds 		ipip_ecn_decapsulate(iph, skb);
3771da177e4SLinus Torvalds 		netif_rx(skb);
3781da177e4SLinus Torvalds 		read_unlock(&ipip_lock);
3791da177e4SLinus Torvalds 		return 0;
3801da177e4SLinus Torvalds 	}
3811da177e4SLinus Torvalds 	read_unlock(&ipip_lock);
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds 	return -1;
3841da177e4SLinus Torvalds }
3851da177e4SLinus Torvalds 
3861da177e4SLinus Torvalds /*
3871da177e4SLinus Torvalds  *	This function assumes it is being called from dev_queue_xmit()
3881da177e4SLinus Torvalds  *	and that skb is filled properly by that function.
3891da177e4SLinus Torvalds  */
3901da177e4SLinus Torvalds 
3911da177e4SLinus Torvalds static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
3921da177e4SLinus Torvalds {
3932941a486SPatrick McHardy 	struct ip_tunnel *tunnel = netdev_priv(dev);
39450f59ceaSPavel Emelyanov 	struct net_device_stats *stats = &tunnel->dev->stats;
3951da177e4SLinus Torvalds 	struct iphdr  *tiph = &tunnel->parms.iph;
3961da177e4SLinus Torvalds 	u8     tos = tunnel->parms.iph.tos;
397d5a0a1e3SAl Viro 	__be16 df = tiph->frag_off;
3981da177e4SLinus Torvalds 	struct rtable *rt;     			/* Route to the other host */
3991da177e4SLinus Torvalds 	struct net_device *tdev;			/* Device to other host */
400eddc9ec5SArnaldo Carvalho de Melo 	struct iphdr  *old_iph = ip_hdr(skb);
4011da177e4SLinus Torvalds 	struct iphdr  *iph;			/* Our new IP header */
402c2636b4dSChuck Lever 	unsigned int max_headroom;		/* The extra header space needed */
403d5a0a1e3SAl Viro 	__be32 dst = tiph->daddr;
4041da177e4SLinus Torvalds 	int    mtu;
4051da177e4SLinus Torvalds 
4061da177e4SLinus Torvalds 	if (tunnel->recursion++) {
40750f59ceaSPavel Emelyanov 		stats->collisions++;
4081da177e4SLinus Torvalds 		goto tx_error;
4091da177e4SLinus Torvalds 	}
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds 	if (skb->protocol != htons(ETH_P_IP))
4121da177e4SLinus Torvalds 		goto tx_error;
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds 	if (tos&1)
4151da177e4SLinus Torvalds 		tos = old_iph->tos;
4161da177e4SLinus Torvalds 
4171da177e4SLinus Torvalds 	if (!dst) {
4181da177e4SLinus Torvalds 		/* NBMA tunnel */
419ee6b9673SEric Dumazet 		if ((rt = skb->rtable) == NULL) {
42050f59ceaSPavel Emelyanov 			stats->tx_fifo_errors++;
4211da177e4SLinus Torvalds 			goto tx_error;
4221da177e4SLinus Torvalds 		}
4231da177e4SLinus Torvalds 		if ((dst = rt->rt_gateway) == 0)
4241da177e4SLinus Torvalds 			goto tx_error_icmp;
4251da177e4SLinus Torvalds 	}
4261da177e4SLinus Torvalds 
4271da177e4SLinus Torvalds 	{
4281da177e4SLinus Torvalds 		struct flowi fl = { .oif = tunnel->parms.link,
4291da177e4SLinus Torvalds 				    .nl_u = { .ip4_u =
4301da177e4SLinus Torvalds 					      { .daddr = dst,
4311da177e4SLinus Torvalds 						.saddr = tiph->saddr,
4321da177e4SLinus Torvalds 						.tos = RT_TOS(tos) } },
4331da177e4SLinus Torvalds 				    .proto = IPPROTO_IPIP };
434b99f0152SPavel Emelyanov 		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
43550f59ceaSPavel Emelyanov 			stats->tx_carrier_errors++;
4361da177e4SLinus Torvalds 			goto tx_error_icmp;
4371da177e4SLinus Torvalds 		}
4381da177e4SLinus Torvalds 	}
4391da177e4SLinus Torvalds 	tdev = rt->u.dst.dev;
4401da177e4SLinus Torvalds 
4411da177e4SLinus Torvalds 	if (tdev == dev) {
4421da177e4SLinus Torvalds 		ip_rt_put(rt);
44350f59ceaSPavel Emelyanov 		stats->collisions++;
4441da177e4SLinus Torvalds 		goto tx_error;
4451da177e4SLinus Torvalds 	}
4461da177e4SLinus Torvalds 
4471da177e4SLinus Torvalds 	if (tiph->frag_off)
4481da177e4SLinus Torvalds 		mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr);
4491da177e4SLinus Torvalds 	else
4501da177e4SLinus Torvalds 		mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu;
4511da177e4SLinus Torvalds 
4521da177e4SLinus Torvalds 	if (mtu < 68) {
45350f59ceaSPavel Emelyanov 		stats->collisions++;
4541da177e4SLinus Torvalds 		ip_rt_put(rt);
4551da177e4SLinus Torvalds 		goto tx_error;
4561da177e4SLinus Torvalds 	}
4571da177e4SLinus Torvalds 	if (skb->dst)
4581da177e4SLinus Torvalds 		skb->dst->ops->update_pmtu(skb->dst, mtu);
4591da177e4SLinus Torvalds 
4601da177e4SLinus Torvalds 	df |= (old_iph->frag_off&htons(IP_DF));
4611da177e4SLinus Torvalds 
4621da177e4SLinus Torvalds 	if ((old_iph->frag_off&htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) {
4631da177e4SLinus Torvalds 		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
4641da177e4SLinus Torvalds 		ip_rt_put(rt);
4651da177e4SLinus Torvalds 		goto tx_error;
4661da177e4SLinus Torvalds 	}
4671da177e4SLinus Torvalds 
4681da177e4SLinus Torvalds 	if (tunnel->err_count > 0) {
469*26d94b46SWei Yongjun 		if (time_before(jiffies,
470*26d94b46SWei Yongjun 				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
4711da177e4SLinus Torvalds 			tunnel->err_count--;
4721da177e4SLinus Torvalds 			dst_link_failure(skb);
4731da177e4SLinus Torvalds 		} else
4741da177e4SLinus Torvalds 			tunnel->err_count = 0;
4751da177e4SLinus Torvalds 	}
4761da177e4SLinus Torvalds 
4771da177e4SLinus Torvalds 	/*
4781da177e4SLinus Torvalds 	 * Okay, now see if we can stuff it in the buffer as-is.
4791da177e4SLinus Torvalds 	 */
4801da177e4SLinus Torvalds 	max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr));
4811da177e4SLinus Torvalds 
482cfbba49dSPatrick McHardy 	if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
483cfbba49dSPatrick McHardy 	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
4841da177e4SLinus Torvalds 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
4851da177e4SLinus Torvalds 		if (!new_skb) {
4861da177e4SLinus Torvalds 			ip_rt_put(rt);
4871da177e4SLinus Torvalds 			stats->tx_dropped++;
4881da177e4SLinus Torvalds 			dev_kfree_skb(skb);
4891da177e4SLinus Torvalds 			tunnel->recursion--;
4901da177e4SLinus Torvalds 			return 0;
4911da177e4SLinus Torvalds 		}
4921da177e4SLinus Torvalds 		if (skb->sk)
4931da177e4SLinus Torvalds 			skb_set_owner_w(new_skb, skb->sk);
4941da177e4SLinus Torvalds 		dev_kfree_skb(skb);
4951da177e4SLinus Torvalds 		skb = new_skb;
496eddc9ec5SArnaldo Carvalho de Melo 		old_iph = ip_hdr(skb);
4971da177e4SLinus Torvalds 	}
4981da177e4SLinus Torvalds 
499b0e380b1SArnaldo Carvalho de Melo 	skb->transport_header = skb->network_header;
500e2d1bca7SArnaldo Carvalho de Melo 	skb_push(skb, sizeof(struct iphdr));
501e2d1bca7SArnaldo Carvalho de Melo 	skb_reset_network_header(skb);
5021da177e4SLinus Torvalds 	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
50348d5cad8SPatrick McHardy 	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
50448d5cad8SPatrick McHardy 			      IPSKB_REROUTED);
5051da177e4SLinus Torvalds 	dst_release(skb->dst);
5061da177e4SLinus Torvalds 	skb->dst = &rt->u.dst;
5071da177e4SLinus Torvalds 
5081da177e4SLinus Torvalds 	/*
5091da177e4SLinus Torvalds 	 *	Push down and install the IPIP header.
5101da177e4SLinus Torvalds 	 */
5111da177e4SLinus Torvalds 
512eddc9ec5SArnaldo Carvalho de Melo 	iph 			=	ip_hdr(skb);
5131da177e4SLinus Torvalds 	iph->version		=	4;
5141da177e4SLinus Torvalds 	iph->ihl		=	sizeof(struct iphdr)>>2;
5151da177e4SLinus Torvalds 	iph->frag_off		=	df;
5161da177e4SLinus Torvalds 	iph->protocol		=	IPPROTO_IPIP;
5171da177e4SLinus Torvalds 	iph->tos		=	INET_ECN_encapsulate(tos, old_iph->tos);
5181da177e4SLinus Torvalds 	iph->daddr		=	rt->rt_dst;
5191da177e4SLinus Torvalds 	iph->saddr		=	rt->rt_src;
5201da177e4SLinus Torvalds 
5211da177e4SLinus Torvalds 	if ((iph->ttl = tiph->ttl) == 0)
5221da177e4SLinus Torvalds 		iph->ttl	=	old_iph->ttl;
5231da177e4SLinus Torvalds 
5241da177e4SLinus Torvalds 	nf_reset(skb);
5251da177e4SLinus Torvalds 
5261da177e4SLinus Torvalds 	IPTUNNEL_XMIT();
5271da177e4SLinus Torvalds 	tunnel->recursion--;
5281da177e4SLinus Torvalds 	return 0;
5291da177e4SLinus Torvalds 
5301da177e4SLinus Torvalds tx_error_icmp:
5311da177e4SLinus Torvalds 	dst_link_failure(skb);
5321da177e4SLinus Torvalds tx_error:
5331da177e4SLinus Torvalds 	stats->tx_errors++;
5341da177e4SLinus Torvalds 	dev_kfree_skb(skb);
5351da177e4SLinus Torvalds 	tunnel->recursion--;
5361da177e4SLinus Torvalds 	return 0;
5371da177e4SLinus Torvalds }
5381da177e4SLinus Torvalds 
5395533995bSMichal Schmidt static void ipip_tunnel_bind_dev(struct net_device *dev)
5405533995bSMichal Schmidt {
5415533995bSMichal Schmidt 	struct net_device *tdev = NULL;
5425533995bSMichal Schmidt 	struct ip_tunnel *tunnel;
5435533995bSMichal Schmidt 	struct iphdr *iph;
5445533995bSMichal Schmidt 
5455533995bSMichal Schmidt 	tunnel = netdev_priv(dev);
5465533995bSMichal Schmidt 	iph = &tunnel->parms.iph;
5475533995bSMichal Schmidt 
5485533995bSMichal Schmidt 	if (iph->daddr) {
5495533995bSMichal Schmidt 		struct flowi fl = { .oif = tunnel->parms.link,
5505533995bSMichal Schmidt 				    .nl_u = { .ip4_u =
5515533995bSMichal Schmidt 					      { .daddr = iph->daddr,
5525533995bSMichal Schmidt 						.saddr = iph->saddr,
5535533995bSMichal Schmidt 						.tos = RT_TOS(iph->tos) } },
5545533995bSMichal Schmidt 				    .proto = IPPROTO_IPIP };
5555533995bSMichal Schmidt 		struct rtable *rt;
556b99f0152SPavel Emelyanov 		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
5575533995bSMichal Schmidt 			tdev = rt->u.dst.dev;
5585533995bSMichal Schmidt 			ip_rt_put(rt);
5595533995bSMichal Schmidt 		}
5605533995bSMichal Schmidt 		dev->flags |= IFF_POINTOPOINT;
5615533995bSMichal Schmidt 	}
5625533995bSMichal Schmidt 
5635533995bSMichal Schmidt 	if (!tdev && tunnel->parms.link)
564b99f0152SPavel Emelyanov 		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
5655533995bSMichal Schmidt 
5665533995bSMichal Schmidt 	if (tdev) {
5675533995bSMichal Schmidt 		dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
5685533995bSMichal Schmidt 		dev->mtu = tdev->mtu - sizeof(struct iphdr);
5695533995bSMichal Schmidt 	}
5705533995bSMichal Schmidt 	dev->iflink = tunnel->parms.link;
5715533995bSMichal Schmidt }
5725533995bSMichal Schmidt 
5731da177e4SLinus Torvalds static int
5741da177e4SLinus Torvalds ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
5751da177e4SLinus Torvalds {
5761da177e4SLinus Torvalds 	int err = 0;
5771da177e4SLinus Torvalds 	struct ip_tunnel_parm p;
5781da177e4SLinus Torvalds 	struct ip_tunnel *t;
579b9855c54SPavel Emelyanov 	struct net *net = dev_net(dev);
580b9855c54SPavel Emelyanov 	struct ipip_net *ipn = net_generic(net, ipip_net_id);
5811da177e4SLinus Torvalds 
5821da177e4SLinus Torvalds 	switch (cmd) {
5831da177e4SLinus Torvalds 	case SIOCGETTUNNEL:
5841da177e4SLinus Torvalds 		t = NULL;
585b9855c54SPavel Emelyanov 		if (dev == ipn->fb_tunnel_dev) {
5861da177e4SLinus Torvalds 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
5871da177e4SLinus Torvalds 				err = -EFAULT;
5881da177e4SLinus Torvalds 				break;
5891da177e4SLinus Torvalds 			}
590b9fae5c9SPavel Emelyanov 			t = ipip_tunnel_locate(net, &p, 0);
5911da177e4SLinus Torvalds 		}
5921da177e4SLinus Torvalds 		if (t == NULL)
5932941a486SPatrick McHardy 			t = netdev_priv(dev);
5941da177e4SLinus Torvalds 		memcpy(&p, &t->parms, sizeof(p));
5951da177e4SLinus Torvalds 		if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
5961da177e4SLinus Torvalds 			err = -EFAULT;
5971da177e4SLinus Torvalds 		break;
5981da177e4SLinus Torvalds 
5991da177e4SLinus Torvalds 	case SIOCADDTUNNEL:
6001da177e4SLinus Torvalds 	case SIOCCHGTUNNEL:
6011da177e4SLinus Torvalds 		err = -EPERM;
6021da177e4SLinus Torvalds 		if (!capable(CAP_NET_ADMIN))
6031da177e4SLinus Torvalds 			goto done;
6041da177e4SLinus Torvalds 
6051da177e4SLinus Torvalds 		err = -EFAULT;
6061da177e4SLinus Torvalds 		if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
6071da177e4SLinus Torvalds 			goto done;
6081da177e4SLinus Torvalds 
6091da177e4SLinus Torvalds 		err = -EINVAL;
6101da177e4SLinus Torvalds 		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
6111da177e4SLinus Torvalds 		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
6121da177e4SLinus Torvalds 			goto done;
6131da177e4SLinus Torvalds 		if (p.iph.ttl)
6141da177e4SLinus Torvalds 			p.iph.frag_off |= htons(IP_DF);
6151da177e4SLinus Torvalds 
616b9fae5c9SPavel Emelyanov 		t = ipip_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
6171da177e4SLinus Torvalds 
618b9855c54SPavel Emelyanov 		if (dev != ipn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
6191da177e4SLinus Torvalds 			if (t != NULL) {
6201da177e4SLinus Torvalds 				if (t->dev != dev) {
6211da177e4SLinus Torvalds 					err = -EEXIST;
6221da177e4SLinus Torvalds 					break;
6231da177e4SLinus Torvalds 				}
6241da177e4SLinus Torvalds 			} else {
6251da177e4SLinus Torvalds 				if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) ||
6261da177e4SLinus Torvalds 				    (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) {
6271da177e4SLinus Torvalds 					err = -EINVAL;
6281da177e4SLinus Torvalds 					break;
6291da177e4SLinus Torvalds 				}
6302941a486SPatrick McHardy 				t = netdev_priv(dev);
631b9fae5c9SPavel Emelyanov 				ipip_tunnel_unlink(ipn, t);
6321da177e4SLinus Torvalds 				t->parms.iph.saddr = p.iph.saddr;
6331da177e4SLinus Torvalds 				t->parms.iph.daddr = p.iph.daddr;
6341da177e4SLinus Torvalds 				memcpy(dev->dev_addr, &p.iph.saddr, 4);
6351da177e4SLinus Torvalds 				memcpy(dev->broadcast, &p.iph.daddr, 4);
636b9fae5c9SPavel Emelyanov 				ipip_tunnel_link(ipn, t);
6371da177e4SLinus Torvalds 				netdev_state_change(dev);
6381da177e4SLinus Torvalds 			}
6391da177e4SLinus Torvalds 		}
6401da177e4SLinus Torvalds 
6411da177e4SLinus Torvalds 		if (t) {
6421da177e4SLinus Torvalds 			err = 0;
6431da177e4SLinus Torvalds 			if (cmd == SIOCCHGTUNNEL) {
6441da177e4SLinus Torvalds 				t->parms.iph.ttl = p.iph.ttl;
6451da177e4SLinus Torvalds 				t->parms.iph.tos = p.iph.tos;
6461da177e4SLinus Torvalds 				t->parms.iph.frag_off = p.iph.frag_off;
6475533995bSMichal Schmidt 				if (t->parms.link != p.link) {
6485533995bSMichal Schmidt 					t->parms.link = p.link;
6495533995bSMichal Schmidt 					ipip_tunnel_bind_dev(dev);
6505533995bSMichal Schmidt 					netdev_state_change(dev);
6515533995bSMichal Schmidt 				}
6521da177e4SLinus Torvalds 			}
6531da177e4SLinus Torvalds 			if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
6541da177e4SLinus Torvalds 				err = -EFAULT;
6551da177e4SLinus Torvalds 		} else
6561da177e4SLinus Torvalds 			err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
6571da177e4SLinus Torvalds 		break;
6581da177e4SLinus Torvalds 
6591da177e4SLinus Torvalds 	case SIOCDELTUNNEL:
6601da177e4SLinus Torvalds 		err = -EPERM;
6611da177e4SLinus Torvalds 		if (!capable(CAP_NET_ADMIN))
6621da177e4SLinus Torvalds 			goto done;
6631da177e4SLinus Torvalds 
664b9855c54SPavel Emelyanov 		if (dev == ipn->fb_tunnel_dev) {
6651da177e4SLinus Torvalds 			err = -EFAULT;
6661da177e4SLinus Torvalds 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
6671da177e4SLinus Torvalds 				goto done;
6681da177e4SLinus Torvalds 			err = -ENOENT;
669b9fae5c9SPavel Emelyanov 			if ((t = ipip_tunnel_locate(net, &p, 0)) == NULL)
6701da177e4SLinus Torvalds 				goto done;
6711da177e4SLinus Torvalds 			err = -EPERM;
672b9855c54SPavel Emelyanov 			if (t->dev == ipn->fb_tunnel_dev)
6731da177e4SLinus Torvalds 				goto done;
6741da177e4SLinus Torvalds 			dev = t->dev;
6751da177e4SLinus Torvalds 		}
67622f8cde5SStephen Hemminger 		unregister_netdevice(dev);
67722f8cde5SStephen Hemminger 		err = 0;
6781da177e4SLinus Torvalds 		break;
6791da177e4SLinus Torvalds 
6801da177e4SLinus Torvalds 	default:
6811da177e4SLinus Torvalds 		err = -EINVAL;
6821da177e4SLinus Torvalds 	}
6831da177e4SLinus Torvalds 
6841da177e4SLinus Torvalds done:
6851da177e4SLinus Torvalds 	return err;
6861da177e4SLinus Torvalds }
6871da177e4SLinus Torvalds 
6881da177e4SLinus Torvalds static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
6891da177e4SLinus Torvalds {
6901da177e4SLinus Torvalds 	if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr))
6911da177e4SLinus Torvalds 		return -EINVAL;
6921da177e4SLinus Torvalds 	dev->mtu = new_mtu;
6931da177e4SLinus Torvalds 	return 0;
6941da177e4SLinus Torvalds }
6951da177e4SLinus Torvalds 
69623a12b14SStephen Hemminger static const struct net_device_ops ipip_netdev_ops = {
69723a12b14SStephen Hemminger 	.ndo_uninit	= ipip_tunnel_uninit,
69823a12b14SStephen Hemminger 	.ndo_start_xmit	= ipip_tunnel_xmit,
69923a12b14SStephen Hemminger 	.ndo_do_ioctl	= ipip_tunnel_ioctl,
70023a12b14SStephen Hemminger 	.ndo_change_mtu	= ipip_tunnel_change_mtu,
70123a12b14SStephen Hemminger 
70223a12b14SStephen Hemminger };
70323a12b14SStephen Hemminger 
7041da177e4SLinus Torvalds static void ipip_tunnel_setup(struct net_device *dev)
7051da177e4SLinus Torvalds {
70623a12b14SStephen Hemminger 	dev->netdev_ops		= &ipip_netdev_ops;
7071da177e4SLinus Torvalds 	dev->destructor		= free_netdev;
7081da177e4SLinus Torvalds 
7091da177e4SLinus Torvalds 	dev->type		= ARPHRD_TUNNEL;
7101da177e4SLinus Torvalds 	dev->hard_header_len 	= LL_MAX_HEADER + sizeof(struct iphdr);
71146f25dffSKris Katterjohn 	dev->mtu		= ETH_DATA_LEN - sizeof(struct iphdr);
7121da177e4SLinus Torvalds 	dev->flags		= IFF_NOARP;
7131da177e4SLinus Torvalds 	dev->iflink		= 0;
7141da177e4SLinus Torvalds 	dev->addr_len		= 4;
7150a826406SPavel Emelyanov 	dev->features		|= NETIF_F_NETNS_LOCAL;
7161da177e4SLinus Torvalds }
7171da177e4SLinus Torvalds 
71823a12b14SStephen Hemminger static void ipip_tunnel_init(struct net_device *dev)
7191da177e4SLinus Torvalds {
72023a12b14SStephen Hemminger 	struct ip_tunnel *tunnel = netdev_priv(dev);
7211da177e4SLinus Torvalds 
7221da177e4SLinus Torvalds 	tunnel->dev = dev;
7231da177e4SLinus Torvalds 	strcpy(tunnel->parms.name, dev->name);
7241da177e4SLinus Torvalds 
7251da177e4SLinus Torvalds 	memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
7261da177e4SLinus Torvalds 	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
7271da177e4SLinus Torvalds 
7285533995bSMichal Schmidt 	ipip_tunnel_bind_dev(dev);
7291da177e4SLinus Torvalds }
7301da177e4SLinus Torvalds 
73123a12b14SStephen Hemminger static void ipip_fb_tunnel_init(struct net_device *dev)
7321da177e4SLinus Torvalds {
7332941a486SPatrick McHardy 	struct ip_tunnel *tunnel = netdev_priv(dev);
7341da177e4SLinus Torvalds 	struct iphdr *iph = &tunnel->parms.iph;
73544d3c299SPavel Emelyanov 	struct ipip_net *ipn = net_generic(dev_net(dev), ipip_net_id);
7361da177e4SLinus Torvalds 
7371da177e4SLinus Torvalds 	tunnel->dev = dev;
7381da177e4SLinus Torvalds 	strcpy(tunnel->parms.name, dev->name);
7391da177e4SLinus Torvalds 
7401da177e4SLinus Torvalds 	iph->version		= 4;
7411da177e4SLinus Torvalds 	iph->protocol		= IPPROTO_IPIP;
7421da177e4SLinus Torvalds 	iph->ihl		= 5;
7431da177e4SLinus Torvalds 
7441da177e4SLinus Torvalds 	dev_hold(dev);
74544d3c299SPavel Emelyanov 	ipn->tunnels_wc[0]	= tunnel;
7461da177e4SLinus Torvalds }
7471da177e4SLinus Torvalds 
7481da177e4SLinus Torvalds static struct xfrm_tunnel ipip_handler = {
7491da177e4SLinus Torvalds 	.handler	=	ipip_rcv,
7501da177e4SLinus Torvalds 	.err_handler	=	ipip_err,
751d2acc347SHerbert Xu 	.priority	=	1,
7521da177e4SLinus Torvalds };
7531da177e4SLinus Torvalds 
7545747a1aaSStephen Hemminger static const char banner[] __initconst =
7551da177e4SLinus Torvalds 	KERN_INFO "IPv4 over IPv4 tunneling driver\n";
7561da177e4SLinus Torvalds 
75744d3c299SPavel Emelyanov static void ipip_destroy_tunnels(struct ipip_net *ipn)
75844d3c299SPavel Emelyanov {
75944d3c299SPavel Emelyanov 	int prio;
76044d3c299SPavel Emelyanov 
76144d3c299SPavel Emelyanov 	for (prio = 1; prio < 4; prio++) {
76244d3c299SPavel Emelyanov 		int h;
76344d3c299SPavel Emelyanov 		for (h = 0; h < HASH_SIZE; h++) {
76444d3c299SPavel Emelyanov 			struct ip_tunnel *t;
76544d3c299SPavel Emelyanov 			while ((t = ipn->tunnels[prio][h]) != NULL)
76644d3c299SPavel Emelyanov 				unregister_netdevice(t->dev);
76744d3c299SPavel Emelyanov 		}
76844d3c299SPavel Emelyanov 	}
76944d3c299SPavel Emelyanov }
77044d3c299SPavel Emelyanov 
77110dc4c7bSPavel Emelyanov static int ipip_init_net(struct net *net)
77210dc4c7bSPavel Emelyanov {
77310dc4c7bSPavel Emelyanov 	int err;
77410dc4c7bSPavel Emelyanov 	struct ipip_net *ipn;
77510dc4c7bSPavel Emelyanov 
77610dc4c7bSPavel Emelyanov 	err = -ENOMEM;
77744d3c299SPavel Emelyanov 	ipn = kzalloc(sizeof(struct ipip_net), GFP_KERNEL);
77810dc4c7bSPavel Emelyanov 	if (ipn == NULL)
77910dc4c7bSPavel Emelyanov 		goto err_alloc;
78010dc4c7bSPavel Emelyanov 
78110dc4c7bSPavel Emelyanov 	err = net_assign_generic(net, ipip_net_id, ipn);
78210dc4c7bSPavel Emelyanov 	if (err < 0)
78310dc4c7bSPavel Emelyanov 		goto err_assign;
78410dc4c7bSPavel Emelyanov 
78544d3c299SPavel Emelyanov 	ipn->tunnels[0] = ipn->tunnels_wc;
78644d3c299SPavel Emelyanov 	ipn->tunnels[1] = ipn->tunnels_l;
78744d3c299SPavel Emelyanov 	ipn->tunnels[2] = ipn->tunnels_r;
78844d3c299SPavel Emelyanov 	ipn->tunnels[3] = ipn->tunnels_r_l;
78944d3c299SPavel Emelyanov 
790b9855c54SPavel Emelyanov 	ipn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel),
791b9855c54SPavel Emelyanov 					   "tunl0",
792b9855c54SPavel Emelyanov 					   ipip_tunnel_setup);
793b9855c54SPavel Emelyanov 	if (!ipn->fb_tunnel_dev) {
794b9855c54SPavel Emelyanov 		err = -ENOMEM;
795b9855c54SPavel Emelyanov 		goto err_alloc_dev;
796b9855c54SPavel Emelyanov 	}
797be77e593SAlexey Dobriyan 	dev_net_set(ipn->fb_tunnel_dev, net);
798b9855c54SPavel Emelyanov 
79923a12b14SStephen Hemminger 	ipip_fb_tunnel_init(ipn->fb_tunnel_dev);
800b9855c54SPavel Emelyanov 
801b9855c54SPavel Emelyanov 	if ((err = register_netdev(ipn->fb_tunnel_dev)))
802b9855c54SPavel Emelyanov 		goto err_reg_dev;
803b9855c54SPavel Emelyanov 
80410dc4c7bSPavel Emelyanov 	return 0;
80510dc4c7bSPavel Emelyanov 
806b9855c54SPavel Emelyanov err_reg_dev:
807b9855c54SPavel Emelyanov 	free_netdev(ipn->fb_tunnel_dev);
808b9855c54SPavel Emelyanov err_alloc_dev:
809b9855c54SPavel Emelyanov 	/* nothing */
81010dc4c7bSPavel Emelyanov err_assign:
81110dc4c7bSPavel Emelyanov 	kfree(ipn);
81210dc4c7bSPavel Emelyanov err_alloc:
81310dc4c7bSPavel Emelyanov 	return err;
81410dc4c7bSPavel Emelyanov }
81510dc4c7bSPavel Emelyanov 
81610dc4c7bSPavel Emelyanov static void ipip_exit_net(struct net *net)
81710dc4c7bSPavel Emelyanov {
81810dc4c7bSPavel Emelyanov 	struct ipip_net *ipn;
81910dc4c7bSPavel Emelyanov 
82010dc4c7bSPavel Emelyanov 	ipn = net_generic(net, ipip_net_id);
821b9855c54SPavel Emelyanov 	rtnl_lock();
82244d3c299SPavel Emelyanov 	ipip_destroy_tunnels(ipn);
823b9855c54SPavel Emelyanov 	unregister_netdevice(ipn->fb_tunnel_dev);
824b9855c54SPavel Emelyanov 	rtnl_unlock();
82510dc4c7bSPavel Emelyanov 	kfree(ipn);
82610dc4c7bSPavel Emelyanov }
82710dc4c7bSPavel Emelyanov 
82810dc4c7bSPavel Emelyanov static struct pernet_operations ipip_net_ops = {
82910dc4c7bSPavel Emelyanov 	.init = ipip_init_net,
83010dc4c7bSPavel Emelyanov 	.exit = ipip_exit_net,
83110dc4c7bSPavel Emelyanov };
83210dc4c7bSPavel Emelyanov 
8331da177e4SLinus Torvalds static int __init ipip_init(void)
8341da177e4SLinus Torvalds {
8351da177e4SLinus Torvalds 	int err;
8361da177e4SLinus Torvalds 
8371da177e4SLinus Torvalds 	printk(banner);
8381da177e4SLinus Torvalds 
839c0d56408SKazunori MIYAZAWA 	if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
8401da177e4SLinus Torvalds 		printk(KERN_INFO "ipip init: can't register tunnel\n");
8411da177e4SLinus Torvalds 		return -EAGAIN;
8421da177e4SLinus Torvalds 	}
8431da177e4SLinus Torvalds 
84410dc4c7bSPavel Emelyanov 	err = register_pernet_gen_device(&ipip_net_id, &ipip_net_ops);
84510dc4c7bSPavel Emelyanov 	if (err)
846c0d56408SKazunori MIYAZAWA 		xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
847b9855c54SPavel Emelyanov 
848b9855c54SPavel Emelyanov 	return err;
8491da177e4SLinus Torvalds }
8501da177e4SLinus Torvalds 
8511da177e4SLinus Torvalds static void __exit ipip_fini(void)
8521da177e4SLinus Torvalds {
853c0d56408SKazunori MIYAZAWA 	if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
8541da177e4SLinus Torvalds 		printk(KERN_INFO "ipip close: can't deregister tunnel\n");
8551da177e4SLinus Torvalds 
85610dc4c7bSPavel Emelyanov 	unregister_pernet_gen_device(ipip_net_id, &ipip_net_ops);
8571da177e4SLinus Torvalds }
8581da177e4SLinus Torvalds 
8591da177e4SLinus Torvalds module_init(ipip_init);
8601da177e4SLinus Torvalds module_exit(ipip_fini);
8611da177e4SLinus Torvalds MODULE_LICENSE("GPL");
862