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> 271da177e4SLinus Torvalds #include <linux/mroute.h> 282e15ea39SPravin B Shelar #include <linux/if_vlan.h> 291da177e4SLinus Torvalds #include <linux/init.h> 301da177e4SLinus Torvalds #include <linux/in6.h> 311da177e4SLinus Torvalds #include <linux/inetdevice.h> 321da177e4SLinus Torvalds #include <linux/igmp.h> 331da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h> 34e1a80002SHerbert Xu #include <linux/etherdevice.h> 3546f25dffSKris Katterjohn #include <linux/if_ether.h> 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds #include <net/sock.h> 381da177e4SLinus Torvalds #include <net/ip.h> 391da177e4SLinus Torvalds #include <net/icmp.h> 401da177e4SLinus Torvalds #include <net/protocol.h> 41c5441932SPravin B Shelar #include <net/ip_tunnels.h> 421da177e4SLinus Torvalds #include <net/arp.h> 431da177e4SLinus Torvalds #include <net/checksum.h> 441da177e4SLinus Torvalds #include <net/dsfield.h> 451da177e4SLinus Torvalds #include <net/inet_ecn.h> 461da177e4SLinus Torvalds #include <net/xfrm.h> 4759a4c759SPavel Emelyanov #include <net/net_namespace.h> 4859a4c759SPavel Emelyanov #include <net/netns/generic.h> 49c19e654dSHerbert Xu #include <net/rtnetlink.h> 5000959adeSDmitry Kozlov #include <net/gre.h> 512e15ea39SPravin B Shelar #include <net/dst_metadata.h> 521da177e4SLinus Torvalds 53dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 541da177e4SLinus Torvalds #include <net/ipv6.h> 551da177e4SLinus Torvalds #include <net/ip6_fib.h> 561da177e4SLinus Torvalds #include <net/ip6_route.h> 571da177e4SLinus Torvalds #endif 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds /* 601da177e4SLinus Torvalds Problems & solutions 611da177e4SLinus Torvalds -------------------- 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds 1. The most important issue is detecting local dead loops. 641da177e4SLinus Torvalds They would cause complete host lockup in transmit, which 651da177e4SLinus Torvalds would be "resolved" by stack overflow or, if queueing is enabled, 661da177e4SLinus Torvalds with infinite looping in net_bh. 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds We cannot track such dead loops during route installation, 691da177e4SLinus Torvalds it is infeasible task. The most general solutions would be 701da177e4SLinus Torvalds to keep skb->encapsulation counter (sort of local ttl), 716d0722a2SEric Dumazet and silently drop packet when it expires. It is a good 72bff52857Sstephen hemminger solution, but it supposes maintaining new variable in ALL 731da177e4SLinus Torvalds skb, even if no tunneling is used. 741da177e4SLinus Torvalds 756d0722a2SEric Dumazet Current solution: xmit_recursion breaks dead loops. This is a percpu 766d0722a2SEric Dumazet counter, since when we enter the first ndo_xmit(), cpu migration is 776d0722a2SEric Dumazet forbidden. We force an exit if this counter reaches RECURSION_LIMIT 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds 2. Networking dead loops would not kill routers, but would really 801da177e4SLinus Torvalds kill network. IP hop limit plays role of "t->recursion" in this case, 811da177e4SLinus Torvalds if we copy it from packet being encapsulated to upper header. 821da177e4SLinus Torvalds It is very good solution, but it introduces two problems: 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds - Routing protocols, using packets with ttl=1 (OSPF, RIP2), 851da177e4SLinus Torvalds do not work over tunnels. 861da177e4SLinus Torvalds - traceroute does not work. I planned to relay ICMP from tunnel, 871da177e4SLinus Torvalds so that this problem would be solved and traceroute output 881da177e4SLinus Torvalds would even more informative. This idea appeared to be wrong: 891da177e4SLinus Torvalds only Linux complies to rfc1812 now (yes, guys, Linux is the only 901da177e4SLinus Torvalds true router now :-)), all routers (at least, in neighbourhood of mine) 911da177e4SLinus Torvalds return only 8 bytes of payload. It is the end. 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds Hence, if we want that OSPF worked or traceroute said something reasonable, 941da177e4SLinus Torvalds we should search for another solution. 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds One of them is to parse packet trying to detect inner encapsulation 971da177e4SLinus Torvalds made by our node. It is difficult or even impossible, especially, 98bff52857Sstephen hemminger taking into account fragmentation. TO be short, ttl is not solution at all. 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds Current solution: The solution was UNEXPECTEDLY SIMPLE. 1011da177e4SLinus Torvalds We force DF flag on tunnels with preconfigured hop limit, 1021da177e4SLinus Torvalds that is ALL. :-) Well, it does not remove the problem completely, 1031da177e4SLinus Torvalds but exponential growth of network traffic is changed to linear 1041da177e4SLinus Torvalds (branches, that exceed pmtu are pruned) and tunnel mtu 105bff52857Sstephen hemminger rapidly degrades to value <68, where looping stops. 1061da177e4SLinus Torvalds Yes, it is not good if there exists a router in the loop, 1071da177e4SLinus Torvalds which does not force DF, even when encapsulating packets have DF set. 1081da177e4SLinus Torvalds But it is not our problem! Nobody could accuse us, we made 1091da177e4SLinus Torvalds all that we could make. Even if it is your gated who injected 1101da177e4SLinus Torvalds fatal route to network, even if it were you who configured 1111da177e4SLinus Torvalds fatal static route: you are innocent. :-) 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds Alexey Kuznetsov. 1141da177e4SLinus Torvalds */ 1151da177e4SLinus Torvalds 116eccc1bb8Sstephen hemminger static bool log_ecn_error = true; 117eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644); 118eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); 119eccc1bb8Sstephen hemminger 120c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly; 1211da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev); 122eb8ce741SPavel Emelyanov 123f99189b1SEric Dumazet static int ipgre_net_id __read_mostly; 124c5441932SPravin B Shelar static int gre_tap_net_id __read_mostly; 125eb8ce741SPavel Emelyanov 126*9f57c67cSPravin B Shelar static int ip_gre_calc_hlen(__be16 o_flags) 127*9f57c67cSPravin B Shelar { 128*9f57c67cSPravin B Shelar int addend = 4; 129*9f57c67cSPravin B Shelar 130*9f57c67cSPravin B Shelar if (o_flags & TUNNEL_CSUM) 131*9f57c67cSPravin B Shelar addend += 4; 132*9f57c67cSPravin B Shelar if (o_flags & TUNNEL_KEY) 133*9f57c67cSPravin B Shelar addend += 4; 134*9f57c67cSPravin B Shelar if (o_flags & TUNNEL_SEQ) 135*9f57c67cSPravin B Shelar addend += 4; 136*9f57c67cSPravin B Shelar return addend; 137*9f57c67cSPravin B Shelar } 138*9f57c67cSPravin B Shelar 139*9f57c67cSPravin B Shelar static __be16 gre_flags_to_tnl_flags(__be16 flags) 140*9f57c67cSPravin B Shelar { 141*9f57c67cSPravin B Shelar __be16 tflags = 0; 142*9f57c67cSPravin B Shelar 143*9f57c67cSPravin B Shelar if (flags & GRE_CSUM) 144*9f57c67cSPravin B Shelar tflags |= TUNNEL_CSUM; 145*9f57c67cSPravin B Shelar if (flags & GRE_ROUTING) 146*9f57c67cSPravin B Shelar tflags |= TUNNEL_ROUTING; 147*9f57c67cSPravin B Shelar if (flags & GRE_KEY) 148*9f57c67cSPravin B Shelar tflags |= TUNNEL_KEY; 149*9f57c67cSPravin B Shelar if (flags & GRE_SEQ) 150*9f57c67cSPravin B Shelar tflags |= TUNNEL_SEQ; 151*9f57c67cSPravin B Shelar if (flags & GRE_STRICT) 152*9f57c67cSPravin B Shelar tflags |= TUNNEL_STRICT; 153*9f57c67cSPravin B Shelar if (flags & GRE_REC) 154*9f57c67cSPravin B Shelar tflags |= TUNNEL_REC; 155*9f57c67cSPravin B Shelar if (flags & GRE_VERSION) 156*9f57c67cSPravin B Shelar tflags |= TUNNEL_VERSION; 157*9f57c67cSPravin B Shelar 158*9f57c67cSPravin B Shelar return tflags; 159*9f57c67cSPravin B Shelar } 160*9f57c67cSPravin B Shelar 161*9f57c67cSPravin B Shelar static __be16 tnl_flags_to_gre_flags(__be16 tflags) 162*9f57c67cSPravin B Shelar { 163*9f57c67cSPravin B Shelar __be16 flags = 0; 164*9f57c67cSPravin B Shelar 165*9f57c67cSPravin B Shelar if (tflags & TUNNEL_CSUM) 166*9f57c67cSPravin B Shelar flags |= GRE_CSUM; 167*9f57c67cSPravin B Shelar if (tflags & TUNNEL_ROUTING) 168*9f57c67cSPravin B Shelar flags |= GRE_ROUTING; 169*9f57c67cSPravin B Shelar if (tflags & TUNNEL_KEY) 170*9f57c67cSPravin B Shelar flags |= GRE_KEY; 171*9f57c67cSPravin B Shelar if (tflags & TUNNEL_SEQ) 172*9f57c67cSPravin B Shelar flags |= GRE_SEQ; 173*9f57c67cSPravin B Shelar if (tflags & TUNNEL_STRICT) 174*9f57c67cSPravin B Shelar flags |= GRE_STRICT; 175*9f57c67cSPravin B Shelar if (tflags & TUNNEL_REC) 176*9f57c67cSPravin B Shelar flags |= GRE_REC; 177*9f57c67cSPravin B Shelar if (tflags & TUNNEL_VERSION) 178*9f57c67cSPravin B Shelar flags |= GRE_VERSION; 179*9f57c67cSPravin B Shelar 180*9f57c67cSPravin B Shelar return flags; 181*9f57c67cSPravin B Shelar } 182*9f57c67cSPravin B Shelar 183*9f57c67cSPravin B Shelar static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, 184*9f57c67cSPravin B Shelar bool *csum_err) 185*9f57c67cSPravin B Shelar { 186*9f57c67cSPravin B Shelar const struct gre_base_hdr *greh; 187*9f57c67cSPravin B Shelar __be32 *options; 188*9f57c67cSPravin B Shelar int hdr_len; 189*9f57c67cSPravin B Shelar 190*9f57c67cSPravin B Shelar if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr)))) 191*9f57c67cSPravin B Shelar return -EINVAL; 192*9f57c67cSPravin B Shelar 193*9f57c67cSPravin B Shelar greh = (struct gre_base_hdr *)skb_transport_header(skb); 194*9f57c67cSPravin B Shelar if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING))) 195*9f57c67cSPravin B Shelar return -EINVAL; 196*9f57c67cSPravin B Shelar 197*9f57c67cSPravin B Shelar tpi->flags = gre_flags_to_tnl_flags(greh->flags); 198*9f57c67cSPravin B Shelar hdr_len = ip_gre_calc_hlen(tpi->flags); 199*9f57c67cSPravin B Shelar 200*9f57c67cSPravin B Shelar if (!pskb_may_pull(skb, hdr_len)) 201*9f57c67cSPravin B Shelar return -EINVAL; 202*9f57c67cSPravin B Shelar 203*9f57c67cSPravin B Shelar greh = (struct gre_base_hdr *)skb_transport_header(skb); 204*9f57c67cSPravin B Shelar tpi->proto = greh->protocol; 205*9f57c67cSPravin B Shelar 206*9f57c67cSPravin B Shelar options = (__be32 *)(greh + 1); 207*9f57c67cSPravin B Shelar if (greh->flags & GRE_CSUM) { 208*9f57c67cSPravin B Shelar if (skb_checksum_simple_validate(skb)) { 209*9f57c67cSPravin B Shelar *csum_err = true; 210*9f57c67cSPravin B Shelar return -EINVAL; 211*9f57c67cSPravin B Shelar } 212*9f57c67cSPravin B Shelar 213*9f57c67cSPravin B Shelar skb_checksum_try_convert(skb, IPPROTO_GRE, 0, 214*9f57c67cSPravin B Shelar null_compute_pseudo); 215*9f57c67cSPravin B Shelar options++; 216*9f57c67cSPravin B Shelar } 217*9f57c67cSPravin B Shelar 218*9f57c67cSPravin B Shelar if (greh->flags & GRE_KEY) { 219*9f57c67cSPravin B Shelar tpi->key = *options; 220*9f57c67cSPravin B Shelar options++; 221*9f57c67cSPravin B Shelar } else { 222*9f57c67cSPravin B Shelar tpi->key = 0; 223*9f57c67cSPravin B Shelar } 224*9f57c67cSPravin B Shelar if (unlikely(greh->flags & GRE_SEQ)) { 225*9f57c67cSPravin B Shelar tpi->seq = *options; 226*9f57c67cSPravin B Shelar options++; 227*9f57c67cSPravin B Shelar } else { 228*9f57c67cSPravin B Shelar tpi->seq = 0; 229*9f57c67cSPravin B Shelar } 230*9f57c67cSPravin B Shelar /* WCCP version 1 and 2 protocol decoding. 231*9f57c67cSPravin B Shelar * - Change protocol to IP 232*9f57c67cSPravin B Shelar * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header 233*9f57c67cSPravin B Shelar */ 234*9f57c67cSPravin B Shelar if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { 235*9f57c67cSPravin B Shelar tpi->proto = htons(ETH_P_IP); 236*9f57c67cSPravin B Shelar if ((*(u8 *)options & 0xF0) != 0x40) { 237*9f57c67cSPravin B Shelar hdr_len += 4; 238*9f57c67cSPravin B Shelar if (!pskb_may_pull(skb, hdr_len)) 239*9f57c67cSPravin B Shelar return -EINVAL; 240*9f57c67cSPravin B Shelar } 241*9f57c67cSPravin B Shelar } 242*9f57c67cSPravin B Shelar return iptunnel_pull_header(skb, hdr_len, tpi->proto); 243*9f57c67cSPravin B Shelar } 244*9f57c67cSPravin B Shelar 245*9f57c67cSPravin B Shelar static void ipgre_err(struct sk_buff *skb, u32 info, 246bda7bb46SPravin B Shelar const struct tnl_ptk_info *tpi) 2471da177e4SLinus Torvalds { 2481da177e4SLinus Torvalds 249071f92d0SRami Rosen /* All the routers (except for Linux) return only 2501da177e4SLinus Torvalds 8 bytes of packet payload. It means, that precise relaying of 2511da177e4SLinus Torvalds ICMP in the real Internet is absolutely infeasible. 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds Moreover, Cisco "wise men" put GRE key to the third word 254c5441932SPravin B Shelar in GRE header. It makes impossible maintaining even soft 255c5441932SPravin B Shelar state for keyed GRE tunnels with enabled checksum. Tell 256c5441932SPravin B Shelar them "thank you". 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds Well, I wonder, rfc1812 was written by Cisco employee, 259bff52857Sstephen hemminger what the hell these idiots break standards established 260bff52857Sstephen hemminger by themselves??? 2611da177e4SLinus Torvalds */ 262c5441932SPravin B Shelar struct net *net = dev_net(skb->dev); 263c5441932SPravin B Shelar struct ip_tunnel_net *itn; 26496f5a846SEric Dumazet const struct iphdr *iph; 26588c7664fSArnaldo Carvalho de Melo const int type = icmp_hdr(skb)->type; 26688c7664fSArnaldo Carvalho de Melo const int code = icmp_hdr(skb)->code; 2671da177e4SLinus Torvalds struct ip_tunnel *t; 268d2083287Sstephen hemminger 2691da177e4SLinus Torvalds switch (type) { 2701da177e4SLinus Torvalds default: 2711da177e4SLinus Torvalds case ICMP_PARAMETERPROB: 272*9f57c67cSPravin B Shelar return; 2731da177e4SLinus Torvalds 2741da177e4SLinus Torvalds case ICMP_DEST_UNREACH: 2751da177e4SLinus Torvalds switch (code) { 2761da177e4SLinus Torvalds case ICMP_SR_FAILED: 2771da177e4SLinus Torvalds case ICMP_PORT_UNREACH: 2781da177e4SLinus Torvalds /* Impossible event. */ 279*9f57c67cSPravin B Shelar return; 2801da177e4SLinus Torvalds default: 2811da177e4SLinus Torvalds /* All others are translated to HOST_UNREACH. 2821da177e4SLinus Torvalds rfc2003 contains "deep thoughts" about NET_UNREACH, 2831da177e4SLinus Torvalds I believe they are just ether pollution. --ANK 2841da177e4SLinus Torvalds */ 2851da177e4SLinus Torvalds break; 2861da177e4SLinus Torvalds } 2871da177e4SLinus Torvalds break; 288*9f57c67cSPravin B Shelar 2891da177e4SLinus Torvalds case ICMP_TIME_EXCEEDED: 2901da177e4SLinus Torvalds if (code != ICMP_EXC_TTL) 291*9f57c67cSPravin B Shelar return; 2921da177e4SLinus Torvalds break; 29355be7a9cSDavid S. Miller 29455be7a9cSDavid S. Miller case ICMP_REDIRECT: 29555be7a9cSDavid S. Miller break; 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 298bda7bb46SPravin B Shelar if (tpi->proto == htons(ETH_P_TEB)) 299c5441932SPravin B Shelar itn = net_generic(net, gre_tap_net_id); 300c5441932SPravin B Shelar else 301c5441932SPravin B Shelar itn = net_generic(net, ipgre_net_id); 302c5441932SPravin B Shelar 303c0c0c50fSDuan Jiong iph = (const struct iphdr *)(icmp_hdr(skb) + 1); 304bda7bb46SPravin B Shelar t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 305bda7bb46SPravin B Shelar iph->daddr, iph->saddr, tpi->key); 306d2083287Sstephen hemminger 30751456b29SIan Morris if (!t) 308*9f57c67cSPravin B Shelar return; 30936393395SDavid S. Miller 31036393395SDavid S. Miller if (t->parms.iph.daddr == 0 || 311f97c1e0cSJoe Perches ipv4_is_multicast(t->parms.iph.daddr)) 312*9f57c67cSPravin B Shelar return; 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 315*9f57c67cSPravin B Shelar return; 3161da177e4SLinus Torvalds 317da6185d8SWei Yongjun if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) 3181da177e4SLinus Torvalds t->err_count++; 3191da177e4SLinus Torvalds else 3201da177e4SLinus Torvalds t->err_count = 1; 3211da177e4SLinus Torvalds t->err_time = jiffies; 322*9f57c67cSPravin B Shelar } 323*9f57c67cSPravin B Shelar 324*9f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info) 325*9f57c67cSPravin B Shelar { 326*9f57c67cSPravin B Shelar /* All the routers (except for Linux) return only 327*9f57c67cSPravin B Shelar * 8 bytes of packet payload. It means, that precise relaying of 328*9f57c67cSPravin B Shelar * ICMP in the real Internet is absolutely infeasible. 329*9f57c67cSPravin B Shelar * 330*9f57c67cSPravin B Shelar * Moreover, Cisco "wise men" put GRE key to the third word 331*9f57c67cSPravin B Shelar * in GRE header. It makes impossible maintaining even soft 332*9f57c67cSPravin B Shelar * state for keyed 333*9f57c67cSPravin B Shelar * GRE tunnels with enabled checksum. Tell them "thank you". 334*9f57c67cSPravin B Shelar * 335*9f57c67cSPravin B Shelar * Well, I wonder, rfc1812 was written by Cisco employee, 336*9f57c67cSPravin B Shelar * what the hell these idiots break standards established 337*9f57c67cSPravin B Shelar * by themselves??? 338*9f57c67cSPravin B Shelar */ 339*9f57c67cSPravin B Shelar 340*9f57c67cSPravin B Shelar const int type = icmp_hdr(skb)->type; 341*9f57c67cSPravin B Shelar const int code = icmp_hdr(skb)->code; 342*9f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 343*9f57c67cSPravin B Shelar bool csum_err = false; 344*9f57c67cSPravin B Shelar 345*9f57c67cSPravin B Shelar if (parse_gre_header(skb, &tpi, &csum_err)) { 346*9f57c67cSPravin B Shelar if (!csum_err) /* ignore csum errors. */ 347*9f57c67cSPravin B Shelar return; 348*9f57c67cSPravin B Shelar } 349*9f57c67cSPravin B Shelar 350*9f57c67cSPravin B Shelar if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 351*9f57c67cSPravin B Shelar ipv4_update_pmtu(skb, dev_net(skb->dev), info, 352*9f57c67cSPravin B Shelar skb->dev->ifindex, 0, IPPROTO_GRE, 0); 353*9f57c67cSPravin B Shelar return; 354*9f57c67cSPravin B Shelar } 355*9f57c67cSPravin B Shelar if (type == ICMP_REDIRECT) { 356*9f57c67cSPravin B Shelar ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0, 357*9f57c67cSPravin B Shelar IPPROTO_GRE, 0); 358*9f57c67cSPravin B Shelar return; 359*9f57c67cSPravin B Shelar } 360*9f57c67cSPravin B Shelar 361*9f57c67cSPravin B Shelar ipgre_err(skb, info, &tpi); 3621da177e4SLinus Torvalds } 3631da177e4SLinus Torvalds 3642e15ea39SPravin B Shelar static __be64 key_to_tunnel_id(__be32 key) 3652e15ea39SPravin B Shelar { 3662e15ea39SPravin B Shelar #ifdef __BIG_ENDIAN 3672e15ea39SPravin B Shelar return (__force __be64)((__force u32)key); 3682e15ea39SPravin B Shelar #else 3692e15ea39SPravin B Shelar return (__force __be64)((__force u64)key << 32); 3702e15ea39SPravin B Shelar #endif 3712e15ea39SPravin B Shelar } 3722e15ea39SPravin B Shelar 3732e15ea39SPravin B Shelar /* Returns the least-significant 32 bits of a __be64. */ 3742e15ea39SPravin B Shelar static __be32 tunnel_id_to_key(__be64 x) 3752e15ea39SPravin B Shelar { 3762e15ea39SPravin B Shelar #ifdef __BIG_ENDIAN 3772e15ea39SPravin B Shelar return (__force __be32)x; 3782e15ea39SPravin B Shelar #else 3792e15ea39SPravin B Shelar return (__force __be32)((__force u64)x >> 32); 3802e15ea39SPravin B Shelar #endif 3812e15ea39SPravin B Shelar } 3822e15ea39SPravin B Shelar 383bda7bb46SPravin B Shelar static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) 3841da177e4SLinus Torvalds { 385c5441932SPravin B Shelar struct net *net = dev_net(skb->dev); 3862e15ea39SPravin B Shelar struct metadata_dst *tun_dst = NULL; 387c5441932SPravin B Shelar struct ip_tunnel_net *itn; 388b71d1d42SEric Dumazet const struct iphdr *iph; 3891da177e4SLinus Torvalds struct ip_tunnel *tunnel; 3901da177e4SLinus Torvalds 391bda7bb46SPravin B Shelar if (tpi->proto == htons(ETH_P_TEB)) 392c5441932SPravin B Shelar itn = net_generic(net, gre_tap_net_id); 393c5441932SPravin B Shelar else 394c5441932SPravin B Shelar itn = net_generic(net, ipgre_net_id); 395c5441932SPravin B Shelar 396eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb); 397bda7bb46SPravin B Shelar tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 398bda7bb46SPravin B Shelar iph->saddr, iph->daddr, tpi->key); 3991da177e4SLinus Torvalds 400d2083287Sstephen hemminger if (tunnel) { 4010e3da5bbSTimo Teräs skb_pop_mac_header(skb); 4022e15ea39SPravin B Shelar if (tunnel->collect_md) { 4032e15ea39SPravin B Shelar struct ip_tunnel_info *info; 4042e15ea39SPravin B Shelar 4052e15ea39SPravin B Shelar tun_dst = metadata_dst_alloc(0, GFP_ATOMIC); 4062e15ea39SPravin B Shelar if (!tun_dst) 4072e15ea39SPravin B Shelar return PACKET_REJECT; 4082e15ea39SPravin B Shelar 4092e15ea39SPravin B Shelar info = &tun_dst->u.tun_info; 4102e15ea39SPravin B Shelar info->key.ipv4_src = iph->saddr; 4112e15ea39SPravin B Shelar info->key.ipv4_dst = iph->daddr; 4122e15ea39SPravin B Shelar info->key.ipv4_tos = iph->tos; 4132e15ea39SPravin B Shelar info->key.ipv4_ttl = iph->ttl; 4142e15ea39SPravin B Shelar 4152e15ea39SPravin B Shelar info->mode = IP_TUNNEL_INFO_RX; 4162e15ea39SPravin B Shelar info->key.tun_flags = tpi->flags & 4172e15ea39SPravin B Shelar (TUNNEL_CSUM | TUNNEL_KEY); 4182e15ea39SPravin B Shelar info->key.tun_id = key_to_tunnel_id(tpi->key); 4192e15ea39SPravin B Shelar 4202e15ea39SPravin B Shelar info->key.tp_src = 0; 4212e15ea39SPravin B Shelar info->key.tp_dst = 0; 4222e15ea39SPravin B Shelar } 4232e15ea39SPravin B Shelar 4242e15ea39SPravin B Shelar ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 425bda7bb46SPravin B Shelar return PACKET_RCVD; 4261da177e4SLinus Torvalds } 427bda7bb46SPravin B Shelar return PACKET_REJECT; 4281da177e4SLinus Torvalds } 4291da177e4SLinus Torvalds 430*9f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb) 431*9f57c67cSPravin B Shelar { 432*9f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 433*9f57c67cSPravin B Shelar bool csum_err = false; 434*9f57c67cSPravin B Shelar 435*9f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 436*9f57c67cSPravin B Shelar if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { 437*9f57c67cSPravin B Shelar /* Looped back packet, drop it! */ 438*9f57c67cSPravin B Shelar if (rt_is_output_route(skb_rtable(skb))) 439*9f57c67cSPravin B Shelar goto drop; 440*9f57c67cSPravin B Shelar } 441*9f57c67cSPravin B Shelar #endif 442*9f57c67cSPravin B Shelar 443*9f57c67cSPravin B Shelar if (parse_gre_header(skb, &tpi, &csum_err) < 0) 444*9f57c67cSPravin B Shelar goto drop; 445*9f57c67cSPravin B Shelar 446*9f57c67cSPravin B Shelar if (ipgre_rcv(skb, &tpi) == PACKET_RCVD) 447*9f57c67cSPravin B Shelar return 0; 448*9f57c67cSPravin B Shelar 449*9f57c67cSPravin B Shelar icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 450*9f57c67cSPravin B Shelar drop: 451*9f57c67cSPravin B Shelar kfree_skb(skb); 452*9f57c67cSPravin B Shelar return 0; 453*9f57c67cSPravin B Shelar } 454*9f57c67cSPravin B Shelar 4552e15ea39SPravin B Shelar static void build_header(struct sk_buff *skb, int hdr_len, __be16 flags, 4562e15ea39SPravin B Shelar __be16 proto, __be32 key, __be32 seq) 4572e15ea39SPravin B Shelar { 4582e15ea39SPravin B Shelar struct gre_base_hdr *greh; 4592e15ea39SPravin B Shelar 4602e15ea39SPravin B Shelar skb_push(skb, hdr_len); 4612e15ea39SPravin B Shelar 4622e15ea39SPravin B Shelar skb_reset_transport_header(skb); 4632e15ea39SPravin B Shelar greh = (struct gre_base_hdr *)skb->data; 4642e15ea39SPravin B Shelar greh->flags = tnl_flags_to_gre_flags(flags); 4652e15ea39SPravin B Shelar greh->protocol = proto; 4662e15ea39SPravin B Shelar 4672e15ea39SPravin B Shelar if (flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) { 4682e15ea39SPravin B Shelar __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4); 4692e15ea39SPravin B Shelar 4702e15ea39SPravin B Shelar if (flags & TUNNEL_SEQ) { 4712e15ea39SPravin B Shelar *ptr = seq; 4722e15ea39SPravin B Shelar ptr--; 4732e15ea39SPravin B Shelar } 4742e15ea39SPravin B Shelar if (flags & TUNNEL_KEY) { 4752e15ea39SPravin B Shelar *ptr = key; 4762e15ea39SPravin B Shelar ptr--; 4772e15ea39SPravin B Shelar } 4782e15ea39SPravin B Shelar if (flags & TUNNEL_CSUM && 4792e15ea39SPravin B Shelar !(skb_shinfo(skb)->gso_type & 4802e15ea39SPravin B Shelar (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) { 4812e15ea39SPravin B Shelar *ptr = 0; 4822e15ea39SPravin B Shelar *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0, 4832e15ea39SPravin B Shelar skb->len, 0)); 4842e15ea39SPravin B Shelar } 4852e15ea39SPravin B Shelar } 4862e15ea39SPravin B Shelar } 4872e15ea39SPravin B Shelar 488c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, 489c5441932SPravin B Shelar const struct iphdr *tnl_params, 490c5441932SPravin B Shelar __be16 proto) 491c5441932SPravin B Shelar { 492c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 493c5441932SPravin B Shelar 494c5441932SPravin B Shelar if (tunnel->parms.o_flags & TUNNEL_SEQ) 495c5441932SPravin B Shelar tunnel->o_seqno++; 496cef401deSEric Dumazet 497c5441932SPravin B Shelar /* Push GRE header. */ 4982e15ea39SPravin B Shelar build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags, 4992e15ea39SPravin B Shelar proto, tunnel->parms.o_key, htonl(tunnel->o_seqno)); 5001da177e4SLinus Torvalds 5012e15ea39SPravin B Shelar skb_set_inner_protocol(skb, proto); 502bf3d6a8fSNicolas Dichtel ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); 5031da177e4SLinus Torvalds } 5041da177e4SLinus Torvalds 505b2acd1dcSPravin B Shelar static struct sk_buff *gre_handle_offloads(struct sk_buff *skb, 506b2acd1dcSPravin B Shelar bool csum) 507b2acd1dcSPravin B Shelar { 508b2acd1dcSPravin B Shelar return iptunnel_handle_offloads(skb, csum, 509b2acd1dcSPravin B Shelar csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); 510b2acd1dcSPravin B Shelar } 511b2acd1dcSPravin B Shelar 5122e15ea39SPravin B Shelar static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) 5132e15ea39SPravin B Shelar { 5142e15ea39SPravin B Shelar struct ip_tunnel_info *tun_info; 5152e15ea39SPravin B Shelar struct net *net = dev_net(dev); 5162e15ea39SPravin B Shelar const struct ip_tunnel_key *key; 5172e15ea39SPravin B Shelar struct flowi4 fl; 5182e15ea39SPravin B Shelar struct rtable *rt; 5192e15ea39SPravin B Shelar int min_headroom; 5202e15ea39SPravin B Shelar int tunnel_hlen; 5212e15ea39SPravin B Shelar __be16 df, flags; 5222e15ea39SPravin B Shelar int err; 5232e15ea39SPravin B Shelar 5242e15ea39SPravin B Shelar tun_info = skb_tunnel_info(skb, AF_INET); 5252e15ea39SPravin B Shelar if (unlikely(!tun_info || tun_info->mode != IP_TUNNEL_INFO_TX)) 5262e15ea39SPravin B Shelar goto err_free_skb; 5272e15ea39SPravin B Shelar 5282e15ea39SPravin B Shelar key = &tun_info->key; 5292e15ea39SPravin B Shelar memset(&fl, 0, sizeof(fl)); 5302e15ea39SPravin B Shelar fl.daddr = key->ipv4_dst; 5312e15ea39SPravin B Shelar fl.saddr = key->ipv4_src; 5322e15ea39SPravin B Shelar fl.flowi4_tos = RT_TOS(key->ipv4_tos); 5332e15ea39SPravin B Shelar fl.flowi4_mark = skb->mark; 5342e15ea39SPravin B Shelar fl.flowi4_proto = IPPROTO_GRE; 5352e15ea39SPravin B Shelar 5362e15ea39SPravin B Shelar rt = ip_route_output_key(net, &fl); 5372e15ea39SPravin B Shelar if (IS_ERR(rt)) 5382e15ea39SPravin B Shelar goto err_free_skb; 5392e15ea39SPravin B Shelar 5402e15ea39SPravin B Shelar tunnel_hlen = ip_gre_calc_hlen(key->tun_flags); 5412e15ea39SPravin B Shelar 5422e15ea39SPravin B Shelar min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len 5432e15ea39SPravin B Shelar + tunnel_hlen + sizeof(struct iphdr); 5442e15ea39SPravin B Shelar if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { 5452e15ea39SPravin B Shelar int head_delta = SKB_DATA_ALIGN(min_headroom - 5462e15ea39SPravin B Shelar skb_headroom(skb) + 5472e15ea39SPravin B Shelar 16); 5482e15ea39SPravin B Shelar err = pskb_expand_head(skb, max_t(int, head_delta, 0), 5492e15ea39SPravin B Shelar 0, GFP_ATOMIC); 5502e15ea39SPravin B Shelar if (unlikely(err)) 5512e15ea39SPravin B Shelar goto err_free_rt; 5522e15ea39SPravin B Shelar } 5532e15ea39SPravin B Shelar 5542e15ea39SPravin B Shelar /* Push Tunnel header. */ 5552e15ea39SPravin B Shelar skb = gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)); 5562e15ea39SPravin B Shelar if (IS_ERR(skb)) { 5572e15ea39SPravin B Shelar skb = NULL; 5582e15ea39SPravin B Shelar goto err_free_rt; 5592e15ea39SPravin B Shelar } 5602e15ea39SPravin B Shelar 5612e15ea39SPravin B Shelar flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); 5622e15ea39SPravin B Shelar build_header(skb, tunnel_hlen, flags, htons(ETH_P_TEB), 5632e15ea39SPravin B Shelar tunnel_id_to_key(tun_info->key.tun_id), 0); 5642e15ea39SPravin B Shelar 5652e15ea39SPravin B Shelar df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; 5662e15ea39SPravin B Shelar err = iptunnel_xmit(skb->sk, rt, skb, fl.saddr, 5672e15ea39SPravin B Shelar key->ipv4_dst, IPPROTO_GRE, 5682e15ea39SPravin B Shelar key->ipv4_tos, key->ipv4_ttl, df, false); 5692e15ea39SPravin B Shelar iptunnel_xmit_stats(err, &dev->stats, dev->tstats); 5702e15ea39SPravin B Shelar return; 5712e15ea39SPravin B Shelar 5722e15ea39SPravin B Shelar err_free_rt: 5732e15ea39SPravin B Shelar ip_rt_put(rt); 5742e15ea39SPravin B Shelar err_free_skb: 5752e15ea39SPravin B Shelar kfree_skb(skb); 5762e15ea39SPravin B Shelar dev->stats.tx_dropped++; 5772e15ea39SPravin B Shelar } 5782e15ea39SPravin B Shelar 579c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb, 580c5441932SPravin B Shelar struct net_device *dev) 581ee34c1ebSMichal Schmidt { 582c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 583c5441932SPravin B Shelar const struct iphdr *tnl_params; 584ee34c1ebSMichal Schmidt 5852e15ea39SPravin B Shelar if (tunnel->collect_md) { 5862e15ea39SPravin B Shelar gre_fb_xmit(skb, dev); 5872e15ea39SPravin B Shelar return NETDEV_TX_OK; 5882e15ea39SPravin B Shelar } 5892e15ea39SPravin B Shelar 590c5441932SPravin B Shelar if (dev->header_ops) { 591c5441932SPravin B Shelar /* Need space for new headers */ 592c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom - 5932bac7cb3SChen Gang (tunnel->hlen + sizeof(struct iphdr)))) 594c5441932SPravin B Shelar goto free_skb; 595ee34c1ebSMichal Schmidt 596c5441932SPravin B Shelar tnl_params = (const struct iphdr *)skb->data; 597cbb1e85fSDavid S. Miller 598c5441932SPravin B Shelar /* Pull skb since ip_tunnel_xmit() needs skb->data pointing 599c5441932SPravin B Shelar * to gre header. 600c5441932SPravin B Shelar */ 601c5441932SPravin B Shelar skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); 6028a0033a9STimo Teräs skb_reset_mac_header(skb); 603c5441932SPravin B Shelar } else { 604c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 605c5441932SPravin B Shelar goto free_skb; 606c5441932SPravin B Shelar 607c5441932SPravin B Shelar tnl_params = &tunnel->parms.iph; 608ee34c1ebSMichal Schmidt } 609e1a80002SHerbert Xu 6108a0033a9STimo Teräs skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); 6118a0033a9STimo Teräs if (IS_ERR(skb)) 6128a0033a9STimo Teräs goto out; 6138a0033a9STimo Teräs 614c5441932SPravin B Shelar __gre_xmit(skb, dev, tnl_params, skb->protocol); 615c5441932SPravin B Shelar return NETDEV_TX_OK; 616c5441932SPravin B Shelar 617c5441932SPravin B Shelar free_skb: 6183acfa1e7SEric Dumazet kfree_skb(skb); 619c5441932SPravin B Shelar out: 620c5441932SPravin B Shelar dev->stats.tx_dropped++; 621c5441932SPravin B Shelar return NETDEV_TX_OK; 622ee34c1ebSMichal Schmidt } 623ee34c1ebSMichal Schmidt 624c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, 625c5441932SPravin B Shelar struct net_device *dev) 626c5441932SPravin B Shelar { 627c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 628ee34c1ebSMichal Schmidt 6292e15ea39SPravin B Shelar if (tunnel->collect_md) { 6302e15ea39SPravin B Shelar gre_fb_xmit(skb, dev); 6312e15ea39SPravin B Shelar return NETDEV_TX_OK; 6322e15ea39SPravin B Shelar } 6332e15ea39SPravin B Shelar 63445f2e997SPravin B Shelar skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); 635c5441932SPravin B Shelar if (IS_ERR(skb)) 636c5441932SPravin B Shelar goto out; 637ee34c1ebSMichal Schmidt 638c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 639c5441932SPravin B Shelar goto free_skb; 64042aa9162SHerbert Xu 641c5441932SPravin B Shelar __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB)); 642c5441932SPravin B Shelar return NETDEV_TX_OK; 643c5441932SPravin B Shelar 644c5441932SPravin B Shelar free_skb: 6453acfa1e7SEric Dumazet kfree_skb(skb); 646c5441932SPravin B Shelar out: 647c5441932SPravin B Shelar dev->stats.tx_dropped++; 648c5441932SPravin B Shelar return NETDEV_TX_OK; 64968c33163SPravin B Shelar } 650ee34c1ebSMichal Schmidt 651c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev, 652c5441932SPravin B Shelar struct ifreq *ifr, int cmd) 6531da177e4SLinus Torvalds { 6544565e991STom Herbert int err; 6551da177e4SLinus Torvalds struct ip_tunnel_parm p; 6561da177e4SLinus Torvalds 6571da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 658c5441932SPravin B Shelar return -EFAULT; 6596c734fb8SCong Wang if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { 6601da177e4SLinus Torvalds if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || 6611da177e4SLinus Torvalds p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) || 6626c734fb8SCong Wang ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) 6631da177e4SLinus Torvalds return -EINVAL; 664c5441932SPravin B Shelar } 665c5441932SPravin B Shelar p.i_flags = gre_flags_to_tnl_flags(p.i_flags); 666c5441932SPravin B Shelar p.o_flags = gre_flags_to_tnl_flags(p.o_flags); 667c5441932SPravin B Shelar 668c5441932SPravin B Shelar err = ip_tunnel_ioctl(dev, &p, cmd); 669c5441932SPravin B Shelar if (err) 670c5441932SPravin B Shelar return err; 671c5441932SPravin B Shelar 672c5441932SPravin B Shelar p.i_flags = tnl_flags_to_gre_flags(p.i_flags); 673c5441932SPravin B Shelar p.o_flags = tnl_flags_to_gre_flags(p.o_flags); 674c5441932SPravin B Shelar 675c5441932SPravin B Shelar if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) 676c5441932SPravin B Shelar return -EFAULT; 6771da177e4SLinus Torvalds return 0; 6781da177e4SLinus Torvalds } 6791da177e4SLinus Torvalds 6801da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-) 6811da177e4SLinus Torvalds It allows to construct virtual multiprotocol broadcast "LAN" 6821da177e4SLinus Torvalds over the Internet, provided multicast routing is tuned. 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds 6851da177e4SLinus Torvalds I have no idea was this bicycle invented before me, 6861da177e4SLinus Torvalds so that I had to set ARPHRD_IPGRE to a random value. 6871da177e4SLinus Torvalds I have an impression, that Cisco could make something similar, 6881da177e4SLinus Torvalds but this feature is apparently missing in IOS<=11.2(8). 6891da177e4SLinus Torvalds 6901da177e4SLinus Torvalds I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks 6911da177e4SLinus Torvalds with broadcast 224.66.66.66. If you have access to mbone, play with me :-) 6921da177e4SLinus Torvalds 6931da177e4SLinus Torvalds ping -t 255 224.66.66.66 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds If nobody answers, mbone does not work. 6961da177e4SLinus Torvalds 6971da177e4SLinus Torvalds ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 6981da177e4SLinus Torvalds ip addr add 10.66.66.<somewhat>/24 dev Universe 6991da177e4SLinus Torvalds ifconfig Universe up 7001da177e4SLinus Torvalds ifconfig Universe add fe80::<Your_real_addr>/10 7011da177e4SLinus Torvalds ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 7021da177e4SLinus Torvalds ftp 10.66.66.66 7031da177e4SLinus Torvalds ... 7041da177e4SLinus Torvalds ftp fec0:6666:6666::193.233.7.65 7051da177e4SLinus Torvalds ... 7061da177e4SLinus Torvalds */ 7073b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev, 7083b04dddeSStephen Hemminger unsigned short type, 7091507850bSEric Dumazet const void *daddr, const void *saddr, unsigned int len) 7101da177e4SLinus Torvalds { 7112941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 712c5441932SPravin B Shelar struct iphdr *iph; 713c5441932SPravin B Shelar struct gre_base_hdr *greh; 714c5441932SPravin B Shelar 715c5441932SPravin B Shelar iph = (struct iphdr *)skb_push(skb, t->hlen + sizeof(*iph)); 716c5441932SPravin B Shelar greh = (struct gre_base_hdr *)(iph+1); 717c5441932SPravin B Shelar greh->flags = tnl_flags_to_gre_flags(t->parms.o_flags); 718c5441932SPravin B Shelar greh->protocol = htons(type); 7191da177e4SLinus Torvalds 7201da177e4SLinus Torvalds memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); 7211da177e4SLinus Torvalds 722c5441932SPravin B Shelar /* Set the source hardware address. */ 7231da177e4SLinus Torvalds if (saddr) 7241da177e4SLinus Torvalds memcpy(&iph->saddr, saddr, 4); 7256d55cb91STimo Teräs if (daddr) 7261da177e4SLinus Torvalds memcpy(&iph->daddr, daddr, 4); 7276d55cb91STimo Teräs if (iph->daddr) 72877a482bdSTimo Teräs return t->hlen + sizeof(*iph); 7291da177e4SLinus Torvalds 730c5441932SPravin B Shelar return -(t->hlen + sizeof(*iph)); 7311da177e4SLinus Torvalds } 7321da177e4SLinus Torvalds 7336a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) 7346a5f44d7STimo Teras { 735b71d1d42SEric Dumazet const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); 7366a5f44d7STimo Teras memcpy(haddr, &iph->saddr, 4); 7376a5f44d7STimo Teras return 4; 7386a5f44d7STimo Teras } 7396a5f44d7STimo Teras 7403b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = { 7413b04dddeSStephen Hemminger .create = ipgre_header, 7426a5f44d7STimo Teras .parse = ipgre_header_parse, 7433b04dddeSStephen Hemminger }; 7443b04dddeSStephen Hemminger 7456a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST 7461da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev) 7471da177e4SLinus Torvalds { 7482941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 7491da177e4SLinus Torvalds 750f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr)) { 751cbb1e85fSDavid S. Miller struct flowi4 fl4; 752cbb1e85fSDavid S. Miller struct rtable *rt; 753cbb1e85fSDavid S. Miller 754b57708adSNicolas Dichtel rt = ip_route_output_gre(t->net, &fl4, 75578fbfd8aSDavid S. Miller t->parms.iph.daddr, 75678fbfd8aSDavid S. Miller t->parms.iph.saddr, 75778fbfd8aSDavid S. Miller t->parms.o_key, 75878fbfd8aSDavid S. Miller RT_TOS(t->parms.iph.tos), 75978fbfd8aSDavid S. Miller t->parms.link); 760b23dd4feSDavid S. Miller if (IS_ERR(rt)) 7611da177e4SLinus Torvalds return -EADDRNOTAVAIL; 762d8d1f30bSChangli Gao dev = rt->dst.dev; 7631da177e4SLinus Torvalds ip_rt_put(rt); 76451456b29SIan Morris if (!__in_dev_get_rtnl(dev)) 7651da177e4SLinus Torvalds return -EADDRNOTAVAIL; 7661da177e4SLinus Torvalds t->mlink = dev->ifindex; 767e5ed6399SHerbert Xu ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); 7681da177e4SLinus Torvalds } 7691da177e4SLinus Torvalds return 0; 7701da177e4SLinus Torvalds } 7711da177e4SLinus Torvalds 7721da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev) 7731da177e4SLinus Torvalds { 7742941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 775b8c26a33SStephen Hemminger 776f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) { 7777fee0ca2SDenis V. Lunev struct in_device *in_dev; 778b57708adSNicolas Dichtel in_dev = inetdev_by_index(t->net, t->mlink); 7798723e1b4SEric Dumazet if (in_dev) 7801da177e4SLinus Torvalds ip_mc_dec_group(in_dev, t->parms.iph.daddr); 7811da177e4SLinus Torvalds } 7821da177e4SLinus Torvalds return 0; 7831da177e4SLinus Torvalds } 7841da177e4SLinus Torvalds #endif 7851da177e4SLinus Torvalds 786b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = { 787b8c26a33SStephen Hemminger .ndo_init = ipgre_tunnel_init, 788c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 789b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST 790b8c26a33SStephen Hemminger .ndo_open = ipgre_open, 791b8c26a33SStephen Hemminger .ndo_stop = ipgre_close, 792b8c26a33SStephen Hemminger #endif 793c5441932SPravin B Shelar .ndo_start_xmit = ipgre_xmit, 794b8c26a33SStephen Hemminger .ndo_do_ioctl = ipgre_tunnel_ioctl, 795c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 796c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 7971e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 798b8c26a33SStephen Hemminger }; 799b8c26a33SStephen Hemminger 8006b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG | \ 8016b78f16eSEric Dumazet NETIF_F_FRAGLIST | \ 8026b78f16eSEric Dumazet NETIF_F_HIGHDMA | \ 8036b78f16eSEric Dumazet NETIF_F_HW_CSUM) 8046b78f16eSEric Dumazet 8051da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev) 8061da177e4SLinus Torvalds { 807b8c26a33SStephen Hemminger dev->netdev_ops = &ipgre_netdev_ops; 8085a455275SNicolas Dichtel dev->type = ARPHRD_IPGRE; 809c5441932SPravin B Shelar ip_tunnel_setup(dev, ipgre_net_id); 810c5441932SPravin B Shelar } 8111da177e4SLinus Torvalds 812c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev) 813c5441932SPravin B Shelar { 814c5441932SPravin B Shelar struct ip_tunnel *tunnel; 8154565e991STom Herbert int t_hlen; 816c5441932SPravin B Shelar 817c5441932SPravin B Shelar tunnel = netdev_priv(dev); 8184565e991STom Herbert tunnel->tun_hlen = ip_gre_calc_hlen(tunnel->parms.o_flags); 819c5441932SPravin B Shelar tunnel->parms.iph.protocol = IPPROTO_GRE; 820c5441932SPravin B Shelar 8214565e991STom Herbert tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; 8224565e991STom Herbert 8234565e991STom Herbert t_hlen = tunnel->hlen + sizeof(struct iphdr); 8244565e991STom Herbert 8254565e991STom Herbert dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; 8264565e991STom Herbert dev->mtu = ETH_DATA_LEN - t_hlen - 4; 8276b78f16eSEric Dumazet 828b57708adSNicolas Dichtel dev->features |= GRE_FEATURES; 8296b78f16eSEric Dumazet dev->hw_features |= GRE_FEATURES; 830c5441932SPravin B Shelar 831c5441932SPravin B Shelar if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 832c5441932SPravin B Shelar /* TCP offload with GRE SEQ is not supported. */ 833c5441932SPravin B Shelar dev->features |= NETIF_F_GSO_SOFTWARE; 834c5441932SPravin B Shelar dev->hw_features |= NETIF_F_GSO_SOFTWARE; 835c5441932SPravin B Shelar /* Can use a lockless transmit, unless we generate 836c5441932SPravin B Shelar * output sequences 837c5441932SPravin B Shelar */ 838c5441932SPravin B Shelar dev->features |= NETIF_F_LLTX; 839c5441932SPravin B Shelar } 8401da177e4SLinus Torvalds } 8411da177e4SLinus Torvalds 8421da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev) 8431da177e4SLinus Torvalds { 844c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 845c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 8461da177e4SLinus Torvalds 847c5441932SPravin B Shelar __gre_tunnel_init(dev); 8481da177e4SLinus Torvalds 849c5441932SPravin B Shelar memcpy(dev->dev_addr, &iph->saddr, 4); 850c5441932SPravin B Shelar memcpy(dev->broadcast, &iph->daddr, 4); 8511da177e4SLinus Torvalds 852c5441932SPravin B Shelar dev->flags = IFF_NOARP; 85302875878SEric Dumazet netif_keep_dst(dev); 854c5441932SPravin B Shelar dev->addr_len = 4; 8551da177e4SLinus Torvalds 8561da177e4SLinus Torvalds if (iph->daddr) { 8571da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST 858f97c1e0cSJoe Perches if (ipv4_is_multicast(iph->daddr)) { 8591da177e4SLinus Torvalds if (!iph->saddr) 8601da177e4SLinus Torvalds return -EINVAL; 8611da177e4SLinus Torvalds dev->flags = IFF_BROADCAST; 8623b04dddeSStephen Hemminger dev->header_ops = &ipgre_header_ops; 8631da177e4SLinus Torvalds } 8641da177e4SLinus Torvalds #endif 865ee34c1ebSMichal Schmidt } else 8666a5f44d7STimo Teras dev->header_ops = &ipgre_header_ops; 8671da177e4SLinus Torvalds 868c5441932SPravin B Shelar return ip_tunnel_init(dev); 86960769a5dSEric Dumazet } 87060769a5dSEric Dumazet 871*9f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = { 872*9f57c67cSPravin B Shelar .handler = gre_rcv, 873*9f57c67cSPravin B Shelar .err_handler = gre_err, 8741da177e4SLinus Torvalds }; 8751da177e4SLinus Torvalds 8762c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net) 87759a4c759SPavel Emelyanov { 878c5441932SPravin B Shelar return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); 87959a4c759SPavel Emelyanov } 88059a4c759SPavel Emelyanov 8812c8c1e72SAlexey Dobriyan static void __net_exit ipgre_exit_net(struct net *net) 88259a4c759SPavel Emelyanov { 883c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id); 8846c742e71SNicolas Dichtel ip_tunnel_delete_net(itn, &ipgre_link_ops); 88559a4c759SPavel Emelyanov } 88659a4c759SPavel Emelyanov 88759a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = { 88859a4c759SPavel Emelyanov .init = ipgre_init_net, 88959a4c759SPavel Emelyanov .exit = ipgre_exit_net, 890cfb8fbf2SEric W. Biederman .id = &ipgre_net_id, 891c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 89259a4c759SPavel Emelyanov }; 8931da177e4SLinus Torvalds 894c19e654dSHerbert Xu static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) 895c19e654dSHerbert Xu { 896c19e654dSHerbert Xu __be16 flags; 897c19e654dSHerbert Xu 898c19e654dSHerbert Xu if (!data) 899c19e654dSHerbert Xu return 0; 900c19e654dSHerbert Xu 901c19e654dSHerbert Xu flags = 0; 902c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 903c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 904c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 905c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 906c19e654dSHerbert Xu if (flags & (GRE_VERSION|GRE_ROUTING)) 907c19e654dSHerbert Xu return -EINVAL; 908c19e654dSHerbert Xu 909c19e654dSHerbert Xu return 0; 910c19e654dSHerbert Xu } 911c19e654dSHerbert Xu 912e1a80002SHerbert Xu static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[]) 913e1a80002SHerbert Xu { 914e1a80002SHerbert Xu __be32 daddr; 915e1a80002SHerbert Xu 916e1a80002SHerbert Xu if (tb[IFLA_ADDRESS]) { 917e1a80002SHerbert Xu if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) 918e1a80002SHerbert Xu return -EINVAL; 919e1a80002SHerbert Xu if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 920e1a80002SHerbert Xu return -EADDRNOTAVAIL; 921e1a80002SHerbert Xu } 922e1a80002SHerbert Xu 923e1a80002SHerbert Xu if (!data) 924e1a80002SHerbert Xu goto out; 925e1a80002SHerbert Xu 926e1a80002SHerbert Xu if (data[IFLA_GRE_REMOTE]) { 927e1a80002SHerbert Xu memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); 928e1a80002SHerbert Xu if (!daddr) 929e1a80002SHerbert Xu return -EINVAL; 930e1a80002SHerbert Xu } 931e1a80002SHerbert Xu 932e1a80002SHerbert Xu out: 933e1a80002SHerbert Xu return ipgre_tunnel_validate(tb, data); 934e1a80002SHerbert Xu } 935e1a80002SHerbert Xu 9362e15ea39SPravin B Shelar static void ipgre_netlink_parms(struct net_device *dev, 9372e15ea39SPravin B Shelar struct nlattr *data[], 9382e15ea39SPravin B Shelar struct nlattr *tb[], 939c19e654dSHerbert Xu struct ip_tunnel_parm *parms) 940c19e654dSHerbert Xu { 9417bb82d92SHerbert Xu memset(parms, 0, sizeof(*parms)); 942c19e654dSHerbert Xu 943c19e654dSHerbert Xu parms->iph.protocol = IPPROTO_GRE; 944c19e654dSHerbert Xu 945c19e654dSHerbert Xu if (!data) 946c19e654dSHerbert Xu return; 947c19e654dSHerbert Xu 948c19e654dSHerbert Xu if (data[IFLA_GRE_LINK]) 949c19e654dSHerbert Xu parms->link = nla_get_u32(data[IFLA_GRE_LINK]); 950c19e654dSHerbert Xu 951c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 952c5441932SPravin B Shelar parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); 953c19e654dSHerbert Xu 954c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 955c5441932SPravin B Shelar parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); 956c19e654dSHerbert Xu 957c19e654dSHerbert Xu if (data[IFLA_GRE_IKEY]) 958c19e654dSHerbert Xu parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); 959c19e654dSHerbert Xu 960c19e654dSHerbert Xu if (data[IFLA_GRE_OKEY]) 961c19e654dSHerbert Xu parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); 962c19e654dSHerbert Xu 963c19e654dSHerbert Xu if (data[IFLA_GRE_LOCAL]) 96467b61f6cSJiri Benc parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); 965c19e654dSHerbert Xu 966c19e654dSHerbert Xu if (data[IFLA_GRE_REMOTE]) 96767b61f6cSJiri Benc parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); 968c19e654dSHerbert Xu 969c19e654dSHerbert Xu if (data[IFLA_GRE_TTL]) 970c19e654dSHerbert Xu parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); 971c19e654dSHerbert Xu 972c19e654dSHerbert Xu if (data[IFLA_GRE_TOS]) 973c19e654dSHerbert Xu parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); 974c19e654dSHerbert Xu 975c19e654dSHerbert Xu if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) 976c19e654dSHerbert Xu parms->iph.frag_off = htons(IP_DF); 9772e15ea39SPravin B Shelar 9782e15ea39SPravin B Shelar if (data[IFLA_GRE_COLLECT_METADATA]) { 9792e15ea39SPravin B Shelar struct ip_tunnel *t = netdev_priv(dev); 9802e15ea39SPravin B Shelar 9812e15ea39SPravin B Shelar t->collect_md = true; 9822e15ea39SPravin B Shelar } 983c19e654dSHerbert Xu } 984c19e654dSHerbert Xu 9854565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */ 9864565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[], 9874565e991STom Herbert struct ip_tunnel_encap *ipencap) 9884565e991STom Herbert { 9894565e991STom Herbert bool ret = false; 9904565e991STom Herbert 9914565e991STom Herbert memset(ipencap, 0, sizeof(*ipencap)); 9924565e991STom Herbert 9934565e991STom Herbert if (!data) 9944565e991STom Herbert return ret; 9954565e991STom Herbert 9964565e991STom Herbert if (data[IFLA_GRE_ENCAP_TYPE]) { 9974565e991STom Herbert ret = true; 9984565e991STom Herbert ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); 9994565e991STom Herbert } 10004565e991STom Herbert 10014565e991STom Herbert if (data[IFLA_GRE_ENCAP_FLAGS]) { 10024565e991STom Herbert ret = true; 10034565e991STom Herbert ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); 10044565e991STom Herbert } 10054565e991STom Herbert 10064565e991STom Herbert if (data[IFLA_GRE_ENCAP_SPORT]) { 10074565e991STom Herbert ret = true; 10083e97fa70SSabrina Dubroca ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); 10094565e991STom Herbert } 10104565e991STom Herbert 10114565e991STom Herbert if (data[IFLA_GRE_ENCAP_DPORT]) { 10124565e991STom Herbert ret = true; 10133e97fa70SSabrina Dubroca ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); 10144565e991STom Herbert } 10154565e991STom Herbert 10164565e991STom Herbert return ret; 10174565e991STom Herbert } 10184565e991STom Herbert 1019c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev) 1020e1a80002SHerbert Xu { 1021c5441932SPravin B Shelar __gre_tunnel_init(dev); 1022bec94d43Sstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1023e1a80002SHerbert Xu 1024c5441932SPravin B Shelar return ip_tunnel_init(dev); 1025e1a80002SHerbert Xu } 1026e1a80002SHerbert Xu 1027c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = { 1028c5441932SPravin B Shelar .ndo_init = gre_tap_init, 1029c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 1030c5441932SPravin B Shelar .ndo_start_xmit = gre_tap_xmit, 1031b8c26a33SStephen Hemminger .ndo_set_mac_address = eth_mac_addr, 1032b8c26a33SStephen Hemminger .ndo_validate_addr = eth_validate_addr, 1033c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 1034c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 10351e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 1036b8c26a33SStephen Hemminger }; 1037b8c26a33SStephen Hemminger 1038e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev) 1039e1a80002SHerbert Xu { 1040e1a80002SHerbert Xu ether_setup(dev); 1041c5441932SPravin B Shelar dev->netdev_ops = &gre_tap_netdev_ops; 1042f8c1b7ceSstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1043c5441932SPravin B Shelar ip_tunnel_setup(dev, gre_tap_net_id); 1044e1a80002SHerbert Xu } 1045e1a80002SHerbert Xu 1046c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev, 1047c5441932SPravin B Shelar struct nlattr *tb[], struct nlattr *data[]) 1048c19e654dSHerbert Xu { 1049c5441932SPravin B Shelar struct ip_tunnel_parm p; 10504565e991STom Herbert struct ip_tunnel_encap ipencap; 10514565e991STom Herbert 10524565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 10534565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 10544565e991STom Herbert int err = ip_tunnel_encap_setup(t, &ipencap); 10554565e991STom Herbert 10564565e991STom Herbert if (err < 0) 10574565e991STom Herbert return err; 10584565e991STom Herbert } 1059c19e654dSHerbert Xu 10602e15ea39SPravin B Shelar ipgre_netlink_parms(dev, data, tb, &p); 1061c5441932SPravin B Shelar return ip_tunnel_newlink(dev, tb, &p); 1062c19e654dSHerbert Xu } 1063c19e654dSHerbert Xu 1064c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], 1065c19e654dSHerbert Xu struct nlattr *data[]) 1066c19e654dSHerbert Xu { 1067c19e654dSHerbert Xu struct ip_tunnel_parm p; 10684565e991STom Herbert struct ip_tunnel_encap ipencap; 10694565e991STom Herbert 10704565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 10714565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 10724565e991STom Herbert int err = ip_tunnel_encap_setup(t, &ipencap); 10734565e991STom Herbert 10744565e991STom Herbert if (err < 0) 10754565e991STom Herbert return err; 10764565e991STom Herbert } 1077c19e654dSHerbert Xu 10782e15ea39SPravin B Shelar ipgre_netlink_parms(dev, data, tb, &p); 1079c5441932SPravin B Shelar return ip_tunnel_changelink(dev, tb, &p); 1080c19e654dSHerbert Xu } 1081c19e654dSHerbert Xu 1082c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev) 1083c19e654dSHerbert Xu { 1084c19e654dSHerbert Xu return 1085c19e654dSHerbert Xu /* IFLA_GRE_LINK */ 1086c19e654dSHerbert Xu nla_total_size(4) + 1087c19e654dSHerbert Xu /* IFLA_GRE_IFLAGS */ 1088c19e654dSHerbert Xu nla_total_size(2) + 1089c19e654dSHerbert Xu /* IFLA_GRE_OFLAGS */ 1090c19e654dSHerbert Xu nla_total_size(2) + 1091c19e654dSHerbert Xu /* IFLA_GRE_IKEY */ 1092c19e654dSHerbert Xu nla_total_size(4) + 1093c19e654dSHerbert Xu /* IFLA_GRE_OKEY */ 1094c19e654dSHerbert Xu nla_total_size(4) + 1095c19e654dSHerbert Xu /* IFLA_GRE_LOCAL */ 1096c19e654dSHerbert Xu nla_total_size(4) + 1097c19e654dSHerbert Xu /* IFLA_GRE_REMOTE */ 1098c19e654dSHerbert Xu nla_total_size(4) + 1099c19e654dSHerbert Xu /* IFLA_GRE_TTL */ 1100c19e654dSHerbert Xu nla_total_size(1) + 1101c19e654dSHerbert Xu /* IFLA_GRE_TOS */ 1102c19e654dSHerbert Xu nla_total_size(1) + 1103c19e654dSHerbert Xu /* IFLA_GRE_PMTUDISC */ 1104c19e654dSHerbert Xu nla_total_size(1) + 11054565e991STom Herbert /* IFLA_GRE_ENCAP_TYPE */ 11064565e991STom Herbert nla_total_size(2) + 11074565e991STom Herbert /* IFLA_GRE_ENCAP_FLAGS */ 11084565e991STom Herbert nla_total_size(2) + 11094565e991STom Herbert /* IFLA_GRE_ENCAP_SPORT */ 11104565e991STom Herbert nla_total_size(2) + 11114565e991STom Herbert /* IFLA_GRE_ENCAP_DPORT */ 11124565e991STom Herbert nla_total_size(2) + 11132e15ea39SPravin B Shelar /* IFLA_GRE_COLLECT_METADATA */ 11142e15ea39SPravin B Shelar nla_total_size(0) + 1115c19e654dSHerbert Xu 0; 1116c19e654dSHerbert Xu } 1117c19e654dSHerbert Xu 1118c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) 1119c19e654dSHerbert Xu { 1120c19e654dSHerbert Xu struct ip_tunnel *t = netdev_priv(dev); 1121c19e654dSHerbert Xu struct ip_tunnel_parm *p = &t->parms; 1122c19e654dSHerbert Xu 1123f3756b79SDavid S. Miller if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || 1124c5441932SPravin B Shelar nla_put_be16(skb, IFLA_GRE_IFLAGS, tnl_flags_to_gre_flags(p->i_flags)) || 1125c5441932SPravin B Shelar nla_put_be16(skb, IFLA_GRE_OFLAGS, tnl_flags_to_gre_flags(p->o_flags)) || 1126f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || 1127f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || 1128930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || 1129930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) || 1130f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) || 1131f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) || 1132f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_PMTUDISC, 1133f3756b79SDavid S. Miller !!(p->iph.frag_off & htons(IP_DF)))) 1134f3756b79SDavid S. Miller goto nla_put_failure; 11354565e991STom Herbert 11364565e991STom Herbert if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, 11374565e991STom Herbert t->encap.type) || 11383e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, 11394565e991STom Herbert t->encap.sport) || 11403e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, 11414565e991STom Herbert t->encap.dport) || 11424565e991STom Herbert nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, 1143e1b2cb65STom Herbert t->encap.flags)) 11444565e991STom Herbert goto nla_put_failure; 11454565e991STom Herbert 11462e15ea39SPravin B Shelar if (t->collect_md) { 11472e15ea39SPravin B Shelar if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) 11482e15ea39SPravin B Shelar goto nla_put_failure; 11492e15ea39SPravin B Shelar } 11502e15ea39SPravin B Shelar 1151c19e654dSHerbert Xu return 0; 1152c19e654dSHerbert Xu 1153c19e654dSHerbert Xu nla_put_failure: 1154c19e654dSHerbert Xu return -EMSGSIZE; 1155c19e654dSHerbert Xu } 1156c19e654dSHerbert Xu 1157c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { 1158c19e654dSHerbert Xu [IFLA_GRE_LINK] = { .type = NLA_U32 }, 1159c19e654dSHerbert Xu [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, 1160c19e654dSHerbert Xu [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, 1161c19e654dSHerbert Xu [IFLA_GRE_IKEY] = { .type = NLA_U32 }, 1162c19e654dSHerbert Xu [IFLA_GRE_OKEY] = { .type = NLA_U32 }, 11634d74f8baSPatrick McHardy [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, 11644d74f8baSPatrick McHardy [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, 1165c19e654dSHerbert Xu [IFLA_GRE_TTL] = { .type = NLA_U8 }, 1166c19e654dSHerbert Xu [IFLA_GRE_TOS] = { .type = NLA_U8 }, 1167c19e654dSHerbert Xu [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, 11684565e991STom Herbert [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, 11694565e991STom Herbert [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, 11704565e991STom Herbert [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, 11714565e991STom Herbert [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, 11722e15ea39SPravin B Shelar [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, 1173c19e654dSHerbert Xu }; 1174c19e654dSHerbert Xu 1175c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = { 1176c19e654dSHerbert Xu .kind = "gre", 1177c19e654dSHerbert Xu .maxtype = IFLA_GRE_MAX, 1178c19e654dSHerbert Xu .policy = ipgre_policy, 1179c19e654dSHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1180c19e654dSHerbert Xu .setup = ipgre_tunnel_setup, 1181c19e654dSHerbert Xu .validate = ipgre_tunnel_validate, 1182c19e654dSHerbert Xu .newlink = ipgre_newlink, 1183c19e654dSHerbert Xu .changelink = ipgre_changelink, 1184c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1185c19e654dSHerbert Xu .get_size = ipgre_get_size, 1186c19e654dSHerbert Xu .fill_info = ipgre_fill_info, 11871728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1188c19e654dSHerbert Xu }; 1189c19e654dSHerbert Xu 1190e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { 1191e1a80002SHerbert Xu .kind = "gretap", 1192e1a80002SHerbert Xu .maxtype = IFLA_GRE_MAX, 1193e1a80002SHerbert Xu .policy = ipgre_policy, 1194e1a80002SHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1195e1a80002SHerbert Xu .setup = ipgre_tap_setup, 1196e1a80002SHerbert Xu .validate = ipgre_tap_validate, 1197e1a80002SHerbert Xu .newlink = ipgre_newlink, 1198e1a80002SHerbert Xu .changelink = ipgre_changelink, 1199c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1200e1a80002SHerbert Xu .get_size = ipgre_get_size, 1201e1a80002SHerbert Xu .fill_info = ipgre_fill_info, 12021728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1203e1a80002SHerbert Xu }; 1204e1a80002SHerbert Xu 1205b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name, 1206b2acd1dcSPravin B Shelar u8 name_assign_type) 1207b2acd1dcSPravin B Shelar { 1208b2acd1dcSPravin B Shelar struct nlattr *tb[IFLA_MAX + 1]; 1209b2acd1dcSPravin B Shelar struct net_device *dev; 1210b2acd1dcSPravin B Shelar struct ip_tunnel *t; 1211b2acd1dcSPravin B Shelar int err; 1212b2acd1dcSPravin B Shelar 1213b2acd1dcSPravin B Shelar memset(&tb, 0, sizeof(tb)); 1214b2acd1dcSPravin B Shelar 1215b2acd1dcSPravin B Shelar dev = rtnl_create_link(net, name, name_assign_type, 1216b2acd1dcSPravin B Shelar &ipgre_tap_ops, tb); 1217b2acd1dcSPravin B Shelar if (IS_ERR(dev)) 1218b2acd1dcSPravin B Shelar return dev; 1219b2acd1dcSPravin B Shelar 1220b2acd1dcSPravin B Shelar /* Configure flow based GRE device. */ 1221b2acd1dcSPravin B Shelar t = netdev_priv(dev); 1222b2acd1dcSPravin B Shelar t->collect_md = true; 1223b2acd1dcSPravin B Shelar 1224b2acd1dcSPravin B Shelar err = ipgre_newlink(net, dev, tb, NULL); 1225b2acd1dcSPravin B Shelar if (err < 0) 1226b2acd1dcSPravin B Shelar goto out; 1227b2acd1dcSPravin B Shelar return dev; 1228b2acd1dcSPravin B Shelar out: 1229b2acd1dcSPravin B Shelar free_netdev(dev); 1230b2acd1dcSPravin B Shelar return ERR_PTR(err); 1231b2acd1dcSPravin B Shelar } 1232b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create); 1233b2acd1dcSPravin B Shelar 1234c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net) 1235c5441932SPravin B Shelar { 12362e15ea39SPravin B Shelar return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); 1237c5441932SPravin B Shelar } 1238c5441932SPravin B Shelar 1239c5441932SPravin B Shelar static void __net_exit ipgre_tap_exit_net(struct net *net) 1240c5441932SPravin B Shelar { 1241c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id); 12426c742e71SNicolas Dichtel ip_tunnel_delete_net(itn, &ipgre_tap_ops); 1243c5441932SPravin B Shelar } 1244c5441932SPravin B Shelar 1245c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = { 1246c5441932SPravin B Shelar .init = ipgre_tap_init_net, 1247c5441932SPravin B Shelar .exit = ipgre_tap_exit_net, 1248c5441932SPravin B Shelar .id = &gre_tap_net_id, 1249c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 1250c5441932SPravin B Shelar }; 12511da177e4SLinus Torvalds 12521da177e4SLinus Torvalds static int __init ipgre_init(void) 12531da177e4SLinus Torvalds { 12541da177e4SLinus Torvalds int err; 12551da177e4SLinus Torvalds 1256058bd4d2SJoe Perches pr_info("GRE over IPv4 tunneling driver\n"); 12571da177e4SLinus Torvalds 1258cfb8fbf2SEric W. Biederman err = register_pernet_device(&ipgre_net_ops); 125959a4c759SPavel Emelyanov if (err < 0) 1260c2892f02SAlexey Dobriyan return err; 1261c2892f02SAlexey Dobriyan 1262c5441932SPravin B Shelar err = register_pernet_device(&ipgre_tap_net_ops); 1263c5441932SPravin B Shelar if (err < 0) 1264c5441932SPravin B Shelar goto pnet_tap_faied; 1265c5441932SPravin B Shelar 1266*9f57c67cSPravin B Shelar err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); 1267c2892f02SAlexey Dobriyan if (err < 0) { 1268058bd4d2SJoe Perches pr_info("%s: can't add protocol\n", __func__); 1269c2892f02SAlexey Dobriyan goto add_proto_failed; 1270c2892f02SAlexey Dobriyan } 12717daa0004SPavel Emelyanov 1272c19e654dSHerbert Xu err = rtnl_link_register(&ipgre_link_ops); 1273c19e654dSHerbert Xu if (err < 0) 1274c19e654dSHerbert Xu goto rtnl_link_failed; 1275c19e654dSHerbert Xu 1276e1a80002SHerbert Xu err = rtnl_link_register(&ipgre_tap_ops); 1277e1a80002SHerbert Xu if (err < 0) 1278e1a80002SHerbert Xu goto tap_ops_failed; 1279e1a80002SHerbert Xu 1280c5441932SPravin B Shelar return 0; 1281c19e654dSHerbert Xu 1282e1a80002SHerbert Xu tap_ops_failed: 1283e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 1284c19e654dSHerbert Xu rtnl_link_failed: 1285*9f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1286c2892f02SAlexey Dobriyan add_proto_failed: 1287c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1288c5441932SPravin B Shelar pnet_tap_faied: 1289c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 1290c5441932SPravin B Shelar return err; 12911da177e4SLinus Torvalds } 12921da177e4SLinus Torvalds 1293db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void) 12941da177e4SLinus Torvalds { 1295e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_tap_ops); 1296c19e654dSHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 1297*9f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1298c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1299c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 13001da177e4SLinus Torvalds } 13011da177e4SLinus Torvalds 13021da177e4SLinus Torvalds module_init(ipgre_init); 13031da177e4SLinus Torvalds module_exit(ipgre_fini); 13041da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 13054d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre"); 13064d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap"); 13078909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0"); 1308c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0"); 1309