xref: /linux/net/ipv4/ip_gre.c (revision c29a70d2cadfea443c027d23481f820530b70057)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *	Linux NET3:	GRE over IP protocol decoder.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *	Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *	This program is free software; you can redistribute it and/or
71da177e4SLinus Torvalds  *	modify it under the terms of the GNU General Public License
81da177e4SLinus Torvalds  *	as published by the Free Software Foundation; either version
91da177e4SLinus Torvalds  *	2 of the License, or (at your option) any later version.
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
13afd46503SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14afd46503SJoe Perches 
154fc268d2SRandy Dunlap #include <linux/capability.h>
161da177e4SLinus Torvalds #include <linux/module.h>
171da177e4SLinus Torvalds #include <linux/types.h>
181da177e4SLinus Torvalds #include <linux/kernel.h>
195a0e3ad6STejun Heo #include <linux/slab.h>
201da177e4SLinus Torvalds #include <asm/uaccess.h>
211da177e4SLinus Torvalds #include <linux/skbuff.h>
221da177e4SLinus Torvalds #include <linux/netdevice.h>
231da177e4SLinus Torvalds #include <linux/in.h>
241da177e4SLinus Torvalds #include <linux/tcp.h>
251da177e4SLinus Torvalds #include <linux/udp.h>
261da177e4SLinus Torvalds #include <linux/if_arp.h>
271da177e4SLinus Torvalds #include <linux/mroute.h>
282e15ea39SPravin B Shelar #include <linux/if_vlan.h>
291da177e4SLinus Torvalds #include <linux/init.h>
301da177e4SLinus Torvalds #include <linux/in6.h>
311da177e4SLinus Torvalds #include <linux/inetdevice.h>
321da177e4SLinus Torvalds #include <linux/igmp.h>
331da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h>
34e1a80002SHerbert Xu #include <linux/etherdevice.h>
3546f25dffSKris Katterjohn #include <linux/if_ether.h>
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds #include <net/sock.h>
381da177e4SLinus Torvalds #include <net/ip.h>
391da177e4SLinus Torvalds #include <net/icmp.h>
401da177e4SLinus Torvalds #include <net/protocol.h>
41c5441932SPravin B Shelar #include <net/ip_tunnels.h>
421da177e4SLinus Torvalds #include <net/arp.h>
431da177e4SLinus Torvalds #include <net/checksum.h>
441da177e4SLinus Torvalds #include <net/dsfield.h>
451da177e4SLinus Torvalds #include <net/inet_ecn.h>
461da177e4SLinus Torvalds #include <net/xfrm.h>
4759a4c759SPavel Emelyanov #include <net/net_namespace.h>
4859a4c759SPavel Emelyanov #include <net/netns/generic.h>
49c19e654dSHerbert Xu #include <net/rtnetlink.h>
5000959adeSDmitry Kozlov #include <net/gre.h>
512e15ea39SPravin B Shelar #include <net/dst_metadata.h>
521da177e4SLinus Torvalds 
53dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
541da177e4SLinus Torvalds #include <net/ipv6.h>
551da177e4SLinus Torvalds #include <net/ip6_fib.h>
561da177e4SLinus Torvalds #include <net/ip6_route.h>
571da177e4SLinus Torvalds #endif
581da177e4SLinus Torvalds 
591da177e4SLinus Torvalds /*
601da177e4SLinus Torvalds    Problems & solutions
611da177e4SLinus Torvalds    --------------------
621da177e4SLinus Torvalds 
631da177e4SLinus Torvalds    1. The most important issue is detecting local dead loops.
641da177e4SLinus Torvalds    They would cause complete host lockup in transmit, which
651da177e4SLinus Torvalds    would be "resolved" by stack overflow or, if queueing is enabled,
661da177e4SLinus Torvalds    with infinite looping in net_bh.
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds    We cannot track such dead loops during route installation,
691da177e4SLinus Torvalds    it is infeasible task. The most general solutions would be
701da177e4SLinus Torvalds    to keep skb->encapsulation counter (sort of local ttl),
716d0722a2SEric Dumazet    and silently drop packet when it expires. It is a good
72bff52857Sstephen hemminger    solution, but it supposes maintaining new variable in ALL
731da177e4SLinus Torvalds    skb, even if no tunneling is used.
741da177e4SLinus Torvalds 
756d0722a2SEric Dumazet    Current solution: xmit_recursion breaks dead loops. This is a percpu
766d0722a2SEric Dumazet    counter, since when we enter the first ndo_xmit(), cpu migration is
776d0722a2SEric Dumazet    forbidden. We force an exit if this counter reaches RECURSION_LIMIT
781da177e4SLinus Torvalds 
791da177e4SLinus Torvalds    2. Networking dead loops would not kill routers, but would really
801da177e4SLinus Torvalds    kill network. IP hop limit plays role of "t->recursion" in this case,
811da177e4SLinus Torvalds    if we copy it from packet being encapsulated to upper header.
821da177e4SLinus Torvalds    It is very good solution, but it introduces two problems:
831da177e4SLinus Torvalds 
841da177e4SLinus Torvalds    - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
851da177e4SLinus Torvalds      do not work over tunnels.
861da177e4SLinus Torvalds    - traceroute does not work. I planned to relay ICMP from tunnel,
871da177e4SLinus Torvalds      so that this problem would be solved and traceroute output
881da177e4SLinus Torvalds      would even more informative. This idea appeared to be wrong:
891da177e4SLinus Torvalds      only Linux complies to rfc1812 now (yes, guys, Linux is the only
901da177e4SLinus Torvalds      true router now :-)), all routers (at least, in neighbourhood of mine)
911da177e4SLinus Torvalds      return only 8 bytes of payload. It is the end.
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds    Hence, if we want that OSPF worked or traceroute said something reasonable,
941da177e4SLinus Torvalds    we should search for another solution.
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds    One of them is to parse packet trying to detect inner encapsulation
971da177e4SLinus Torvalds    made by our node. It is difficult or even impossible, especially,
98bff52857Sstephen hemminger    taking into account fragmentation. TO be short, ttl is not solution at all.
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds    Current solution: The solution was UNEXPECTEDLY SIMPLE.
1011da177e4SLinus Torvalds    We force DF flag on tunnels with preconfigured hop limit,
1021da177e4SLinus Torvalds    that is ALL. :-) Well, it does not remove the problem completely,
1031da177e4SLinus Torvalds    but exponential growth of network traffic is changed to linear
1041da177e4SLinus Torvalds    (branches, that exceed pmtu are pruned) and tunnel mtu
105bff52857Sstephen hemminger    rapidly degrades to value <68, where looping stops.
1061da177e4SLinus Torvalds    Yes, it is not good if there exists a router in the loop,
1071da177e4SLinus Torvalds    which does not force DF, even when encapsulating packets have DF set.
1081da177e4SLinus Torvalds    But it is not our problem! Nobody could accuse us, we made
1091da177e4SLinus Torvalds    all that we could make. Even if it is your gated who injected
1101da177e4SLinus Torvalds    fatal route to network, even if it were you who configured
1111da177e4SLinus Torvalds    fatal static route: you are innocent. :-)
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds    Alexey Kuznetsov.
1141da177e4SLinus Torvalds  */
1151da177e4SLinus Torvalds 
116eccc1bb8Sstephen hemminger static bool log_ecn_error = true;
117eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644);
118eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
119eccc1bb8Sstephen hemminger 
120c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly;
1211da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev);
122eb8ce741SPavel Emelyanov 
123f99189b1SEric Dumazet static int ipgre_net_id __read_mostly;
124c5441932SPravin B Shelar static int gre_tap_net_id __read_mostly;
125eb8ce741SPavel Emelyanov 
1269f57c67cSPravin B Shelar static int ip_gre_calc_hlen(__be16 o_flags)
1279f57c67cSPravin B Shelar {
1289f57c67cSPravin B Shelar 	int addend = 4;
1299f57c67cSPravin B Shelar 
1309f57c67cSPravin B Shelar 	if (o_flags & TUNNEL_CSUM)
1319f57c67cSPravin B Shelar 		addend += 4;
1329f57c67cSPravin B Shelar 	if (o_flags & TUNNEL_KEY)
1339f57c67cSPravin B Shelar 		addend += 4;
1349f57c67cSPravin B Shelar 	if (o_flags & TUNNEL_SEQ)
1359f57c67cSPravin B Shelar 		addend += 4;
1369f57c67cSPravin B Shelar 	return addend;
1379f57c67cSPravin B Shelar }
1389f57c67cSPravin B Shelar 
1399f57c67cSPravin B Shelar static __be16 gre_flags_to_tnl_flags(__be16 flags)
1409f57c67cSPravin B Shelar {
1419f57c67cSPravin B Shelar 	__be16 tflags = 0;
1429f57c67cSPravin B Shelar 
1439f57c67cSPravin B Shelar 	if (flags & GRE_CSUM)
1449f57c67cSPravin B Shelar 		tflags |= TUNNEL_CSUM;
1459f57c67cSPravin B Shelar 	if (flags & GRE_ROUTING)
1469f57c67cSPravin B Shelar 		tflags |= TUNNEL_ROUTING;
1479f57c67cSPravin B Shelar 	if (flags & GRE_KEY)
1489f57c67cSPravin B Shelar 		tflags |= TUNNEL_KEY;
1499f57c67cSPravin B Shelar 	if (flags & GRE_SEQ)
1509f57c67cSPravin B Shelar 		tflags |= TUNNEL_SEQ;
1519f57c67cSPravin B Shelar 	if (flags & GRE_STRICT)
1529f57c67cSPravin B Shelar 		tflags |= TUNNEL_STRICT;
1539f57c67cSPravin B Shelar 	if (flags & GRE_REC)
1549f57c67cSPravin B Shelar 		tflags |= TUNNEL_REC;
1559f57c67cSPravin B Shelar 	if (flags & GRE_VERSION)
1569f57c67cSPravin B Shelar 		tflags |= TUNNEL_VERSION;
1579f57c67cSPravin B Shelar 
1589f57c67cSPravin B Shelar 	return tflags;
1599f57c67cSPravin B Shelar }
1609f57c67cSPravin B Shelar 
1619f57c67cSPravin B Shelar static __be16 tnl_flags_to_gre_flags(__be16 tflags)
1629f57c67cSPravin B Shelar {
1639f57c67cSPravin B Shelar 	__be16 flags = 0;
1649f57c67cSPravin B Shelar 
1659f57c67cSPravin B Shelar 	if (tflags & TUNNEL_CSUM)
1669f57c67cSPravin B Shelar 		flags |= GRE_CSUM;
1679f57c67cSPravin B Shelar 	if (tflags & TUNNEL_ROUTING)
1689f57c67cSPravin B Shelar 		flags |= GRE_ROUTING;
1699f57c67cSPravin B Shelar 	if (tflags & TUNNEL_KEY)
1709f57c67cSPravin B Shelar 		flags |= GRE_KEY;
1719f57c67cSPravin B Shelar 	if (tflags & TUNNEL_SEQ)
1729f57c67cSPravin B Shelar 		flags |= GRE_SEQ;
1739f57c67cSPravin B Shelar 	if (tflags & TUNNEL_STRICT)
1749f57c67cSPravin B Shelar 		flags |= GRE_STRICT;
1759f57c67cSPravin B Shelar 	if (tflags & TUNNEL_REC)
1769f57c67cSPravin B Shelar 		flags |= GRE_REC;
1779f57c67cSPravin B Shelar 	if (tflags & TUNNEL_VERSION)
1789f57c67cSPravin B Shelar 		flags |= GRE_VERSION;
1799f57c67cSPravin B Shelar 
1809f57c67cSPravin B Shelar 	return flags;
1819f57c67cSPravin B Shelar }
1829f57c67cSPravin B Shelar 
1839f57c67cSPravin B Shelar static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
1849f57c67cSPravin B Shelar 			    bool *csum_err)
1859f57c67cSPravin B Shelar {
1869f57c67cSPravin B Shelar 	const struct gre_base_hdr *greh;
1879f57c67cSPravin B Shelar 	__be32 *options;
1889f57c67cSPravin B Shelar 	int hdr_len;
1899f57c67cSPravin B Shelar 
1909f57c67cSPravin B Shelar 	if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr))))
1919f57c67cSPravin B Shelar 		return -EINVAL;
1929f57c67cSPravin B Shelar 
1939f57c67cSPravin B Shelar 	greh = (struct gre_base_hdr *)skb_transport_header(skb);
1949f57c67cSPravin B Shelar 	if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING)))
1959f57c67cSPravin B Shelar 		return -EINVAL;
1969f57c67cSPravin B Shelar 
1979f57c67cSPravin B Shelar 	tpi->flags = gre_flags_to_tnl_flags(greh->flags);
1989f57c67cSPravin B Shelar 	hdr_len = ip_gre_calc_hlen(tpi->flags);
1999f57c67cSPravin B Shelar 
2009f57c67cSPravin B Shelar 	if (!pskb_may_pull(skb, hdr_len))
2019f57c67cSPravin B Shelar 		return -EINVAL;
2029f57c67cSPravin B Shelar 
2039f57c67cSPravin B Shelar 	greh = (struct gre_base_hdr *)skb_transport_header(skb);
2049f57c67cSPravin B Shelar 	tpi->proto = greh->protocol;
2059f57c67cSPravin B Shelar 
2069f57c67cSPravin B Shelar 	options = (__be32 *)(greh + 1);
2079f57c67cSPravin B Shelar 	if (greh->flags & GRE_CSUM) {
2089f57c67cSPravin B Shelar 		if (skb_checksum_simple_validate(skb)) {
2099f57c67cSPravin B Shelar 			*csum_err = true;
2109f57c67cSPravin B Shelar 			return -EINVAL;
2119f57c67cSPravin B Shelar 		}
2129f57c67cSPravin B Shelar 
2139f57c67cSPravin B Shelar 		skb_checksum_try_convert(skb, IPPROTO_GRE, 0,
2149f57c67cSPravin B Shelar 					 null_compute_pseudo);
2159f57c67cSPravin B Shelar 		options++;
2169f57c67cSPravin B Shelar 	}
2179f57c67cSPravin B Shelar 
2189f57c67cSPravin B Shelar 	if (greh->flags & GRE_KEY) {
2199f57c67cSPravin B Shelar 		tpi->key = *options;
2209f57c67cSPravin B Shelar 		options++;
2219f57c67cSPravin B Shelar 	} else {
2229f57c67cSPravin B Shelar 		tpi->key = 0;
2239f57c67cSPravin B Shelar 	}
2249f57c67cSPravin B Shelar 	if (unlikely(greh->flags & GRE_SEQ)) {
2259f57c67cSPravin B Shelar 		tpi->seq = *options;
2269f57c67cSPravin B Shelar 		options++;
2279f57c67cSPravin B Shelar 	} else {
2289f57c67cSPravin B Shelar 		tpi->seq = 0;
2299f57c67cSPravin B Shelar 	}
2309f57c67cSPravin B Shelar 	/* WCCP version 1 and 2 protocol decoding.
2319f57c67cSPravin B Shelar 	 * - Change protocol to IP
2329f57c67cSPravin B Shelar 	 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
2339f57c67cSPravin B Shelar 	 */
2349f57c67cSPravin B Shelar 	if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) {
2359f57c67cSPravin B Shelar 		tpi->proto = htons(ETH_P_IP);
2369f57c67cSPravin B Shelar 		if ((*(u8 *)options & 0xF0) != 0x40) {
2379f57c67cSPravin B Shelar 			hdr_len += 4;
2389f57c67cSPravin B Shelar 			if (!pskb_may_pull(skb, hdr_len))
2399f57c67cSPravin B Shelar 				return -EINVAL;
2409f57c67cSPravin B Shelar 		}
2419f57c67cSPravin B Shelar 	}
2429f57c67cSPravin B Shelar 	return iptunnel_pull_header(skb, hdr_len, tpi->proto);
2439f57c67cSPravin B Shelar }
2449f57c67cSPravin B Shelar 
2459f57c67cSPravin B Shelar static void ipgre_err(struct sk_buff *skb, u32 info,
246bda7bb46SPravin B Shelar 		      const struct tnl_ptk_info *tpi)
2471da177e4SLinus Torvalds {
2481da177e4SLinus Torvalds 
249071f92d0SRami Rosen 	/* All the routers (except for Linux) return only
2501da177e4SLinus Torvalds 	   8 bytes of packet payload. It means, that precise relaying of
2511da177e4SLinus Torvalds 	   ICMP in the real Internet is absolutely infeasible.
2521da177e4SLinus Torvalds 
2531da177e4SLinus Torvalds 	   Moreover, Cisco "wise men" put GRE key to the third word
254c5441932SPravin B Shelar 	   in GRE header. It makes impossible maintaining even soft
255c5441932SPravin B Shelar 	   state for keyed GRE tunnels with enabled checksum. Tell
256c5441932SPravin B Shelar 	   them "thank you".
2571da177e4SLinus Torvalds 
2581da177e4SLinus Torvalds 	   Well, I wonder, rfc1812 was written by Cisco employee,
259bff52857Sstephen hemminger 	   what the hell these idiots break standards established
260bff52857Sstephen hemminger 	   by themselves???
2611da177e4SLinus Torvalds 	   */
262c5441932SPravin B Shelar 	struct net *net = dev_net(skb->dev);
263c5441932SPravin B Shelar 	struct ip_tunnel_net *itn;
26496f5a846SEric Dumazet 	const struct iphdr *iph;
26588c7664fSArnaldo Carvalho de Melo 	const int type = icmp_hdr(skb)->type;
26688c7664fSArnaldo Carvalho de Melo 	const int code = icmp_hdr(skb)->code;
2671da177e4SLinus Torvalds 	struct ip_tunnel *t;
268d2083287Sstephen hemminger 
2691da177e4SLinus Torvalds 	switch (type) {
2701da177e4SLinus Torvalds 	default:
2711da177e4SLinus Torvalds 	case ICMP_PARAMETERPROB:
2729f57c67cSPravin B Shelar 		return;
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 	case ICMP_DEST_UNREACH:
2751da177e4SLinus Torvalds 		switch (code) {
2761da177e4SLinus Torvalds 		case ICMP_SR_FAILED:
2771da177e4SLinus Torvalds 		case ICMP_PORT_UNREACH:
2781da177e4SLinus Torvalds 			/* Impossible event. */
2799f57c67cSPravin B Shelar 			return;
2801da177e4SLinus Torvalds 		default:
2811da177e4SLinus Torvalds 			/* All others are translated to HOST_UNREACH.
2821da177e4SLinus Torvalds 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
2831da177e4SLinus Torvalds 			   I believe they are just ether pollution. --ANK
2841da177e4SLinus Torvalds 			 */
2851da177e4SLinus Torvalds 			break;
2861da177e4SLinus Torvalds 		}
2871da177e4SLinus Torvalds 		break;
2889f57c67cSPravin B Shelar 
2891da177e4SLinus Torvalds 	case ICMP_TIME_EXCEEDED:
2901da177e4SLinus Torvalds 		if (code != ICMP_EXC_TTL)
2919f57c67cSPravin B Shelar 			return;
2921da177e4SLinus Torvalds 		break;
29355be7a9cSDavid S. Miller 
29455be7a9cSDavid S. Miller 	case ICMP_REDIRECT:
29555be7a9cSDavid S. Miller 		break;
2961da177e4SLinus Torvalds 	}
2971da177e4SLinus Torvalds 
298bda7bb46SPravin B Shelar 	if (tpi->proto == htons(ETH_P_TEB))
299c5441932SPravin B Shelar 		itn = net_generic(net, gre_tap_net_id);
300c5441932SPravin B Shelar 	else
301c5441932SPravin B Shelar 		itn = net_generic(net, ipgre_net_id);
302c5441932SPravin B Shelar 
303c0c0c50fSDuan Jiong 	iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
304bda7bb46SPravin B Shelar 	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
305bda7bb46SPravin B Shelar 			     iph->daddr, iph->saddr, tpi->key);
306d2083287Sstephen hemminger 
30751456b29SIan Morris 	if (!t)
3089f57c67cSPravin B Shelar 		return;
30936393395SDavid S. Miller 
31036393395SDavid S. Miller 	if (t->parms.iph.daddr == 0 ||
311f97c1e0cSJoe Perches 	    ipv4_is_multicast(t->parms.iph.daddr))
3129f57c67cSPravin B Shelar 		return;
3131da177e4SLinus Torvalds 
3141da177e4SLinus Torvalds 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
3159f57c67cSPravin B Shelar 		return;
3161da177e4SLinus Torvalds 
317da6185d8SWei Yongjun 	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
3181da177e4SLinus Torvalds 		t->err_count++;
3191da177e4SLinus Torvalds 	else
3201da177e4SLinus Torvalds 		t->err_count = 1;
3211da177e4SLinus Torvalds 	t->err_time = jiffies;
3229f57c67cSPravin B Shelar }
3239f57c67cSPravin B Shelar 
3249f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info)
3259f57c67cSPravin B Shelar {
3269f57c67cSPravin B Shelar 	/* All the routers (except for Linux) return only
3279f57c67cSPravin B Shelar 	 * 8 bytes of packet payload. It means, that precise relaying of
3289f57c67cSPravin B Shelar 	 * ICMP in the real Internet is absolutely infeasible.
3299f57c67cSPravin B Shelar 	 *
3309f57c67cSPravin B Shelar 	 * Moreover, Cisco "wise men" put GRE key to the third word
3319f57c67cSPravin B Shelar 	 * in GRE header. It makes impossible maintaining even soft
3329f57c67cSPravin B Shelar 	 * state for keyed
3339f57c67cSPravin B Shelar 	 * GRE tunnels with enabled checksum. Tell them "thank you".
3349f57c67cSPravin B Shelar 	 *
3359f57c67cSPravin B Shelar 	 * Well, I wonder, rfc1812 was written by Cisco employee,
3369f57c67cSPravin B Shelar 	 * what the hell these idiots break standards established
3379f57c67cSPravin B Shelar 	 * by themselves???
3389f57c67cSPravin B Shelar 	 */
3399f57c67cSPravin B Shelar 
3409f57c67cSPravin B Shelar 	const int type = icmp_hdr(skb)->type;
3419f57c67cSPravin B Shelar 	const int code = icmp_hdr(skb)->code;
3429f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
3439f57c67cSPravin B Shelar 	bool csum_err = false;
3449f57c67cSPravin B Shelar 
3459f57c67cSPravin B Shelar 	if (parse_gre_header(skb, &tpi, &csum_err)) {
3469f57c67cSPravin B Shelar 		if (!csum_err)		/* ignore csum errors. */
3479f57c67cSPravin B Shelar 			return;
3489f57c67cSPravin B Shelar 	}
3499f57c67cSPravin B Shelar 
3509f57c67cSPravin B Shelar 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
3519f57c67cSPravin B Shelar 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
3529f57c67cSPravin B Shelar 				 skb->dev->ifindex, 0, IPPROTO_GRE, 0);
3539f57c67cSPravin B Shelar 		return;
3549f57c67cSPravin B Shelar 	}
3559f57c67cSPravin B Shelar 	if (type == ICMP_REDIRECT) {
3569f57c67cSPravin B Shelar 		ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0,
3579f57c67cSPravin B Shelar 			      IPPROTO_GRE, 0);
3589f57c67cSPravin B Shelar 		return;
3599f57c67cSPravin B Shelar 	}
3609f57c67cSPravin B Shelar 
3619f57c67cSPravin B Shelar 	ipgre_err(skb, info, &tpi);
3621da177e4SLinus Torvalds }
3631da177e4SLinus Torvalds 
3642e15ea39SPravin B Shelar static __be64 key_to_tunnel_id(__be32 key)
3652e15ea39SPravin B Shelar {
3662e15ea39SPravin B Shelar #ifdef __BIG_ENDIAN
3672e15ea39SPravin B Shelar 	return (__force __be64)((__force u32)key);
3682e15ea39SPravin B Shelar #else
3692e15ea39SPravin B Shelar 	return (__force __be64)((__force u64)key << 32);
3702e15ea39SPravin B Shelar #endif
3712e15ea39SPravin B Shelar }
3722e15ea39SPravin B Shelar 
3732e15ea39SPravin B Shelar /* Returns the least-significant 32 bits of a __be64. */
3742e15ea39SPravin B Shelar static __be32 tunnel_id_to_key(__be64 x)
3752e15ea39SPravin B Shelar {
3762e15ea39SPravin B Shelar #ifdef __BIG_ENDIAN
3772e15ea39SPravin B Shelar 	return (__force __be32)x;
3782e15ea39SPravin B Shelar #else
3792e15ea39SPravin B Shelar 	return (__force __be32)((__force u64)x >> 32);
3802e15ea39SPravin B Shelar #endif
3812e15ea39SPravin B Shelar }
3822e15ea39SPravin B Shelar 
383bda7bb46SPravin B Shelar static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
3841da177e4SLinus Torvalds {
385c5441932SPravin B Shelar 	struct net *net = dev_net(skb->dev);
3862e15ea39SPravin B Shelar 	struct metadata_dst *tun_dst = NULL;
387c5441932SPravin B Shelar 	struct ip_tunnel_net *itn;
388b71d1d42SEric Dumazet 	const struct iphdr *iph;
3891da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
3901da177e4SLinus Torvalds 
391bda7bb46SPravin B Shelar 	if (tpi->proto == htons(ETH_P_TEB))
392c5441932SPravin B Shelar 		itn = net_generic(net, gre_tap_net_id);
393c5441932SPravin B Shelar 	else
394c5441932SPravin B Shelar 		itn = net_generic(net, ipgre_net_id);
395c5441932SPravin B Shelar 
396eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
397bda7bb46SPravin B Shelar 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
398bda7bb46SPravin B Shelar 				  iph->saddr, iph->daddr, tpi->key);
3991da177e4SLinus Torvalds 
400d2083287Sstephen hemminger 	if (tunnel) {
4010e3da5bbSTimo Teräs 		skb_pop_mac_header(skb);
4022e15ea39SPravin B Shelar 		if (tunnel->collect_md) {
403*c29a70d2SPravin B Shelar 			__be16 flags;
404*c29a70d2SPravin B Shelar 			__be64 tun_id;
4052e15ea39SPravin B Shelar 
406*c29a70d2SPravin B Shelar 			flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
407*c29a70d2SPravin B Shelar 			tun_id = key_to_tunnel_id(tpi->key);
408*c29a70d2SPravin B Shelar 			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
4092e15ea39SPravin B Shelar 			if (!tun_dst)
4102e15ea39SPravin B Shelar 				return PACKET_REJECT;
4112e15ea39SPravin B Shelar 		}
4122e15ea39SPravin B Shelar 
4132e15ea39SPravin B Shelar 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
414bda7bb46SPravin B Shelar 		return PACKET_RCVD;
4151da177e4SLinus Torvalds 	}
416bda7bb46SPravin B Shelar 	return PACKET_REJECT;
4171da177e4SLinus Torvalds }
4181da177e4SLinus Torvalds 
4199f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb)
4209f57c67cSPravin B Shelar {
4219f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
4229f57c67cSPravin B Shelar 	bool csum_err = false;
4239f57c67cSPravin B Shelar 
4249f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST
4259f57c67cSPravin B Shelar 	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
4269f57c67cSPravin B Shelar 		/* Looped back packet, drop it! */
4279f57c67cSPravin B Shelar 		if (rt_is_output_route(skb_rtable(skb)))
4289f57c67cSPravin B Shelar 			goto drop;
4299f57c67cSPravin B Shelar 	}
4309f57c67cSPravin B Shelar #endif
4319f57c67cSPravin B Shelar 
4329f57c67cSPravin B Shelar 	if (parse_gre_header(skb, &tpi, &csum_err) < 0)
4339f57c67cSPravin B Shelar 		goto drop;
4349f57c67cSPravin B Shelar 
4359f57c67cSPravin B Shelar 	if (ipgre_rcv(skb, &tpi) == PACKET_RCVD)
4369f57c67cSPravin B Shelar 		return 0;
4379f57c67cSPravin B Shelar 
4389f57c67cSPravin B Shelar 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
4399f57c67cSPravin B Shelar drop:
4409f57c67cSPravin B Shelar 	kfree_skb(skb);
4419f57c67cSPravin B Shelar 	return 0;
4429f57c67cSPravin B Shelar }
4439f57c67cSPravin B Shelar 
4442e15ea39SPravin B Shelar static void build_header(struct sk_buff *skb, int hdr_len, __be16 flags,
4452e15ea39SPravin B Shelar 			 __be16 proto, __be32 key, __be32 seq)
4462e15ea39SPravin B Shelar {
4472e15ea39SPravin B Shelar 	struct gre_base_hdr *greh;
4482e15ea39SPravin B Shelar 
4492e15ea39SPravin B Shelar 	skb_push(skb, hdr_len);
4502e15ea39SPravin B Shelar 
4512e15ea39SPravin B Shelar 	skb_reset_transport_header(skb);
4522e15ea39SPravin B Shelar 	greh = (struct gre_base_hdr *)skb->data;
4532e15ea39SPravin B Shelar 	greh->flags = tnl_flags_to_gre_flags(flags);
4542e15ea39SPravin B Shelar 	greh->protocol = proto;
4552e15ea39SPravin B Shelar 
4562e15ea39SPravin B Shelar 	if (flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) {
4572e15ea39SPravin B Shelar 		__be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
4582e15ea39SPravin B Shelar 
4592e15ea39SPravin B Shelar 		if (flags & TUNNEL_SEQ) {
4602e15ea39SPravin B Shelar 			*ptr = seq;
4612e15ea39SPravin B Shelar 			ptr--;
4622e15ea39SPravin B Shelar 		}
4632e15ea39SPravin B Shelar 		if (flags & TUNNEL_KEY) {
4642e15ea39SPravin B Shelar 			*ptr = key;
4652e15ea39SPravin B Shelar 			ptr--;
4662e15ea39SPravin B Shelar 		}
4672e15ea39SPravin B Shelar 		if (flags & TUNNEL_CSUM &&
4682e15ea39SPravin B Shelar 		    !(skb_shinfo(skb)->gso_type &
4692e15ea39SPravin B Shelar 		      (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) {
4702e15ea39SPravin B Shelar 			*ptr = 0;
4712e15ea39SPravin B Shelar 			*(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0,
4722e15ea39SPravin B Shelar 								 skb->len, 0));
4732e15ea39SPravin B Shelar 		}
4742e15ea39SPravin B Shelar 	}
4752e15ea39SPravin B Shelar }
4762e15ea39SPravin B Shelar 
477c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
478c5441932SPravin B Shelar 		       const struct iphdr *tnl_params,
479c5441932SPravin B Shelar 		       __be16 proto)
480c5441932SPravin B Shelar {
481c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
482c5441932SPravin B Shelar 
483c5441932SPravin B Shelar 	if (tunnel->parms.o_flags & TUNNEL_SEQ)
484c5441932SPravin B Shelar 		tunnel->o_seqno++;
485cef401deSEric Dumazet 
486c5441932SPravin B Shelar 	/* Push GRE header. */
4872e15ea39SPravin B Shelar 	build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags,
4882e15ea39SPravin B Shelar 		     proto, tunnel->parms.o_key, htonl(tunnel->o_seqno));
4891da177e4SLinus Torvalds 
4902e15ea39SPravin B Shelar 	skb_set_inner_protocol(skb, proto);
491bf3d6a8fSNicolas Dichtel 	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
4921da177e4SLinus Torvalds }
4931da177e4SLinus Torvalds 
494b2acd1dcSPravin B Shelar static struct sk_buff *gre_handle_offloads(struct sk_buff *skb,
495b2acd1dcSPravin B Shelar 					   bool csum)
496b2acd1dcSPravin B Shelar {
497b2acd1dcSPravin B Shelar 	return iptunnel_handle_offloads(skb, csum,
498b2acd1dcSPravin B Shelar 					csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
499b2acd1dcSPravin B Shelar }
500b2acd1dcSPravin B Shelar 
5012e15ea39SPravin B Shelar static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)
5022e15ea39SPravin B Shelar {
5032e15ea39SPravin B Shelar 	struct ip_tunnel_info *tun_info;
5042e15ea39SPravin B Shelar 	struct net *net = dev_net(dev);
5052e15ea39SPravin B Shelar 	const struct ip_tunnel_key *key;
5062e15ea39SPravin B Shelar 	struct flowi4 fl;
5072e15ea39SPravin B Shelar 	struct rtable *rt;
5082e15ea39SPravin B Shelar 	int min_headroom;
5092e15ea39SPravin B Shelar 	int tunnel_hlen;
5102e15ea39SPravin B Shelar 	__be16 df, flags;
5112e15ea39SPravin B Shelar 	int err;
5122e15ea39SPravin B Shelar 
51361adedf3SJiri Benc 	tun_info = skb_tunnel_info(skb);
5142e15ea39SPravin B Shelar 	if (unlikely(!tun_info || tun_info->mode != IP_TUNNEL_INFO_TX))
5152e15ea39SPravin B Shelar 		goto err_free_skb;
5162e15ea39SPravin B Shelar 
5172e15ea39SPravin B Shelar 	key = &tun_info->key;
5182e15ea39SPravin B Shelar 	memset(&fl, 0, sizeof(fl));
519c1ea5d67SJiri Benc 	fl.daddr = key->u.ipv4.dst;
520c1ea5d67SJiri Benc 	fl.saddr = key->u.ipv4.src;
5217c383fb2SJiri Benc 	fl.flowi4_tos = RT_TOS(key->tos);
5222e15ea39SPravin B Shelar 	fl.flowi4_mark = skb->mark;
5232e15ea39SPravin B Shelar 	fl.flowi4_proto = IPPROTO_GRE;
5242e15ea39SPravin B Shelar 
5252e15ea39SPravin B Shelar 	rt = ip_route_output_key(net, &fl);
5262e15ea39SPravin B Shelar 	if (IS_ERR(rt))
5272e15ea39SPravin B Shelar 		goto err_free_skb;
5282e15ea39SPravin B Shelar 
5292e15ea39SPravin B Shelar 	tunnel_hlen = ip_gre_calc_hlen(key->tun_flags);
5302e15ea39SPravin B Shelar 
5312e15ea39SPravin B Shelar 	min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
5322e15ea39SPravin B Shelar 			+ tunnel_hlen + sizeof(struct iphdr);
5332e15ea39SPravin B Shelar 	if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
5342e15ea39SPravin B Shelar 		int head_delta = SKB_DATA_ALIGN(min_headroom -
5352e15ea39SPravin B Shelar 						skb_headroom(skb) +
5362e15ea39SPravin B Shelar 						16);
5372e15ea39SPravin B Shelar 		err = pskb_expand_head(skb, max_t(int, head_delta, 0),
5382e15ea39SPravin B Shelar 				       0, GFP_ATOMIC);
5392e15ea39SPravin B Shelar 		if (unlikely(err))
5402e15ea39SPravin B Shelar 			goto err_free_rt;
5412e15ea39SPravin B Shelar 	}
5422e15ea39SPravin B Shelar 
5432e15ea39SPravin B Shelar 	/* Push Tunnel header. */
5442e15ea39SPravin B Shelar 	skb = gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM));
5452e15ea39SPravin B Shelar 	if (IS_ERR(skb)) {
5462e15ea39SPravin B Shelar 		skb = NULL;
5472e15ea39SPravin B Shelar 		goto err_free_rt;
5482e15ea39SPravin B Shelar 	}
5492e15ea39SPravin B Shelar 
5502e15ea39SPravin B Shelar 	flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
5512e15ea39SPravin B Shelar 	build_header(skb, tunnel_hlen, flags, htons(ETH_P_TEB),
5522e15ea39SPravin B Shelar 		     tunnel_id_to_key(tun_info->key.tun_id), 0);
5532e15ea39SPravin B Shelar 
5542e15ea39SPravin B Shelar 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
5552e15ea39SPravin B Shelar 	err = iptunnel_xmit(skb->sk, rt, skb, fl.saddr,
556c1ea5d67SJiri Benc 			    key->u.ipv4.dst, IPPROTO_GRE,
5577c383fb2SJiri Benc 			    key->tos, key->ttl, df, false);
5582e15ea39SPravin B Shelar 	iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
5592e15ea39SPravin B Shelar 	return;
5602e15ea39SPravin B Shelar 
5612e15ea39SPravin B Shelar err_free_rt:
5622e15ea39SPravin B Shelar 	ip_rt_put(rt);
5632e15ea39SPravin B Shelar err_free_skb:
5642e15ea39SPravin B Shelar 	kfree_skb(skb);
5652e15ea39SPravin B Shelar 	dev->stats.tx_dropped++;
5662e15ea39SPravin B Shelar }
5672e15ea39SPravin B Shelar 
568c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
569c5441932SPravin B Shelar 			      struct net_device *dev)
570ee34c1ebSMichal Schmidt {
571c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
572c5441932SPravin B Shelar 	const struct iphdr *tnl_params;
573ee34c1ebSMichal Schmidt 
5742e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
5752e15ea39SPravin B Shelar 		gre_fb_xmit(skb, dev);
5762e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
5772e15ea39SPravin B Shelar 	}
5782e15ea39SPravin B Shelar 
579c5441932SPravin B Shelar 	if (dev->header_ops) {
580c5441932SPravin B Shelar 		/* Need space for new headers */
581c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom -
5822bac7cb3SChen Gang 				      (tunnel->hlen + sizeof(struct iphdr))))
583c5441932SPravin B Shelar 			goto free_skb;
584ee34c1ebSMichal Schmidt 
585c5441932SPravin B Shelar 		tnl_params = (const struct iphdr *)skb->data;
586cbb1e85fSDavid S. Miller 
587c5441932SPravin B Shelar 		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
588c5441932SPravin B Shelar 		 * to gre header.
589c5441932SPravin B Shelar 		 */
590c5441932SPravin B Shelar 		skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
5918a0033a9STimo Teräs 		skb_reset_mac_header(skb);
592c5441932SPravin B Shelar 	} else {
593c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom))
594c5441932SPravin B Shelar 			goto free_skb;
595c5441932SPravin B Shelar 
596c5441932SPravin B Shelar 		tnl_params = &tunnel->parms.iph;
597ee34c1ebSMichal Schmidt 	}
598e1a80002SHerbert Xu 
5998a0033a9STimo Teräs 	skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM));
6008a0033a9STimo Teräs 	if (IS_ERR(skb))
6018a0033a9STimo Teräs 		goto out;
6028a0033a9STimo Teräs 
603c5441932SPravin B Shelar 	__gre_xmit(skb, dev, tnl_params, skb->protocol);
604c5441932SPravin B Shelar 	return NETDEV_TX_OK;
605c5441932SPravin B Shelar 
606c5441932SPravin B Shelar free_skb:
6073acfa1e7SEric Dumazet 	kfree_skb(skb);
608c5441932SPravin B Shelar out:
609c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
610c5441932SPravin B Shelar 	return NETDEV_TX_OK;
611ee34c1ebSMichal Schmidt }
612ee34c1ebSMichal Schmidt 
613c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
614c5441932SPravin B Shelar 				struct net_device *dev)
615c5441932SPravin B Shelar {
616c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
617ee34c1ebSMichal Schmidt 
6182e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
6192e15ea39SPravin B Shelar 		gre_fb_xmit(skb, dev);
6202e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
6212e15ea39SPravin B Shelar 	}
6222e15ea39SPravin B Shelar 
62345f2e997SPravin B Shelar 	skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM));
624c5441932SPravin B Shelar 	if (IS_ERR(skb))
625c5441932SPravin B Shelar 		goto out;
626ee34c1ebSMichal Schmidt 
627c5441932SPravin B Shelar 	if (skb_cow_head(skb, dev->needed_headroom))
628c5441932SPravin B Shelar 		goto free_skb;
62942aa9162SHerbert Xu 
630c5441932SPravin B Shelar 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
631c5441932SPravin B Shelar 	return NETDEV_TX_OK;
632c5441932SPravin B Shelar 
633c5441932SPravin B Shelar free_skb:
6343acfa1e7SEric Dumazet 	kfree_skb(skb);
635c5441932SPravin B Shelar out:
636c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
637c5441932SPravin B Shelar 	return NETDEV_TX_OK;
63868c33163SPravin B Shelar }
639ee34c1ebSMichal Schmidt 
640c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev,
641c5441932SPravin B Shelar 			      struct ifreq *ifr, int cmd)
6421da177e4SLinus Torvalds {
6434565e991STom Herbert 	int err;
6441da177e4SLinus Torvalds 	struct ip_tunnel_parm p;
6451da177e4SLinus Torvalds 
6461da177e4SLinus Torvalds 	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
647c5441932SPravin B Shelar 		return -EFAULT;
6486c734fb8SCong Wang 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
6491da177e4SLinus Torvalds 		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
6501da177e4SLinus Torvalds 		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
6516c734fb8SCong Wang 		    ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
6521da177e4SLinus Torvalds 			return -EINVAL;
653c5441932SPravin B Shelar 	}
654c5441932SPravin B Shelar 	p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
655c5441932SPravin B Shelar 	p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
656c5441932SPravin B Shelar 
657c5441932SPravin B Shelar 	err = ip_tunnel_ioctl(dev, &p, cmd);
658c5441932SPravin B Shelar 	if (err)
659c5441932SPravin B Shelar 		return err;
660c5441932SPravin B Shelar 
661c5441932SPravin B Shelar 	p.i_flags = tnl_flags_to_gre_flags(p.i_flags);
662c5441932SPravin B Shelar 	p.o_flags = tnl_flags_to_gre_flags(p.o_flags);
663c5441932SPravin B Shelar 
664c5441932SPravin B Shelar 	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
665c5441932SPravin B Shelar 		return -EFAULT;
6661da177e4SLinus Torvalds 	return 0;
6671da177e4SLinus Torvalds }
6681da177e4SLinus Torvalds 
6691da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-)
6701da177e4SLinus Torvalds    It allows to construct virtual multiprotocol broadcast "LAN"
6711da177e4SLinus Torvalds    over the Internet, provided multicast routing is tuned.
6721da177e4SLinus Torvalds 
6731da177e4SLinus Torvalds 
6741da177e4SLinus Torvalds    I have no idea was this bicycle invented before me,
6751da177e4SLinus Torvalds    so that I had to set ARPHRD_IPGRE to a random value.
6761da177e4SLinus Torvalds    I have an impression, that Cisco could make something similar,
6771da177e4SLinus Torvalds    but this feature is apparently missing in IOS<=11.2(8).
6781da177e4SLinus Torvalds 
6791da177e4SLinus Torvalds    I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
6801da177e4SLinus Torvalds    with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
6811da177e4SLinus Torvalds 
6821da177e4SLinus Torvalds    ping -t 255 224.66.66.66
6831da177e4SLinus Torvalds 
6841da177e4SLinus Torvalds    If nobody answers, mbone does not work.
6851da177e4SLinus Torvalds 
6861da177e4SLinus Torvalds    ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
6871da177e4SLinus Torvalds    ip addr add 10.66.66.<somewhat>/24 dev Universe
6881da177e4SLinus Torvalds    ifconfig Universe up
6891da177e4SLinus Torvalds    ifconfig Universe add fe80::<Your_real_addr>/10
6901da177e4SLinus Torvalds    ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
6911da177e4SLinus Torvalds    ftp 10.66.66.66
6921da177e4SLinus Torvalds    ...
6931da177e4SLinus Torvalds    ftp fec0:6666:6666::193.233.7.65
6941da177e4SLinus Torvalds    ...
6951da177e4SLinus Torvalds  */
6963b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
6973b04dddeSStephen Hemminger 			unsigned short type,
6981507850bSEric Dumazet 			const void *daddr, const void *saddr, unsigned int len)
6991da177e4SLinus Torvalds {
7002941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
701c5441932SPravin B Shelar 	struct iphdr *iph;
702c5441932SPravin B Shelar 	struct gre_base_hdr *greh;
703c5441932SPravin B Shelar 
704c5441932SPravin B Shelar 	iph = (struct iphdr *)skb_push(skb, t->hlen + sizeof(*iph));
705c5441932SPravin B Shelar 	greh = (struct gre_base_hdr *)(iph+1);
706c5441932SPravin B Shelar 	greh->flags = tnl_flags_to_gre_flags(t->parms.o_flags);
707c5441932SPravin B Shelar 	greh->protocol = htons(type);
7081da177e4SLinus Torvalds 
7091da177e4SLinus Torvalds 	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
7101da177e4SLinus Torvalds 
711c5441932SPravin B Shelar 	/* Set the source hardware address. */
7121da177e4SLinus Torvalds 	if (saddr)
7131da177e4SLinus Torvalds 		memcpy(&iph->saddr, saddr, 4);
7146d55cb91STimo Teräs 	if (daddr)
7151da177e4SLinus Torvalds 		memcpy(&iph->daddr, daddr, 4);
7166d55cb91STimo Teräs 	if (iph->daddr)
71777a482bdSTimo Teräs 		return t->hlen + sizeof(*iph);
7181da177e4SLinus Torvalds 
719c5441932SPravin B Shelar 	return -(t->hlen + sizeof(*iph));
7201da177e4SLinus Torvalds }
7211da177e4SLinus Torvalds 
7226a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
7236a5f44d7STimo Teras {
724b71d1d42SEric Dumazet 	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
7256a5f44d7STimo Teras 	memcpy(haddr, &iph->saddr, 4);
7266a5f44d7STimo Teras 	return 4;
7276a5f44d7STimo Teras }
7286a5f44d7STimo Teras 
7293b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = {
7303b04dddeSStephen Hemminger 	.create	= ipgre_header,
7316a5f44d7STimo Teras 	.parse	= ipgre_header_parse,
7323b04dddeSStephen Hemminger };
7333b04dddeSStephen Hemminger 
7346a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST
7351da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev)
7361da177e4SLinus Torvalds {
7372941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
7381da177e4SLinus Torvalds 
739f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
740cbb1e85fSDavid S. Miller 		struct flowi4 fl4;
741cbb1e85fSDavid S. Miller 		struct rtable *rt;
742cbb1e85fSDavid S. Miller 
743b57708adSNicolas Dichtel 		rt = ip_route_output_gre(t->net, &fl4,
74478fbfd8aSDavid S. Miller 					 t->parms.iph.daddr,
74578fbfd8aSDavid S. Miller 					 t->parms.iph.saddr,
74678fbfd8aSDavid S. Miller 					 t->parms.o_key,
74778fbfd8aSDavid S. Miller 					 RT_TOS(t->parms.iph.tos),
74878fbfd8aSDavid S. Miller 					 t->parms.link);
749b23dd4feSDavid S. Miller 		if (IS_ERR(rt))
7501da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
751d8d1f30bSChangli Gao 		dev = rt->dst.dev;
7521da177e4SLinus Torvalds 		ip_rt_put(rt);
75351456b29SIan Morris 		if (!__in_dev_get_rtnl(dev))
7541da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
7551da177e4SLinus Torvalds 		t->mlink = dev->ifindex;
756e5ed6399SHerbert Xu 		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
7571da177e4SLinus Torvalds 	}
7581da177e4SLinus Torvalds 	return 0;
7591da177e4SLinus Torvalds }
7601da177e4SLinus Torvalds 
7611da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev)
7621da177e4SLinus Torvalds {
7632941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
764b8c26a33SStephen Hemminger 
765f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
7667fee0ca2SDenis V. Lunev 		struct in_device *in_dev;
767b57708adSNicolas Dichtel 		in_dev = inetdev_by_index(t->net, t->mlink);
7688723e1b4SEric Dumazet 		if (in_dev)
7691da177e4SLinus Torvalds 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
7701da177e4SLinus Torvalds 	}
7711da177e4SLinus Torvalds 	return 0;
7721da177e4SLinus Torvalds }
7731da177e4SLinus Torvalds #endif
7741da177e4SLinus Torvalds 
775b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = {
776b8c26a33SStephen Hemminger 	.ndo_init		= ipgre_tunnel_init,
777c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
778b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST
779b8c26a33SStephen Hemminger 	.ndo_open		= ipgre_open,
780b8c26a33SStephen Hemminger 	.ndo_stop		= ipgre_close,
781b8c26a33SStephen Hemminger #endif
782c5441932SPravin B Shelar 	.ndo_start_xmit		= ipgre_xmit,
783b8c26a33SStephen Hemminger 	.ndo_do_ioctl		= ipgre_tunnel_ioctl,
784c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
785c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
7861e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
787b8c26a33SStephen Hemminger };
788b8c26a33SStephen Hemminger 
7896b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG |		\
7906b78f16eSEric Dumazet 		      NETIF_F_FRAGLIST |	\
7916b78f16eSEric Dumazet 		      NETIF_F_HIGHDMA |		\
7926b78f16eSEric Dumazet 		      NETIF_F_HW_CSUM)
7936b78f16eSEric Dumazet 
7941da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev)
7951da177e4SLinus Torvalds {
796b8c26a33SStephen Hemminger 	dev->netdev_ops		= &ipgre_netdev_ops;
7975a455275SNicolas Dichtel 	dev->type		= ARPHRD_IPGRE;
798c5441932SPravin B Shelar 	ip_tunnel_setup(dev, ipgre_net_id);
799c5441932SPravin B Shelar }
8001da177e4SLinus Torvalds 
801c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev)
802c5441932SPravin B Shelar {
803c5441932SPravin B Shelar 	struct ip_tunnel *tunnel;
8044565e991STom Herbert 	int t_hlen;
805c5441932SPravin B Shelar 
806c5441932SPravin B Shelar 	tunnel = netdev_priv(dev);
8074565e991STom Herbert 	tunnel->tun_hlen = ip_gre_calc_hlen(tunnel->parms.o_flags);
808c5441932SPravin B Shelar 	tunnel->parms.iph.protocol = IPPROTO_GRE;
809c5441932SPravin B Shelar 
8104565e991STom Herbert 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
8114565e991STom Herbert 
8124565e991STom Herbert 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
8134565e991STom Herbert 
8144565e991STom Herbert 	dev->needed_headroom	= LL_MAX_HEADER + t_hlen + 4;
8154565e991STom Herbert 	dev->mtu		= ETH_DATA_LEN - t_hlen - 4;
8166b78f16eSEric Dumazet 
817b57708adSNicolas Dichtel 	dev->features		|= GRE_FEATURES;
8186b78f16eSEric Dumazet 	dev->hw_features	|= GRE_FEATURES;
819c5441932SPravin B Shelar 
820c5441932SPravin B Shelar 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
821c5441932SPravin B Shelar 		/* TCP offload with GRE SEQ is not supported. */
822c5441932SPravin B Shelar 		dev->features    |= NETIF_F_GSO_SOFTWARE;
823c5441932SPravin B Shelar 		dev->hw_features |= NETIF_F_GSO_SOFTWARE;
824c5441932SPravin B Shelar 		/* Can use a lockless transmit, unless we generate
825c5441932SPravin B Shelar 		 * output sequences
826c5441932SPravin B Shelar 		 */
827c5441932SPravin B Shelar 		dev->features |= NETIF_F_LLTX;
828c5441932SPravin B Shelar 	}
8291da177e4SLinus Torvalds }
8301da177e4SLinus Torvalds 
8311da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev)
8321da177e4SLinus Torvalds {
833c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
834c5441932SPravin B Shelar 	struct iphdr *iph = &tunnel->parms.iph;
8351da177e4SLinus Torvalds 
836c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
8371da177e4SLinus Torvalds 
838c5441932SPravin B Shelar 	memcpy(dev->dev_addr, &iph->saddr, 4);
839c5441932SPravin B Shelar 	memcpy(dev->broadcast, &iph->daddr, 4);
8401da177e4SLinus Torvalds 
841c5441932SPravin B Shelar 	dev->flags		= IFF_NOARP;
84202875878SEric Dumazet 	netif_keep_dst(dev);
843c5441932SPravin B Shelar 	dev->addr_len		= 4;
8441da177e4SLinus Torvalds 
8451da177e4SLinus Torvalds 	if (iph->daddr) {
8461da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST
847f97c1e0cSJoe Perches 		if (ipv4_is_multicast(iph->daddr)) {
8481da177e4SLinus Torvalds 			if (!iph->saddr)
8491da177e4SLinus Torvalds 				return -EINVAL;
8501da177e4SLinus Torvalds 			dev->flags = IFF_BROADCAST;
8513b04dddeSStephen Hemminger 			dev->header_ops = &ipgre_header_ops;
8521da177e4SLinus Torvalds 		}
8531da177e4SLinus Torvalds #endif
854ee34c1ebSMichal Schmidt 	} else
8556a5f44d7STimo Teras 		dev->header_ops = &ipgre_header_ops;
8561da177e4SLinus Torvalds 
857c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
85860769a5dSEric Dumazet }
85960769a5dSEric Dumazet 
8609f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = {
8619f57c67cSPravin B Shelar 	.handler     = gre_rcv,
8629f57c67cSPravin B Shelar 	.err_handler = gre_err,
8631da177e4SLinus Torvalds };
8641da177e4SLinus Torvalds 
8652c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net)
86659a4c759SPavel Emelyanov {
867c5441932SPravin B Shelar 	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
86859a4c759SPavel Emelyanov }
86959a4c759SPavel Emelyanov 
8702c8c1e72SAlexey Dobriyan static void __net_exit ipgre_exit_net(struct net *net)
87159a4c759SPavel Emelyanov {
872c5441932SPravin B Shelar 	struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id);
8736c742e71SNicolas Dichtel 	ip_tunnel_delete_net(itn, &ipgre_link_ops);
87459a4c759SPavel Emelyanov }
87559a4c759SPavel Emelyanov 
87659a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = {
87759a4c759SPavel Emelyanov 	.init = ipgre_init_net,
87859a4c759SPavel Emelyanov 	.exit = ipgre_exit_net,
879cfb8fbf2SEric W. Biederman 	.id   = &ipgre_net_id,
880c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
88159a4c759SPavel Emelyanov };
8821da177e4SLinus Torvalds 
883c19e654dSHerbert Xu static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
884c19e654dSHerbert Xu {
885c19e654dSHerbert Xu 	__be16 flags;
886c19e654dSHerbert Xu 
887c19e654dSHerbert Xu 	if (!data)
888c19e654dSHerbert Xu 		return 0;
889c19e654dSHerbert Xu 
890c19e654dSHerbert Xu 	flags = 0;
891c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
892c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
893c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
894c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
895c19e654dSHerbert Xu 	if (flags & (GRE_VERSION|GRE_ROUTING))
896c19e654dSHerbert Xu 		return -EINVAL;
897c19e654dSHerbert Xu 
898c19e654dSHerbert Xu 	return 0;
899c19e654dSHerbert Xu }
900c19e654dSHerbert Xu 
901e1a80002SHerbert Xu static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
902e1a80002SHerbert Xu {
903e1a80002SHerbert Xu 	__be32 daddr;
904e1a80002SHerbert Xu 
905e1a80002SHerbert Xu 	if (tb[IFLA_ADDRESS]) {
906e1a80002SHerbert Xu 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
907e1a80002SHerbert Xu 			return -EINVAL;
908e1a80002SHerbert Xu 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
909e1a80002SHerbert Xu 			return -EADDRNOTAVAIL;
910e1a80002SHerbert Xu 	}
911e1a80002SHerbert Xu 
912e1a80002SHerbert Xu 	if (!data)
913e1a80002SHerbert Xu 		goto out;
914e1a80002SHerbert Xu 
915e1a80002SHerbert Xu 	if (data[IFLA_GRE_REMOTE]) {
916e1a80002SHerbert Xu 		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
917e1a80002SHerbert Xu 		if (!daddr)
918e1a80002SHerbert Xu 			return -EINVAL;
919e1a80002SHerbert Xu 	}
920e1a80002SHerbert Xu 
921e1a80002SHerbert Xu out:
922e1a80002SHerbert Xu 	return ipgre_tunnel_validate(tb, data);
923e1a80002SHerbert Xu }
924e1a80002SHerbert Xu 
9252e15ea39SPravin B Shelar static void ipgre_netlink_parms(struct net_device *dev,
9262e15ea39SPravin B Shelar 				struct nlattr *data[],
9272e15ea39SPravin B Shelar 				struct nlattr *tb[],
928c19e654dSHerbert Xu 				struct ip_tunnel_parm *parms)
929c19e654dSHerbert Xu {
9307bb82d92SHerbert Xu 	memset(parms, 0, sizeof(*parms));
931c19e654dSHerbert Xu 
932c19e654dSHerbert Xu 	parms->iph.protocol = IPPROTO_GRE;
933c19e654dSHerbert Xu 
934c19e654dSHerbert Xu 	if (!data)
935c19e654dSHerbert Xu 		return;
936c19e654dSHerbert Xu 
937c19e654dSHerbert Xu 	if (data[IFLA_GRE_LINK])
938c19e654dSHerbert Xu 		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
939c19e654dSHerbert Xu 
940c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
941c5441932SPravin B Shelar 		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
942c19e654dSHerbert Xu 
943c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
944c5441932SPravin B Shelar 		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
945c19e654dSHerbert Xu 
946c19e654dSHerbert Xu 	if (data[IFLA_GRE_IKEY])
947c19e654dSHerbert Xu 		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
948c19e654dSHerbert Xu 
949c19e654dSHerbert Xu 	if (data[IFLA_GRE_OKEY])
950c19e654dSHerbert Xu 		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
951c19e654dSHerbert Xu 
952c19e654dSHerbert Xu 	if (data[IFLA_GRE_LOCAL])
95367b61f6cSJiri Benc 		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
954c19e654dSHerbert Xu 
955c19e654dSHerbert Xu 	if (data[IFLA_GRE_REMOTE])
95667b61f6cSJiri Benc 		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
957c19e654dSHerbert Xu 
958c19e654dSHerbert Xu 	if (data[IFLA_GRE_TTL])
959c19e654dSHerbert Xu 		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
960c19e654dSHerbert Xu 
961c19e654dSHerbert Xu 	if (data[IFLA_GRE_TOS])
962c19e654dSHerbert Xu 		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
963c19e654dSHerbert Xu 
964c19e654dSHerbert Xu 	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC]))
965c19e654dSHerbert Xu 		parms->iph.frag_off = htons(IP_DF);
9662e15ea39SPravin B Shelar 
9672e15ea39SPravin B Shelar 	if (data[IFLA_GRE_COLLECT_METADATA]) {
9682e15ea39SPravin B Shelar 		struct ip_tunnel *t = netdev_priv(dev);
9692e15ea39SPravin B Shelar 
9702e15ea39SPravin B Shelar 		t->collect_md = true;
9712e15ea39SPravin B Shelar 	}
972c19e654dSHerbert Xu }
973c19e654dSHerbert Xu 
9744565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */
9754565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[],
9764565e991STom Herbert 				      struct ip_tunnel_encap *ipencap)
9774565e991STom Herbert {
9784565e991STom Herbert 	bool ret = false;
9794565e991STom Herbert 
9804565e991STom Herbert 	memset(ipencap, 0, sizeof(*ipencap));
9814565e991STom Herbert 
9824565e991STom Herbert 	if (!data)
9834565e991STom Herbert 		return ret;
9844565e991STom Herbert 
9854565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_TYPE]) {
9864565e991STom Herbert 		ret = true;
9874565e991STom Herbert 		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
9884565e991STom Herbert 	}
9894565e991STom Herbert 
9904565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_FLAGS]) {
9914565e991STom Herbert 		ret = true;
9924565e991STom Herbert 		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
9934565e991STom Herbert 	}
9944565e991STom Herbert 
9954565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_SPORT]) {
9964565e991STom Herbert 		ret = true;
9973e97fa70SSabrina Dubroca 		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
9984565e991STom Herbert 	}
9994565e991STom Herbert 
10004565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_DPORT]) {
10014565e991STom Herbert 		ret = true;
10023e97fa70SSabrina Dubroca 		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
10034565e991STom Herbert 	}
10044565e991STom Herbert 
10054565e991STom Herbert 	return ret;
10064565e991STom Herbert }
10074565e991STom Herbert 
1008c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev)
1009e1a80002SHerbert Xu {
1010c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
1011bec94d43Sstephen hemminger 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
1012e1a80002SHerbert Xu 
1013c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
1014e1a80002SHerbert Xu }
1015e1a80002SHerbert Xu 
1016c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = {
1017c5441932SPravin B Shelar 	.ndo_init		= gre_tap_init,
1018c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
1019c5441932SPravin B Shelar 	.ndo_start_xmit		= gre_tap_xmit,
1020b8c26a33SStephen Hemminger 	.ndo_set_mac_address 	= eth_mac_addr,
1021b8c26a33SStephen Hemminger 	.ndo_validate_addr	= eth_validate_addr,
1022c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
1023c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
10241e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
1025b8c26a33SStephen Hemminger };
1026b8c26a33SStephen Hemminger 
1027e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev)
1028e1a80002SHerbert Xu {
1029e1a80002SHerbert Xu 	ether_setup(dev);
1030c5441932SPravin B Shelar 	dev->netdev_ops		= &gre_tap_netdev_ops;
1031f8c1b7ceSstephen hemminger 	dev->priv_flags 	|= IFF_LIVE_ADDR_CHANGE;
1032c5441932SPravin B Shelar 	ip_tunnel_setup(dev, gre_tap_net_id);
1033e1a80002SHerbert Xu }
1034e1a80002SHerbert Xu 
1035c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev,
1036c5441932SPravin B Shelar 			 struct nlattr *tb[], struct nlattr *data[])
1037c19e654dSHerbert Xu {
1038c5441932SPravin B Shelar 	struct ip_tunnel_parm p;
10394565e991STom Herbert 	struct ip_tunnel_encap ipencap;
10404565e991STom Herbert 
10414565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
10424565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
10434565e991STom Herbert 		int err = ip_tunnel_encap_setup(t, &ipencap);
10444565e991STom Herbert 
10454565e991STom Herbert 		if (err < 0)
10464565e991STom Herbert 			return err;
10474565e991STom Herbert 	}
1048c19e654dSHerbert Xu 
10492e15ea39SPravin B Shelar 	ipgre_netlink_parms(dev, data, tb, &p);
1050c5441932SPravin B Shelar 	return ip_tunnel_newlink(dev, tb, &p);
1051c19e654dSHerbert Xu }
1052c19e654dSHerbert Xu 
1053c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1054c19e654dSHerbert Xu 			    struct nlattr *data[])
1055c19e654dSHerbert Xu {
1056c19e654dSHerbert Xu 	struct ip_tunnel_parm p;
10574565e991STom Herbert 	struct ip_tunnel_encap ipencap;
10584565e991STom Herbert 
10594565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
10604565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
10614565e991STom Herbert 		int err = ip_tunnel_encap_setup(t, &ipencap);
10624565e991STom Herbert 
10634565e991STom Herbert 		if (err < 0)
10644565e991STom Herbert 			return err;
10654565e991STom Herbert 	}
1066c19e654dSHerbert Xu 
10672e15ea39SPravin B Shelar 	ipgre_netlink_parms(dev, data, tb, &p);
1068c5441932SPravin B Shelar 	return ip_tunnel_changelink(dev, tb, &p);
1069c19e654dSHerbert Xu }
1070c19e654dSHerbert Xu 
1071c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev)
1072c19e654dSHerbert Xu {
1073c19e654dSHerbert Xu 	return
1074c19e654dSHerbert Xu 		/* IFLA_GRE_LINK */
1075c19e654dSHerbert Xu 		nla_total_size(4) +
1076c19e654dSHerbert Xu 		/* IFLA_GRE_IFLAGS */
1077c19e654dSHerbert Xu 		nla_total_size(2) +
1078c19e654dSHerbert Xu 		/* IFLA_GRE_OFLAGS */
1079c19e654dSHerbert Xu 		nla_total_size(2) +
1080c19e654dSHerbert Xu 		/* IFLA_GRE_IKEY */
1081c19e654dSHerbert Xu 		nla_total_size(4) +
1082c19e654dSHerbert Xu 		/* IFLA_GRE_OKEY */
1083c19e654dSHerbert Xu 		nla_total_size(4) +
1084c19e654dSHerbert Xu 		/* IFLA_GRE_LOCAL */
1085c19e654dSHerbert Xu 		nla_total_size(4) +
1086c19e654dSHerbert Xu 		/* IFLA_GRE_REMOTE */
1087c19e654dSHerbert Xu 		nla_total_size(4) +
1088c19e654dSHerbert Xu 		/* IFLA_GRE_TTL */
1089c19e654dSHerbert Xu 		nla_total_size(1) +
1090c19e654dSHerbert Xu 		/* IFLA_GRE_TOS */
1091c19e654dSHerbert Xu 		nla_total_size(1) +
1092c19e654dSHerbert Xu 		/* IFLA_GRE_PMTUDISC */
1093c19e654dSHerbert Xu 		nla_total_size(1) +
10944565e991STom Herbert 		/* IFLA_GRE_ENCAP_TYPE */
10954565e991STom Herbert 		nla_total_size(2) +
10964565e991STom Herbert 		/* IFLA_GRE_ENCAP_FLAGS */
10974565e991STom Herbert 		nla_total_size(2) +
10984565e991STom Herbert 		/* IFLA_GRE_ENCAP_SPORT */
10994565e991STom Herbert 		nla_total_size(2) +
11004565e991STom Herbert 		/* IFLA_GRE_ENCAP_DPORT */
11014565e991STom Herbert 		nla_total_size(2) +
11022e15ea39SPravin B Shelar 		/* IFLA_GRE_COLLECT_METADATA */
11032e15ea39SPravin B Shelar 		nla_total_size(0) +
1104c19e654dSHerbert Xu 		0;
1105c19e654dSHerbert Xu }
1106c19e654dSHerbert Xu 
1107c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1108c19e654dSHerbert Xu {
1109c19e654dSHerbert Xu 	struct ip_tunnel *t = netdev_priv(dev);
1110c19e654dSHerbert Xu 	struct ip_tunnel_parm *p = &t->parms;
1111c19e654dSHerbert Xu 
1112f3756b79SDavid S. Miller 	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
1113c5441932SPravin B Shelar 	    nla_put_be16(skb, IFLA_GRE_IFLAGS, tnl_flags_to_gre_flags(p->i_flags)) ||
1114c5441932SPravin B Shelar 	    nla_put_be16(skb, IFLA_GRE_OFLAGS, tnl_flags_to_gre_flags(p->o_flags)) ||
1115f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1116f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
1117930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1118930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
1119f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1120f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1121f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
1122f3756b79SDavid S. Miller 		       !!(p->iph.frag_off & htons(IP_DF))))
1123f3756b79SDavid S. Miller 		goto nla_put_failure;
11244565e991STom Herbert 
11254565e991STom Herbert 	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
11264565e991STom Herbert 			t->encap.type) ||
11273e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
11284565e991STom Herbert 			 t->encap.sport) ||
11293e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
11304565e991STom Herbert 			 t->encap.dport) ||
11314565e991STom Herbert 	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
1132e1b2cb65STom Herbert 			t->encap.flags))
11334565e991STom Herbert 		goto nla_put_failure;
11344565e991STom Herbert 
11352e15ea39SPravin B Shelar 	if (t->collect_md) {
11362e15ea39SPravin B Shelar 		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
11372e15ea39SPravin B Shelar 			goto nla_put_failure;
11382e15ea39SPravin B Shelar 	}
11392e15ea39SPravin B Shelar 
1140c19e654dSHerbert Xu 	return 0;
1141c19e654dSHerbert Xu 
1142c19e654dSHerbert Xu nla_put_failure:
1143c19e654dSHerbert Xu 	return -EMSGSIZE;
1144c19e654dSHerbert Xu }
1145c19e654dSHerbert Xu 
1146c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1147c19e654dSHerbert Xu 	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
1148c19e654dSHerbert Xu 	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
1149c19e654dSHerbert Xu 	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
1150c19e654dSHerbert Xu 	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
1151c19e654dSHerbert Xu 	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
11524d74f8baSPatrick McHardy 	[IFLA_GRE_LOCAL]	= { .len = FIELD_SIZEOF(struct iphdr, saddr) },
11534d74f8baSPatrick McHardy 	[IFLA_GRE_REMOTE]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
1154c19e654dSHerbert Xu 	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
1155c19e654dSHerbert Xu 	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
1156c19e654dSHerbert Xu 	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
11574565e991STom Herbert 	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
11584565e991STom Herbert 	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
11594565e991STom Herbert 	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
11604565e991STom Herbert 	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
11612e15ea39SPravin B Shelar 	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
1162c19e654dSHerbert Xu };
1163c19e654dSHerbert Xu 
1164c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1165c19e654dSHerbert Xu 	.kind		= "gre",
1166c19e654dSHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1167c19e654dSHerbert Xu 	.policy		= ipgre_policy,
1168c19e654dSHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1169c19e654dSHerbert Xu 	.setup		= ipgre_tunnel_setup,
1170c19e654dSHerbert Xu 	.validate	= ipgre_tunnel_validate,
1171c19e654dSHerbert Xu 	.newlink	= ipgre_newlink,
1172c19e654dSHerbert Xu 	.changelink	= ipgre_changelink,
1173c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1174c19e654dSHerbert Xu 	.get_size	= ipgre_get_size,
1175c19e654dSHerbert Xu 	.fill_info	= ipgre_fill_info,
11761728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1177c19e654dSHerbert Xu };
1178c19e654dSHerbert Xu 
1179e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1180e1a80002SHerbert Xu 	.kind		= "gretap",
1181e1a80002SHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1182e1a80002SHerbert Xu 	.policy		= ipgre_policy,
1183e1a80002SHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1184e1a80002SHerbert Xu 	.setup		= ipgre_tap_setup,
1185e1a80002SHerbert Xu 	.validate	= ipgre_tap_validate,
1186e1a80002SHerbert Xu 	.newlink	= ipgre_newlink,
1187e1a80002SHerbert Xu 	.changelink	= ipgre_changelink,
1188c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1189e1a80002SHerbert Xu 	.get_size	= ipgre_get_size,
1190e1a80002SHerbert Xu 	.fill_info	= ipgre_fill_info,
11911728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1192e1a80002SHerbert Xu };
1193e1a80002SHerbert Xu 
1194b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1195b2acd1dcSPravin B Shelar 					u8 name_assign_type)
1196b2acd1dcSPravin B Shelar {
1197b2acd1dcSPravin B Shelar 	struct nlattr *tb[IFLA_MAX + 1];
1198b2acd1dcSPravin B Shelar 	struct net_device *dev;
1199b2acd1dcSPravin B Shelar 	struct ip_tunnel *t;
1200b2acd1dcSPravin B Shelar 	int err;
1201b2acd1dcSPravin B Shelar 
1202b2acd1dcSPravin B Shelar 	memset(&tb, 0, sizeof(tb));
1203b2acd1dcSPravin B Shelar 
1204b2acd1dcSPravin B Shelar 	dev = rtnl_create_link(net, name, name_assign_type,
1205b2acd1dcSPravin B Shelar 			       &ipgre_tap_ops, tb);
1206b2acd1dcSPravin B Shelar 	if (IS_ERR(dev))
1207b2acd1dcSPravin B Shelar 		return dev;
1208b2acd1dcSPravin B Shelar 
1209b2acd1dcSPravin B Shelar 	/* Configure flow based GRE device. */
1210b2acd1dcSPravin B Shelar 	t = netdev_priv(dev);
1211b2acd1dcSPravin B Shelar 	t->collect_md = true;
1212b2acd1dcSPravin B Shelar 
1213b2acd1dcSPravin B Shelar 	err = ipgre_newlink(net, dev, tb, NULL);
1214b2acd1dcSPravin B Shelar 	if (err < 0)
1215b2acd1dcSPravin B Shelar 		goto out;
1216b2acd1dcSPravin B Shelar 	return dev;
1217b2acd1dcSPravin B Shelar out:
1218b2acd1dcSPravin B Shelar 	free_netdev(dev);
1219b2acd1dcSPravin B Shelar 	return ERR_PTR(err);
1220b2acd1dcSPravin B Shelar }
1221b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1222b2acd1dcSPravin B Shelar 
1223c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net)
1224c5441932SPravin B Shelar {
12252e15ea39SPravin B Shelar 	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
1226c5441932SPravin B Shelar }
1227c5441932SPravin B Shelar 
1228c5441932SPravin B Shelar static void __net_exit ipgre_tap_exit_net(struct net *net)
1229c5441932SPravin B Shelar {
1230c5441932SPravin B Shelar 	struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id);
12316c742e71SNicolas Dichtel 	ip_tunnel_delete_net(itn, &ipgre_tap_ops);
1232c5441932SPravin B Shelar }
1233c5441932SPravin B Shelar 
1234c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = {
1235c5441932SPravin B Shelar 	.init = ipgre_tap_init_net,
1236c5441932SPravin B Shelar 	.exit = ipgre_tap_exit_net,
1237c5441932SPravin B Shelar 	.id   = &gre_tap_net_id,
1238c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
1239c5441932SPravin B Shelar };
12401da177e4SLinus Torvalds 
12411da177e4SLinus Torvalds static int __init ipgre_init(void)
12421da177e4SLinus Torvalds {
12431da177e4SLinus Torvalds 	int err;
12441da177e4SLinus Torvalds 
1245058bd4d2SJoe Perches 	pr_info("GRE over IPv4 tunneling driver\n");
12461da177e4SLinus Torvalds 
1247cfb8fbf2SEric W. Biederman 	err = register_pernet_device(&ipgre_net_ops);
124859a4c759SPavel Emelyanov 	if (err < 0)
1249c2892f02SAlexey Dobriyan 		return err;
1250c2892f02SAlexey Dobriyan 
1251c5441932SPravin B Shelar 	err = register_pernet_device(&ipgre_tap_net_ops);
1252c5441932SPravin B Shelar 	if (err < 0)
1253c5441932SPravin B Shelar 		goto pnet_tap_faied;
1254c5441932SPravin B Shelar 
12559f57c67cSPravin B Shelar 	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
1256c2892f02SAlexey Dobriyan 	if (err < 0) {
1257058bd4d2SJoe Perches 		pr_info("%s: can't add protocol\n", __func__);
1258c2892f02SAlexey Dobriyan 		goto add_proto_failed;
1259c2892f02SAlexey Dobriyan 	}
12607daa0004SPavel Emelyanov 
1261c19e654dSHerbert Xu 	err = rtnl_link_register(&ipgre_link_ops);
1262c19e654dSHerbert Xu 	if (err < 0)
1263c19e654dSHerbert Xu 		goto rtnl_link_failed;
1264c19e654dSHerbert Xu 
1265e1a80002SHerbert Xu 	err = rtnl_link_register(&ipgre_tap_ops);
1266e1a80002SHerbert Xu 	if (err < 0)
1267e1a80002SHerbert Xu 		goto tap_ops_failed;
1268e1a80002SHerbert Xu 
1269c5441932SPravin B Shelar 	return 0;
1270c19e654dSHerbert Xu 
1271e1a80002SHerbert Xu tap_ops_failed:
1272e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
1273c19e654dSHerbert Xu rtnl_link_failed:
12749f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1275c2892f02SAlexey Dobriyan add_proto_failed:
1276c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1277c5441932SPravin B Shelar pnet_tap_faied:
1278c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
1279c5441932SPravin B Shelar 	return err;
12801da177e4SLinus Torvalds }
12811da177e4SLinus Torvalds 
1282db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void)
12831da177e4SLinus Torvalds {
1284e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_tap_ops);
1285c19e654dSHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
12869f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1287c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1288c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
12891da177e4SLinus Torvalds }
12901da177e4SLinus Torvalds 
12911da177e4SLinus Torvalds module_init(ipgre_init);
12921da177e4SLinus Torvalds module_exit(ipgre_fini);
12931da177e4SLinus Torvalds MODULE_LICENSE("GPL");
12944d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre");
12954d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap");
12968909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0");
1297c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0");
1298