xref: /linux/net/ipv4/ipip.c (revision 737e828bdbdaf2f9d7de07f20a0308ac46ce5178)
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>
985a0e3ad6STejun Heo #include <linux/slab.h>
991da177e4SLinus Torvalds #include <asm/uaccess.h>
1001da177e4SLinus Torvalds #include <linux/skbuff.h>
1011da177e4SLinus Torvalds #include <linux/netdevice.h>
1021da177e4SLinus Torvalds #include <linux/in.h>
1031da177e4SLinus Torvalds #include <linux/tcp.h>
1041da177e4SLinus Torvalds #include <linux/udp.h>
1051da177e4SLinus Torvalds #include <linux/if_arp.h>
1061da177e4SLinus Torvalds #include <linux/mroute.h>
1071da177e4SLinus Torvalds #include <linux/init.h>
1081da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h>
10946f25dffSKris Katterjohn #include <linux/if_ether.h>
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds #include <net/sock.h>
1121da177e4SLinus Torvalds #include <net/ip.h>
1131da177e4SLinus Torvalds #include <net/icmp.h>
114c5441932SPravin B Shelar #include <net/ip_tunnels.h>
1151da177e4SLinus Torvalds #include <net/inet_ecn.h>
1161da177e4SLinus Torvalds #include <net/xfrm.h>
11710dc4c7bSPavel Emelyanov #include <net/net_namespace.h>
11810dc4c7bSPavel Emelyanov #include <net/netns/generic.h>
1191da177e4SLinus Torvalds 
120eccc1bb8Sstephen hemminger static bool log_ecn_error = true;
121eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644);
122eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
123eccc1bb8Sstephen hemminger 
124f99189b1SEric Dumazet static int ipip_net_id __read_mostly;
12510dc4c7bSPavel Emelyanov 
1263c97af99SEric Dumazet static int ipip_tunnel_init(struct net_device *dev);
1270974658dSNicolas Dichtel static struct rtnl_link_ops ipip_link_ops __read_mostly;
1281da177e4SLinus Torvalds 
129d2acc347SHerbert Xu static int ipip_err(struct sk_buff *skb, u32 info)
1301da177e4SLinus Torvalds {
1311da177e4SLinus Torvalds 
132071f92d0SRami Rosen /* All the routers (except for Linux) return only
1331da177e4SLinus Torvalds    8 bytes of packet payload. It means, that precise relaying of
1341da177e4SLinus Torvalds    ICMP in the real Internet is absolutely infeasible.
1351da177e4SLinus Torvalds  */
136fd58156eSPravin B Shelar 	struct net *net = dev_net(skb->dev);
137fd58156eSPravin B Shelar 	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
138b71d1d42SEric Dumazet 	const struct iphdr *iph = (const struct iphdr *)skb->data;
1391da177e4SLinus Torvalds 	struct ip_tunnel *t;
140d2acc347SHerbert Xu 	int err;
141fd58156eSPravin B Shelar 	const int type = icmp_hdr(skb)->type;
142fd58156eSPravin B Shelar 	const int code = icmp_hdr(skb)->code;
1431da177e4SLinus Torvalds 
144d2acc347SHerbert Xu 	err = -ENOENT;
145fd58156eSPravin B Shelar 	t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
146fd58156eSPravin B Shelar 			     iph->daddr, iph->saddr, 0);
14736393395SDavid S. Miller 	if (t == NULL)
14836393395SDavid S. Miller 		goto out;
14936393395SDavid S. Miller 
15036393395SDavid S. Miller 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
15136393395SDavid S. Miller 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
15236393395SDavid S. Miller 				 t->dev->ifindex, 0, IPPROTO_IPIP, 0);
15336393395SDavid S. Miller 		err = 0;
15436393395SDavid S. Miller 		goto out;
15536393395SDavid S. Miller 	}
15636393395SDavid S. Miller 
15755be7a9cSDavid S. Miller 	if (type == ICMP_REDIRECT) {
15855be7a9cSDavid S. Miller 		ipv4_redirect(skb, dev_net(skb->dev), t->dev->ifindex, 0,
15955be7a9cSDavid S. Miller 			      IPPROTO_IPIP, 0);
16055be7a9cSDavid S. Miller 		err = 0;
16155be7a9cSDavid S. Miller 		goto out;
16255be7a9cSDavid S. Miller 	}
16355be7a9cSDavid S. Miller 
16436393395SDavid S. Miller 	if (t->parms.iph.daddr == 0)
1651da177e4SLinus Torvalds 		goto out;
166d2acc347SHerbert Xu 
167d2acc347SHerbert Xu 	err = 0;
1681da177e4SLinus Torvalds 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
1691da177e4SLinus Torvalds 		goto out;
1701da177e4SLinus Torvalds 
17126d94b46SWei Yongjun 	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
1721da177e4SLinus Torvalds 		t->err_count++;
1731da177e4SLinus Torvalds 	else
1741da177e4SLinus Torvalds 		t->err_count = 1;
1751da177e4SLinus Torvalds 	t->err_time = jiffies;
176b0558ef2Sstephen hemminger 
177fd58156eSPravin B Shelar out:
178d2acc347SHerbert Xu 	return err;
1791da177e4SLinus Torvalds }
1801da177e4SLinus Torvalds 
181fd58156eSPravin B Shelar static const struct tnl_ptk_info tpi = {
182fd58156eSPravin B Shelar 	/* no tunnel info required for ipip. */
183fd58156eSPravin B Shelar 	.proto = htons(ETH_P_IP),
184fd58156eSPravin B Shelar };
185fd58156eSPravin B Shelar 
1861da177e4SLinus Torvalds static int ipip_rcv(struct sk_buff *skb)
1871da177e4SLinus Torvalds {
188fd58156eSPravin B Shelar 	struct net *net = dev_net(skb->dev);
189fd58156eSPravin B Shelar 	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
1901da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
1913d7b46cdSPravin B Shelar 	const struct iphdr *iph;
1921da177e4SLinus Torvalds 
1933d7b46cdSPravin B Shelar 	iph = ip_hdr(skb);
194fd58156eSPravin B Shelar 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
195fd58156eSPravin B Shelar 			iph->saddr, iph->daddr, 0);
196fd58156eSPravin B Shelar 	if (tunnel) {
197eccc1bb8Sstephen hemminger 		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
198eccc1bb8Sstephen hemminger 			goto drop;
199*737e828bSLi Hongjun 		if (iptunnel_pull_header(skb, 0, tpi.proto))
200*737e828bSLi Hongjun 			goto drop;
201fd58156eSPravin B Shelar 		return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error);
2021da177e4SLinus Torvalds 	}
2031da177e4SLinus Torvalds 
2041da177e4SLinus Torvalds 	return -1;
205eccc1bb8Sstephen hemminger 
206eccc1bb8Sstephen hemminger drop:
207eccc1bb8Sstephen hemminger 	kfree_skb(skb);
208eccc1bb8Sstephen hemminger 	return 0;
2091da177e4SLinus Torvalds }
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds /*
2121da177e4SLinus Torvalds  *	This function assumes it is being called from dev_queue_xmit()
2131da177e4SLinus Torvalds  *	and that skb is filled properly by that function.
2141da177e4SLinus Torvalds  */
2156fef4c0cSStephen Hemminger static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
2161da177e4SLinus Torvalds {
2172941a486SPatrick McHardy 	struct ip_tunnel *tunnel = netdev_priv(dev);
218b71d1d42SEric Dumazet 	const struct iphdr  *tiph = &tunnel->parms.iph;
2191da177e4SLinus Torvalds 
220fd58156eSPravin B Shelar 	if (unlikely(skb->protocol != htons(ETH_P_IP)))
2211da177e4SLinus Torvalds 		goto tx_error;
222cef401deSEric Dumazet 
223fd58156eSPravin B Shelar 	if (likely(!skb->encapsulation)) {
2244f3ed920SPravin B Shelar 		skb_reset_inner_headers(skb);
2254f3ed920SPravin B Shelar 		skb->encapsulation = 1;
2264f3ed920SPravin B Shelar 	}
2274f3ed920SPravin B Shelar 
228bf3d6a8fSNicolas Dichtel 	ip_tunnel_xmit(skb, dev, tiph, tiph->protocol);
2296ed10654SPatrick McHardy 	return NETDEV_TX_OK;
2301da177e4SLinus Torvalds 
2311da177e4SLinus Torvalds tx_error:
2323c97af99SEric Dumazet 	dev->stats.tx_errors++;
2331da177e4SLinus Torvalds 	dev_kfree_skb(skb);
2346ed10654SPatrick McHardy 	return NETDEV_TX_OK;
2351da177e4SLinus Torvalds }
2361da177e4SLinus Torvalds 
2371da177e4SLinus Torvalds static int
2381da177e4SLinus Torvalds ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2391da177e4SLinus Torvalds {
2401da177e4SLinus Torvalds 	int err = 0;
2411da177e4SLinus Torvalds 	struct ip_tunnel_parm p;
2421da177e4SLinus Torvalds 
2431da177e4SLinus Torvalds 	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
244fd58156eSPravin B Shelar 		return -EFAULT;
2451da177e4SLinus Torvalds 
2463b7b514fSCong Wang 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
2471da177e4SLinus Torvalds 		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
2481da177e4SLinus Torvalds 		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
249fd58156eSPravin B Shelar 			return -EINVAL;
2503b7b514fSCong Wang 	}
2513b7b514fSCong Wang 
2523b7b514fSCong Wang 	p.i_key = p.o_key = p.i_flags = p.o_flags = 0;
2531da177e4SLinus Torvalds 	if (p.iph.ttl)
2541da177e4SLinus Torvalds 		p.iph.frag_off |= htons(IP_DF);
2551da177e4SLinus Torvalds 
256fd58156eSPravin B Shelar 	err = ip_tunnel_ioctl(dev, &p, cmd);
257fd58156eSPravin B Shelar 	if (err)
2581da177e4SLinus Torvalds 		return err;
2591da177e4SLinus Torvalds 
260fd58156eSPravin B Shelar 	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
261fd58156eSPravin B Shelar 		return -EFAULT;
262fd58156eSPravin B Shelar 
2631da177e4SLinus Torvalds 	return 0;
2641da177e4SLinus Torvalds }
2651da177e4SLinus Torvalds 
26623a12b14SStephen Hemminger static const struct net_device_ops ipip_netdev_ops = {
267fd58156eSPravin B Shelar 	.ndo_init       = ipip_tunnel_init,
268fd58156eSPravin B Shelar 	.ndo_uninit     = ip_tunnel_uninit,
26923a12b14SStephen Hemminger 	.ndo_start_xmit	= ipip_tunnel_xmit,
27023a12b14SStephen Hemminger 	.ndo_do_ioctl	= ipip_tunnel_ioctl,
271fd58156eSPravin B Shelar 	.ndo_change_mtu = ip_tunnel_change_mtu,
272fd58156eSPravin B Shelar 	.ndo_get_stats64 = ip_tunnel_get_stats64,
27323a12b14SStephen Hemminger };
27423a12b14SStephen Hemminger 
275c3b89fbbSEric Dumazet #define IPIP_FEATURES (NETIF_F_SG |		\
276c3b89fbbSEric Dumazet 		       NETIF_F_FRAGLIST |	\
277c3b89fbbSEric Dumazet 		       NETIF_F_HIGHDMA |	\
278c3b89fbbSEric Dumazet 		       NETIF_F_HW_CSUM)
279c3b89fbbSEric Dumazet 
2801da177e4SLinus Torvalds static void ipip_tunnel_setup(struct net_device *dev)
2811da177e4SLinus Torvalds {
28223a12b14SStephen Hemminger 	dev->netdev_ops		= &ipip_netdev_ops;
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds 	dev->type		= ARPHRD_TUNNEL;
2851da177e4SLinus Torvalds 	dev->flags		= IFF_NOARP;
2861da177e4SLinus Torvalds 	dev->iflink		= 0;
2871da177e4SLinus Torvalds 	dev->addr_len		= 4;
2880a826406SPavel Emelyanov 	dev->features		|= NETIF_F_NETNS_LOCAL;
289153f0943SEric Dumazet 	dev->features		|= NETIF_F_LLTX;
29028e72216SEric Dumazet 	dev->priv_flags		&= ~IFF_XMIT_DST_RELEASE;
291c3b89fbbSEric Dumazet 
292c3b89fbbSEric Dumazet 	dev->features		|= IPIP_FEATURES;
293c3b89fbbSEric Dumazet 	dev->hw_features	|= IPIP_FEATURES;
294fd58156eSPravin B Shelar 	ip_tunnel_setup(dev, ipip_net_id);
2951da177e4SLinus Torvalds }
2961da177e4SLinus Torvalds 
2973c97af99SEric Dumazet static int ipip_tunnel_init(struct net_device *dev)
2981da177e4SLinus Torvalds {
29923a12b14SStephen Hemminger 	struct ip_tunnel *tunnel = netdev_priv(dev);
3001da177e4SLinus Torvalds 
3011da177e4SLinus Torvalds 	memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
3021da177e4SLinus Torvalds 	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
3031da177e4SLinus Torvalds 
304fd58156eSPravin B Shelar 	tunnel->hlen = 0;
305fd58156eSPravin B Shelar 	tunnel->parms.iph.protocol = IPPROTO_IPIP;
306fd58156eSPravin B Shelar 	return ip_tunnel_init(dev);
3071da177e4SLinus Torvalds }
3081da177e4SLinus Torvalds 
309be42da0eSNicolas Dichtel static void ipip_netlink_parms(struct nlattr *data[],
310be42da0eSNicolas Dichtel 			       struct ip_tunnel_parm *parms)
311be42da0eSNicolas Dichtel {
312be42da0eSNicolas Dichtel 	memset(parms, 0, sizeof(*parms));
313be42da0eSNicolas Dichtel 
314be42da0eSNicolas Dichtel 	parms->iph.version = 4;
315be42da0eSNicolas Dichtel 	parms->iph.protocol = IPPROTO_IPIP;
316be42da0eSNicolas Dichtel 	parms->iph.ihl = 5;
317be42da0eSNicolas Dichtel 
318be42da0eSNicolas Dichtel 	if (!data)
319be42da0eSNicolas Dichtel 		return;
320be42da0eSNicolas Dichtel 
321be42da0eSNicolas Dichtel 	if (data[IFLA_IPTUN_LINK])
322be42da0eSNicolas Dichtel 		parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
323be42da0eSNicolas Dichtel 
324be42da0eSNicolas Dichtel 	if (data[IFLA_IPTUN_LOCAL])
325fea379b2SNicolas Dichtel 		parms->iph.saddr = nla_get_be32(data[IFLA_IPTUN_LOCAL]);
326be42da0eSNicolas Dichtel 
327be42da0eSNicolas Dichtel 	if (data[IFLA_IPTUN_REMOTE])
328fea379b2SNicolas Dichtel 		parms->iph.daddr = nla_get_be32(data[IFLA_IPTUN_REMOTE]);
329be42da0eSNicolas Dichtel 
330be42da0eSNicolas Dichtel 	if (data[IFLA_IPTUN_TTL]) {
331be42da0eSNicolas Dichtel 		parms->iph.ttl = nla_get_u8(data[IFLA_IPTUN_TTL]);
332be42da0eSNicolas Dichtel 		if (parms->iph.ttl)
333be42da0eSNicolas Dichtel 			parms->iph.frag_off = htons(IP_DF);
334be42da0eSNicolas Dichtel 	}
335be42da0eSNicolas Dichtel 
336be42da0eSNicolas Dichtel 	if (data[IFLA_IPTUN_TOS])
337be42da0eSNicolas Dichtel 		parms->iph.tos = nla_get_u8(data[IFLA_IPTUN_TOS]);
338be42da0eSNicolas Dichtel 
339be42da0eSNicolas Dichtel 	if (!data[IFLA_IPTUN_PMTUDISC] || nla_get_u8(data[IFLA_IPTUN_PMTUDISC]))
340be42da0eSNicolas Dichtel 		parms->iph.frag_off = htons(IP_DF);
341be42da0eSNicolas Dichtel }
342be42da0eSNicolas Dichtel 
343be42da0eSNicolas Dichtel static int ipip_newlink(struct net *src_net, struct net_device *dev,
344be42da0eSNicolas Dichtel 			struct nlattr *tb[], struct nlattr *data[])
345be42da0eSNicolas Dichtel {
346fd58156eSPravin B Shelar 	struct ip_tunnel_parm p;
347be42da0eSNicolas Dichtel 
348fd58156eSPravin B Shelar 	ipip_netlink_parms(data, &p);
349fd58156eSPravin B Shelar 	return ip_tunnel_newlink(dev, tb, &p);
350be42da0eSNicolas Dichtel }
351be42da0eSNicolas Dichtel 
352be42da0eSNicolas Dichtel static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
353be42da0eSNicolas Dichtel 			   struct nlattr *data[])
354be42da0eSNicolas Dichtel {
355be42da0eSNicolas Dichtel 	struct ip_tunnel_parm p;
356be42da0eSNicolas Dichtel 
357be42da0eSNicolas Dichtel 	ipip_netlink_parms(data, &p);
358be42da0eSNicolas Dichtel 
359be42da0eSNicolas Dichtel 	if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
360be42da0eSNicolas Dichtel 	    (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
361be42da0eSNicolas Dichtel 		return -EINVAL;
362be42da0eSNicolas Dichtel 
363fd58156eSPravin B Shelar 	return ip_tunnel_changelink(dev, tb, &p);
364be42da0eSNicolas Dichtel }
365be42da0eSNicolas Dichtel 
3660974658dSNicolas Dichtel static size_t ipip_get_size(const struct net_device *dev)
3670974658dSNicolas Dichtel {
3680974658dSNicolas Dichtel 	return
3690974658dSNicolas Dichtel 		/* IFLA_IPTUN_LINK */
3700974658dSNicolas Dichtel 		nla_total_size(4) +
3710974658dSNicolas Dichtel 		/* IFLA_IPTUN_LOCAL */
3720974658dSNicolas Dichtel 		nla_total_size(4) +
3730974658dSNicolas Dichtel 		/* IFLA_IPTUN_REMOTE */
3740974658dSNicolas Dichtel 		nla_total_size(4) +
3750974658dSNicolas Dichtel 		/* IFLA_IPTUN_TTL */
3760974658dSNicolas Dichtel 		nla_total_size(1) +
3770974658dSNicolas Dichtel 		/* IFLA_IPTUN_TOS */
3780974658dSNicolas Dichtel 		nla_total_size(1) +
379befe2aa1SNicolas Dichtel 		/* IFLA_IPTUN_PMTUDISC */
380befe2aa1SNicolas Dichtel 		nla_total_size(1) +
3810974658dSNicolas Dichtel 		0;
3820974658dSNicolas Dichtel }
3830974658dSNicolas Dichtel 
3840974658dSNicolas Dichtel static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
3850974658dSNicolas Dichtel {
3860974658dSNicolas Dichtel 	struct ip_tunnel *tunnel = netdev_priv(dev);
3870974658dSNicolas Dichtel 	struct ip_tunnel_parm *parm = &tunnel->parms;
3880974658dSNicolas Dichtel 
3890974658dSNicolas Dichtel 	if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
3900974658dSNicolas Dichtel 	    nla_put_be32(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||
3910974658dSNicolas Dichtel 	    nla_put_be32(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
3920974658dSNicolas Dichtel 	    nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
393befe2aa1SNicolas Dichtel 	    nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
394befe2aa1SNicolas Dichtel 	    nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
395befe2aa1SNicolas Dichtel 		       !!(parm->iph.frag_off & htons(IP_DF))))
3960974658dSNicolas Dichtel 		goto nla_put_failure;
3970974658dSNicolas Dichtel 	return 0;
3980974658dSNicolas Dichtel 
3990974658dSNicolas Dichtel nla_put_failure:
4000974658dSNicolas Dichtel 	return -EMSGSIZE;
4010974658dSNicolas Dichtel }
4020974658dSNicolas Dichtel 
403be42da0eSNicolas Dichtel static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
404be42da0eSNicolas Dichtel 	[IFLA_IPTUN_LINK]		= { .type = NLA_U32 },
405be42da0eSNicolas Dichtel 	[IFLA_IPTUN_LOCAL]		= { .type = NLA_U32 },
406be42da0eSNicolas Dichtel 	[IFLA_IPTUN_REMOTE]		= { .type = NLA_U32 },
407be42da0eSNicolas Dichtel 	[IFLA_IPTUN_TTL]		= { .type = NLA_U8 },
408be42da0eSNicolas Dichtel 	[IFLA_IPTUN_TOS]		= { .type = NLA_U8 },
409be42da0eSNicolas Dichtel 	[IFLA_IPTUN_PMTUDISC]		= { .type = NLA_U8 },
410be42da0eSNicolas Dichtel };
411be42da0eSNicolas Dichtel 
4120974658dSNicolas Dichtel static struct rtnl_link_ops ipip_link_ops __read_mostly = {
4130974658dSNicolas Dichtel 	.kind		= "ipip",
4140974658dSNicolas Dichtel 	.maxtype	= IFLA_IPTUN_MAX,
415be42da0eSNicolas Dichtel 	.policy		= ipip_policy,
4160974658dSNicolas Dichtel 	.priv_size	= sizeof(struct ip_tunnel),
417be42da0eSNicolas Dichtel 	.setup		= ipip_tunnel_setup,
418be42da0eSNicolas Dichtel 	.newlink	= ipip_newlink,
419be42da0eSNicolas Dichtel 	.changelink	= ipip_changelink,
420fd58156eSPravin B Shelar 	.dellink	= ip_tunnel_dellink,
4210974658dSNicolas Dichtel 	.get_size	= ipip_get_size,
4220974658dSNicolas Dichtel 	.fill_info	= ipip_fill_info,
4230974658dSNicolas Dichtel };
4240974658dSNicolas Dichtel 
4256dcd814bSEric Dumazet static struct xfrm_tunnel ipip_handler __read_mostly = {
4261da177e4SLinus Torvalds 	.handler	=	ipip_rcv,
4271da177e4SLinus Torvalds 	.err_handler	=	ipip_err,
428d2acc347SHerbert Xu 	.priority	=	1,
4291da177e4SLinus Torvalds };
4301da177e4SLinus Torvalds 
4312c8c1e72SAlexey Dobriyan static int __net_init ipip_init_net(struct net *net)
43210dc4c7bSPavel Emelyanov {
433fd58156eSPravin B Shelar 	return ip_tunnel_init_net(net, ipip_net_id, &ipip_link_ops, "tunl0");
43410dc4c7bSPavel Emelyanov }
43510dc4c7bSPavel Emelyanov 
4362c8c1e72SAlexey Dobriyan static void __net_exit ipip_exit_net(struct net *net)
43710dc4c7bSPavel Emelyanov {
438fd58156eSPravin B Shelar 	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
439fd58156eSPravin B Shelar 	ip_tunnel_delete_net(itn);
44010dc4c7bSPavel Emelyanov }
44110dc4c7bSPavel Emelyanov 
44210dc4c7bSPavel Emelyanov static struct pernet_operations ipip_net_ops = {
44310dc4c7bSPavel Emelyanov 	.init = ipip_init_net,
44410dc4c7bSPavel Emelyanov 	.exit = ipip_exit_net,
44586de8a63SEric W. Biederman 	.id   = &ipip_net_id,
446fd58156eSPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
44710dc4c7bSPavel Emelyanov };
44810dc4c7bSPavel Emelyanov 
4491da177e4SLinus Torvalds static int __init ipip_init(void)
4501da177e4SLinus Torvalds {
4511da177e4SLinus Torvalds 	int err;
4521da177e4SLinus Torvalds 
453fd58156eSPravin B Shelar 	pr_info("ipip: IPv4 over IPv4 tunneling driver\n");
4541da177e4SLinus Torvalds 
45586de8a63SEric W. Biederman 	err = register_pernet_device(&ipip_net_ops);
456d5aa407fSAlexey Dobriyan 	if (err < 0)
457d5aa407fSAlexey Dobriyan 		return err;
458d5aa407fSAlexey Dobriyan 	err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
459d5aa407fSAlexey Dobriyan 	if (err < 0) {
460058bd4d2SJoe Perches 		pr_info("%s: can't register tunnel\n", __func__);
4610974658dSNicolas Dichtel 		goto xfrm_tunnel_failed;
462d5aa407fSAlexey Dobriyan 	}
4630974658dSNicolas Dichtel 	err = rtnl_link_register(&ipip_link_ops);
4640974658dSNicolas Dichtel 	if (err < 0)
4650974658dSNicolas Dichtel 		goto rtnl_link_failed;
4660974658dSNicolas Dichtel 
4670974658dSNicolas Dichtel out:
468b9855c54SPavel Emelyanov 	return err;
4690974658dSNicolas Dichtel 
4700974658dSNicolas Dichtel rtnl_link_failed:
4710974658dSNicolas Dichtel 	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
4720974658dSNicolas Dichtel xfrm_tunnel_failed:
4730974658dSNicolas Dichtel 	unregister_pernet_device(&ipip_net_ops);
4740974658dSNicolas Dichtel 	goto out;
4751da177e4SLinus Torvalds }
4761da177e4SLinus Torvalds 
4771da177e4SLinus Torvalds static void __exit ipip_fini(void)
4781da177e4SLinus Torvalds {
4790974658dSNicolas Dichtel 	rtnl_link_unregister(&ipip_link_ops);
480c0d56408SKazunori MIYAZAWA 	if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
481058bd4d2SJoe Perches 		pr_info("%s: can't deregister tunnel\n", __func__);
4821da177e4SLinus Torvalds 
48386de8a63SEric W. Biederman 	unregister_pernet_device(&ipip_net_ops);
4841da177e4SLinus Torvalds }
4851da177e4SLinus Torvalds 
4861da177e4SLinus Torvalds module_init(ipip_init);
4871da177e4SLinus Torvalds module_exit(ipip_fini);
4881da177e4SLinus Torvalds MODULE_LICENSE("GPL");
4898909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("tunl0");
490