11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Linux NET3: GRE over IP protocol decoder. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru) 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 71da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 81da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 91da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds 13afd46503SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14afd46503SJoe Perches 154fc268d2SRandy Dunlap #include <linux/capability.h> 161da177e4SLinus Torvalds #include <linux/module.h> 171da177e4SLinus Torvalds #include <linux/types.h> 181da177e4SLinus Torvalds #include <linux/kernel.h> 195a0e3ad6STejun Heo #include <linux/slab.h> 201da177e4SLinus Torvalds #include <asm/uaccess.h> 211da177e4SLinus Torvalds #include <linux/skbuff.h> 221da177e4SLinus Torvalds #include <linux/netdevice.h> 231da177e4SLinus Torvalds #include <linux/in.h> 241da177e4SLinus Torvalds #include <linux/tcp.h> 251da177e4SLinus Torvalds #include <linux/udp.h> 261da177e4SLinus Torvalds #include <linux/if_arp.h> 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 116f99189b1SEric Dumazet static int ipgre_net_id __read_mostly; 117c5441932SPravin B Shelar static 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; 1411da177e4SLinus Torvalds struct ip_tunnel *t; 142d2083287Sstephen hemminger 1431da177e4SLinus Torvalds switch (type) { 1441da177e4SLinus Torvalds default: 1451da177e4SLinus Torvalds case ICMP_PARAMETERPROB: 1469f57c67cSPravin B Shelar return; 1471da177e4SLinus Torvalds 1481da177e4SLinus Torvalds case ICMP_DEST_UNREACH: 1491da177e4SLinus Torvalds switch (code) { 1501da177e4SLinus Torvalds case ICMP_SR_FAILED: 1511da177e4SLinus Torvalds case ICMP_PORT_UNREACH: 1521da177e4SLinus Torvalds /* Impossible event. */ 1539f57c67cSPravin B Shelar return; 1541da177e4SLinus Torvalds default: 1551da177e4SLinus Torvalds /* All others are translated to HOST_UNREACH. 1561da177e4SLinus Torvalds rfc2003 contains "deep thoughts" about NET_UNREACH, 1571da177e4SLinus Torvalds I believe they are just ether pollution. --ANK 1581da177e4SLinus Torvalds */ 1591da177e4SLinus Torvalds break; 1601da177e4SLinus Torvalds } 1611da177e4SLinus Torvalds break; 1629f57c67cSPravin B Shelar 1631da177e4SLinus Torvalds case ICMP_TIME_EXCEEDED: 1641da177e4SLinus Torvalds if (code != ICMP_EXC_TTL) 1659f57c67cSPravin B Shelar return; 1661da177e4SLinus Torvalds break; 16755be7a9cSDavid S. Miller 16855be7a9cSDavid S. Miller case ICMP_REDIRECT: 16955be7a9cSDavid S. Miller break; 1701da177e4SLinus Torvalds } 1711da177e4SLinus Torvalds 172bda7bb46SPravin B Shelar if (tpi->proto == htons(ETH_P_TEB)) 173c5441932SPravin B Shelar itn = net_generic(net, gre_tap_net_id); 174c5441932SPravin B Shelar else 175c5441932SPravin B Shelar itn = net_generic(net, ipgre_net_id); 176c5441932SPravin B Shelar 177c0c0c50fSDuan Jiong iph = (const struct iphdr *)(icmp_hdr(skb) + 1); 178bda7bb46SPravin B Shelar t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 179bda7bb46SPravin B Shelar iph->daddr, iph->saddr, tpi->key); 180d2083287Sstephen hemminger 18151456b29SIan Morris if (!t) 1829f57c67cSPravin B Shelar return; 18336393395SDavid S. Miller 18436393395SDavid S. Miller if (t->parms.iph.daddr == 0 || 185f97c1e0cSJoe Perches ipv4_is_multicast(t->parms.iph.daddr)) 1869f57c67cSPravin B Shelar return; 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 1899f57c67cSPravin B Shelar return; 1901da177e4SLinus Torvalds 191da6185d8SWei Yongjun if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) 1921da177e4SLinus Torvalds t->err_count++; 1931da177e4SLinus Torvalds else 1941da177e4SLinus Torvalds t->err_count = 1; 1951da177e4SLinus Torvalds t->err_time = jiffies; 1969f57c67cSPravin B Shelar } 1979f57c67cSPravin B Shelar 1989f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info) 1999f57c67cSPravin B Shelar { 2009f57c67cSPravin B Shelar /* All the routers (except for Linux) return only 2019f57c67cSPravin B Shelar * 8 bytes of packet payload. It means, that precise relaying of 2029f57c67cSPravin B Shelar * ICMP in the real Internet is absolutely infeasible. 2039f57c67cSPravin B Shelar * 2049f57c67cSPravin B Shelar * Moreover, Cisco "wise men" put GRE key to the third word 2059f57c67cSPravin B Shelar * in GRE header. It makes impossible maintaining even soft 2069f57c67cSPravin B Shelar * state for keyed 2079f57c67cSPravin B Shelar * GRE tunnels with enabled checksum. Tell them "thank you". 2089f57c67cSPravin B Shelar * 2099f57c67cSPravin B Shelar * Well, I wonder, rfc1812 was written by Cisco employee, 2109f57c67cSPravin B Shelar * what the hell these idiots break standards established 2119f57c67cSPravin B Shelar * by themselves??? 2129f57c67cSPravin B Shelar */ 2139f57c67cSPravin B Shelar 214*e582615aSEric Dumazet const struct iphdr *iph = (struct iphdr *)skb->data; 2159f57c67cSPravin B Shelar const int type = icmp_hdr(skb)->type; 2169f57c67cSPravin B Shelar const int code = icmp_hdr(skb)->code; 2179f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 2189f57c67cSPravin B Shelar bool csum_err = false; 2199f57c67cSPravin B Shelar 220*e582615aSEric Dumazet if (gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 221*e582615aSEric Dumazet iph->ihl * 4) < 0) { 2229f57c67cSPravin B Shelar if (!csum_err) /* ignore csum errors. */ 2239f57c67cSPravin B Shelar return; 2249f57c67cSPravin B Shelar } 2259f57c67cSPravin B Shelar 2269f57c67cSPravin B Shelar if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 2279f57c67cSPravin B Shelar ipv4_update_pmtu(skb, dev_net(skb->dev), info, 2289f57c67cSPravin B Shelar skb->dev->ifindex, 0, IPPROTO_GRE, 0); 2299f57c67cSPravin B Shelar return; 2309f57c67cSPravin B Shelar } 2319f57c67cSPravin B Shelar if (type == ICMP_REDIRECT) { 2329f57c67cSPravin B Shelar ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0, 2339f57c67cSPravin B Shelar IPPROTO_GRE, 0); 2349f57c67cSPravin B Shelar return; 2359f57c67cSPravin B Shelar } 2369f57c67cSPravin B Shelar 2379f57c67cSPravin B Shelar ipgre_err(skb, info, &tpi); 2381da177e4SLinus Torvalds } 2391da177e4SLinus Torvalds 2402e15ea39SPravin B Shelar static __be64 key_to_tunnel_id(__be32 key) 2412e15ea39SPravin B Shelar { 2422e15ea39SPravin B Shelar #ifdef __BIG_ENDIAN 2432e15ea39SPravin B Shelar return (__force __be64)((__force u32)key); 2442e15ea39SPravin B Shelar #else 2452e15ea39SPravin B Shelar return (__force __be64)((__force u64)key << 32); 2462e15ea39SPravin B Shelar #endif 2472e15ea39SPravin B Shelar } 2482e15ea39SPravin B Shelar 2492e15ea39SPravin B Shelar /* Returns the least-significant 32 bits of a __be64. */ 2502e15ea39SPravin B Shelar static __be32 tunnel_id_to_key(__be64 x) 2512e15ea39SPravin B Shelar { 2522e15ea39SPravin B Shelar #ifdef __BIG_ENDIAN 2532e15ea39SPravin B Shelar return (__force __be32)x; 2542e15ea39SPravin B Shelar #else 2552e15ea39SPravin B Shelar return (__force __be32)((__force u64)x >> 32); 2562e15ea39SPravin B Shelar #endif 2572e15ea39SPravin B Shelar } 2582e15ea39SPravin B Shelar 259125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 260125372faSJiri Benc struct ip_tunnel_net *itn, int hdr_len, bool raw_proto) 2611da177e4SLinus Torvalds { 2622e15ea39SPravin B Shelar struct metadata_dst *tun_dst = NULL; 263b71d1d42SEric Dumazet const struct iphdr *iph; 2641da177e4SLinus Torvalds struct ip_tunnel *tunnel; 2651da177e4SLinus Torvalds 266eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb); 267bda7bb46SPravin B Shelar tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 268bda7bb46SPravin B Shelar iph->saddr, iph->daddr, tpi->key); 2691da177e4SLinus Torvalds 270d2083287Sstephen hemminger if (tunnel) { 271125372faSJiri Benc if (__iptunnel_pull_header(skb, hdr_len, tpi->proto, 272125372faSJiri Benc raw_proto, false) < 0) 273244a797bSJiri Benc goto drop; 274244a797bSJiri Benc 275e271c7b4SJiri Benc if (tunnel->dev->type != ARPHRD_NONE) 2760e3da5bbSTimo Teräs skb_pop_mac_header(skb); 277e271c7b4SJiri Benc else 278e271c7b4SJiri Benc skb_reset_mac_header(skb); 2792e15ea39SPravin B Shelar if (tunnel->collect_md) { 280c29a70d2SPravin B Shelar __be16 flags; 281c29a70d2SPravin B Shelar __be64 tun_id; 2822e15ea39SPravin B Shelar 283c29a70d2SPravin B Shelar flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); 284c29a70d2SPravin B Shelar tun_id = key_to_tunnel_id(tpi->key); 285c29a70d2SPravin B Shelar tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0); 2862e15ea39SPravin B Shelar if (!tun_dst) 2872e15ea39SPravin B Shelar return PACKET_REJECT; 2882e15ea39SPravin B Shelar } 2892e15ea39SPravin B Shelar 2902e15ea39SPravin B Shelar ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 291bda7bb46SPravin B Shelar return PACKET_RCVD; 2921da177e4SLinus Torvalds } 293125372faSJiri Benc return PACKET_NEXT; 294244a797bSJiri Benc 295244a797bSJiri Benc drop: 296244a797bSJiri Benc kfree_skb(skb); 297244a797bSJiri Benc return PACKET_RCVD; 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds 300125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 301125372faSJiri Benc int hdr_len) 302125372faSJiri Benc { 303125372faSJiri Benc struct net *net = dev_net(skb->dev); 304125372faSJiri Benc struct ip_tunnel_net *itn; 305125372faSJiri Benc int res; 306125372faSJiri Benc 307125372faSJiri Benc if (tpi->proto == htons(ETH_P_TEB)) 308125372faSJiri Benc itn = net_generic(net, gre_tap_net_id); 309125372faSJiri Benc else 310125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 311125372faSJiri Benc 312125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, false); 313125372faSJiri Benc if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) { 314125372faSJiri Benc /* ipgre tunnels in collect metadata mode should receive 315125372faSJiri Benc * also ETH_P_TEB traffic. 316125372faSJiri Benc */ 317125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 318125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, true); 319125372faSJiri Benc } 320125372faSJiri Benc return res; 321125372faSJiri Benc } 322125372faSJiri Benc 3239f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb) 3249f57c67cSPravin B Shelar { 3259f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 3269f57c67cSPravin B Shelar bool csum_err = false; 32795f5c64cSTom Herbert int hdr_len; 3289f57c67cSPravin B Shelar 3299f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 3309f57c67cSPravin B Shelar if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { 3319f57c67cSPravin B Shelar /* Looped back packet, drop it! */ 3329f57c67cSPravin B Shelar if (rt_is_output_route(skb_rtable(skb))) 3339f57c67cSPravin B Shelar goto drop; 3349f57c67cSPravin B Shelar } 3359f57c67cSPravin B Shelar #endif 3369f57c67cSPravin B Shelar 337*e582615aSEric Dumazet hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0); 338f132ae7cSJiri Benc if (hdr_len < 0) 33995f5c64cSTom Herbert goto drop; 34095f5c64cSTom Herbert 341244a797bSJiri Benc if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) 3429f57c67cSPravin B Shelar return 0; 3439f57c67cSPravin B Shelar 3449f57c67cSPravin B Shelar icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 3459f57c67cSPravin B Shelar drop: 3469f57c67cSPravin B Shelar kfree_skb(skb); 3479f57c67cSPravin B Shelar return 0; 3489f57c67cSPravin B Shelar } 3499f57c67cSPravin B Shelar 350c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, 351c5441932SPravin B Shelar const struct iphdr *tnl_params, 352c5441932SPravin B Shelar __be16 proto) 353c5441932SPravin B Shelar { 354c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 355c5441932SPravin B Shelar 356c5441932SPravin B Shelar if (tunnel->parms.o_flags & TUNNEL_SEQ) 357c5441932SPravin B Shelar tunnel->o_seqno++; 358cef401deSEric Dumazet 359c5441932SPravin B Shelar /* Push GRE header. */ 360182a352dSTom Herbert gre_build_header(skb, tunnel->tun_hlen, 361182a352dSTom Herbert tunnel->parms.o_flags, proto, tunnel->parms.o_key, 362182a352dSTom Herbert htonl(tunnel->o_seqno)); 3631da177e4SLinus Torvalds 3642e15ea39SPravin B Shelar skb_set_inner_protocol(skb, proto); 365bf3d6a8fSNicolas Dichtel ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); 3661da177e4SLinus Torvalds } 3671da177e4SLinus Torvalds 368aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum) 369b2acd1dcSPravin B Shelar { 3706fa79666SEdward Cree return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); 371b2acd1dcSPravin B Shelar } 372b2acd1dcSPravin B Shelar 373fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb, 374fc4099f1SPravin B Shelar struct net_device *dev, 375fc4099f1SPravin B Shelar struct flowi4 *fl, 376fc4099f1SPravin B Shelar const struct ip_tunnel_key *key) 377fc4099f1SPravin B Shelar { 378fc4099f1SPravin B Shelar struct net *net = dev_net(dev); 379fc4099f1SPravin B Shelar 380fc4099f1SPravin B Shelar memset(fl, 0, sizeof(*fl)); 381fc4099f1SPravin B Shelar fl->daddr = key->u.ipv4.dst; 382fc4099f1SPravin B Shelar fl->saddr = key->u.ipv4.src; 383fc4099f1SPravin B Shelar fl->flowi4_tos = RT_TOS(key->tos); 384fc4099f1SPravin B Shelar fl->flowi4_mark = skb->mark; 385fc4099f1SPravin B Shelar fl->flowi4_proto = IPPROTO_GRE; 386fc4099f1SPravin B Shelar 387fc4099f1SPravin B Shelar return ip_route_output_key(net, fl); 388fc4099f1SPravin B Shelar } 389fc4099f1SPravin B Shelar 3902090714eSJiri Benc static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev, 3912090714eSJiri Benc __be16 proto) 3922e15ea39SPravin B Shelar { 3932e15ea39SPravin B Shelar struct ip_tunnel_info *tun_info; 3942e15ea39SPravin B Shelar const struct ip_tunnel_key *key; 395db3c6139SDaniel Borkmann struct rtable *rt = NULL; 3962e15ea39SPravin B Shelar struct flowi4 fl; 3972e15ea39SPravin B Shelar int min_headroom; 3982e15ea39SPravin B Shelar int tunnel_hlen; 3992e15ea39SPravin B Shelar __be16 df, flags; 400db3c6139SDaniel Borkmann bool use_cache; 4012e15ea39SPravin B Shelar int err; 4022e15ea39SPravin B Shelar 40361adedf3SJiri Benc tun_info = skb_tunnel_info(skb); 4047f9562a1SJiri Benc if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 4057f9562a1SJiri Benc ip_tunnel_info_af(tun_info) != AF_INET)) 4062e15ea39SPravin B Shelar goto err_free_skb; 4072e15ea39SPravin B Shelar 4082e15ea39SPravin B Shelar key = &tun_info->key; 409db3c6139SDaniel Borkmann use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); 410db3c6139SDaniel Borkmann if (use_cache) 411db3c6139SDaniel Borkmann rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl.saddr); 4123c1cb4d2SPaolo Abeni if (!rt) { 413fc4099f1SPravin B Shelar rt = gre_get_rt(skb, dev, &fl, key); 4142e15ea39SPravin B Shelar if (IS_ERR(rt)) 4152e15ea39SPravin B Shelar goto err_free_skb; 416db3c6139SDaniel Borkmann if (use_cache) 4173c1cb4d2SPaolo Abeni dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, 4183c1cb4d2SPaolo Abeni fl.saddr); 4193c1cb4d2SPaolo Abeni } 4202e15ea39SPravin B Shelar 42195f5c64cSTom Herbert tunnel_hlen = gre_calc_hlen(key->tun_flags); 4222e15ea39SPravin B Shelar 4232e15ea39SPravin B Shelar min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len 4242e15ea39SPravin B Shelar + tunnel_hlen + sizeof(struct iphdr); 4252e15ea39SPravin B Shelar if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { 4262e15ea39SPravin B Shelar int head_delta = SKB_DATA_ALIGN(min_headroom - 4272e15ea39SPravin B Shelar skb_headroom(skb) + 4282e15ea39SPravin B Shelar 16); 4292e15ea39SPravin B Shelar err = pskb_expand_head(skb, max_t(int, head_delta, 0), 4302e15ea39SPravin B Shelar 0, GFP_ATOMIC); 4312e15ea39SPravin B Shelar if (unlikely(err)) 4322e15ea39SPravin B Shelar goto err_free_rt; 4332e15ea39SPravin B Shelar } 4342e15ea39SPravin B Shelar 4352e15ea39SPravin B Shelar /* Push Tunnel header. */ 436aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM))) 4372e15ea39SPravin B Shelar goto err_free_rt; 4382e15ea39SPravin B Shelar 4392e15ea39SPravin B Shelar flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); 440cba65321SDavid S. Miller gre_build_header(skb, tunnel_hlen, flags, proto, 4412e15ea39SPravin B Shelar tunnel_id_to_key(tun_info->key.tun_id), 0); 4422e15ea39SPravin B Shelar 4432e15ea39SPravin B Shelar df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; 444039f5062SPravin B Shelar 445039f5062SPravin B Shelar iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, 4467c383fb2SJiri Benc key->tos, key->ttl, df, false); 4472e15ea39SPravin B Shelar return; 4482e15ea39SPravin B Shelar 4492e15ea39SPravin B Shelar err_free_rt: 4502e15ea39SPravin B Shelar ip_rt_put(rt); 4512e15ea39SPravin B Shelar err_free_skb: 4522e15ea39SPravin B Shelar kfree_skb(skb); 4532e15ea39SPravin B Shelar dev->stats.tx_dropped++; 4542e15ea39SPravin B Shelar } 4552e15ea39SPravin B Shelar 456fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) 457fc4099f1SPravin B Shelar { 458fc4099f1SPravin B Shelar struct ip_tunnel_info *info = skb_tunnel_info(skb); 459fc4099f1SPravin B Shelar struct rtable *rt; 460fc4099f1SPravin B Shelar struct flowi4 fl4; 461fc4099f1SPravin B Shelar 462fc4099f1SPravin B Shelar if (ip_tunnel_info_af(info) != AF_INET) 463fc4099f1SPravin B Shelar return -EINVAL; 464fc4099f1SPravin B Shelar 465fc4099f1SPravin B Shelar rt = gre_get_rt(skb, dev, &fl4, &info->key); 466fc4099f1SPravin B Shelar if (IS_ERR(rt)) 467fc4099f1SPravin B Shelar return PTR_ERR(rt); 468fc4099f1SPravin B Shelar 469fc4099f1SPravin B Shelar ip_rt_put(rt); 470fc4099f1SPravin B Shelar info->key.u.ipv4.src = fl4.saddr; 471fc4099f1SPravin B Shelar return 0; 472fc4099f1SPravin B Shelar } 473fc4099f1SPravin B Shelar 474c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb, 475c5441932SPravin B Shelar struct net_device *dev) 476ee34c1ebSMichal Schmidt { 477c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 478c5441932SPravin B Shelar const struct iphdr *tnl_params; 479ee34c1ebSMichal Schmidt 4802e15ea39SPravin B Shelar if (tunnel->collect_md) { 4812090714eSJiri Benc gre_fb_xmit(skb, dev, skb->protocol); 4822e15ea39SPravin B Shelar return NETDEV_TX_OK; 4832e15ea39SPravin B Shelar } 4842e15ea39SPravin B Shelar 485c5441932SPravin B Shelar if (dev->header_ops) { 486c5441932SPravin B Shelar /* Need space for new headers */ 487c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom - 4882bac7cb3SChen Gang (tunnel->hlen + sizeof(struct iphdr)))) 489c5441932SPravin B Shelar goto free_skb; 490ee34c1ebSMichal Schmidt 491c5441932SPravin B Shelar tnl_params = (const struct iphdr *)skb->data; 492cbb1e85fSDavid S. Miller 493c5441932SPravin B Shelar /* Pull skb since ip_tunnel_xmit() needs skb->data pointing 494c5441932SPravin B Shelar * to gre header. 495c5441932SPravin B Shelar */ 496c5441932SPravin B Shelar skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); 4978a0033a9STimo Teräs skb_reset_mac_header(skb); 498c5441932SPravin B Shelar } else { 499c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 500c5441932SPravin B Shelar goto free_skb; 501c5441932SPravin B Shelar 502c5441932SPravin B Shelar tnl_params = &tunnel->parms.iph; 503ee34c1ebSMichal Schmidt } 504e1a80002SHerbert Xu 505aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 506aed069dfSAlexander Duyck goto free_skb; 5078a0033a9STimo Teräs 508c5441932SPravin B Shelar __gre_xmit(skb, dev, tnl_params, skb->protocol); 509c5441932SPravin B Shelar return NETDEV_TX_OK; 510c5441932SPravin B Shelar 511c5441932SPravin B Shelar free_skb: 5123acfa1e7SEric Dumazet kfree_skb(skb); 513c5441932SPravin B Shelar dev->stats.tx_dropped++; 514c5441932SPravin B Shelar return NETDEV_TX_OK; 515ee34c1ebSMichal Schmidt } 516ee34c1ebSMichal Schmidt 517c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, 518c5441932SPravin B Shelar struct net_device *dev) 519c5441932SPravin B Shelar { 520c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 521ee34c1ebSMichal Schmidt 5222e15ea39SPravin B Shelar if (tunnel->collect_md) { 5232090714eSJiri Benc gre_fb_xmit(skb, dev, htons(ETH_P_TEB)); 5242e15ea39SPravin B Shelar return NETDEV_TX_OK; 5252e15ea39SPravin B Shelar } 5262e15ea39SPravin B Shelar 527aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 528aed069dfSAlexander Duyck goto free_skb; 529ee34c1ebSMichal Schmidt 530c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 531c5441932SPravin B Shelar goto free_skb; 53242aa9162SHerbert Xu 533c5441932SPravin B Shelar __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB)); 534c5441932SPravin B Shelar return NETDEV_TX_OK; 535c5441932SPravin B Shelar 536c5441932SPravin B Shelar free_skb: 5373acfa1e7SEric Dumazet kfree_skb(skb); 538c5441932SPravin B Shelar dev->stats.tx_dropped++; 539c5441932SPravin B Shelar return NETDEV_TX_OK; 54068c33163SPravin B Shelar } 541ee34c1ebSMichal Schmidt 542c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev, 543c5441932SPravin B Shelar struct ifreq *ifr, int cmd) 5441da177e4SLinus Torvalds { 5454565e991STom Herbert int err; 5461da177e4SLinus Torvalds struct ip_tunnel_parm p; 5471da177e4SLinus Torvalds 5481da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 549c5441932SPravin B Shelar return -EFAULT; 5506c734fb8SCong Wang if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { 5511da177e4SLinus Torvalds if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || 5521da177e4SLinus Torvalds p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) || 5536c734fb8SCong Wang ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) 5541da177e4SLinus Torvalds return -EINVAL; 555c5441932SPravin B Shelar } 556c5441932SPravin B Shelar p.i_flags = gre_flags_to_tnl_flags(p.i_flags); 557c5441932SPravin B Shelar p.o_flags = gre_flags_to_tnl_flags(p.o_flags); 558c5441932SPravin B Shelar 559c5441932SPravin B Shelar err = ip_tunnel_ioctl(dev, &p, cmd); 560c5441932SPravin B Shelar if (err) 561c5441932SPravin B Shelar return err; 562c5441932SPravin B Shelar 56395f5c64cSTom Herbert p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags); 56495f5c64cSTom Herbert p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags); 565c5441932SPravin B Shelar 566c5441932SPravin B Shelar if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) 567c5441932SPravin B Shelar return -EFAULT; 5681da177e4SLinus Torvalds return 0; 5691da177e4SLinus Torvalds } 5701da177e4SLinus Torvalds 5711da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-) 5721da177e4SLinus Torvalds It allows to construct virtual multiprotocol broadcast "LAN" 5731da177e4SLinus Torvalds over the Internet, provided multicast routing is tuned. 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds 5761da177e4SLinus Torvalds I have no idea was this bicycle invented before me, 5771da177e4SLinus Torvalds so that I had to set ARPHRD_IPGRE to a random value. 5781da177e4SLinus Torvalds I have an impression, that Cisco could make something similar, 5791da177e4SLinus Torvalds but this feature is apparently missing in IOS<=11.2(8). 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks 5821da177e4SLinus Torvalds with broadcast 224.66.66.66. If you have access to mbone, play with me :-) 5831da177e4SLinus Torvalds 5841da177e4SLinus Torvalds ping -t 255 224.66.66.66 5851da177e4SLinus Torvalds 5861da177e4SLinus Torvalds If nobody answers, mbone does not work. 5871da177e4SLinus Torvalds 5881da177e4SLinus Torvalds ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 5891da177e4SLinus Torvalds ip addr add 10.66.66.<somewhat>/24 dev Universe 5901da177e4SLinus Torvalds ifconfig Universe up 5911da177e4SLinus Torvalds ifconfig Universe add fe80::<Your_real_addr>/10 5921da177e4SLinus Torvalds ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 5931da177e4SLinus Torvalds ftp 10.66.66.66 5941da177e4SLinus Torvalds ... 5951da177e4SLinus Torvalds ftp fec0:6666:6666::193.233.7.65 5961da177e4SLinus Torvalds ... 5971da177e4SLinus Torvalds */ 5983b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev, 5993b04dddeSStephen Hemminger unsigned short type, 6001507850bSEric Dumazet const void *daddr, const void *saddr, unsigned int len) 6011da177e4SLinus Torvalds { 6022941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 603c5441932SPravin B Shelar struct iphdr *iph; 604c5441932SPravin B Shelar struct gre_base_hdr *greh; 605c5441932SPravin B Shelar 606c5441932SPravin B Shelar iph = (struct iphdr *)skb_push(skb, t->hlen + sizeof(*iph)); 607c5441932SPravin B Shelar greh = (struct gre_base_hdr *)(iph+1); 60895f5c64cSTom Herbert greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags); 609c5441932SPravin B Shelar greh->protocol = htons(type); 6101da177e4SLinus Torvalds 6111da177e4SLinus Torvalds memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); 6121da177e4SLinus Torvalds 613c5441932SPravin B Shelar /* Set the source hardware address. */ 6141da177e4SLinus Torvalds if (saddr) 6151da177e4SLinus Torvalds memcpy(&iph->saddr, saddr, 4); 6166d55cb91STimo Teräs if (daddr) 6171da177e4SLinus Torvalds memcpy(&iph->daddr, daddr, 4); 6186d55cb91STimo Teräs if (iph->daddr) 61977a482bdSTimo Teräs return t->hlen + sizeof(*iph); 6201da177e4SLinus Torvalds 621c5441932SPravin B Shelar return -(t->hlen + sizeof(*iph)); 6221da177e4SLinus Torvalds } 6231da177e4SLinus Torvalds 6246a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) 6256a5f44d7STimo Teras { 626b71d1d42SEric Dumazet const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); 6276a5f44d7STimo Teras memcpy(haddr, &iph->saddr, 4); 6286a5f44d7STimo Teras return 4; 6296a5f44d7STimo Teras } 6306a5f44d7STimo Teras 6313b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = { 6323b04dddeSStephen Hemminger .create = ipgre_header, 6336a5f44d7STimo Teras .parse = ipgre_header_parse, 6343b04dddeSStephen Hemminger }; 6353b04dddeSStephen Hemminger 6366a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST 6371da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev) 6381da177e4SLinus Torvalds { 6392941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 6401da177e4SLinus Torvalds 641f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr)) { 642cbb1e85fSDavid S. Miller struct flowi4 fl4; 643cbb1e85fSDavid S. Miller struct rtable *rt; 644cbb1e85fSDavid S. Miller 645b57708adSNicolas Dichtel rt = ip_route_output_gre(t->net, &fl4, 64678fbfd8aSDavid S. Miller t->parms.iph.daddr, 64778fbfd8aSDavid S. Miller t->parms.iph.saddr, 64878fbfd8aSDavid S. Miller t->parms.o_key, 64978fbfd8aSDavid S. Miller RT_TOS(t->parms.iph.tos), 65078fbfd8aSDavid S. Miller t->parms.link); 651b23dd4feSDavid S. Miller if (IS_ERR(rt)) 6521da177e4SLinus Torvalds return -EADDRNOTAVAIL; 653d8d1f30bSChangli Gao dev = rt->dst.dev; 6541da177e4SLinus Torvalds ip_rt_put(rt); 65551456b29SIan Morris if (!__in_dev_get_rtnl(dev)) 6561da177e4SLinus Torvalds return -EADDRNOTAVAIL; 6571da177e4SLinus Torvalds t->mlink = dev->ifindex; 658e5ed6399SHerbert Xu ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); 6591da177e4SLinus Torvalds } 6601da177e4SLinus Torvalds return 0; 6611da177e4SLinus Torvalds } 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev) 6641da177e4SLinus Torvalds { 6652941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 666b8c26a33SStephen Hemminger 667f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) { 6687fee0ca2SDenis V. Lunev struct in_device *in_dev; 669b57708adSNicolas Dichtel in_dev = inetdev_by_index(t->net, t->mlink); 6708723e1b4SEric Dumazet if (in_dev) 6711da177e4SLinus Torvalds ip_mc_dec_group(in_dev, t->parms.iph.daddr); 6721da177e4SLinus Torvalds } 6731da177e4SLinus Torvalds return 0; 6741da177e4SLinus Torvalds } 6751da177e4SLinus Torvalds #endif 6761da177e4SLinus Torvalds 677b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = { 678b8c26a33SStephen Hemminger .ndo_init = ipgre_tunnel_init, 679c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 680b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST 681b8c26a33SStephen Hemminger .ndo_open = ipgre_open, 682b8c26a33SStephen Hemminger .ndo_stop = ipgre_close, 683b8c26a33SStephen Hemminger #endif 684c5441932SPravin B Shelar .ndo_start_xmit = ipgre_xmit, 685b8c26a33SStephen Hemminger .ndo_do_ioctl = ipgre_tunnel_ioctl, 686c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 687c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 6881e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 689b8c26a33SStephen Hemminger }; 690b8c26a33SStephen Hemminger 6916b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG | \ 6926b78f16eSEric Dumazet NETIF_F_FRAGLIST | \ 6936b78f16eSEric Dumazet NETIF_F_HIGHDMA | \ 6946b78f16eSEric Dumazet NETIF_F_HW_CSUM) 6956b78f16eSEric Dumazet 6961da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev) 6971da177e4SLinus Torvalds { 698b8c26a33SStephen Hemminger dev->netdev_ops = &ipgre_netdev_ops; 6995a455275SNicolas Dichtel dev->type = ARPHRD_IPGRE; 700c5441932SPravin B Shelar ip_tunnel_setup(dev, ipgre_net_id); 701c5441932SPravin B Shelar } 7021da177e4SLinus Torvalds 703c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev) 704c5441932SPravin B Shelar { 705c5441932SPravin B Shelar struct ip_tunnel *tunnel; 7064565e991STom Herbert int t_hlen; 707c5441932SPravin B Shelar 708c5441932SPravin B Shelar tunnel = netdev_priv(dev); 70995f5c64cSTom Herbert tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 710c5441932SPravin B Shelar tunnel->parms.iph.protocol = IPPROTO_GRE; 711c5441932SPravin B Shelar 7124565e991STom Herbert tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; 7134565e991STom Herbert 7144565e991STom Herbert t_hlen = tunnel->hlen + sizeof(struct iphdr); 7154565e991STom Herbert 7164565e991STom Herbert dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; 7174565e991STom Herbert dev->mtu = ETH_DATA_LEN - t_hlen - 4; 7186b78f16eSEric Dumazet 719b57708adSNicolas Dichtel dev->features |= GRE_FEATURES; 7206b78f16eSEric Dumazet dev->hw_features |= GRE_FEATURES; 721c5441932SPravin B Shelar 722c5441932SPravin B Shelar if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 723a0ca153fSAlexander Duyck /* TCP offload with GRE SEQ is not supported, nor 724a0ca153fSAlexander Duyck * can we support 2 levels of outer headers requiring 725a0ca153fSAlexander Duyck * an update. 726a0ca153fSAlexander Duyck */ 727a0ca153fSAlexander Duyck if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || 728a0ca153fSAlexander Duyck (tunnel->encap.type == TUNNEL_ENCAP_NONE)) { 729c5441932SPravin B Shelar dev->features |= NETIF_F_GSO_SOFTWARE; 730c5441932SPravin B Shelar dev->hw_features |= NETIF_F_GSO_SOFTWARE; 731a0ca153fSAlexander Duyck } 732a0ca153fSAlexander Duyck 733c5441932SPravin B Shelar /* Can use a lockless transmit, unless we generate 734c5441932SPravin B Shelar * output sequences 735c5441932SPravin B Shelar */ 736c5441932SPravin B Shelar dev->features |= NETIF_F_LLTX; 737c5441932SPravin B Shelar } 7381da177e4SLinus Torvalds } 7391da177e4SLinus Torvalds 7401da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev) 7411da177e4SLinus Torvalds { 742c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 743c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 7441da177e4SLinus Torvalds 745c5441932SPravin B Shelar __gre_tunnel_init(dev); 7461da177e4SLinus Torvalds 747c5441932SPravin B Shelar memcpy(dev->dev_addr, &iph->saddr, 4); 748c5441932SPravin B Shelar memcpy(dev->broadcast, &iph->daddr, 4); 7491da177e4SLinus Torvalds 750c5441932SPravin B Shelar dev->flags = IFF_NOARP; 75102875878SEric Dumazet netif_keep_dst(dev); 752c5441932SPravin B Shelar dev->addr_len = 4; 7531da177e4SLinus Torvalds 754a64b04d8SJiri Benc if (iph->daddr && !tunnel->collect_md) { 7551da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST 756f97c1e0cSJoe Perches if (ipv4_is_multicast(iph->daddr)) { 7571da177e4SLinus Torvalds if (!iph->saddr) 7581da177e4SLinus Torvalds return -EINVAL; 7591da177e4SLinus Torvalds dev->flags = IFF_BROADCAST; 7603b04dddeSStephen Hemminger dev->header_ops = &ipgre_header_ops; 7611da177e4SLinus Torvalds } 7621da177e4SLinus Torvalds #endif 763a64b04d8SJiri Benc } else if (!tunnel->collect_md) { 7646a5f44d7STimo Teras dev->header_ops = &ipgre_header_ops; 765a64b04d8SJiri Benc } 7661da177e4SLinus Torvalds 767c5441932SPravin B Shelar return ip_tunnel_init(dev); 76860769a5dSEric Dumazet } 76960769a5dSEric Dumazet 7709f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = { 7719f57c67cSPravin B Shelar .handler = gre_rcv, 7729f57c67cSPravin B Shelar .err_handler = gre_err, 7731da177e4SLinus Torvalds }; 7741da177e4SLinus Torvalds 7752c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net) 77659a4c759SPavel Emelyanov { 777c5441932SPravin B Shelar return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); 77859a4c759SPavel Emelyanov } 77959a4c759SPavel Emelyanov 7802c8c1e72SAlexey Dobriyan static void __net_exit ipgre_exit_net(struct net *net) 78159a4c759SPavel Emelyanov { 782c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id); 7836c742e71SNicolas Dichtel ip_tunnel_delete_net(itn, &ipgre_link_ops); 78459a4c759SPavel Emelyanov } 78559a4c759SPavel Emelyanov 78659a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = { 78759a4c759SPavel Emelyanov .init = ipgre_init_net, 78859a4c759SPavel Emelyanov .exit = ipgre_exit_net, 789cfb8fbf2SEric W. Biederman .id = &ipgre_net_id, 790c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 79159a4c759SPavel Emelyanov }; 7921da177e4SLinus Torvalds 793c19e654dSHerbert Xu static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) 794c19e654dSHerbert Xu { 795c19e654dSHerbert Xu __be16 flags; 796c19e654dSHerbert Xu 797c19e654dSHerbert Xu if (!data) 798c19e654dSHerbert Xu return 0; 799c19e654dSHerbert Xu 800c19e654dSHerbert Xu flags = 0; 801c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 802c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 803c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 804c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 805c19e654dSHerbert Xu if (flags & (GRE_VERSION|GRE_ROUTING)) 806c19e654dSHerbert Xu return -EINVAL; 807c19e654dSHerbert Xu 808946b636fSJiri Benc if (data[IFLA_GRE_COLLECT_METADATA] && 809946b636fSJiri Benc data[IFLA_GRE_ENCAP_TYPE] && 810946b636fSJiri Benc nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) 811946b636fSJiri Benc return -EINVAL; 812946b636fSJiri Benc 813c19e654dSHerbert Xu return 0; 814c19e654dSHerbert Xu } 815c19e654dSHerbert Xu 816e1a80002SHerbert Xu static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[]) 817e1a80002SHerbert Xu { 818e1a80002SHerbert Xu __be32 daddr; 819e1a80002SHerbert Xu 820e1a80002SHerbert Xu if (tb[IFLA_ADDRESS]) { 821e1a80002SHerbert Xu if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) 822e1a80002SHerbert Xu return -EINVAL; 823e1a80002SHerbert Xu if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 824e1a80002SHerbert Xu return -EADDRNOTAVAIL; 825e1a80002SHerbert Xu } 826e1a80002SHerbert Xu 827e1a80002SHerbert Xu if (!data) 828e1a80002SHerbert Xu goto out; 829e1a80002SHerbert Xu 830e1a80002SHerbert Xu if (data[IFLA_GRE_REMOTE]) { 831e1a80002SHerbert Xu memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); 832e1a80002SHerbert Xu if (!daddr) 833e1a80002SHerbert Xu return -EINVAL; 834e1a80002SHerbert Xu } 835e1a80002SHerbert Xu 836e1a80002SHerbert Xu out: 837e1a80002SHerbert Xu return ipgre_tunnel_validate(tb, data); 838e1a80002SHerbert Xu } 839e1a80002SHerbert Xu 8402e15ea39SPravin B Shelar static void ipgre_netlink_parms(struct net_device *dev, 8412e15ea39SPravin B Shelar struct nlattr *data[], 8422e15ea39SPravin B Shelar struct nlattr *tb[], 843c19e654dSHerbert Xu struct ip_tunnel_parm *parms) 844c19e654dSHerbert Xu { 8457bb82d92SHerbert Xu memset(parms, 0, sizeof(*parms)); 846c19e654dSHerbert Xu 847c19e654dSHerbert Xu parms->iph.protocol = IPPROTO_GRE; 848c19e654dSHerbert Xu 849c19e654dSHerbert Xu if (!data) 850c19e654dSHerbert Xu return; 851c19e654dSHerbert Xu 852c19e654dSHerbert Xu if (data[IFLA_GRE_LINK]) 853c19e654dSHerbert Xu parms->link = nla_get_u32(data[IFLA_GRE_LINK]); 854c19e654dSHerbert Xu 855c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 856c5441932SPravin B Shelar parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); 857c19e654dSHerbert Xu 858c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 859c5441932SPravin B Shelar parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); 860c19e654dSHerbert Xu 861c19e654dSHerbert Xu if (data[IFLA_GRE_IKEY]) 862c19e654dSHerbert Xu parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); 863c19e654dSHerbert Xu 864c19e654dSHerbert Xu if (data[IFLA_GRE_OKEY]) 865c19e654dSHerbert Xu parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); 866c19e654dSHerbert Xu 867c19e654dSHerbert Xu if (data[IFLA_GRE_LOCAL]) 86867b61f6cSJiri Benc parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); 869c19e654dSHerbert Xu 870c19e654dSHerbert Xu if (data[IFLA_GRE_REMOTE]) 87167b61f6cSJiri Benc parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); 872c19e654dSHerbert Xu 873c19e654dSHerbert Xu if (data[IFLA_GRE_TTL]) 874c19e654dSHerbert Xu parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); 875c19e654dSHerbert Xu 876c19e654dSHerbert Xu if (data[IFLA_GRE_TOS]) 877c19e654dSHerbert Xu parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); 878c19e654dSHerbert Xu 879c19e654dSHerbert Xu if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) 880c19e654dSHerbert Xu parms->iph.frag_off = htons(IP_DF); 8812e15ea39SPravin B Shelar 8822e15ea39SPravin B Shelar if (data[IFLA_GRE_COLLECT_METADATA]) { 8832e15ea39SPravin B Shelar struct ip_tunnel *t = netdev_priv(dev); 8842e15ea39SPravin B Shelar 8852e15ea39SPravin B Shelar t->collect_md = true; 886e271c7b4SJiri Benc if (dev->type == ARPHRD_IPGRE) 887e271c7b4SJiri Benc dev->type = ARPHRD_NONE; 8882e15ea39SPravin B Shelar } 889c19e654dSHerbert Xu } 890c19e654dSHerbert Xu 8914565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */ 8924565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[], 8934565e991STom Herbert struct ip_tunnel_encap *ipencap) 8944565e991STom Herbert { 8954565e991STom Herbert bool ret = false; 8964565e991STom Herbert 8974565e991STom Herbert memset(ipencap, 0, sizeof(*ipencap)); 8984565e991STom Herbert 8994565e991STom Herbert if (!data) 9004565e991STom Herbert return ret; 9014565e991STom Herbert 9024565e991STom Herbert if (data[IFLA_GRE_ENCAP_TYPE]) { 9034565e991STom Herbert ret = true; 9044565e991STom Herbert ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); 9054565e991STom Herbert } 9064565e991STom Herbert 9074565e991STom Herbert if (data[IFLA_GRE_ENCAP_FLAGS]) { 9084565e991STom Herbert ret = true; 9094565e991STom Herbert ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); 9104565e991STom Herbert } 9114565e991STom Herbert 9124565e991STom Herbert if (data[IFLA_GRE_ENCAP_SPORT]) { 9134565e991STom Herbert ret = true; 9143e97fa70SSabrina Dubroca ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); 9154565e991STom Herbert } 9164565e991STom Herbert 9174565e991STom Herbert if (data[IFLA_GRE_ENCAP_DPORT]) { 9184565e991STom Herbert ret = true; 9193e97fa70SSabrina Dubroca ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); 9204565e991STom Herbert } 9214565e991STom Herbert 9224565e991STom Herbert return ret; 9234565e991STom Herbert } 9244565e991STom Herbert 925c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev) 926e1a80002SHerbert Xu { 927c5441932SPravin B Shelar __gre_tunnel_init(dev); 928bec94d43Sstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 929e1a80002SHerbert Xu 930c5441932SPravin B Shelar return ip_tunnel_init(dev); 931e1a80002SHerbert Xu } 932e1a80002SHerbert Xu 933c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = { 934c5441932SPravin B Shelar .ndo_init = gre_tap_init, 935c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 936c5441932SPravin B Shelar .ndo_start_xmit = gre_tap_xmit, 937b8c26a33SStephen Hemminger .ndo_set_mac_address = eth_mac_addr, 938b8c26a33SStephen Hemminger .ndo_validate_addr = eth_validate_addr, 939c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 940c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 9411e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 942fc4099f1SPravin B Shelar .ndo_fill_metadata_dst = gre_fill_metadata_dst, 943b8c26a33SStephen Hemminger }; 944b8c26a33SStephen Hemminger 945e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev) 946e1a80002SHerbert Xu { 947e1a80002SHerbert Xu ether_setup(dev); 948c5441932SPravin B Shelar dev->netdev_ops = &gre_tap_netdev_ops; 949d13b161cSJiri Benc dev->priv_flags &= ~IFF_TX_SKB_SHARING; 950f8c1b7ceSstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 951c5441932SPravin B Shelar ip_tunnel_setup(dev, gre_tap_net_id); 952e1a80002SHerbert Xu } 953e1a80002SHerbert Xu 954c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev, 955c5441932SPravin B Shelar struct nlattr *tb[], struct nlattr *data[]) 956c19e654dSHerbert Xu { 957c5441932SPravin B Shelar struct ip_tunnel_parm p; 9584565e991STom Herbert struct ip_tunnel_encap ipencap; 9594565e991STom Herbert 9604565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 9614565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 9624565e991STom Herbert int err = ip_tunnel_encap_setup(t, &ipencap); 9634565e991STom Herbert 9644565e991STom Herbert if (err < 0) 9654565e991STom Herbert return err; 9664565e991STom Herbert } 967c19e654dSHerbert Xu 9682e15ea39SPravin B Shelar ipgre_netlink_parms(dev, data, tb, &p); 969c5441932SPravin B Shelar return ip_tunnel_newlink(dev, tb, &p); 970c19e654dSHerbert Xu } 971c19e654dSHerbert Xu 972c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], 973c19e654dSHerbert Xu struct nlattr *data[]) 974c19e654dSHerbert Xu { 975c19e654dSHerbert Xu struct ip_tunnel_parm p; 9764565e991STom Herbert struct ip_tunnel_encap ipencap; 9774565e991STom Herbert 9784565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 9794565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 9804565e991STom Herbert int err = ip_tunnel_encap_setup(t, &ipencap); 9814565e991STom Herbert 9824565e991STom Herbert if (err < 0) 9834565e991STom Herbert return err; 9844565e991STom Herbert } 985c19e654dSHerbert Xu 9862e15ea39SPravin B Shelar ipgre_netlink_parms(dev, data, tb, &p); 987c5441932SPravin B Shelar return ip_tunnel_changelink(dev, tb, &p); 988c19e654dSHerbert Xu } 989c19e654dSHerbert Xu 990c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev) 991c19e654dSHerbert Xu { 992c19e654dSHerbert Xu return 993c19e654dSHerbert Xu /* IFLA_GRE_LINK */ 994c19e654dSHerbert Xu nla_total_size(4) + 995c19e654dSHerbert Xu /* IFLA_GRE_IFLAGS */ 996c19e654dSHerbert Xu nla_total_size(2) + 997c19e654dSHerbert Xu /* IFLA_GRE_OFLAGS */ 998c19e654dSHerbert Xu nla_total_size(2) + 999c19e654dSHerbert Xu /* IFLA_GRE_IKEY */ 1000c19e654dSHerbert Xu nla_total_size(4) + 1001c19e654dSHerbert Xu /* IFLA_GRE_OKEY */ 1002c19e654dSHerbert Xu nla_total_size(4) + 1003c19e654dSHerbert Xu /* IFLA_GRE_LOCAL */ 1004c19e654dSHerbert Xu nla_total_size(4) + 1005c19e654dSHerbert Xu /* IFLA_GRE_REMOTE */ 1006c19e654dSHerbert Xu nla_total_size(4) + 1007c19e654dSHerbert Xu /* IFLA_GRE_TTL */ 1008c19e654dSHerbert Xu nla_total_size(1) + 1009c19e654dSHerbert Xu /* IFLA_GRE_TOS */ 1010c19e654dSHerbert Xu nla_total_size(1) + 1011c19e654dSHerbert Xu /* IFLA_GRE_PMTUDISC */ 1012c19e654dSHerbert Xu nla_total_size(1) + 10134565e991STom Herbert /* IFLA_GRE_ENCAP_TYPE */ 10144565e991STom Herbert nla_total_size(2) + 10154565e991STom Herbert /* IFLA_GRE_ENCAP_FLAGS */ 10164565e991STom Herbert nla_total_size(2) + 10174565e991STom Herbert /* IFLA_GRE_ENCAP_SPORT */ 10184565e991STom Herbert nla_total_size(2) + 10194565e991STom Herbert /* IFLA_GRE_ENCAP_DPORT */ 10204565e991STom Herbert nla_total_size(2) + 10212e15ea39SPravin B Shelar /* IFLA_GRE_COLLECT_METADATA */ 10222e15ea39SPravin B Shelar nla_total_size(0) + 1023c19e654dSHerbert Xu 0; 1024c19e654dSHerbert Xu } 1025c19e654dSHerbert Xu 1026c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) 1027c19e654dSHerbert Xu { 1028c19e654dSHerbert Xu struct ip_tunnel *t = netdev_priv(dev); 1029c19e654dSHerbert Xu struct ip_tunnel_parm *p = &t->parms; 1030c19e654dSHerbert Xu 1031f3756b79SDavid S. Miller if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || 103295f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_IFLAGS, 103395f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->i_flags)) || 103495f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_OFLAGS, 103595f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->o_flags)) || 1036f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || 1037f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || 1038930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || 1039930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) || 1040f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) || 1041f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) || 1042f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_PMTUDISC, 1043f3756b79SDavid S. Miller !!(p->iph.frag_off & htons(IP_DF)))) 1044f3756b79SDavid S. Miller goto nla_put_failure; 10454565e991STom Herbert 10464565e991STom Herbert if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, 10474565e991STom Herbert t->encap.type) || 10483e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, 10494565e991STom Herbert t->encap.sport) || 10503e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, 10514565e991STom Herbert t->encap.dport) || 10524565e991STom Herbert nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, 1053e1b2cb65STom Herbert t->encap.flags)) 10544565e991STom Herbert goto nla_put_failure; 10554565e991STom Herbert 10562e15ea39SPravin B Shelar if (t->collect_md) { 10572e15ea39SPravin B Shelar if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) 10582e15ea39SPravin B Shelar goto nla_put_failure; 10592e15ea39SPravin B Shelar } 10602e15ea39SPravin B Shelar 1061c19e654dSHerbert Xu return 0; 1062c19e654dSHerbert Xu 1063c19e654dSHerbert Xu nla_put_failure: 1064c19e654dSHerbert Xu return -EMSGSIZE; 1065c19e654dSHerbert Xu } 1066c19e654dSHerbert Xu 1067c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { 1068c19e654dSHerbert Xu [IFLA_GRE_LINK] = { .type = NLA_U32 }, 1069c19e654dSHerbert Xu [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, 1070c19e654dSHerbert Xu [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, 1071c19e654dSHerbert Xu [IFLA_GRE_IKEY] = { .type = NLA_U32 }, 1072c19e654dSHerbert Xu [IFLA_GRE_OKEY] = { .type = NLA_U32 }, 10734d74f8baSPatrick McHardy [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, 10744d74f8baSPatrick McHardy [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, 1075c19e654dSHerbert Xu [IFLA_GRE_TTL] = { .type = NLA_U8 }, 1076c19e654dSHerbert Xu [IFLA_GRE_TOS] = { .type = NLA_U8 }, 1077c19e654dSHerbert Xu [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, 10784565e991STom Herbert [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, 10794565e991STom Herbert [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, 10804565e991STom Herbert [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, 10814565e991STom Herbert [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, 10822e15ea39SPravin B Shelar [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, 1083c19e654dSHerbert Xu }; 1084c19e654dSHerbert Xu 1085c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = { 1086c19e654dSHerbert Xu .kind = "gre", 1087c19e654dSHerbert Xu .maxtype = IFLA_GRE_MAX, 1088c19e654dSHerbert Xu .policy = ipgre_policy, 1089c19e654dSHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1090c19e654dSHerbert Xu .setup = ipgre_tunnel_setup, 1091c19e654dSHerbert Xu .validate = ipgre_tunnel_validate, 1092c19e654dSHerbert Xu .newlink = ipgre_newlink, 1093c19e654dSHerbert Xu .changelink = ipgre_changelink, 1094c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1095c19e654dSHerbert Xu .get_size = ipgre_get_size, 1096c19e654dSHerbert Xu .fill_info = ipgre_fill_info, 10971728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1098c19e654dSHerbert Xu }; 1099c19e654dSHerbert Xu 1100e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { 1101e1a80002SHerbert Xu .kind = "gretap", 1102e1a80002SHerbert Xu .maxtype = IFLA_GRE_MAX, 1103e1a80002SHerbert Xu .policy = ipgre_policy, 1104e1a80002SHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1105e1a80002SHerbert Xu .setup = ipgre_tap_setup, 1106e1a80002SHerbert Xu .validate = ipgre_tap_validate, 1107e1a80002SHerbert Xu .newlink = ipgre_newlink, 1108e1a80002SHerbert Xu .changelink = ipgre_changelink, 1109c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1110e1a80002SHerbert Xu .get_size = ipgre_get_size, 1111e1a80002SHerbert Xu .fill_info = ipgre_fill_info, 11121728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1113e1a80002SHerbert Xu }; 1114e1a80002SHerbert Xu 1115b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name, 1116b2acd1dcSPravin B Shelar u8 name_assign_type) 1117b2acd1dcSPravin B Shelar { 1118b2acd1dcSPravin B Shelar struct nlattr *tb[IFLA_MAX + 1]; 1119b2acd1dcSPravin B Shelar struct net_device *dev; 1120106da663SNicolas Dichtel LIST_HEAD(list_kill); 1121b2acd1dcSPravin B Shelar struct ip_tunnel *t; 1122b2acd1dcSPravin B Shelar int err; 1123b2acd1dcSPravin B Shelar 1124b2acd1dcSPravin B Shelar memset(&tb, 0, sizeof(tb)); 1125b2acd1dcSPravin B Shelar 1126b2acd1dcSPravin B Shelar dev = rtnl_create_link(net, name, name_assign_type, 1127b2acd1dcSPravin B Shelar &ipgre_tap_ops, tb); 1128b2acd1dcSPravin B Shelar if (IS_ERR(dev)) 1129b2acd1dcSPravin B Shelar return dev; 1130b2acd1dcSPravin B Shelar 1131b2acd1dcSPravin B Shelar /* Configure flow based GRE device. */ 1132b2acd1dcSPravin B Shelar t = netdev_priv(dev); 1133b2acd1dcSPravin B Shelar t->collect_md = true; 1134b2acd1dcSPravin B Shelar 1135b2acd1dcSPravin B Shelar err = ipgre_newlink(net, dev, tb, NULL); 1136106da663SNicolas Dichtel if (err < 0) { 1137106da663SNicolas Dichtel free_netdev(dev); 1138106da663SNicolas Dichtel return ERR_PTR(err); 1139106da663SNicolas Dichtel } 11407e059158SDavid Wragg 11417e059158SDavid Wragg /* openvswitch users expect packet sizes to be unrestricted, 11427e059158SDavid Wragg * so set the largest MTU we can. 11437e059158SDavid Wragg */ 11447e059158SDavid Wragg err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); 11457e059158SDavid Wragg if (err) 11467e059158SDavid Wragg goto out; 11477e059158SDavid Wragg 1148da6f1da8SNicolas Dichtel err = rtnl_configure_link(dev, NULL); 1149da6f1da8SNicolas Dichtel if (err < 0) 1150da6f1da8SNicolas Dichtel goto out; 1151da6f1da8SNicolas Dichtel 1152b2acd1dcSPravin B Shelar return dev; 1153b2acd1dcSPravin B Shelar out: 1154106da663SNicolas Dichtel ip_tunnel_dellink(dev, &list_kill); 1155106da663SNicolas Dichtel unregister_netdevice_many(&list_kill); 1156b2acd1dcSPravin B Shelar return ERR_PTR(err); 1157b2acd1dcSPravin B Shelar } 1158b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create); 1159b2acd1dcSPravin B Shelar 1160c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net) 1161c5441932SPravin B Shelar { 11622e15ea39SPravin B Shelar return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); 1163c5441932SPravin B Shelar } 1164c5441932SPravin B Shelar 1165c5441932SPravin B Shelar static void __net_exit ipgre_tap_exit_net(struct net *net) 1166c5441932SPravin B Shelar { 1167c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id); 11686c742e71SNicolas Dichtel ip_tunnel_delete_net(itn, &ipgre_tap_ops); 1169c5441932SPravin B Shelar } 1170c5441932SPravin B Shelar 1171c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = { 1172c5441932SPravin B Shelar .init = ipgre_tap_init_net, 1173c5441932SPravin B Shelar .exit = ipgre_tap_exit_net, 1174c5441932SPravin B Shelar .id = &gre_tap_net_id, 1175c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 1176c5441932SPravin B Shelar }; 11771da177e4SLinus Torvalds 11781da177e4SLinus Torvalds static int __init ipgre_init(void) 11791da177e4SLinus Torvalds { 11801da177e4SLinus Torvalds int err; 11811da177e4SLinus Torvalds 1182058bd4d2SJoe Perches pr_info("GRE over IPv4 tunneling driver\n"); 11831da177e4SLinus Torvalds 1184cfb8fbf2SEric W. Biederman err = register_pernet_device(&ipgre_net_ops); 118559a4c759SPavel Emelyanov if (err < 0) 1186c2892f02SAlexey Dobriyan return err; 1187c2892f02SAlexey Dobriyan 1188c5441932SPravin B Shelar err = register_pernet_device(&ipgre_tap_net_ops); 1189c5441932SPravin B Shelar if (err < 0) 1190c5441932SPravin B Shelar goto pnet_tap_faied; 1191c5441932SPravin B Shelar 11929f57c67cSPravin B Shelar err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); 1193c2892f02SAlexey Dobriyan if (err < 0) { 1194058bd4d2SJoe Perches pr_info("%s: can't add protocol\n", __func__); 1195c2892f02SAlexey Dobriyan goto add_proto_failed; 1196c2892f02SAlexey Dobriyan } 11977daa0004SPavel Emelyanov 1198c19e654dSHerbert Xu err = rtnl_link_register(&ipgre_link_ops); 1199c19e654dSHerbert Xu if (err < 0) 1200c19e654dSHerbert Xu goto rtnl_link_failed; 1201c19e654dSHerbert Xu 1202e1a80002SHerbert Xu err = rtnl_link_register(&ipgre_tap_ops); 1203e1a80002SHerbert Xu if (err < 0) 1204e1a80002SHerbert Xu goto tap_ops_failed; 1205e1a80002SHerbert Xu 1206c5441932SPravin B Shelar return 0; 1207c19e654dSHerbert Xu 1208e1a80002SHerbert Xu tap_ops_failed: 1209e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 1210c19e654dSHerbert Xu rtnl_link_failed: 12119f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1212c2892f02SAlexey Dobriyan add_proto_failed: 1213c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1214c5441932SPravin B Shelar pnet_tap_faied: 1215c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 1216c5441932SPravin B Shelar return err; 12171da177e4SLinus Torvalds } 12181da177e4SLinus Torvalds 1219db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void) 12201da177e4SLinus Torvalds { 1221e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_tap_ops); 1222c19e654dSHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 12239f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1224c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1225c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 12261da177e4SLinus Torvalds } 12271da177e4SLinus Torvalds 12281da177e4SLinus Torvalds module_init(ipgre_init); 12291da177e4SLinus Torvalds module_exit(ipgre_fini); 12301da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 12314d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre"); 12324d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap"); 12338909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0"); 1234c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0"); 1235