11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Linux NET3: IP/IP protocol decoder. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Authors: 51da177e4SLinus Torvalds * Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Fixes: 81da177e4SLinus Torvalds * Alan Cox : Merged and made usable non modular (its so tiny its silly as 91da177e4SLinus Torvalds * a module taking up 2 pages). 101da177e4SLinus Torvalds * Alan Cox : Fixed bug with 1.3.18 and IPIP not working (now needs to set skb->h.iph) 111da177e4SLinus Torvalds * to keep ip_forward happy. 121da177e4SLinus Torvalds * Alan Cox : More fixes for 1.3.21, and firewall fix. Maybe this will work soon 8). 131da177e4SLinus Torvalds * Kai Schulte : Fixed #defines for IP_FIREWALL->FIREWALL 141da177e4SLinus Torvalds * David Woodhouse : Perform some basic ICMP handling. 151da177e4SLinus Torvalds * IPIP Routing without decapsulation. 161da177e4SLinus Torvalds * Carlos Picoto : GRE over IP support 171da177e4SLinus Torvalds * Alexey Kuznetsov: Reworked. Really, now it is truncated version of ipv4/ip_gre.c. 181da177e4SLinus Torvalds * I do not want to merge them together. 191da177e4SLinus Torvalds * 201da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 211da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 221da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 231da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 241da177e4SLinus Torvalds * 251da177e4SLinus Torvalds */ 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds /* tunnel.c: an IP tunnel driver 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds The purpose of this driver is to provide an IP tunnel through 301da177e4SLinus Torvalds which you can tunnel network traffic transparently across subnets. 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds This was written by looking at Nick Holloway's dummy driver 331da177e4SLinus Torvalds Thanks for the great code! 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds -Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds Minor tweaks: 381da177e4SLinus Torvalds Cleaned up the code a little and added some pre-1.3.0 tweaks. 391da177e4SLinus Torvalds dev->hard_header/hard_header_len changed to use no headers. 401da177e4SLinus Torvalds Comments/bracketing tweaked. 411da177e4SLinus Torvalds Made the tunnels use dev->name not tunnel: when error reporting. 421da177e4SLinus Torvalds Added tx_dropped stat 431da177e4SLinus Torvalds 44113aa838SAlan Cox -Alan Cox (alan@lxorguk.ukuu.org.uk) 21 March 95 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds Reworked: 471da177e4SLinus Torvalds Changed to tunnel to destination gateway in addition to the 481da177e4SLinus Torvalds tunnel's pointopoint address 491da177e4SLinus Torvalds Almost completely rewritten 501da177e4SLinus Torvalds Note: There is currently no firewall or ICMP handling done. 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds -Sam Lantinga (slouken@cs.ucdavis.edu) 02/13/96 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds */ 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds /* Things I wish I had known when writing the tunnel driver: 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds When the tunnel_xmit() function is called, the skb contains the 591da177e4SLinus Torvalds packet to be sent (plus a great deal of extra info), and dev 601da177e4SLinus Torvalds contains the tunnel device that _we_ are. 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds When we are passed a packet, we are expected to fill in the 631da177e4SLinus Torvalds source address with our source IP address. 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds What is the proper way to allocate, copy and free a buffer? 661da177e4SLinus Torvalds After you allocate it, it is a "0 length" chunk of memory 671da177e4SLinus Torvalds starting at zero. If you want to add headers to the buffer 681da177e4SLinus Torvalds later, you'll have to call "skb_reserve(skb, amount)" with 691da177e4SLinus Torvalds the amount of memory you want reserved. Then, you call 701da177e4SLinus Torvalds "skb_put(skb, amount)" with the amount of space you want in 711da177e4SLinus Torvalds the buffer. skb_put() returns a pointer to the top (#0) of 721da177e4SLinus Torvalds that buffer. skb->len is set to the amount of space you have 731da177e4SLinus Torvalds "allocated" with skb_put(). You can then write up to skb->len 741da177e4SLinus Torvalds bytes to that buffer. If you need more, you can call skb_put() 751da177e4SLinus Torvalds again with the additional amount of space you need. You can 761da177e4SLinus Torvalds find out how much more space you can allocate by calling 771da177e4SLinus Torvalds "skb_tailroom(skb)". 781da177e4SLinus Torvalds Now, to add header space, call "skb_push(skb, header_len)". 791da177e4SLinus Torvalds This creates space at the beginning of the buffer and returns 801da177e4SLinus Torvalds a pointer to this new space. If later you need to strip a 811da177e4SLinus Torvalds header from a buffer, call "skb_pull(skb, header_len)". 821da177e4SLinus Torvalds skb_headroom() will return how much space is left at the top 831da177e4SLinus Torvalds of the buffer (before the main data). Remember, this headroom 841da177e4SLinus Torvalds space must be reserved before the skb_put() function is called. 851da177e4SLinus Torvalds */ 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds /* 881da177e4SLinus Torvalds This version of net/ipv4/ipip.c is cloned of net/ipv4/ip_gre.c 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds For comments look at net/ipv4/ip_gre.c --ANK 911da177e4SLinus Torvalds */ 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds 944fc268d2SRandy Dunlap #include <linux/capability.h> 951da177e4SLinus Torvalds #include <linux/module.h> 961da177e4SLinus Torvalds #include <linux/types.h> 971da177e4SLinus Torvalds #include <linux/kernel.h> 981da177e4SLinus Torvalds #include <asm/uaccess.h> 991da177e4SLinus Torvalds #include <linux/skbuff.h> 1001da177e4SLinus Torvalds #include <linux/netdevice.h> 1011da177e4SLinus Torvalds #include <linux/in.h> 1021da177e4SLinus Torvalds #include <linux/tcp.h> 1031da177e4SLinus Torvalds #include <linux/udp.h> 1041da177e4SLinus Torvalds #include <linux/if_arp.h> 1051da177e4SLinus Torvalds #include <linux/mroute.h> 1061da177e4SLinus Torvalds #include <linux/init.h> 1071da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h> 10846f25dffSKris Katterjohn #include <linux/if_ether.h> 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds #include <net/sock.h> 1111da177e4SLinus Torvalds #include <net/ip.h> 1121da177e4SLinus Torvalds #include <net/icmp.h> 1131da177e4SLinus Torvalds #include <net/ipip.h> 1141da177e4SLinus Torvalds #include <net/inet_ecn.h> 1151da177e4SLinus Torvalds #include <net/xfrm.h> 11610dc4c7bSPavel Emelyanov #include <net/net_namespace.h> 11710dc4c7bSPavel Emelyanov #include <net/netns/generic.h> 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds #define HASH_SIZE 16 120d5a0a1e3SAl Viro #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) 1211da177e4SLinus Torvalds 12210dc4c7bSPavel Emelyanov static int ipip_net_id; 12310dc4c7bSPavel Emelyanov struct ipip_net { 12444d3c299SPavel Emelyanov struct ip_tunnel *tunnels_r_l[HASH_SIZE]; 12544d3c299SPavel Emelyanov struct ip_tunnel *tunnels_r[HASH_SIZE]; 12644d3c299SPavel Emelyanov struct ip_tunnel *tunnels_l[HASH_SIZE]; 12744d3c299SPavel Emelyanov struct ip_tunnel *tunnels_wc[1]; 12844d3c299SPavel Emelyanov struct ip_tunnel **tunnels[4]; 12944d3c299SPavel Emelyanov 130b9855c54SPavel Emelyanov struct net_device *fb_tunnel_dev; 13110dc4c7bSPavel Emelyanov }; 13210dc4c7bSPavel Emelyanov 13323a12b14SStephen Hemminger static void ipip_fb_tunnel_init(struct net_device *dev); 13423a12b14SStephen Hemminger static void ipip_tunnel_init(struct net_device *dev); 1351da177e4SLinus Torvalds static void ipip_tunnel_setup(struct net_device *dev); 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds static DEFINE_RWLOCK(ipip_lock); 1381da177e4SLinus Torvalds 139b9fae5c9SPavel Emelyanov static struct ip_tunnel * ipip_tunnel_lookup(struct net *net, 140b9fae5c9SPavel Emelyanov __be32 remote, __be32 local) 1411da177e4SLinus Torvalds { 1421da177e4SLinus Torvalds unsigned h0 = HASH(remote); 1431da177e4SLinus Torvalds unsigned h1 = HASH(local); 1441da177e4SLinus Torvalds struct ip_tunnel *t; 14544d3c299SPavel Emelyanov struct ipip_net *ipn = net_generic(net, ipip_net_id); 1461da177e4SLinus Torvalds 14744d3c299SPavel Emelyanov for (t = ipn->tunnels_r_l[h0^h1]; t; t = t->next) { 1481da177e4SLinus Torvalds if (local == t->parms.iph.saddr && 1491da177e4SLinus Torvalds remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) 1501da177e4SLinus Torvalds return t; 1511da177e4SLinus Torvalds } 15244d3c299SPavel Emelyanov for (t = ipn->tunnels_r[h0]; t; t = t->next) { 1531da177e4SLinus Torvalds if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) 1541da177e4SLinus Torvalds return t; 1551da177e4SLinus Torvalds } 15644d3c299SPavel Emelyanov for (t = ipn->tunnels_l[h1]; t; t = t->next) { 1571da177e4SLinus Torvalds if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) 1581da177e4SLinus Torvalds return t; 1591da177e4SLinus Torvalds } 16044d3c299SPavel Emelyanov if ((t = ipn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) 1611da177e4SLinus Torvalds return t; 1621da177e4SLinus Torvalds return NULL; 1631da177e4SLinus Torvalds } 1641da177e4SLinus Torvalds 165b9fae5c9SPavel Emelyanov static struct ip_tunnel **__ipip_bucket(struct ipip_net *ipn, 166b9fae5c9SPavel Emelyanov struct ip_tunnel_parm *parms) 1671da177e4SLinus Torvalds { 16887d1a164SYOSHIFUJI Hideaki __be32 remote = parms->iph.daddr; 16987d1a164SYOSHIFUJI Hideaki __be32 local = parms->iph.saddr; 1701da177e4SLinus Torvalds unsigned h = 0; 1711da177e4SLinus Torvalds int prio = 0; 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds if (remote) { 1741da177e4SLinus Torvalds prio |= 2; 1751da177e4SLinus Torvalds h ^= HASH(remote); 1761da177e4SLinus Torvalds } 1771da177e4SLinus Torvalds if (local) { 1781da177e4SLinus Torvalds prio |= 1; 1791da177e4SLinus Torvalds h ^= HASH(local); 1801da177e4SLinus Torvalds } 18144d3c299SPavel Emelyanov return &ipn->tunnels[prio][h]; 1821da177e4SLinus Torvalds } 1831da177e4SLinus Torvalds 184b9fae5c9SPavel Emelyanov static inline struct ip_tunnel **ipip_bucket(struct ipip_net *ipn, 185b9fae5c9SPavel Emelyanov struct ip_tunnel *t) 18687d1a164SYOSHIFUJI Hideaki { 187b9fae5c9SPavel Emelyanov return __ipip_bucket(ipn, &t->parms); 18887d1a164SYOSHIFUJI Hideaki } 1891da177e4SLinus Torvalds 190b9fae5c9SPavel Emelyanov static void ipip_tunnel_unlink(struct ipip_net *ipn, struct ip_tunnel *t) 1911da177e4SLinus Torvalds { 1921da177e4SLinus Torvalds struct ip_tunnel **tp; 1931da177e4SLinus Torvalds 194b9fae5c9SPavel Emelyanov for (tp = ipip_bucket(ipn, t); *tp; tp = &(*tp)->next) { 1951da177e4SLinus Torvalds if (t == *tp) { 1961da177e4SLinus Torvalds write_lock_bh(&ipip_lock); 1971da177e4SLinus Torvalds *tp = t->next; 1981da177e4SLinus Torvalds write_unlock_bh(&ipip_lock); 1991da177e4SLinus Torvalds break; 2001da177e4SLinus Torvalds } 2011da177e4SLinus Torvalds } 2021da177e4SLinus Torvalds } 2031da177e4SLinus Torvalds 204b9fae5c9SPavel Emelyanov static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t) 2051da177e4SLinus Torvalds { 206b9fae5c9SPavel Emelyanov struct ip_tunnel **tp = ipip_bucket(ipn, t); 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds t->next = *tp; 2091da177e4SLinus Torvalds write_lock_bh(&ipip_lock); 2101da177e4SLinus Torvalds *tp = t; 2111da177e4SLinus Torvalds write_unlock_bh(&ipip_lock); 2121da177e4SLinus Torvalds } 2131da177e4SLinus Torvalds 214b9fae5c9SPavel Emelyanov static struct ip_tunnel * ipip_tunnel_locate(struct net *net, 215b9fae5c9SPavel Emelyanov struct ip_tunnel_parm *parms, int create) 2161da177e4SLinus Torvalds { 217d5a0a1e3SAl Viro __be32 remote = parms->iph.daddr; 218d5a0a1e3SAl Viro __be32 local = parms->iph.saddr; 2191da177e4SLinus Torvalds struct ip_tunnel *t, **tp, *nt; 2201da177e4SLinus Torvalds struct net_device *dev; 2211da177e4SLinus Torvalds char name[IFNAMSIZ]; 222b9fae5c9SPavel Emelyanov struct ipip_net *ipn = net_generic(net, ipip_net_id); 2231da177e4SLinus Torvalds 224b9fae5c9SPavel Emelyanov for (tp = __ipip_bucket(ipn, parms); (t = *tp) != NULL; tp = &t->next) { 2251da177e4SLinus Torvalds if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) 2261da177e4SLinus Torvalds return t; 2271da177e4SLinus Torvalds } 2281da177e4SLinus Torvalds if (!create) 2291da177e4SLinus Torvalds return NULL; 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds if (parms->name[0]) 2321da177e4SLinus Torvalds strlcpy(name, parms->name, IFNAMSIZ); 23334cc7ba6SPavel Emelyanov else 23434cc7ba6SPavel Emelyanov sprintf(name, "tunl%%d"); 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds dev = alloc_netdev(sizeof(*t), name, ipip_tunnel_setup); 2371da177e4SLinus Torvalds if (dev == NULL) 2381da177e4SLinus Torvalds return NULL; 2391da177e4SLinus Torvalds 2400a826406SPavel Emelyanov dev_net_set(dev, net); 2410a826406SPavel Emelyanov 242b37d428bSPavel Emelyanov if (strchr(name, '%')) { 243b37d428bSPavel Emelyanov if (dev_alloc_name(dev, name) < 0) 244b37d428bSPavel Emelyanov goto failed_free; 245b37d428bSPavel Emelyanov } 246b37d428bSPavel Emelyanov 2472941a486SPatrick McHardy nt = netdev_priv(dev); 2481da177e4SLinus Torvalds nt->parms = *parms; 2491da177e4SLinus Torvalds 25023a12b14SStephen Hemminger ipip_tunnel_init(dev); 25123a12b14SStephen Hemminger 252b37d428bSPavel Emelyanov if (register_netdevice(dev) < 0) 253b37d428bSPavel Emelyanov goto failed_free; 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds dev_hold(dev); 256b9fae5c9SPavel Emelyanov ipip_tunnel_link(ipn, nt); 2571da177e4SLinus Torvalds return nt; 2581da177e4SLinus Torvalds 259b37d428bSPavel Emelyanov failed_free: 260b37d428bSPavel Emelyanov free_netdev(dev); 2611da177e4SLinus Torvalds return NULL; 2621da177e4SLinus Torvalds } 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds static void ipip_tunnel_uninit(struct net_device *dev) 2651da177e4SLinus Torvalds { 266b9855c54SPavel Emelyanov struct net *net = dev_net(dev); 267b9855c54SPavel Emelyanov struct ipip_net *ipn = net_generic(net, ipip_net_id); 268b9855c54SPavel Emelyanov 269b9855c54SPavel Emelyanov if (dev == ipn->fb_tunnel_dev) { 2701da177e4SLinus Torvalds write_lock_bh(&ipip_lock); 27144d3c299SPavel Emelyanov ipn->tunnels_wc[0] = NULL; 2721da177e4SLinus Torvalds write_unlock_bh(&ipip_lock); 2731da177e4SLinus Torvalds } else 274b9fae5c9SPavel Emelyanov ipip_tunnel_unlink(ipn, netdev_priv(dev)); 2751da177e4SLinus Torvalds dev_put(dev); 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds 278d2acc347SHerbert Xu static int ipip_err(struct sk_buff *skb, u32 info) 2791da177e4SLinus Torvalds { 2801da177e4SLinus Torvalds 281071f92d0SRami Rosen /* All the routers (except for Linux) return only 2821da177e4SLinus Torvalds 8 bytes of packet payload. It means, that precise relaying of 2831da177e4SLinus Torvalds ICMP in the real Internet is absolutely infeasible. 2841da177e4SLinus Torvalds */ 2851da177e4SLinus Torvalds struct iphdr *iph = (struct iphdr *)skb->data; 28688c7664fSArnaldo Carvalho de Melo const int type = icmp_hdr(skb)->type; 28788c7664fSArnaldo Carvalho de Melo const int code = icmp_hdr(skb)->code; 2881da177e4SLinus Torvalds struct ip_tunnel *t; 289d2acc347SHerbert Xu int err; 2901da177e4SLinus Torvalds 2911da177e4SLinus Torvalds switch (type) { 2921da177e4SLinus Torvalds default: 2931da177e4SLinus Torvalds case ICMP_PARAMETERPROB: 294d2acc347SHerbert Xu return 0; 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds case ICMP_DEST_UNREACH: 2971da177e4SLinus Torvalds switch (code) { 2981da177e4SLinus Torvalds case ICMP_SR_FAILED: 2991da177e4SLinus Torvalds case ICMP_PORT_UNREACH: 3001da177e4SLinus Torvalds /* Impossible event. */ 301d2acc347SHerbert Xu return 0; 3021da177e4SLinus Torvalds case ICMP_FRAG_NEEDED: 3031da177e4SLinus Torvalds /* Soft state for pmtu is maintained by IP core. */ 304d2acc347SHerbert Xu return 0; 3051da177e4SLinus Torvalds default: 3061da177e4SLinus Torvalds /* All others are translated to HOST_UNREACH. 3071da177e4SLinus Torvalds rfc2003 contains "deep thoughts" about NET_UNREACH, 3081da177e4SLinus Torvalds I believe they are just ether pollution. --ANK 3091da177e4SLinus Torvalds */ 3101da177e4SLinus Torvalds break; 3111da177e4SLinus Torvalds } 3121da177e4SLinus Torvalds break; 3131da177e4SLinus Torvalds case ICMP_TIME_EXCEEDED: 3141da177e4SLinus Torvalds if (code != ICMP_EXC_TTL) 315d2acc347SHerbert Xu return 0; 3161da177e4SLinus Torvalds break; 3171da177e4SLinus Torvalds } 3181da177e4SLinus Torvalds 319d2acc347SHerbert Xu err = -ENOENT; 320d2acc347SHerbert Xu 3211da177e4SLinus Torvalds read_lock(&ipip_lock); 322cec3ffaeSPavel Emelyanov t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); 3231da177e4SLinus Torvalds if (t == NULL || t->parms.iph.daddr == 0) 3241da177e4SLinus Torvalds goto out; 325d2acc347SHerbert Xu 326d2acc347SHerbert Xu err = 0; 3271da177e4SLinus Torvalds if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 3281da177e4SLinus Torvalds goto out; 3291da177e4SLinus Torvalds 330*26d94b46SWei Yongjun if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) 3311da177e4SLinus Torvalds t->err_count++; 3321da177e4SLinus Torvalds else 3331da177e4SLinus Torvalds t->err_count = 1; 3341da177e4SLinus Torvalds t->err_time = jiffies; 3351da177e4SLinus Torvalds out: 3361da177e4SLinus Torvalds read_unlock(&ipip_lock); 337d2acc347SHerbert Xu return err; 3381da177e4SLinus Torvalds } 3391da177e4SLinus Torvalds 340eddc9ec5SArnaldo Carvalho de Melo static inline void ipip_ecn_decapsulate(const struct iphdr *outer_iph, 341eddc9ec5SArnaldo Carvalho de Melo struct sk_buff *skb) 3421da177e4SLinus Torvalds { 343eddc9ec5SArnaldo Carvalho de Melo struct iphdr *inner_iph = ip_hdr(skb); 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds if (INET_ECN_is_ce(outer_iph->tos)) 3461da177e4SLinus Torvalds IP_ECN_set_ce(inner_iph); 3471da177e4SLinus Torvalds } 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds static int ipip_rcv(struct sk_buff *skb) 3501da177e4SLinus Torvalds { 3511da177e4SLinus Torvalds struct ip_tunnel *tunnel; 352eddc9ec5SArnaldo Carvalho de Melo const struct iphdr *iph = ip_hdr(skb); 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds read_lock(&ipip_lock); 355cec3ffaeSPavel Emelyanov if ((tunnel = ipip_tunnel_lookup(dev_net(skb->dev), 356b9fae5c9SPavel Emelyanov iph->saddr, iph->daddr)) != NULL) { 3571da177e4SLinus Torvalds if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { 3581da177e4SLinus Torvalds read_unlock(&ipip_lock); 3591da177e4SLinus Torvalds kfree_skb(skb); 3601da177e4SLinus Torvalds return 0; 3611da177e4SLinus Torvalds } 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds secpath_reset(skb); 3641da177e4SLinus Torvalds 365b0e380b1SArnaldo Carvalho de Melo skb->mac_header = skb->network_header; 366c1d2bbe1SArnaldo Carvalho de Melo skb_reset_network_header(skb); 3671da177e4SLinus Torvalds skb->protocol = htons(ETH_P_IP); 3681da177e4SLinus Torvalds skb->pkt_type = PACKET_HOST; 3691da177e4SLinus Torvalds 37050f59ceaSPavel Emelyanov tunnel->dev->stats.rx_packets++; 37150f59ceaSPavel Emelyanov tunnel->dev->stats.rx_bytes += skb->len; 3721da177e4SLinus Torvalds skb->dev = tunnel->dev; 3731da177e4SLinus Torvalds dst_release(skb->dst); 3741da177e4SLinus Torvalds skb->dst = NULL; 3751da177e4SLinus Torvalds nf_reset(skb); 3761da177e4SLinus Torvalds ipip_ecn_decapsulate(iph, skb); 3771da177e4SLinus Torvalds netif_rx(skb); 3781da177e4SLinus Torvalds read_unlock(&ipip_lock); 3791da177e4SLinus Torvalds return 0; 3801da177e4SLinus Torvalds } 3811da177e4SLinus Torvalds read_unlock(&ipip_lock); 3821da177e4SLinus Torvalds 3831da177e4SLinus Torvalds return -1; 3841da177e4SLinus Torvalds } 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds /* 3871da177e4SLinus Torvalds * This function assumes it is being called from dev_queue_xmit() 3881da177e4SLinus Torvalds * and that skb is filled properly by that function. 3891da177e4SLinus Torvalds */ 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) 3921da177e4SLinus Torvalds { 3932941a486SPatrick McHardy struct ip_tunnel *tunnel = netdev_priv(dev); 39450f59ceaSPavel Emelyanov struct net_device_stats *stats = &tunnel->dev->stats; 3951da177e4SLinus Torvalds struct iphdr *tiph = &tunnel->parms.iph; 3961da177e4SLinus Torvalds u8 tos = tunnel->parms.iph.tos; 397d5a0a1e3SAl Viro __be16 df = tiph->frag_off; 3981da177e4SLinus Torvalds struct rtable *rt; /* Route to the other host */ 3991da177e4SLinus Torvalds struct net_device *tdev; /* Device to other host */ 400eddc9ec5SArnaldo Carvalho de Melo struct iphdr *old_iph = ip_hdr(skb); 4011da177e4SLinus Torvalds struct iphdr *iph; /* Our new IP header */ 402c2636b4dSChuck Lever unsigned int max_headroom; /* The extra header space needed */ 403d5a0a1e3SAl Viro __be32 dst = tiph->daddr; 4041da177e4SLinus Torvalds int mtu; 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds if (tunnel->recursion++) { 40750f59ceaSPavel Emelyanov stats->collisions++; 4081da177e4SLinus Torvalds goto tx_error; 4091da177e4SLinus Torvalds } 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds if (skb->protocol != htons(ETH_P_IP)) 4121da177e4SLinus Torvalds goto tx_error; 4131da177e4SLinus Torvalds 4141da177e4SLinus Torvalds if (tos&1) 4151da177e4SLinus Torvalds tos = old_iph->tos; 4161da177e4SLinus Torvalds 4171da177e4SLinus Torvalds if (!dst) { 4181da177e4SLinus Torvalds /* NBMA tunnel */ 419ee6b9673SEric Dumazet if ((rt = skb->rtable) == NULL) { 42050f59ceaSPavel Emelyanov stats->tx_fifo_errors++; 4211da177e4SLinus Torvalds goto tx_error; 4221da177e4SLinus Torvalds } 4231da177e4SLinus Torvalds if ((dst = rt->rt_gateway) == 0) 4241da177e4SLinus Torvalds goto tx_error_icmp; 4251da177e4SLinus Torvalds } 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds { 4281da177e4SLinus Torvalds struct flowi fl = { .oif = tunnel->parms.link, 4291da177e4SLinus Torvalds .nl_u = { .ip4_u = 4301da177e4SLinus Torvalds { .daddr = dst, 4311da177e4SLinus Torvalds .saddr = tiph->saddr, 4321da177e4SLinus Torvalds .tos = RT_TOS(tos) } }, 4331da177e4SLinus Torvalds .proto = IPPROTO_IPIP }; 434b99f0152SPavel Emelyanov if (ip_route_output_key(dev_net(dev), &rt, &fl)) { 43550f59ceaSPavel Emelyanov stats->tx_carrier_errors++; 4361da177e4SLinus Torvalds goto tx_error_icmp; 4371da177e4SLinus Torvalds } 4381da177e4SLinus Torvalds } 4391da177e4SLinus Torvalds tdev = rt->u.dst.dev; 4401da177e4SLinus Torvalds 4411da177e4SLinus Torvalds if (tdev == dev) { 4421da177e4SLinus Torvalds ip_rt_put(rt); 44350f59ceaSPavel Emelyanov stats->collisions++; 4441da177e4SLinus Torvalds goto tx_error; 4451da177e4SLinus Torvalds } 4461da177e4SLinus Torvalds 4471da177e4SLinus Torvalds if (tiph->frag_off) 4481da177e4SLinus Torvalds mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); 4491da177e4SLinus Torvalds else 4501da177e4SLinus Torvalds mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds if (mtu < 68) { 45350f59ceaSPavel Emelyanov stats->collisions++; 4541da177e4SLinus Torvalds ip_rt_put(rt); 4551da177e4SLinus Torvalds goto tx_error; 4561da177e4SLinus Torvalds } 4571da177e4SLinus Torvalds if (skb->dst) 4581da177e4SLinus Torvalds skb->dst->ops->update_pmtu(skb->dst, mtu); 4591da177e4SLinus Torvalds 4601da177e4SLinus Torvalds df |= (old_iph->frag_off&htons(IP_DF)); 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds if ((old_iph->frag_off&htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) { 4631da177e4SLinus Torvalds icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); 4641da177e4SLinus Torvalds ip_rt_put(rt); 4651da177e4SLinus Torvalds goto tx_error; 4661da177e4SLinus Torvalds } 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds if (tunnel->err_count > 0) { 469*26d94b46SWei Yongjun if (time_before(jiffies, 470*26d94b46SWei Yongjun tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { 4711da177e4SLinus Torvalds tunnel->err_count--; 4721da177e4SLinus Torvalds dst_link_failure(skb); 4731da177e4SLinus Torvalds } else 4741da177e4SLinus Torvalds tunnel->err_count = 0; 4751da177e4SLinus Torvalds } 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds /* 4781da177e4SLinus Torvalds * Okay, now see if we can stuff it in the buffer as-is. 4791da177e4SLinus Torvalds */ 4801da177e4SLinus Torvalds max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr)); 4811da177e4SLinus Torvalds 482cfbba49dSPatrick McHardy if (skb_headroom(skb) < max_headroom || skb_shared(skb) || 483cfbba49dSPatrick McHardy (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { 4841da177e4SLinus Torvalds struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); 4851da177e4SLinus Torvalds if (!new_skb) { 4861da177e4SLinus Torvalds ip_rt_put(rt); 4871da177e4SLinus Torvalds stats->tx_dropped++; 4881da177e4SLinus Torvalds dev_kfree_skb(skb); 4891da177e4SLinus Torvalds tunnel->recursion--; 4901da177e4SLinus Torvalds return 0; 4911da177e4SLinus Torvalds } 4921da177e4SLinus Torvalds if (skb->sk) 4931da177e4SLinus Torvalds skb_set_owner_w(new_skb, skb->sk); 4941da177e4SLinus Torvalds dev_kfree_skb(skb); 4951da177e4SLinus Torvalds skb = new_skb; 496eddc9ec5SArnaldo Carvalho de Melo old_iph = ip_hdr(skb); 4971da177e4SLinus Torvalds } 4981da177e4SLinus Torvalds 499b0e380b1SArnaldo Carvalho de Melo skb->transport_header = skb->network_header; 500e2d1bca7SArnaldo Carvalho de Melo skb_push(skb, sizeof(struct iphdr)); 501e2d1bca7SArnaldo Carvalho de Melo skb_reset_network_header(skb); 5021da177e4SLinus Torvalds memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 50348d5cad8SPatrick McHardy IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | 50448d5cad8SPatrick McHardy IPSKB_REROUTED); 5051da177e4SLinus Torvalds dst_release(skb->dst); 5061da177e4SLinus Torvalds skb->dst = &rt->u.dst; 5071da177e4SLinus Torvalds 5081da177e4SLinus Torvalds /* 5091da177e4SLinus Torvalds * Push down and install the IPIP header. 5101da177e4SLinus Torvalds */ 5111da177e4SLinus Torvalds 512eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb); 5131da177e4SLinus Torvalds iph->version = 4; 5141da177e4SLinus Torvalds iph->ihl = sizeof(struct iphdr)>>2; 5151da177e4SLinus Torvalds iph->frag_off = df; 5161da177e4SLinus Torvalds iph->protocol = IPPROTO_IPIP; 5171da177e4SLinus Torvalds iph->tos = INET_ECN_encapsulate(tos, old_iph->tos); 5181da177e4SLinus Torvalds iph->daddr = rt->rt_dst; 5191da177e4SLinus Torvalds iph->saddr = rt->rt_src; 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds if ((iph->ttl = tiph->ttl) == 0) 5221da177e4SLinus Torvalds iph->ttl = old_iph->ttl; 5231da177e4SLinus Torvalds 5241da177e4SLinus Torvalds nf_reset(skb); 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds IPTUNNEL_XMIT(); 5271da177e4SLinus Torvalds tunnel->recursion--; 5281da177e4SLinus Torvalds return 0; 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds tx_error_icmp: 5311da177e4SLinus Torvalds dst_link_failure(skb); 5321da177e4SLinus Torvalds tx_error: 5331da177e4SLinus Torvalds stats->tx_errors++; 5341da177e4SLinus Torvalds dev_kfree_skb(skb); 5351da177e4SLinus Torvalds tunnel->recursion--; 5361da177e4SLinus Torvalds return 0; 5371da177e4SLinus Torvalds } 5381da177e4SLinus Torvalds 5395533995bSMichal Schmidt static void ipip_tunnel_bind_dev(struct net_device *dev) 5405533995bSMichal Schmidt { 5415533995bSMichal Schmidt struct net_device *tdev = NULL; 5425533995bSMichal Schmidt struct ip_tunnel *tunnel; 5435533995bSMichal Schmidt struct iphdr *iph; 5445533995bSMichal Schmidt 5455533995bSMichal Schmidt tunnel = netdev_priv(dev); 5465533995bSMichal Schmidt iph = &tunnel->parms.iph; 5475533995bSMichal Schmidt 5485533995bSMichal Schmidt if (iph->daddr) { 5495533995bSMichal Schmidt struct flowi fl = { .oif = tunnel->parms.link, 5505533995bSMichal Schmidt .nl_u = { .ip4_u = 5515533995bSMichal Schmidt { .daddr = iph->daddr, 5525533995bSMichal Schmidt .saddr = iph->saddr, 5535533995bSMichal Schmidt .tos = RT_TOS(iph->tos) } }, 5545533995bSMichal Schmidt .proto = IPPROTO_IPIP }; 5555533995bSMichal Schmidt struct rtable *rt; 556b99f0152SPavel Emelyanov if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { 5575533995bSMichal Schmidt tdev = rt->u.dst.dev; 5585533995bSMichal Schmidt ip_rt_put(rt); 5595533995bSMichal Schmidt } 5605533995bSMichal Schmidt dev->flags |= IFF_POINTOPOINT; 5615533995bSMichal Schmidt } 5625533995bSMichal Schmidt 5635533995bSMichal Schmidt if (!tdev && tunnel->parms.link) 564b99f0152SPavel Emelyanov tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link); 5655533995bSMichal Schmidt 5665533995bSMichal Schmidt if (tdev) { 5675533995bSMichal Schmidt dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); 5685533995bSMichal Schmidt dev->mtu = tdev->mtu - sizeof(struct iphdr); 5695533995bSMichal Schmidt } 5705533995bSMichal Schmidt dev->iflink = tunnel->parms.link; 5715533995bSMichal Schmidt } 5725533995bSMichal Schmidt 5731da177e4SLinus Torvalds static int 5741da177e4SLinus Torvalds ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) 5751da177e4SLinus Torvalds { 5761da177e4SLinus Torvalds int err = 0; 5771da177e4SLinus Torvalds struct ip_tunnel_parm p; 5781da177e4SLinus Torvalds struct ip_tunnel *t; 579b9855c54SPavel Emelyanov struct net *net = dev_net(dev); 580b9855c54SPavel Emelyanov struct ipip_net *ipn = net_generic(net, ipip_net_id); 5811da177e4SLinus Torvalds 5821da177e4SLinus Torvalds switch (cmd) { 5831da177e4SLinus Torvalds case SIOCGETTUNNEL: 5841da177e4SLinus Torvalds t = NULL; 585b9855c54SPavel Emelyanov if (dev == ipn->fb_tunnel_dev) { 5861da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { 5871da177e4SLinus Torvalds err = -EFAULT; 5881da177e4SLinus Torvalds break; 5891da177e4SLinus Torvalds } 590b9fae5c9SPavel Emelyanov t = ipip_tunnel_locate(net, &p, 0); 5911da177e4SLinus Torvalds } 5921da177e4SLinus Torvalds if (t == NULL) 5932941a486SPatrick McHardy t = netdev_priv(dev); 5941da177e4SLinus Torvalds memcpy(&p, &t->parms, sizeof(p)); 5951da177e4SLinus Torvalds if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) 5961da177e4SLinus Torvalds err = -EFAULT; 5971da177e4SLinus Torvalds break; 5981da177e4SLinus Torvalds 5991da177e4SLinus Torvalds case SIOCADDTUNNEL: 6001da177e4SLinus Torvalds case SIOCCHGTUNNEL: 6011da177e4SLinus Torvalds err = -EPERM; 6021da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 6031da177e4SLinus Torvalds goto done; 6041da177e4SLinus Torvalds 6051da177e4SLinus Torvalds err = -EFAULT; 6061da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 6071da177e4SLinus Torvalds goto done; 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds err = -EINVAL; 6101da177e4SLinus Torvalds if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP || 6111da177e4SLinus Torvalds p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) 6121da177e4SLinus Torvalds goto done; 6131da177e4SLinus Torvalds if (p.iph.ttl) 6141da177e4SLinus Torvalds p.iph.frag_off |= htons(IP_DF); 6151da177e4SLinus Torvalds 616b9fae5c9SPavel Emelyanov t = ipip_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL); 6171da177e4SLinus Torvalds 618b9855c54SPavel Emelyanov if (dev != ipn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { 6191da177e4SLinus Torvalds if (t != NULL) { 6201da177e4SLinus Torvalds if (t->dev != dev) { 6211da177e4SLinus Torvalds err = -EEXIST; 6221da177e4SLinus Torvalds break; 6231da177e4SLinus Torvalds } 6241da177e4SLinus Torvalds } else { 6251da177e4SLinus Torvalds if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) || 6261da177e4SLinus Torvalds (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) { 6271da177e4SLinus Torvalds err = -EINVAL; 6281da177e4SLinus Torvalds break; 6291da177e4SLinus Torvalds } 6302941a486SPatrick McHardy t = netdev_priv(dev); 631b9fae5c9SPavel Emelyanov ipip_tunnel_unlink(ipn, t); 6321da177e4SLinus Torvalds t->parms.iph.saddr = p.iph.saddr; 6331da177e4SLinus Torvalds t->parms.iph.daddr = p.iph.daddr; 6341da177e4SLinus Torvalds memcpy(dev->dev_addr, &p.iph.saddr, 4); 6351da177e4SLinus Torvalds memcpy(dev->broadcast, &p.iph.daddr, 4); 636b9fae5c9SPavel Emelyanov ipip_tunnel_link(ipn, t); 6371da177e4SLinus Torvalds netdev_state_change(dev); 6381da177e4SLinus Torvalds } 6391da177e4SLinus Torvalds } 6401da177e4SLinus Torvalds 6411da177e4SLinus Torvalds if (t) { 6421da177e4SLinus Torvalds err = 0; 6431da177e4SLinus Torvalds if (cmd == SIOCCHGTUNNEL) { 6441da177e4SLinus Torvalds t->parms.iph.ttl = p.iph.ttl; 6451da177e4SLinus Torvalds t->parms.iph.tos = p.iph.tos; 6461da177e4SLinus Torvalds t->parms.iph.frag_off = p.iph.frag_off; 6475533995bSMichal Schmidt if (t->parms.link != p.link) { 6485533995bSMichal Schmidt t->parms.link = p.link; 6495533995bSMichal Schmidt ipip_tunnel_bind_dev(dev); 6505533995bSMichal Schmidt netdev_state_change(dev); 6515533995bSMichal Schmidt } 6521da177e4SLinus Torvalds } 6531da177e4SLinus Torvalds if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) 6541da177e4SLinus Torvalds err = -EFAULT; 6551da177e4SLinus Torvalds } else 6561da177e4SLinus Torvalds err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); 6571da177e4SLinus Torvalds break; 6581da177e4SLinus Torvalds 6591da177e4SLinus Torvalds case SIOCDELTUNNEL: 6601da177e4SLinus Torvalds err = -EPERM; 6611da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 6621da177e4SLinus Torvalds goto done; 6631da177e4SLinus Torvalds 664b9855c54SPavel Emelyanov if (dev == ipn->fb_tunnel_dev) { 6651da177e4SLinus Torvalds err = -EFAULT; 6661da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 6671da177e4SLinus Torvalds goto done; 6681da177e4SLinus Torvalds err = -ENOENT; 669b9fae5c9SPavel Emelyanov if ((t = ipip_tunnel_locate(net, &p, 0)) == NULL) 6701da177e4SLinus Torvalds goto done; 6711da177e4SLinus Torvalds err = -EPERM; 672b9855c54SPavel Emelyanov if (t->dev == ipn->fb_tunnel_dev) 6731da177e4SLinus Torvalds goto done; 6741da177e4SLinus Torvalds dev = t->dev; 6751da177e4SLinus Torvalds } 67622f8cde5SStephen Hemminger unregister_netdevice(dev); 67722f8cde5SStephen Hemminger err = 0; 6781da177e4SLinus Torvalds break; 6791da177e4SLinus Torvalds 6801da177e4SLinus Torvalds default: 6811da177e4SLinus Torvalds err = -EINVAL; 6821da177e4SLinus Torvalds } 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds done: 6851da177e4SLinus Torvalds return err; 6861da177e4SLinus Torvalds } 6871da177e4SLinus Torvalds 6881da177e4SLinus Torvalds static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu) 6891da177e4SLinus Torvalds { 6901da177e4SLinus Torvalds if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr)) 6911da177e4SLinus Torvalds return -EINVAL; 6921da177e4SLinus Torvalds dev->mtu = new_mtu; 6931da177e4SLinus Torvalds return 0; 6941da177e4SLinus Torvalds } 6951da177e4SLinus Torvalds 69623a12b14SStephen Hemminger static const struct net_device_ops ipip_netdev_ops = { 69723a12b14SStephen Hemminger .ndo_uninit = ipip_tunnel_uninit, 69823a12b14SStephen Hemminger .ndo_start_xmit = ipip_tunnel_xmit, 69923a12b14SStephen Hemminger .ndo_do_ioctl = ipip_tunnel_ioctl, 70023a12b14SStephen Hemminger .ndo_change_mtu = ipip_tunnel_change_mtu, 70123a12b14SStephen Hemminger 70223a12b14SStephen Hemminger }; 70323a12b14SStephen Hemminger 7041da177e4SLinus Torvalds static void ipip_tunnel_setup(struct net_device *dev) 7051da177e4SLinus Torvalds { 70623a12b14SStephen Hemminger dev->netdev_ops = &ipip_netdev_ops; 7071da177e4SLinus Torvalds dev->destructor = free_netdev; 7081da177e4SLinus Torvalds 7091da177e4SLinus Torvalds dev->type = ARPHRD_TUNNEL; 7101da177e4SLinus Torvalds dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); 71146f25dffSKris Katterjohn dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr); 7121da177e4SLinus Torvalds dev->flags = IFF_NOARP; 7131da177e4SLinus Torvalds dev->iflink = 0; 7141da177e4SLinus Torvalds dev->addr_len = 4; 7150a826406SPavel Emelyanov dev->features |= NETIF_F_NETNS_LOCAL; 7161da177e4SLinus Torvalds } 7171da177e4SLinus Torvalds 71823a12b14SStephen Hemminger static void ipip_tunnel_init(struct net_device *dev) 7191da177e4SLinus Torvalds { 72023a12b14SStephen Hemminger struct ip_tunnel *tunnel = netdev_priv(dev); 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds tunnel->dev = dev; 7231da177e4SLinus Torvalds strcpy(tunnel->parms.name, dev->name); 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); 7261da177e4SLinus Torvalds memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); 7271da177e4SLinus Torvalds 7285533995bSMichal Schmidt ipip_tunnel_bind_dev(dev); 7291da177e4SLinus Torvalds } 7301da177e4SLinus Torvalds 73123a12b14SStephen Hemminger static void ipip_fb_tunnel_init(struct net_device *dev) 7321da177e4SLinus Torvalds { 7332941a486SPatrick McHardy struct ip_tunnel *tunnel = netdev_priv(dev); 7341da177e4SLinus Torvalds struct iphdr *iph = &tunnel->parms.iph; 73544d3c299SPavel Emelyanov struct ipip_net *ipn = net_generic(dev_net(dev), ipip_net_id); 7361da177e4SLinus Torvalds 7371da177e4SLinus Torvalds tunnel->dev = dev; 7381da177e4SLinus Torvalds strcpy(tunnel->parms.name, dev->name); 7391da177e4SLinus Torvalds 7401da177e4SLinus Torvalds iph->version = 4; 7411da177e4SLinus Torvalds iph->protocol = IPPROTO_IPIP; 7421da177e4SLinus Torvalds iph->ihl = 5; 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds dev_hold(dev); 74544d3c299SPavel Emelyanov ipn->tunnels_wc[0] = tunnel; 7461da177e4SLinus Torvalds } 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds static struct xfrm_tunnel ipip_handler = { 7491da177e4SLinus Torvalds .handler = ipip_rcv, 7501da177e4SLinus Torvalds .err_handler = ipip_err, 751d2acc347SHerbert Xu .priority = 1, 7521da177e4SLinus Torvalds }; 7531da177e4SLinus Torvalds 7545747a1aaSStephen Hemminger static const char banner[] __initconst = 7551da177e4SLinus Torvalds KERN_INFO "IPv4 over IPv4 tunneling driver\n"; 7561da177e4SLinus Torvalds 75744d3c299SPavel Emelyanov static void ipip_destroy_tunnels(struct ipip_net *ipn) 75844d3c299SPavel Emelyanov { 75944d3c299SPavel Emelyanov int prio; 76044d3c299SPavel Emelyanov 76144d3c299SPavel Emelyanov for (prio = 1; prio < 4; prio++) { 76244d3c299SPavel Emelyanov int h; 76344d3c299SPavel Emelyanov for (h = 0; h < HASH_SIZE; h++) { 76444d3c299SPavel Emelyanov struct ip_tunnel *t; 76544d3c299SPavel Emelyanov while ((t = ipn->tunnels[prio][h]) != NULL) 76644d3c299SPavel Emelyanov unregister_netdevice(t->dev); 76744d3c299SPavel Emelyanov } 76844d3c299SPavel Emelyanov } 76944d3c299SPavel Emelyanov } 77044d3c299SPavel Emelyanov 77110dc4c7bSPavel Emelyanov static int ipip_init_net(struct net *net) 77210dc4c7bSPavel Emelyanov { 77310dc4c7bSPavel Emelyanov int err; 77410dc4c7bSPavel Emelyanov struct ipip_net *ipn; 77510dc4c7bSPavel Emelyanov 77610dc4c7bSPavel Emelyanov err = -ENOMEM; 77744d3c299SPavel Emelyanov ipn = kzalloc(sizeof(struct ipip_net), GFP_KERNEL); 77810dc4c7bSPavel Emelyanov if (ipn == NULL) 77910dc4c7bSPavel Emelyanov goto err_alloc; 78010dc4c7bSPavel Emelyanov 78110dc4c7bSPavel Emelyanov err = net_assign_generic(net, ipip_net_id, ipn); 78210dc4c7bSPavel Emelyanov if (err < 0) 78310dc4c7bSPavel Emelyanov goto err_assign; 78410dc4c7bSPavel Emelyanov 78544d3c299SPavel Emelyanov ipn->tunnels[0] = ipn->tunnels_wc; 78644d3c299SPavel Emelyanov ipn->tunnels[1] = ipn->tunnels_l; 78744d3c299SPavel Emelyanov ipn->tunnels[2] = ipn->tunnels_r; 78844d3c299SPavel Emelyanov ipn->tunnels[3] = ipn->tunnels_r_l; 78944d3c299SPavel Emelyanov 790b9855c54SPavel Emelyanov ipn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), 791b9855c54SPavel Emelyanov "tunl0", 792b9855c54SPavel Emelyanov ipip_tunnel_setup); 793b9855c54SPavel Emelyanov if (!ipn->fb_tunnel_dev) { 794b9855c54SPavel Emelyanov err = -ENOMEM; 795b9855c54SPavel Emelyanov goto err_alloc_dev; 796b9855c54SPavel Emelyanov } 797be77e593SAlexey Dobriyan dev_net_set(ipn->fb_tunnel_dev, net); 798b9855c54SPavel Emelyanov 79923a12b14SStephen Hemminger ipip_fb_tunnel_init(ipn->fb_tunnel_dev); 800b9855c54SPavel Emelyanov 801b9855c54SPavel Emelyanov if ((err = register_netdev(ipn->fb_tunnel_dev))) 802b9855c54SPavel Emelyanov goto err_reg_dev; 803b9855c54SPavel Emelyanov 80410dc4c7bSPavel Emelyanov return 0; 80510dc4c7bSPavel Emelyanov 806b9855c54SPavel Emelyanov err_reg_dev: 807b9855c54SPavel Emelyanov free_netdev(ipn->fb_tunnel_dev); 808b9855c54SPavel Emelyanov err_alloc_dev: 809b9855c54SPavel Emelyanov /* nothing */ 81010dc4c7bSPavel Emelyanov err_assign: 81110dc4c7bSPavel Emelyanov kfree(ipn); 81210dc4c7bSPavel Emelyanov err_alloc: 81310dc4c7bSPavel Emelyanov return err; 81410dc4c7bSPavel Emelyanov } 81510dc4c7bSPavel Emelyanov 81610dc4c7bSPavel Emelyanov static void ipip_exit_net(struct net *net) 81710dc4c7bSPavel Emelyanov { 81810dc4c7bSPavel Emelyanov struct ipip_net *ipn; 81910dc4c7bSPavel Emelyanov 82010dc4c7bSPavel Emelyanov ipn = net_generic(net, ipip_net_id); 821b9855c54SPavel Emelyanov rtnl_lock(); 82244d3c299SPavel Emelyanov ipip_destroy_tunnels(ipn); 823b9855c54SPavel Emelyanov unregister_netdevice(ipn->fb_tunnel_dev); 824b9855c54SPavel Emelyanov rtnl_unlock(); 82510dc4c7bSPavel Emelyanov kfree(ipn); 82610dc4c7bSPavel Emelyanov } 82710dc4c7bSPavel Emelyanov 82810dc4c7bSPavel Emelyanov static struct pernet_operations ipip_net_ops = { 82910dc4c7bSPavel Emelyanov .init = ipip_init_net, 83010dc4c7bSPavel Emelyanov .exit = ipip_exit_net, 83110dc4c7bSPavel Emelyanov }; 83210dc4c7bSPavel Emelyanov 8331da177e4SLinus Torvalds static int __init ipip_init(void) 8341da177e4SLinus Torvalds { 8351da177e4SLinus Torvalds int err; 8361da177e4SLinus Torvalds 8371da177e4SLinus Torvalds printk(banner); 8381da177e4SLinus Torvalds 839c0d56408SKazunori MIYAZAWA if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) { 8401da177e4SLinus Torvalds printk(KERN_INFO "ipip init: can't register tunnel\n"); 8411da177e4SLinus Torvalds return -EAGAIN; 8421da177e4SLinus Torvalds } 8431da177e4SLinus Torvalds 84410dc4c7bSPavel Emelyanov err = register_pernet_gen_device(&ipip_net_id, &ipip_net_ops); 84510dc4c7bSPavel Emelyanov if (err) 846c0d56408SKazunori MIYAZAWA xfrm4_tunnel_deregister(&ipip_handler, AF_INET); 847b9855c54SPavel Emelyanov 848b9855c54SPavel Emelyanov return err; 8491da177e4SLinus Torvalds } 8501da177e4SLinus Torvalds 8511da177e4SLinus Torvalds static void __exit ipip_fini(void) 8521da177e4SLinus Torvalds { 853c0d56408SKazunori MIYAZAWA if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET)) 8541da177e4SLinus Torvalds printk(KERN_INFO "ipip close: can't deregister tunnel\n"); 8551da177e4SLinus Torvalds 85610dc4c7bSPavel Emelyanov unregister_pernet_gen_device(ipip_net_id, &ipip_net_ops); 8571da177e4SLinus Torvalds } 8581da177e4SLinus Torvalds 8591da177e4SLinus Torvalds module_init(ipip_init); 8601da177e4SLinus Torvalds module_exit(ipip_fini); 8611da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 862