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 52dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 531da177e4SLinus Torvalds #include <net/ipv6.h> 541da177e4SLinus Torvalds #include <net/ip6_fib.h> 551da177e4SLinus Torvalds #include <net/ip6_route.h> 561da177e4SLinus Torvalds #endif 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds /* 591da177e4SLinus Torvalds Problems & solutions 601da177e4SLinus Torvalds -------------------- 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds 1. The most important issue is detecting local dead loops. 631da177e4SLinus Torvalds They would cause complete host lockup in transmit, which 641da177e4SLinus Torvalds would be "resolved" by stack overflow or, if queueing is enabled, 651da177e4SLinus Torvalds with infinite looping in net_bh. 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds We cannot track such dead loops during route installation, 681da177e4SLinus Torvalds it is infeasible task. The most general solutions would be 691da177e4SLinus Torvalds to keep skb->encapsulation counter (sort of local ttl), 706d0722a2SEric Dumazet and silently drop packet when it expires. It is a good 71bff52857Sstephen hemminger solution, but it supposes maintaining new variable in ALL 721da177e4SLinus Torvalds skb, even if no tunneling is used. 731da177e4SLinus Torvalds 746d0722a2SEric Dumazet Current solution: xmit_recursion breaks dead loops. This is a percpu 756d0722a2SEric Dumazet counter, since when we enter the first ndo_xmit(), cpu migration is 766d0722a2SEric Dumazet forbidden. We force an exit if this counter reaches RECURSION_LIMIT 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds 2. Networking dead loops would not kill routers, but would really 791da177e4SLinus Torvalds kill network. IP hop limit plays role of "t->recursion" in this case, 801da177e4SLinus Torvalds if we copy it from packet being encapsulated to upper header. 811da177e4SLinus Torvalds It is very good solution, but it introduces two problems: 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds - Routing protocols, using packets with ttl=1 (OSPF, RIP2), 841da177e4SLinus Torvalds do not work over tunnels. 851da177e4SLinus Torvalds - traceroute does not work. I planned to relay ICMP from tunnel, 861da177e4SLinus Torvalds so that this problem would be solved and traceroute output 871da177e4SLinus Torvalds would even more informative. This idea appeared to be wrong: 881da177e4SLinus Torvalds only Linux complies to rfc1812 now (yes, guys, Linux is the only 891da177e4SLinus Torvalds true router now :-)), all routers (at least, in neighbourhood of mine) 901da177e4SLinus Torvalds return only 8 bytes of payload. It is the end. 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds Hence, if we want that OSPF worked or traceroute said something reasonable, 931da177e4SLinus Torvalds we should search for another solution. 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds One of them is to parse packet trying to detect inner encapsulation 961da177e4SLinus Torvalds made by our node. It is difficult or even impossible, especially, 97bff52857Sstephen hemminger taking into account fragmentation. TO be short, ttl is not solution at all. 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds Current solution: The solution was UNEXPECTEDLY SIMPLE. 1001da177e4SLinus Torvalds We force DF flag on tunnels with preconfigured hop limit, 1011da177e4SLinus Torvalds that is ALL. :-) Well, it does not remove the problem completely, 1021da177e4SLinus Torvalds but exponential growth of network traffic is changed to linear 1031da177e4SLinus Torvalds (branches, that exceed pmtu are pruned) and tunnel mtu 104bff52857Sstephen hemminger rapidly degrades to value <68, where looping stops. 1051da177e4SLinus Torvalds Yes, it is not good if there exists a router in the loop, 1061da177e4SLinus Torvalds which does not force DF, even when encapsulating packets have DF set. 1071da177e4SLinus Torvalds But it is not our problem! Nobody could accuse us, we made 1081da177e4SLinus Torvalds all that we could make. Even if it is your gated who injected 1091da177e4SLinus Torvalds fatal route to network, even if it were you who configured 1101da177e4SLinus Torvalds fatal static route: you are innocent. :-) 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds Alexey Kuznetsov. 1131da177e4SLinus Torvalds */ 1141da177e4SLinus Torvalds 115eccc1bb8Sstephen hemminger static bool log_ecn_error = true; 116eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644); 117eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); 118eccc1bb8Sstephen hemminger 119c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly; 1201da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev); 121eb8ce741SPavel Emelyanov 122f99189b1SEric Dumazet static int ipgre_net_id __read_mostly; 123c5441932SPravin B Shelar static int gre_tap_net_id __read_mostly; 124eb8ce741SPavel Emelyanov 1259f57c67cSPravin B Shelar static void ipgre_err(struct sk_buff *skb, u32 info, 126bda7bb46SPravin B Shelar const struct tnl_ptk_info *tpi) 1271da177e4SLinus Torvalds { 1281da177e4SLinus Torvalds 129071f92d0SRami Rosen /* All the routers (except for Linux) return only 1301da177e4SLinus Torvalds 8 bytes of packet payload. It means, that precise relaying of 1311da177e4SLinus Torvalds ICMP in the real Internet is absolutely infeasible. 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds Moreover, Cisco "wise men" put GRE key to the third word 134c5441932SPravin B Shelar in GRE header. It makes impossible maintaining even soft 135c5441932SPravin B Shelar state for keyed GRE tunnels with enabled checksum. Tell 136c5441932SPravin B Shelar them "thank you". 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds Well, I wonder, rfc1812 was written by Cisco employee, 139bff52857Sstephen hemminger what the hell these idiots break standards established 140bff52857Sstephen hemminger by themselves??? 1411da177e4SLinus Torvalds */ 142c5441932SPravin B Shelar struct net *net = dev_net(skb->dev); 143c5441932SPravin B Shelar struct ip_tunnel_net *itn; 14496f5a846SEric Dumazet const struct iphdr *iph; 14588c7664fSArnaldo Carvalho de Melo const int type = icmp_hdr(skb)->type; 14688c7664fSArnaldo Carvalho de Melo const int code = icmp_hdr(skb)->code; 1471da177e4SLinus Torvalds struct ip_tunnel *t; 148d2083287Sstephen hemminger 1491da177e4SLinus Torvalds switch (type) { 1501da177e4SLinus Torvalds default: 1511da177e4SLinus Torvalds case ICMP_PARAMETERPROB: 1529f57c67cSPravin B Shelar return; 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds case ICMP_DEST_UNREACH: 1551da177e4SLinus Torvalds switch (code) { 1561da177e4SLinus Torvalds case ICMP_SR_FAILED: 1571da177e4SLinus Torvalds case ICMP_PORT_UNREACH: 1581da177e4SLinus Torvalds /* Impossible event. */ 1599f57c67cSPravin B Shelar return; 1601da177e4SLinus Torvalds default: 1611da177e4SLinus Torvalds /* All others are translated to HOST_UNREACH. 1621da177e4SLinus Torvalds rfc2003 contains "deep thoughts" about NET_UNREACH, 1631da177e4SLinus Torvalds I believe they are just ether pollution. --ANK 1641da177e4SLinus Torvalds */ 1651da177e4SLinus Torvalds break; 1661da177e4SLinus Torvalds } 1671da177e4SLinus Torvalds break; 1689f57c67cSPravin B Shelar 1691da177e4SLinus Torvalds case ICMP_TIME_EXCEEDED: 1701da177e4SLinus Torvalds if (code != ICMP_EXC_TTL) 1719f57c67cSPravin B Shelar return; 1721da177e4SLinus Torvalds break; 17355be7a9cSDavid S. Miller 17455be7a9cSDavid S. Miller case ICMP_REDIRECT: 17555be7a9cSDavid S. Miller break; 1761da177e4SLinus Torvalds } 1771da177e4SLinus Torvalds 178bda7bb46SPravin B Shelar if (tpi->proto == htons(ETH_P_TEB)) 179c5441932SPravin B Shelar itn = net_generic(net, gre_tap_net_id); 180c5441932SPravin B Shelar else 181c5441932SPravin B Shelar itn = net_generic(net, ipgre_net_id); 182c5441932SPravin B Shelar 183c0c0c50fSDuan Jiong iph = (const struct iphdr *)(icmp_hdr(skb) + 1); 184bda7bb46SPravin B Shelar t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 185bda7bb46SPravin B Shelar iph->daddr, iph->saddr, tpi->key); 186d2083287Sstephen hemminger 18751456b29SIan Morris if (!t) 1889f57c67cSPravin B Shelar return; 18936393395SDavid S. Miller 19036393395SDavid S. Miller if (t->parms.iph.daddr == 0 || 191f97c1e0cSJoe Perches ipv4_is_multicast(t->parms.iph.daddr)) 1929f57c67cSPravin B Shelar return; 1931da177e4SLinus Torvalds 1941da177e4SLinus Torvalds if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 1959f57c67cSPravin B Shelar return; 1961da177e4SLinus Torvalds 197da6185d8SWei Yongjun if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) 1981da177e4SLinus Torvalds t->err_count++; 1991da177e4SLinus Torvalds else 2001da177e4SLinus Torvalds t->err_count = 1; 2011da177e4SLinus Torvalds t->err_time = jiffies; 2029f57c67cSPravin B Shelar } 2039f57c67cSPravin B Shelar 2049f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info) 2059f57c67cSPravin B Shelar { 2069f57c67cSPravin B Shelar /* All the routers (except for Linux) return only 2079f57c67cSPravin B Shelar * 8 bytes of packet payload. It means, that precise relaying of 2089f57c67cSPravin B Shelar * ICMP in the real Internet is absolutely infeasible. 2099f57c67cSPravin B Shelar * 2109f57c67cSPravin B Shelar * Moreover, Cisco "wise men" put GRE key to the third word 2119f57c67cSPravin B Shelar * in GRE header. It makes impossible maintaining even soft 2129f57c67cSPravin B Shelar * state for keyed 2139f57c67cSPravin B Shelar * GRE tunnels with enabled checksum. Tell them "thank you". 2149f57c67cSPravin B Shelar * 2159f57c67cSPravin B Shelar * Well, I wonder, rfc1812 was written by Cisco employee, 2169f57c67cSPravin B Shelar * what the hell these idiots break standards established 2179f57c67cSPravin B Shelar * by themselves??? 2189f57c67cSPravin B Shelar */ 2199f57c67cSPravin B Shelar 2209f57c67cSPravin B Shelar const int type = icmp_hdr(skb)->type; 2219f57c67cSPravin B Shelar const int code = icmp_hdr(skb)->code; 2229f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 2239f57c67cSPravin B Shelar bool csum_err = false; 22495f5c64cSTom Herbert int hdr_len; 2259f57c67cSPravin B Shelar 22695f5c64cSTom Herbert if (gre_parse_header(skb, &tpi, &csum_err, &hdr_len)) { 2279f57c67cSPravin B Shelar if (!csum_err) /* ignore csum errors. */ 2289f57c67cSPravin B Shelar return; 2299f57c67cSPravin B Shelar } 2309f57c67cSPravin B Shelar 23195f5c64cSTom Herbert if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false)) 23295f5c64cSTom Herbert return; 23395f5c64cSTom Herbert 2349f57c67cSPravin B Shelar if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 2359f57c67cSPravin B Shelar ipv4_update_pmtu(skb, dev_net(skb->dev), info, 2369f57c67cSPravin B Shelar skb->dev->ifindex, 0, IPPROTO_GRE, 0); 2379f57c67cSPravin B Shelar return; 2389f57c67cSPravin B Shelar } 2399f57c67cSPravin B Shelar if (type == ICMP_REDIRECT) { 2409f57c67cSPravin B Shelar ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0, 2419f57c67cSPravin B Shelar IPPROTO_GRE, 0); 2429f57c67cSPravin B Shelar return; 2439f57c67cSPravin B Shelar } 2449f57c67cSPravin B Shelar 2459f57c67cSPravin B Shelar ipgre_err(skb, info, &tpi); 2461da177e4SLinus Torvalds } 2471da177e4SLinus Torvalds 2482e15ea39SPravin B Shelar static __be64 key_to_tunnel_id(__be32 key) 2492e15ea39SPravin B Shelar { 2502e15ea39SPravin B Shelar #ifdef __BIG_ENDIAN 2512e15ea39SPravin B Shelar return (__force __be64)((__force u32)key); 2522e15ea39SPravin B Shelar #else 2532e15ea39SPravin B Shelar return (__force __be64)((__force u64)key << 32); 2542e15ea39SPravin B Shelar #endif 2552e15ea39SPravin B Shelar } 2562e15ea39SPravin B Shelar 2572e15ea39SPravin B Shelar /* Returns the least-significant 32 bits of a __be64. */ 2582e15ea39SPravin B Shelar static __be32 tunnel_id_to_key(__be64 x) 2592e15ea39SPravin B Shelar { 2602e15ea39SPravin B Shelar #ifdef __BIG_ENDIAN 2612e15ea39SPravin B Shelar return (__force __be32)x; 2622e15ea39SPravin B Shelar #else 2632e15ea39SPravin B Shelar return (__force __be32)((__force u64)x >> 32); 2642e15ea39SPravin B Shelar #endif 2652e15ea39SPravin B Shelar } 2662e15ea39SPravin B Shelar 267bda7bb46SPravin B Shelar static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) 2681da177e4SLinus Torvalds { 269c5441932SPravin B Shelar struct net *net = dev_net(skb->dev); 2702e15ea39SPravin B Shelar struct metadata_dst *tun_dst = NULL; 271c5441932SPravin B Shelar struct ip_tunnel_net *itn; 272b71d1d42SEric Dumazet const struct iphdr *iph; 2731da177e4SLinus Torvalds struct ip_tunnel *tunnel; 2741da177e4SLinus Torvalds 275bda7bb46SPravin B Shelar if (tpi->proto == htons(ETH_P_TEB)) 276c5441932SPravin B Shelar itn = net_generic(net, gre_tap_net_id); 277c5441932SPravin B Shelar else 278c5441932SPravin B Shelar itn = net_generic(net, ipgre_net_id); 279c5441932SPravin B Shelar 280eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb); 281bda7bb46SPravin B Shelar tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 282bda7bb46SPravin B Shelar iph->saddr, iph->daddr, tpi->key); 2831da177e4SLinus Torvalds 284d2083287Sstephen hemminger if (tunnel) { 2850e3da5bbSTimo Teräs skb_pop_mac_header(skb); 2862e15ea39SPravin B Shelar if (tunnel->collect_md) { 287c29a70d2SPravin B Shelar __be16 flags; 288c29a70d2SPravin B Shelar __be64 tun_id; 2892e15ea39SPravin B Shelar 290c29a70d2SPravin B Shelar flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); 291c29a70d2SPravin B Shelar tun_id = key_to_tunnel_id(tpi->key); 292c29a70d2SPravin B Shelar tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0); 2932e15ea39SPravin B Shelar if (!tun_dst) 2942e15ea39SPravin B Shelar return PACKET_REJECT; 2952e15ea39SPravin B Shelar } 2962e15ea39SPravin B Shelar 2972e15ea39SPravin B Shelar ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 298bda7bb46SPravin B Shelar return PACKET_RCVD; 2991da177e4SLinus Torvalds } 300bda7bb46SPravin B Shelar return PACKET_REJECT; 3011da177e4SLinus Torvalds } 3021da177e4SLinus Torvalds 3039f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb) 3049f57c67cSPravin B Shelar { 3059f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 3069f57c67cSPravin B Shelar bool csum_err = false; 30795f5c64cSTom Herbert int hdr_len; 3089f57c67cSPravin B Shelar 3099f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 3109f57c67cSPravin B Shelar if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { 3119f57c67cSPravin B Shelar /* Looped back packet, drop it! */ 3129f57c67cSPravin B Shelar if (rt_is_output_route(skb_rtable(skb))) 3139f57c67cSPravin B Shelar goto drop; 3149f57c67cSPravin B Shelar } 3159f57c67cSPravin B Shelar #endif 3169f57c67cSPravin B Shelar 31795f5c64cSTom Herbert if (gre_parse_header(skb, &tpi, &csum_err, &hdr_len) < 0) 31895f5c64cSTom Herbert goto drop; 31995f5c64cSTom Herbert 32095f5c64cSTom Herbert if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false)) 3219f57c67cSPravin B Shelar goto drop; 3229f57c67cSPravin B Shelar 3239f57c67cSPravin B Shelar if (ipgre_rcv(skb, &tpi) == PACKET_RCVD) 3249f57c67cSPravin B Shelar return 0; 3259f57c67cSPravin B Shelar 3269f57c67cSPravin B Shelar icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 3279f57c67cSPravin B Shelar drop: 3289f57c67cSPravin B Shelar kfree_skb(skb); 3299f57c67cSPravin B Shelar return 0; 3309f57c67cSPravin B Shelar } 3319f57c67cSPravin B Shelar 332c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, 333c5441932SPravin B Shelar const struct iphdr *tnl_params, 334c5441932SPravin B Shelar __be16 proto) 335c5441932SPravin B Shelar { 336c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 337c5441932SPravin B Shelar 338c5441932SPravin B Shelar if (tunnel->parms.o_flags & TUNNEL_SEQ) 339c5441932SPravin B Shelar tunnel->o_seqno++; 340cef401deSEric Dumazet 341c5441932SPravin B Shelar /* Push GRE header. */ 342182a352dSTom Herbert gre_build_header(skb, tunnel->tun_hlen, 343182a352dSTom Herbert tunnel->parms.o_flags, proto, tunnel->parms.o_key, 344182a352dSTom Herbert htonl(tunnel->o_seqno)); 3451da177e4SLinus Torvalds 3462e15ea39SPravin B Shelar skb_set_inner_protocol(skb, proto); 347bf3d6a8fSNicolas Dichtel ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); 3481da177e4SLinus Torvalds } 3491da177e4SLinus Torvalds 350aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum) 351b2acd1dcSPravin B Shelar { 3526fa79666SEdward Cree return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); 353b2acd1dcSPravin B Shelar } 354b2acd1dcSPravin B Shelar 355fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb, 356fc4099f1SPravin B Shelar struct net_device *dev, 357fc4099f1SPravin B Shelar struct flowi4 *fl, 358fc4099f1SPravin B Shelar const struct ip_tunnel_key *key) 359fc4099f1SPravin B Shelar { 360fc4099f1SPravin B Shelar struct net *net = dev_net(dev); 361fc4099f1SPravin B Shelar 362fc4099f1SPravin B Shelar memset(fl, 0, sizeof(*fl)); 363fc4099f1SPravin B Shelar fl->daddr = key->u.ipv4.dst; 364fc4099f1SPravin B Shelar fl->saddr = key->u.ipv4.src; 365fc4099f1SPravin B Shelar fl->flowi4_tos = RT_TOS(key->tos); 366fc4099f1SPravin B Shelar fl->flowi4_mark = skb->mark; 367fc4099f1SPravin B Shelar fl->flowi4_proto = IPPROTO_GRE; 368fc4099f1SPravin B Shelar 369fc4099f1SPravin B Shelar return ip_route_output_key(net, fl); 370fc4099f1SPravin B Shelar } 371fc4099f1SPravin B Shelar 3722090714eSJiri Benc static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev, 3732090714eSJiri Benc __be16 proto) 3742e15ea39SPravin B Shelar { 3752e15ea39SPravin B Shelar struct ip_tunnel_info *tun_info; 3762e15ea39SPravin B Shelar const struct ip_tunnel_key *key; 377db3c6139SDaniel Borkmann struct rtable *rt = NULL; 3782e15ea39SPravin B Shelar struct flowi4 fl; 3792e15ea39SPravin B Shelar int min_headroom; 3802e15ea39SPravin B Shelar int tunnel_hlen; 3812e15ea39SPravin B Shelar __be16 df, flags; 382db3c6139SDaniel Borkmann bool use_cache; 3832e15ea39SPravin B Shelar int err; 3842e15ea39SPravin B Shelar 38561adedf3SJiri Benc tun_info = skb_tunnel_info(skb); 3867f9562a1SJiri Benc if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 3877f9562a1SJiri Benc ip_tunnel_info_af(tun_info) != AF_INET)) 3882e15ea39SPravin B Shelar goto err_free_skb; 3892e15ea39SPravin B Shelar 3902e15ea39SPravin B Shelar key = &tun_info->key; 391db3c6139SDaniel Borkmann use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); 392db3c6139SDaniel Borkmann if (use_cache) 393db3c6139SDaniel Borkmann rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl.saddr); 3943c1cb4d2SPaolo Abeni if (!rt) { 395fc4099f1SPravin B Shelar rt = gre_get_rt(skb, dev, &fl, key); 3962e15ea39SPravin B Shelar if (IS_ERR(rt)) 3972e15ea39SPravin B Shelar goto err_free_skb; 398db3c6139SDaniel Borkmann if (use_cache) 3993c1cb4d2SPaolo Abeni dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, 4003c1cb4d2SPaolo Abeni fl.saddr); 4013c1cb4d2SPaolo Abeni } 4022e15ea39SPravin B Shelar 40395f5c64cSTom Herbert tunnel_hlen = gre_calc_hlen(key->tun_flags); 4042e15ea39SPravin B Shelar 4052e15ea39SPravin B Shelar min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len 4062e15ea39SPravin B Shelar + tunnel_hlen + sizeof(struct iphdr); 4072e15ea39SPravin B Shelar if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { 4082e15ea39SPravin B Shelar int head_delta = SKB_DATA_ALIGN(min_headroom - 4092e15ea39SPravin B Shelar skb_headroom(skb) + 4102e15ea39SPravin B Shelar 16); 4112e15ea39SPravin B Shelar err = pskb_expand_head(skb, max_t(int, head_delta, 0), 4122e15ea39SPravin B Shelar 0, GFP_ATOMIC); 4132e15ea39SPravin B Shelar if (unlikely(err)) 4142e15ea39SPravin B Shelar goto err_free_rt; 4152e15ea39SPravin B Shelar } 4162e15ea39SPravin B Shelar 4172e15ea39SPravin B Shelar /* Push Tunnel header. */ 418aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM))) 4192e15ea39SPravin B Shelar goto err_free_rt; 4202e15ea39SPravin B Shelar 4212e15ea39SPravin B Shelar flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); 422*cba65321SDavid S. Miller gre_build_header(skb, tunnel_hlen, flags, proto, 4232e15ea39SPravin B Shelar tunnel_id_to_key(tun_info->key.tun_id), 0); 4242e15ea39SPravin B Shelar 4252e15ea39SPravin B Shelar df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; 426039f5062SPravin B Shelar 427039f5062SPravin B Shelar iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, 4287c383fb2SJiri Benc key->tos, key->ttl, df, false); 4292e15ea39SPravin B Shelar return; 4302e15ea39SPravin B Shelar 4312e15ea39SPravin B Shelar err_free_rt: 4322e15ea39SPravin B Shelar ip_rt_put(rt); 4332e15ea39SPravin B Shelar err_free_skb: 4342e15ea39SPravin B Shelar kfree_skb(skb); 4352e15ea39SPravin B Shelar dev->stats.tx_dropped++; 4362e15ea39SPravin B Shelar } 4372e15ea39SPravin B Shelar 438fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) 439fc4099f1SPravin B Shelar { 440fc4099f1SPravin B Shelar struct ip_tunnel_info *info = skb_tunnel_info(skb); 441fc4099f1SPravin B Shelar struct rtable *rt; 442fc4099f1SPravin B Shelar struct flowi4 fl4; 443fc4099f1SPravin B Shelar 444fc4099f1SPravin B Shelar if (ip_tunnel_info_af(info) != AF_INET) 445fc4099f1SPravin B Shelar return -EINVAL; 446fc4099f1SPravin B Shelar 447fc4099f1SPravin B Shelar rt = gre_get_rt(skb, dev, &fl4, &info->key); 448fc4099f1SPravin B Shelar if (IS_ERR(rt)) 449fc4099f1SPravin B Shelar return PTR_ERR(rt); 450fc4099f1SPravin B Shelar 451fc4099f1SPravin B Shelar ip_rt_put(rt); 452fc4099f1SPravin B Shelar info->key.u.ipv4.src = fl4.saddr; 453fc4099f1SPravin B Shelar return 0; 454fc4099f1SPravin B Shelar } 455fc4099f1SPravin B Shelar 456c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb, 457c5441932SPravin B Shelar struct net_device *dev) 458ee34c1ebSMichal Schmidt { 459c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 460c5441932SPravin B Shelar const struct iphdr *tnl_params; 461ee34c1ebSMichal Schmidt 4622e15ea39SPravin B Shelar if (tunnel->collect_md) { 4632090714eSJiri Benc gre_fb_xmit(skb, dev, skb->protocol); 4642e15ea39SPravin B Shelar return NETDEV_TX_OK; 4652e15ea39SPravin B Shelar } 4662e15ea39SPravin B Shelar 467c5441932SPravin B Shelar if (dev->header_ops) { 468c5441932SPravin B Shelar /* Need space for new headers */ 469c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom - 4702bac7cb3SChen Gang (tunnel->hlen + sizeof(struct iphdr)))) 471c5441932SPravin B Shelar goto free_skb; 472ee34c1ebSMichal Schmidt 473c5441932SPravin B Shelar tnl_params = (const struct iphdr *)skb->data; 474cbb1e85fSDavid S. Miller 475c5441932SPravin B Shelar /* Pull skb since ip_tunnel_xmit() needs skb->data pointing 476c5441932SPravin B Shelar * to gre header. 477c5441932SPravin B Shelar */ 478c5441932SPravin B Shelar skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); 4798a0033a9STimo Teräs skb_reset_mac_header(skb); 480c5441932SPravin B Shelar } else { 481c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 482c5441932SPravin B Shelar goto free_skb; 483c5441932SPravin B Shelar 484c5441932SPravin B Shelar tnl_params = &tunnel->parms.iph; 485ee34c1ebSMichal Schmidt } 486e1a80002SHerbert Xu 487aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 488aed069dfSAlexander Duyck goto free_skb; 4898a0033a9STimo Teräs 490c5441932SPravin B Shelar __gre_xmit(skb, dev, tnl_params, skb->protocol); 491c5441932SPravin B Shelar return NETDEV_TX_OK; 492c5441932SPravin B Shelar 493c5441932SPravin B Shelar free_skb: 4943acfa1e7SEric Dumazet kfree_skb(skb); 495c5441932SPravin B Shelar dev->stats.tx_dropped++; 496c5441932SPravin B Shelar return NETDEV_TX_OK; 497ee34c1ebSMichal Schmidt } 498ee34c1ebSMichal Schmidt 499c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, 500c5441932SPravin B Shelar struct net_device *dev) 501c5441932SPravin B Shelar { 502c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 503ee34c1ebSMichal Schmidt 5042e15ea39SPravin B Shelar if (tunnel->collect_md) { 5052090714eSJiri Benc gre_fb_xmit(skb, dev, htons(ETH_P_TEB)); 5062e15ea39SPravin B Shelar return NETDEV_TX_OK; 5072e15ea39SPravin B Shelar } 5082e15ea39SPravin B Shelar 509aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 510aed069dfSAlexander Duyck goto free_skb; 511ee34c1ebSMichal Schmidt 512c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 513c5441932SPravin B Shelar goto free_skb; 51442aa9162SHerbert Xu 515c5441932SPravin B Shelar __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB)); 516c5441932SPravin B Shelar return NETDEV_TX_OK; 517c5441932SPravin B Shelar 518c5441932SPravin B Shelar free_skb: 5193acfa1e7SEric Dumazet kfree_skb(skb); 520c5441932SPravin B Shelar dev->stats.tx_dropped++; 521c5441932SPravin B Shelar return NETDEV_TX_OK; 52268c33163SPravin B Shelar } 523ee34c1ebSMichal Schmidt 524c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev, 525c5441932SPravin B Shelar struct ifreq *ifr, int cmd) 5261da177e4SLinus Torvalds { 5274565e991STom Herbert int err; 5281da177e4SLinus Torvalds struct ip_tunnel_parm p; 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 531c5441932SPravin B Shelar return -EFAULT; 5326c734fb8SCong Wang if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { 5331da177e4SLinus Torvalds if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || 5341da177e4SLinus Torvalds p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) || 5356c734fb8SCong Wang ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) 5361da177e4SLinus Torvalds return -EINVAL; 537c5441932SPravin B Shelar } 538c5441932SPravin B Shelar p.i_flags = gre_flags_to_tnl_flags(p.i_flags); 539c5441932SPravin B Shelar p.o_flags = gre_flags_to_tnl_flags(p.o_flags); 540c5441932SPravin B Shelar 541c5441932SPravin B Shelar err = ip_tunnel_ioctl(dev, &p, cmd); 542c5441932SPravin B Shelar if (err) 543c5441932SPravin B Shelar return err; 544c5441932SPravin B Shelar 54595f5c64cSTom Herbert p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags); 54695f5c64cSTom Herbert p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags); 547c5441932SPravin B Shelar 548c5441932SPravin B Shelar if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) 549c5441932SPravin B Shelar return -EFAULT; 5501da177e4SLinus Torvalds return 0; 5511da177e4SLinus Torvalds } 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-) 5541da177e4SLinus Torvalds It allows to construct virtual multiprotocol broadcast "LAN" 5551da177e4SLinus Torvalds over the Internet, provided multicast routing is tuned. 5561da177e4SLinus Torvalds 5571da177e4SLinus Torvalds 5581da177e4SLinus Torvalds I have no idea was this bicycle invented before me, 5591da177e4SLinus Torvalds so that I had to set ARPHRD_IPGRE to a random value. 5601da177e4SLinus Torvalds I have an impression, that Cisco could make something similar, 5611da177e4SLinus Torvalds but this feature is apparently missing in IOS<=11.2(8). 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks 5641da177e4SLinus Torvalds with broadcast 224.66.66.66. If you have access to mbone, play with me :-) 5651da177e4SLinus Torvalds 5661da177e4SLinus Torvalds ping -t 255 224.66.66.66 5671da177e4SLinus Torvalds 5681da177e4SLinus Torvalds If nobody answers, mbone does not work. 5691da177e4SLinus Torvalds 5701da177e4SLinus Torvalds ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 5711da177e4SLinus Torvalds ip addr add 10.66.66.<somewhat>/24 dev Universe 5721da177e4SLinus Torvalds ifconfig Universe up 5731da177e4SLinus Torvalds ifconfig Universe add fe80::<Your_real_addr>/10 5741da177e4SLinus Torvalds ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 5751da177e4SLinus Torvalds ftp 10.66.66.66 5761da177e4SLinus Torvalds ... 5771da177e4SLinus Torvalds ftp fec0:6666:6666::193.233.7.65 5781da177e4SLinus Torvalds ... 5791da177e4SLinus Torvalds */ 5803b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev, 5813b04dddeSStephen Hemminger unsigned short type, 5821507850bSEric Dumazet const void *daddr, const void *saddr, unsigned int len) 5831da177e4SLinus Torvalds { 5842941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 585c5441932SPravin B Shelar struct iphdr *iph; 586c5441932SPravin B Shelar struct gre_base_hdr *greh; 587c5441932SPravin B Shelar 588c5441932SPravin B Shelar iph = (struct iphdr *)skb_push(skb, t->hlen + sizeof(*iph)); 589c5441932SPravin B Shelar greh = (struct gre_base_hdr *)(iph+1); 59095f5c64cSTom Herbert greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags); 591c5441932SPravin B Shelar greh->protocol = htons(type); 5921da177e4SLinus Torvalds 5931da177e4SLinus Torvalds memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); 5941da177e4SLinus Torvalds 595c5441932SPravin B Shelar /* Set the source hardware address. */ 5961da177e4SLinus Torvalds if (saddr) 5971da177e4SLinus Torvalds memcpy(&iph->saddr, saddr, 4); 5986d55cb91STimo Teräs if (daddr) 5991da177e4SLinus Torvalds memcpy(&iph->daddr, daddr, 4); 6006d55cb91STimo Teräs if (iph->daddr) 60177a482bdSTimo Teräs return t->hlen + sizeof(*iph); 6021da177e4SLinus Torvalds 603c5441932SPravin B Shelar return -(t->hlen + sizeof(*iph)); 6041da177e4SLinus Torvalds } 6051da177e4SLinus Torvalds 6066a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) 6076a5f44d7STimo Teras { 608b71d1d42SEric Dumazet const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); 6096a5f44d7STimo Teras memcpy(haddr, &iph->saddr, 4); 6106a5f44d7STimo Teras return 4; 6116a5f44d7STimo Teras } 6126a5f44d7STimo Teras 6133b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = { 6143b04dddeSStephen Hemminger .create = ipgre_header, 6156a5f44d7STimo Teras .parse = ipgre_header_parse, 6163b04dddeSStephen Hemminger }; 6173b04dddeSStephen Hemminger 6186a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST 6191da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev) 6201da177e4SLinus Torvalds { 6212941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 6221da177e4SLinus Torvalds 623f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr)) { 624cbb1e85fSDavid S. Miller struct flowi4 fl4; 625cbb1e85fSDavid S. Miller struct rtable *rt; 626cbb1e85fSDavid S. Miller 627b57708adSNicolas Dichtel rt = ip_route_output_gre(t->net, &fl4, 62878fbfd8aSDavid S. Miller t->parms.iph.daddr, 62978fbfd8aSDavid S. Miller t->parms.iph.saddr, 63078fbfd8aSDavid S. Miller t->parms.o_key, 63178fbfd8aSDavid S. Miller RT_TOS(t->parms.iph.tos), 63278fbfd8aSDavid S. Miller t->parms.link); 633b23dd4feSDavid S. Miller if (IS_ERR(rt)) 6341da177e4SLinus Torvalds return -EADDRNOTAVAIL; 635d8d1f30bSChangli Gao dev = rt->dst.dev; 6361da177e4SLinus Torvalds ip_rt_put(rt); 63751456b29SIan Morris if (!__in_dev_get_rtnl(dev)) 6381da177e4SLinus Torvalds return -EADDRNOTAVAIL; 6391da177e4SLinus Torvalds t->mlink = dev->ifindex; 640e5ed6399SHerbert Xu ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); 6411da177e4SLinus Torvalds } 6421da177e4SLinus Torvalds return 0; 6431da177e4SLinus Torvalds } 6441da177e4SLinus Torvalds 6451da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev) 6461da177e4SLinus Torvalds { 6472941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 648b8c26a33SStephen Hemminger 649f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) { 6507fee0ca2SDenis V. Lunev struct in_device *in_dev; 651b57708adSNicolas Dichtel in_dev = inetdev_by_index(t->net, t->mlink); 6528723e1b4SEric Dumazet if (in_dev) 6531da177e4SLinus Torvalds ip_mc_dec_group(in_dev, t->parms.iph.daddr); 6541da177e4SLinus Torvalds } 6551da177e4SLinus Torvalds return 0; 6561da177e4SLinus Torvalds } 6571da177e4SLinus Torvalds #endif 6581da177e4SLinus Torvalds 659b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = { 660b8c26a33SStephen Hemminger .ndo_init = ipgre_tunnel_init, 661c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 662b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST 663b8c26a33SStephen Hemminger .ndo_open = ipgre_open, 664b8c26a33SStephen Hemminger .ndo_stop = ipgre_close, 665b8c26a33SStephen Hemminger #endif 666c5441932SPravin B Shelar .ndo_start_xmit = ipgre_xmit, 667b8c26a33SStephen Hemminger .ndo_do_ioctl = ipgre_tunnel_ioctl, 668c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 669c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 6701e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 671b8c26a33SStephen Hemminger }; 672b8c26a33SStephen Hemminger 6736b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG | \ 6746b78f16eSEric Dumazet NETIF_F_FRAGLIST | \ 6756b78f16eSEric Dumazet NETIF_F_HIGHDMA | \ 6766b78f16eSEric Dumazet NETIF_F_HW_CSUM) 6776b78f16eSEric Dumazet 6781da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev) 6791da177e4SLinus Torvalds { 680b8c26a33SStephen Hemminger dev->netdev_ops = &ipgre_netdev_ops; 6815a455275SNicolas Dichtel dev->type = ARPHRD_IPGRE; 682c5441932SPravin B Shelar ip_tunnel_setup(dev, ipgre_net_id); 683c5441932SPravin B Shelar } 6841da177e4SLinus Torvalds 685c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev) 686c5441932SPravin B Shelar { 687c5441932SPravin B Shelar struct ip_tunnel *tunnel; 6884565e991STom Herbert int t_hlen; 689c5441932SPravin B Shelar 690c5441932SPravin B Shelar tunnel = netdev_priv(dev); 69195f5c64cSTom Herbert tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 692c5441932SPravin B Shelar tunnel->parms.iph.protocol = IPPROTO_GRE; 693c5441932SPravin B Shelar 6944565e991STom Herbert tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; 6954565e991STom Herbert 6964565e991STom Herbert t_hlen = tunnel->hlen + sizeof(struct iphdr); 6974565e991STom Herbert 6984565e991STom Herbert dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; 6994565e991STom Herbert dev->mtu = ETH_DATA_LEN - t_hlen - 4; 7006b78f16eSEric Dumazet 701b57708adSNicolas Dichtel dev->features |= GRE_FEATURES; 7026b78f16eSEric Dumazet dev->hw_features |= GRE_FEATURES; 703c5441932SPravin B Shelar 704c5441932SPravin B Shelar if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 705a0ca153fSAlexander Duyck /* TCP offload with GRE SEQ is not supported, nor 706a0ca153fSAlexander Duyck * can we support 2 levels of outer headers requiring 707a0ca153fSAlexander Duyck * an update. 708a0ca153fSAlexander Duyck */ 709a0ca153fSAlexander Duyck if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || 710a0ca153fSAlexander Duyck (tunnel->encap.type == TUNNEL_ENCAP_NONE)) { 711c5441932SPravin B Shelar dev->features |= NETIF_F_GSO_SOFTWARE; 712c5441932SPravin B Shelar dev->hw_features |= NETIF_F_GSO_SOFTWARE; 713a0ca153fSAlexander Duyck } 714a0ca153fSAlexander Duyck 715c5441932SPravin B Shelar /* Can use a lockless transmit, unless we generate 716c5441932SPravin B Shelar * output sequences 717c5441932SPravin B Shelar */ 718c5441932SPravin B Shelar dev->features |= NETIF_F_LLTX; 719c5441932SPravin B Shelar } 7201da177e4SLinus Torvalds } 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev) 7231da177e4SLinus Torvalds { 724c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 725c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 7261da177e4SLinus Torvalds 727c5441932SPravin B Shelar __gre_tunnel_init(dev); 7281da177e4SLinus Torvalds 729c5441932SPravin B Shelar memcpy(dev->dev_addr, &iph->saddr, 4); 730c5441932SPravin B Shelar memcpy(dev->broadcast, &iph->daddr, 4); 7311da177e4SLinus Torvalds 732c5441932SPravin B Shelar dev->flags = IFF_NOARP; 73302875878SEric Dumazet netif_keep_dst(dev); 734c5441932SPravin B Shelar dev->addr_len = 4; 7351da177e4SLinus Torvalds 736a64b04d8SJiri Benc if (iph->daddr && !tunnel->collect_md) { 7371da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST 738f97c1e0cSJoe Perches if (ipv4_is_multicast(iph->daddr)) { 7391da177e4SLinus Torvalds if (!iph->saddr) 7401da177e4SLinus Torvalds return -EINVAL; 7411da177e4SLinus Torvalds dev->flags = IFF_BROADCAST; 7423b04dddeSStephen Hemminger dev->header_ops = &ipgre_header_ops; 7431da177e4SLinus Torvalds } 7441da177e4SLinus Torvalds #endif 745a64b04d8SJiri Benc } else if (!tunnel->collect_md) { 7466a5f44d7STimo Teras dev->header_ops = &ipgre_header_ops; 747a64b04d8SJiri Benc } 7481da177e4SLinus Torvalds 749c5441932SPravin B Shelar return ip_tunnel_init(dev); 75060769a5dSEric Dumazet } 75160769a5dSEric Dumazet 7529f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = { 7539f57c67cSPravin B Shelar .handler = gre_rcv, 7549f57c67cSPravin B Shelar .err_handler = gre_err, 7551da177e4SLinus Torvalds }; 7561da177e4SLinus Torvalds 7572c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net) 75859a4c759SPavel Emelyanov { 759c5441932SPravin B Shelar return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); 76059a4c759SPavel Emelyanov } 76159a4c759SPavel Emelyanov 7622c8c1e72SAlexey Dobriyan static void __net_exit ipgre_exit_net(struct net *net) 76359a4c759SPavel Emelyanov { 764c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id); 7656c742e71SNicolas Dichtel ip_tunnel_delete_net(itn, &ipgre_link_ops); 76659a4c759SPavel Emelyanov } 76759a4c759SPavel Emelyanov 76859a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = { 76959a4c759SPavel Emelyanov .init = ipgre_init_net, 77059a4c759SPavel Emelyanov .exit = ipgre_exit_net, 771cfb8fbf2SEric W. Biederman .id = &ipgre_net_id, 772c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 77359a4c759SPavel Emelyanov }; 7741da177e4SLinus Torvalds 775c19e654dSHerbert Xu static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) 776c19e654dSHerbert Xu { 777c19e654dSHerbert Xu __be16 flags; 778c19e654dSHerbert Xu 779c19e654dSHerbert Xu if (!data) 780c19e654dSHerbert Xu return 0; 781c19e654dSHerbert Xu 782c19e654dSHerbert Xu flags = 0; 783c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 784c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 785c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 786c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 787c19e654dSHerbert Xu if (flags & (GRE_VERSION|GRE_ROUTING)) 788c19e654dSHerbert Xu return -EINVAL; 789c19e654dSHerbert Xu 790946b636fSJiri Benc if (data[IFLA_GRE_COLLECT_METADATA] && 791946b636fSJiri Benc data[IFLA_GRE_ENCAP_TYPE] && 792946b636fSJiri Benc nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) 793946b636fSJiri Benc return -EINVAL; 794946b636fSJiri Benc 795c19e654dSHerbert Xu return 0; 796c19e654dSHerbert Xu } 797c19e654dSHerbert Xu 798e1a80002SHerbert Xu static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[]) 799e1a80002SHerbert Xu { 800e1a80002SHerbert Xu __be32 daddr; 801e1a80002SHerbert Xu 802e1a80002SHerbert Xu if (tb[IFLA_ADDRESS]) { 803e1a80002SHerbert Xu if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) 804e1a80002SHerbert Xu return -EINVAL; 805e1a80002SHerbert Xu if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 806e1a80002SHerbert Xu return -EADDRNOTAVAIL; 807e1a80002SHerbert Xu } 808e1a80002SHerbert Xu 809e1a80002SHerbert Xu if (!data) 810e1a80002SHerbert Xu goto out; 811e1a80002SHerbert Xu 812e1a80002SHerbert Xu if (data[IFLA_GRE_REMOTE]) { 813e1a80002SHerbert Xu memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); 814e1a80002SHerbert Xu if (!daddr) 815e1a80002SHerbert Xu return -EINVAL; 816e1a80002SHerbert Xu } 817e1a80002SHerbert Xu 818e1a80002SHerbert Xu out: 819e1a80002SHerbert Xu return ipgre_tunnel_validate(tb, data); 820e1a80002SHerbert Xu } 821e1a80002SHerbert Xu 8222e15ea39SPravin B Shelar static void ipgre_netlink_parms(struct net_device *dev, 8232e15ea39SPravin B Shelar struct nlattr *data[], 8242e15ea39SPravin B Shelar struct nlattr *tb[], 825c19e654dSHerbert Xu struct ip_tunnel_parm *parms) 826c19e654dSHerbert Xu { 8277bb82d92SHerbert Xu memset(parms, 0, sizeof(*parms)); 828c19e654dSHerbert Xu 829c19e654dSHerbert Xu parms->iph.protocol = IPPROTO_GRE; 830c19e654dSHerbert Xu 831c19e654dSHerbert Xu if (!data) 832c19e654dSHerbert Xu return; 833c19e654dSHerbert Xu 834c19e654dSHerbert Xu if (data[IFLA_GRE_LINK]) 835c19e654dSHerbert Xu parms->link = nla_get_u32(data[IFLA_GRE_LINK]); 836c19e654dSHerbert Xu 837c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 838c5441932SPravin B Shelar parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); 839c19e654dSHerbert Xu 840c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 841c5441932SPravin B Shelar parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); 842c19e654dSHerbert Xu 843c19e654dSHerbert Xu if (data[IFLA_GRE_IKEY]) 844c19e654dSHerbert Xu parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); 845c19e654dSHerbert Xu 846c19e654dSHerbert Xu if (data[IFLA_GRE_OKEY]) 847c19e654dSHerbert Xu parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); 848c19e654dSHerbert Xu 849c19e654dSHerbert Xu if (data[IFLA_GRE_LOCAL]) 85067b61f6cSJiri Benc parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); 851c19e654dSHerbert Xu 852c19e654dSHerbert Xu if (data[IFLA_GRE_REMOTE]) 85367b61f6cSJiri Benc parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); 854c19e654dSHerbert Xu 855c19e654dSHerbert Xu if (data[IFLA_GRE_TTL]) 856c19e654dSHerbert Xu parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); 857c19e654dSHerbert Xu 858c19e654dSHerbert Xu if (data[IFLA_GRE_TOS]) 859c19e654dSHerbert Xu parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); 860c19e654dSHerbert Xu 861c19e654dSHerbert Xu if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) 862c19e654dSHerbert Xu parms->iph.frag_off = htons(IP_DF); 8632e15ea39SPravin B Shelar 8642e15ea39SPravin B Shelar if (data[IFLA_GRE_COLLECT_METADATA]) { 8652e15ea39SPravin B Shelar struct ip_tunnel *t = netdev_priv(dev); 8662e15ea39SPravin B Shelar 8672e15ea39SPravin B Shelar t->collect_md = true; 8682e15ea39SPravin B Shelar } 869c19e654dSHerbert Xu } 870c19e654dSHerbert Xu 8714565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */ 8724565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[], 8734565e991STom Herbert struct ip_tunnel_encap *ipencap) 8744565e991STom Herbert { 8754565e991STom Herbert bool ret = false; 8764565e991STom Herbert 8774565e991STom Herbert memset(ipencap, 0, sizeof(*ipencap)); 8784565e991STom Herbert 8794565e991STom Herbert if (!data) 8804565e991STom Herbert return ret; 8814565e991STom Herbert 8824565e991STom Herbert if (data[IFLA_GRE_ENCAP_TYPE]) { 8834565e991STom Herbert ret = true; 8844565e991STom Herbert ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); 8854565e991STom Herbert } 8864565e991STom Herbert 8874565e991STom Herbert if (data[IFLA_GRE_ENCAP_FLAGS]) { 8884565e991STom Herbert ret = true; 8894565e991STom Herbert ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); 8904565e991STom Herbert } 8914565e991STom Herbert 8924565e991STom Herbert if (data[IFLA_GRE_ENCAP_SPORT]) { 8934565e991STom Herbert ret = true; 8943e97fa70SSabrina Dubroca ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); 8954565e991STom Herbert } 8964565e991STom Herbert 8974565e991STom Herbert if (data[IFLA_GRE_ENCAP_DPORT]) { 8984565e991STom Herbert ret = true; 8993e97fa70SSabrina Dubroca ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); 9004565e991STom Herbert } 9014565e991STom Herbert 9024565e991STom Herbert return ret; 9034565e991STom Herbert } 9044565e991STom Herbert 905c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev) 906e1a80002SHerbert Xu { 907c5441932SPravin B Shelar __gre_tunnel_init(dev); 908bec94d43Sstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 909e1a80002SHerbert Xu 910c5441932SPravin B Shelar return ip_tunnel_init(dev); 911e1a80002SHerbert Xu } 912e1a80002SHerbert Xu 913c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = { 914c5441932SPravin B Shelar .ndo_init = gre_tap_init, 915c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 916c5441932SPravin B Shelar .ndo_start_xmit = gre_tap_xmit, 917b8c26a33SStephen Hemminger .ndo_set_mac_address = eth_mac_addr, 918b8c26a33SStephen Hemminger .ndo_validate_addr = eth_validate_addr, 919c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 920c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 9211e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 922fc4099f1SPravin B Shelar .ndo_fill_metadata_dst = gre_fill_metadata_dst, 923b8c26a33SStephen Hemminger }; 924b8c26a33SStephen Hemminger 925e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev) 926e1a80002SHerbert Xu { 927e1a80002SHerbert Xu ether_setup(dev); 928c5441932SPravin B Shelar dev->netdev_ops = &gre_tap_netdev_ops; 929d13b161cSJiri Benc dev->priv_flags &= ~IFF_TX_SKB_SHARING; 930f8c1b7ceSstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 931c5441932SPravin B Shelar ip_tunnel_setup(dev, gre_tap_net_id); 932e1a80002SHerbert Xu } 933e1a80002SHerbert Xu 934c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev, 935c5441932SPravin B Shelar struct nlattr *tb[], struct nlattr *data[]) 936c19e654dSHerbert Xu { 937c5441932SPravin B Shelar struct ip_tunnel_parm p; 9384565e991STom Herbert struct ip_tunnel_encap ipencap; 9394565e991STom Herbert 9404565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 9414565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 9424565e991STom Herbert int err = ip_tunnel_encap_setup(t, &ipencap); 9434565e991STom Herbert 9444565e991STom Herbert if (err < 0) 9454565e991STom Herbert return err; 9464565e991STom Herbert } 947c19e654dSHerbert Xu 9482e15ea39SPravin B Shelar ipgre_netlink_parms(dev, data, tb, &p); 949c5441932SPravin B Shelar return ip_tunnel_newlink(dev, tb, &p); 950c19e654dSHerbert Xu } 951c19e654dSHerbert Xu 952c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], 953c19e654dSHerbert Xu struct nlattr *data[]) 954c19e654dSHerbert Xu { 955c19e654dSHerbert Xu struct ip_tunnel_parm p; 9564565e991STom Herbert struct ip_tunnel_encap ipencap; 9574565e991STom Herbert 9584565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 9594565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 9604565e991STom Herbert int err = ip_tunnel_encap_setup(t, &ipencap); 9614565e991STom Herbert 9624565e991STom Herbert if (err < 0) 9634565e991STom Herbert return err; 9644565e991STom Herbert } 965c19e654dSHerbert Xu 9662e15ea39SPravin B Shelar ipgre_netlink_parms(dev, data, tb, &p); 967c5441932SPravin B Shelar return ip_tunnel_changelink(dev, tb, &p); 968c19e654dSHerbert Xu } 969c19e654dSHerbert Xu 970c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev) 971c19e654dSHerbert Xu { 972c19e654dSHerbert Xu return 973c19e654dSHerbert Xu /* IFLA_GRE_LINK */ 974c19e654dSHerbert Xu nla_total_size(4) + 975c19e654dSHerbert Xu /* IFLA_GRE_IFLAGS */ 976c19e654dSHerbert Xu nla_total_size(2) + 977c19e654dSHerbert Xu /* IFLA_GRE_OFLAGS */ 978c19e654dSHerbert Xu nla_total_size(2) + 979c19e654dSHerbert Xu /* IFLA_GRE_IKEY */ 980c19e654dSHerbert Xu nla_total_size(4) + 981c19e654dSHerbert Xu /* IFLA_GRE_OKEY */ 982c19e654dSHerbert Xu nla_total_size(4) + 983c19e654dSHerbert Xu /* IFLA_GRE_LOCAL */ 984c19e654dSHerbert Xu nla_total_size(4) + 985c19e654dSHerbert Xu /* IFLA_GRE_REMOTE */ 986c19e654dSHerbert Xu nla_total_size(4) + 987c19e654dSHerbert Xu /* IFLA_GRE_TTL */ 988c19e654dSHerbert Xu nla_total_size(1) + 989c19e654dSHerbert Xu /* IFLA_GRE_TOS */ 990c19e654dSHerbert Xu nla_total_size(1) + 991c19e654dSHerbert Xu /* IFLA_GRE_PMTUDISC */ 992c19e654dSHerbert Xu nla_total_size(1) + 9934565e991STom Herbert /* IFLA_GRE_ENCAP_TYPE */ 9944565e991STom Herbert nla_total_size(2) + 9954565e991STom Herbert /* IFLA_GRE_ENCAP_FLAGS */ 9964565e991STom Herbert nla_total_size(2) + 9974565e991STom Herbert /* IFLA_GRE_ENCAP_SPORT */ 9984565e991STom Herbert nla_total_size(2) + 9994565e991STom Herbert /* IFLA_GRE_ENCAP_DPORT */ 10004565e991STom Herbert nla_total_size(2) + 10012e15ea39SPravin B Shelar /* IFLA_GRE_COLLECT_METADATA */ 10022e15ea39SPravin B Shelar nla_total_size(0) + 1003c19e654dSHerbert Xu 0; 1004c19e654dSHerbert Xu } 1005c19e654dSHerbert Xu 1006c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) 1007c19e654dSHerbert Xu { 1008c19e654dSHerbert Xu struct ip_tunnel *t = netdev_priv(dev); 1009c19e654dSHerbert Xu struct ip_tunnel_parm *p = &t->parms; 1010c19e654dSHerbert Xu 1011f3756b79SDavid S. Miller if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || 101295f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_IFLAGS, 101395f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->i_flags)) || 101495f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_OFLAGS, 101595f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->o_flags)) || 1016f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || 1017f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || 1018930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || 1019930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) || 1020f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) || 1021f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) || 1022f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_PMTUDISC, 1023f3756b79SDavid S. Miller !!(p->iph.frag_off & htons(IP_DF)))) 1024f3756b79SDavid S. Miller goto nla_put_failure; 10254565e991STom Herbert 10264565e991STom Herbert if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, 10274565e991STom Herbert t->encap.type) || 10283e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, 10294565e991STom Herbert t->encap.sport) || 10303e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, 10314565e991STom Herbert t->encap.dport) || 10324565e991STom Herbert nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, 1033e1b2cb65STom Herbert t->encap.flags)) 10344565e991STom Herbert goto nla_put_failure; 10354565e991STom Herbert 10362e15ea39SPravin B Shelar if (t->collect_md) { 10372e15ea39SPravin B Shelar if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) 10382e15ea39SPravin B Shelar goto nla_put_failure; 10392e15ea39SPravin B Shelar } 10402e15ea39SPravin B Shelar 1041c19e654dSHerbert Xu return 0; 1042c19e654dSHerbert Xu 1043c19e654dSHerbert Xu nla_put_failure: 1044c19e654dSHerbert Xu return -EMSGSIZE; 1045c19e654dSHerbert Xu } 1046c19e654dSHerbert Xu 1047c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { 1048c19e654dSHerbert Xu [IFLA_GRE_LINK] = { .type = NLA_U32 }, 1049c19e654dSHerbert Xu [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, 1050c19e654dSHerbert Xu [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, 1051c19e654dSHerbert Xu [IFLA_GRE_IKEY] = { .type = NLA_U32 }, 1052c19e654dSHerbert Xu [IFLA_GRE_OKEY] = { .type = NLA_U32 }, 10534d74f8baSPatrick McHardy [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, 10544d74f8baSPatrick McHardy [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, 1055c19e654dSHerbert Xu [IFLA_GRE_TTL] = { .type = NLA_U8 }, 1056c19e654dSHerbert Xu [IFLA_GRE_TOS] = { .type = NLA_U8 }, 1057c19e654dSHerbert Xu [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, 10584565e991STom Herbert [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, 10594565e991STom Herbert [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, 10604565e991STom Herbert [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, 10614565e991STom Herbert [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, 10622e15ea39SPravin B Shelar [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, 1063c19e654dSHerbert Xu }; 1064c19e654dSHerbert Xu 1065c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = { 1066c19e654dSHerbert Xu .kind = "gre", 1067c19e654dSHerbert Xu .maxtype = IFLA_GRE_MAX, 1068c19e654dSHerbert Xu .policy = ipgre_policy, 1069c19e654dSHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1070c19e654dSHerbert Xu .setup = ipgre_tunnel_setup, 1071c19e654dSHerbert Xu .validate = ipgre_tunnel_validate, 1072c19e654dSHerbert Xu .newlink = ipgre_newlink, 1073c19e654dSHerbert Xu .changelink = ipgre_changelink, 1074c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1075c19e654dSHerbert Xu .get_size = ipgre_get_size, 1076c19e654dSHerbert Xu .fill_info = ipgre_fill_info, 10771728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1078c19e654dSHerbert Xu }; 1079c19e654dSHerbert Xu 1080e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { 1081e1a80002SHerbert Xu .kind = "gretap", 1082e1a80002SHerbert Xu .maxtype = IFLA_GRE_MAX, 1083e1a80002SHerbert Xu .policy = ipgre_policy, 1084e1a80002SHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1085e1a80002SHerbert Xu .setup = ipgre_tap_setup, 1086e1a80002SHerbert Xu .validate = ipgre_tap_validate, 1087e1a80002SHerbert Xu .newlink = ipgre_newlink, 1088e1a80002SHerbert Xu .changelink = ipgre_changelink, 1089c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1090e1a80002SHerbert Xu .get_size = ipgre_get_size, 1091e1a80002SHerbert Xu .fill_info = ipgre_fill_info, 10921728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1093e1a80002SHerbert Xu }; 1094e1a80002SHerbert Xu 1095b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name, 1096b2acd1dcSPravin B Shelar u8 name_assign_type) 1097b2acd1dcSPravin B Shelar { 1098b2acd1dcSPravin B Shelar struct nlattr *tb[IFLA_MAX + 1]; 1099b2acd1dcSPravin B Shelar struct net_device *dev; 1100b2acd1dcSPravin B Shelar struct ip_tunnel *t; 1101b2acd1dcSPravin B Shelar int err; 1102b2acd1dcSPravin B Shelar 1103b2acd1dcSPravin B Shelar memset(&tb, 0, sizeof(tb)); 1104b2acd1dcSPravin B Shelar 1105b2acd1dcSPravin B Shelar dev = rtnl_create_link(net, name, name_assign_type, 1106b2acd1dcSPravin B Shelar &ipgre_tap_ops, tb); 1107b2acd1dcSPravin B Shelar if (IS_ERR(dev)) 1108b2acd1dcSPravin B Shelar return dev; 1109b2acd1dcSPravin B Shelar 1110b2acd1dcSPravin B Shelar /* Configure flow based GRE device. */ 1111b2acd1dcSPravin B Shelar t = netdev_priv(dev); 1112b2acd1dcSPravin B Shelar t->collect_md = true; 1113b2acd1dcSPravin B Shelar 1114b2acd1dcSPravin B Shelar err = ipgre_newlink(net, dev, tb, NULL); 1115b2acd1dcSPravin B Shelar if (err < 0) 1116b2acd1dcSPravin B Shelar goto out; 11177e059158SDavid Wragg 11187e059158SDavid Wragg /* openvswitch users expect packet sizes to be unrestricted, 11197e059158SDavid Wragg * so set the largest MTU we can. 11207e059158SDavid Wragg */ 11217e059158SDavid Wragg err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); 11227e059158SDavid Wragg if (err) 11237e059158SDavid Wragg goto out; 11247e059158SDavid Wragg 1125b2acd1dcSPravin B Shelar return dev; 1126b2acd1dcSPravin B Shelar out: 1127b2acd1dcSPravin B Shelar free_netdev(dev); 1128b2acd1dcSPravin B Shelar return ERR_PTR(err); 1129b2acd1dcSPravin B Shelar } 1130b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create); 1131b2acd1dcSPravin B Shelar 1132c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net) 1133c5441932SPravin B Shelar { 11342e15ea39SPravin B Shelar return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); 1135c5441932SPravin B Shelar } 1136c5441932SPravin B Shelar 1137c5441932SPravin B Shelar static void __net_exit ipgre_tap_exit_net(struct net *net) 1138c5441932SPravin B Shelar { 1139c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id); 11406c742e71SNicolas Dichtel ip_tunnel_delete_net(itn, &ipgre_tap_ops); 1141c5441932SPravin B Shelar } 1142c5441932SPravin B Shelar 1143c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = { 1144c5441932SPravin B Shelar .init = ipgre_tap_init_net, 1145c5441932SPravin B Shelar .exit = ipgre_tap_exit_net, 1146c5441932SPravin B Shelar .id = &gre_tap_net_id, 1147c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 1148c5441932SPravin B Shelar }; 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvalds static int __init ipgre_init(void) 11511da177e4SLinus Torvalds { 11521da177e4SLinus Torvalds int err; 11531da177e4SLinus Torvalds 1154058bd4d2SJoe Perches pr_info("GRE over IPv4 tunneling driver\n"); 11551da177e4SLinus Torvalds 1156cfb8fbf2SEric W. Biederman err = register_pernet_device(&ipgre_net_ops); 115759a4c759SPavel Emelyanov if (err < 0) 1158c2892f02SAlexey Dobriyan return err; 1159c2892f02SAlexey Dobriyan 1160c5441932SPravin B Shelar err = register_pernet_device(&ipgre_tap_net_ops); 1161c5441932SPravin B Shelar if (err < 0) 1162c5441932SPravin B Shelar goto pnet_tap_faied; 1163c5441932SPravin B Shelar 11649f57c67cSPravin B Shelar err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); 1165c2892f02SAlexey Dobriyan if (err < 0) { 1166058bd4d2SJoe Perches pr_info("%s: can't add protocol\n", __func__); 1167c2892f02SAlexey Dobriyan goto add_proto_failed; 1168c2892f02SAlexey Dobriyan } 11697daa0004SPavel Emelyanov 1170c19e654dSHerbert Xu err = rtnl_link_register(&ipgre_link_ops); 1171c19e654dSHerbert Xu if (err < 0) 1172c19e654dSHerbert Xu goto rtnl_link_failed; 1173c19e654dSHerbert Xu 1174e1a80002SHerbert Xu err = rtnl_link_register(&ipgre_tap_ops); 1175e1a80002SHerbert Xu if (err < 0) 1176e1a80002SHerbert Xu goto tap_ops_failed; 1177e1a80002SHerbert Xu 1178c5441932SPravin B Shelar return 0; 1179c19e654dSHerbert Xu 1180e1a80002SHerbert Xu tap_ops_failed: 1181e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 1182c19e654dSHerbert Xu rtnl_link_failed: 11839f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1184c2892f02SAlexey Dobriyan add_proto_failed: 1185c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1186c5441932SPravin B Shelar pnet_tap_faied: 1187c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 1188c5441932SPravin B Shelar return err; 11891da177e4SLinus Torvalds } 11901da177e4SLinus Torvalds 1191db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void) 11921da177e4SLinus Torvalds { 1193e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_tap_ops); 1194c19e654dSHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 11959f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1196c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1197c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 11981da177e4SLinus Torvalds } 11991da177e4SLinus Torvalds 12001da177e4SLinus Torvalds module_init(ipgre_init); 12011da177e4SLinus Torvalds module_exit(ipgre_fini); 12021da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 12034d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre"); 12044d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap"); 12058909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0"); 1206c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0"); 1207