xref: /linux/net/ipv4/ip_gre.c (revision 7c0f6ba682b9c7632072ffbedf8d328c8f3c42ba)
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>
20*7c0f6ba6SLinus Torvalds #include <linux/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>
272e15ea39SPravin B Shelar #include <linux/if_vlan.h>
281da177e4SLinus Torvalds #include <linux/init.h>
291da177e4SLinus Torvalds #include <linux/in6.h>
301da177e4SLinus Torvalds #include <linux/inetdevice.h>
311da177e4SLinus Torvalds #include <linux/igmp.h>
321da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h>
33e1a80002SHerbert Xu #include <linux/etherdevice.h>
3446f25dffSKris Katterjohn #include <linux/if_ether.h>
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds #include <net/sock.h>
371da177e4SLinus Torvalds #include <net/ip.h>
381da177e4SLinus Torvalds #include <net/icmp.h>
391da177e4SLinus Torvalds #include <net/protocol.h>
40c5441932SPravin B Shelar #include <net/ip_tunnels.h>
411da177e4SLinus Torvalds #include <net/arp.h>
421da177e4SLinus Torvalds #include <net/checksum.h>
431da177e4SLinus Torvalds #include <net/dsfield.h>
441da177e4SLinus Torvalds #include <net/inet_ecn.h>
451da177e4SLinus Torvalds #include <net/xfrm.h>
4659a4c759SPavel Emelyanov #include <net/net_namespace.h>
4759a4c759SPavel Emelyanov #include <net/netns/generic.h>
48c19e654dSHerbert Xu #include <net/rtnetlink.h>
4900959adeSDmitry Kozlov #include <net/gre.h>
502e15ea39SPravin B Shelar #include <net/dst_metadata.h>
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds /*
531da177e4SLinus Torvalds    Problems & solutions
541da177e4SLinus Torvalds    --------------------
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds    1. The most important issue is detecting local dead loops.
571da177e4SLinus Torvalds    They would cause complete host lockup in transmit, which
581da177e4SLinus Torvalds    would be "resolved" by stack overflow or, if queueing is enabled,
591da177e4SLinus Torvalds    with infinite looping in net_bh.
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds    We cannot track such dead loops during route installation,
621da177e4SLinus Torvalds    it is infeasible task. The most general solutions would be
631da177e4SLinus Torvalds    to keep skb->encapsulation counter (sort of local ttl),
646d0722a2SEric Dumazet    and silently drop packet when it expires. It is a good
65bff52857Sstephen hemminger    solution, but it supposes maintaining new variable in ALL
661da177e4SLinus Torvalds    skb, even if no tunneling is used.
671da177e4SLinus Torvalds 
686d0722a2SEric Dumazet    Current solution: xmit_recursion breaks dead loops. This is a percpu
696d0722a2SEric Dumazet    counter, since when we enter the first ndo_xmit(), cpu migration is
706d0722a2SEric Dumazet    forbidden. We force an exit if this counter reaches RECURSION_LIMIT
711da177e4SLinus Torvalds 
721da177e4SLinus Torvalds    2. Networking dead loops would not kill routers, but would really
731da177e4SLinus Torvalds    kill network. IP hop limit plays role of "t->recursion" in this case,
741da177e4SLinus Torvalds    if we copy it from packet being encapsulated to upper header.
751da177e4SLinus Torvalds    It is very good solution, but it introduces two problems:
761da177e4SLinus Torvalds 
771da177e4SLinus Torvalds    - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
781da177e4SLinus Torvalds      do not work over tunnels.
791da177e4SLinus Torvalds    - traceroute does not work. I planned to relay ICMP from tunnel,
801da177e4SLinus Torvalds      so that this problem would be solved and traceroute output
811da177e4SLinus Torvalds      would even more informative. This idea appeared to be wrong:
821da177e4SLinus Torvalds      only Linux complies to rfc1812 now (yes, guys, Linux is the only
831da177e4SLinus Torvalds      true router now :-)), all routers (at least, in neighbourhood of mine)
841da177e4SLinus Torvalds      return only 8 bytes of payload. It is the end.
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds    Hence, if we want that OSPF worked or traceroute said something reasonable,
871da177e4SLinus Torvalds    we should search for another solution.
881da177e4SLinus Torvalds 
891da177e4SLinus Torvalds    One of them is to parse packet trying to detect inner encapsulation
901da177e4SLinus Torvalds    made by our node. It is difficult or even impossible, especially,
91bff52857Sstephen hemminger    taking into account fragmentation. TO be short, ttl is not solution at all.
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds    Current solution: The solution was UNEXPECTEDLY SIMPLE.
941da177e4SLinus Torvalds    We force DF flag on tunnels with preconfigured hop limit,
951da177e4SLinus Torvalds    that is ALL. :-) Well, it does not remove the problem completely,
961da177e4SLinus Torvalds    but exponential growth of network traffic is changed to linear
971da177e4SLinus Torvalds    (branches, that exceed pmtu are pruned) and tunnel mtu
98bff52857Sstephen hemminger    rapidly degrades to value <68, where looping stops.
991da177e4SLinus Torvalds    Yes, it is not good if there exists a router in the loop,
1001da177e4SLinus Torvalds    which does not force DF, even when encapsulating packets have DF set.
1011da177e4SLinus Torvalds    But it is not our problem! Nobody could accuse us, we made
1021da177e4SLinus Torvalds    all that we could make. Even if it is your gated who injected
1031da177e4SLinus Torvalds    fatal route to network, even if it were you who configured
1041da177e4SLinus Torvalds    fatal static route: you are innocent. :-)
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds    Alexey Kuznetsov.
1071da177e4SLinus Torvalds  */
1081da177e4SLinus Torvalds 
109eccc1bb8Sstephen hemminger static bool log_ecn_error = true;
110eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644);
111eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
112eccc1bb8Sstephen hemminger 
113c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly;
1141da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev);
115eb8ce741SPavel Emelyanov 
116c7d03a00SAlexey Dobriyan static unsigned int ipgre_net_id __read_mostly;
117c7d03a00SAlexey Dobriyan static unsigned int gre_tap_net_id __read_mostly;
118eb8ce741SPavel Emelyanov 
1199f57c67cSPravin B Shelar static void ipgre_err(struct sk_buff *skb, u32 info,
120bda7bb46SPravin B Shelar 		      const struct tnl_ptk_info *tpi)
1211da177e4SLinus Torvalds {
1221da177e4SLinus Torvalds 
123071f92d0SRami Rosen 	/* All the routers (except for Linux) return only
1241da177e4SLinus Torvalds 	   8 bytes of packet payload. It means, that precise relaying of
1251da177e4SLinus Torvalds 	   ICMP in the real Internet is absolutely infeasible.
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds 	   Moreover, Cisco "wise men" put GRE key to the third word
128c5441932SPravin B Shelar 	   in GRE header. It makes impossible maintaining even soft
129c5441932SPravin B Shelar 	   state for keyed GRE tunnels with enabled checksum. Tell
130c5441932SPravin B Shelar 	   them "thank you".
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds 	   Well, I wonder, rfc1812 was written by Cisco employee,
133bff52857Sstephen hemminger 	   what the hell these idiots break standards established
134bff52857Sstephen hemminger 	   by themselves???
1351da177e4SLinus Torvalds 	   */
136c5441932SPravin B Shelar 	struct net *net = dev_net(skb->dev);
137c5441932SPravin B Shelar 	struct ip_tunnel_net *itn;
13896f5a846SEric Dumazet 	const struct iphdr *iph;
13988c7664fSArnaldo Carvalho de Melo 	const int type = icmp_hdr(skb)->type;
14088c7664fSArnaldo Carvalho de Melo 	const int code = icmp_hdr(skb)->code;
14120e1954fSEric Dumazet 	unsigned int data_len = 0;
1421da177e4SLinus Torvalds 	struct ip_tunnel *t;
143d2083287Sstephen hemminger 
1441da177e4SLinus Torvalds 	switch (type) {
1451da177e4SLinus Torvalds 	default:
1461da177e4SLinus Torvalds 	case ICMP_PARAMETERPROB:
1479f57c67cSPravin B Shelar 		return;
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds 	case ICMP_DEST_UNREACH:
1501da177e4SLinus Torvalds 		switch (code) {
1511da177e4SLinus Torvalds 		case ICMP_SR_FAILED:
1521da177e4SLinus Torvalds 		case ICMP_PORT_UNREACH:
1531da177e4SLinus Torvalds 			/* Impossible event. */
1549f57c67cSPravin B Shelar 			return;
1551da177e4SLinus Torvalds 		default:
1561da177e4SLinus Torvalds 			/* All others are translated to HOST_UNREACH.
1571da177e4SLinus Torvalds 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
1581da177e4SLinus Torvalds 			   I believe they are just ether pollution. --ANK
1591da177e4SLinus Torvalds 			 */
1601da177e4SLinus Torvalds 			break;
1611da177e4SLinus Torvalds 		}
1621da177e4SLinus Torvalds 		break;
1639f57c67cSPravin B Shelar 
1641da177e4SLinus Torvalds 	case ICMP_TIME_EXCEEDED:
1651da177e4SLinus Torvalds 		if (code != ICMP_EXC_TTL)
1669f57c67cSPravin B Shelar 			return;
16720e1954fSEric Dumazet 		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
1681da177e4SLinus Torvalds 		break;
16955be7a9cSDavid S. Miller 
17055be7a9cSDavid S. Miller 	case ICMP_REDIRECT:
17155be7a9cSDavid S. Miller 		break;
1721da177e4SLinus Torvalds 	}
1731da177e4SLinus Torvalds 
174bda7bb46SPravin B Shelar 	if (tpi->proto == htons(ETH_P_TEB))
175c5441932SPravin B Shelar 		itn = net_generic(net, gre_tap_net_id);
176c5441932SPravin B Shelar 	else
177c5441932SPravin B Shelar 		itn = net_generic(net, ipgre_net_id);
178c5441932SPravin B Shelar 
179c0c0c50fSDuan Jiong 	iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
180bda7bb46SPravin B Shelar 	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
181bda7bb46SPravin B Shelar 			     iph->daddr, iph->saddr, tpi->key);
182d2083287Sstephen hemminger 
18351456b29SIan Morris 	if (!t)
1849f57c67cSPravin B Shelar 		return;
18536393395SDavid S. Miller 
1869b8c6d7bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1879b8c6d7bSEric Dumazet        if (tpi->proto == htons(ETH_P_IPV6) &&
18820e1954fSEric Dumazet            !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
18920e1954fSEric Dumazet 				       type, data_len))
1909b8c6d7bSEric Dumazet                return;
1919b8c6d7bSEric Dumazet #endif
1929b8c6d7bSEric Dumazet 
19336393395SDavid S. Miller 	if (t->parms.iph.daddr == 0 ||
194f97c1e0cSJoe Perches 	    ipv4_is_multicast(t->parms.iph.daddr))
1959f57c67cSPravin B Shelar 		return;
1961da177e4SLinus Torvalds 
1971da177e4SLinus Torvalds 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
1989f57c67cSPravin B Shelar 		return;
1991da177e4SLinus Torvalds 
200da6185d8SWei Yongjun 	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
2011da177e4SLinus Torvalds 		t->err_count++;
2021da177e4SLinus Torvalds 	else
2031da177e4SLinus Torvalds 		t->err_count = 1;
2041da177e4SLinus Torvalds 	t->err_time = jiffies;
2059f57c67cSPravin B Shelar }
2069f57c67cSPravin B Shelar 
2079f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info)
2089f57c67cSPravin B Shelar {
2099f57c67cSPravin B Shelar 	/* All the routers (except for Linux) return only
2109f57c67cSPravin B Shelar 	 * 8 bytes of packet payload. It means, that precise relaying of
2119f57c67cSPravin B Shelar 	 * ICMP in the real Internet is absolutely infeasible.
2129f57c67cSPravin B Shelar 	 *
2139f57c67cSPravin B Shelar 	 * Moreover, Cisco "wise men" put GRE key to the third word
2149f57c67cSPravin B Shelar 	 * in GRE header. It makes impossible maintaining even soft
2159f57c67cSPravin B Shelar 	 * state for keyed
2169f57c67cSPravin B Shelar 	 * GRE tunnels with enabled checksum. Tell them "thank you".
2179f57c67cSPravin B Shelar 	 *
2189f57c67cSPravin B Shelar 	 * Well, I wonder, rfc1812 was written by Cisco employee,
2199f57c67cSPravin B Shelar 	 * what the hell these idiots break standards established
2209f57c67cSPravin B Shelar 	 * by themselves???
2219f57c67cSPravin B Shelar 	 */
2229f57c67cSPravin B Shelar 
223e582615aSEric Dumazet 	const struct iphdr *iph = (struct iphdr *)skb->data;
2249f57c67cSPravin B Shelar 	const int type = icmp_hdr(skb)->type;
2259f57c67cSPravin B Shelar 	const int code = icmp_hdr(skb)->code;
2269f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
2279f57c67cSPravin B Shelar 	bool csum_err = false;
2289f57c67cSPravin B Shelar 
229e582615aSEric Dumazet 	if (gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP),
230e582615aSEric Dumazet 			     iph->ihl * 4) < 0) {
2319f57c67cSPravin B Shelar 		if (!csum_err)		/* ignore csum errors. */
2329f57c67cSPravin B Shelar 			return;
2339f57c67cSPravin B Shelar 	}
2349f57c67cSPravin B Shelar 
2359f57c67cSPravin B Shelar 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
2369f57c67cSPravin B Shelar 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
2379f57c67cSPravin B Shelar 				 skb->dev->ifindex, 0, IPPROTO_GRE, 0);
2389f57c67cSPravin B Shelar 		return;
2399f57c67cSPravin B Shelar 	}
2409f57c67cSPravin B Shelar 	if (type == ICMP_REDIRECT) {
2419f57c67cSPravin B Shelar 		ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0,
2429f57c67cSPravin B Shelar 			      IPPROTO_GRE, 0);
2439f57c67cSPravin B Shelar 		return;
2449f57c67cSPravin B Shelar 	}
2459f57c67cSPravin B Shelar 
2469f57c67cSPravin B Shelar 	ipgre_err(skb, info, &tpi);
2471da177e4SLinus Torvalds }
2481da177e4SLinus Torvalds 
249125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
250125372faSJiri Benc 		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
2511da177e4SLinus Torvalds {
2522e15ea39SPravin B Shelar 	struct metadata_dst *tun_dst = NULL;
253b71d1d42SEric Dumazet 	const struct iphdr *iph;
2541da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
2551da177e4SLinus Torvalds 
256eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
257bda7bb46SPravin B Shelar 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
258bda7bb46SPravin B Shelar 				  iph->saddr, iph->daddr, tpi->key);
2591da177e4SLinus Torvalds 
260d2083287Sstephen hemminger 	if (tunnel) {
261125372faSJiri Benc 		if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
262125372faSJiri Benc 					   raw_proto, false) < 0)
263244a797bSJiri Benc 			goto drop;
264244a797bSJiri Benc 
265e271c7b4SJiri Benc 		if (tunnel->dev->type != ARPHRD_NONE)
2660e3da5bbSTimo Teräs 			skb_pop_mac_header(skb);
267e271c7b4SJiri Benc 		else
268e271c7b4SJiri Benc 			skb_reset_mac_header(skb);
2692e15ea39SPravin B Shelar 		if (tunnel->collect_md) {
270c29a70d2SPravin B Shelar 			__be16 flags;
271c29a70d2SPravin B Shelar 			__be64 tun_id;
2722e15ea39SPravin B Shelar 
273c29a70d2SPravin B Shelar 			flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
274d817f432SAmir Vadai 			tun_id = key32_to_tunnel_id(tpi->key);
275c29a70d2SPravin B Shelar 			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
2762e15ea39SPravin B Shelar 			if (!tun_dst)
2772e15ea39SPravin B Shelar 				return PACKET_REJECT;
2782e15ea39SPravin B Shelar 		}
2792e15ea39SPravin B Shelar 
2802e15ea39SPravin B Shelar 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
281bda7bb46SPravin B Shelar 		return PACKET_RCVD;
2821da177e4SLinus Torvalds 	}
283125372faSJiri Benc 	return PACKET_NEXT;
284244a797bSJiri Benc 
285244a797bSJiri Benc drop:
286244a797bSJiri Benc 	kfree_skb(skb);
287244a797bSJiri Benc 	return PACKET_RCVD;
2881da177e4SLinus Torvalds }
2891da177e4SLinus Torvalds 
290125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
291125372faSJiri Benc 		     int hdr_len)
292125372faSJiri Benc {
293125372faSJiri Benc 	struct net *net = dev_net(skb->dev);
294125372faSJiri Benc 	struct ip_tunnel_net *itn;
295125372faSJiri Benc 	int res;
296125372faSJiri Benc 
297125372faSJiri Benc 	if (tpi->proto == htons(ETH_P_TEB))
298125372faSJiri Benc 		itn = net_generic(net, gre_tap_net_id);
299125372faSJiri Benc 	else
300125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
301125372faSJiri Benc 
302125372faSJiri Benc 	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
303125372faSJiri Benc 	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
304125372faSJiri Benc 		/* ipgre tunnels in collect metadata mode should receive
305125372faSJiri Benc 		 * also ETH_P_TEB traffic.
306125372faSJiri Benc 		 */
307125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
308125372faSJiri Benc 		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
309125372faSJiri Benc 	}
310125372faSJiri Benc 	return res;
311125372faSJiri Benc }
312125372faSJiri Benc 
3139f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb)
3149f57c67cSPravin B Shelar {
3159f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
3169f57c67cSPravin B Shelar 	bool csum_err = false;
31795f5c64cSTom Herbert 	int hdr_len;
3189f57c67cSPravin B Shelar 
3199f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST
3209f57c67cSPravin B Shelar 	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
3219f57c67cSPravin B Shelar 		/* Looped back packet, drop it! */
3229f57c67cSPravin B Shelar 		if (rt_is_output_route(skb_rtable(skb)))
3239f57c67cSPravin B Shelar 			goto drop;
3249f57c67cSPravin B Shelar 	}
3259f57c67cSPravin B Shelar #endif
3269f57c67cSPravin B Shelar 
327e582615aSEric Dumazet 	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
328f132ae7cSJiri Benc 	if (hdr_len < 0)
32995f5c64cSTom Herbert 		goto drop;
33095f5c64cSTom Herbert 
331244a797bSJiri Benc 	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
3329f57c67cSPravin B Shelar 		return 0;
3339f57c67cSPravin B Shelar 
3349f57c67cSPravin B Shelar 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
3359f57c67cSPravin B Shelar drop:
3369f57c67cSPravin B Shelar 	kfree_skb(skb);
3379f57c67cSPravin B Shelar 	return 0;
3389f57c67cSPravin B Shelar }
3399f57c67cSPravin B Shelar 
340c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
341c5441932SPravin B Shelar 		       const struct iphdr *tnl_params,
342c5441932SPravin B Shelar 		       __be16 proto)
343c5441932SPravin B Shelar {
344c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
345c5441932SPravin B Shelar 
346c5441932SPravin B Shelar 	if (tunnel->parms.o_flags & TUNNEL_SEQ)
347c5441932SPravin B Shelar 		tunnel->o_seqno++;
348cef401deSEric Dumazet 
349c5441932SPravin B Shelar 	/* Push GRE header. */
350182a352dSTom Herbert 	gre_build_header(skb, tunnel->tun_hlen,
351182a352dSTom Herbert 			 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
352182a352dSTom Herbert 			 htonl(tunnel->o_seqno));
3531da177e4SLinus Torvalds 
354bf3d6a8fSNicolas Dichtel 	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
3551da177e4SLinus Torvalds }
3561da177e4SLinus Torvalds 
357aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum)
358b2acd1dcSPravin B Shelar {
3596fa79666SEdward Cree 	return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
360b2acd1dcSPravin B Shelar }
361b2acd1dcSPravin B Shelar 
362fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb,
363fc4099f1SPravin B Shelar 				 struct net_device *dev,
364fc4099f1SPravin B Shelar 				 struct flowi4 *fl,
365fc4099f1SPravin B Shelar 				 const struct ip_tunnel_key *key)
366fc4099f1SPravin B Shelar {
367fc4099f1SPravin B Shelar 	struct net *net = dev_net(dev);
368fc4099f1SPravin B Shelar 
369fc4099f1SPravin B Shelar 	memset(fl, 0, sizeof(*fl));
370fc4099f1SPravin B Shelar 	fl->daddr = key->u.ipv4.dst;
371fc4099f1SPravin B Shelar 	fl->saddr = key->u.ipv4.src;
372fc4099f1SPravin B Shelar 	fl->flowi4_tos = RT_TOS(key->tos);
373fc4099f1SPravin B Shelar 	fl->flowi4_mark = skb->mark;
374fc4099f1SPravin B Shelar 	fl->flowi4_proto = IPPROTO_GRE;
375fc4099f1SPravin B Shelar 
376fc4099f1SPravin B Shelar 	return ip_route_output_key(net, fl);
377fc4099f1SPravin B Shelar }
378fc4099f1SPravin B Shelar 
3792090714eSJiri Benc static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
3802090714eSJiri Benc 			__be16 proto)
3812e15ea39SPravin B Shelar {
3822e15ea39SPravin B Shelar 	struct ip_tunnel_info *tun_info;
3832e15ea39SPravin B Shelar 	const struct ip_tunnel_key *key;
384db3c6139SDaniel Borkmann 	struct rtable *rt = NULL;
3852e15ea39SPravin B Shelar 	struct flowi4 fl;
3862e15ea39SPravin B Shelar 	int min_headroom;
3872e15ea39SPravin B Shelar 	int tunnel_hlen;
3882e15ea39SPravin B Shelar 	__be16 df, flags;
389db3c6139SDaniel Borkmann 	bool use_cache;
3902e15ea39SPravin B Shelar 	int err;
3912e15ea39SPravin B Shelar 
39261adedf3SJiri Benc 	tun_info = skb_tunnel_info(skb);
3937f9562a1SJiri Benc 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
3947f9562a1SJiri Benc 		     ip_tunnel_info_af(tun_info) != AF_INET))
3952e15ea39SPravin B Shelar 		goto err_free_skb;
3962e15ea39SPravin B Shelar 
3972e15ea39SPravin B Shelar 	key = &tun_info->key;
398db3c6139SDaniel Borkmann 	use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
399db3c6139SDaniel Borkmann 	if (use_cache)
400db3c6139SDaniel Borkmann 		rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl.saddr);
4013c1cb4d2SPaolo Abeni 	if (!rt) {
402fc4099f1SPravin B Shelar 		rt = gre_get_rt(skb, dev, &fl, key);
4032e15ea39SPravin B Shelar 		if (IS_ERR(rt))
4042e15ea39SPravin B Shelar 				goto err_free_skb;
405db3c6139SDaniel Borkmann 		if (use_cache)
4063c1cb4d2SPaolo Abeni 			dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
4073c1cb4d2SPaolo Abeni 					  fl.saddr);
4083c1cb4d2SPaolo Abeni 	}
4092e15ea39SPravin B Shelar 
41095f5c64cSTom Herbert 	tunnel_hlen = gre_calc_hlen(key->tun_flags);
4112e15ea39SPravin B Shelar 
4122e15ea39SPravin B Shelar 	min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
4132e15ea39SPravin B Shelar 			+ tunnel_hlen + sizeof(struct iphdr);
4142e15ea39SPravin B Shelar 	if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
4152e15ea39SPravin B Shelar 		int head_delta = SKB_DATA_ALIGN(min_headroom -
4162e15ea39SPravin B Shelar 						skb_headroom(skb) +
4172e15ea39SPravin B Shelar 						16);
4182e15ea39SPravin B Shelar 		err = pskb_expand_head(skb, max_t(int, head_delta, 0),
4192e15ea39SPravin B Shelar 				       0, GFP_ATOMIC);
4202e15ea39SPravin B Shelar 		if (unlikely(err))
4212e15ea39SPravin B Shelar 			goto err_free_rt;
4222e15ea39SPravin B Shelar 	}
4232e15ea39SPravin B Shelar 
4242e15ea39SPravin B Shelar 	/* Push Tunnel header. */
425aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
4262e15ea39SPravin B Shelar 		goto err_free_rt;
4272e15ea39SPravin B Shelar 
4282e15ea39SPravin B Shelar 	flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
429cba65321SDavid S. Miller 	gre_build_header(skb, tunnel_hlen, flags, proto,
430d817f432SAmir Vadai 			 tunnel_id_to_key32(tun_info->key.tun_id), 0);
4312e15ea39SPravin B Shelar 
4322e15ea39SPravin B Shelar 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
433039f5062SPravin B Shelar 
434039f5062SPravin B Shelar 	iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
4357c383fb2SJiri Benc 		      key->tos, key->ttl, df, false);
4362e15ea39SPravin B Shelar 	return;
4372e15ea39SPravin B Shelar 
4382e15ea39SPravin B Shelar err_free_rt:
4392e15ea39SPravin B Shelar 	ip_rt_put(rt);
4402e15ea39SPravin B Shelar err_free_skb:
4412e15ea39SPravin B Shelar 	kfree_skb(skb);
4422e15ea39SPravin B Shelar 	dev->stats.tx_dropped++;
4432e15ea39SPravin B Shelar }
4442e15ea39SPravin B Shelar 
445fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
446fc4099f1SPravin B Shelar {
447fc4099f1SPravin B Shelar 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
448fc4099f1SPravin B Shelar 	struct rtable *rt;
449fc4099f1SPravin B Shelar 	struct flowi4 fl4;
450fc4099f1SPravin B Shelar 
451fc4099f1SPravin B Shelar 	if (ip_tunnel_info_af(info) != AF_INET)
452fc4099f1SPravin B Shelar 		return -EINVAL;
453fc4099f1SPravin B Shelar 
454fc4099f1SPravin B Shelar 	rt = gre_get_rt(skb, dev, &fl4, &info->key);
455fc4099f1SPravin B Shelar 	if (IS_ERR(rt))
456fc4099f1SPravin B Shelar 		return PTR_ERR(rt);
457fc4099f1SPravin B Shelar 
458fc4099f1SPravin B Shelar 	ip_rt_put(rt);
459fc4099f1SPravin B Shelar 	info->key.u.ipv4.src = fl4.saddr;
460fc4099f1SPravin B Shelar 	return 0;
461fc4099f1SPravin B Shelar }
462fc4099f1SPravin B Shelar 
463c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
464c5441932SPravin B Shelar 			      struct net_device *dev)
465ee34c1ebSMichal Schmidt {
466c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
467c5441932SPravin B Shelar 	const struct iphdr *tnl_params;
468ee34c1ebSMichal Schmidt 
4692e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
4702090714eSJiri Benc 		gre_fb_xmit(skb, dev, skb->protocol);
4712e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
4722e15ea39SPravin B Shelar 	}
4732e15ea39SPravin B Shelar 
474c5441932SPravin B Shelar 	if (dev->header_ops) {
475c5441932SPravin B Shelar 		/* Need space for new headers */
476c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom -
4772bac7cb3SChen Gang 				      (tunnel->hlen + sizeof(struct iphdr))))
478c5441932SPravin B Shelar 			goto free_skb;
479ee34c1ebSMichal Schmidt 
480c5441932SPravin B Shelar 		tnl_params = (const struct iphdr *)skb->data;
481cbb1e85fSDavid S. Miller 
482c5441932SPravin B Shelar 		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
483c5441932SPravin B Shelar 		 * to gre header.
484c5441932SPravin B Shelar 		 */
485c5441932SPravin B Shelar 		skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
4868a0033a9STimo Teräs 		skb_reset_mac_header(skb);
487c5441932SPravin B Shelar 	} else {
488c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom))
489c5441932SPravin B Shelar 			goto free_skb;
490c5441932SPravin B Shelar 
491c5441932SPravin B Shelar 		tnl_params = &tunnel->parms.iph;
492ee34c1ebSMichal Schmidt 	}
493e1a80002SHerbert Xu 
494aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
495aed069dfSAlexander Duyck 		goto free_skb;
4968a0033a9STimo Teräs 
497c5441932SPravin B Shelar 	__gre_xmit(skb, dev, tnl_params, skb->protocol);
498c5441932SPravin B Shelar 	return NETDEV_TX_OK;
499c5441932SPravin B Shelar 
500c5441932SPravin B Shelar free_skb:
5013acfa1e7SEric Dumazet 	kfree_skb(skb);
502c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
503c5441932SPravin B Shelar 	return NETDEV_TX_OK;
504ee34c1ebSMichal Schmidt }
505ee34c1ebSMichal Schmidt 
506c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
507c5441932SPravin B Shelar 				struct net_device *dev)
508c5441932SPravin B Shelar {
509c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
510ee34c1ebSMichal Schmidt 
5112e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
5122090714eSJiri Benc 		gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
5132e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
5142e15ea39SPravin B Shelar 	}
5152e15ea39SPravin B Shelar 
516aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
517aed069dfSAlexander Duyck 		goto free_skb;
518ee34c1ebSMichal Schmidt 
519c5441932SPravin B Shelar 	if (skb_cow_head(skb, dev->needed_headroom))
520c5441932SPravin B Shelar 		goto free_skb;
52142aa9162SHerbert Xu 
522c5441932SPravin B Shelar 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
523c5441932SPravin B Shelar 	return NETDEV_TX_OK;
524c5441932SPravin B Shelar 
525c5441932SPravin B Shelar free_skb:
5263acfa1e7SEric Dumazet 	kfree_skb(skb);
527c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
528c5441932SPravin B Shelar 	return NETDEV_TX_OK;
52968c33163SPravin B Shelar }
530ee34c1ebSMichal Schmidt 
531c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev,
532c5441932SPravin B Shelar 			      struct ifreq *ifr, int cmd)
5331da177e4SLinus Torvalds {
5344565e991STom Herbert 	int err;
5351da177e4SLinus Torvalds 	struct ip_tunnel_parm p;
5361da177e4SLinus Torvalds 
5371da177e4SLinus Torvalds 	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
538c5441932SPravin B Shelar 		return -EFAULT;
5396c734fb8SCong Wang 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
5401da177e4SLinus Torvalds 		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
5411da177e4SLinus Torvalds 		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
5426c734fb8SCong Wang 		    ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
5431da177e4SLinus Torvalds 			return -EINVAL;
544c5441932SPravin B Shelar 	}
545c5441932SPravin B Shelar 	p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
546c5441932SPravin B Shelar 	p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
547c5441932SPravin B Shelar 
548c5441932SPravin B Shelar 	err = ip_tunnel_ioctl(dev, &p, cmd);
549c5441932SPravin B Shelar 	if (err)
550c5441932SPravin B Shelar 		return err;
551c5441932SPravin B Shelar 
55295f5c64cSTom Herbert 	p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
55395f5c64cSTom Herbert 	p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
554c5441932SPravin B Shelar 
555c5441932SPravin B Shelar 	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
556c5441932SPravin B Shelar 		return -EFAULT;
5571da177e4SLinus Torvalds 	return 0;
5581da177e4SLinus Torvalds }
5591da177e4SLinus Torvalds 
5601da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-)
5611da177e4SLinus Torvalds    It allows to construct virtual multiprotocol broadcast "LAN"
5621da177e4SLinus Torvalds    over the Internet, provided multicast routing is tuned.
5631da177e4SLinus Torvalds 
5641da177e4SLinus Torvalds 
5651da177e4SLinus Torvalds    I have no idea was this bicycle invented before me,
5661da177e4SLinus Torvalds    so that I had to set ARPHRD_IPGRE to a random value.
5671da177e4SLinus Torvalds    I have an impression, that Cisco could make something similar,
5681da177e4SLinus Torvalds    but this feature is apparently missing in IOS<=11.2(8).
5691da177e4SLinus Torvalds 
5701da177e4SLinus Torvalds    I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
5711da177e4SLinus Torvalds    with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
5721da177e4SLinus Torvalds 
5731da177e4SLinus Torvalds    ping -t 255 224.66.66.66
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds    If nobody answers, mbone does not work.
5761da177e4SLinus Torvalds 
5771da177e4SLinus Torvalds    ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
5781da177e4SLinus Torvalds    ip addr add 10.66.66.<somewhat>/24 dev Universe
5791da177e4SLinus Torvalds    ifconfig Universe up
5801da177e4SLinus Torvalds    ifconfig Universe add fe80::<Your_real_addr>/10
5811da177e4SLinus Torvalds    ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
5821da177e4SLinus Torvalds    ftp 10.66.66.66
5831da177e4SLinus Torvalds    ...
5841da177e4SLinus Torvalds    ftp fec0:6666:6666::193.233.7.65
5851da177e4SLinus Torvalds    ...
5861da177e4SLinus Torvalds  */
5873b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
5883b04dddeSStephen Hemminger 			unsigned short type,
5891507850bSEric Dumazet 			const void *daddr, const void *saddr, unsigned int len)
5901da177e4SLinus Torvalds {
5912941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
592c5441932SPravin B Shelar 	struct iphdr *iph;
593c5441932SPravin B Shelar 	struct gre_base_hdr *greh;
594c5441932SPravin B Shelar 
595c5441932SPravin B Shelar 	iph = (struct iphdr *)skb_push(skb, t->hlen + sizeof(*iph));
596c5441932SPravin B Shelar 	greh = (struct gre_base_hdr *)(iph+1);
59795f5c64cSTom Herbert 	greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
598c5441932SPravin B Shelar 	greh->protocol = htons(type);
5991da177e4SLinus Torvalds 
6001da177e4SLinus Torvalds 	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
6011da177e4SLinus Torvalds 
602c5441932SPravin B Shelar 	/* Set the source hardware address. */
6031da177e4SLinus Torvalds 	if (saddr)
6041da177e4SLinus Torvalds 		memcpy(&iph->saddr, saddr, 4);
6056d55cb91STimo Teräs 	if (daddr)
6061da177e4SLinus Torvalds 		memcpy(&iph->daddr, daddr, 4);
6076d55cb91STimo Teräs 	if (iph->daddr)
60877a482bdSTimo Teräs 		return t->hlen + sizeof(*iph);
6091da177e4SLinus Torvalds 
610c5441932SPravin B Shelar 	return -(t->hlen + sizeof(*iph));
6111da177e4SLinus Torvalds }
6121da177e4SLinus Torvalds 
6136a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
6146a5f44d7STimo Teras {
615b71d1d42SEric Dumazet 	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
6166a5f44d7STimo Teras 	memcpy(haddr, &iph->saddr, 4);
6176a5f44d7STimo Teras 	return 4;
6186a5f44d7STimo Teras }
6196a5f44d7STimo Teras 
6203b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = {
6213b04dddeSStephen Hemminger 	.create	= ipgre_header,
6226a5f44d7STimo Teras 	.parse	= ipgre_header_parse,
6233b04dddeSStephen Hemminger };
6243b04dddeSStephen Hemminger 
6256a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST
6261da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev)
6271da177e4SLinus Torvalds {
6282941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
6291da177e4SLinus Torvalds 
630f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
631cbb1e85fSDavid S. Miller 		struct flowi4 fl4;
632cbb1e85fSDavid S. Miller 		struct rtable *rt;
633cbb1e85fSDavid S. Miller 
634b57708adSNicolas Dichtel 		rt = ip_route_output_gre(t->net, &fl4,
63578fbfd8aSDavid S. Miller 					 t->parms.iph.daddr,
63678fbfd8aSDavid S. Miller 					 t->parms.iph.saddr,
63778fbfd8aSDavid S. Miller 					 t->parms.o_key,
63878fbfd8aSDavid S. Miller 					 RT_TOS(t->parms.iph.tos),
63978fbfd8aSDavid S. Miller 					 t->parms.link);
640b23dd4feSDavid S. Miller 		if (IS_ERR(rt))
6411da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
642d8d1f30bSChangli Gao 		dev = rt->dst.dev;
6431da177e4SLinus Torvalds 		ip_rt_put(rt);
64451456b29SIan Morris 		if (!__in_dev_get_rtnl(dev))
6451da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
6461da177e4SLinus Torvalds 		t->mlink = dev->ifindex;
647e5ed6399SHerbert Xu 		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
6481da177e4SLinus Torvalds 	}
6491da177e4SLinus Torvalds 	return 0;
6501da177e4SLinus Torvalds }
6511da177e4SLinus Torvalds 
6521da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev)
6531da177e4SLinus Torvalds {
6542941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
655b8c26a33SStephen Hemminger 
656f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
6577fee0ca2SDenis V. Lunev 		struct in_device *in_dev;
658b57708adSNicolas Dichtel 		in_dev = inetdev_by_index(t->net, t->mlink);
6598723e1b4SEric Dumazet 		if (in_dev)
6601da177e4SLinus Torvalds 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
6611da177e4SLinus Torvalds 	}
6621da177e4SLinus Torvalds 	return 0;
6631da177e4SLinus Torvalds }
6641da177e4SLinus Torvalds #endif
6651da177e4SLinus Torvalds 
666b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = {
667b8c26a33SStephen Hemminger 	.ndo_init		= ipgre_tunnel_init,
668c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
669b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST
670b8c26a33SStephen Hemminger 	.ndo_open		= ipgre_open,
671b8c26a33SStephen Hemminger 	.ndo_stop		= ipgre_close,
672b8c26a33SStephen Hemminger #endif
673c5441932SPravin B Shelar 	.ndo_start_xmit		= ipgre_xmit,
674b8c26a33SStephen Hemminger 	.ndo_do_ioctl		= ipgre_tunnel_ioctl,
675c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
676c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
6771e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
678b8c26a33SStephen Hemminger };
679b8c26a33SStephen Hemminger 
6806b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG |		\
6816b78f16eSEric Dumazet 		      NETIF_F_FRAGLIST |	\
6826b78f16eSEric Dumazet 		      NETIF_F_HIGHDMA |		\
6836b78f16eSEric Dumazet 		      NETIF_F_HW_CSUM)
6846b78f16eSEric Dumazet 
6851da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev)
6861da177e4SLinus Torvalds {
687b8c26a33SStephen Hemminger 	dev->netdev_ops		= &ipgre_netdev_ops;
6885a455275SNicolas Dichtel 	dev->type		= ARPHRD_IPGRE;
689c5441932SPravin B Shelar 	ip_tunnel_setup(dev, ipgre_net_id);
690c5441932SPravin B Shelar }
6911da177e4SLinus Torvalds 
692c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev)
693c5441932SPravin B Shelar {
694c5441932SPravin B Shelar 	struct ip_tunnel *tunnel;
6954565e991STom Herbert 	int t_hlen;
696c5441932SPravin B Shelar 
697c5441932SPravin B Shelar 	tunnel = netdev_priv(dev);
69895f5c64cSTom Herbert 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
699c5441932SPravin B Shelar 	tunnel->parms.iph.protocol = IPPROTO_GRE;
700c5441932SPravin B Shelar 
7014565e991STom Herbert 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
7024565e991STom Herbert 
7034565e991STom Herbert 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
7044565e991STom Herbert 
7054565e991STom Herbert 	dev->needed_headroom	= LL_MAX_HEADER + t_hlen + 4;
7064565e991STom Herbert 	dev->mtu		= ETH_DATA_LEN - t_hlen - 4;
7076b78f16eSEric Dumazet 
708b57708adSNicolas Dichtel 	dev->features		|= GRE_FEATURES;
7096b78f16eSEric Dumazet 	dev->hw_features	|= GRE_FEATURES;
710c5441932SPravin B Shelar 
711c5441932SPravin B Shelar 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
712a0ca153fSAlexander Duyck 		/* TCP offload with GRE SEQ is not supported, nor
713a0ca153fSAlexander Duyck 		 * can we support 2 levels of outer headers requiring
714a0ca153fSAlexander Duyck 		 * an update.
715a0ca153fSAlexander Duyck 		 */
716a0ca153fSAlexander Duyck 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
717a0ca153fSAlexander Duyck 		    (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
718c5441932SPravin B Shelar 			dev->features    |= NETIF_F_GSO_SOFTWARE;
719c5441932SPravin B Shelar 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
720a0ca153fSAlexander Duyck 		}
721a0ca153fSAlexander Duyck 
722c5441932SPravin B Shelar 		/* Can use a lockless transmit, unless we generate
723c5441932SPravin B Shelar 		 * output sequences
724c5441932SPravin B Shelar 		 */
725c5441932SPravin B Shelar 		dev->features |= NETIF_F_LLTX;
726c5441932SPravin B Shelar 	}
7271da177e4SLinus Torvalds }
7281da177e4SLinus Torvalds 
7291da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev)
7301da177e4SLinus Torvalds {
731c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
732c5441932SPravin B Shelar 	struct iphdr *iph = &tunnel->parms.iph;
7331da177e4SLinus Torvalds 
734c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
7351da177e4SLinus Torvalds 
736c5441932SPravin B Shelar 	memcpy(dev->dev_addr, &iph->saddr, 4);
737c5441932SPravin B Shelar 	memcpy(dev->broadcast, &iph->daddr, 4);
7381da177e4SLinus Torvalds 
739c5441932SPravin B Shelar 	dev->flags		= IFF_NOARP;
74002875878SEric Dumazet 	netif_keep_dst(dev);
741c5441932SPravin B Shelar 	dev->addr_len		= 4;
7421da177e4SLinus Torvalds 
743a64b04d8SJiri Benc 	if (iph->daddr && !tunnel->collect_md) {
7441da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST
745f97c1e0cSJoe Perches 		if (ipv4_is_multicast(iph->daddr)) {
7461da177e4SLinus Torvalds 			if (!iph->saddr)
7471da177e4SLinus Torvalds 				return -EINVAL;
7481da177e4SLinus Torvalds 			dev->flags = IFF_BROADCAST;
7493b04dddeSStephen Hemminger 			dev->header_ops = &ipgre_header_ops;
7501da177e4SLinus Torvalds 		}
7511da177e4SLinus Torvalds #endif
752a64b04d8SJiri Benc 	} else if (!tunnel->collect_md) {
7536a5f44d7STimo Teras 		dev->header_ops = &ipgre_header_ops;
754a64b04d8SJiri Benc 	}
7551da177e4SLinus Torvalds 
756c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
75760769a5dSEric Dumazet }
75860769a5dSEric Dumazet 
7599f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = {
7609f57c67cSPravin B Shelar 	.handler     = gre_rcv,
7619f57c67cSPravin B Shelar 	.err_handler = gre_err,
7621da177e4SLinus Torvalds };
7631da177e4SLinus Torvalds 
7642c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net)
76559a4c759SPavel Emelyanov {
766c5441932SPravin B Shelar 	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
76759a4c759SPavel Emelyanov }
76859a4c759SPavel Emelyanov 
7692c8c1e72SAlexey Dobriyan static void __net_exit ipgre_exit_net(struct net *net)
77059a4c759SPavel Emelyanov {
771c5441932SPravin B Shelar 	struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id);
7726c742e71SNicolas Dichtel 	ip_tunnel_delete_net(itn, &ipgre_link_ops);
77359a4c759SPavel Emelyanov }
77459a4c759SPavel Emelyanov 
77559a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = {
77659a4c759SPavel Emelyanov 	.init = ipgre_init_net,
77759a4c759SPavel Emelyanov 	.exit = ipgre_exit_net,
778cfb8fbf2SEric W. Biederman 	.id   = &ipgre_net_id,
779c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
78059a4c759SPavel Emelyanov };
7811da177e4SLinus Torvalds 
782c19e654dSHerbert Xu static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
783c19e654dSHerbert Xu {
784c19e654dSHerbert Xu 	__be16 flags;
785c19e654dSHerbert Xu 
786c19e654dSHerbert Xu 	if (!data)
787c19e654dSHerbert Xu 		return 0;
788c19e654dSHerbert Xu 
789c19e654dSHerbert Xu 	flags = 0;
790c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
791c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
792c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
793c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
794c19e654dSHerbert Xu 	if (flags & (GRE_VERSION|GRE_ROUTING))
795c19e654dSHerbert Xu 		return -EINVAL;
796c19e654dSHerbert Xu 
797946b636fSJiri Benc 	if (data[IFLA_GRE_COLLECT_METADATA] &&
798946b636fSJiri Benc 	    data[IFLA_GRE_ENCAP_TYPE] &&
799946b636fSJiri Benc 	    nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
800946b636fSJiri Benc 		return -EINVAL;
801946b636fSJiri Benc 
802c19e654dSHerbert Xu 	return 0;
803c19e654dSHerbert Xu }
804c19e654dSHerbert Xu 
805e1a80002SHerbert Xu static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
806e1a80002SHerbert Xu {
807e1a80002SHerbert Xu 	__be32 daddr;
808e1a80002SHerbert Xu 
809e1a80002SHerbert Xu 	if (tb[IFLA_ADDRESS]) {
810e1a80002SHerbert Xu 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
811e1a80002SHerbert Xu 			return -EINVAL;
812e1a80002SHerbert Xu 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
813e1a80002SHerbert Xu 			return -EADDRNOTAVAIL;
814e1a80002SHerbert Xu 	}
815e1a80002SHerbert Xu 
816e1a80002SHerbert Xu 	if (!data)
817e1a80002SHerbert Xu 		goto out;
818e1a80002SHerbert Xu 
819e1a80002SHerbert Xu 	if (data[IFLA_GRE_REMOTE]) {
820e1a80002SHerbert Xu 		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
821e1a80002SHerbert Xu 		if (!daddr)
822e1a80002SHerbert Xu 			return -EINVAL;
823e1a80002SHerbert Xu 	}
824e1a80002SHerbert Xu 
825e1a80002SHerbert Xu out:
826e1a80002SHerbert Xu 	return ipgre_tunnel_validate(tb, data);
827e1a80002SHerbert Xu }
828e1a80002SHerbert Xu 
82922a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev,
8302e15ea39SPravin B Shelar 				struct nlattr *data[],
8312e15ea39SPravin B Shelar 				struct nlattr *tb[],
832c19e654dSHerbert Xu 				struct ip_tunnel_parm *parms)
833c19e654dSHerbert Xu {
83422a59be8SPhilip Prindeville 	struct ip_tunnel *t = netdev_priv(dev);
83522a59be8SPhilip Prindeville 
8367bb82d92SHerbert Xu 	memset(parms, 0, sizeof(*parms));
837c19e654dSHerbert Xu 
838c19e654dSHerbert Xu 	parms->iph.protocol = IPPROTO_GRE;
839c19e654dSHerbert Xu 
840c19e654dSHerbert Xu 	if (!data)
84122a59be8SPhilip Prindeville 		return 0;
842c19e654dSHerbert Xu 
843c19e654dSHerbert Xu 	if (data[IFLA_GRE_LINK])
844c19e654dSHerbert Xu 		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
845c19e654dSHerbert Xu 
846c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
847c5441932SPravin B Shelar 		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
848c19e654dSHerbert Xu 
849c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
850c5441932SPravin B Shelar 		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
851c19e654dSHerbert Xu 
852c19e654dSHerbert Xu 	if (data[IFLA_GRE_IKEY])
853c19e654dSHerbert Xu 		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
854c19e654dSHerbert Xu 
855c19e654dSHerbert Xu 	if (data[IFLA_GRE_OKEY])
856c19e654dSHerbert Xu 		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
857c19e654dSHerbert Xu 
858c19e654dSHerbert Xu 	if (data[IFLA_GRE_LOCAL])
85967b61f6cSJiri Benc 		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
860c19e654dSHerbert Xu 
861c19e654dSHerbert Xu 	if (data[IFLA_GRE_REMOTE])
86267b61f6cSJiri Benc 		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
863c19e654dSHerbert Xu 
864c19e654dSHerbert Xu 	if (data[IFLA_GRE_TTL])
865c19e654dSHerbert Xu 		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
866c19e654dSHerbert Xu 
867c19e654dSHerbert Xu 	if (data[IFLA_GRE_TOS])
868c19e654dSHerbert Xu 		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
869c19e654dSHerbert Xu 
87022a59be8SPhilip Prindeville 	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
87122a59be8SPhilip Prindeville 		if (t->ignore_df)
87222a59be8SPhilip Prindeville 			return -EINVAL;
873c19e654dSHerbert Xu 		parms->iph.frag_off = htons(IP_DF);
87422a59be8SPhilip Prindeville 	}
8752e15ea39SPravin B Shelar 
8762e15ea39SPravin B Shelar 	if (data[IFLA_GRE_COLLECT_METADATA]) {
8772e15ea39SPravin B Shelar 		t->collect_md = true;
878e271c7b4SJiri Benc 		if (dev->type == ARPHRD_IPGRE)
879e271c7b4SJiri Benc 			dev->type = ARPHRD_NONE;
8802e15ea39SPravin B Shelar 	}
88122a59be8SPhilip Prindeville 
88222a59be8SPhilip Prindeville 	if (data[IFLA_GRE_IGNORE_DF]) {
88322a59be8SPhilip Prindeville 		if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
88422a59be8SPhilip Prindeville 		  && (parms->iph.frag_off & htons(IP_DF)))
88522a59be8SPhilip Prindeville 			return -EINVAL;
88622a59be8SPhilip Prindeville 		t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
88722a59be8SPhilip Prindeville 	}
88822a59be8SPhilip Prindeville 
88922a59be8SPhilip Prindeville 	return 0;
890c19e654dSHerbert Xu }
891c19e654dSHerbert Xu 
8924565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */
8934565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[],
8944565e991STom Herbert 				      struct ip_tunnel_encap *ipencap)
8954565e991STom Herbert {
8964565e991STom Herbert 	bool ret = false;
8974565e991STom Herbert 
8984565e991STom Herbert 	memset(ipencap, 0, sizeof(*ipencap));
8994565e991STom Herbert 
9004565e991STom Herbert 	if (!data)
9014565e991STom Herbert 		return ret;
9024565e991STom Herbert 
9034565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_TYPE]) {
9044565e991STom Herbert 		ret = true;
9054565e991STom Herbert 		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
9064565e991STom Herbert 	}
9074565e991STom Herbert 
9084565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_FLAGS]) {
9094565e991STom Herbert 		ret = true;
9104565e991STom Herbert 		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
9114565e991STom Herbert 	}
9124565e991STom Herbert 
9134565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_SPORT]) {
9144565e991STom Herbert 		ret = true;
9153e97fa70SSabrina Dubroca 		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
9164565e991STom Herbert 	}
9174565e991STom Herbert 
9184565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_DPORT]) {
9194565e991STom Herbert 		ret = true;
9203e97fa70SSabrina Dubroca 		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
9214565e991STom Herbert 	}
9224565e991STom Herbert 
9234565e991STom Herbert 	return ret;
9244565e991STom Herbert }
9254565e991STom Herbert 
926c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev)
927e1a80002SHerbert Xu {
928c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
929bec94d43Sstephen hemminger 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
930e1a80002SHerbert Xu 
931c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
932e1a80002SHerbert Xu }
933e1a80002SHerbert Xu 
934c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = {
935c5441932SPravin B Shelar 	.ndo_init		= gre_tap_init,
936c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
937c5441932SPravin B Shelar 	.ndo_start_xmit		= gre_tap_xmit,
938b8c26a33SStephen Hemminger 	.ndo_set_mac_address 	= eth_mac_addr,
939b8c26a33SStephen Hemminger 	.ndo_validate_addr	= eth_validate_addr,
940c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
941c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
9421e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
943fc4099f1SPravin B Shelar 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
944b8c26a33SStephen Hemminger };
945b8c26a33SStephen Hemminger 
946e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev)
947e1a80002SHerbert Xu {
948e1a80002SHerbert Xu 	ether_setup(dev);
949c5441932SPravin B Shelar 	dev->netdev_ops	= &gre_tap_netdev_ops;
950d13b161cSJiri Benc 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
951f8c1b7ceSstephen hemminger 	dev->priv_flags	|= IFF_LIVE_ADDR_CHANGE;
952c5441932SPravin B Shelar 	ip_tunnel_setup(dev, gre_tap_net_id);
953e1a80002SHerbert Xu }
954e1a80002SHerbert Xu 
955c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev,
956c5441932SPravin B Shelar 			 struct nlattr *tb[], struct nlattr *data[])
957c19e654dSHerbert Xu {
958c5441932SPravin B Shelar 	struct ip_tunnel_parm p;
9594565e991STom Herbert 	struct ip_tunnel_encap ipencap;
96022a59be8SPhilip Prindeville 	int err;
9614565e991STom Herbert 
9624565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
9634565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
96422a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
9654565e991STom Herbert 
9664565e991STom Herbert 		if (err < 0)
9674565e991STom Herbert 			return err;
9684565e991STom Herbert 	}
969c19e654dSHerbert Xu 
97022a59be8SPhilip Prindeville 	err = ipgre_netlink_parms(dev, data, tb, &p);
97122a59be8SPhilip Prindeville 	if (err < 0)
97222a59be8SPhilip Prindeville 		return err;
973c5441932SPravin B Shelar 	return ip_tunnel_newlink(dev, tb, &p);
974c19e654dSHerbert Xu }
975c19e654dSHerbert Xu 
976c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
977c19e654dSHerbert Xu 			    struct nlattr *data[])
978c19e654dSHerbert Xu {
979c19e654dSHerbert Xu 	struct ip_tunnel_parm p;
9804565e991STom Herbert 	struct ip_tunnel_encap ipencap;
98122a59be8SPhilip Prindeville 	int err;
9824565e991STom Herbert 
9834565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
9844565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
98522a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
9864565e991STom Herbert 
9874565e991STom Herbert 		if (err < 0)
9884565e991STom Herbert 			return err;
9894565e991STom Herbert 	}
990c19e654dSHerbert Xu 
99122a59be8SPhilip Prindeville 	err = ipgre_netlink_parms(dev, data, tb, &p);
99222a59be8SPhilip Prindeville 	if (err < 0)
99322a59be8SPhilip Prindeville 		return err;
994c5441932SPravin B Shelar 	return ip_tunnel_changelink(dev, tb, &p);
995c19e654dSHerbert Xu }
996c19e654dSHerbert Xu 
997c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev)
998c19e654dSHerbert Xu {
999c19e654dSHerbert Xu 	return
1000c19e654dSHerbert Xu 		/* IFLA_GRE_LINK */
1001c19e654dSHerbert Xu 		nla_total_size(4) +
1002c19e654dSHerbert Xu 		/* IFLA_GRE_IFLAGS */
1003c19e654dSHerbert Xu 		nla_total_size(2) +
1004c19e654dSHerbert Xu 		/* IFLA_GRE_OFLAGS */
1005c19e654dSHerbert Xu 		nla_total_size(2) +
1006c19e654dSHerbert Xu 		/* IFLA_GRE_IKEY */
1007c19e654dSHerbert Xu 		nla_total_size(4) +
1008c19e654dSHerbert Xu 		/* IFLA_GRE_OKEY */
1009c19e654dSHerbert Xu 		nla_total_size(4) +
1010c19e654dSHerbert Xu 		/* IFLA_GRE_LOCAL */
1011c19e654dSHerbert Xu 		nla_total_size(4) +
1012c19e654dSHerbert Xu 		/* IFLA_GRE_REMOTE */
1013c19e654dSHerbert Xu 		nla_total_size(4) +
1014c19e654dSHerbert Xu 		/* IFLA_GRE_TTL */
1015c19e654dSHerbert Xu 		nla_total_size(1) +
1016c19e654dSHerbert Xu 		/* IFLA_GRE_TOS */
1017c19e654dSHerbert Xu 		nla_total_size(1) +
1018c19e654dSHerbert Xu 		/* IFLA_GRE_PMTUDISC */
1019c19e654dSHerbert Xu 		nla_total_size(1) +
10204565e991STom Herbert 		/* IFLA_GRE_ENCAP_TYPE */
10214565e991STom Herbert 		nla_total_size(2) +
10224565e991STom Herbert 		/* IFLA_GRE_ENCAP_FLAGS */
10234565e991STom Herbert 		nla_total_size(2) +
10244565e991STom Herbert 		/* IFLA_GRE_ENCAP_SPORT */
10254565e991STom Herbert 		nla_total_size(2) +
10264565e991STom Herbert 		/* IFLA_GRE_ENCAP_DPORT */
10274565e991STom Herbert 		nla_total_size(2) +
10282e15ea39SPravin B Shelar 		/* IFLA_GRE_COLLECT_METADATA */
10292e15ea39SPravin B Shelar 		nla_total_size(0) +
103022a59be8SPhilip Prindeville 		/* IFLA_GRE_IGNORE_DF */
103122a59be8SPhilip Prindeville 		nla_total_size(1) +
1032c19e654dSHerbert Xu 		0;
1033c19e654dSHerbert Xu }
1034c19e654dSHerbert Xu 
1035c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1036c19e654dSHerbert Xu {
1037c19e654dSHerbert Xu 	struct ip_tunnel *t = netdev_priv(dev);
1038c19e654dSHerbert Xu 	struct ip_tunnel_parm *p = &t->parms;
1039c19e654dSHerbert Xu 
1040f3756b79SDavid S. Miller 	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
104195f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_IFLAGS,
104295f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
104395f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_OFLAGS,
104495f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->o_flags)) ||
1045f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1046f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
1047930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1048930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
1049f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1050f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1051f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
1052f3756b79SDavid S. Miller 		       !!(p->iph.frag_off & htons(IP_DF))))
1053f3756b79SDavid S. Miller 		goto nla_put_failure;
10544565e991STom Herbert 
10554565e991STom Herbert 	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
10564565e991STom Herbert 			t->encap.type) ||
10573e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
10584565e991STom Herbert 			 t->encap.sport) ||
10593e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
10604565e991STom Herbert 			 t->encap.dport) ||
10614565e991STom Herbert 	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
1062e1b2cb65STom Herbert 			t->encap.flags))
10634565e991STom Herbert 		goto nla_put_failure;
10644565e991STom Herbert 
106522a59be8SPhilip Prindeville 	if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
106622a59be8SPhilip Prindeville 		goto nla_put_failure;
106722a59be8SPhilip Prindeville 
10682e15ea39SPravin B Shelar 	if (t->collect_md) {
10692e15ea39SPravin B Shelar 		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
10702e15ea39SPravin B Shelar 			goto nla_put_failure;
10712e15ea39SPravin B Shelar 	}
10722e15ea39SPravin B Shelar 
1073c19e654dSHerbert Xu 	return 0;
1074c19e654dSHerbert Xu 
1075c19e654dSHerbert Xu nla_put_failure:
1076c19e654dSHerbert Xu 	return -EMSGSIZE;
1077c19e654dSHerbert Xu }
1078c19e654dSHerbert Xu 
1079c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1080c19e654dSHerbert Xu 	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
1081c19e654dSHerbert Xu 	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
1082c19e654dSHerbert Xu 	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
1083c19e654dSHerbert Xu 	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
1084c19e654dSHerbert Xu 	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
10854d74f8baSPatrick McHardy 	[IFLA_GRE_LOCAL]	= { .len = FIELD_SIZEOF(struct iphdr, saddr) },
10864d74f8baSPatrick McHardy 	[IFLA_GRE_REMOTE]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
1087c19e654dSHerbert Xu 	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
1088c19e654dSHerbert Xu 	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
1089c19e654dSHerbert Xu 	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
10904565e991STom Herbert 	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
10914565e991STom Herbert 	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
10924565e991STom Herbert 	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
10934565e991STom Herbert 	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
10942e15ea39SPravin B Shelar 	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
109522a59be8SPhilip Prindeville 	[IFLA_GRE_IGNORE_DF]	= { .type = NLA_U8 },
1096c19e654dSHerbert Xu };
1097c19e654dSHerbert Xu 
1098c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1099c19e654dSHerbert Xu 	.kind		= "gre",
1100c19e654dSHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1101c19e654dSHerbert Xu 	.policy		= ipgre_policy,
1102c19e654dSHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1103c19e654dSHerbert Xu 	.setup		= ipgre_tunnel_setup,
1104c19e654dSHerbert Xu 	.validate	= ipgre_tunnel_validate,
1105c19e654dSHerbert Xu 	.newlink	= ipgre_newlink,
1106c19e654dSHerbert Xu 	.changelink	= ipgre_changelink,
1107c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1108c19e654dSHerbert Xu 	.get_size	= ipgre_get_size,
1109c19e654dSHerbert Xu 	.fill_info	= ipgre_fill_info,
11101728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1111c19e654dSHerbert Xu };
1112c19e654dSHerbert Xu 
1113e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1114e1a80002SHerbert Xu 	.kind		= "gretap",
1115e1a80002SHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1116e1a80002SHerbert Xu 	.policy		= ipgre_policy,
1117e1a80002SHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1118e1a80002SHerbert Xu 	.setup		= ipgre_tap_setup,
1119e1a80002SHerbert Xu 	.validate	= ipgre_tap_validate,
1120e1a80002SHerbert Xu 	.newlink	= ipgre_newlink,
1121e1a80002SHerbert Xu 	.changelink	= ipgre_changelink,
1122c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1123e1a80002SHerbert Xu 	.get_size	= ipgre_get_size,
1124e1a80002SHerbert Xu 	.fill_info	= ipgre_fill_info,
11251728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1126e1a80002SHerbert Xu };
1127e1a80002SHerbert Xu 
1128b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1129b2acd1dcSPravin B Shelar 					u8 name_assign_type)
1130b2acd1dcSPravin B Shelar {
1131b2acd1dcSPravin B Shelar 	struct nlattr *tb[IFLA_MAX + 1];
1132b2acd1dcSPravin B Shelar 	struct net_device *dev;
1133106da663SNicolas Dichtel 	LIST_HEAD(list_kill);
1134b2acd1dcSPravin B Shelar 	struct ip_tunnel *t;
1135b2acd1dcSPravin B Shelar 	int err;
1136b2acd1dcSPravin B Shelar 
1137b2acd1dcSPravin B Shelar 	memset(&tb, 0, sizeof(tb));
1138b2acd1dcSPravin B Shelar 
1139b2acd1dcSPravin B Shelar 	dev = rtnl_create_link(net, name, name_assign_type,
1140b2acd1dcSPravin B Shelar 			       &ipgre_tap_ops, tb);
1141b2acd1dcSPravin B Shelar 	if (IS_ERR(dev))
1142b2acd1dcSPravin B Shelar 		return dev;
1143b2acd1dcSPravin B Shelar 
1144b2acd1dcSPravin B Shelar 	/* Configure flow based GRE device. */
1145b2acd1dcSPravin B Shelar 	t = netdev_priv(dev);
1146b2acd1dcSPravin B Shelar 	t->collect_md = true;
1147b2acd1dcSPravin B Shelar 
1148b2acd1dcSPravin B Shelar 	err = ipgre_newlink(net, dev, tb, NULL);
1149106da663SNicolas Dichtel 	if (err < 0) {
1150106da663SNicolas Dichtel 		free_netdev(dev);
1151106da663SNicolas Dichtel 		return ERR_PTR(err);
1152106da663SNicolas Dichtel 	}
11537e059158SDavid Wragg 
11547e059158SDavid Wragg 	/* openvswitch users expect packet sizes to be unrestricted,
11557e059158SDavid Wragg 	 * so set the largest MTU we can.
11567e059158SDavid Wragg 	 */
11577e059158SDavid Wragg 	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
11587e059158SDavid Wragg 	if (err)
11597e059158SDavid Wragg 		goto out;
11607e059158SDavid Wragg 
1161da6f1da8SNicolas Dichtel 	err = rtnl_configure_link(dev, NULL);
1162da6f1da8SNicolas Dichtel 	if (err < 0)
1163da6f1da8SNicolas Dichtel 		goto out;
1164da6f1da8SNicolas Dichtel 
1165b2acd1dcSPravin B Shelar 	return dev;
1166b2acd1dcSPravin B Shelar out:
1167106da663SNicolas Dichtel 	ip_tunnel_dellink(dev, &list_kill);
1168106da663SNicolas Dichtel 	unregister_netdevice_many(&list_kill);
1169b2acd1dcSPravin B Shelar 	return ERR_PTR(err);
1170b2acd1dcSPravin B Shelar }
1171b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1172b2acd1dcSPravin B Shelar 
1173c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net)
1174c5441932SPravin B Shelar {
11752e15ea39SPravin B Shelar 	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
1176c5441932SPravin B Shelar }
1177c5441932SPravin B Shelar 
1178c5441932SPravin B Shelar static void __net_exit ipgre_tap_exit_net(struct net *net)
1179c5441932SPravin B Shelar {
1180c5441932SPravin B Shelar 	struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id);
11816c742e71SNicolas Dichtel 	ip_tunnel_delete_net(itn, &ipgre_tap_ops);
1182c5441932SPravin B Shelar }
1183c5441932SPravin B Shelar 
1184c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = {
1185c5441932SPravin B Shelar 	.init = ipgre_tap_init_net,
1186c5441932SPravin B Shelar 	.exit = ipgre_tap_exit_net,
1187c5441932SPravin B Shelar 	.id   = &gre_tap_net_id,
1188c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
1189c5441932SPravin B Shelar };
11901da177e4SLinus Torvalds 
11911da177e4SLinus Torvalds static int __init ipgre_init(void)
11921da177e4SLinus Torvalds {
11931da177e4SLinus Torvalds 	int err;
11941da177e4SLinus Torvalds 
1195058bd4d2SJoe Perches 	pr_info("GRE over IPv4 tunneling driver\n");
11961da177e4SLinus Torvalds 
1197cfb8fbf2SEric W. Biederman 	err = register_pernet_device(&ipgre_net_ops);
119859a4c759SPavel Emelyanov 	if (err < 0)
1199c2892f02SAlexey Dobriyan 		return err;
1200c2892f02SAlexey Dobriyan 
1201c5441932SPravin B Shelar 	err = register_pernet_device(&ipgre_tap_net_ops);
1202c5441932SPravin B Shelar 	if (err < 0)
1203c5441932SPravin B Shelar 		goto pnet_tap_faied;
1204c5441932SPravin B Shelar 
12059f57c67cSPravin B Shelar 	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
1206c2892f02SAlexey Dobriyan 	if (err < 0) {
1207058bd4d2SJoe Perches 		pr_info("%s: can't add protocol\n", __func__);
1208c2892f02SAlexey Dobriyan 		goto add_proto_failed;
1209c2892f02SAlexey Dobriyan 	}
12107daa0004SPavel Emelyanov 
1211c19e654dSHerbert Xu 	err = rtnl_link_register(&ipgre_link_ops);
1212c19e654dSHerbert Xu 	if (err < 0)
1213c19e654dSHerbert Xu 		goto rtnl_link_failed;
1214c19e654dSHerbert Xu 
1215e1a80002SHerbert Xu 	err = rtnl_link_register(&ipgre_tap_ops);
1216e1a80002SHerbert Xu 	if (err < 0)
1217e1a80002SHerbert Xu 		goto tap_ops_failed;
1218e1a80002SHerbert Xu 
1219c5441932SPravin B Shelar 	return 0;
1220c19e654dSHerbert Xu 
1221e1a80002SHerbert Xu tap_ops_failed:
1222e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
1223c19e654dSHerbert Xu rtnl_link_failed:
12249f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1225c2892f02SAlexey Dobriyan add_proto_failed:
1226c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1227c5441932SPravin B Shelar pnet_tap_faied:
1228c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
1229c5441932SPravin B Shelar 	return err;
12301da177e4SLinus Torvalds }
12311da177e4SLinus Torvalds 
1232db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void)
12331da177e4SLinus Torvalds {
1234e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_tap_ops);
1235c19e654dSHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
12369f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1237c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1238c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
12391da177e4SLinus Torvalds }
12401da177e4SLinus Torvalds 
12411da177e4SLinus Torvalds module_init(ipgre_init);
12421da177e4SLinus Torvalds module_exit(ipgre_fini);
12431da177e4SLinus Torvalds MODULE_LICENSE("GPL");
12444d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre");
12454d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap");
12468909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0");
1247c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0");
1248