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 int ip_gre_calc_hlen(__be16 o_flags) 1269f57c67cSPravin B Shelar { 1279f57c67cSPravin B Shelar int addend = 4; 1289f57c67cSPravin B Shelar 1299f57c67cSPravin B Shelar if (o_flags & TUNNEL_CSUM) 1309f57c67cSPravin B Shelar addend += 4; 1319f57c67cSPravin B Shelar if (o_flags & TUNNEL_KEY) 1329f57c67cSPravin B Shelar addend += 4; 1339f57c67cSPravin B Shelar if (o_flags & TUNNEL_SEQ) 1349f57c67cSPravin B Shelar addend += 4; 1359f57c67cSPravin B Shelar return addend; 1369f57c67cSPravin B Shelar } 1379f57c67cSPravin B Shelar 1389f57c67cSPravin B Shelar static __be16 gre_flags_to_tnl_flags(__be16 flags) 1399f57c67cSPravin B Shelar { 1409f57c67cSPravin B Shelar __be16 tflags = 0; 1419f57c67cSPravin B Shelar 1429f57c67cSPravin B Shelar if (flags & GRE_CSUM) 1439f57c67cSPravin B Shelar tflags |= TUNNEL_CSUM; 1449f57c67cSPravin B Shelar if (flags & GRE_ROUTING) 1459f57c67cSPravin B Shelar tflags |= TUNNEL_ROUTING; 1469f57c67cSPravin B Shelar if (flags & GRE_KEY) 1479f57c67cSPravin B Shelar tflags |= TUNNEL_KEY; 1489f57c67cSPravin B Shelar if (flags & GRE_SEQ) 1499f57c67cSPravin B Shelar tflags |= TUNNEL_SEQ; 1509f57c67cSPravin B Shelar if (flags & GRE_STRICT) 1519f57c67cSPravin B Shelar tflags |= TUNNEL_STRICT; 1529f57c67cSPravin B Shelar if (flags & GRE_REC) 1539f57c67cSPravin B Shelar tflags |= TUNNEL_REC; 1549f57c67cSPravin B Shelar if (flags & GRE_VERSION) 1559f57c67cSPravin B Shelar tflags |= TUNNEL_VERSION; 1569f57c67cSPravin B Shelar 1579f57c67cSPravin B Shelar return tflags; 1589f57c67cSPravin B Shelar } 1599f57c67cSPravin B Shelar 1609f57c67cSPravin B Shelar static __be16 tnl_flags_to_gre_flags(__be16 tflags) 1619f57c67cSPravin B Shelar { 1629f57c67cSPravin B Shelar __be16 flags = 0; 1639f57c67cSPravin B Shelar 1649f57c67cSPravin B Shelar if (tflags & TUNNEL_CSUM) 1659f57c67cSPravin B Shelar flags |= GRE_CSUM; 1669f57c67cSPravin B Shelar if (tflags & TUNNEL_ROUTING) 1679f57c67cSPravin B Shelar flags |= GRE_ROUTING; 1689f57c67cSPravin B Shelar if (tflags & TUNNEL_KEY) 1699f57c67cSPravin B Shelar flags |= GRE_KEY; 1709f57c67cSPravin B Shelar if (tflags & TUNNEL_SEQ) 1719f57c67cSPravin B Shelar flags |= GRE_SEQ; 1729f57c67cSPravin B Shelar if (tflags & TUNNEL_STRICT) 1739f57c67cSPravin B Shelar flags |= GRE_STRICT; 1749f57c67cSPravin B Shelar if (tflags & TUNNEL_REC) 1759f57c67cSPravin B Shelar flags |= GRE_REC; 1769f57c67cSPravin B Shelar if (tflags & TUNNEL_VERSION) 1779f57c67cSPravin B Shelar flags |= GRE_VERSION; 1789f57c67cSPravin B Shelar 1799f57c67cSPravin B Shelar return flags; 1809f57c67cSPravin B Shelar } 1819f57c67cSPravin B Shelar 1829f57c67cSPravin B Shelar static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, 1839f57c67cSPravin B Shelar bool *csum_err) 1849f57c67cSPravin B Shelar { 1859f57c67cSPravin B Shelar const struct gre_base_hdr *greh; 1869f57c67cSPravin B Shelar __be32 *options; 1879f57c67cSPravin B Shelar int hdr_len; 1889f57c67cSPravin B Shelar 1899f57c67cSPravin B Shelar if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr)))) 1909f57c67cSPravin B Shelar return -EINVAL; 1919f57c67cSPravin B Shelar 1929f57c67cSPravin B Shelar greh = (struct gre_base_hdr *)skb_transport_header(skb); 1939f57c67cSPravin B Shelar if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING))) 1949f57c67cSPravin B Shelar return -EINVAL; 1959f57c67cSPravin B Shelar 1969f57c67cSPravin B Shelar tpi->flags = gre_flags_to_tnl_flags(greh->flags); 1979f57c67cSPravin B Shelar hdr_len = ip_gre_calc_hlen(tpi->flags); 1989f57c67cSPravin B Shelar 1999f57c67cSPravin B Shelar if (!pskb_may_pull(skb, hdr_len)) 2009f57c67cSPravin B Shelar return -EINVAL; 2019f57c67cSPravin B Shelar 2029f57c67cSPravin B Shelar greh = (struct gre_base_hdr *)skb_transport_header(skb); 2039f57c67cSPravin B Shelar tpi->proto = greh->protocol; 2049f57c67cSPravin B Shelar 2059f57c67cSPravin B Shelar options = (__be32 *)(greh + 1); 2069f57c67cSPravin B Shelar if (greh->flags & GRE_CSUM) { 2079f57c67cSPravin B Shelar if (skb_checksum_simple_validate(skb)) { 2089f57c67cSPravin B Shelar *csum_err = true; 2099f57c67cSPravin B Shelar return -EINVAL; 2109f57c67cSPravin B Shelar } 2119f57c67cSPravin B Shelar 2129f57c67cSPravin B Shelar skb_checksum_try_convert(skb, IPPROTO_GRE, 0, 2139f57c67cSPravin B Shelar null_compute_pseudo); 2149f57c67cSPravin B Shelar options++; 2159f57c67cSPravin B Shelar } 2169f57c67cSPravin B Shelar 2179f57c67cSPravin B Shelar if (greh->flags & GRE_KEY) { 2189f57c67cSPravin B Shelar tpi->key = *options; 2199f57c67cSPravin B Shelar options++; 2209f57c67cSPravin B Shelar } else { 2219f57c67cSPravin B Shelar tpi->key = 0; 2229f57c67cSPravin B Shelar } 2239f57c67cSPravin B Shelar if (unlikely(greh->flags & GRE_SEQ)) { 2249f57c67cSPravin B Shelar tpi->seq = *options; 2259f57c67cSPravin B Shelar options++; 2269f57c67cSPravin B Shelar } else { 2279f57c67cSPravin B Shelar tpi->seq = 0; 2289f57c67cSPravin B Shelar } 2299f57c67cSPravin B Shelar /* WCCP version 1 and 2 protocol decoding. 2309f57c67cSPravin B Shelar * - Change protocol to IP 2319f57c67cSPravin B Shelar * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header 2329f57c67cSPravin B Shelar */ 2339f57c67cSPravin B Shelar if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { 2349f57c67cSPravin B Shelar tpi->proto = htons(ETH_P_IP); 2359f57c67cSPravin B Shelar if ((*(u8 *)options & 0xF0) != 0x40) { 2369f57c67cSPravin B Shelar hdr_len += 4; 2379f57c67cSPravin B Shelar if (!pskb_may_pull(skb, hdr_len)) 2389f57c67cSPravin B Shelar return -EINVAL; 2399f57c67cSPravin B Shelar } 2409f57c67cSPravin B Shelar } 2419f57c67cSPravin B Shelar return iptunnel_pull_header(skb, hdr_len, tpi->proto); 2429f57c67cSPravin B Shelar } 2439f57c67cSPravin B Shelar 2449f57c67cSPravin B Shelar static void ipgre_err(struct sk_buff *skb, u32 info, 245bda7bb46SPravin B Shelar const struct tnl_ptk_info *tpi) 2461da177e4SLinus Torvalds { 2471da177e4SLinus Torvalds 248071f92d0SRami Rosen /* All the routers (except for Linux) return only 2491da177e4SLinus Torvalds 8 bytes of packet payload. It means, that precise relaying of 2501da177e4SLinus Torvalds ICMP in the real Internet is absolutely infeasible. 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds Moreover, Cisco "wise men" put GRE key to the third word 253c5441932SPravin B Shelar in GRE header. It makes impossible maintaining even soft 254c5441932SPravin B Shelar state for keyed GRE tunnels with enabled checksum. Tell 255c5441932SPravin B Shelar them "thank you". 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds Well, I wonder, rfc1812 was written by Cisco employee, 258bff52857Sstephen hemminger what the hell these idiots break standards established 259bff52857Sstephen hemminger by themselves??? 2601da177e4SLinus Torvalds */ 261c5441932SPravin B Shelar struct net *net = dev_net(skb->dev); 262c5441932SPravin B Shelar struct ip_tunnel_net *itn; 26396f5a846SEric Dumazet const struct iphdr *iph; 26488c7664fSArnaldo Carvalho de Melo const int type = icmp_hdr(skb)->type; 26588c7664fSArnaldo Carvalho de Melo const int code = icmp_hdr(skb)->code; 2661da177e4SLinus Torvalds struct ip_tunnel *t; 267d2083287Sstephen hemminger 2681da177e4SLinus Torvalds switch (type) { 2691da177e4SLinus Torvalds default: 2701da177e4SLinus Torvalds case ICMP_PARAMETERPROB: 2719f57c67cSPravin B Shelar return; 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds case ICMP_DEST_UNREACH: 2741da177e4SLinus Torvalds switch (code) { 2751da177e4SLinus Torvalds case ICMP_SR_FAILED: 2761da177e4SLinus Torvalds case ICMP_PORT_UNREACH: 2771da177e4SLinus Torvalds /* Impossible event. */ 2789f57c67cSPravin B Shelar return; 2791da177e4SLinus Torvalds default: 2801da177e4SLinus Torvalds /* All others are translated to HOST_UNREACH. 2811da177e4SLinus Torvalds rfc2003 contains "deep thoughts" about NET_UNREACH, 2821da177e4SLinus Torvalds I believe they are just ether pollution. --ANK 2831da177e4SLinus Torvalds */ 2841da177e4SLinus Torvalds break; 2851da177e4SLinus Torvalds } 2861da177e4SLinus Torvalds break; 2879f57c67cSPravin B Shelar 2881da177e4SLinus Torvalds case ICMP_TIME_EXCEEDED: 2891da177e4SLinus Torvalds if (code != ICMP_EXC_TTL) 2909f57c67cSPravin B Shelar return; 2911da177e4SLinus Torvalds break; 29255be7a9cSDavid S. Miller 29355be7a9cSDavid S. Miller case ICMP_REDIRECT: 29455be7a9cSDavid S. Miller break; 2951da177e4SLinus Torvalds } 2961da177e4SLinus Torvalds 297bda7bb46SPravin B Shelar if (tpi->proto == htons(ETH_P_TEB)) 298c5441932SPravin B Shelar itn = net_generic(net, gre_tap_net_id); 299c5441932SPravin B Shelar else 300c5441932SPravin B Shelar itn = net_generic(net, ipgre_net_id); 301c5441932SPravin B Shelar 302c0c0c50fSDuan Jiong iph = (const struct iphdr *)(icmp_hdr(skb) + 1); 303bda7bb46SPravin B Shelar t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 304bda7bb46SPravin B Shelar iph->daddr, iph->saddr, tpi->key); 305d2083287Sstephen hemminger 30651456b29SIan Morris if (!t) 3079f57c67cSPravin B Shelar return; 30836393395SDavid S. Miller 30936393395SDavid S. Miller if (t->parms.iph.daddr == 0 || 310f97c1e0cSJoe Perches ipv4_is_multicast(t->parms.iph.daddr)) 3119f57c67cSPravin B Shelar return; 3121da177e4SLinus Torvalds 3131da177e4SLinus Torvalds if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 3149f57c67cSPravin B Shelar return; 3151da177e4SLinus Torvalds 316da6185d8SWei Yongjun if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) 3171da177e4SLinus Torvalds t->err_count++; 3181da177e4SLinus Torvalds else 3191da177e4SLinus Torvalds t->err_count = 1; 3201da177e4SLinus Torvalds t->err_time = jiffies; 3219f57c67cSPravin B Shelar } 3229f57c67cSPravin B Shelar 3239f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info) 3249f57c67cSPravin B Shelar { 3259f57c67cSPravin B Shelar /* All the routers (except for Linux) return only 3269f57c67cSPravin B Shelar * 8 bytes of packet payload. It means, that precise relaying of 3279f57c67cSPravin B Shelar * ICMP in the real Internet is absolutely infeasible. 3289f57c67cSPravin B Shelar * 3299f57c67cSPravin B Shelar * Moreover, Cisco "wise men" put GRE key to the third word 3309f57c67cSPravin B Shelar * in GRE header. It makes impossible maintaining even soft 3319f57c67cSPravin B Shelar * state for keyed 3329f57c67cSPravin B Shelar * GRE tunnels with enabled checksum. Tell them "thank you". 3339f57c67cSPravin B Shelar * 3349f57c67cSPravin B Shelar * Well, I wonder, rfc1812 was written by Cisco employee, 3359f57c67cSPravin B Shelar * what the hell these idiots break standards established 3369f57c67cSPravin B Shelar * by themselves??? 3379f57c67cSPravin B Shelar */ 3389f57c67cSPravin B Shelar 3399f57c67cSPravin B Shelar const int type = icmp_hdr(skb)->type; 3409f57c67cSPravin B Shelar const int code = icmp_hdr(skb)->code; 3419f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 3429f57c67cSPravin B Shelar bool csum_err = false; 3439f57c67cSPravin B Shelar 3449f57c67cSPravin B Shelar if (parse_gre_header(skb, &tpi, &csum_err)) { 3459f57c67cSPravin B Shelar if (!csum_err) /* ignore csum errors. */ 3469f57c67cSPravin B Shelar return; 3479f57c67cSPravin B Shelar } 3489f57c67cSPravin B Shelar 3499f57c67cSPravin B Shelar if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 3509f57c67cSPravin B Shelar ipv4_update_pmtu(skb, dev_net(skb->dev), info, 3519f57c67cSPravin B Shelar skb->dev->ifindex, 0, IPPROTO_GRE, 0); 3529f57c67cSPravin B Shelar return; 3539f57c67cSPravin B Shelar } 3549f57c67cSPravin B Shelar if (type == ICMP_REDIRECT) { 3559f57c67cSPravin B Shelar ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0, 3569f57c67cSPravin B Shelar IPPROTO_GRE, 0); 3579f57c67cSPravin B Shelar return; 3589f57c67cSPravin B Shelar } 3599f57c67cSPravin B Shelar 3609f57c67cSPravin B Shelar ipgre_err(skb, info, &tpi); 3611da177e4SLinus Torvalds } 3621da177e4SLinus Torvalds 3632e15ea39SPravin B Shelar static __be64 key_to_tunnel_id(__be32 key) 3642e15ea39SPravin B Shelar { 3652e15ea39SPravin B Shelar #ifdef __BIG_ENDIAN 3662e15ea39SPravin B Shelar return (__force __be64)((__force u32)key); 3672e15ea39SPravin B Shelar #else 3682e15ea39SPravin B Shelar return (__force __be64)((__force u64)key << 32); 3692e15ea39SPravin B Shelar #endif 3702e15ea39SPravin B Shelar } 3712e15ea39SPravin B Shelar 3722e15ea39SPravin B Shelar /* Returns the least-significant 32 bits of a __be64. */ 3732e15ea39SPravin B Shelar static __be32 tunnel_id_to_key(__be64 x) 3742e15ea39SPravin B Shelar { 3752e15ea39SPravin B Shelar #ifdef __BIG_ENDIAN 3762e15ea39SPravin B Shelar return (__force __be32)x; 3772e15ea39SPravin B Shelar #else 3782e15ea39SPravin B Shelar return (__force __be32)((__force u64)x >> 32); 3792e15ea39SPravin B Shelar #endif 3802e15ea39SPravin B Shelar } 3812e15ea39SPravin B Shelar 382bda7bb46SPravin B Shelar static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) 3831da177e4SLinus Torvalds { 384c5441932SPravin B Shelar struct net *net = dev_net(skb->dev); 3852e15ea39SPravin B Shelar struct metadata_dst *tun_dst = NULL; 386c5441932SPravin B Shelar struct ip_tunnel_net *itn; 387b71d1d42SEric Dumazet const struct iphdr *iph; 3881da177e4SLinus Torvalds struct ip_tunnel *tunnel; 3891da177e4SLinus Torvalds 390bda7bb46SPravin B Shelar if (tpi->proto == htons(ETH_P_TEB)) 391c5441932SPravin B Shelar itn = net_generic(net, gre_tap_net_id); 392c5441932SPravin B Shelar else 393c5441932SPravin B Shelar itn = net_generic(net, ipgre_net_id); 394c5441932SPravin B Shelar 395eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb); 396bda7bb46SPravin B Shelar tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 397bda7bb46SPravin B Shelar iph->saddr, iph->daddr, tpi->key); 3981da177e4SLinus Torvalds 399d2083287Sstephen hemminger if (tunnel) { 4000e3da5bbSTimo Teräs skb_pop_mac_header(skb); 4012e15ea39SPravin B Shelar if (tunnel->collect_md) { 402c29a70d2SPravin B Shelar __be16 flags; 403c29a70d2SPravin B Shelar __be64 tun_id; 4042e15ea39SPravin B Shelar 405c29a70d2SPravin B Shelar flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); 406c29a70d2SPravin B Shelar tun_id = key_to_tunnel_id(tpi->key); 407c29a70d2SPravin B Shelar tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0); 4082e15ea39SPravin B Shelar if (!tun_dst) 4092e15ea39SPravin B Shelar return PACKET_REJECT; 4102e15ea39SPravin B Shelar } 4112e15ea39SPravin B Shelar 4122e15ea39SPravin B Shelar ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 413bda7bb46SPravin B Shelar return PACKET_RCVD; 4141da177e4SLinus Torvalds } 415bda7bb46SPravin B Shelar return PACKET_REJECT; 4161da177e4SLinus Torvalds } 4171da177e4SLinus Torvalds 4189f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb) 4199f57c67cSPravin B Shelar { 4209f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 4219f57c67cSPravin B Shelar bool csum_err = false; 4229f57c67cSPravin B Shelar 4239f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 4249f57c67cSPravin B Shelar if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { 4259f57c67cSPravin B Shelar /* Looped back packet, drop it! */ 4269f57c67cSPravin B Shelar if (rt_is_output_route(skb_rtable(skb))) 4279f57c67cSPravin B Shelar goto drop; 4289f57c67cSPravin B Shelar } 4299f57c67cSPravin B Shelar #endif 4309f57c67cSPravin B Shelar 4319f57c67cSPravin B Shelar if (parse_gre_header(skb, &tpi, &csum_err) < 0) 4329f57c67cSPravin B Shelar goto drop; 4339f57c67cSPravin B Shelar 4349f57c67cSPravin B Shelar if (ipgre_rcv(skb, &tpi) == PACKET_RCVD) 4359f57c67cSPravin B Shelar return 0; 4369f57c67cSPravin B Shelar 4379f57c67cSPravin B Shelar icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 4389f57c67cSPravin B Shelar drop: 4399f57c67cSPravin B Shelar kfree_skb(skb); 4409f57c67cSPravin B Shelar return 0; 4419f57c67cSPravin B Shelar } 4429f57c67cSPravin B Shelar 4432e15ea39SPravin B Shelar static void build_header(struct sk_buff *skb, int hdr_len, __be16 flags, 4442e15ea39SPravin B Shelar __be16 proto, __be32 key, __be32 seq) 4452e15ea39SPravin B Shelar { 4462e15ea39SPravin B Shelar struct gre_base_hdr *greh; 4472e15ea39SPravin B Shelar 4482e15ea39SPravin B Shelar skb_push(skb, hdr_len); 4492e15ea39SPravin B Shelar 4502e15ea39SPravin B Shelar skb_reset_transport_header(skb); 4512e15ea39SPravin B Shelar greh = (struct gre_base_hdr *)skb->data; 4522e15ea39SPravin B Shelar greh->flags = tnl_flags_to_gre_flags(flags); 4532e15ea39SPravin B Shelar greh->protocol = proto; 4542e15ea39SPravin B Shelar 4552e15ea39SPravin B Shelar if (flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) { 4562e15ea39SPravin B Shelar __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4); 4572e15ea39SPravin B Shelar 4582e15ea39SPravin B Shelar if (flags & TUNNEL_SEQ) { 4592e15ea39SPravin B Shelar *ptr = seq; 4602e15ea39SPravin B Shelar ptr--; 4612e15ea39SPravin B Shelar } 4622e15ea39SPravin B Shelar if (flags & TUNNEL_KEY) { 4632e15ea39SPravin B Shelar *ptr = key; 4642e15ea39SPravin B Shelar ptr--; 4652e15ea39SPravin B Shelar } 4662e15ea39SPravin B Shelar if (flags & TUNNEL_CSUM && 4672e15ea39SPravin B Shelar !(skb_shinfo(skb)->gso_type & 4682e15ea39SPravin B Shelar (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) { 4692e15ea39SPravin B Shelar *ptr = 0; 4702e15ea39SPravin B Shelar *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0, 4712e15ea39SPravin B Shelar skb->len, 0)); 4722e15ea39SPravin B Shelar } 4732e15ea39SPravin B Shelar } 4742e15ea39SPravin B Shelar } 4752e15ea39SPravin B Shelar 476c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, 477c5441932SPravin B Shelar const struct iphdr *tnl_params, 478c5441932SPravin B Shelar __be16 proto) 479c5441932SPravin B Shelar { 480c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 481c5441932SPravin B Shelar 482c5441932SPravin B Shelar if (tunnel->parms.o_flags & TUNNEL_SEQ) 483c5441932SPravin B Shelar tunnel->o_seqno++; 484cef401deSEric Dumazet 485c5441932SPravin B Shelar /* Push GRE header. */ 4862e15ea39SPravin B Shelar build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags, 4872e15ea39SPravin B Shelar proto, tunnel->parms.o_key, htonl(tunnel->o_seqno)); 4881da177e4SLinus Torvalds 4892e15ea39SPravin B Shelar skb_set_inner_protocol(skb, proto); 490bf3d6a8fSNicolas Dichtel ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); 4911da177e4SLinus Torvalds } 4921da177e4SLinus Torvalds 493b2acd1dcSPravin B Shelar static struct sk_buff *gre_handle_offloads(struct sk_buff *skb, 494b2acd1dcSPravin B Shelar bool csum) 495b2acd1dcSPravin B Shelar { 496b2acd1dcSPravin B Shelar return iptunnel_handle_offloads(skb, csum, 497b2acd1dcSPravin B Shelar csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); 498b2acd1dcSPravin B Shelar } 499b2acd1dcSPravin B Shelar 500fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb, 501fc4099f1SPravin B Shelar struct net_device *dev, 502fc4099f1SPravin B Shelar struct flowi4 *fl, 503fc4099f1SPravin B Shelar const struct ip_tunnel_key *key) 504fc4099f1SPravin B Shelar { 505fc4099f1SPravin B Shelar struct net *net = dev_net(dev); 506fc4099f1SPravin B Shelar 507fc4099f1SPravin B Shelar memset(fl, 0, sizeof(*fl)); 508fc4099f1SPravin B Shelar fl->daddr = key->u.ipv4.dst; 509fc4099f1SPravin B Shelar fl->saddr = key->u.ipv4.src; 510fc4099f1SPravin B Shelar fl->flowi4_tos = RT_TOS(key->tos); 511fc4099f1SPravin B Shelar fl->flowi4_mark = skb->mark; 512fc4099f1SPravin B Shelar fl->flowi4_proto = IPPROTO_GRE; 513fc4099f1SPravin B Shelar 514fc4099f1SPravin B Shelar return ip_route_output_key(net, fl); 515fc4099f1SPravin B Shelar } 516fc4099f1SPravin B Shelar 5172e15ea39SPravin B Shelar static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) 5182e15ea39SPravin B Shelar { 5192e15ea39SPravin B Shelar struct ip_tunnel_info *tun_info; 5202e15ea39SPravin B Shelar const struct ip_tunnel_key *key; 5212e15ea39SPravin B Shelar struct flowi4 fl; 5222e15ea39SPravin B Shelar struct rtable *rt; 5232e15ea39SPravin B Shelar int min_headroom; 5242e15ea39SPravin B Shelar int tunnel_hlen; 5252e15ea39SPravin B Shelar __be16 df, flags; 5262e15ea39SPravin B Shelar int err; 5272e15ea39SPravin B Shelar 52861adedf3SJiri Benc tun_info = skb_tunnel_info(skb); 5297f9562a1SJiri Benc if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 5307f9562a1SJiri Benc ip_tunnel_info_af(tun_info) != AF_INET)) 5312e15ea39SPravin B Shelar goto err_free_skb; 5322e15ea39SPravin B Shelar 5332e15ea39SPravin B Shelar key = &tun_info->key; 534fc4099f1SPravin B Shelar rt = gre_get_rt(skb, dev, &fl, key); 5352e15ea39SPravin B Shelar if (IS_ERR(rt)) 5362e15ea39SPravin B Shelar goto err_free_skb; 5372e15ea39SPravin B Shelar 5382e15ea39SPravin B Shelar tunnel_hlen = ip_gre_calc_hlen(key->tun_flags); 5392e15ea39SPravin B Shelar 5402e15ea39SPravin B Shelar min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len 5412e15ea39SPravin B Shelar + tunnel_hlen + sizeof(struct iphdr); 5422e15ea39SPravin B Shelar if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { 5432e15ea39SPravin B Shelar int head_delta = SKB_DATA_ALIGN(min_headroom - 5442e15ea39SPravin B Shelar skb_headroom(skb) + 5452e15ea39SPravin B Shelar 16); 5462e15ea39SPravin B Shelar err = pskb_expand_head(skb, max_t(int, head_delta, 0), 5472e15ea39SPravin B Shelar 0, GFP_ATOMIC); 5482e15ea39SPravin B Shelar if (unlikely(err)) 5492e15ea39SPravin B Shelar goto err_free_rt; 5502e15ea39SPravin B Shelar } 5512e15ea39SPravin B Shelar 5522e15ea39SPravin B Shelar /* Push Tunnel header. */ 5532e15ea39SPravin B Shelar skb = gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)); 5542e15ea39SPravin B Shelar if (IS_ERR(skb)) { 5552e15ea39SPravin B Shelar skb = NULL; 5562e15ea39SPravin B Shelar goto err_free_rt; 5572e15ea39SPravin B Shelar } 5582e15ea39SPravin B Shelar 5592e15ea39SPravin B Shelar flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); 5602e15ea39SPravin B Shelar build_header(skb, tunnel_hlen, flags, htons(ETH_P_TEB), 5612e15ea39SPravin B Shelar tunnel_id_to_key(tun_info->key.tun_id), 0); 5622e15ea39SPravin B Shelar 5632e15ea39SPravin B Shelar df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; 564039f5062SPravin B Shelar 565039f5062SPravin B Shelar iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, 5667c383fb2SJiri Benc key->tos, key->ttl, df, false); 5672e15ea39SPravin B Shelar return; 5682e15ea39SPravin B Shelar 5692e15ea39SPravin B Shelar err_free_rt: 5702e15ea39SPravin B Shelar ip_rt_put(rt); 5712e15ea39SPravin B Shelar err_free_skb: 5722e15ea39SPravin B Shelar kfree_skb(skb); 5732e15ea39SPravin B Shelar dev->stats.tx_dropped++; 5742e15ea39SPravin B Shelar } 5752e15ea39SPravin B Shelar 576fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) 577fc4099f1SPravin B Shelar { 578fc4099f1SPravin B Shelar struct ip_tunnel_info *info = skb_tunnel_info(skb); 579fc4099f1SPravin B Shelar struct rtable *rt; 580fc4099f1SPravin B Shelar struct flowi4 fl4; 581fc4099f1SPravin B Shelar 582fc4099f1SPravin B Shelar if (ip_tunnel_info_af(info) != AF_INET) 583fc4099f1SPravin B Shelar return -EINVAL; 584fc4099f1SPravin B Shelar 585fc4099f1SPravin B Shelar rt = gre_get_rt(skb, dev, &fl4, &info->key); 586fc4099f1SPravin B Shelar if (IS_ERR(rt)) 587fc4099f1SPravin B Shelar return PTR_ERR(rt); 588fc4099f1SPravin B Shelar 589fc4099f1SPravin B Shelar ip_rt_put(rt); 590fc4099f1SPravin B Shelar info->key.u.ipv4.src = fl4.saddr; 591fc4099f1SPravin B Shelar return 0; 592fc4099f1SPravin B Shelar } 593fc4099f1SPravin B Shelar 594c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb, 595c5441932SPravin B Shelar struct net_device *dev) 596ee34c1ebSMichal Schmidt { 597c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 598c5441932SPravin B Shelar const struct iphdr *tnl_params; 599ee34c1ebSMichal Schmidt 6002e15ea39SPravin B Shelar if (tunnel->collect_md) { 6012e15ea39SPravin B Shelar gre_fb_xmit(skb, dev); 6022e15ea39SPravin B Shelar return NETDEV_TX_OK; 6032e15ea39SPravin B Shelar } 6042e15ea39SPravin B Shelar 605c5441932SPravin B Shelar if (dev->header_ops) { 606c5441932SPravin B Shelar /* Need space for new headers */ 607c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom - 6082bac7cb3SChen Gang (tunnel->hlen + sizeof(struct iphdr)))) 609c5441932SPravin B Shelar goto free_skb; 610ee34c1ebSMichal Schmidt 611c5441932SPravin B Shelar tnl_params = (const struct iphdr *)skb->data; 612cbb1e85fSDavid S. Miller 613c5441932SPravin B Shelar /* Pull skb since ip_tunnel_xmit() needs skb->data pointing 614c5441932SPravin B Shelar * to gre header. 615c5441932SPravin B Shelar */ 616c5441932SPravin B Shelar skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); 6178a0033a9STimo Teräs skb_reset_mac_header(skb); 618c5441932SPravin B Shelar } else { 619c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 620c5441932SPravin B Shelar goto free_skb; 621c5441932SPravin B Shelar 622c5441932SPravin B Shelar tnl_params = &tunnel->parms.iph; 623ee34c1ebSMichal Schmidt } 624e1a80002SHerbert Xu 6258a0033a9STimo Teräs skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); 6268a0033a9STimo Teräs if (IS_ERR(skb)) 6278a0033a9STimo Teräs goto out; 6288a0033a9STimo Teräs 629c5441932SPravin B Shelar __gre_xmit(skb, dev, tnl_params, skb->protocol); 630c5441932SPravin B Shelar return NETDEV_TX_OK; 631c5441932SPravin B Shelar 632c5441932SPravin B Shelar free_skb: 6333acfa1e7SEric Dumazet kfree_skb(skb); 634c5441932SPravin B Shelar out: 635c5441932SPravin B Shelar dev->stats.tx_dropped++; 636c5441932SPravin B Shelar return NETDEV_TX_OK; 637ee34c1ebSMichal Schmidt } 638ee34c1ebSMichal Schmidt 639c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, 640c5441932SPravin B Shelar struct net_device *dev) 641c5441932SPravin B Shelar { 642c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 643ee34c1ebSMichal Schmidt 6442e15ea39SPravin B Shelar if (tunnel->collect_md) { 6452e15ea39SPravin B Shelar gre_fb_xmit(skb, dev); 6462e15ea39SPravin B Shelar return NETDEV_TX_OK; 6472e15ea39SPravin B Shelar } 6482e15ea39SPravin B Shelar 64945f2e997SPravin B Shelar skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); 650c5441932SPravin B Shelar if (IS_ERR(skb)) 651c5441932SPravin B Shelar goto out; 652ee34c1ebSMichal Schmidt 653c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 654c5441932SPravin B Shelar goto free_skb; 65542aa9162SHerbert Xu 656c5441932SPravin B Shelar __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB)); 657c5441932SPravin B Shelar return NETDEV_TX_OK; 658c5441932SPravin B Shelar 659c5441932SPravin B Shelar free_skb: 6603acfa1e7SEric Dumazet kfree_skb(skb); 661c5441932SPravin B Shelar out: 662c5441932SPravin B Shelar dev->stats.tx_dropped++; 663c5441932SPravin B Shelar return NETDEV_TX_OK; 66468c33163SPravin B Shelar } 665ee34c1ebSMichal Schmidt 666c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev, 667c5441932SPravin B Shelar struct ifreq *ifr, int cmd) 6681da177e4SLinus Torvalds { 6694565e991STom Herbert int err; 6701da177e4SLinus Torvalds struct ip_tunnel_parm p; 6711da177e4SLinus Torvalds 6721da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 673c5441932SPravin B Shelar return -EFAULT; 6746c734fb8SCong Wang if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { 6751da177e4SLinus Torvalds if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || 6761da177e4SLinus Torvalds p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) || 6776c734fb8SCong Wang ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) 6781da177e4SLinus Torvalds return -EINVAL; 679c5441932SPravin B Shelar } 680c5441932SPravin B Shelar p.i_flags = gre_flags_to_tnl_flags(p.i_flags); 681c5441932SPravin B Shelar p.o_flags = gre_flags_to_tnl_flags(p.o_flags); 682c5441932SPravin B Shelar 683c5441932SPravin B Shelar err = ip_tunnel_ioctl(dev, &p, cmd); 684c5441932SPravin B Shelar if (err) 685c5441932SPravin B Shelar return err; 686c5441932SPravin B Shelar 687c5441932SPravin B Shelar p.i_flags = tnl_flags_to_gre_flags(p.i_flags); 688c5441932SPravin B Shelar p.o_flags = tnl_flags_to_gre_flags(p.o_flags); 689c5441932SPravin B Shelar 690c5441932SPravin B Shelar if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) 691c5441932SPravin B Shelar return -EFAULT; 6921da177e4SLinus Torvalds return 0; 6931da177e4SLinus Torvalds } 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-) 6961da177e4SLinus Torvalds It allows to construct virtual multiprotocol broadcast "LAN" 6971da177e4SLinus Torvalds over the Internet, provided multicast routing is tuned. 6981da177e4SLinus Torvalds 6991da177e4SLinus Torvalds 7001da177e4SLinus Torvalds I have no idea was this bicycle invented before me, 7011da177e4SLinus Torvalds so that I had to set ARPHRD_IPGRE to a random value. 7021da177e4SLinus Torvalds I have an impression, that Cisco could make something similar, 7031da177e4SLinus Torvalds but this feature is apparently missing in IOS<=11.2(8). 7041da177e4SLinus Torvalds 7051da177e4SLinus Torvalds I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks 7061da177e4SLinus Torvalds with broadcast 224.66.66.66. If you have access to mbone, play with me :-) 7071da177e4SLinus Torvalds 7081da177e4SLinus Torvalds ping -t 255 224.66.66.66 7091da177e4SLinus Torvalds 7101da177e4SLinus Torvalds If nobody answers, mbone does not work. 7111da177e4SLinus Torvalds 7121da177e4SLinus Torvalds ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 7131da177e4SLinus Torvalds ip addr add 10.66.66.<somewhat>/24 dev Universe 7141da177e4SLinus Torvalds ifconfig Universe up 7151da177e4SLinus Torvalds ifconfig Universe add fe80::<Your_real_addr>/10 7161da177e4SLinus Torvalds ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 7171da177e4SLinus Torvalds ftp 10.66.66.66 7181da177e4SLinus Torvalds ... 7191da177e4SLinus Torvalds ftp fec0:6666:6666::193.233.7.65 7201da177e4SLinus Torvalds ... 7211da177e4SLinus Torvalds */ 7223b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev, 7233b04dddeSStephen Hemminger unsigned short type, 7241507850bSEric Dumazet const void *daddr, const void *saddr, unsigned int len) 7251da177e4SLinus Torvalds { 7262941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 727c5441932SPravin B Shelar struct iphdr *iph; 728c5441932SPravin B Shelar struct gre_base_hdr *greh; 729c5441932SPravin B Shelar 730c5441932SPravin B Shelar iph = (struct iphdr *)skb_push(skb, t->hlen + sizeof(*iph)); 731c5441932SPravin B Shelar greh = (struct gre_base_hdr *)(iph+1); 732c5441932SPravin B Shelar greh->flags = tnl_flags_to_gre_flags(t->parms.o_flags); 733c5441932SPravin B Shelar greh->protocol = htons(type); 7341da177e4SLinus Torvalds 7351da177e4SLinus Torvalds memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); 7361da177e4SLinus Torvalds 737c5441932SPravin B Shelar /* Set the source hardware address. */ 7381da177e4SLinus Torvalds if (saddr) 7391da177e4SLinus Torvalds memcpy(&iph->saddr, saddr, 4); 7406d55cb91STimo Teräs if (daddr) 7411da177e4SLinus Torvalds memcpy(&iph->daddr, daddr, 4); 7426d55cb91STimo Teräs if (iph->daddr) 74377a482bdSTimo Teräs return t->hlen + sizeof(*iph); 7441da177e4SLinus Torvalds 745c5441932SPravin B Shelar return -(t->hlen + sizeof(*iph)); 7461da177e4SLinus Torvalds } 7471da177e4SLinus Torvalds 7486a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) 7496a5f44d7STimo Teras { 750b71d1d42SEric Dumazet const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); 7516a5f44d7STimo Teras memcpy(haddr, &iph->saddr, 4); 7526a5f44d7STimo Teras return 4; 7536a5f44d7STimo Teras } 7546a5f44d7STimo Teras 7553b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = { 7563b04dddeSStephen Hemminger .create = ipgre_header, 7576a5f44d7STimo Teras .parse = ipgre_header_parse, 7583b04dddeSStephen Hemminger }; 7593b04dddeSStephen Hemminger 7606a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST 7611da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev) 7621da177e4SLinus Torvalds { 7632941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 7641da177e4SLinus Torvalds 765f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr)) { 766cbb1e85fSDavid S. Miller struct flowi4 fl4; 767cbb1e85fSDavid S. Miller struct rtable *rt; 768cbb1e85fSDavid S. Miller 769b57708adSNicolas Dichtel rt = ip_route_output_gre(t->net, &fl4, 77078fbfd8aSDavid S. Miller t->parms.iph.daddr, 77178fbfd8aSDavid S. Miller t->parms.iph.saddr, 77278fbfd8aSDavid S. Miller t->parms.o_key, 77378fbfd8aSDavid S. Miller RT_TOS(t->parms.iph.tos), 77478fbfd8aSDavid S. Miller t->parms.link); 775b23dd4feSDavid S. Miller if (IS_ERR(rt)) 7761da177e4SLinus Torvalds return -EADDRNOTAVAIL; 777d8d1f30bSChangli Gao dev = rt->dst.dev; 7781da177e4SLinus Torvalds ip_rt_put(rt); 77951456b29SIan Morris if (!__in_dev_get_rtnl(dev)) 7801da177e4SLinus Torvalds return -EADDRNOTAVAIL; 7811da177e4SLinus Torvalds t->mlink = dev->ifindex; 782e5ed6399SHerbert Xu ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); 7831da177e4SLinus Torvalds } 7841da177e4SLinus Torvalds return 0; 7851da177e4SLinus Torvalds } 7861da177e4SLinus Torvalds 7871da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev) 7881da177e4SLinus Torvalds { 7892941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 790b8c26a33SStephen Hemminger 791f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) { 7927fee0ca2SDenis V. Lunev struct in_device *in_dev; 793b57708adSNicolas Dichtel in_dev = inetdev_by_index(t->net, t->mlink); 7948723e1b4SEric Dumazet if (in_dev) 7951da177e4SLinus Torvalds ip_mc_dec_group(in_dev, t->parms.iph.daddr); 7961da177e4SLinus Torvalds } 7971da177e4SLinus Torvalds return 0; 7981da177e4SLinus Torvalds } 7991da177e4SLinus Torvalds #endif 8001da177e4SLinus Torvalds 801b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = { 802b8c26a33SStephen Hemminger .ndo_init = ipgre_tunnel_init, 803c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 804b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST 805b8c26a33SStephen Hemminger .ndo_open = ipgre_open, 806b8c26a33SStephen Hemminger .ndo_stop = ipgre_close, 807b8c26a33SStephen Hemminger #endif 808c5441932SPravin B Shelar .ndo_start_xmit = ipgre_xmit, 809b8c26a33SStephen Hemminger .ndo_do_ioctl = ipgre_tunnel_ioctl, 810c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 811c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 8121e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 813b8c26a33SStephen Hemminger }; 814b8c26a33SStephen Hemminger 8156b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG | \ 8166b78f16eSEric Dumazet NETIF_F_FRAGLIST | \ 8176b78f16eSEric Dumazet NETIF_F_HIGHDMA | \ 8186b78f16eSEric Dumazet NETIF_F_HW_CSUM) 8196b78f16eSEric Dumazet 8201da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev) 8211da177e4SLinus Torvalds { 822b8c26a33SStephen Hemminger dev->netdev_ops = &ipgre_netdev_ops; 8235a455275SNicolas Dichtel dev->type = ARPHRD_IPGRE; 824c5441932SPravin B Shelar ip_tunnel_setup(dev, ipgre_net_id); 825c5441932SPravin B Shelar } 8261da177e4SLinus Torvalds 827c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev) 828c5441932SPravin B Shelar { 829c5441932SPravin B Shelar struct ip_tunnel *tunnel; 8304565e991STom Herbert int t_hlen; 831c5441932SPravin B Shelar 832c5441932SPravin B Shelar tunnel = netdev_priv(dev); 8334565e991STom Herbert tunnel->tun_hlen = ip_gre_calc_hlen(tunnel->parms.o_flags); 834c5441932SPravin B Shelar tunnel->parms.iph.protocol = IPPROTO_GRE; 835c5441932SPravin B Shelar 8364565e991STom Herbert tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; 8374565e991STom Herbert 8384565e991STom Herbert t_hlen = tunnel->hlen + sizeof(struct iphdr); 8394565e991STom Herbert 8404565e991STom Herbert dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; 8414565e991STom Herbert dev->mtu = ETH_DATA_LEN - t_hlen - 4; 8426b78f16eSEric Dumazet 843b57708adSNicolas Dichtel dev->features |= GRE_FEATURES; 8446b78f16eSEric Dumazet dev->hw_features |= GRE_FEATURES; 845c5441932SPravin B Shelar 846c5441932SPravin B Shelar if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 847c5441932SPravin B Shelar /* TCP offload with GRE SEQ is not supported. */ 848c5441932SPravin B Shelar dev->features |= NETIF_F_GSO_SOFTWARE; 849c5441932SPravin B Shelar dev->hw_features |= NETIF_F_GSO_SOFTWARE; 850c5441932SPravin B Shelar /* Can use a lockless transmit, unless we generate 851c5441932SPravin B Shelar * output sequences 852c5441932SPravin B Shelar */ 853c5441932SPravin B Shelar dev->features |= NETIF_F_LLTX; 854c5441932SPravin B Shelar } 8551da177e4SLinus Torvalds } 8561da177e4SLinus Torvalds 8571da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev) 8581da177e4SLinus Torvalds { 859c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 860c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 8611da177e4SLinus Torvalds 862c5441932SPravin B Shelar __gre_tunnel_init(dev); 8631da177e4SLinus Torvalds 864c5441932SPravin B Shelar memcpy(dev->dev_addr, &iph->saddr, 4); 865c5441932SPravin B Shelar memcpy(dev->broadcast, &iph->daddr, 4); 8661da177e4SLinus Torvalds 867c5441932SPravin B Shelar dev->flags = IFF_NOARP; 86802875878SEric Dumazet netif_keep_dst(dev); 869c5441932SPravin B Shelar dev->addr_len = 4; 8701da177e4SLinus Torvalds 8711da177e4SLinus Torvalds if (iph->daddr) { 8721da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST 873f97c1e0cSJoe Perches if (ipv4_is_multicast(iph->daddr)) { 8741da177e4SLinus Torvalds if (!iph->saddr) 8751da177e4SLinus Torvalds return -EINVAL; 8761da177e4SLinus Torvalds dev->flags = IFF_BROADCAST; 8773b04dddeSStephen Hemminger dev->header_ops = &ipgre_header_ops; 8781da177e4SLinus Torvalds } 8791da177e4SLinus Torvalds #endif 880ee34c1ebSMichal Schmidt } else 8816a5f44d7STimo Teras dev->header_ops = &ipgre_header_ops; 8821da177e4SLinus Torvalds 883c5441932SPravin B Shelar return ip_tunnel_init(dev); 88460769a5dSEric Dumazet } 88560769a5dSEric Dumazet 8869f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = { 8879f57c67cSPravin B Shelar .handler = gre_rcv, 8889f57c67cSPravin B Shelar .err_handler = gre_err, 8891da177e4SLinus Torvalds }; 8901da177e4SLinus Torvalds 8912c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net) 89259a4c759SPavel Emelyanov { 893c5441932SPravin B Shelar return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); 89459a4c759SPavel Emelyanov } 89559a4c759SPavel Emelyanov 8962c8c1e72SAlexey Dobriyan static void __net_exit ipgre_exit_net(struct net *net) 89759a4c759SPavel Emelyanov { 898c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id); 8996c742e71SNicolas Dichtel ip_tunnel_delete_net(itn, &ipgre_link_ops); 90059a4c759SPavel Emelyanov } 90159a4c759SPavel Emelyanov 90259a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = { 90359a4c759SPavel Emelyanov .init = ipgre_init_net, 90459a4c759SPavel Emelyanov .exit = ipgre_exit_net, 905cfb8fbf2SEric W. Biederman .id = &ipgre_net_id, 906c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 90759a4c759SPavel Emelyanov }; 9081da177e4SLinus Torvalds 909c19e654dSHerbert Xu static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) 910c19e654dSHerbert Xu { 911c19e654dSHerbert Xu __be16 flags; 912c19e654dSHerbert Xu 913c19e654dSHerbert Xu if (!data) 914c19e654dSHerbert Xu return 0; 915c19e654dSHerbert Xu 916c19e654dSHerbert Xu flags = 0; 917c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 918c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 919c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 920c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 921c19e654dSHerbert Xu if (flags & (GRE_VERSION|GRE_ROUTING)) 922c19e654dSHerbert Xu return -EINVAL; 923c19e654dSHerbert Xu 924c19e654dSHerbert Xu return 0; 925c19e654dSHerbert Xu } 926c19e654dSHerbert Xu 927e1a80002SHerbert Xu static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[]) 928e1a80002SHerbert Xu { 929e1a80002SHerbert Xu __be32 daddr; 930e1a80002SHerbert Xu 931e1a80002SHerbert Xu if (tb[IFLA_ADDRESS]) { 932e1a80002SHerbert Xu if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) 933e1a80002SHerbert Xu return -EINVAL; 934e1a80002SHerbert Xu if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 935e1a80002SHerbert Xu return -EADDRNOTAVAIL; 936e1a80002SHerbert Xu } 937e1a80002SHerbert Xu 938e1a80002SHerbert Xu if (!data) 939e1a80002SHerbert Xu goto out; 940e1a80002SHerbert Xu 941e1a80002SHerbert Xu if (data[IFLA_GRE_REMOTE]) { 942e1a80002SHerbert Xu memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); 943e1a80002SHerbert Xu if (!daddr) 944e1a80002SHerbert Xu return -EINVAL; 945e1a80002SHerbert Xu } 946e1a80002SHerbert Xu 947e1a80002SHerbert Xu out: 948e1a80002SHerbert Xu return ipgre_tunnel_validate(tb, data); 949e1a80002SHerbert Xu } 950e1a80002SHerbert Xu 9512e15ea39SPravin B Shelar static void ipgre_netlink_parms(struct net_device *dev, 9522e15ea39SPravin B Shelar struct nlattr *data[], 9532e15ea39SPravin B Shelar struct nlattr *tb[], 954c19e654dSHerbert Xu struct ip_tunnel_parm *parms) 955c19e654dSHerbert Xu { 9567bb82d92SHerbert Xu memset(parms, 0, sizeof(*parms)); 957c19e654dSHerbert Xu 958c19e654dSHerbert Xu parms->iph.protocol = IPPROTO_GRE; 959c19e654dSHerbert Xu 960c19e654dSHerbert Xu if (!data) 961c19e654dSHerbert Xu return; 962c19e654dSHerbert Xu 963c19e654dSHerbert Xu if (data[IFLA_GRE_LINK]) 964c19e654dSHerbert Xu parms->link = nla_get_u32(data[IFLA_GRE_LINK]); 965c19e654dSHerbert Xu 966c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 967c5441932SPravin B Shelar parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); 968c19e654dSHerbert Xu 969c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 970c5441932SPravin B Shelar parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); 971c19e654dSHerbert Xu 972c19e654dSHerbert Xu if (data[IFLA_GRE_IKEY]) 973c19e654dSHerbert Xu parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); 974c19e654dSHerbert Xu 975c19e654dSHerbert Xu if (data[IFLA_GRE_OKEY]) 976c19e654dSHerbert Xu parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); 977c19e654dSHerbert Xu 978c19e654dSHerbert Xu if (data[IFLA_GRE_LOCAL]) 97967b61f6cSJiri Benc parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); 980c19e654dSHerbert Xu 981c19e654dSHerbert Xu if (data[IFLA_GRE_REMOTE]) 98267b61f6cSJiri Benc parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); 983c19e654dSHerbert Xu 984c19e654dSHerbert Xu if (data[IFLA_GRE_TTL]) 985c19e654dSHerbert Xu parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); 986c19e654dSHerbert Xu 987c19e654dSHerbert Xu if (data[IFLA_GRE_TOS]) 988c19e654dSHerbert Xu parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); 989c19e654dSHerbert Xu 990c19e654dSHerbert Xu if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) 991c19e654dSHerbert Xu parms->iph.frag_off = htons(IP_DF); 9922e15ea39SPravin B Shelar 9932e15ea39SPravin B Shelar if (data[IFLA_GRE_COLLECT_METADATA]) { 9942e15ea39SPravin B Shelar struct ip_tunnel *t = netdev_priv(dev); 9952e15ea39SPravin B Shelar 9962e15ea39SPravin B Shelar t->collect_md = true; 9972e15ea39SPravin B Shelar } 998c19e654dSHerbert Xu } 999c19e654dSHerbert Xu 10004565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */ 10014565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[], 10024565e991STom Herbert struct ip_tunnel_encap *ipencap) 10034565e991STom Herbert { 10044565e991STom Herbert bool ret = false; 10054565e991STom Herbert 10064565e991STom Herbert memset(ipencap, 0, sizeof(*ipencap)); 10074565e991STom Herbert 10084565e991STom Herbert if (!data) 10094565e991STom Herbert return ret; 10104565e991STom Herbert 10114565e991STom Herbert if (data[IFLA_GRE_ENCAP_TYPE]) { 10124565e991STom Herbert ret = true; 10134565e991STom Herbert ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); 10144565e991STom Herbert } 10154565e991STom Herbert 10164565e991STom Herbert if (data[IFLA_GRE_ENCAP_FLAGS]) { 10174565e991STom Herbert ret = true; 10184565e991STom Herbert ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); 10194565e991STom Herbert } 10204565e991STom Herbert 10214565e991STom Herbert if (data[IFLA_GRE_ENCAP_SPORT]) { 10224565e991STom Herbert ret = true; 10233e97fa70SSabrina Dubroca ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); 10244565e991STom Herbert } 10254565e991STom Herbert 10264565e991STom Herbert if (data[IFLA_GRE_ENCAP_DPORT]) { 10274565e991STom Herbert ret = true; 10283e97fa70SSabrina Dubroca ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); 10294565e991STom Herbert } 10304565e991STom Herbert 10314565e991STom Herbert return ret; 10324565e991STom Herbert } 10334565e991STom Herbert 1034c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev) 1035e1a80002SHerbert Xu { 1036c5441932SPravin B Shelar __gre_tunnel_init(dev); 1037bec94d43Sstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1038e1a80002SHerbert Xu 1039c5441932SPravin B Shelar return ip_tunnel_init(dev); 1040e1a80002SHerbert Xu } 1041e1a80002SHerbert Xu 1042c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = { 1043c5441932SPravin B Shelar .ndo_init = gre_tap_init, 1044c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 1045c5441932SPravin B Shelar .ndo_start_xmit = gre_tap_xmit, 1046b8c26a33SStephen Hemminger .ndo_set_mac_address = eth_mac_addr, 1047b8c26a33SStephen Hemminger .ndo_validate_addr = eth_validate_addr, 1048c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 1049c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 10501e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 1051fc4099f1SPravin B Shelar .ndo_fill_metadata_dst = gre_fill_metadata_dst, 1052b8c26a33SStephen Hemminger }; 1053b8c26a33SStephen Hemminger 1054e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev) 1055e1a80002SHerbert Xu { 1056e1a80002SHerbert Xu ether_setup(dev); 1057c5441932SPravin B Shelar dev->netdev_ops = &gre_tap_netdev_ops; 1058*d13b161cSJiri Benc dev->priv_flags &= ~IFF_TX_SKB_SHARING; 1059f8c1b7ceSstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1060c5441932SPravin B Shelar ip_tunnel_setup(dev, gre_tap_net_id); 1061e1a80002SHerbert Xu } 1062e1a80002SHerbert Xu 1063c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev, 1064c5441932SPravin B Shelar struct nlattr *tb[], struct nlattr *data[]) 1065c19e654dSHerbert Xu { 1066c5441932SPravin B Shelar struct ip_tunnel_parm p; 10674565e991STom Herbert struct ip_tunnel_encap ipencap; 10684565e991STom Herbert 10694565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 10704565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 10714565e991STom Herbert int err = ip_tunnel_encap_setup(t, &ipencap); 10724565e991STom Herbert 10734565e991STom Herbert if (err < 0) 10744565e991STom Herbert return err; 10754565e991STom Herbert } 1076c19e654dSHerbert Xu 10772e15ea39SPravin B Shelar ipgre_netlink_parms(dev, data, tb, &p); 1078c5441932SPravin B Shelar return ip_tunnel_newlink(dev, tb, &p); 1079c19e654dSHerbert Xu } 1080c19e654dSHerbert Xu 1081c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], 1082c19e654dSHerbert Xu struct nlattr *data[]) 1083c19e654dSHerbert Xu { 1084c19e654dSHerbert Xu struct ip_tunnel_parm p; 10854565e991STom Herbert struct ip_tunnel_encap ipencap; 10864565e991STom Herbert 10874565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 10884565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 10894565e991STom Herbert int err = ip_tunnel_encap_setup(t, &ipencap); 10904565e991STom Herbert 10914565e991STom Herbert if (err < 0) 10924565e991STom Herbert return err; 10934565e991STom Herbert } 1094c19e654dSHerbert Xu 10952e15ea39SPravin B Shelar ipgre_netlink_parms(dev, data, tb, &p); 1096c5441932SPravin B Shelar return ip_tunnel_changelink(dev, tb, &p); 1097c19e654dSHerbert Xu } 1098c19e654dSHerbert Xu 1099c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev) 1100c19e654dSHerbert Xu { 1101c19e654dSHerbert Xu return 1102c19e654dSHerbert Xu /* IFLA_GRE_LINK */ 1103c19e654dSHerbert Xu nla_total_size(4) + 1104c19e654dSHerbert Xu /* IFLA_GRE_IFLAGS */ 1105c19e654dSHerbert Xu nla_total_size(2) + 1106c19e654dSHerbert Xu /* IFLA_GRE_OFLAGS */ 1107c19e654dSHerbert Xu nla_total_size(2) + 1108c19e654dSHerbert Xu /* IFLA_GRE_IKEY */ 1109c19e654dSHerbert Xu nla_total_size(4) + 1110c19e654dSHerbert Xu /* IFLA_GRE_OKEY */ 1111c19e654dSHerbert Xu nla_total_size(4) + 1112c19e654dSHerbert Xu /* IFLA_GRE_LOCAL */ 1113c19e654dSHerbert Xu nla_total_size(4) + 1114c19e654dSHerbert Xu /* IFLA_GRE_REMOTE */ 1115c19e654dSHerbert Xu nla_total_size(4) + 1116c19e654dSHerbert Xu /* IFLA_GRE_TTL */ 1117c19e654dSHerbert Xu nla_total_size(1) + 1118c19e654dSHerbert Xu /* IFLA_GRE_TOS */ 1119c19e654dSHerbert Xu nla_total_size(1) + 1120c19e654dSHerbert Xu /* IFLA_GRE_PMTUDISC */ 1121c19e654dSHerbert Xu nla_total_size(1) + 11224565e991STom Herbert /* IFLA_GRE_ENCAP_TYPE */ 11234565e991STom Herbert nla_total_size(2) + 11244565e991STom Herbert /* IFLA_GRE_ENCAP_FLAGS */ 11254565e991STom Herbert nla_total_size(2) + 11264565e991STom Herbert /* IFLA_GRE_ENCAP_SPORT */ 11274565e991STom Herbert nla_total_size(2) + 11284565e991STom Herbert /* IFLA_GRE_ENCAP_DPORT */ 11294565e991STom Herbert nla_total_size(2) + 11302e15ea39SPravin B Shelar /* IFLA_GRE_COLLECT_METADATA */ 11312e15ea39SPravin B Shelar nla_total_size(0) + 1132c19e654dSHerbert Xu 0; 1133c19e654dSHerbert Xu } 1134c19e654dSHerbert Xu 1135c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) 1136c19e654dSHerbert Xu { 1137c19e654dSHerbert Xu struct ip_tunnel *t = netdev_priv(dev); 1138c19e654dSHerbert Xu struct ip_tunnel_parm *p = &t->parms; 1139c19e654dSHerbert Xu 1140f3756b79SDavid S. Miller if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || 1141c5441932SPravin B Shelar nla_put_be16(skb, IFLA_GRE_IFLAGS, tnl_flags_to_gre_flags(p->i_flags)) || 1142c5441932SPravin B Shelar nla_put_be16(skb, IFLA_GRE_OFLAGS, tnl_flags_to_gre_flags(p->o_flags)) || 1143f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || 1144f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || 1145930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || 1146930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) || 1147f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) || 1148f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) || 1149f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_PMTUDISC, 1150f3756b79SDavid S. Miller !!(p->iph.frag_off & htons(IP_DF)))) 1151f3756b79SDavid S. Miller goto nla_put_failure; 11524565e991STom Herbert 11534565e991STom Herbert if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, 11544565e991STom Herbert t->encap.type) || 11553e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, 11564565e991STom Herbert t->encap.sport) || 11573e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, 11584565e991STom Herbert t->encap.dport) || 11594565e991STom Herbert nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, 1160e1b2cb65STom Herbert t->encap.flags)) 11614565e991STom Herbert goto nla_put_failure; 11624565e991STom Herbert 11632e15ea39SPravin B Shelar if (t->collect_md) { 11642e15ea39SPravin B Shelar if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) 11652e15ea39SPravin B Shelar goto nla_put_failure; 11662e15ea39SPravin B Shelar } 11672e15ea39SPravin B Shelar 1168c19e654dSHerbert Xu return 0; 1169c19e654dSHerbert Xu 1170c19e654dSHerbert Xu nla_put_failure: 1171c19e654dSHerbert Xu return -EMSGSIZE; 1172c19e654dSHerbert Xu } 1173c19e654dSHerbert Xu 1174c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { 1175c19e654dSHerbert Xu [IFLA_GRE_LINK] = { .type = NLA_U32 }, 1176c19e654dSHerbert Xu [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, 1177c19e654dSHerbert Xu [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, 1178c19e654dSHerbert Xu [IFLA_GRE_IKEY] = { .type = NLA_U32 }, 1179c19e654dSHerbert Xu [IFLA_GRE_OKEY] = { .type = NLA_U32 }, 11804d74f8baSPatrick McHardy [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, 11814d74f8baSPatrick McHardy [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, 1182c19e654dSHerbert Xu [IFLA_GRE_TTL] = { .type = NLA_U8 }, 1183c19e654dSHerbert Xu [IFLA_GRE_TOS] = { .type = NLA_U8 }, 1184c19e654dSHerbert Xu [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, 11854565e991STom Herbert [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, 11864565e991STom Herbert [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, 11874565e991STom Herbert [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, 11884565e991STom Herbert [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, 11892e15ea39SPravin B Shelar [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, 1190c19e654dSHerbert Xu }; 1191c19e654dSHerbert Xu 1192c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = { 1193c19e654dSHerbert Xu .kind = "gre", 1194c19e654dSHerbert Xu .maxtype = IFLA_GRE_MAX, 1195c19e654dSHerbert Xu .policy = ipgre_policy, 1196c19e654dSHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1197c19e654dSHerbert Xu .setup = ipgre_tunnel_setup, 1198c19e654dSHerbert Xu .validate = ipgre_tunnel_validate, 1199c19e654dSHerbert Xu .newlink = ipgre_newlink, 1200c19e654dSHerbert Xu .changelink = ipgre_changelink, 1201c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1202c19e654dSHerbert Xu .get_size = ipgre_get_size, 1203c19e654dSHerbert Xu .fill_info = ipgre_fill_info, 12041728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1205c19e654dSHerbert Xu }; 1206c19e654dSHerbert Xu 1207e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { 1208e1a80002SHerbert Xu .kind = "gretap", 1209e1a80002SHerbert Xu .maxtype = IFLA_GRE_MAX, 1210e1a80002SHerbert Xu .policy = ipgre_policy, 1211e1a80002SHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1212e1a80002SHerbert Xu .setup = ipgre_tap_setup, 1213e1a80002SHerbert Xu .validate = ipgre_tap_validate, 1214e1a80002SHerbert Xu .newlink = ipgre_newlink, 1215e1a80002SHerbert Xu .changelink = ipgre_changelink, 1216c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1217e1a80002SHerbert Xu .get_size = ipgre_get_size, 1218e1a80002SHerbert Xu .fill_info = ipgre_fill_info, 12191728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1220e1a80002SHerbert Xu }; 1221e1a80002SHerbert Xu 1222b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name, 1223b2acd1dcSPravin B Shelar u8 name_assign_type) 1224b2acd1dcSPravin B Shelar { 1225b2acd1dcSPravin B Shelar struct nlattr *tb[IFLA_MAX + 1]; 1226b2acd1dcSPravin B Shelar struct net_device *dev; 1227b2acd1dcSPravin B Shelar struct ip_tunnel *t; 1228b2acd1dcSPravin B Shelar int err; 1229b2acd1dcSPravin B Shelar 1230b2acd1dcSPravin B Shelar memset(&tb, 0, sizeof(tb)); 1231b2acd1dcSPravin B Shelar 1232b2acd1dcSPravin B Shelar dev = rtnl_create_link(net, name, name_assign_type, 1233b2acd1dcSPravin B Shelar &ipgre_tap_ops, tb); 1234b2acd1dcSPravin B Shelar if (IS_ERR(dev)) 1235b2acd1dcSPravin B Shelar return dev; 1236b2acd1dcSPravin B Shelar 1237b2acd1dcSPravin B Shelar /* Configure flow based GRE device. */ 1238b2acd1dcSPravin B Shelar t = netdev_priv(dev); 1239b2acd1dcSPravin B Shelar t->collect_md = true; 1240b2acd1dcSPravin B Shelar 1241b2acd1dcSPravin B Shelar err = ipgre_newlink(net, dev, tb, NULL); 1242b2acd1dcSPravin B Shelar if (err < 0) 1243b2acd1dcSPravin B Shelar goto out; 12447e059158SDavid Wragg 12457e059158SDavid Wragg /* openvswitch users expect packet sizes to be unrestricted, 12467e059158SDavid Wragg * so set the largest MTU we can. 12477e059158SDavid Wragg */ 12487e059158SDavid Wragg err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); 12497e059158SDavid Wragg if (err) 12507e059158SDavid Wragg goto out; 12517e059158SDavid Wragg 1252b2acd1dcSPravin B Shelar return dev; 1253b2acd1dcSPravin B Shelar out: 1254b2acd1dcSPravin B Shelar free_netdev(dev); 1255b2acd1dcSPravin B Shelar return ERR_PTR(err); 1256b2acd1dcSPravin B Shelar } 1257b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create); 1258b2acd1dcSPravin B Shelar 1259c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net) 1260c5441932SPravin B Shelar { 12612e15ea39SPravin B Shelar return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); 1262c5441932SPravin B Shelar } 1263c5441932SPravin B Shelar 1264c5441932SPravin B Shelar static void __net_exit ipgre_tap_exit_net(struct net *net) 1265c5441932SPravin B Shelar { 1266c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id); 12676c742e71SNicolas Dichtel ip_tunnel_delete_net(itn, &ipgre_tap_ops); 1268c5441932SPravin B Shelar } 1269c5441932SPravin B Shelar 1270c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = { 1271c5441932SPravin B Shelar .init = ipgre_tap_init_net, 1272c5441932SPravin B Shelar .exit = ipgre_tap_exit_net, 1273c5441932SPravin B Shelar .id = &gre_tap_net_id, 1274c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 1275c5441932SPravin B Shelar }; 12761da177e4SLinus Torvalds 12771da177e4SLinus Torvalds static int __init ipgre_init(void) 12781da177e4SLinus Torvalds { 12791da177e4SLinus Torvalds int err; 12801da177e4SLinus Torvalds 1281058bd4d2SJoe Perches pr_info("GRE over IPv4 tunneling driver\n"); 12821da177e4SLinus Torvalds 1283cfb8fbf2SEric W. Biederman err = register_pernet_device(&ipgre_net_ops); 128459a4c759SPavel Emelyanov if (err < 0) 1285c2892f02SAlexey Dobriyan return err; 1286c2892f02SAlexey Dobriyan 1287c5441932SPravin B Shelar err = register_pernet_device(&ipgre_tap_net_ops); 1288c5441932SPravin B Shelar if (err < 0) 1289c5441932SPravin B Shelar goto pnet_tap_faied; 1290c5441932SPravin B Shelar 12919f57c67cSPravin B Shelar err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); 1292c2892f02SAlexey Dobriyan if (err < 0) { 1293058bd4d2SJoe Perches pr_info("%s: can't add protocol\n", __func__); 1294c2892f02SAlexey Dobriyan goto add_proto_failed; 1295c2892f02SAlexey Dobriyan } 12967daa0004SPavel Emelyanov 1297c19e654dSHerbert Xu err = rtnl_link_register(&ipgre_link_ops); 1298c19e654dSHerbert Xu if (err < 0) 1299c19e654dSHerbert Xu goto rtnl_link_failed; 1300c19e654dSHerbert Xu 1301e1a80002SHerbert Xu err = rtnl_link_register(&ipgre_tap_ops); 1302e1a80002SHerbert Xu if (err < 0) 1303e1a80002SHerbert Xu goto tap_ops_failed; 1304e1a80002SHerbert Xu 1305c5441932SPravin B Shelar return 0; 1306c19e654dSHerbert Xu 1307e1a80002SHerbert Xu tap_ops_failed: 1308e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 1309c19e654dSHerbert Xu rtnl_link_failed: 13109f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1311c2892f02SAlexey Dobriyan add_proto_failed: 1312c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1313c5441932SPravin B Shelar pnet_tap_faied: 1314c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 1315c5441932SPravin B Shelar return err; 13161da177e4SLinus Torvalds } 13171da177e4SLinus Torvalds 1318db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void) 13191da177e4SLinus Torvalds { 1320e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_tap_ops); 1321c19e654dSHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 13229f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1323c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1324c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 13251da177e4SLinus Torvalds } 13261da177e4SLinus Torvalds 13271da177e4SLinus Torvalds module_init(ipgre_init); 13281da177e4SLinus Torvalds module_exit(ipgre_fini); 13291da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 13304d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre"); 13314d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap"); 13328909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0"); 1333c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0"); 1334