11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Linux NET3: GRE over IP protocol decoder. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru) 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 71da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 81da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 91da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds 13afd46503SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14afd46503SJoe Perches 154fc268d2SRandy Dunlap #include <linux/capability.h> 161da177e4SLinus Torvalds #include <linux/module.h> 171da177e4SLinus Torvalds #include <linux/types.h> 181da177e4SLinus Torvalds #include <linux/kernel.h> 195a0e3ad6STejun Heo #include <linux/slab.h> 207c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 211da177e4SLinus Torvalds #include <linux/skbuff.h> 221da177e4SLinus Torvalds #include <linux/netdevice.h> 231da177e4SLinus Torvalds #include <linux/in.h> 241da177e4SLinus Torvalds #include <linux/tcp.h> 251da177e4SLinus Torvalds #include <linux/udp.h> 261da177e4SLinus Torvalds #include <linux/if_arp.h> 272e15ea39SPravin B Shelar #include <linux/if_vlan.h> 281da177e4SLinus Torvalds #include <linux/init.h> 291da177e4SLinus Torvalds #include <linux/in6.h> 301da177e4SLinus Torvalds #include <linux/inetdevice.h> 311da177e4SLinus Torvalds #include <linux/igmp.h> 321da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h> 33e1a80002SHerbert Xu #include <linux/etherdevice.h> 3446f25dffSKris Katterjohn #include <linux/if_ether.h> 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds #include <net/sock.h> 371da177e4SLinus Torvalds #include <net/ip.h> 381da177e4SLinus Torvalds #include <net/icmp.h> 391da177e4SLinus Torvalds #include <net/protocol.h> 40c5441932SPravin B Shelar #include <net/ip_tunnels.h> 411da177e4SLinus Torvalds #include <net/arp.h> 421da177e4SLinus Torvalds #include <net/checksum.h> 431da177e4SLinus Torvalds #include <net/dsfield.h> 441da177e4SLinus Torvalds #include <net/inet_ecn.h> 451da177e4SLinus Torvalds #include <net/xfrm.h> 4659a4c759SPavel Emelyanov #include <net/net_namespace.h> 4759a4c759SPavel Emelyanov #include <net/netns/generic.h> 48c19e654dSHerbert Xu #include <net/rtnetlink.h> 4900959adeSDmitry Kozlov #include <net/gre.h> 502e15ea39SPravin B Shelar #include <net/dst_metadata.h> 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds /* 531da177e4SLinus Torvalds Problems & solutions 541da177e4SLinus Torvalds -------------------- 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds 1. The most important issue is detecting local dead loops. 571da177e4SLinus Torvalds They would cause complete host lockup in transmit, which 581da177e4SLinus Torvalds would be "resolved" by stack overflow or, if queueing is enabled, 591da177e4SLinus Torvalds with infinite looping in net_bh. 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds We cannot track such dead loops during route installation, 621da177e4SLinus Torvalds it is infeasible task. The most general solutions would be 631da177e4SLinus Torvalds to keep skb->encapsulation counter (sort of local ttl), 646d0722a2SEric Dumazet and silently drop packet when it expires. It is a good 65bff52857Sstephen hemminger solution, but it supposes maintaining new variable in ALL 661da177e4SLinus Torvalds skb, even if no tunneling is used. 671da177e4SLinus Torvalds 686d0722a2SEric Dumazet Current solution: xmit_recursion breaks dead loops. This is a percpu 696d0722a2SEric Dumazet counter, since when we enter the first ndo_xmit(), cpu migration is 706d0722a2SEric Dumazet forbidden. We force an exit if this counter reaches RECURSION_LIMIT 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds 2. Networking dead loops would not kill routers, but would really 731da177e4SLinus Torvalds kill network. IP hop limit plays role of "t->recursion" in this case, 741da177e4SLinus Torvalds if we copy it from packet being encapsulated to upper header. 751da177e4SLinus Torvalds It is very good solution, but it introduces two problems: 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds - Routing protocols, using packets with ttl=1 (OSPF, RIP2), 781da177e4SLinus Torvalds do not work over tunnels. 791da177e4SLinus Torvalds - traceroute does not work. I planned to relay ICMP from tunnel, 801da177e4SLinus Torvalds so that this problem would be solved and traceroute output 811da177e4SLinus Torvalds would even more informative. This idea appeared to be wrong: 821da177e4SLinus Torvalds only Linux complies to rfc1812 now (yes, guys, Linux is the only 831da177e4SLinus Torvalds true router now :-)), all routers (at least, in neighbourhood of mine) 841da177e4SLinus Torvalds return only 8 bytes of payload. It is the end. 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds Hence, if we want that OSPF worked or traceroute said something reasonable, 871da177e4SLinus Torvalds we should search for another solution. 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds One of them is to parse packet trying to detect inner encapsulation 901da177e4SLinus Torvalds made by our node. It is difficult or even impossible, especially, 91bff52857Sstephen hemminger taking into account fragmentation. TO be short, ttl is not solution at all. 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds Current solution: The solution was UNEXPECTEDLY SIMPLE. 941da177e4SLinus Torvalds We force DF flag on tunnels with preconfigured hop limit, 951da177e4SLinus Torvalds that is ALL. :-) Well, it does not remove the problem completely, 961da177e4SLinus Torvalds but exponential growth of network traffic is changed to linear 971da177e4SLinus Torvalds (branches, that exceed pmtu are pruned) and tunnel mtu 98bff52857Sstephen hemminger rapidly degrades to value <68, where looping stops. 991da177e4SLinus Torvalds Yes, it is not good if there exists a router in the loop, 1001da177e4SLinus Torvalds which does not force DF, even when encapsulating packets have DF set. 1011da177e4SLinus Torvalds But it is not our problem! Nobody could accuse us, we made 1021da177e4SLinus Torvalds all that we could make. Even if it is your gated who injected 1031da177e4SLinus Torvalds fatal route to network, even if it were you who configured 1041da177e4SLinus Torvalds fatal static route: you are innocent. :-) 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds Alexey Kuznetsov. 1071da177e4SLinus Torvalds */ 1081da177e4SLinus Torvalds 109eccc1bb8Sstephen hemminger static bool log_ecn_error = true; 110eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644); 111eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); 112eccc1bb8Sstephen hemminger 113c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly; 1141da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev); 115eb8ce741SPavel Emelyanov 116c7d03a00SAlexey Dobriyan static unsigned int ipgre_net_id __read_mostly; 117c7d03a00SAlexey Dobriyan static unsigned int gre_tap_net_id __read_mostly; 118eb8ce741SPavel Emelyanov 1199f57c67cSPravin B Shelar static void ipgre_err(struct sk_buff *skb, u32 info, 120bda7bb46SPravin B Shelar const struct tnl_ptk_info *tpi) 1211da177e4SLinus Torvalds { 1221da177e4SLinus Torvalds 123071f92d0SRami Rosen /* All the routers (except for Linux) return only 1241da177e4SLinus Torvalds 8 bytes of packet payload. It means, that precise relaying of 1251da177e4SLinus Torvalds ICMP in the real Internet is absolutely infeasible. 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds Moreover, Cisco "wise men" put GRE key to the third word 128c5441932SPravin B Shelar in GRE header. It makes impossible maintaining even soft 129c5441932SPravin B Shelar state for keyed GRE tunnels with enabled checksum. Tell 130c5441932SPravin B Shelar them "thank you". 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds Well, I wonder, rfc1812 was written by Cisco employee, 133bff52857Sstephen hemminger what the hell these idiots break standards established 134bff52857Sstephen hemminger by themselves??? 1351da177e4SLinus Torvalds */ 136c5441932SPravin B Shelar struct net *net = dev_net(skb->dev); 137c5441932SPravin B Shelar struct ip_tunnel_net *itn; 13896f5a846SEric Dumazet const struct iphdr *iph; 13988c7664fSArnaldo Carvalho de Melo const int type = icmp_hdr(skb)->type; 14088c7664fSArnaldo Carvalho de Melo const int code = icmp_hdr(skb)->code; 14120e1954fSEric Dumazet unsigned int data_len = 0; 1421da177e4SLinus Torvalds struct ip_tunnel *t; 143d2083287Sstephen hemminger 1441da177e4SLinus Torvalds switch (type) { 1451da177e4SLinus Torvalds default: 1461da177e4SLinus Torvalds case ICMP_PARAMETERPROB: 1479f57c67cSPravin B Shelar return; 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds case ICMP_DEST_UNREACH: 1501da177e4SLinus Torvalds switch (code) { 1511da177e4SLinus Torvalds case ICMP_SR_FAILED: 1521da177e4SLinus Torvalds case ICMP_PORT_UNREACH: 1531da177e4SLinus Torvalds /* Impossible event. */ 1549f57c67cSPravin B Shelar return; 1551da177e4SLinus Torvalds default: 1561da177e4SLinus Torvalds /* All others are translated to HOST_UNREACH. 1571da177e4SLinus Torvalds rfc2003 contains "deep thoughts" about NET_UNREACH, 1581da177e4SLinus Torvalds I believe they are just ether pollution. --ANK 1591da177e4SLinus Torvalds */ 1601da177e4SLinus Torvalds break; 1611da177e4SLinus Torvalds } 1621da177e4SLinus Torvalds break; 1639f57c67cSPravin B Shelar 1641da177e4SLinus Torvalds case ICMP_TIME_EXCEEDED: 1651da177e4SLinus Torvalds if (code != ICMP_EXC_TTL) 1669f57c67cSPravin B Shelar return; 16720e1954fSEric Dumazet data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */ 1681da177e4SLinus Torvalds break; 16955be7a9cSDavid S. Miller 17055be7a9cSDavid S. Miller case ICMP_REDIRECT: 17155be7a9cSDavid S. Miller break; 1721da177e4SLinus Torvalds } 1731da177e4SLinus Torvalds 174bda7bb46SPravin B Shelar if (tpi->proto == htons(ETH_P_TEB)) 175c5441932SPravin B Shelar itn = net_generic(net, gre_tap_net_id); 176c5441932SPravin B Shelar else 177c5441932SPravin B Shelar itn = net_generic(net, ipgre_net_id); 178c5441932SPravin B Shelar 179c0c0c50fSDuan Jiong iph = (const struct iphdr *)(icmp_hdr(skb) + 1); 180bda7bb46SPravin B Shelar t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 181bda7bb46SPravin B Shelar iph->daddr, iph->saddr, tpi->key); 182d2083287Sstephen hemminger 18351456b29SIan Morris if (!t) 1849f57c67cSPravin B Shelar return; 18536393395SDavid S. Miller 1869b8c6d7bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 1879b8c6d7bSEric Dumazet if (tpi->proto == htons(ETH_P_IPV6) && 18820e1954fSEric Dumazet !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len, 18920e1954fSEric Dumazet type, data_len)) 1909b8c6d7bSEric Dumazet return; 1919b8c6d7bSEric Dumazet #endif 1929b8c6d7bSEric Dumazet 19336393395SDavid S. Miller if (t->parms.iph.daddr == 0 || 194f97c1e0cSJoe Perches ipv4_is_multicast(t->parms.iph.daddr)) 1959f57c67cSPravin B Shelar return; 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 1989f57c67cSPravin B Shelar return; 1991da177e4SLinus Torvalds 200da6185d8SWei Yongjun if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) 2011da177e4SLinus Torvalds t->err_count++; 2021da177e4SLinus Torvalds else 2031da177e4SLinus Torvalds t->err_count = 1; 2041da177e4SLinus Torvalds t->err_time = jiffies; 2059f57c67cSPravin B Shelar } 2069f57c67cSPravin B Shelar 2079f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info) 2089f57c67cSPravin B Shelar { 2099f57c67cSPravin B Shelar /* All the routers (except for Linux) return only 2109f57c67cSPravin B Shelar * 8 bytes of packet payload. It means, that precise relaying of 2119f57c67cSPravin B Shelar * ICMP in the real Internet is absolutely infeasible. 2129f57c67cSPravin B Shelar * 2139f57c67cSPravin B Shelar * Moreover, Cisco "wise men" put GRE key to the third word 2149f57c67cSPravin B Shelar * in GRE header. It makes impossible maintaining even soft 2159f57c67cSPravin B Shelar * state for keyed 2169f57c67cSPravin B Shelar * GRE tunnels with enabled checksum. Tell them "thank you". 2179f57c67cSPravin B Shelar * 2189f57c67cSPravin B Shelar * Well, I wonder, rfc1812 was written by Cisco employee, 2199f57c67cSPravin B Shelar * what the hell these idiots break standards established 2209f57c67cSPravin B Shelar * by themselves??? 2219f57c67cSPravin B Shelar */ 2229f57c67cSPravin B Shelar 223e582615aSEric Dumazet const struct iphdr *iph = (struct iphdr *)skb->data; 2249f57c67cSPravin B Shelar const int type = icmp_hdr(skb)->type; 2259f57c67cSPravin B Shelar const int code = icmp_hdr(skb)->code; 2269f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 2279f57c67cSPravin B Shelar bool csum_err = false; 2289f57c67cSPravin B Shelar 229e582615aSEric Dumazet if (gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 230e582615aSEric Dumazet iph->ihl * 4) < 0) { 2319f57c67cSPravin B Shelar if (!csum_err) /* ignore csum errors. */ 2329f57c67cSPravin B Shelar return; 2339f57c67cSPravin B Shelar } 2349f57c67cSPravin B Shelar 2359f57c67cSPravin B Shelar if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 2369f57c67cSPravin B Shelar ipv4_update_pmtu(skb, dev_net(skb->dev), info, 2379f57c67cSPravin B Shelar skb->dev->ifindex, 0, IPPROTO_GRE, 0); 2389f57c67cSPravin B Shelar return; 2399f57c67cSPravin B Shelar } 2409f57c67cSPravin B Shelar if (type == ICMP_REDIRECT) { 2419f57c67cSPravin B Shelar ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0, 2429f57c67cSPravin B Shelar IPPROTO_GRE, 0); 2439f57c67cSPravin B Shelar return; 2449f57c67cSPravin B Shelar } 2459f57c67cSPravin B Shelar 2469f57c67cSPravin B Shelar ipgre_err(skb, info, &tpi); 2471da177e4SLinus Torvalds } 2481da177e4SLinus Torvalds 249125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 250125372faSJiri Benc struct ip_tunnel_net *itn, int hdr_len, bool raw_proto) 2511da177e4SLinus Torvalds { 2522e15ea39SPravin B Shelar struct metadata_dst *tun_dst = NULL; 253b71d1d42SEric Dumazet const struct iphdr *iph; 2541da177e4SLinus Torvalds struct ip_tunnel *tunnel; 2551da177e4SLinus Torvalds 256eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb); 257bda7bb46SPravin B Shelar tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 258bda7bb46SPravin B Shelar iph->saddr, iph->daddr, tpi->key); 2591da177e4SLinus Torvalds 260d2083287Sstephen hemminger if (tunnel) { 261125372faSJiri Benc if (__iptunnel_pull_header(skb, hdr_len, tpi->proto, 262125372faSJiri Benc raw_proto, false) < 0) 263244a797bSJiri Benc goto drop; 264244a797bSJiri Benc 265e271c7b4SJiri Benc if (tunnel->dev->type != ARPHRD_NONE) 2660e3da5bbSTimo Teräs skb_pop_mac_header(skb); 267e271c7b4SJiri Benc else 268e271c7b4SJiri Benc skb_reset_mac_header(skb); 2692e15ea39SPravin B Shelar if (tunnel->collect_md) { 270c29a70d2SPravin B Shelar __be16 flags; 271c29a70d2SPravin B Shelar __be64 tun_id; 2722e15ea39SPravin B Shelar 273c29a70d2SPravin B Shelar flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); 274d817f432SAmir Vadai tun_id = key32_to_tunnel_id(tpi->key); 275c29a70d2SPravin B Shelar tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0); 2762e15ea39SPravin B Shelar if (!tun_dst) 2772e15ea39SPravin B Shelar return PACKET_REJECT; 2782e15ea39SPravin B Shelar } 2792e15ea39SPravin B Shelar 2802e15ea39SPravin B Shelar ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 281bda7bb46SPravin B Shelar return PACKET_RCVD; 2821da177e4SLinus Torvalds } 283125372faSJiri Benc return PACKET_NEXT; 284244a797bSJiri Benc 285244a797bSJiri Benc drop: 286244a797bSJiri Benc kfree_skb(skb); 287244a797bSJiri Benc return PACKET_RCVD; 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds 290125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 291125372faSJiri Benc int hdr_len) 292125372faSJiri Benc { 293125372faSJiri Benc struct net *net = dev_net(skb->dev); 294125372faSJiri Benc struct ip_tunnel_net *itn; 295125372faSJiri Benc int res; 296125372faSJiri Benc 297125372faSJiri Benc if (tpi->proto == htons(ETH_P_TEB)) 298125372faSJiri Benc itn = net_generic(net, gre_tap_net_id); 299125372faSJiri Benc else 300125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 301125372faSJiri Benc 302125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, false); 303125372faSJiri Benc if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) { 304125372faSJiri Benc /* ipgre tunnels in collect metadata mode should receive 305125372faSJiri Benc * also ETH_P_TEB traffic. 306125372faSJiri Benc */ 307125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 308125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, true); 309125372faSJiri Benc } 310125372faSJiri Benc return res; 311125372faSJiri Benc } 312125372faSJiri Benc 3139f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb) 3149f57c67cSPravin B Shelar { 3159f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 3169f57c67cSPravin B Shelar bool csum_err = false; 31795f5c64cSTom Herbert int hdr_len; 3189f57c67cSPravin B Shelar 3199f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 3209f57c67cSPravin B Shelar if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { 3219f57c67cSPravin B Shelar /* Looped back packet, drop it! */ 3229f57c67cSPravin B Shelar if (rt_is_output_route(skb_rtable(skb))) 3239f57c67cSPravin B Shelar goto drop; 3249f57c67cSPravin B Shelar } 3259f57c67cSPravin B Shelar #endif 3269f57c67cSPravin B Shelar 327e582615aSEric Dumazet hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0); 328f132ae7cSJiri Benc if (hdr_len < 0) 32995f5c64cSTom Herbert goto drop; 33095f5c64cSTom Herbert 331244a797bSJiri Benc if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) 3329f57c67cSPravin B Shelar return 0; 3339f57c67cSPravin B Shelar 3349f57c67cSPravin B Shelar icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 3359f57c67cSPravin B Shelar drop: 3369f57c67cSPravin B Shelar kfree_skb(skb); 3379f57c67cSPravin B Shelar return 0; 3389f57c67cSPravin B Shelar } 3399f57c67cSPravin B Shelar 340c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, 341c5441932SPravin B Shelar const struct iphdr *tnl_params, 342c5441932SPravin B Shelar __be16 proto) 343c5441932SPravin B Shelar { 344c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 345c5441932SPravin B Shelar 346c5441932SPravin B Shelar if (tunnel->parms.o_flags & TUNNEL_SEQ) 347c5441932SPravin B Shelar tunnel->o_seqno++; 348cef401deSEric Dumazet 349c5441932SPravin B Shelar /* Push GRE header. */ 350182a352dSTom Herbert gre_build_header(skb, tunnel->tun_hlen, 351182a352dSTom Herbert tunnel->parms.o_flags, proto, tunnel->parms.o_key, 352182a352dSTom Herbert htonl(tunnel->o_seqno)); 3531da177e4SLinus Torvalds 354bf3d6a8fSNicolas Dichtel ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); 3551da177e4SLinus Torvalds } 3561da177e4SLinus Torvalds 357aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum) 358b2acd1dcSPravin B Shelar { 3596fa79666SEdward Cree return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); 360b2acd1dcSPravin B Shelar } 361b2acd1dcSPravin B Shelar 362fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb, 363fc4099f1SPravin B Shelar struct net_device *dev, 364fc4099f1SPravin B Shelar struct flowi4 *fl, 365fc4099f1SPravin B Shelar const struct ip_tunnel_key *key) 366fc4099f1SPravin B Shelar { 367fc4099f1SPravin B Shelar struct net *net = dev_net(dev); 368fc4099f1SPravin B Shelar 369fc4099f1SPravin B Shelar memset(fl, 0, sizeof(*fl)); 370fc4099f1SPravin B Shelar fl->daddr = key->u.ipv4.dst; 371fc4099f1SPravin B Shelar fl->saddr = key->u.ipv4.src; 372fc4099f1SPravin B Shelar fl->flowi4_tos = RT_TOS(key->tos); 373fc4099f1SPravin B Shelar fl->flowi4_mark = skb->mark; 374fc4099f1SPravin B Shelar fl->flowi4_proto = IPPROTO_GRE; 375fc4099f1SPravin B Shelar 376fc4099f1SPravin B Shelar return ip_route_output_key(net, fl); 377fc4099f1SPravin B Shelar } 378fc4099f1SPravin B Shelar 3792090714eSJiri Benc static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev, 3802090714eSJiri Benc __be16 proto) 3812e15ea39SPravin B Shelar { 3822e15ea39SPravin B Shelar struct ip_tunnel_info *tun_info; 3832e15ea39SPravin B Shelar const struct ip_tunnel_key *key; 384db3c6139SDaniel Borkmann struct rtable *rt = NULL; 3852e15ea39SPravin B Shelar struct flowi4 fl; 3862e15ea39SPravin B Shelar int min_headroom; 3872e15ea39SPravin B Shelar int tunnel_hlen; 3882e15ea39SPravin B Shelar __be16 df, flags; 389db3c6139SDaniel Borkmann bool use_cache; 3902e15ea39SPravin B Shelar int err; 3912e15ea39SPravin B Shelar 39261adedf3SJiri Benc tun_info = skb_tunnel_info(skb); 3937f9562a1SJiri Benc if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 3947f9562a1SJiri Benc ip_tunnel_info_af(tun_info) != AF_INET)) 3952e15ea39SPravin B Shelar goto err_free_skb; 3962e15ea39SPravin B Shelar 3972e15ea39SPravin B Shelar key = &tun_info->key; 398db3c6139SDaniel Borkmann use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); 399db3c6139SDaniel Borkmann if (use_cache) 400db3c6139SDaniel Borkmann rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl.saddr); 4013c1cb4d2SPaolo Abeni if (!rt) { 402fc4099f1SPravin B Shelar rt = gre_get_rt(skb, dev, &fl, key); 4032e15ea39SPravin B Shelar if (IS_ERR(rt)) 4042e15ea39SPravin B Shelar goto err_free_skb; 405db3c6139SDaniel Borkmann if (use_cache) 4063c1cb4d2SPaolo Abeni dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, 4073c1cb4d2SPaolo Abeni fl.saddr); 4083c1cb4d2SPaolo Abeni } 4092e15ea39SPravin B Shelar 41095f5c64cSTom Herbert tunnel_hlen = gre_calc_hlen(key->tun_flags); 4112e15ea39SPravin B Shelar 4122e15ea39SPravin B Shelar min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len 4132e15ea39SPravin B Shelar + tunnel_hlen + sizeof(struct iphdr); 4142e15ea39SPravin B Shelar if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { 4152e15ea39SPravin B Shelar int head_delta = SKB_DATA_ALIGN(min_headroom - 4162e15ea39SPravin B Shelar skb_headroom(skb) + 4172e15ea39SPravin B Shelar 16); 4182e15ea39SPravin B Shelar err = pskb_expand_head(skb, max_t(int, head_delta, 0), 4192e15ea39SPravin B Shelar 0, GFP_ATOMIC); 4202e15ea39SPravin B Shelar if (unlikely(err)) 4212e15ea39SPravin B Shelar goto err_free_rt; 4222e15ea39SPravin B Shelar } 4232e15ea39SPravin B Shelar 4242e15ea39SPravin B Shelar /* Push Tunnel header. */ 425aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM))) 4262e15ea39SPravin B Shelar goto err_free_rt; 4272e15ea39SPravin B Shelar 4282e15ea39SPravin B Shelar flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); 429cba65321SDavid S. Miller gre_build_header(skb, tunnel_hlen, flags, proto, 430d817f432SAmir Vadai tunnel_id_to_key32(tun_info->key.tun_id), 0); 4312e15ea39SPravin B Shelar 4322e15ea39SPravin B Shelar df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; 433039f5062SPravin B Shelar 434039f5062SPravin B Shelar iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, 4357c383fb2SJiri Benc key->tos, key->ttl, df, false); 4362e15ea39SPravin B Shelar return; 4372e15ea39SPravin B Shelar 4382e15ea39SPravin B Shelar err_free_rt: 4392e15ea39SPravin B Shelar ip_rt_put(rt); 4402e15ea39SPravin B Shelar err_free_skb: 4412e15ea39SPravin B Shelar kfree_skb(skb); 4422e15ea39SPravin B Shelar dev->stats.tx_dropped++; 4432e15ea39SPravin B Shelar } 4442e15ea39SPravin B Shelar 445fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) 446fc4099f1SPravin B Shelar { 447fc4099f1SPravin B Shelar struct ip_tunnel_info *info = skb_tunnel_info(skb); 448fc4099f1SPravin B Shelar struct rtable *rt; 449fc4099f1SPravin B Shelar struct flowi4 fl4; 450fc4099f1SPravin B Shelar 451fc4099f1SPravin B Shelar if (ip_tunnel_info_af(info) != AF_INET) 452fc4099f1SPravin B Shelar return -EINVAL; 453fc4099f1SPravin B Shelar 454fc4099f1SPravin B Shelar rt = gre_get_rt(skb, dev, &fl4, &info->key); 455fc4099f1SPravin B Shelar if (IS_ERR(rt)) 456fc4099f1SPravin B Shelar return PTR_ERR(rt); 457fc4099f1SPravin B Shelar 458fc4099f1SPravin B Shelar ip_rt_put(rt); 459fc4099f1SPravin B Shelar info->key.u.ipv4.src = fl4.saddr; 460fc4099f1SPravin B Shelar return 0; 461fc4099f1SPravin B Shelar } 462fc4099f1SPravin B Shelar 463c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb, 464c5441932SPravin B Shelar struct net_device *dev) 465ee34c1ebSMichal Schmidt { 466c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 467c5441932SPravin B Shelar const struct iphdr *tnl_params; 468ee34c1ebSMichal Schmidt 4692e15ea39SPravin B Shelar if (tunnel->collect_md) { 4702090714eSJiri Benc gre_fb_xmit(skb, dev, skb->protocol); 4712e15ea39SPravin B Shelar return NETDEV_TX_OK; 4722e15ea39SPravin B Shelar } 4732e15ea39SPravin B Shelar 474c5441932SPravin B Shelar if (dev->header_ops) { 475c5441932SPravin B Shelar /* Need space for new headers */ 476c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom - 4772bac7cb3SChen Gang (tunnel->hlen + sizeof(struct iphdr)))) 478c5441932SPravin B Shelar goto free_skb; 479ee34c1ebSMichal Schmidt 480c5441932SPravin B Shelar tnl_params = (const struct iphdr *)skb->data; 481cbb1e85fSDavid S. Miller 482c5441932SPravin B Shelar /* Pull skb since ip_tunnel_xmit() needs skb->data pointing 483c5441932SPravin B Shelar * to gre header. 484c5441932SPravin B Shelar */ 485c5441932SPravin B Shelar skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); 4868a0033a9STimo Teräs skb_reset_mac_header(skb); 487c5441932SPravin B Shelar } else { 488c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 489c5441932SPravin B Shelar goto free_skb; 490c5441932SPravin B Shelar 491c5441932SPravin B Shelar tnl_params = &tunnel->parms.iph; 492ee34c1ebSMichal Schmidt } 493e1a80002SHerbert Xu 494aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 495aed069dfSAlexander Duyck goto free_skb; 4968a0033a9STimo Teräs 497c5441932SPravin B Shelar __gre_xmit(skb, dev, tnl_params, skb->protocol); 498c5441932SPravin B Shelar return NETDEV_TX_OK; 499c5441932SPravin B Shelar 500c5441932SPravin B Shelar free_skb: 5013acfa1e7SEric Dumazet kfree_skb(skb); 502c5441932SPravin B Shelar dev->stats.tx_dropped++; 503c5441932SPravin B Shelar return NETDEV_TX_OK; 504ee34c1ebSMichal Schmidt } 505ee34c1ebSMichal Schmidt 506c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, 507c5441932SPravin B Shelar struct net_device *dev) 508c5441932SPravin B Shelar { 509c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 510ee34c1ebSMichal Schmidt 5112e15ea39SPravin B Shelar if (tunnel->collect_md) { 5122090714eSJiri Benc gre_fb_xmit(skb, dev, htons(ETH_P_TEB)); 5132e15ea39SPravin B Shelar return NETDEV_TX_OK; 5142e15ea39SPravin B Shelar } 5152e15ea39SPravin B Shelar 516aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 517aed069dfSAlexander Duyck goto free_skb; 518ee34c1ebSMichal Schmidt 519c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 520c5441932SPravin B Shelar goto free_skb; 52142aa9162SHerbert Xu 522c5441932SPravin B Shelar __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB)); 523c5441932SPravin B Shelar return NETDEV_TX_OK; 524c5441932SPravin B Shelar 525c5441932SPravin B Shelar free_skb: 5263acfa1e7SEric Dumazet kfree_skb(skb); 527c5441932SPravin B Shelar dev->stats.tx_dropped++; 528c5441932SPravin B Shelar return NETDEV_TX_OK; 52968c33163SPravin B Shelar } 530ee34c1ebSMichal Schmidt 531c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev, 532c5441932SPravin B Shelar struct ifreq *ifr, int cmd) 5331da177e4SLinus Torvalds { 5344565e991STom Herbert int err; 5351da177e4SLinus Torvalds struct ip_tunnel_parm p; 5361da177e4SLinus Torvalds 5371da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 538c5441932SPravin B Shelar return -EFAULT; 5396c734fb8SCong Wang if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { 5401da177e4SLinus Torvalds if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || 5411da177e4SLinus Torvalds p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) || 5426c734fb8SCong Wang ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) 5431da177e4SLinus Torvalds return -EINVAL; 544c5441932SPravin B Shelar } 545c5441932SPravin B Shelar p.i_flags = gre_flags_to_tnl_flags(p.i_flags); 546c5441932SPravin B Shelar p.o_flags = gre_flags_to_tnl_flags(p.o_flags); 547c5441932SPravin B Shelar 548c5441932SPravin B Shelar err = ip_tunnel_ioctl(dev, &p, cmd); 549c5441932SPravin B Shelar if (err) 550c5441932SPravin B Shelar return err; 551c5441932SPravin B Shelar 55295f5c64cSTom Herbert p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags); 55395f5c64cSTom Herbert p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags); 554c5441932SPravin B Shelar 555c5441932SPravin B Shelar if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) 556c5441932SPravin B Shelar return -EFAULT; 5571da177e4SLinus Torvalds return 0; 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds 5601da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-) 5611da177e4SLinus Torvalds It allows to construct virtual multiprotocol broadcast "LAN" 5621da177e4SLinus Torvalds over the Internet, provided multicast routing is tuned. 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds 5651da177e4SLinus Torvalds I have no idea was this bicycle invented before me, 5661da177e4SLinus Torvalds so that I had to set ARPHRD_IPGRE to a random value. 5671da177e4SLinus Torvalds I have an impression, that Cisco could make something similar, 5681da177e4SLinus Torvalds but this feature is apparently missing in IOS<=11.2(8). 5691da177e4SLinus Torvalds 5701da177e4SLinus Torvalds I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks 5711da177e4SLinus Torvalds with broadcast 224.66.66.66. If you have access to mbone, play with me :-) 5721da177e4SLinus Torvalds 5731da177e4SLinus Torvalds ping -t 255 224.66.66.66 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds If nobody answers, mbone does not work. 5761da177e4SLinus Torvalds 5771da177e4SLinus Torvalds ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 5781da177e4SLinus Torvalds ip addr add 10.66.66.<somewhat>/24 dev Universe 5791da177e4SLinus Torvalds ifconfig Universe up 5801da177e4SLinus Torvalds ifconfig Universe add fe80::<Your_real_addr>/10 5811da177e4SLinus Torvalds ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 5821da177e4SLinus Torvalds ftp 10.66.66.66 5831da177e4SLinus Torvalds ... 5841da177e4SLinus Torvalds ftp fec0:6666:6666::193.233.7.65 5851da177e4SLinus Torvalds ... 5861da177e4SLinus Torvalds */ 5873b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev, 5883b04dddeSStephen Hemminger unsigned short type, 5891507850bSEric Dumazet const void *daddr, const void *saddr, unsigned int len) 5901da177e4SLinus Torvalds { 5912941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 592c5441932SPravin B Shelar struct iphdr *iph; 593c5441932SPravin B Shelar struct gre_base_hdr *greh; 594c5441932SPravin B Shelar 595d58ff351SJohannes Berg iph = skb_push(skb, t->hlen + sizeof(*iph)); 596c5441932SPravin B Shelar greh = (struct gre_base_hdr *)(iph+1); 59795f5c64cSTom Herbert greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags); 598c5441932SPravin B Shelar greh->protocol = htons(type); 5991da177e4SLinus Torvalds 6001da177e4SLinus Torvalds memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); 6011da177e4SLinus Torvalds 602c5441932SPravin B Shelar /* Set the source hardware address. */ 6031da177e4SLinus Torvalds if (saddr) 6041da177e4SLinus Torvalds memcpy(&iph->saddr, saddr, 4); 6056d55cb91STimo Teräs if (daddr) 6061da177e4SLinus Torvalds memcpy(&iph->daddr, daddr, 4); 6076d55cb91STimo Teräs if (iph->daddr) 60877a482bdSTimo Teräs return t->hlen + sizeof(*iph); 6091da177e4SLinus Torvalds 610c5441932SPravin B Shelar return -(t->hlen + sizeof(*iph)); 6111da177e4SLinus Torvalds } 6121da177e4SLinus Torvalds 6136a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) 6146a5f44d7STimo Teras { 615b71d1d42SEric Dumazet const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); 6166a5f44d7STimo Teras memcpy(haddr, &iph->saddr, 4); 6176a5f44d7STimo Teras return 4; 6186a5f44d7STimo Teras } 6196a5f44d7STimo Teras 6203b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = { 6213b04dddeSStephen Hemminger .create = ipgre_header, 6226a5f44d7STimo Teras .parse = ipgre_header_parse, 6233b04dddeSStephen Hemminger }; 6243b04dddeSStephen Hemminger 6256a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST 6261da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev) 6271da177e4SLinus Torvalds { 6282941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 6291da177e4SLinus Torvalds 630f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr)) { 631cbb1e85fSDavid S. Miller struct flowi4 fl4; 632cbb1e85fSDavid S. Miller struct rtable *rt; 633cbb1e85fSDavid S. Miller 634b57708adSNicolas Dichtel rt = ip_route_output_gre(t->net, &fl4, 63578fbfd8aSDavid S. Miller t->parms.iph.daddr, 63678fbfd8aSDavid S. Miller t->parms.iph.saddr, 63778fbfd8aSDavid S. Miller t->parms.o_key, 63878fbfd8aSDavid S. Miller RT_TOS(t->parms.iph.tos), 63978fbfd8aSDavid S. Miller t->parms.link); 640b23dd4feSDavid S. Miller if (IS_ERR(rt)) 6411da177e4SLinus Torvalds return -EADDRNOTAVAIL; 642d8d1f30bSChangli Gao dev = rt->dst.dev; 6431da177e4SLinus Torvalds ip_rt_put(rt); 64451456b29SIan Morris if (!__in_dev_get_rtnl(dev)) 6451da177e4SLinus Torvalds return -EADDRNOTAVAIL; 6461da177e4SLinus Torvalds t->mlink = dev->ifindex; 647e5ed6399SHerbert Xu ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); 6481da177e4SLinus Torvalds } 6491da177e4SLinus Torvalds return 0; 6501da177e4SLinus Torvalds } 6511da177e4SLinus Torvalds 6521da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev) 6531da177e4SLinus Torvalds { 6542941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 655b8c26a33SStephen Hemminger 656f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) { 6577fee0ca2SDenis V. Lunev struct in_device *in_dev; 658b57708adSNicolas Dichtel in_dev = inetdev_by_index(t->net, t->mlink); 6598723e1b4SEric Dumazet if (in_dev) 6601da177e4SLinus Torvalds ip_mc_dec_group(in_dev, t->parms.iph.daddr); 6611da177e4SLinus Torvalds } 6621da177e4SLinus Torvalds return 0; 6631da177e4SLinus Torvalds } 6641da177e4SLinus Torvalds #endif 6651da177e4SLinus Torvalds 666b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = { 667b8c26a33SStephen Hemminger .ndo_init = ipgre_tunnel_init, 668c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 669b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST 670b8c26a33SStephen Hemminger .ndo_open = ipgre_open, 671b8c26a33SStephen Hemminger .ndo_stop = ipgre_close, 672b8c26a33SStephen Hemminger #endif 673c5441932SPravin B Shelar .ndo_start_xmit = ipgre_xmit, 674b8c26a33SStephen Hemminger .ndo_do_ioctl = ipgre_tunnel_ioctl, 675c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 676c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 6771e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 678b8c26a33SStephen Hemminger }; 679b8c26a33SStephen Hemminger 6806b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG | \ 6816b78f16eSEric Dumazet NETIF_F_FRAGLIST | \ 6826b78f16eSEric Dumazet NETIF_F_HIGHDMA | \ 6836b78f16eSEric Dumazet NETIF_F_HW_CSUM) 6846b78f16eSEric Dumazet 6851da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev) 6861da177e4SLinus Torvalds { 687b8c26a33SStephen Hemminger dev->netdev_ops = &ipgre_netdev_ops; 6885a455275SNicolas Dichtel dev->type = ARPHRD_IPGRE; 689c5441932SPravin B Shelar ip_tunnel_setup(dev, ipgre_net_id); 690c5441932SPravin B Shelar } 6911da177e4SLinus Torvalds 692c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev) 693c5441932SPravin B Shelar { 694c5441932SPravin B Shelar struct ip_tunnel *tunnel; 6954565e991STom Herbert int t_hlen; 696c5441932SPravin B Shelar 697c5441932SPravin B Shelar tunnel = netdev_priv(dev); 69895f5c64cSTom Herbert tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 699c5441932SPravin B Shelar tunnel->parms.iph.protocol = IPPROTO_GRE; 700c5441932SPravin B Shelar 7014565e991STom Herbert tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; 7024565e991STom Herbert 7034565e991STom Herbert t_hlen = tunnel->hlen + sizeof(struct iphdr); 7044565e991STom Herbert 7054565e991STom Herbert dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; 7064565e991STom Herbert dev->mtu = ETH_DATA_LEN - t_hlen - 4; 7076b78f16eSEric Dumazet 708b57708adSNicolas Dichtel dev->features |= GRE_FEATURES; 7096b78f16eSEric Dumazet dev->hw_features |= GRE_FEATURES; 710c5441932SPravin B Shelar 711c5441932SPravin B Shelar if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 712a0ca153fSAlexander Duyck /* TCP offload with GRE SEQ is not supported, nor 713a0ca153fSAlexander Duyck * can we support 2 levels of outer headers requiring 714a0ca153fSAlexander Duyck * an update. 715a0ca153fSAlexander Duyck */ 716a0ca153fSAlexander Duyck if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || 717a0ca153fSAlexander Duyck (tunnel->encap.type == TUNNEL_ENCAP_NONE)) { 718c5441932SPravin B Shelar dev->features |= NETIF_F_GSO_SOFTWARE; 719c5441932SPravin B Shelar dev->hw_features |= NETIF_F_GSO_SOFTWARE; 720a0ca153fSAlexander Duyck } 721a0ca153fSAlexander Duyck 722c5441932SPravin B Shelar /* Can use a lockless transmit, unless we generate 723c5441932SPravin B Shelar * output sequences 724c5441932SPravin B Shelar */ 725c5441932SPravin B Shelar dev->features |= NETIF_F_LLTX; 726c5441932SPravin B Shelar } 7271da177e4SLinus Torvalds } 7281da177e4SLinus Torvalds 7291da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev) 7301da177e4SLinus Torvalds { 731c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 732c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 7331da177e4SLinus Torvalds 734c5441932SPravin B Shelar __gre_tunnel_init(dev); 7351da177e4SLinus Torvalds 736c5441932SPravin B Shelar memcpy(dev->dev_addr, &iph->saddr, 4); 737c5441932SPravin B Shelar memcpy(dev->broadcast, &iph->daddr, 4); 7381da177e4SLinus Torvalds 739c5441932SPravin B Shelar dev->flags = IFF_NOARP; 74002875878SEric Dumazet netif_keep_dst(dev); 741c5441932SPravin B Shelar dev->addr_len = 4; 7421da177e4SLinus Torvalds 743a64b04d8SJiri Benc if (iph->daddr && !tunnel->collect_md) { 7441da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST 745f97c1e0cSJoe Perches if (ipv4_is_multicast(iph->daddr)) { 7461da177e4SLinus Torvalds if (!iph->saddr) 7471da177e4SLinus Torvalds return -EINVAL; 7481da177e4SLinus Torvalds dev->flags = IFF_BROADCAST; 7493b04dddeSStephen Hemminger dev->header_ops = &ipgre_header_ops; 7501da177e4SLinus Torvalds } 7511da177e4SLinus Torvalds #endif 752a64b04d8SJiri Benc } else if (!tunnel->collect_md) { 7536a5f44d7STimo Teras dev->header_ops = &ipgre_header_ops; 754a64b04d8SJiri Benc } 7551da177e4SLinus Torvalds 756c5441932SPravin B Shelar return ip_tunnel_init(dev); 75760769a5dSEric Dumazet } 75860769a5dSEric Dumazet 7599f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = { 7609f57c67cSPravin B Shelar .handler = gre_rcv, 7619f57c67cSPravin B Shelar .err_handler = gre_err, 7621da177e4SLinus Torvalds }; 7631da177e4SLinus Torvalds 7642c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net) 76559a4c759SPavel Emelyanov { 766c5441932SPravin B Shelar return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); 76759a4c759SPavel Emelyanov } 76859a4c759SPavel Emelyanov 7692c8c1e72SAlexey Dobriyan static void __net_exit ipgre_exit_net(struct net *net) 77059a4c759SPavel Emelyanov { 771c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id); 7726c742e71SNicolas Dichtel ip_tunnel_delete_net(itn, &ipgre_link_ops); 77359a4c759SPavel Emelyanov } 77459a4c759SPavel Emelyanov 77559a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = { 77659a4c759SPavel Emelyanov .init = ipgre_init_net, 77759a4c759SPavel Emelyanov .exit = ipgre_exit_net, 778cfb8fbf2SEric W. Biederman .id = &ipgre_net_id, 779c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 78059a4c759SPavel Emelyanov }; 7811da177e4SLinus Torvalds 782*a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[], 783*a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack) 784c19e654dSHerbert Xu { 785c19e654dSHerbert Xu __be16 flags; 786c19e654dSHerbert Xu 787c19e654dSHerbert Xu if (!data) 788c19e654dSHerbert Xu return 0; 789c19e654dSHerbert Xu 790c19e654dSHerbert Xu flags = 0; 791c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 792c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 793c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 794c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 795c19e654dSHerbert Xu if (flags & (GRE_VERSION|GRE_ROUTING)) 796c19e654dSHerbert Xu return -EINVAL; 797c19e654dSHerbert Xu 798946b636fSJiri Benc if (data[IFLA_GRE_COLLECT_METADATA] && 799946b636fSJiri Benc data[IFLA_GRE_ENCAP_TYPE] && 800946b636fSJiri Benc nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) 801946b636fSJiri Benc return -EINVAL; 802946b636fSJiri Benc 803c19e654dSHerbert Xu return 0; 804c19e654dSHerbert Xu } 805c19e654dSHerbert Xu 806*a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[], 807*a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack) 808e1a80002SHerbert Xu { 809e1a80002SHerbert Xu __be32 daddr; 810e1a80002SHerbert Xu 811e1a80002SHerbert Xu if (tb[IFLA_ADDRESS]) { 812e1a80002SHerbert Xu if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) 813e1a80002SHerbert Xu return -EINVAL; 814e1a80002SHerbert Xu if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 815e1a80002SHerbert Xu return -EADDRNOTAVAIL; 816e1a80002SHerbert Xu } 817e1a80002SHerbert Xu 818e1a80002SHerbert Xu if (!data) 819e1a80002SHerbert Xu goto out; 820e1a80002SHerbert Xu 821e1a80002SHerbert Xu if (data[IFLA_GRE_REMOTE]) { 822e1a80002SHerbert Xu memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); 823e1a80002SHerbert Xu if (!daddr) 824e1a80002SHerbert Xu return -EINVAL; 825e1a80002SHerbert Xu } 826e1a80002SHerbert Xu 827e1a80002SHerbert Xu out: 828*a8b8a889SMatthias Schiffer return ipgre_tunnel_validate(tb, data, extack); 829e1a80002SHerbert Xu } 830e1a80002SHerbert Xu 83122a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev, 8322e15ea39SPravin B Shelar struct nlattr *data[], 8332e15ea39SPravin B Shelar struct nlattr *tb[], 8349830ad4cSCraig Gallek struct ip_tunnel_parm *parms, 8359830ad4cSCraig Gallek __u32 *fwmark) 836c19e654dSHerbert Xu { 83722a59be8SPhilip Prindeville struct ip_tunnel *t = netdev_priv(dev); 83822a59be8SPhilip Prindeville 8397bb82d92SHerbert Xu memset(parms, 0, sizeof(*parms)); 840c19e654dSHerbert Xu 841c19e654dSHerbert Xu parms->iph.protocol = IPPROTO_GRE; 842c19e654dSHerbert Xu 843c19e654dSHerbert Xu if (!data) 84422a59be8SPhilip Prindeville return 0; 845c19e654dSHerbert Xu 846c19e654dSHerbert Xu if (data[IFLA_GRE_LINK]) 847c19e654dSHerbert Xu parms->link = nla_get_u32(data[IFLA_GRE_LINK]); 848c19e654dSHerbert Xu 849c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 850c5441932SPravin B Shelar parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); 851c19e654dSHerbert Xu 852c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 853c5441932SPravin B Shelar parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); 854c19e654dSHerbert Xu 855c19e654dSHerbert Xu if (data[IFLA_GRE_IKEY]) 856c19e654dSHerbert Xu parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); 857c19e654dSHerbert Xu 858c19e654dSHerbert Xu if (data[IFLA_GRE_OKEY]) 859c19e654dSHerbert Xu parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); 860c19e654dSHerbert Xu 861c19e654dSHerbert Xu if (data[IFLA_GRE_LOCAL]) 86267b61f6cSJiri Benc parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); 863c19e654dSHerbert Xu 864c19e654dSHerbert Xu if (data[IFLA_GRE_REMOTE]) 86567b61f6cSJiri Benc parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); 866c19e654dSHerbert Xu 867c19e654dSHerbert Xu if (data[IFLA_GRE_TTL]) 868c19e654dSHerbert Xu parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); 869c19e654dSHerbert Xu 870c19e654dSHerbert Xu if (data[IFLA_GRE_TOS]) 871c19e654dSHerbert Xu parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); 872c19e654dSHerbert Xu 87322a59be8SPhilip Prindeville if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) { 87422a59be8SPhilip Prindeville if (t->ignore_df) 87522a59be8SPhilip Prindeville return -EINVAL; 876c19e654dSHerbert Xu parms->iph.frag_off = htons(IP_DF); 87722a59be8SPhilip Prindeville } 8782e15ea39SPravin B Shelar 8792e15ea39SPravin B Shelar if (data[IFLA_GRE_COLLECT_METADATA]) { 8802e15ea39SPravin B Shelar t->collect_md = true; 881e271c7b4SJiri Benc if (dev->type == ARPHRD_IPGRE) 882e271c7b4SJiri Benc dev->type = ARPHRD_NONE; 8832e15ea39SPravin B Shelar } 88422a59be8SPhilip Prindeville 88522a59be8SPhilip Prindeville if (data[IFLA_GRE_IGNORE_DF]) { 88622a59be8SPhilip Prindeville if (nla_get_u8(data[IFLA_GRE_IGNORE_DF]) 88722a59be8SPhilip Prindeville && (parms->iph.frag_off & htons(IP_DF))) 88822a59be8SPhilip Prindeville return -EINVAL; 88922a59be8SPhilip Prindeville t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]); 89022a59be8SPhilip Prindeville } 89122a59be8SPhilip Prindeville 8929830ad4cSCraig Gallek if (data[IFLA_GRE_FWMARK]) 8939830ad4cSCraig Gallek *fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]); 8949830ad4cSCraig Gallek 89522a59be8SPhilip Prindeville return 0; 896c19e654dSHerbert Xu } 897c19e654dSHerbert Xu 8984565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */ 8994565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[], 9004565e991STom Herbert struct ip_tunnel_encap *ipencap) 9014565e991STom Herbert { 9024565e991STom Herbert bool ret = false; 9034565e991STom Herbert 9044565e991STom Herbert memset(ipencap, 0, sizeof(*ipencap)); 9054565e991STom Herbert 9064565e991STom Herbert if (!data) 9074565e991STom Herbert return ret; 9084565e991STom Herbert 9094565e991STom Herbert if (data[IFLA_GRE_ENCAP_TYPE]) { 9104565e991STom Herbert ret = true; 9114565e991STom Herbert ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); 9124565e991STom Herbert } 9134565e991STom Herbert 9144565e991STom Herbert if (data[IFLA_GRE_ENCAP_FLAGS]) { 9154565e991STom Herbert ret = true; 9164565e991STom Herbert ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); 9174565e991STom Herbert } 9184565e991STom Herbert 9194565e991STom Herbert if (data[IFLA_GRE_ENCAP_SPORT]) { 9204565e991STom Herbert ret = true; 9213e97fa70SSabrina Dubroca ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); 9224565e991STom Herbert } 9234565e991STom Herbert 9244565e991STom Herbert if (data[IFLA_GRE_ENCAP_DPORT]) { 9254565e991STom Herbert ret = true; 9263e97fa70SSabrina Dubroca ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); 9274565e991STom Herbert } 9284565e991STom Herbert 9294565e991STom Herbert return ret; 9304565e991STom Herbert } 9314565e991STom Herbert 932c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev) 933e1a80002SHerbert Xu { 934c5441932SPravin B Shelar __gre_tunnel_init(dev); 935bec94d43Sstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 936e1a80002SHerbert Xu 937c5441932SPravin B Shelar return ip_tunnel_init(dev); 938e1a80002SHerbert Xu } 939e1a80002SHerbert Xu 940c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = { 941c5441932SPravin B Shelar .ndo_init = gre_tap_init, 942c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 943c5441932SPravin B Shelar .ndo_start_xmit = gre_tap_xmit, 944b8c26a33SStephen Hemminger .ndo_set_mac_address = eth_mac_addr, 945b8c26a33SStephen Hemminger .ndo_validate_addr = eth_validate_addr, 946c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 947c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 9481e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 949fc4099f1SPravin B Shelar .ndo_fill_metadata_dst = gre_fill_metadata_dst, 950b8c26a33SStephen Hemminger }; 951b8c26a33SStephen Hemminger 952e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev) 953e1a80002SHerbert Xu { 954e1a80002SHerbert Xu ether_setup(dev); 955c5441932SPravin B Shelar dev->netdev_ops = &gre_tap_netdev_ops; 956d13b161cSJiri Benc dev->priv_flags &= ~IFF_TX_SKB_SHARING; 957f8c1b7ceSstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 958c5441932SPravin B Shelar ip_tunnel_setup(dev, gre_tap_net_id); 959e1a80002SHerbert Xu } 960e1a80002SHerbert Xu 961c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev, 9627a3f4a18SMatthias Schiffer struct nlattr *tb[], struct nlattr *data[], 9637a3f4a18SMatthias Schiffer struct netlink_ext_ack *extack) 964c19e654dSHerbert Xu { 965c5441932SPravin B Shelar struct ip_tunnel_parm p; 9664565e991STom Herbert struct ip_tunnel_encap ipencap; 9679830ad4cSCraig Gallek __u32 fwmark = 0; 96822a59be8SPhilip Prindeville int err; 9694565e991STom Herbert 9704565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 9714565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 97222a59be8SPhilip Prindeville err = ip_tunnel_encap_setup(t, &ipencap); 9734565e991STom Herbert 9744565e991STom Herbert if (err < 0) 9754565e991STom Herbert return err; 9764565e991STom Herbert } 977c19e654dSHerbert Xu 9789830ad4cSCraig Gallek err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); 97922a59be8SPhilip Prindeville if (err < 0) 98022a59be8SPhilip Prindeville return err; 9819830ad4cSCraig Gallek return ip_tunnel_newlink(dev, tb, &p, fwmark); 982c19e654dSHerbert Xu } 983c19e654dSHerbert Xu 984c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], 985ad744b22SMatthias Schiffer struct nlattr *data[], 986ad744b22SMatthias Schiffer struct netlink_ext_ack *extack) 987c19e654dSHerbert Xu { 9889830ad4cSCraig Gallek struct ip_tunnel *t = netdev_priv(dev); 989c19e654dSHerbert Xu struct ip_tunnel_parm p; 9904565e991STom Herbert struct ip_tunnel_encap ipencap; 9919830ad4cSCraig Gallek __u32 fwmark = t->fwmark; 99222a59be8SPhilip Prindeville int err; 9934565e991STom Herbert 9944565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 99522a59be8SPhilip Prindeville err = ip_tunnel_encap_setup(t, &ipencap); 9964565e991STom Herbert 9974565e991STom Herbert if (err < 0) 9984565e991STom Herbert return err; 9994565e991STom Herbert } 1000c19e654dSHerbert Xu 10019830ad4cSCraig Gallek err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); 100222a59be8SPhilip Prindeville if (err < 0) 100322a59be8SPhilip Prindeville return err; 10049830ad4cSCraig Gallek return ip_tunnel_changelink(dev, tb, &p, fwmark); 1005c19e654dSHerbert Xu } 1006c19e654dSHerbert Xu 1007c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev) 1008c19e654dSHerbert Xu { 1009c19e654dSHerbert Xu return 1010c19e654dSHerbert Xu /* IFLA_GRE_LINK */ 1011c19e654dSHerbert Xu nla_total_size(4) + 1012c19e654dSHerbert Xu /* IFLA_GRE_IFLAGS */ 1013c19e654dSHerbert Xu nla_total_size(2) + 1014c19e654dSHerbert Xu /* IFLA_GRE_OFLAGS */ 1015c19e654dSHerbert Xu nla_total_size(2) + 1016c19e654dSHerbert Xu /* IFLA_GRE_IKEY */ 1017c19e654dSHerbert Xu nla_total_size(4) + 1018c19e654dSHerbert Xu /* IFLA_GRE_OKEY */ 1019c19e654dSHerbert Xu nla_total_size(4) + 1020c19e654dSHerbert Xu /* IFLA_GRE_LOCAL */ 1021c19e654dSHerbert Xu nla_total_size(4) + 1022c19e654dSHerbert Xu /* IFLA_GRE_REMOTE */ 1023c19e654dSHerbert Xu nla_total_size(4) + 1024c19e654dSHerbert Xu /* IFLA_GRE_TTL */ 1025c19e654dSHerbert Xu nla_total_size(1) + 1026c19e654dSHerbert Xu /* IFLA_GRE_TOS */ 1027c19e654dSHerbert Xu nla_total_size(1) + 1028c19e654dSHerbert Xu /* IFLA_GRE_PMTUDISC */ 1029c19e654dSHerbert Xu nla_total_size(1) + 10304565e991STom Herbert /* IFLA_GRE_ENCAP_TYPE */ 10314565e991STom Herbert nla_total_size(2) + 10324565e991STom Herbert /* IFLA_GRE_ENCAP_FLAGS */ 10334565e991STom Herbert nla_total_size(2) + 10344565e991STom Herbert /* IFLA_GRE_ENCAP_SPORT */ 10354565e991STom Herbert nla_total_size(2) + 10364565e991STom Herbert /* IFLA_GRE_ENCAP_DPORT */ 10374565e991STom Herbert nla_total_size(2) + 10382e15ea39SPravin B Shelar /* IFLA_GRE_COLLECT_METADATA */ 10392e15ea39SPravin B Shelar nla_total_size(0) + 104022a59be8SPhilip Prindeville /* IFLA_GRE_IGNORE_DF */ 104122a59be8SPhilip Prindeville nla_total_size(1) + 10429830ad4cSCraig Gallek /* IFLA_GRE_FWMARK */ 10439830ad4cSCraig Gallek nla_total_size(4) + 1044c19e654dSHerbert Xu 0; 1045c19e654dSHerbert Xu } 1046c19e654dSHerbert Xu 1047c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) 1048c19e654dSHerbert Xu { 1049c19e654dSHerbert Xu struct ip_tunnel *t = netdev_priv(dev); 1050c19e654dSHerbert Xu struct ip_tunnel_parm *p = &t->parms; 1051c19e654dSHerbert Xu 1052f3756b79SDavid S. Miller if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || 105395f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_IFLAGS, 105495f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->i_flags)) || 105595f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_OFLAGS, 105695f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->o_flags)) || 1057f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || 1058f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || 1059930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || 1060930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) || 1061f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) || 1062f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) || 1063f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_PMTUDISC, 10649830ad4cSCraig Gallek !!(p->iph.frag_off & htons(IP_DF))) || 10659830ad4cSCraig Gallek nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark)) 1066f3756b79SDavid S. Miller goto nla_put_failure; 10674565e991STom Herbert 10684565e991STom Herbert if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, 10694565e991STom Herbert t->encap.type) || 10703e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, 10714565e991STom Herbert t->encap.sport) || 10723e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, 10734565e991STom Herbert t->encap.dport) || 10744565e991STom Herbert nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, 1075e1b2cb65STom Herbert t->encap.flags)) 10764565e991STom Herbert goto nla_put_failure; 10774565e991STom Herbert 107822a59be8SPhilip Prindeville if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df)) 107922a59be8SPhilip Prindeville goto nla_put_failure; 108022a59be8SPhilip Prindeville 10812e15ea39SPravin B Shelar if (t->collect_md) { 10822e15ea39SPravin B Shelar if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) 10832e15ea39SPravin B Shelar goto nla_put_failure; 10842e15ea39SPravin B Shelar } 10852e15ea39SPravin B Shelar 1086c19e654dSHerbert Xu return 0; 1087c19e654dSHerbert Xu 1088c19e654dSHerbert Xu nla_put_failure: 1089c19e654dSHerbert Xu return -EMSGSIZE; 1090c19e654dSHerbert Xu } 1091c19e654dSHerbert Xu 1092c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { 1093c19e654dSHerbert Xu [IFLA_GRE_LINK] = { .type = NLA_U32 }, 1094c19e654dSHerbert Xu [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, 1095c19e654dSHerbert Xu [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, 1096c19e654dSHerbert Xu [IFLA_GRE_IKEY] = { .type = NLA_U32 }, 1097c19e654dSHerbert Xu [IFLA_GRE_OKEY] = { .type = NLA_U32 }, 10984d74f8baSPatrick McHardy [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, 10994d74f8baSPatrick McHardy [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, 1100c19e654dSHerbert Xu [IFLA_GRE_TTL] = { .type = NLA_U8 }, 1101c19e654dSHerbert Xu [IFLA_GRE_TOS] = { .type = NLA_U8 }, 1102c19e654dSHerbert Xu [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, 11034565e991STom Herbert [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, 11044565e991STom Herbert [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, 11054565e991STom Herbert [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, 11064565e991STom Herbert [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, 11072e15ea39SPravin B Shelar [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, 110822a59be8SPhilip Prindeville [IFLA_GRE_IGNORE_DF] = { .type = NLA_U8 }, 11099830ad4cSCraig Gallek [IFLA_GRE_FWMARK] = { .type = NLA_U32 }, 1110c19e654dSHerbert Xu }; 1111c19e654dSHerbert Xu 1112c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = { 1113c19e654dSHerbert Xu .kind = "gre", 1114c19e654dSHerbert Xu .maxtype = IFLA_GRE_MAX, 1115c19e654dSHerbert Xu .policy = ipgre_policy, 1116c19e654dSHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1117c19e654dSHerbert Xu .setup = ipgre_tunnel_setup, 1118c19e654dSHerbert Xu .validate = ipgre_tunnel_validate, 1119c19e654dSHerbert Xu .newlink = ipgre_newlink, 1120c19e654dSHerbert Xu .changelink = ipgre_changelink, 1121c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1122c19e654dSHerbert Xu .get_size = ipgre_get_size, 1123c19e654dSHerbert Xu .fill_info = ipgre_fill_info, 11241728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1125c19e654dSHerbert Xu }; 1126c19e654dSHerbert Xu 1127e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { 1128e1a80002SHerbert Xu .kind = "gretap", 1129e1a80002SHerbert Xu .maxtype = IFLA_GRE_MAX, 1130e1a80002SHerbert Xu .policy = ipgre_policy, 1131e1a80002SHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1132e1a80002SHerbert Xu .setup = ipgre_tap_setup, 1133e1a80002SHerbert Xu .validate = ipgre_tap_validate, 1134e1a80002SHerbert Xu .newlink = ipgre_newlink, 1135e1a80002SHerbert Xu .changelink = ipgre_changelink, 1136c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1137e1a80002SHerbert Xu .get_size = ipgre_get_size, 1138e1a80002SHerbert Xu .fill_info = ipgre_fill_info, 11391728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1140e1a80002SHerbert Xu }; 1141e1a80002SHerbert Xu 1142b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name, 1143b2acd1dcSPravin B Shelar u8 name_assign_type) 1144b2acd1dcSPravin B Shelar { 1145b2acd1dcSPravin B Shelar struct nlattr *tb[IFLA_MAX + 1]; 1146b2acd1dcSPravin B Shelar struct net_device *dev; 1147106da663SNicolas Dichtel LIST_HEAD(list_kill); 1148b2acd1dcSPravin B Shelar struct ip_tunnel *t; 1149b2acd1dcSPravin B Shelar int err; 1150b2acd1dcSPravin B Shelar 1151b2acd1dcSPravin B Shelar memset(&tb, 0, sizeof(tb)); 1152b2acd1dcSPravin B Shelar 1153b2acd1dcSPravin B Shelar dev = rtnl_create_link(net, name, name_assign_type, 1154b2acd1dcSPravin B Shelar &ipgre_tap_ops, tb); 1155b2acd1dcSPravin B Shelar if (IS_ERR(dev)) 1156b2acd1dcSPravin B Shelar return dev; 1157b2acd1dcSPravin B Shelar 1158b2acd1dcSPravin B Shelar /* Configure flow based GRE device. */ 1159b2acd1dcSPravin B Shelar t = netdev_priv(dev); 1160b2acd1dcSPravin B Shelar t->collect_md = true; 1161b2acd1dcSPravin B Shelar 11627a3f4a18SMatthias Schiffer err = ipgre_newlink(net, dev, tb, NULL, NULL); 1163106da663SNicolas Dichtel if (err < 0) { 1164106da663SNicolas Dichtel free_netdev(dev); 1165106da663SNicolas Dichtel return ERR_PTR(err); 1166106da663SNicolas Dichtel } 11677e059158SDavid Wragg 11687e059158SDavid Wragg /* openvswitch users expect packet sizes to be unrestricted, 11697e059158SDavid Wragg * so set the largest MTU we can. 11707e059158SDavid Wragg */ 11717e059158SDavid Wragg err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); 11727e059158SDavid Wragg if (err) 11737e059158SDavid Wragg goto out; 11747e059158SDavid Wragg 1175da6f1da8SNicolas Dichtel err = rtnl_configure_link(dev, NULL); 1176da6f1da8SNicolas Dichtel if (err < 0) 1177da6f1da8SNicolas Dichtel goto out; 1178da6f1da8SNicolas Dichtel 1179b2acd1dcSPravin B Shelar return dev; 1180b2acd1dcSPravin B Shelar out: 1181106da663SNicolas Dichtel ip_tunnel_dellink(dev, &list_kill); 1182106da663SNicolas Dichtel unregister_netdevice_many(&list_kill); 1183b2acd1dcSPravin B Shelar return ERR_PTR(err); 1184b2acd1dcSPravin B Shelar } 1185b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create); 1186b2acd1dcSPravin B Shelar 1187c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net) 1188c5441932SPravin B Shelar { 11892e15ea39SPravin B Shelar return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); 1190c5441932SPravin B Shelar } 1191c5441932SPravin B Shelar 1192c5441932SPravin B Shelar static void __net_exit ipgre_tap_exit_net(struct net *net) 1193c5441932SPravin B Shelar { 1194c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id); 11956c742e71SNicolas Dichtel ip_tunnel_delete_net(itn, &ipgre_tap_ops); 1196c5441932SPravin B Shelar } 1197c5441932SPravin B Shelar 1198c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = { 1199c5441932SPravin B Shelar .init = ipgre_tap_init_net, 1200c5441932SPravin B Shelar .exit = ipgre_tap_exit_net, 1201c5441932SPravin B Shelar .id = &gre_tap_net_id, 1202c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 1203c5441932SPravin B Shelar }; 12041da177e4SLinus Torvalds 12051da177e4SLinus Torvalds static int __init ipgre_init(void) 12061da177e4SLinus Torvalds { 12071da177e4SLinus Torvalds int err; 12081da177e4SLinus Torvalds 1209058bd4d2SJoe Perches pr_info("GRE over IPv4 tunneling driver\n"); 12101da177e4SLinus Torvalds 1211cfb8fbf2SEric W. Biederman err = register_pernet_device(&ipgre_net_ops); 121259a4c759SPavel Emelyanov if (err < 0) 1213c2892f02SAlexey Dobriyan return err; 1214c2892f02SAlexey Dobriyan 1215c5441932SPravin B Shelar err = register_pernet_device(&ipgre_tap_net_ops); 1216c5441932SPravin B Shelar if (err < 0) 1217c5441932SPravin B Shelar goto pnet_tap_faied; 1218c5441932SPravin B Shelar 12199f57c67cSPravin B Shelar err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); 1220c2892f02SAlexey Dobriyan if (err < 0) { 1221058bd4d2SJoe Perches pr_info("%s: can't add protocol\n", __func__); 1222c2892f02SAlexey Dobriyan goto add_proto_failed; 1223c2892f02SAlexey Dobriyan } 12247daa0004SPavel Emelyanov 1225c19e654dSHerbert Xu err = rtnl_link_register(&ipgre_link_ops); 1226c19e654dSHerbert Xu if (err < 0) 1227c19e654dSHerbert Xu goto rtnl_link_failed; 1228c19e654dSHerbert Xu 1229e1a80002SHerbert Xu err = rtnl_link_register(&ipgre_tap_ops); 1230e1a80002SHerbert Xu if (err < 0) 1231e1a80002SHerbert Xu goto tap_ops_failed; 1232e1a80002SHerbert Xu 1233c5441932SPravin B Shelar return 0; 1234c19e654dSHerbert Xu 1235e1a80002SHerbert Xu tap_ops_failed: 1236e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 1237c19e654dSHerbert Xu rtnl_link_failed: 12389f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1239c2892f02SAlexey Dobriyan add_proto_failed: 1240c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1241c5441932SPravin B Shelar pnet_tap_faied: 1242c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 1243c5441932SPravin B Shelar return err; 12441da177e4SLinus Torvalds } 12451da177e4SLinus Torvalds 1246db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void) 12471da177e4SLinus Torvalds { 1248e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_tap_ops); 1249c19e654dSHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 12509f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1251c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1252c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 12531da177e4SLinus Torvalds } 12541da177e4SLinus Torvalds 12551da177e4SLinus Torvalds module_init(ipgre_init); 12561da177e4SLinus Torvalds module_exit(ipgre_fini); 12571da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 12584d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre"); 12594d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap"); 12608909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0"); 1261c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0"); 1262