xref: /linux/net/ipv4/ip_gre.c (revision 862a03c35ed76c50a562f7406ad23315f7862642)
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>
207c0f6ba6SLinus 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>
5184e54fe0SWilliam Tu #include <net/erspan.h>
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds /*
541da177e4SLinus Torvalds    Problems & solutions
551da177e4SLinus Torvalds    --------------------
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds    1. The most important issue is detecting local dead loops.
581da177e4SLinus Torvalds    They would cause complete host lockup in transmit, which
591da177e4SLinus Torvalds    would be "resolved" by stack overflow or, if queueing is enabled,
601da177e4SLinus Torvalds    with infinite looping in net_bh.
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds    We cannot track such dead loops during route installation,
631da177e4SLinus Torvalds    it is infeasible task. The most general solutions would be
641da177e4SLinus Torvalds    to keep skb->encapsulation counter (sort of local ttl),
656d0722a2SEric Dumazet    and silently drop packet when it expires. It is a good
66bff52857Sstephen hemminger    solution, but it supposes maintaining new variable in ALL
671da177e4SLinus Torvalds    skb, even if no tunneling is used.
681da177e4SLinus Torvalds 
696d0722a2SEric Dumazet    Current solution: xmit_recursion breaks dead loops. This is a percpu
706d0722a2SEric Dumazet    counter, since when we enter the first ndo_xmit(), cpu migration is
716d0722a2SEric Dumazet    forbidden. We force an exit if this counter reaches RECURSION_LIMIT
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds    2. Networking dead loops would not kill routers, but would really
741da177e4SLinus Torvalds    kill network. IP hop limit plays role of "t->recursion" in this case,
751da177e4SLinus Torvalds    if we copy it from packet being encapsulated to upper header.
761da177e4SLinus Torvalds    It is very good solution, but it introduces two problems:
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds    - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
791da177e4SLinus Torvalds      do not work over tunnels.
801da177e4SLinus Torvalds    - traceroute does not work. I planned to relay ICMP from tunnel,
811da177e4SLinus Torvalds      so that this problem would be solved and traceroute output
821da177e4SLinus Torvalds      would even more informative. This idea appeared to be wrong:
831da177e4SLinus Torvalds      only Linux complies to rfc1812 now (yes, guys, Linux is the only
841da177e4SLinus Torvalds      true router now :-)), all routers (at least, in neighbourhood of mine)
851da177e4SLinus Torvalds      return only 8 bytes of payload. It is the end.
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds    Hence, if we want that OSPF worked or traceroute said something reasonable,
881da177e4SLinus Torvalds    we should search for another solution.
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds    One of them is to parse packet trying to detect inner encapsulation
911da177e4SLinus Torvalds    made by our node. It is difficult or even impossible, especially,
92bff52857Sstephen hemminger    taking into account fragmentation. TO be short, ttl is not solution at all.
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds    Current solution: The solution was UNEXPECTEDLY SIMPLE.
951da177e4SLinus Torvalds    We force DF flag on tunnels with preconfigured hop limit,
961da177e4SLinus Torvalds    that is ALL. :-) Well, it does not remove the problem completely,
971da177e4SLinus Torvalds    but exponential growth of network traffic is changed to linear
981da177e4SLinus Torvalds    (branches, that exceed pmtu are pruned) and tunnel mtu
99bff52857Sstephen hemminger    rapidly degrades to value <68, where looping stops.
1001da177e4SLinus Torvalds    Yes, it is not good if there exists a router in the loop,
1011da177e4SLinus Torvalds    which does not force DF, even when encapsulating packets have DF set.
1021da177e4SLinus Torvalds    But it is not our problem! Nobody could accuse us, we made
1031da177e4SLinus Torvalds    all that we could make. Even if it is your gated who injected
1041da177e4SLinus Torvalds    fatal route to network, even if it were you who configured
1051da177e4SLinus Torvalds    fatal static route: you are innocent. :-)
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds    Alexey Kuznetsov.
1081da177e4SLinus Torvalds  */
1091da177e4SLinus Torvalds 
110eccc1bb8Sstephen hemminger static bool log_ecn_error = true;
111eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644);
112eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
113eccc1bb8Sstephen hemminger 
114c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly;
1151da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev);
116eb8ce741SPavel Emelyanov 
117c7d03a00SAlexey Dobriyan static unsigned int ipgre_net_id __read_mostly;
118c7d03a00SAlexey Dobriyan static unsigned int gre_tap_net_id __read_mostly;
11984e54fe0SWilliam Tu static unsigned int erspan_net_id __read_mostly;
120eb8ce741SPavel Emelyanov 
1219f57c67cSPravin B Shelar static void ipgre_err(struct sk_buff *skb, u32 info,
122bda7bb46SPravin B Shelar 		      const struct tnl_ptk_info *tpi)
1231da177e4SLinus Torvalds {
1241da177e4SLinus Torvalds 
125071f92d0SRami Rosen 	/* All the routers (except for Linux) return only
1261da177e4SLinus Torvalds 	   8 bytes of packet payload. It means, that precise relaying of
1271da177e4SLinus Torvalds 	   ICMP in the real Internet is absolutely infeasible.
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds 	   Moreover, Cisco "wise men" put GRE key to the third word
130c5441932SPravin B Shelar 	   in GRE header. It makes impossible maintaining even soft
131c5441932SPravin B Shelar 	   state for keyed GRE tunnels with enabled checksum. Tell
132c5441932SPravin B Shelar 	   them "thank you".
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds 	   Well, I wonder, rfc1812 was written by Cisco employee,
135bff52857Sstephen hemminger 	   what the hell these idiots break standards established
136bff52857Sstephen hemminger 	   by themselves???
1371da177e4SLinus Torvalds 	   */
138c5441932SPravin B Shelar 	struct net *net = dev_net(skb->dev);
139c5441932SPravin B Shelar 	struct ip_tunnel_net *itn;
14096f5a846SEric Dumazet 	const struct iphdr *iph;
14188c7664fSArnaldo Carvalho de Melo 	const int type = icmp_hdr(skb)->type;
14288c7664fSArnaldo Carvalho de Melo 	const int code = icmp_hdr(skb)->code;
14320e1954fSEric Dumazet 	unsigned int data_len = 0;
1441da177e4SLinus Torvalds 	struct ip_tunnel *t;
145d2083287Sstephen hemminger 
1461da177e4SLinus Torvalds 	switch (type) {
1471da177e4SLinus Torvalds 	default:
1481da177e4SLinus Torvalds 	case ICMP_PARAMETERPROB:
1499f57c67cSPravin B Shelar 		return;
1501da177e4SLinus Torvalds 
1511da177e4SLinus Torvalds 	case ICMP_DEST_UNREACH:
1521da177e4SLinus Torvalds 		switch (code) {
1531da177e4SLinus Torvalds 		case ICMP_SR_FAILED:
1541da177e4SLinus Torvalds 		case ICMP_PORT_UNREACH:
1551da177e4SLinus Torvalds 			/* Impossible event. */
1569f57c67cSPravin B Shelar 			return;
1571da177e4SLinus Torvalds 		default:
1581da177e4SLinus Torvalds 			/* All others are translated to HOST_UNREACH.
1591da177e4SLinus Torvalds 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
1601da177e4SLinus Torvalds 			   I believe they are just ether pollution. --ANK
1611da177e4SLinus Torvalds 			 */
1621da177e4SLinus Torvalds 			break;
1631da177e4SLinus Torvalds 		}
1641da177e4SLinus Torvalds 		break;
1659f57c67cSPravin B Shelar 
1661da177e4SLinus Torvalds 	case ICMP_TIME_EXCEEDED:
1671da177e4SLinus Torvalds 		if (code != ICMP_EXC_TTL)
1689f57c67cSPravin B Shelar 			return;
16920e1954fSEric Dumazet 		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
1701da177e4SLinus Torvalds 		break;
17155be7a9cSDavid S. Miller 
17255be7a9cSDavid S. Miller 	case ICMP_REDIRECT:
17355be7a9cSDavid S. Miller 		break;
1741da177e4SLinus Torvalds 	}
1751da177e4SLinus Torvalds 
176bda7bb46SPravin B Shelar 	if (tpi->proto == htons(ETH_P_TEB))
177c5441932SPravin B Shelar 		itn = net_generic(net, gre_tap_net_id);
178c5441932SPravin B Shelar 	else
179c5441932SPravin B Shelar 		itn = net_generic(net, ipgre_net_id);
180c5441932SPravin B Shelar 
181c0c0c50fSDuan Jiong 	iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
182bda7bb46SPravin B Shelar 	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
183bda7bb46SPravin B Shelar 			     iph->daddr, iph->saddr, tpi->key);
184d2083287Sstephen hemminger 
18551456b29SIan Morris 	if (!t)
1869f57c67cSPravin B Shelar 		return;
18736393395SDavid S. Miller 
1889b8c6d7bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1899b8c6d7bSEric Dumazet        if (tpi->proto == htons(ETH_P_IPV6) &&
19020e1954fSEric Dumazet            !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
19120e1954fSEric Dumazet 				       type, data_len))
1929b8c6d7bSEric Dumazet                return;
1939b8c6d7bSEric Dumazet #endif
1949b8c6d7bSEric Dumazet 
19536393395SDavid S. Miller 	if (t->parms.iph.daddr == 0 ||
196f97c1e0cSJoe Perches 	    ipv4_is_multicast(t->parms.iph.daddr))
1979f57c67cSPravin B Shelar 		return;
1981da177e4SLinus Torvalds 
1991da177e4SLinus Torvalds 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
2009f57c67cSPravin B Shelar 		return;
2011da177e4SLinus Torvalds 
202da6185d8SWei Yongjun 	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
2031da177e4SLinus Torvalds 		t->err_count++;
2041da177e4SLinus Torvalds 	else
2051da177e4SLinus Torvalds 		t->err_count = 1;
2061da177e4SLinus Torvalds 	t->err_time = jiffies;
2079f57c67cSPravin B Shelar }
2089f57c67cSPravin B Shelar 
2099f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info)
2109f57c67cSPravin B Shelar {
2119f57c67cSPravin B Shelar 	/* All the routers (except for Linux) return only
2129f57c67cSPravin B Shelar 	 * 8 bytes of packet payload. It means, that precise relaying of
2139f57c67cSPravin B Shelar 	 * ICMP in the real Internet is absolutely infeasible.
2149f57c67cSPravin B Shelar 	 *
2159f57c67cSPravin B Shelar 	 * Moreover, Cisco "wise men" put GRE key to the third word
2169f57c67cSPravin B Shelar 	 * in GRE header. It makes impossible maintaining even soft
2179f57c67cSPravin B Shelar 	 * state for keyed
2189f57c67cSPravin B Shelar 	 * GRE tunnels with enabled checksum. Tell them "thank you".
2199f57c67cSPravin B Shelar 	 *
2209f57c67cSPravin B Shelar 	 * Well, I wonder, rfc1812 was written by Cisco employee,
2219f57c67cSPravin B Shelar 	 * what the hell these idiots break standards established
2229f57c67cSPravin B Shelar 	 * by themselves???
2239f57c67cSPravin B Shelar 	 */
2249f57c67cSPravin B Shelar 
225e582615aSEric Dumazet 	const struct iphdr *iph = (struct iphdr *)skb->data;
2269f57c67cSPravin B Shelar 	const int type = icmp_hdr(skb)->type;
2279f57c67cSPravin B Shelar 	const int code = icmp_hdr(skb)->code;
2289f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
2299f57c67cSPravin B Shelar 	bool csum_err = false;
2309f57c67cSPravin B Shelar 
231e582615aSEric Dumazet 	if (gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP),
232e582615aSEric Dumazet 			     iph->ihl * 4) < 0) {
2339f57c67cSPravin B Shelar 		if (!csum_err)		/* ignore csum errors. */
2349f57c67cSPravin B Shelar 			return;
2359f57c67cSPravin B Shelar 	}
2369f57c67cSPravin B Shelar 
2379f57c67cSPravin B Shelar 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
2389f57c67cSPravin B Shelar 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
2399f57c67cSPravin B Shelar 				 skb->dev->ifindex, 0, IPPROTO_GRE, 0);
2409f57c67cSPravin B Shelar 		return;
2419f57c67cSPravin B Shelar 	}
2429f57c67cSPravin B Shelar 	if (type == ICMP_REDIRECT) {
2439f57c67cSPravin B Shelar 		ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0,
2449f57c67cSPravin B Shelar 			      IPPROTO_GRE, 0);
2459f57c67cSPravin B Shelar 		return;
2469f57c67cSPravin B Shelar 	}
2479f57c67cSPravin B Shelar 
2489f57c67cSPravin B Shelar 	ipgre_err(skb, info, &tpi);
2491da177e4SLinus Torvalds }
2501da177e4SLinus Torvalds 
25184e54fe0SWilliam Tu static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
25284e54fe0SWilliam Tu 		      int gre_hdr_len)
25384e54fe0SWilliam Tu {
25484e54fe0SWilliam Tu 	struct net *net = dev_net(skb->dev);
25584e54fe0SWilliam Tu 	struct metadata_dst *tun_dst = NULL;
25684e54fe0SWilliam Tu 	struct ip_tunnel_net *itn;
25784e54fe0SWilliam Tu 	struct ip_tunnel *tunnel;
25884e54fe0SWilliam Tu 	struct erspanhdr *ershdr;
25984e54fe0SWilliam Tu 	const struct iphdr *iph;
26084e54fe0SWilliam Tu 	__be32 session_id;
26184e54fe0SWilliam Tu 	__be32 index;
26284e54fe0SWilliam Tu 	int len;
26384e54fe0SWilliam Tu 
26484e54fe0SWilliam Tu 	itn = net_generic(net, erspan_net_id);
26584e54fe0SWilliam Tu 	len = gre_hdr_len + sizeof(*ershdr);
26684e54fe0SWilliam Tu 
26784e54fe0SWilliam Tu 	if (unlikely(!pskb_may_pull(skb, len)))
26884e54fe0SWilliam Tu 		return -ENOMEM;
26984e54fe0SWilliam Tu 
27084e54fe0SWilliam Tu 	iph = ip_hdr(skb);
27184e54fe0SWilliam Tu 	ershdr = (struct erspanhdr *)(skb->data + gre_hdr_len);
27284e54fe0SWilliam Tu 
27384e54fe0SWilliam Tu 	/* The original GRE header does not have key field,
27484e54fe0SWilliam Tu 	 * Use ERSPAN 10-bit session ID as key.
27584e54fe0SWilliam Tu 	 */
27684e54fe0SWilliam Tu 	session_id = cpu_to_be32(ntohs(ershdr->session_id));
27784e54fe0SWilliam Tu 	tpi->key = session_id;
27884e54fe0SWilliam Tu 	index = ershdr->md.index;
27984e54fe0SWilliam Tu 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
28084e54fe0SWilliam Tu 				  tpi->flags | TUNNEL_KEY,
28184e54fe0SWilliam Tu 				  iph->saddr, iph->daddr, tpi->key);
28284e54fe0SWilliam Tu 
28384e54fe0SWilliam Tu 	if (tunnel) {
28484e54fe0SWilliam Tu 		if (__iptunnel_pull_header(skb,
28584e54fe0SWilliam Tu 					   gre_hdr_len + sizeof(*ershdr),
28684e54fe0SWilliam Tu 					   htons(ETH_P_TEB),
28784e54fe0SWilliam Tu 					   false, false) < 0)
28884e54fe0SWilliam Tu 			goto drop;
28984e54fe0SWilliam Tu 
29084e54fe0SWilliam Tu 		tunnel->index = ntohl(index);
29184e54fe0SWilliam Tu 		skb_reset_mac_header(skb);
29284e54fe0SWilliam Tu 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
29384e54fe0SWilliam Tu 		return PACKET_RCVD;
29484e54fe0SWilliam Tu 	}
29584e54fe0SWilliam Tu drop:
29684e54fe0SWilliam Tu 	kfree_skb(skb);
29784e54fe0SWilliam Tu 	return PACKET_RCVD;
29884e54fe0SWilliam Tu }
29984e54fe0SWilliam Tu 
300125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
301125372faSJiri Benc 		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
3021da177e4SLinus Torvalds {
3032e15ea39SPravin B Shelar 	struct metadata_dst *tun_dst = NULL;
304b71d1d42SEric Dumazet 	const struct iphdr *iph;
3051da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
3061da177e4SLinus Torvalds 
307eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
308bda7bb46SPravin B Shelar 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
309bda7bb46SPravin B Shelar 				  iph->saddr, iph->daddr, tpi->key);
3101da177e4SLinus Torvalds 
311d2083287Sstephen hemminger 	if (tunnel) {
312125372faSJiri Benc 		if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
313125372faSJiri Benc 					   raw_proto, false) < 0)
314244a797bSJiri Benc 			goto drop;
315244a797bSJiri Benc 
316e271c7b4SJiri Benc 		if (tunnel->dev->type != ARPHRD_NONE)
3170e3da5bbSTimo Teräs 			skb_pop_mac_header(skb);
318e271c7b4SJiri Benc 		else
319e271c7b4SJiri Benc 			skb_reset_mac_header(skb);
3202e15ea39SPravin B Shelar 		if (tunnel->collect_md) {
321c29a70d2SPravin B Shelar 			__be16 flags;
322c29a70d2SPravin B Shelar 			__be64 tun_id;
3232e15ea39SPravin B Shelar 
324c29a70d2SPravin B Shelar 			flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
325d817f432SAmir Vadai 			tun_id = key32_to_tunnel_id(tpi->key);
326c29a70d2SPravin B Shelar 			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
3272e15ea39SPravin B Shelar 			if (!tun_dst)
3282e15ea39SPravin B Shelar 				return PACKET_REJECT;
3292e15ea39SPravin B Shelar 		}
3302e15ea39SPravin B Shelar 
3312e15ea39SPravin B Shelar 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
332bda7bb46SPravin B Shelar 		return PACKET_RCVD;
3331da177e4SLinus Torvalds 	}
334125372faSJiri Benc 	return PACKET_NEXT;
335244a797bSJiri Benc 
336244a797bSJiri Benc drop:
337244a797bSJiri Benc 	kfree_skb(skb);
338244a797bSJiri Benc 	return PACKET_RCVD;
3391da177e4SLinus Torvalds }
3401da177e4SLinus Torvalds 
341125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
342125372faSJiri Benc 		     int hdr_len)
343125372faSJiri Benc {
344125372faSJiri Benc 	struct net *net = dev_net(skb->dev);
345125372faSJiri Benc 	struct ip_tunnel_net *itn;
346125372faSJiri Benc 	int res;
347125372faSJiri Benc 
348125372faSJiri Benc 	if (tpi->proto == htons(ETH_P_TEB))
349125372faSJiri Benc 		itn = net_generic(net, gre_tap_net_id);
350125372faSJiri Benc 	else
351125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
352125372faSJiri Benc 
353125372faSJiri Benc 	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
354125372faSJiri Benc 	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
355125372faSJiri Benc 		/* ipgre tunnels in collect metadata mode should receive
356125372faSJiri Benc 		 * also ETH_P_TEB traffic.
357125372faSJiri Benc 		 */
358125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
359125372faSJiri Benc 		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
360125372faSJiri Benc 	}
361125372faSJiri Benc 	return res;
362125372faSJiri Benc }
363125372faSJiri Benc 
3649f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb)
3659f57c67cSPravin B Shelar {
3669f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
3679f57c67cSPravin B Shelar 	bool csum_err = false;
36895f5c64cSTom Herbert 	int hdr_len;
3699f57c67cSPravin B Shelar 
3709f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST
3719f57c67cSPravin B Shelar 	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
3729f57c67cSPravin B Shelar 		/* Looped back packet, drop it! */
3739f57c67cSPravin B Shelar 		if (rt_is_output_route(skb_rtable(skb)))
3749f57c67cSPravin B Shelar 			goto drop;
3759f57c67cSPravin B Shelar 	}
3769f57c67cSPravin B Shelar #endif
3779f57c67cSPravin B Shelar 
378e582615aSEric Dumazet 	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
379f132ae7cSJiri Benc 	if (hdr_len < 0)
38095f5c64cSTom Herbert 		goto drop;
38195f5c64cSTom Herbert 
38284e54fe0SWilliam Tu 	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) {
38384e54fe0SWilliam Tu 		if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
38484e54fe0SWilliam Tu 			return 0;
38584e54fe0SWilliam Tu 	}
38684e54fe0SWilliam Tu 
387244a797bSJiri Benc 	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
3889f57c67cSPravin B Shelar 		return 0;
3899f57c67cSPravin B Shelar 
3909f57c67cSPravin B Shelar 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
3919f57c67cSPravin B Shelar drop:
3929f57c67cSPravin B Shelar 	kfree_skb(skb);
3939f57c67cSPravin B Shelar 	return 0;
3949f57c67cSPravin B Shelar }
3959f57c67cSPravin B Shelar 
396c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
397c5441932SPravin B Shelar 		       const struct iphdr *tnl_params,
398c5441932SPravin B Shelar 		       __be16 proto)
399c5441932SPravin B Shelar {
400c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
401c5441932SPravin B Shelar 
402c5441932SPravin B Shelar 	if (tunnel->parms.o_flags & TUNNEL_SEQ)
403c5441932SPravin B Shelar 		tunnel->o_seqno++;
404cef401deSEric Dumazet 
405c5441932SPravin B Shelar 	/* Push GRE header. */
406182a352dSTom Herbert 	gre_build_header(skb, tunnel->tun_hlen,
407182a352dSTom Herbert 			 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
408182a352dSTom Herbert 			 htonl(tunnel->o_seqno));
4091da177e4SLinus Torvalds 
410bf3d6a8fSNicolas Dichtel 	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
4111da177e4SLinus Torvalds }
4121da177e4SLinus Torvalds 
413aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum)
414b2acd1dcSPravin B Shelar {
4156fa79666SEdward Cree 	return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
416b2acd1dcSPravin B Shelar }
417b2acd1dcSPravin B Shelar 
418fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb,
419fc4099f1SPravin B Shelar 				 struct net_device *dev,
420fc4099f1SPravin B Shelar 				 struct flowi4 *fl,
421fc4099f1SPravin B Shelar 				 const struct ip_tunnel_key *key)
422fc4099f1SPravin B Shelar {
423fc4099f1SPravin B Shelar 	struct net *net = dev_net(dev);
424fc4099f1SPravin B Shelar 
425fc4099f1SPravin B Shelar 	memset(fl, 0, sizeof(*fl));
426fc4099f1SPravin B Shelar 	fl->daddr = key->u.ipv4.dst;
427fc4099f1SPravin B Shelar 	fl->saddr = key->u.ipv4.src;
428fc4099f1SPravin B Shelar 	fl->flowi4_tos = RT_TOS(key->tos);
429fc4099f1SPravin B Shelar 	fl->flowi4_mark = skb->mark;
430fc4099f1SPravin B Shelar 	fl->flowi4_proto = IPPROTO_GRE;
431fc4099f1SPravin B Shelar 
432fc4099f1SPravin B Shelar 	return ip_route_output_key(net, fl);
433fc4099f1SPravin B Shelar }
434fc4099f1SPravin B Shelar 
435*862a03c3SWilliam Tu static struct rtable *prepare_fb_xmit(struct sk_buff *skb,
436*862a03c3SWilliam Tu 				      struct net_device *dev,
437*862a03c3SWilliam Tu 				      struct flowi4 *fl,
438*862a03c3SWilliam Tu 				      int tunnel_hlen)
4392e15ea39SPravin B Shelar {
4402e15ea39SPravin B Shelar 	struct ip_tunnel_info *tun_info;
4412e15ea39SPravin B Shelar 	const struct ip_tunnel_key *key;
442db3c6139SDaniel Borkmann 	struct rtable *rt = NULL;
4432e15ea39SPravin B Shelar 	int min_headroom;
444db3c6139SDaniel Borkmann 	bool use_cache;
4452e15ea39SPravin B Shelar 	int err;
4462e15ea39SPravin B Shelar 
44761adedf3SJiri Benc 	tun_info = skb_tunnel_info(skb);
4482e15ea39SPravin B Shelar 	key = &tun_info->key;
449db3c6139SDaniel Borkmann 	use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
450*862a03c3SWilliam Tu 
451db3c6139SDaniel Borkmann 	if (use_cache)
452*862a03c3SWilliam Tu 		rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl->saddr);
4533c1cb4d2SPaolo Abeni 	if (!rt) {
454*862a03c3SWilliam Tu 		rt = gre_get_rt(skb, dev, fl, key);
4552e15ea39SPravin B Shelar 		if (IS_ERR(rt))
4562e15ea39SPravin B Shelar 			goto err_free_skb;
457db3c6139SDaniel Borkmann 		if (use_cache)
4583c1cb4d2SPaolo Abeni 			dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
459*862a03c3SWilliam Tu 					  fl->saddr);
4603c1cb4d2SPaolo Abeni 	}
4612e15ea39SPravin B Shelar 
4622e15ea39SPravin B Shelar 	min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
4632e15ea39SPravin B Shelar 			+ tunnel_hlen + sizeof(struct iphdr);
4642e15ea39SPravin B Shelar 	if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
4652e15ea39SPravin B Shelar 		int head_delta = SKB_DATA_ALIGN(min_headroom -
4662e15ea39SPravin B Shelar 						skb_headroom(skb) +
4672e15ea39SPravin B Shelar 						16);
4682e15ea39SPravin B Shelar 		err = pskb_expand_head(skb, max_t(int, head_delta, 0),
4692e15ea39SPravin B Shelar 				       0, GFP_ATOMIC);
4702e15ea39SPravin B Shelar 		if (unlikely(err))
4712e15ea39SPravin B Shelar 			goto err_free_rt;
4722e15ea39SPravin B Shelar 	}
473*862a03c3SWilliam Tu 	return rt;
474*862a03c3SWilliam Tu 
475*862a03c3SWilliam Tu err_free_rt:
476*862a03c3SWilliam Tu 	ip_rt_put(rt);
477*862a03c3SWilliam Tu err_free_skb:
478*862a03c3SWilliam Tu 	kfree_skb(skb);
479*862a03c3SWilliam Tu 	dev->stats.tx_dropped++;
480*862a03c3SWilliam Tu 	return NULL;
481*862a03c3SWilliam Tu }
482*862a03c3SWilliam Tu 
483*862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
484*862a03c3SWilliam Tu 			__be16 proto)
485*862a03c3SWilliam Tu {
486*862a03c3SWilliam Tu 	struct ip_tunnel_info *tun_info;
487*862a03c3SWilliam Tu 	const struct ip_tunnel_key *key;
488*862a03c3SWilliam Tu 	struct rtable *rt = NULL;
489*862a03c3SWilliam Tu 	struct flowi4 fl;
490*862a03c3SWilliam Tu 	int tunnel_hlen;
491*862a03c3SWilliam Tu 	__be16 df, flags;
492*862a03c3SWilliam Tu 
493*862a03c3SWilliam Tu 	tun_info = skb_tunnel_info(skb);
494*862a03c3SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
495*862a03c3SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
496*862a03c3SWilliam Tu 		goto err_free_skb;
497*862a03c3SWilliam Tu 
498*862a03c3SWilliam Tu 	key = &tun_info->key;
499*862a03c3SWilliam Tu 	tunnel_hlen = gre_calc_hlen(key->tun_flags);
500*862a03c3SWilliam Tu 
501*862a03c3SWilliam Tu 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
502*862a03c3SWilliam Tu 	if (!rt)
503*862a03c3SWilliam Tu 		return;
5042e15ea39SPravin B Shelar 
5052e15ea39SPravin B Shelar 	/* Push Tunnel header. */
506aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
5072e15ea39SPravin B Shelar 		goto err_free_rt;
5082e15ea39SPravin B Shelar 
5092e15ea39SPravin B Shelar 	flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
510cba65321SDavid S. Miller 	gre_build_header(skb, tunnel_hlen, flags, proto,
511d817f432SAmir Vadai 			 tunnel_id_to_key32(tun_info->key.tun_id), 0);
5122e15ea39SPravin B Shelar 
5132e15ea39SPravin B Shelar 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
514039f5062SPravin B Shelar 
515039f5062SPravin B Shelar 	iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
5167c383fb2SJiri Benc 		      key->tos, key->ttl, df, false);
5172e15ea39SPravin B Shelar 	return;
5182e15ea39SPravin B Shelar 
5192e15ea39SPravin B Shelar err_free_rt:
5202e15ea39SPravin B Shelar 	ip_rt_put(rt);
5212e15ea39SPravin B Shelar err_free_skb:
5222e15ea39SPravin B Shelar 	kfree_skb(skb);
5232e15ea39SPravin B Shelar 	dev->stats.tx_dropped++;
5242e15ea39SPravin B Shelar }
5252e15ea39SPravin B Shelar 
526fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
527fc4099f1SPravin B Shelar {
528fc4099f1SPravin B Shelar 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
529fc4099f1SPravin B Shelar 	struct rtable *rt;
530fc4099f1SPravin B Shelar 	struct flowi4 fl4;
531fc4099f1SPravin B Shelar 
532fc4099f1SPravin B Shelar 	if (ip_tunnel_info_af(info) != AF_INET)
533fc4099f1SPravin B Shelar 		return -EINVAL;
534fc4099f1SPravin B Shelar 
535fc4099f1SPravin B Shelar 	rt = gre_get_rt(skb, dev, &fl4, &info->key);
536fc4099f1SPravin B Shelar 	if (IS_ERR(rt))
537fc4099f1SPravin B Shelar 		return PTR_ERR(rt);
538fc4099f1SPravin B Shelar 
539fc4099f1SPravin B Shelar 	ip_rt_put(rt);
540fc4099f1SPravin B Shelar 	info->key.u.ipv4.src = fl4.saddr;
541fc4099f1SPravin B Shelar 	return 0;
542fc4099f1SPravin B Shelar }
543fc4099f1SPravin B Shelar 
544c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
545c5441932SPravin B Shelar 			      struct net_device *dev)
546ee34c1ebSMichal Schmidt {
547c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
548c5441932SPravin B Shelar 	const struct iphdr *tnl_params;
549ee34c1ebSMichal Schmidt 
5502e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
5512090714eSJiri Benc 		gre_fb_xmit(skb, dev, skb->protocol);
5522e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
5532e15ea39SPravin B Shelar 	}
5542e15ea39SPravin B Shelar 
555c5441932SPravin B Shelar 	if (dev->header_ops) {
556c5441932SPravin B Shelar 		/* Need space for new headers */
557c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom -
5582bac7cb3SChen Gang 				      (tunnel->hlen + sizeof(struct iphdr))))
559c5441932SPravin B Shelar 			goto free_skb;
560ee34c1ebSMichal Schmidt 
561c5441932SPravin B Shelar 		tnl_params = (const struct iphdr *)skb->data;
562cbb1e85fSDavid S. Miller 
563c5441932SPravin B Shelar 		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
564c5441932SPravin B Shelar 		 * to gre header.
565c5441932SPravin B Shelar 		 */
566c5441932SPravin B Shelar 		skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
5678a0033a9STimo Teräs 		skb_reset_mac_header(skb);
568c5441932SPravin B Shelar 	} else {
569c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom))
570c5441932SPravin B Shelar 			goto free_skb;
571c5441932SPravin B Shelar 
572c5441932SPravin B Shelar 		tnl_params = &tunnel->parms.iph;
573ee34c1ebSMichal Schmidt 	}
574e1a80002SHerbert Xu 
575aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
576aed069dfSAlexander Duyck 		goto free_skb;
5778a0033a9STimo Teräs 
578c5441932SPravin B Shelar 	__gre_xmit(skb, dev, tnl_params, skb->protocol);
579c5441932SPravin B Shelar 	return NETDEV_TX_OK;
580c5441932SPravin B Shelar 
581c5441932SPravin B Shelar free_skb:
5823acfa1e7SEric Dumazet 	kfree_skb(skb);
583c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
584c5441932SPravin B Shelar 	return NETDEV_TX_OK;
585ee34c1ebSMichal Schmidt }
586ee34c1ebSMichal Schmidt 
58784e54fe0SWilliam Tu static inline u8 tos_to_cos(u8 tos)
58884e54fe0SWilliam Tu {
58984e54fe0SWilliam Tu 	u8 dscp, cos;
59084e54fe0SWilliam Tu 
59184e54fe0SWilliam Tu 	dscp = tos >> 2;
59284e54fe0SWilliam Tu 	cos = dscp >> 3;
59384e54fe0SWilliam Tu 	return cos;
59484e54fe0SWilliam Tu }
59584e54fe0SWilliam Tu 
59684e54fe0SWilliam Tu static void erspan_build_header(struct sk_buff *skb,
59784e54fe0SWilliam Tu 				__be32 id, u32 index, bool truncate)
59884e54fe0SWilliam Tu {
59984e54fe0SWilliam Tu 	struct iphdr *iphdr = ip_hdr(skb);
60084e54fe0SWilliam Tu 	struct ethhdr *eth = eth_hdr(skb);
60184e54fe0SWilliam Tu 	enum erspan_encap_type enc_type;
60284e54fe0SWilliam Tu 	struct erspanhdr *ershdr;
60384e54fe0SWilliam Tu 	struct qtag_prefix {
60484e54fe0SWilliam Tu 		__be16 eth_type;
60584e54fe0SWilliam Tu 		__be16 tci;
60684e54fe0SWilliam Tu 	} *qp;
60784e54fe0SWilliam Tu 	u16 vlan_tci = 0;
60884e54fe0SWilliam Tu 
60984e54fe0SWilliam Tu 	enc_type = ERSPAN_ENCAP_NOVLAN;
61084e54fe0SWilliam Tu 
61184e54fe0SWilliam Tu 	/* If mirrored packet has vlan tag, extract tci and
61284e54fe0SWilliam Tu 	 *  perserve vlan header in the mirrored frame.
61384e54fe0SWilliam Tu 	 */
61484e54fe0SWilliam Tu 	if (eth->h_proto == htons(ETH_P_8021Q)) {
61584e54fe0SWilliam Tu 		qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN);
61684e54fe0SWilliam Tu 		vlan_tci = ntohs(qp->tci);
61784e54fe0SWilliam Tu 		enc_type = ERSPAN_ENCAP_INFRAME;
61884e54fe0SWilliam Tu 	}
61984e54fe0SWilliam Tu 
62084e54fe0SWilliam Tu 	skb_push(skb, sizeof(*ershdr));
62184e54fe0SWilliam Tu 	ershdr = (struct erspanhdr *)skb->data;
62284e54fe0SWilliam Tu 	memset(ershdr, 0, sizeof(*ershdr));
62384e54fe0SWilliam Tu 
62484e54fe0SWilliam Tu 	ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) |
62584e54fe0SWilliam Tu 				 (ERSPAN_VERSION << VER_OFFSET));
62684e54fe0SWilliam Tu 	ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) |
62784e54fe0SWilliam Tu 			   ((tos_to_cos(iphdr->tos) << COS_OFFSET) & COS_MASK) |
62884e54fe0SWilliam Tu 			   (enc_type << EN_OFFSET & EN_MASK) |
62984e54fe0SWilliam Tu 			   ((truncate << T_OFFSET) & T_MASK));
63084e54fe0SWilliam Tu 	ershdr->md.index = htonl(index & INDEX_MASK);
63184e54fe0SWilliam Tu }
63284e54fe0SWilliam Tu 
63384e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb,
63484e54fe0SWilliam Tu 			       struct net_device *dev)
63584e54fe0SWilliam Tu {
63684e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
63784e54fe0SWilliam Tu 	bool truncate = false;
63884e54fe0SWilliam Tu 
63984e54fe0SWilliam Tu 	if (gre_handle_offloads(skb, false))
64084e54fe0SWilliam Tu 		goto free_skb;
64184e54fe0SWilliam Tu 
64284e54fe0SWilliam Tu 	if (skb_cow_head(skb, dev->needed_headroom))
64384e54fe0SWilliam Tu 		goto free_skb;
64484e54fe0SWilliam Tu 
64584e54fe0SWilliam Tu 	if (skb->len > dev->mtu) {
64684e54fe0SWilliam Tu 		pskb_trim(skb, dev->mtu);
64784e54fe0SWilliam Tu 		truncate = true;
64884e54fe0SWilliam Tu 	}
64984e54fe0SWilliam Tu 
65084e54fe0SWilliam Tu 	/* Push ERSPAN header */
65184e54fe0SWilliam Tu 	erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, truncate);
65284e54fe0SWilliam Tu 	tunnel->parms.o_flags &= ~TUNNEL_KEY;
65384e54fe0SWilliam Tu 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
65484e54fe0SWilliam Tu 	return NETDEV_TX_OK;
65584e54fe0SWilliam Tu 
65684e54fe0SWilliam Tu free_skb:
65784e54fe0SWilliam Tu 	kfree_skb(skb);
65884e54fe0SWilliam Tu 	dev->stats.tx_dropped++;
65984e54fe0SWilliam Tu 	return NETDEV_TX_OK;
66084e54fe0SWilliam Tu }
66184e54fe0SWilliam Tu 
662c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
663c5441932SPravin B Shelar 				struct net_device *dev)
664c5441932SPravin B Shelar {
665c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
666ee34c1ebSMichal Schmidt 
6672e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
6682090714eSJiri Benc 		gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
6692e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
6702e15ea39SPravin B Shelar 	}
6712e15ea39SPravin B Shelar 
672aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
673aed069dfSAlexander Duyck 		goto free_skb;
674ee34c1ebSMichal Schmidt 
675c5441932SPravin B Shelar 	if (skb_cow_head(skb, dev->needed_headroom))
676c5441932SPravin B Shelar 		goto free_skb;
67742aa9162SHerbert Xu 
678c5441932SPravin B Shelar 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
679c5441932SPravin B Shelar 	return NETDEV_TX_OK;
680c5441932SPravin B Shelar 
681c5441932SPravin B Shelar free_skb:
6823acfa1e7SEric Dumazet 	kfree_skb(skb);
683c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
684c5441932SPravin B Shelar 	return NETDEV_TX_OK;
68568c33163SPravin B Shelar }
686ee34c1ebSMichal Schmidt 
687c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev,
688c5441932SPravin B Shelar 			      struct ifreq *ifr, int cmd)
6891da177e4SLinus Torvalds {
6904565e991STom Herbert 	int err;
6911da177e4SLinus Torvalds 	struct ip_tunnel_parm p;
6921da177e4SLinus Torvalds 
6931da177e4SLinus Torvalds 	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
694c5441932SPravin B Shelar 		return -EFAULT;
6956c734fb8SCong Wang 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
6961da177e4SLinus Torvalds 		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
6971da177e4SLinus Torvalds 		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
6986c734fb8SCong Wang 		    ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
6991da177e4SLinus Torvalds 			return -EINVAL;
700c5441932SPravin B Shelar 	}
701c5441932SPravin B Shelar 	p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
702c5441932SPravin B Shelar 	p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
703c5441932SPravin B Shelar 
704c5441932SPravin B Shelar 	err = ip_tunnel_ioctl(dev, &p, cmd);
705c5441932SPravin B Shelar 	if (err)
706c5441932SPravin B Shelar 		return err;
707c5441932SPravin B Shelar 
70895f5c64cSTom Herbert 	p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
70995f5c64cSTom Herbert 	p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
710c5441932SPravin B Shelar 
711c5441932SPravin B Shelar 	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
712c5441932SPravin B Shelar 		return -EFAULT;
7131da177e4SLinus Torvalds 	return 0;
7141da177e4SLinus Torvalds }
7151da177e4SLinus Torvalds 
7161da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-)
7171da177e4SLinus Torvalds    It allows to construct virtual multiprotocol broadcast "LAN"
7181da177e4SLinus Torvalds    over the Internet, provided multicast routing is tuned.
7191da177e4SLinus Torvalds 
7201da177e4SLinus Torvalds 
7211da177e4SLinus Torvalds    I have no idea was this bicycle invented before me,
7221da177e4SLinus Torvalds    so that I had to set ARPHRD_IPGRE to a random value.
7231da177e4SLinus Torvalds    I have an impression, that Cisco could make something similar,
7241da177e4SLinus Torvalds    but this feature is apparently missing in IOS<=11.2(8).
7251da177e4SLinus Torvalds 
7261da177e4SLinus Torvalds    I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
7271da177e4SLinus Torvalds    with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
7281da177e4SLinus Torvalds 
7291da177e4SLinus Torvalds    ping -t 255 224.66.66.66
7301da177e4SLinus Torvalds 
7311da177e4SLinus Torvalds    If nobody answers, mbone does not work.
7321da177e4SLinus Torvalds 
7331da177e4SLinus Torvalds    ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
7341da177e4SLinus Torvalds    ip addr add 10.66.66.<somewhat>/24 dev Universe
7351da177e4SLinus Torvalds    ifconfig Universe up
7361da177e4SLinus Torvalds    ifconfig Universe add fe80::<Your_real_addr>/10
7371da177e4SLinus Torvalds    ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
7381da177e4SLinus Torvalds    ftp 10.66.66.66
7391da177e4SLinus Torvalds    ...
7401da177e4SLinus Torvalds    ftp fec0:6666:6666::193.233.7.65
7411da177e4SLinus Torvalds    ...
7421da177e4SLinus Torvalds  */
7433b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
7443b04dddeSStephen Hemminger 			unsigned short type,
7451507850bSEric Dumazet 			const void *daddr, const void *saddr, unsigned int len)
7461da177e4SLinus Torvalds {
7472941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
748c5441932SPravin B Shelar 	struct iphdr *iph;
749c5441932SPravin B Shelar 	struct gre_base_hdr *greh;
750c5441932SPravin B Shelar 
751d58ff351SJohannes Berg 	iph = skb_push(skb, t->hlen + sizeof(*iph));
752c5441932SPravin B Shelar 	greh = (struct gre_base_hdr *)(iph+1);
75395f5c64cSTom Herbert 	greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
754c5441932SPravin B Shelar 	greh->protocol = htons(type);
7551da177e4SLinus Torvalds 
7561da177e4SLinus Torvalds 	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
7571da177e4SLinus Torvalds 
758c5441932SPravin B Shelar 	/* Set the source hardware address. */
7591da177e4SLinus Torvalds 	if (saddr)
7601da177e4SLinus Torvalds 		memcpy(&iph->saddr, saddr, 4);
7616d55cb91STimo Teräs 	if (daddr)
7621da177e4SLinus Torvalds 		memcpy(&iph->daddr, daddr, 4);
7636d55cb91STimo Teräs 	if (iph->daddr)
76477a482bdSTimo Teräs 		return t->hlen + sizeof(*iph);
7651da177e4SLinus Torvalds 
766c5441932SPravin B Shelar 	return -(t->hlen + sizeof(*iph));
7671da177e4SLinus Torvalds }
7681da177e4SLinus Torvalds 
7696a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
7706a5f44d7STimo Teras {
771b71d1d42SEric Dumazet 	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
7726a5f44d7STimo Teras 	memcpy(haddr, &iph->saddr, 4);
7736a5f44d7STimo Teras 	return 4;
7746a5f44d7STimo Teras }
7756a5f44d7STimo Teras 
7763b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = {
7773b04dddeSStephen Hemminger 	.create	= ipgre_header,
7786a5f44d7STimo Teras 	.parse	= ipgre_header_parse,
7793b04dddeSStephen Hemminger };
7803b04dddeSStephen Hemminger 
7816a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST
7821da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev)
7831da177e4SLinus Torvalds {
7842941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
7851da177e4SLinus Torvalds 
786f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
787cbb1e85fSDavid S. Miller 		struct flowi4 fl4;
788cbb1e85fSDavid S. Miller 		struct rtable *rt;
789cbb1e85fSDavid S. Miller 
790b57708adSNicolas Dichtel 		rt = ip_route_output_gre(t->net, &fl4,
79178fbfd8aSDavid S. Miller 					 t->parms.iph.daddr,
79278fbfd8aSDavid S. Miller 					 t->parms.iph.saddr,
79378fbfd8aSDavid S. Miller 					 t->parms.o_key,
79478fbfd8aSDavid S. Miller 					 RT_TOS(t->parms.iph.tos),
79578fbfd8aSDavid S. Miller 					 t->parms.link);
796b23dd4feSDavid S. Miller 		if (IS_ERR(rt))
7971da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
798d8d1f30bSChangli Gao 		dev = rt->dst.dev;
7991da177e4SLinus Torvalds 		ip_rt_put(rt);
80051456b29SIan Morris 		if (!__in_dev_get_rtnl(dev))
8011da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
8021da177e4SLinus Torvalds 		t->mlink = dev->ifindex;
803e5ed6399SHerbert Xu 		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
8041da177e4SLinus Torvalds 	}
8051da177e4SLinus Torvalds 	return 0;
8061da177e4SLinus Torvalds }
8071da177e4SLinus Torvalds 
8081da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev)
8091da177e4SLinus Torvalds {
8102941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
811b8c26a33SStephen Hemminger 
812f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
8137fee0ca2SDenis V. Lunev 		struct in_device *in_dev;
814b57708adSNicolas Dichtel 		in_dev = inetdev_by_index(t->net, t->mlink);
8158723e1b4SEric Dumazet 		if (in_dev)
8161da177e4SLinus Torvalds 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
8171da177e4SLinus Torvalds 	}
8181da177e4SLinus Torvalds 	return 0;
8191da177e4SLinus Torvalds }
8201da177e4SLinus Torvalds #endif
8211da177e4SLinus Torvalds 
822b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = {
823b8c26a33SStephen Hemminger 	.ndo_init		= ipgre_tunnel_init,
824c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
825b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST
826b8c26a33SStephen Hemminger 	.ndo_open		= ipgre_open,
827b8c26a33SStephen Hemminger 	.ndo_stop		= ipgre_close,
828b8c26a33SStephen Hemminger #endif
829c5441932SPravin B Shelar 	.ndo_start_xmit		= ipgre_xmit,
830b8c26a33SStephen Hemminger 	.ndo_do_ioctl		= ipgre_tunnel_ioctl,
831c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
832c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
8331e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
834b8c26a33SStephen Hemminger };
835b8c26a33SStephen Hemminger 
8366b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG |		\
8376b78f16eSEric Dumazet 		      NETIF_F_FRAGLIST |	\
8386b78f16eSEric Dumazet 		      NETIF_F_HIGHDMA |		\
8396b78f16eSEric Dumazet 		      NETIF_F_HW_CSUM)
8406b78f16eSEric Dumazet 
8411da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev)
8421da177e4SLinus Torvalds {
843b8c26a33SStephen Hemminger 	dev->netdev_ops		= &ipgre_netdev_ops;
8445a455275SNicolas Dichtel 	dev->type		= ARPHRD_IPGRE;
845c5441932SPravin B Shelar 	ip_tunnel_setup(dev, ipgre_net_id);
846c5441932SPravin B Shelar }
8471da177e4SLinus Torvalds 
848c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev)
849c5441932SPravin B Shelar {
850c5441932SPravin B Shelar 	struct ip_tunnel *tunnel;
8514565e991STom Herbert 	int t_hlen;
852c5441932SPravin B Shelar 
853c5441932SPravin B Shelar 	tunnel = netdev_priv(dev);
85495f5c64cSTom Herbert 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
855c5441932SPravin B Shelar 	tunnel->parms.iph.protocol = IPPROTO_GRE;
856c5441932SPravin B Shelar 
8574565e991STom Herbert 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
8584565e991STom Herbert 
8594565e991STom Herbert 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
8604565e991STom Herbert 
8614565e991STom Herbert 	dev->needed_headroom	= LL_MAX_HEADER + t_hlen + 4;
8624565e991STom Herbert 	dev->mtu		= ETH_DATA_LEN - t_hlen - 4;
8636b78f16eSEric Dumazet 
864b57708adSNicolas Dichtel 	dev->features		|= GRE_FEATURES;
8656b78f16eSEric Dumazet 	dev->hw_features	|= GRE_FEATURES;
866c5441932SPravin B Shelar 
867c5441932SPravin B Shelar 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
868a0ca153fSAlexander Duyck 		/* TCP offload with GRE SEQ is not supported, nor
869a0ca153fSAlexander Duyck 		 * can we support 2 levels of outer headers requiring
870a0ca153fSAlexander Duyck 		 * an update.
871a0ca153fSAlexander Duyck 		 */
872a0ca153fSAlexander Duyck 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
873a0ca153fSAlexander Duyck 		    (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
874c5441932SPravin B Shelar 			dev->features    |= NETIF_F_GSO_SOFTWARE;
875c5441932SPravin B Shelar 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
876a0ca153fSAlexander Duyck 		}
877a0ca153fSAlexander Duyck 
878c5441932SPravin B Shelar 		/* Can use a lockless transmit, unless we generate
879c5441932SPravin B Shelar 		 * output sequences
880c5441932SPravin B Shelar 		 */
881c5441932SPravin B Shelar 		dev->features |= NETIF_F_LLTX;
882c5441932SPravin B Shelar 	}
8831da177e4SLinus Torvalds }
8841da177e4SLinus Torvalds 
8851da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev)
8861da177e4SLinus Torvalds {
887c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
888c5441932SPravin B Shelar 	struct iphdr *iph = &tunnel->parms.iph;
8891da177e4SLinus Torvalds 
890c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
8911da177e4SLinus Torvalds 
892c5441932SPravin B Shelar 	memcpy(dev->dev_addr, &iph->saddr, 4);
893c5441932SPravin B Shelar 	memcpy(dev->broadcast, &iph->daddr, 4);
8941da177e4SLinus Torvalds 
895c5441932SPravin B Shelar 	dev->flags		= IFF_NOARP;
89602875878SEric Dumazet 	netif_keep_dst(dev);
897c5441932SPravin B Shelar 	dev->addr_len		= 4;
8981da177e4SLinus Torvalds 
899a64b04d8SJiri Benc 	if (iph->daddr && !tunnel->collect_md) {
9001da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST
901f97c1e0cSJoe Perches 		if (ipv4_is_multicast(iph->daddr)) {
9021da177e4SLinus Torvalds 			if (!iph->saddr)
9031da177e4SLinus Torvalds 				return -EINVAL;
9041da177e4SLinus Torvalds 			dev->flags = IFF_BROADCAST;
9053b04dddeSStephen Hemminger 			dev->header_ops = &ipgre_header_ops;
9061da177e4SLinus Torvalds 		}
9071da177e4SLinus Torvalds #endif
908a64b04d8SJiri Benc 	} else if (!tunnel->collect_md) {
9096a5f44d7STimo Teras 		dev->header_ops = &ipgre_header_ops;
910a64b04d8SJiri Benc 	}
9111da177e4SLinus Torvalds 
912c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
91360769a5dSEric Dumazet }
91460769a5dSEric Dumazet 
9159f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = {
9169f57c67cSPravin B Shelar 	.handler     = gre_rcv,
9179f57c67cSPravin B Shelar 	.err_handler = gre_err,
9181da177e4SLinus Torvalds };
9191da177e4SLinus Torvalds 
9202c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net)
92159a4c759SPavel Emelyanov {
922c5441932SPravin B Shelar 	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
92359a4c759SPavel Emelyanov }
92459a4c759SPavel Emelyanov 
9252c8c1e72SAlexey Dobriyan static void __net_exit ipgre_exit_net(struct net *net)
92659a4c759SPavel Emelyanov {
927c5441932SPravin B Shelar 	struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id);
9286c742e71SNicolas Dichtel 	ip_tunnel_delete_net(itn, &ipgre_link_ops);
92959a4c759SPavel Emelyanov }
93059a4c759SPavel Emelyanov 
93159a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = {
93259a4c759SPavel Emelyanov 	.init = ipgre_init_net,
93359a4c759SPavel Emelyanov 	.exit = ipgre_exit_net,
934cfb8fbf2SEric W. Biederman 	.id   = &ipgre_net_id,
935c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
93659a4c759SPavel Emelyanov };
9371da177e4SLinus Torvalds 
938a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
939a8b8a889SMatthias Schiffer 				 struct netlink_ext_ack *extack)
940c19e654dSHerbert Xu {
941c19e654dSHerbert Xu 	__be16 flags;
942c19e654dSHerbert Xu 
943c19e654dSHerbert Xu 	if (!data)
944c19e654dSHerbert Xu 		return 0;
945c19e654dSHerbert Xu 
946c19e654dSHerbert Xu 	flags = 0;
947c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
948c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
949c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
950c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
951c19e654dSHerbert Xu 	if (flags & (GRE_VERSION|GRE_ROUTING))
952c19e654dSHerbert Xu 		return -EINVAL;
953c19e654dSHerbert Xu 
954946b636fSJiri Benc 	if (data[IFLA_GRE_COLLECT_METADATA] &&
955946b636fSJiri Benc 	    data[IFLA_GRE_ENCAP_TYPE] &&
956946b636fSJiri Benc 	    nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
957946b636fSJiri Benc 		return -EINVAL;
958946b636fSJiri Benc 
959c19e654dSHerbert Xu 	return 0;
960c19e654dSHerbert Xu }
961c19e654dSHerbert Xu 
962a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
963a8b8a889SMatthias Schiffer 			      struct netlink_ext_ack *extack)
964e1a80002SHerbert Xu {
965e1a80002SHerbert Xu 	__be32 daddr;
966e1a80002SHerbert Xu 
967e1a80002SHerbert Xu 	if (tb[IFLA_ADDRESS]) {
968e1a80002SHerbert Xu 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
969e1a80002SHerbert Xu 			return -EINVAL;
970e1a80002SHerbert Xu 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
971e1a80002SHerbert Xu 			return -EADDRNOTAVAIL;
972e1a80002SHerbert Xu 	}
973e1a80002SHerbert Xu 
974e1a80002SHerbert Xu 	if (!data)
975e1a80002SHerbert Xu 		goto out;
976e1a80002SHerbert Xu 
977e1a80002SHerbert Xu 	if (data[IFLA_GRE_REMOTE]) {
978e1a80002SHerbert Xu 		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
979e1a80002SHerbert Xu 		if (!daddr)
980e1a80002SHerbert Xu 			return -EINVAL;
981e1a80002SHerbert Xu 	}
982e1a80002SHerbert Xu 
983e1a80002SHerbert Xu out:
984a8b8a889SMatthias Schiffer 	return ipgre_tunnel_validate(tb, data, extack);
985e1a80002SHerbert Xu }
986e1a80002SHerbert Xu 
98784e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
98884e54fe0SWilliam Tu 			   struct netlink_ext_ack *extack)
98984e54fe0SWilliam Tu {
99084e54fe0SWilliam Tu 	__be16 flags = 0;
99184e54fe0SWilliam Tu 	int ret;
99284e54fe0SWilliam Tu 
99384e54fe0SWilliam Tu 	if (!data)
99484e54fe0SWilliam Tu 		return 0;
99584e54fe0SWilliam Tu 
99684e54fe0SWilliam Tu 	ret = ipgre_tap_validate(tb, data, extack);
99784e54fe0SWilliam Tu 	if (ret)
99884e54fe0SWilliam Tu 		return ret;
99984e54fe0SWilliam Tu 
100084e54fe0SWilliam Tu 	/* ERSPAN should only have GRE sequence and key flag */
100184e54fe0SWilliam Tu 	flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
100284e54fe0SWilliam Tu 	flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
100384e54fe0SWilliam Tu 	if (flags != (GRE_SEQ | GRE_KEY))
100484e54fe0SWilliam Tu 		return -EINVAL;
100584e54fe0SWilliam Tu 
100684e54fe0SWilliam Tu 	/* ERSPAN Session ID only has 10-bit. Since we reuse
100784e54fe0SWilliam Tu 	 * 32-bit key field as ID, check it's range.
100884e54fe0SWilliam Tu 	 */
100984e54fe0SWilliam Tu 	if (data[IFLA_GRE_IKEY] &&
101084e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
101184e54fe0SWilliam Tu 		return -EINVAL;
101284e54fe0SWilliam Tu 
101384e54fe0SWilliam Tu 	if (data[IFLA_GRE_OKEY] &&
101484e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
101584e54fe0SWilliam Tu 		return -EINVAL;
101684e54fe0SWilliam Tu 
101784e54fe0SWilliam Tu 	return 0;
101884e54fe0SWilliam Tu }
101984e54fe0SWilliam Tu 
102022a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev,
10212e15ea39SPravin B Shelar 				struct nlattr *data[],
10222e15ea39SPravin B Shelar 				struct nlattr *tb[],
10239830ad4cSCraig Gallek 				struct ip_tunnel_parm *parms,
10249830ad4cSCraig Gallek 				__u32 *fwmark)
1025c19e654dSHerbert Xu {
102622a59be8SPhilip Prindeville 	struct ip_tunnel *t = netdev_priv(dev);
102722a59be8SPhilip Prindeville 
10287bb82d92SHerbert Xu 	memset(parms, 0, sizeof(*parms));
1029c19e654dSHerbert Xu 
1030c19e654dSHerbert Xu 	parms->iph.protocol = IPPROTO_GRE;
1031c19e654dSHerbert Xu 
1032c19e654dSHerbert Xu 	if (!data)
103322a59be8SPhilip Prindeville 		return 0;
1034c19e654dSHerbert Xu 
1035c19e654dSHerbert Xu 	if (data[IFLA_GRE_LINK])
1036c19e654dSHerbert Xu 		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1037c19e654dSHerbert Xu 
1038c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1039c5441932SPravin B Shelar 		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
1040c19e654dSHerbert Xu 
1041c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1042c5441932SPravin B Shelar 		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
1043c19e654dSHerbert Xu 
1044c19e654dSHerbert Xu 	if (data[IFLA_GRE_IKEY])
1045c19e654dSHerbert Xu 		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1046c19e654dSHerbert Xu 
1047c19e654dSHerbert Xu 	if (data[IFLA_GRE_OKEY])
1048c19e654dSHerbert Xu 		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1049c19e654dSHerbert Xu 
1050c19e654dSHerbert Xu 	if (data[IFLA_GRE_LOCAL])
105167b61f6cSJiri Benc 		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
1052c19e654dSHerbert Xu 
1053c19e654dSHerbert Xu 	if (data[IFLA_GRE_REMOTE])
105467b61f6cSJiri Benc 		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
1055c19e654dSHerbert Xu 
1056c19e654dSHerbert Xu 	if (data[IFLA_GRE_TTL])
1057c19e654dSHerbert Xu 		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1058c19e654dSHerbert Xu 
1059c19e654dSHerbert Xu 	if (data[IFLA_GRE_TOS])
1060c19e654dSHerbert Xu 		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1061c19e654dSHerbert Xu 
106222a59be8SPhilip Prindeville 	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
106322a59be8SPhilip Prindeville 		if (t->ignore_df)
106422a59be8SPhilip Prindeville 			return -EINVAL;
1065c19e654dSHerbert Xu 		parms->iph.frag_off = htons(IP_DF);
106622a59be8SPhilip Prindeville 	}
10672e15ea39SPravin B Shelar 
10682e15ea39SPravin B Shelar 	if (data[IFLA_GRE_COLLECT_METADATA]) {
10692e15ea39SPravin B Shelar 		t->collect_md = true;
1070e271c7b4SJiri Benc 		if (dev->type == ARPHRD_IPGRE)
1071e271c7b4SJiri Benc 			dev->type = ARPHRD_NONE;
10722e15ea39SPravin B Shelar 	}
107322a59be8SPhilip Prindeville 
107422a59be8SPhilip Prindeville 	if (data[IFLA_GRE_IGNORE_DF]) {
107522a59be8SPhilip Prindeville 		if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
107622a59be8SPhilip Prindeville 		  && (parms->iph.frag_off & htons(IP_DF)))
107722a59be8SPhilip Prindeville 			return -EINVAL;
107822a59be8SPhilip Prindeville 		t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
107922a59be8SPhilip Prindeville 	}
108022a59be8SPhilip Prindeville 
10819830ad4cSCraig Gallek 	if (data[IFLA_GRE_FWMARK])
10829830ad4cSCraig Gallek 		*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
10839830ad4cSCraig Gallek 
108484e54fe0SWilliam Tu 	if (data[IFLA_GRE_ERSPAN_INDEX]) {
108584e54fe0SWilliam Tu 		t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
108684e54fe0SWilliam Tu 
108784e54fe0SWilliam Tu 		if (t->index & ~INDEX_MASK)
108884e54fe0SWilliam Tu 			return -EINVAL;
108984e54fe0SWilliam Tu 	}
109084e54fe0SWilliam Tu 
109122a59be8SPhilip Prindeville 	return 0;
1092c19e654dSHerbert Xu }
1093c19e654dSHerbert Xu 
10944565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */
10954565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[],
10964565e991STom Herbert 				      struct ip_tunnel_encap *ipencap)
10974565e991STom Herbert {
10984565e991STom Herbert 	bool ret = false;
10994565e991STom Herbert 
11004565e991STom Herbert 	memset(ipencap, 0, sizeof(*ipencap));
11014565e991STom Herbert 
11024565e991STom Herbert 	if (!data)
11034565e991STom Herbert 		return ret;
11044565e991STom Herbert 
11054565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_TYPE]) {
11064565e991STom Herbert 		ret = true;
11074565e991STom Herbert 		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
11084565e991STom Herbert 	}
11094565e991STom Herbert 
11104565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_FLAGS]) {
11114565e991STom Herbert 		ret = true;
11124565e991STom Herbert 		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
11134565e991STom Herbert 	}
11144565e991STom Herbert 
11154565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_SPORT]) {
11164565e991STom Herbert 		ret = true;
11173e97fa70SSabrina Dubroca 		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
11184565e991STom Herbert 	}
11194565e991STom Herbert 
11204565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_DPORT]) {
11214565e991STom Herbert 		ret = true;
11223e97fa70SSabrina Dubroca 		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
11234565e991STom Herbert 	}
11244565e991STom Herbert 
11254565e991STom Herbert 	return ret;
11264565e991STom Herbert }
11274565e991STom Herbert 
1128c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev)
1129e1a80002SHerbert Xu {
1130c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
1131bec94d43Sstephen hemminger 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
1132e1a80002SHerbert Xu 
1133c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
1134e1a80002SHerbert Xu }
1135e1a80002SHerbert Xu 
1136c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = {
1137c5441932SPravin B Shelar 	.ndo_init		= gre_tap_init,
1138c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
1139c5441932SPravin B Shelar 	.ndo_start_xmit		= gre_tap_xmit,
1140b8c26a33SStephen Hemminger 	.ndo_set_mac_address 	= eth_mac_addr,
1141b8c26a33SStephen Hemminger 	.ndo_validate_addr	= eth_validate_addr,
1142c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
1143c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
11441e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
1145fc4099f1SPravin B Shelar 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
1146b8c26a33SStephen Hemminger };
1147b8c26a33SStephen Hemminger 
114884e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev)
114984e54fe0SWilliam Tu {
115084e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
115184e54fe0SWilliam Tu 	int t_hlen;
115284e54fe0SWilliam Tu 
115384e54fe0SWilliam Tu 	tunnel->tun_hlen = 8;
115484e54fe0SWilliam Tu 	tunnel->parms.iph.protocol = IPPROTO_GRE;
115584e54fe0SWilliam Tu 	t_hlen = tunnel->hlen + sizeof(struct iphdr) + sizeof(struct erspanhdr);
115684e54fe0SWilliam Tu 
115784e54fe0SWilliam Tu 	dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
115884e54fe0SWilliam Tu 	dev->mtu = ETH_DATA_LEN - t_hlen - 4;
115984e54fe0SWilliam Tu 	dev->features		|= GRE_FEATURES;
116084e54fe0SWilliam Tu 	dev->hw_features	|= GRE_FEATURES;
116184e54fe0SWilliam Tu 	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
116284e54fe0SWilliam Tu 
116384e54fe0SWilliam Tu 	return ip_tunnel_init(dev);
116484e54fe0SWilliam Tu }
116584e54fe0SWilliam Tu 
116684e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = {
116784e54fe0SWilliam Tu 	.ndo_init		= erspan_tunnel_init,
116884e54fe0SWilliam Tu 	.ndo_uninit		= ip_tunnel_uninit,
116984e54fe0SWilliam Tu 	.ndo_start_xmit		= erspan_xmit,
117084e54fe0SWilliam Tu 	.ndo_set_mac_address	= eth_mac_addr,
117184e54fe0SWilliam Tu 	.ndo_validate_addr	= eth_validate_addr,
117284e54fe0SWilliam Tu 	.ndo_change_mtu		= ip_tunnel_change_mtu,
117384e54fe0SWilliam Tu 	.ndo_get_stats64	= ip_tunnel_get_stats64,
117484e54fe0SWilliam Tu 	.ndo_get_iflink		= ip_tunnel_get_iflink,
117584e54fe0SWilliam Tu 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
117684e54fe0SWilliam Tu };
117784e54fe0SWilliam Tu 
1178e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev)
1179e1a80002SHerbert Xu {
1180e1a80002SHerbert Xu 	ether_setup(dev);
1181c5441932SPravin B Shelar 	dev->netdev_ops	= &gre_tap_netdev_ops;
1182d13b161cSJiri Benc 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1183f8c1b7ceSstephen hemminger 	dev->priv_flags	|= IFF_LIVE_ADDR_CHANGE;
1184c5441932SPravin B Shelar 	ip_tunnel_setup(dev, gre_tap_net_id);
1185e1a80002SHerbert Xu }
1186e1a80002SHerbert Xu 
1187c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev,
11887a3f4a18SMatthias Schiffer 			 struct nlattr *tb[], struct nlattr *data[],
11897a3f4a18SMatthias Schiffer 			 struct netlink_ext_ack *extack)
1190c19e654dSHerbert Xu {
1191c5441932SPravin B Shelar 	struct ip_tunnel_parm p;
11924565e991STom Herbert 	struct ip_tunnel_encap ipencap;
11939830ad4cSCraig Gallek 	__u32 fwmark = 0;
119422a59be8SPhilip Prindeville 	int err;
11954565e991STom Herbert 
11964565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
11974565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
119822a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
11994565e991STom Herbert 
12004565e991STom Herbert 		if (err < 0)
12014565e991STom Herbert 			return err;
12024565e991STom Herbert 	}
1203c19e654dSHerbert Xu 
12049830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
120522a59be8SPhilip Prindeville 	if (err < 0)
120622a59be8SPhilip Prindeville 		return err;
12079830ad4cSCraig Gallek 	return ip_tunnel_newlink(dev, tb, &p, fwmark);
1208c19e654dSHerbert Xu }
1209c19e654dSHerbert Xu 
1210c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1211ad744b22SMatthias Schiffer 			    struct nlattr *data[],
1212ad744b22SMatthias Schiffer 			    struct netlink_ext_ack *extack)
1213c19e654dSHerbert Xu {
12149830ad4cSCraig Gallek 	struct ip_tunnel *t = netdev_priv(dev);
1215c19e654dSHerbert Xu 	struct ip_tunnel_parm p;
12164565e991STom Herbert 	struct ip_tunnel_encap ipencap;
12179830ad4cSCraig Gallek 	__u32 fwmark = t->fwmark;
121822a59be8SPhilip Prindeville 	int err;
12194565e991STom Herbert 
12204565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
122122a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
12224565e991STom Herbert 
12234565e991STom Herbert 		if (err < 0)
12244565e991STom Herbert 			return err;
12254565e991STom Herbert 	}
1226c19e654dSHerbert Xu 
12279830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
122822a59be8SPhilip Prindeville 	if (err < 0)
122922a59be8SPhilip Prindeville 		return err;
12309830ad4cSCraig Gallek 	return ip_tunnel_changelink(dev, tb, &p, fwmark);
1231c19e654dSHerbert Xu }
1232c19e654dSHerbert Xu 
1233c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev)
1234c19e654dSHerbert Xu {
1235c19e654dSHerbert Xu 	return
1236c19e654dSHerbert Xu 		/* IFLA_GRE_LINK */
1237c19e654dSHerbert Xu 		nla_total_size(4) +
1238c19e654dSHerbert Xu 		/* IFLA_GRE_IFLAGS */
1239c19e654dSHerbert Xu 		nla_total_size(2) +
1240c19e654dSHerbert Xu 		/* IFLA_GRE_OFLAGS */
1241c19e654dSHerbert Xu 		nla_total_size(2) +
1242c19e654dSHerbert Xu 		/* IFLA_GRE_IKEY */
1243c19e654dSHerbert Xu 		nla_total_size(4) +
1244c19e654dSHerbert Xu 		/* IFLA_GRE_OKEY */
1245c19e654dSHerbert Xu 		nla_total_size(4) +
1246c19e654dSHerbert Xu 		/* IFLA_GRE_LOCAL */
1247c19e654dSHerbert Xu 		nla_total_size(4) +
1248c19e654dSHerbert Xu 		/* IFLA_GRE_REMOTE */
1249c19e654dSHerbert Xu 		nla_total_size(4) +
1250c19e654dSHerbert Xu 		/* IFLA_GRE_TTL */
1251c19e654dSHerbert Xu 		nla_total_size(1) +
1252c19e654dSHerbert Xu 		/* IFLA_GRE_TOS */
1253c19e654dSHerbert Xu 		nla_total_size(1) +
1254c19e654dSHerbert Xu 		/* IFLA_GRE_PMTUDISC */
1255c19e654dSHerbert Xu 		nla_total_size(1) +
12564565e991STom Herbert 		/* IFLA_GRE_ENCAP_TYPE */
12574565e991STom Herbert 		nla_total_size(2) +
12584565e991STom Herbert 		/* IFLA_GRE_ENCAP_FLAGS */
12594565e991STom Herbert 		nla_total_size(2) +
12604565e991STom Herbert 		/* IFLA_GRE_ENCAP_SPORT */
12614565e991STom Herbert 		nla_total_size(2) +
12624565e991STom Herbert 		/* IFLA_GRE_ENCAP_DPORT */
12634565e991STom Herbert 		nla_total_size(2) +
12642e15ea39SPravin B Shelar 		/* IFLA_GRE_COLLECT_METADATA */
12652e15ea39SPravin B Shelar 		nla_total_size(0) +
126622a59be8SPhilip Prindeville 		/* IFLA_GRE_IGNORE_DF */
126722a59be8SPhilip Prindeville 		nla_total_size(1) +
12689830ad4cSCraig Gallek 		/* IFLA_GRE_FWMARK */
12699830ad4cSCraig Gallek 		nla_total_size(4) +
127084e54fe0SWilliam Tu 		/* IFLA_GRE_ERSPAN_INDEX */
127184e54fe0SWilliam Tu 		nla_total_size(4) +
1272c19e654dSHerbert Xu 		0;
1273c19e654dSHerbert Xu }
1274c19e654dSHerbert Xu 
1275c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1276c19e654dSHerbert Xu {
1277c19e654dSHerbert Xu 	struct ip_tunnel *t = netdev_priv(dev);
1278c19e654dSHerbert Xu 	struct ip_tunnel_parm *p = &t->parms;
1279c19e654dSHerbert Xu 
1280f3756b79SDavid S. Miller 	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
128195f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_IFLAGS,
128295f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
128395f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_OFLAGS,
128495f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->o_flags)) ||
1285f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1286f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
1287930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1288930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
1289f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1290f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1291f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
12929830ad4cSCraig Gallek 		       !!(p->iph.frag_off & htons(IP_DF))) ||
12939830ad4cSCraig Gallek 	    nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
1294f3756b79SDavid S. Miller 		goto nla_put_failure;
12954565e991STom Herbert 
12964565e991STom Herbert 	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
12974565e991STom Herbert 			t->encap.type) ||
12983e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
12994565e991STom Herbert 			 t->encap.sport) ||
13003e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
13014565e991STom Herbert 			 t->encap.dport) ||
13024565e991STom Herbert 	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
1303e1b2cb65STom Herbert 			t->encap.flags))
13044565e991STom Herbert 		goto nla_put_failure;
13054565e991STom Herbert 
130622a59be8SPhilip Prindeville 	if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
130722a59be8SPhilip Prindeville 		goto nla_put_failure;
130822a59be8SPhilip Prindeville 
13092e15ea39SPravin B Shelar 	if (t->collect_md) {
13102e15ea39SPravin B Shelar 		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
13112e15ea39SPravin B Shelar 			goto nla_put_failure;
13122e15ea39SPravin B Shelar 	}
13132e15ea39SPravin B Shelar 
131484e54fe0SWilliam Tu 	if (t->index)
131584e54fe0SWilliam Tu 		if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
131684e54fe0SWilliam Tu 			goto nla_put_failure;
131784e54fe0SWilliam Tu 
1318c19e654dSHerbert Xu 	return 0;
1319c19e654dSHerbert Xu 
1320c19e654dSHerbert Xu nla_put_failure:
1321c19e654dSHerbert Xu 	return -EMSGSIZE;
1322c19e654dSHerbert Xu }
1323c19e654dSHerbert Xu 
132484e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev)
132584e54fe0SWilliam Tu {
132684e54fe0SWilliam Tu 	ether_setup(dev);
132784e54fe0SWilliam Tu 	dev->netdev_ops = &erspan_netdev_ops;
132884e54fe0SWilliam Tu 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
132984e54fe0SWilliam Tu 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
133084e54fe0SWilliam Tu 	ip_tunnel_setup(dev, erspan_net_id);
133184e54fe0SWilliam Tu }
133284e54fe0SWilliam Tu 
1333c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1334c19e654dSHerbert Xu 	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
1335c19e654dSHerbert Xu 	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
1336c19e654dSHerbert Xu 	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
1337c19e654dSHerbert Xu 	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
1338c19e654dSHerbert Xu 	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
13394d74f8baSPatrick McHardy 	[IFLA_GRE_LOCAL]	= { .len = FIELD_SIZEOF(struct iphdr, saddr) },
13404d74f8baSPatrick McHardy 	[IFLA_GRE_REMOTE]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
1341c19e654dSHerbert Xu 	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
1342c19e654dSHerbert Xu 	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
1343c19e654dSHerbert Xu 	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
13444565e991STom Herbert 	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
13454565e991STom Herbert 	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
13464565e991STom Herbert 	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
13474565e991STom Herbert 	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
13482e15ea39SPravin B Shelar 	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
134922a59be8SPhilip Prindeville 	[IFLA_GRE_IGNORE_DF]	= { .type = NLA_U8 },
13509830ad4cSCraig Gallek 	[IFLA_GRE_FWMARK]	= { .type = NLA_U32 },
135184e54fe0SWilliam Tu 	[IFLA_GRE_ERSPAN_INDEX]	= { .type = NLA_U32 },
1352c19e654dSHerbert Xu };
1353c19e654dSHerbert Xu 
1354c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1355c19e654dSHerbert Xu 	.kind		= "gre",
1356c19e654dSHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1357c19e654dSHerbert Xu 	.policy		= ipgre_policy,
1358c19e654dSHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1359c19e654dSHerbert Xu 	.setup		= ipgre_tunnel_setup,
1360c19e654dSHerbert Xu 	.validate	= ipgre_tunnel_validate,
1361c19e654dSHerbert Xu 	.newlink	= ipgre_newlink,
1362c19e654dSHerbert Xu 	.changelink	= ipgre_changelink,
1363c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1364c19e654dSHerbert Xu 	.get_size	= ipgre_get_size,
1365c19e654dSHerbert Xu 	.fill_info	= ipgre_fill_info,
13661728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1367c19e654dSHerbert Xu };
1368c19e654dSHerbert Xu 
1369e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1370e1a80002SHerbert Xu 	.kind		= "gretap",
1371e1a80002SHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1372e1a80002SHerbert Xu 	.policy		= ipgre_policy,
1373e1a80002SHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1374e1a80002SHerbert Xu 	.setup		= ipgre_tap_setup,
1375e1a80002SHerbert Xu 	.validate	= ipgre_tap_validate,
1376e1a80002SHerbert Xu 	.newlink	= ipgre_newlink,
1377e1a80002SHerbert Xu 	.changelink	= ipgre_changelink,
1378c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1379e1a80002SHerbert Xu 	.get_size	= ipgre_get_size,
1380e1a80002SHerbert Xu 	.fill_info	= ipgre_fill_info,
13811728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1382e1a80002SHerbert Xu };
1383e1a80002SHerbert Xu 
138484e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = {
138584e54fe0SWilliam Tu 	.kind		= "erspan",
138684e54fe0SWilliam Tu 	.maxtype	= IFLA_GRE_MAX,
138784e54fe0SWilliam Tu 	.policy		= ipgre_policy,
138884e54fe0SWilliam Tu 	.priv_size	= sizeof(struct ip_tunnel),
138984e54fe0SWilliam Tu 	.setup		= erspan_setup,
139084e54fe0SWilliam Tu 	.validate	= erspan_validate,
139184e54fe0SWilliam Tu 	.newlink	= ipgre_newlink,
139284e54fe0SWilliam Tu 	.changelink	= ipgre_changelink,
139384e54fe0SWilliam Tu 	.dellink	= ip_tunnel_dellink,
139484e54fe0SWilliam Tu 	.get_size	= ipgre_get_size,
139584e54fe0SWilliam Tu 	.fill_info	= ipgre_fill_info,
139684e54fe0SWilliam Tu 	.get_link_net	= ip_tunnel_get_link_net,
139784e54fe0SWilliam Tu };
139884e54fe0SWilliam Tu 
1399b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1400b2acd1dcSPravin B Shelar 					u8 name_assign_type)
1401b2acd1dcSPravin B Shelar {
1402b2acd1dcSPravin B Shelar 	struct nlattr *tb[IFLA_MAX + 1];
1403b2acd1dcSPravin B Shelar 	struct net_device *dev;
1404106da663SNicolas Dichtel 	LIST_HEAD(list_kill);
1405b2acd1dcSPravin B Shelar 	struct ip_tunnel *t;
1406b2acd1dcSPravin B Shelar 	int err;
1407b2acd1dcSPravin B Shelar 
1408b2acd1dcSPravin B Shelar 	memset(&tb, 0, sizeof(tb));
1409b2acd1dcSPravin B Shelar 
1410b2acd1dcSPravin B Shelar 	dev = rtnl_create_link(net, name, name_assign_type,
1411b2acd1dcSPravin B Shelar 			       &ipgre_tap_ops, tb);
1412b2acd1dcSPravin B Shelar 	if (IS_ERR(dev))
1413b2acd1dcSPravin B Shelar 		return dev;
1414b2acd1dcSPravin B Shelar 
1415b2acd1dcSPravin B Shelar 	/* Configure flow based GRE device. */
1416b2acd1dcSPravin B Shelar 	t = netdev_priv(dev);
1417b2acd1dcSPravin B Shelar 	t->collect_md = true;
1418b2acd1dcSPravin B Shelar 
14197a3f4a18SMatthias Schiffer 	err = ipgre_newlink(net, dev, tb, NULL, NULL);
1420106da663SNicolas Dichtel 	if (err < 0) {
1421106da663SNicolas Dichtel 		free_netdev(dev);
1422106da663SNicolas Dichtel 		return ERR_PTR(err);
1423106da663SNicolas Dichtel 	}
14247e059158SDavid Wragg 
14257e059158SDavid Wragg 	/* openvswitch users expect packet sizes to be unrestricted,
14267e059158SDavid Wragg 	 * so set the largest MTU we can.
14277e059158SDavid Wragg 	 */
14287e059158SDavid Wragg 	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
14297e059158SDavid Wragg 	if (err)
14307e059158SDavid Wragg 		goto out;
14317e059158SDavid Wragg 
1432da6f1da8SNicolas Dichtel 	err = rtnl_configure_link(dev, NULL);
1433da6f1da8SNicolas Dichtel 	if (err < 0)
1434da6f1da8SNicolas Dichtel 		goto out;
1435da6f1da8SNicolas Dichtel 
1436b2acd1dcSPravin B Shelar 	return dev;
1437b2acd1dcSPravin B Shelar out:
1438106da663SNicolas Dichtel 	ip_tunnel_dellink(dev, &list_kill);
1439106da663SNicolas Dichtel 	unregister_netdevice_many(&list_kill);
1440b2acd1dcSPravin B Shelar 	return ERR_PTR(err);
1441b2acd1dcSPravin B Shelar }
1442b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1443b2acd1dcSPravin B Shelar 
1444c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net)
1445c5441932SPravin B Shelar {
14462e15ea39SPravin B Shelar 	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
1447c5441932SPravin B Shelar }
1448c5441932SPravin B Shelar 
1449c5441932SPravin B Shelar static void __net_exit ipgre_tap_exit_net(struct net *net)
1450c5441932SPravin B Shelar {
1451c5441932SPravin B Shelar 	struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id);
14526c742e71SNicolas Dichtel 	ip_tunnel_delete_net(itn, &ipgre_tap_ops);
1453c5441932SPravin B Shelar }
1454c5441932SPravin B Shelar 
1455c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = {
1456c5441932SPravin B Shelar 	.init = ipgre_tap_init_net,
1457c5441932SPravin B Shelar 	.exit = ipgre_tap_exit_net,
1458c5441932SPravin B Shelar 	.id   = &gre_tap_net_id,
1459c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
1460c5441932SPravin B Shelar };
14611da177e4SLinus Torvalds 
146284e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net)
146384e54fe0SWilliam Tu {
146484e54fe0SWilliam Tu 	return ip_tunnel_init_net(net, erspan_net_id,
146584e54fe0SWilliam Tu 				  &erspan_link_ops, "erspan0");
146684e54fe0SWilliam Tu }
146784e54fe0SWilliam Tu 
146884e54fe0SWilliam Tu static void __net_exit erspan_exit_net(struct net *net)
146984e54fe0SWilliam Tu {
147084e54fe0SWilliam Tu 	struct ip_tunnel_net *itn = net_generic(net, erspan_net_id);
147184e54fe0SWilliam Tu 
147284e54fe0SWilliam Tu 	ip_tunnel_delete_net(itn, &erspan_link_ops);
147384e54fe0SWilliam Tu }
147484e54fe0SWilliam Tu 
147584e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = {
147684e54fe0SWilliam Tu 	.init = erspan_init_net,
147784e54fe0SWilliam Tu 	.exit = erspan_exit_net,
147884e54fe0SWilliam Tu 	.id   = &erspan_net_id,
147984e54fe0SWilliam Tu 	.size = sizeof(struct ip_tunnel_net),
148084e54fe0SWilliam Tu };
148184e54fe0SWilliam Tu 
14821da177e4SLinus Torvalds static int __init ipgre_init(void)
14831da177e4SLinus Torvalds {
14841da177e4SLinus Torvalds 	int err;
14851da177e4SLinus Torvalds 
1486058bd4d2SJoe Perches 	pr_info("GRE over IPv4 tunneling driver\n");
14871da177e4SLinus Torvalds 
1488cfb8fbf2SEric W. Biederman 	err = register_pernet_device(&ipgre_net_ops);
148959a4c759SPavel Emelyanov 	if (err < 0)
1490c2892f02SAlexey Dobriyan 		return err;
1491c2892f02SAlexey Dobriyan 
1492c5441932SPravin B Shelar 	err = register_pernet_device(&ipgre_tap_net_ops);
1493c5441932SPravin B Shelar 	if (err < 0)
1494e3d0328cSWilliam Tu 		goto pnet_tap_failed;
1495c5441932SPravin B Shelar 
149684e54fe0SWilliam Tu 	err = register_pernet_device(&erspan_net_ops);
149784e54fe0SWilliam Tu 	if (err < 0)
149884e54fe0SWilliam Tu 		goto pnet_erspan_failed;
149984e54fe0SWilliam Tu 
15009f57c67cSPravin B Shelar 	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
1501c2892f02SAlexey Dobriyan 	if (err < 0) {
1502058bd4d2SJoe Perches 		pr_info("%s: can't add protocol\n", __func__);
1503c2892f02SAlexey Dobriyan 		goto add_proto_failed;
1504c2892f02SAlexey Dobriyan 	}
15057daa0004SPavel Emelyanov 
1506c19e654dSHerbert Xu 	err = rtnl_link_register(&ipgre_link_ops);
1507c19e654dSHerbert Xu 	if (err < 0)
1508c19e654dSHerbert Xu 		goto rtnl_link_failed;
1509c19e654dSHerbert Xu 
1510e1a80002SHerbert Xu 	err = rtnl_link_register(&ipgre_tap_ops);
1511e1a80002SHerbert Xu 	if (err < 0)
1512e1a80002SHerbert Xu 		goto tap_ops_failed;
1513e1a80002SHerbert Xu 
151484e54fe0SWilliam Tu 	err = rtnl_link_register(&erspan_link_ops);
151584e54fe0SWilliam Tu 	if (err < 0)
151684e54fe0SWilliam Tu 		goto erspan_link_failed;
151784e54fe0SWilliam Tu 
1518c5441932SPravin B Shelar 	return 0;
1519c19e654dSHerbert Xu 
152084e54fe0SWilliam Tu erspan_link_failed:
152184e54fe0SWilliam Tu 	rtnl_link_unregister(&ipgre_tap_ops);
1522e1a80002SHerbert Xu tap_ops_failed:
1523e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
1524c19e654dSHerbert Xu rtnl_link_failed:
15259f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1526c2892f02SAlexey Dobriyan add_proto_failed:
152784e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
152884e54fe0SWilliam Tu pnet_erspan_failed:
1529c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1530e3d0328cSWilliam Tu pnet_tap_failed:
1531c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
1532c5441932SPravin B Shelar 	return err;
15331da177e4SLinus Torvalds }
15341da177e4SLinus Torvalds 
1535db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void)
15361da177e4SLinus Torvalds {
1537e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_tap_ops);
1538c19e654dSHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
153984e54fe0SWilliam Tu 	rtnl_link_unregister(&erspan_link_ops);
15409f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1541c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1542c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
154384e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
15441da177e4SLinus Torvalds }
15451da177e4SLinus Torvalds 
15461da177e4SLinus Torvalds module_init(ipgre_init);
15471da177e4SLinus Torvalds module_exit(ipgre_fini);
15481da177e4SLinus Torvalds MODULE_LICENSE("GPL");
15494d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre");
15504d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap");
155184e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan");
15528909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0");
1553c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0");
155484e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0");
1555