1c9422999SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2c5441932SPravin B Shelar /* 3c5441932SPravin B Shelar * Copyright (c) 2013 Nicira, Inc. 4c5441932SPravin B Shelar */ 5c5441932SPravin B Shelar 6c5441932SPravin B Shelar #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7c5441932SPravin B Shelar 8c5441932SPravin B Shelar #include <linux/capability.h> 9c5441932SPravin B Shelar #include <linux/module.h> 10c5441932SPravin B Shelar #include <linux/types.h> 11c5441932SPravin B Shelar #include <linux/kernel.h> 12c5441932SPravin B Shelar #include <linux/slab.h> 13c5441932SPravin B Shelar #include <linux/uaccess.h> 14c5441932SPravin B Shelar #include <linux/skbuff.h> 15c5441932SPravin B Shelar #include <linux/netdevice.h> 16c5441932SPravin B Shelar #include <linux/in.h> 17c5441932SPravin B Shelar #include <linux/tcp.h> 18c5441932SPravin B Shelar #include <linux/udp.h> 19c5441932SPravin B Shelar #include <linux/if_arp.h> 20c5441932SPravin B Shelar #include <linux/init.h> 21c5441932SPravin B Shelar #include <linux/in6.h> 22c5441932SPravin B Shelar #include <linux/inetdevice.h> 23c5441932SPravin B Shelar #include <linux/igmp.h> 24c5441932SPravin B Shelar #include <linux/netfilter_ipv4.h> 25c5441932SPravin B Shelar #include <linux/etherdevice.h> 26c5441932SPravin B Shelar #include <linux/if_ether.h> 27c5441932SPravin B Shelar #include <linux/if_vlan.h> 28c5441932SPravin B Shelar #include <linux/rculist.h> 2927d79f3bSSachin Kamat #include <linux/err.h> 30c5441932SPravin B Shelar 31c5441932SPravin B Shelar #include <net/sock.h> 32c5441932SPravin B Shelar #include <net/ip.h> 33c5441932SPravin B Shelar #include <net/icmp.h> 34c5441932SPravin B Shelar #include <net/protocol.h> 35c5441932SPravin B Shelar #include <net/ip_tunnels.h> 36c5441932SPravin B Shelar #include <net/arp.h> 37c5441932SPravin B Shelar #include <net/checksum.h> 38c5441932SPravin B Shelar #include <net/dsfield.h> 39c5441932SPravin B Shelar #include <net/inet_ecn.h> 40c5441932SPravin B Shelar #include <net/xfrm.h> 41c5441932SPravin B Shelar #include <net/net_namespace.h> 42c5441932SPravin B Shelar #include <net/netns/generic.h> 438ef890dfSJakub Kicinski #include <net/netdev_lock.h> 44c5441932SPravin B Shelar #include <net/rtnetlink.h> 4556328486STom Herbert #include <net/udp.h> 46cfc7381bSAlexei Starovoitov #include <net/dst_metadata.h> 47c34cfe72SIdo Schimmel #include <net/inet_dscp.h> 4863487babSTom Herbert 49c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 50c5441932SPravin B Shelar #include <net/ipv6.h> 51c5441932SPravin B Shelar #include <net/ip6_fib.h> 52c5441932SPravin B Shelar #include <net/ip6_route.h> 53c5441932SPravin B Shelar #endif 54c5441932SPravin B Shelar 55967680e0SDuan Jiong static unsigned int ip_tunnel_hash(__be32 key, __be32 remote) 56c5441932SPravin B Shelar { 57c5441932SPravin B Shelar return hash_32((__force u32)key ^ (__force u32)remote, 58c5441932SPravin B Shelar IP_TNL_HASH_BITS); 59c5441932SPravin B Shelar } 60c5441932SPravin B Shelar 61117aef12SAlexander Lobakin static bool ip_tunnel_key_match(const struct ip_tunnel_parm_kern *p, 625832c4a7SAlexander Lobakin const unsigned long *flags, __be32 key) 63c5441932SPravin B Shelar { 645832c4a7SAlexander Lobakin if (!test_bit(IP_TUNNEL_KEY_BIT, flags)) 655832c4a7SAlexander Lobakin return !test_bit(IP_TUNNEL_KEY_BIT, p->i_flags); 665832c4a7SAlexander Lobakin 675832c4a7SAlexander Lobakin return test_bit(IP_TUNNEL_KEY_BIT, p->i_flags) && p->i_key == key; 68c5441932SPravin B Shelar } 69c5441932SPravin B Shelar 70c5441932SPravin B Shelar /* Fallback tunnel: no source, no destination, no key, no options 71c5441932SPravin B Shelar 72c5441932SPravin B Shelar Tunnel hash table: 73c5441932SPravin B Shelar We require exact key match i.e. if a key is present in packet 74c5441932SPravin B Shelar it will match only tunnel with the same key; if it is not present, 75c5441932SPravin B Shelar it will match only keyless tunnel. 76c5441932SPravin B Shelar 77c5441932SPravin B Shelar All keysless packets, if not matched configured keyless tunnels 78c5441932SPravin B Shelar will match fallback tunnel. 79c5441932SPravin B Shelar Given src, dst and key, find appropriate for input tunnel. 80c5441932SPravin B Shelar */ 81c5441932SPravin B Shelar struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, 825832c4a7SAlexander Lobakin int link, const unsigned long *flags, 83c5441932SPravin B Shelar __be32 remote, __be32 local, 84c5441932SPravin B Shelar __be32 key) 85c5441932SPravin B Shelar { 86c5441932SPravin B Shelar struct ip_tunnel *t, *cand = NULL; 87c5441932SPravin B Shelar struct hlist_head *head; 88ba61539cSTaehee Yoo struct net_device *ndev; 89ba61539cSTaehee Yoo unsigned int hash; 90c5441932SPravin B Shelar 91967680e0SDuan Jiong hash = ip_tunnel_hash(key, remote); 92c5441932SPravin B Shelar head = &itn->tunnels[hash]; 93c5441932SPravin B Shelar 94c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 95c5441932SPravin B Shelar if (local != t->parms.iph.saddr || 96c5441932SPravin B Shelar remote != t->parms.iph.daddr || 97c5441932SPravin B Shelar !(t->dev->flags & IFF_UP)) 98c5441932SPravin B Shelar continue; 99c5441932SPravin B Shelar 100c5441932SPravin B Shelar if (!ip_tunnel_key_match(&t->parms, flags, key)) 101c5441932SPravin B Shelar continue; 102c5441932SPravin B Shelar 103f694eee9SEric Dumazet if (READ_ONCE(t->parms.link) == link) 104c5441932SPravin B Shelar return t; 105c5441932SPravin B Shelar cand = t; 106c5441932SPravin B Shelar } 107c5441932SPravin B Shelar 108c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 109c5441932SPravin B Shelar if (remote != t->parms.iph.daddr || 110e0056593SDmitry Popov t->parms.iph.saddr != 0 || 111c5441932SPravin B Shelar !(t->dev->flags & IFF_UP)) 112c5441932SPravin B Shelar continue; 113c5441932SPravin B Shelar 114c5441932SPravin B Shelar if (!ip_tunnel_key_match(&t->parms, flags, key)) 115c5441932SPravin B Shelar continue; 116c5441932SPravin B Shelar 117f694eee9SEric Dumazet if (READ_ONCE(t->parms.link) == link) 118c5441932SPravin B Shelar return t; 119f694eee9SEric Dumazet if (!cand) 120c5441932SPravin B Shelar cand = t; 121c5441932SPravin B Shelar } 122c5441932SPravin B Shelar 123967680e0SDuan Jiong hash = ip_tunnel_hash(key, 0); 124c5441932SPravin B Shelar head = &itn->tunnels[hash]; 125c5441932SPravin B Shelar 126c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 127e0056593SDmitry Popov if ((local != t->parms.iph.saddr || t->parms.iph.daddr != 0) && 128e0056593SDmitry Popov (local != t->parms.iph.daddr || !ipv4_is_multicast(local))) 129e0056593SDmitry Popov continue; 130e0056593SDmitry Popov 131e0056593SDmitry Popov if (!(t->dev->flags & IFF_UP)) 132c5441932SPravin B Shelar continue; 133c5441932SPravin B Shelar 134c5441932SPravin B Shelar if (!ip_tunnel_key_match(&t->parms, flags, key)) 135c5441932SPravin B Shelar continue; 136c5441932SPravin B Shelar 137f694eee9SEric Dumazet if (READ_ONCE(t->parms.link) == link) 138c5441932SPravin B Shelar return t; 139f694eee9SEric Dumazet if (!cand) 140c5441932SPravin B Shelar cand = t; 141c5441932SPravin B Shelar } 142c5441932SPravin B Shelar 143c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 1445832c4a7SAlexander Lobakin if ((!test_bit(IP_TUNNEL_NO_KEY_BIT, flags) && 1455832c4a7SAlexander Lobakin t->parms.i_key != key) || 146e0056593SDmitry Popov t->parms.iph.saddr != 0 || 147e0056593SDmitry Popov t->parms.iph.daddr != 0 || 148c5441932SPravin B Shelar !(t->dev->flags & IFF_UP)) 149c5441932SPravin B Shelar continue; 150c5441932SPravin B Shelar 151f694eee9SEric Dumazet if (READ_ONCE(t->parms.link) == link) 152c5441932SPravin B Shelar return t; 153f694eee9SEric Dumazet if (!cand) 154c5441932SPravin B Shelar cand = t; 155c5441932SPravin B Shelar } 156c5441932SPravin B Shelar 157c5441932SPravin B Shelar if (cand) 158c5441932SPravin B Shelar return cand; 159c5441932SPravin B Shelar 1602e15ea39SPravin B Shelar t = rcu_dereference(itn->collect_md_tun); 161833a8b40SHaishuang Yan if (t && t->dev->flags & IFF_UP) 1622e15ea39SPravin B Shelar return t; 1632e15ea39SPravin B Shelar 164ba61539cSTaehee Yoo ndev = READ_ONCE(itn->fb_tunnel_dev); 165ba61539cSTaehee Yoo if (ndev && ndev->flags & IFF_UP) 166ba61539cSTaehee Yoo return netdev_priv(ndev); 167c5441932SPravin B Shelar 168c5441932SPravin B Shelar return NULL; 169c5441932SPravin B Shelar } 170c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_lookup); 171c5441932SPravin B Shelar 172c5441932SPravin B Shelar static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn, 173117aef12SAlexander Lobakin struct ip_tunnel_parm_kern *parms) 174c5441932SPravin B Shelar { 175c5441932SPravin B Shelar unsigned int h; 176c5441932SPravin B Shelar __be32 remote; 1776d608f06SSteffen Klassert __be32 i_key = parms->i_key; 178c5441932SPravin B Shelar 179c5441932SPravin B Shelar if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr)) 180c5441932SPravin B Shelar remote = parms->iph.daddr; 181c5441932SPravin B Shelar else 182c5441932SPravin B Shelar remote = 0; 183c5441932SPravin B Shelar 1845832c4a7SAlexander Lobakin if (!test_bit(IP_TUNNEL_KEY_BIT, parms->i_flags) && 1855832c4a7SAlexander Lobakin test_bit(IP_TUNNEL_VTI_BIT, parms->i_flags)) 1866d608f06SSteffen Klassert i_key = 0; 1876d608f06SSteffen Klassert 1886d608f06SSteffen Klassert h = ip_tunnel_hash(i_key, remote); 189c5441932SPravin B Shelar return &itn->tunnels[h]; 190c5441932SPravin B Shelar } 191c5441932SPravin B Shelar 192c5441932SPravin B Shelar static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t) 193c5441932SPravin B Shelar { 194c5441932SPravin B Shelar struct hlist_head *head = ip_bucket(itn, &t->parms); 195c5441932SPravin B Shelar 1962e15ea39SPravin B Shelar if (t->collect_md) 1972e15ea39SPravin B Shelar rcu_assign_pointer(itn->collect_md_tun, t); 198c5441932SPravin B Shelar hlist_add_head_rcu(&t->hash_node, head); 199c5441932SPravin B Shelar } 200c5441932SPravin B Shelar 2012e15ea39SPravin B Shelar static void ip_tunnel_del(struct ip_tunnel_net *itn, struct ip_tunnel *t) 202c5441932SPravin B Shelar { 2032e15ea39SPravin B Shelar if (t->collect_md) 2042e15ea39SPravin B Shelar rcu_assign_pointer(itn->collect_md_tun, NULL); 205c5441932SPravin B Shelar hlist_del_init_rcu(&t->hash_node); 206c5441932SPravin B Shelar } 207c5441932SPravin B Shelar 208c5441932SPravin B Shelar static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn, 209117aef12SAlexander Lobakin struct ip_tunnel_parm_kern *parms, 210c5441932SPravin B Shelar int type) 211c5441932SPravin B Shelar { 212c5441932SPravin B Shelar __be32 remote = parms->iph.daddr; 213c5441932SPravin B Shelar __be32 local = parms->iph.saddr; 2145832c4a7SAlexander Lobakin IP_TUNNEL_DECLARE_FLAGS(flags); 215c5441932SPravin B Shelar __be32 key = parms->i_key; 216c5441932SPravin B Shelar int link = parms->link; 217c5441932SPravin B Shelar struct ip_tunnel *t = NULL; 218c5441932SPravin B Shelar struct hlist_head *head = ip_bucket(itn, parms); 219c5441932SPravin B Shelar 2205832c4a7SAlexander Lobakin ip_tunnel_flags_copy(flags, parms->i_flags); 2215832c4a7SAlexander Lobakin 22290e0569dSIdo Schimmel hlist_for_each_entry_rcu(t, head, hash_node, lockdep_rtnl_is_held()) { 223c5441932SPravin B Shelar if (local == t->parms.iph.saddr && 224c5441932SPravin B Shelar remote == t->parms.iph.daddr && 225f694eee9SEric Dumazet link == READ_ONCE(t->parms.link) && 2265ce54af1SDmitry Popov type == t->dev->type && 2275ce54af1SDmitry Popov ip_tunnel_key_match(&t->parms, flags, key)) 228c5441932SPravin B Shelar break; 229c5441932SPravin B Shelar } 230c5441932SPravin B Shelar return t; 231c5441932SPravin B Shelar } 232c5441932SPravin B Shelar 233c5441932SPravin B Shelar static struct net_device *__ip_tunnel_create(struct net *net, 234c5441932SPravin B Shelar const struct rtnl_link_ops *ops, 235117aef12SAlexander Lobakin struct ip_tunnel_parm_kern *parms) 236c5441932SPravin B Shelar { 237c5441932SPravin B Shelar int err; 238c5441932SPravin B Shelar struct ip_tunnel *tunnel; 239c5441932SPravin B Shelar struct net_device *dev; 240c5441932SPravin B Shelar char name[IFNAMSIZ]; 241c5441932SPravin B Shelar 242c5441932SPravin B Shelar err = -E2BIG; 2439cb726a2SEric Dumazet if (parms->name[0]) { 2449cb726a2SEric Dumazet if (!dev_valid_name(parms->name)) 245c5441932SPravin B Shelar goto failed; 246*c2dbda07SRuben Wauters strscpy(name, parms->name); 2479cb726a2SEric Dumazet } else { 2489cb726a2SEric Dumazet if (strlen(ops->kind) > (IFNAMSIZ - 3)) 2499cb726a2SEric Dumazet goto failed; 250*c2dbda07SRuben Wauters strscpy(name, ops->kind); 251000ade80SSultan Alsawaf strcat(name, "%d"); 252c5441932SPravin B Shelar } 253c5441932SPravin B Shelar 254c5441932SPravin B Shelar ASSERT_RTNL(); 255c835a677STom Gundersen dev = alloc_netdev(ops->priv_size, name, NET_NAME_UNKNOWN, ops->setup); 256c5441932SPravin B Shelar if (!dev) { 257c5441932SPravin B Shelar err = -ENOMEM; 258c5441932SPravin B Shelar goto failed; 259c5441932SPravin B Shelar } 260c5441932SPravin B Shelar dev_net_set(dev, net); 261c5441932SPravin B Shelar 262c5441932SPravin B Shelar dev->rtnl_link_ops = ops; 263c5441932SPravin B Shelar 264c5441932SPravin B Shelar tunnel = netdev_priv(dev); 265c5441932SPravin B Shelar tunnel->parms = *parms; 2665e6700b3SNicolas Dichtel tunnel->net = net; 267c5441932SPravin B Shelar 268c5441932SPravin B Shelar err = register_netdevice(dev); 269c5441932SPravin B Shelar if (err) 270c5441932SPravin B Shelar goto failed_free; 271c5441932SPravin B Shelar 272c5441932SPravin B Shelar return dev; 273c5441932SPravin B Shelar 274c5441932SPravin B Shelar failed_free: 275c5441932SPravin B Shelar free_netdev(dev); 276c5441932SPravin B Shelar failed: 277c5441932SPravin B Shelar return ERR_PTR(err); 278c5441932SPravin B Shelar } 279c5441932SPravin B Shelar 280c5441932SPravin B Shelar static int ip_tunnel_bind_dev(struct net_device *dev) 281c5441932SPravin B Shelar { 282c5441932SPravin B Shelar struct net_device *tdev = NULL; 283c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 284c5441932SPravin B Shelar const struct iphdr *iph; 285c5441932SPravin B Shelar int hlen = LL_MAX_HEADER; 286c5441932SPravin B Shelar int mtu = ETH_DATA_LEN; 287c5441932SPravin B Shelar int t_hlen = tunnel->hlen + sizeof(struct iphdr); 288c5441932SPravin B Shelar 289c5441932SPravin B Shelar iph = &tunnel->parms.iph; 290c5441932SPravin B Shelar 291c5441932SPravin B Shelar /* Guess output device to choose reasonable mtu and needed_headroom */ 292c5441932SPravin B Shelar if (iph->daddr) { 293c5441932SPravin B Shelar struct flowi4 fl4; 294c5441932SPravin B Shelar struct rtable *rt; 295c5441932SPravin B Shelar 296b0066da5SPetr Machata ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr, 2977d442fabSTom Herbert iph->saddr, tunnel->parms.o_key, 298b5a7b661SXiao Liang iph->tos & INET_DSCP_MASK, tunnel->net, 2997ec9fce4SEyal Birger tunnel->parms.link, tunnel->fwmark, 0, 0); 3007d442fabSTom Herbert rt = ip_route_output_key(tunnel->net, &fl4); 3017d442fabSTom Herbert 302c5441932SPravin B Shelar if (!IS_ERR(rt)) { 303c5441932SPravin B Shelar tdev = rt->dst.dev; 304c5441932SPravin B Shelar ip_rt_put(rt); 305c5441932SPravin B Shelar } 306c5441932SPravin B Shelar if (dev->type != ARPHRD_ETHER) 307c5441932SPravin B Shelar dev->flags |= IFF_POINTOPOINT; 308f27337e1SPaolo Abeni 309f27337e1SPaolo Abeni dst_cache_reset(&tunnel->dst_cache); 310c5441932SPravin B Shelar } 311c5441932SPravin B Shelar 312c5441932SPravin B Shelar if (!tdev && tunnel->parms.link) 3136c742e71SNicolas Dichtel tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link); 314c5441932SPravin B Shelar 315c5441932SPravin B Shelar if (tdev) { 316c5441932SPravin B Shelar hlen = tdev->hard_header_len + tdev->needed_headroom; 31782612de1SNicolas Dichtel mtu = min(tdev->mtu, IP_MAX_MTU); 318c5441932SPravin B Shelar } 319c5441932SPravin B Shelar 320c5441932SPravin B Shelar dev->needed_headroom = t_hlen + hlen; 3219992a078SHangbin Liu mtu -= t_hlen + (dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0); 322c5441932SPravin B Shelar 323b5476022SEric Dumazet if (mtu < IPV4_MIN_MTU) 324b5476022SEric Dumazet mtu = IPV4_MIN_MTU; 325c5441932SPravin B Shelar 326c5441932SPravin B Shelar return mtu; 327c5441932SPravin B Shelar } 328c5441932SPravin B Shelar 329c5441932SPravin B Shelar static struct ip_tunnel *ip_tunnel_create(struct net *net, 330c5441932SPravin B Shelar struct ip_tunnel_net *itn, 331117aef12SAlexander Lobakin struct ip_tunnel_parm_kern *parms) 332c5441932SPravin B Shelar { 3334929fd8cSJulia Lawall struct ip_tunnel *nt; 334c5441932SPravin B Shelar struct net_device *dev; 335b96f9afeSJarod Wilson int t_hlen; 336f6cc9c05SPetr Machata int mtu; 337f6cc9c05SPetr Machata int err; 338c5441932SPravin B Shelar 33979134e6cSEric Dumazet dev = __ip_tunnel_create(net, itn->rtnl_link_ops, parms); 340c5441932SPravin B Shelar if (IS_ERR(dev)) 3416dd3c9ecSFlorian Westphal return ERR_CAST(dev); 342c5441932SPravin B Shelar 343f6cc9c05SPetr Machata mtu = ip_tunnel_bind_dev(dev); 344f6cc9c05SPetr Machata err = dev_set_mtu(dev, mtu); 345f6cc9c05SPetr Machata if (err) 346f6cc9c05SPetr Machata goto err_dev_set_mtu; 347c5441932SPravin B Shelar 348c5441932SPravin B Shelar nt = netdev_priv(dev); 349b96f9afeSJarod Wilson t_hlen = nt->hlen + sizeof(struct iphdr); 350b96f9afeSJarod Wilson dev->min_mtu = ETH_MIN_MTU; 35128e104d0SVadim Fedorenko dev->max_mtu = IP_MAX_MTU - t_hlen; 3529992a078SHangbin Liu if (dev->type == ARPHRD_ETHER) 3539992a078SHangbin Liu dev->max_mtu -= dev->hard_header_len; 3549992a078SHangbin Liu 355c5441932SPravin B Shelar ip_tunnel_add(itn, nt); 356c5441932SPravin B Shelar return nt; 357f6cc9c05SPetr Machata 358f6cc9c05SPetr Machata err_dev_set_mtu: 359f6cc9c05SPetr Machata unregister_netdevice(dev); 360f6cc9c05SPetr Machata return ERR_PTR(err); 361c5441932SPravin B Shelar } 362c5441932SPravin B Shelar 363ac931d4cSChristian Ehrig void ip_tunnel_md_udp_encap(struct sk_buff *skb, struct ip_tunnel_info *info) 364ac931d4cSChristian Ehrig { 365ac931d4cSChristian Ehrig const struct iphdr *iph = ip_hdr(skb); 366ac931d4cSChristian Ehrig const struct udphdr *udph; 367ac931d4cSChristian Ehrig 368ac931d4cSChristian Ehrig if (iph->protocol != IPPROTO_UDP) 369ac931d4cSChristian Ehrig return; 370ac931d4cSChristian Ehrig 371ac931d4cSChristian Ehrig udph = (struct udphdr *)((__u8 *)iph + (iph->ihl << 2)); 372ac931d4cSChristian Ehrig info->encap.sport = udph->source; 373ac931d4cSChristian Ehrig info->encap.dport = udph->dest; 374ac931d4cSChristian Ehrig } 375ac931d4cSChristian Ehrig EXPORT_SYMBOL(ip_tunnel_md_udp_encap); 376ac931d4cSChristian Ehrig 377c5441932SPravin B Shelar int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, 3782e15ea39SPravin B Shelar const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst, 3792e15ea39SPravin B Shelar bool log_ecn_error) 380c5441932SPravin B Shelar { 381c5441932SPravin B Shelar const struct iphdr *iph = ip_hdr(skb); 382b0ec2abfSEric Dumazet int nh, err; 383c5441932SPravin B Shelar 384c5441932SPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 385c5441932SPravin B Shelar if (ipv4_is_multicast(iph->daddr)) { 386c4794d22SEric Dumazet DEV_STATS_INC(tunnel->dev, multicast); 387c5441932SPravin B Shelar skb->pkt_type = PACKET_BROADCAST; 388c5441932SPravin B Shelar } 389c5441932SPravin B Shelar #endif 390c5441932SPravin B Shelar 3915832c4a7SAlexander Lobakin if (test_bit(IP_TUNNEL_CSUM_BIT, tunnel->parms.i_flags) != 3925832c4a7SAlexander Lobakin test_bit(IP_TUNNEL_CSUM_BIT, tpi->flags)) { 393c4794d22SEric Dumazet DEV_STATS_INC(tunnel->dev, rx_crc_errors); 394c4794d22SEric Dumazet DEV_STATS_INC(tunnel->dev, rx_errors); 395c5441932SPravin B Shelar goto drop; 396c5441932SPravin B Shelar } 397c5441932SPravin B Shelar 3985832c4a7SAlexander Lobakin if (test_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.i_flags)) { 3995832c4a7SAlexander Lobakin if (!test_bit(IP_TUNNEL_SEQ_BIT, tpi->flags) || 400c5441932SPravin B Shelar (tunnel->i_seqno && (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) { 401c4794d22SEric Dumazet DEV_STATS_INC(tunnel->dev, rx_fifo_errors); 402c4794d22SEric Dumazet DEV_STATS_INC(tunnel->dev, rx_errors); 403c5441932SPravin B Shelar goto drop; 404c5441932SPravin B Shelar } 405c5441932SPravin B Shelar tunnel->i_seqno = ntohl(tpi->seq) + 1; 406c5441932SPravin B Shelar } 407c5441932SPravin B Shelar 408b0ec2abfSEric Dumazet /* Save offset of outer header relative to skb->head, 409b0ec2abfSEric Dumazet * because we are going to reset the network header to the inner header 410b0ec2abfSEric Dumazet * and might change skb->head. 411b0ec2abfSEric Dumazet */ 412b0ec2abfSEric Dumazet nh = skb_network_header(skb) - skb->head; 413b0ec2abfSEric Dumazet 414227adfb2SGilad Naaman skb_set_network_header(skb, (tunnel->dev->type == ARPHRD_ETHER) ? ETH_HLEN : 0); 415e96f2e7cSYing Cai 416b0ec2abfSEric Dumazet if (!pskb_inet_may_pull(skb)) { 417b0ec2abfSEric Dumazet DEV_STATS_INC(tunnel->dev, rx_length_errors); 418b0ec2abfSEric Dumazet DEV_STATS_INC(tunnel->dev, rx_errors); 419b0ec2abfSEric Dumazet goto drop; 420b0ec2abfSEric Dumazet } 421b0ec2abfSEric Dumazet iph = (struct iphdr *)(skb->head + nh); 422b0ec2abfSEric Dumazet 423c5441932SPravin B Shelar err = IP_ECN_decapsulate(iph, skb); 424c5441932SPravin B Shelar if (unlikely(err)) { 425c5441932SPravin B Shelar if (log_ecn_error) 426c5441932SPravin B Shelar net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", 427c5441932SPravin B Shelar &iph->saddr, iph->tos); 428c5441932SPravin B Shelar if (err > 1) { 429c4794d22SEric Dumazet DEV_STATS_INC(tunnel->dev, rx_frame_errors); 430c4794d22SEric Dumazet DEV_STATS_INC(tunnel->dev, rx_errors); 431c5441932SPravin B Shelar goto drop; 432c5441932SPravin B Shelar } 433c5441932SPravin B Shelar } 434c5441932SPravin B Shelar 435560b50cfSFabian Frederick dev_sw_netstats_rx_add(tunnel->dev, skb->len); 43681b9eab5SAlexei Starovoitov skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev))); 43781b9eab5SAlexei Starovoitov 4383d7b46cdSPravin B Shelar if (tunnel->dev->type == ARPHRD_ETHER) { 4393d7b46cdSPravin B Shelar skb->protocol = eth_type_trans(skb, tunnel->dev); 4403d7b46cdSPravin B Shelar skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); 4413d7b46cdSPravin B Shelar } else { 4423d7b46cdSPravin B Shelar skb->dev = tunnel->dev; 4433d7b46cdSPravin B Shelar } 44464261f23SNicolas Dichtel 4452e15ea39SPravin B Shelar if (tun_dst) 4462e15ea39SPravin B Shelar skb_dst_set(skb, (struct dst_entry *)tun_dst); 4472e15ea39SPravin B Shelar 448c5441932SPravin B Shelar gro_cells_receive(&tunnel->gro_cells, skb); 449c5441932SPravin B Shelar return 0; 450c5441932SPravin B Shelar 451c5441932SPravin B Shelar drop: 452469f87e1SHaishuang Yan if (tun_dst) 453469f87e1SHaishuang Yan dst_release((struct dst_entry *)tun_dst); 454c5441932SPravin B Shelar kfree_skb(skb); 455c5441932SPravin B Shelar return 0; 456c5441932SPravin B Shelar } 457c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_rcv); 458c5441932SPravin B Shelar 459a8c5f90fSTom Herbert int ip_tunnel_encap_add_ops(const struct ip_tunnel_encap_ops *ops, 460a8c5f90fSTom Herbert unsigned int num) 461a8c5f90fSTom Herbert { 462bb1553c8SThomas Graf if (num >= MAX_IPTUN_ENCAP_OPS) 463bb1553c8SThomas Graf return -ERANGE; 464bb1553c8SThomas Graf 465a8c5f90fSTom Herbert return !cmpxchg((const struct ip_tunnel_encap_ops **) 466a8c5f90fSTom Herbert &iptun_encaps[num], 467a8c5f90fSTom Herbert NULL, ops) ? 0 : -1; 46856328486STom Herbert } 469a8c5f90fSTom Herbert EXPORT_SYMBOL(ip_tunnel_encap_add_ops); 470a8c5f90fSTom Herbert 471a8c5f90fSTom Herbert int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *ops, 472a8c5f90fSTom Herbert unsigned int num) 473a8c5f90fSTom Herbert { 474a8c5f90fSTom Herbert int ret; 475a8c5f90fSTom Herbert 476bb1553c8SThomas Graf if (num >= MAX_IPTUN_ENCAP_OPS) 477bb1553c8SThomas Graf return -ERANGE; 478bb1553c8SThomas Graf 479a8c5f90fSTom Herbert ret = (cmpxchg((const struct ip_tunnel_encap_ops **) 480a8c5f90fSTom Herbert &iptun_encaps[num], 481a8c5f90fSTom Herbert ops, NULL) == ops) ? 0 : -1; 482a8c5f90fSTom Herbert 483a8c5f90fSTom Herbert synchronize_net(); 484a8c5f90fSTom Herbert 485a8c5f90fSTom Herbert return ret; 486a8c5f90fSTom Herbert } 487a8c5f90fSTom Herbert EXPORT_SYMBOL(ip_tunnel_encap_del_ops); 48856328486STom Herbert 48956328486STom Herbert int ip_tunnel_encap_setup(struct ip_tunnel *t, 49056328486STom Herbert struct ip_tunnel_encap *ipencap) 49156328486STom Herbert { 49256328486STom Herbert int hlen; 49356328486STom Herbert 49456328486STom Herbert memset(&t->encap, 0, sizeof(t->encap)); 49556328486STom Herbert 49656328486STom Herbert hlen = ip_encap_hlen(ipencap); 49756328486STom Herbert if (hlen < 0) 49856328486STom Herbert return hlen; 49956328486STom Herbert 50056328486STom Herbert t->encap.type = ipencap->type; 50156328486STom Herbert t->encap.sport = ipencap->sport; 50256328486STom Herbert t->encap.dport = ipencap->dport; 50356328486STom Herbert t->encap.flags = ipencap->flags; 50456328486STom Herbert 50556328486STom Herbert t->encap_hlen = hlen; 50656328486STom Herbert t->hlen = t->encap_hlen + t->tun_hlen; 50756328486STom Herbert 50856328486STom Herbert return 0; 50956328486STom Herbert } 51056328486STom Herbert EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup); 51156328486STom Herbert 51223a3647bSPravin B Shelar static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, 513fc24f2b2STimo Teräs struct rtable *rt, __be16 df, 514c8b34e68Swenxu const struct iphdr *inner_iph, 515c8b34e68Swenxu int tunnel_hlen, __be32 dst, bool md) 51623a3647bSPravin B Shelar { 51723a3647bSPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 518c8b34e68Swenxu int pkt_size; 51923a3647bSPravin B Shelar int mtu; 52023a3647bSPravin B Shelar 521c8b34e68Swenxu tunnel_hlen = md ? tunnel_hlen : tunnel->hlen; 52228e104d0SVadim Fedorenko pkt_size = skb->len - tunnel_hlen; 5239992a078SHangbin Liu pkt_size -= dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0; 524c8b34e68Swenxu 5259992a078SHangbin Liu if (df) { 52628e104d0SVadim Fedorenko mtu = dst_mtu(&rt->dst) - (sizeof(struct iphdr) + tunnel_hlen); 5279992a078SHangbin Liu mtu -= dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0; 5289992a078SHangbin Liu } else { 529f4b3ec4eSAlan Maguire mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; 5309992a078SHangbin Liu } 53123a3647bSPravin B Shelar 532f4b3ec4eSAlan Maguire if (skb_valid_dst(skb)) 5337a1592bcSHangbin Liu skb_dst_update_pmtu_no_confirm(skb, mtu); 53423a3647bSPravin B Shelar 53523a3647bSPravin B Shelar if (skb->protocol == htons(ETH_P_IP)) { 53623a3647bSPravin B Shelar if (!skb_is_gso(skb) && 537fc24f2b2STimo Teräs (inner_iph->frag_off & htons(IP_DF)) && 538fc24f2b2STimo Teräs mtu < pkt_size) { 5394372339eSJason A. Donenfeld icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); 54023a3647bSPravin B Shelar return -E2BIG; 54123a3647bSPravin B Shelar } 54223a3647bSPravin B Shelar } 54323a3647bSPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 54423a3647bSPravin B Shelar else if (skb->protocol == htons(ETH_P_IPV6)) { 545f4b3ec4eSAlan Maguire struct rt6_info *rt6; 546c8b34e68Swenxu __be32 daddr; 547c8b34e68Swenxu 548e8dfd42cSEric Dumazet rt6 = skb_valid_dst(skb) ? dst_rt6_info(skb_dst(skb)) : 549f4b3ec4eSAlan Maguire NULL; 550c8b34e68Swenxu daddr = md ? dst : tunnel->parms.iph.daddr; 55123a3647bSPravin B Shelar 55223a3647bSPravin B Shelar if (rt6 && mtu < dst_mtu(skb_dst(skb)) && 55323a3647bSPravin B Shelar mtu >= IPV6_MIN_MTU) { 554c8b34e68Swenxu if ((daddr && !ipv4_is_multicast(daddr)) || 55523a3647bSPravin B Shelar rt6->rt6i_dst.plen == 128) { 55623a3647bSPravin B Shelar rt6->rt6i_flags |= RTF_MODIFIED; 55723a3647bSPravin B Shelar dst_metric_set(skb_dst(skb), RTAX_MTU, mtu); 55823a3647bSPravin B Shelar } 55923a3647bSPravin B Shelar } 56023a3647bSPravin B Shelar 56123a3647bSPravin B Shelar if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU && 56223a3647bSPravin B Shelar mtu < pkt_size) { 5634372339eSJason A. Donenfeld icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); 56423a3647bSPravin B Shelar return -E2BIG; 56523a3647bSPravin B Shelar } 56623a3647bSPravin B Shelar } 56723a3647bSPravin B Shelar #endif 56823a3647bSPravin B Shelar return 0; 56923a3647bSPravin B Shelar } 57023a3647bSPravin B Shelar 5715ae1e992SFlorian Westphal static void ip_tunnel_adj_headroom(struct net_device *dev, unsigned int headroom) 5725ae1e992SFlorian Westphal { 5735ae1e992SFlorian Westphal /* we must cap headroom to some upperlimit, else pskb_expand_head 5745ae1e992SFlorian Westphal * will overflow header offsets in skb_headers_offset_update(). 5755ae1e992SFlorian Westphal */ 5765ae1e992SFlorian Westphal static const unsigned int max_allowed = 512; 5775ae1e992SFlorian Westphal 5785ae1e992SFlorian Westphal if (headroom > max_allowed) 5795ae1e992SFlorian Westphal headroom = max_allowed; 5805ae1e992SFlorian Westphal 5815ae1e992SFlorian Westphal if (headroom > READ_ONCE(dev->needed_headroom)) 5825ae1e992SFlorian Westphal WRITE_ONCE(dev->needed_headroom, headroom); 5835ae1e992SFlorian Westphal } 5845ae1e992SFlorian Westphal 585c8b34e68Swenxu void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, 586c8b34e68Swenxu u8 proto, int tunnel_hlen) 587cfc7381bSAlexei Starovoitov { 588cfc7381bSAlexei Starovoitov struct ip_tunnel *tunnel = netdev_priv(dev); 589cfc7381bSAlexei Starovoitov u32 headroom = sizeof(struct iphdr); 590cfc7381bSAlexei Starovoitov struct ip_tunnel_info *tun_info; 591cfc7381bSAlexei Starovoitov const struct ip_tunnel_key *key; 592cfc7381bSAlexei Starovoitov const struct iphdr *inner_iph; 593f46fe4f8Swenxu struct rtable *rt = NULL; 594cfc7381bSAlexei Starovoitov struct flowi4 fl4; 595cfc7381bSAlexei Starovoitov __be16 df = 0; 596cfc7381bSAlexei Starovoitov u8 tos, ttl; 597f46fe4f8Swenxu bool use_cache; 598cfc7381bSAlexei Starovoitov 599cfc7381bSAlexei Starovoitov tun_info = skb_tunnel_info(skb); 600cfc7381bSAlexei Starovoitov if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 601cfc7381bSAlexei Starovoitov ip_tunnel_info_af(tun_info) != AF_INET)) 602cfc7381bSAlexei Starovoitov goto tx_error; 603cfc7381bSAlexei Starovoitov key = &tun_info->key; 604cfc7381bSAlexei Starovoitov memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 605cfc7381bSAlexei Starovoitov inner_iph = (const struct iphdr *)skb_inner_network_header(skb); 606cfc7381bSAlexei Starovoitov tos = key->tos; 607cfc7381bSAlexei Starovoitov if (tos == 1) { 608cfc7381bSAlexei Starovoitov if (skb->protocol == htons(ETH_P_IP)) 609cfc7381bSAlexei Starovoitov tos = inner_iph->tos; 610cfc7381bSAlexei Starovoitov else if (skb->protocol == htons(ETH_P_IPV6)) 611cfc7381bSAlexei Starovoitov tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); 612cfc7381bSAlexei Starovoitov } 6136e6b904aSwenxu ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src, 614c34cfe72SIdo Schimmel tunnel_id_to_key32(key->tun_id), 615b5a7b661SXiao Liang tos & INET_DSCP_MASK, tunnel->net, 0, skb->mark, 616c34cfe72SIdo Schimmel skb_get_hash(skb), key->flow_flags); 617ac931d4cSChristian Ehrig 618ac931d4cSChristian Ehrig if (!tunnel_hlen) 619ac931d4cSChristian Ehrig tunnel_hlen = ip_encap_hlen(&tun_info->encap); 620ac931d4cSChristian Ehrig 621ac931d4cSChristian Ehrig if (ip_tunnel_encap(skb, &tun_info->encap, &proto, &fl4) < 0) 622cfc7381bSAlexei Starovoitov goto tx_error; 623f46fe4f8Swenxu 624f46fe4f8Swenxu use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); 625f46fe4f8Swenxu if (use_cache) 626f46fe4f8Swenxu rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl4.saddr); 627f46fe4f8Swenxu if (!rt) { 628cfc7381bSAlexei Starovoitov rt = ip_route_output_key(tunnel->net, &fl4); 629cfc7381bSAlexei Starovoitov if (IS_ERR(rt)) { 630c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_carrier_errors); 631cfc7381bSAlexei Starovoitov goto tx_error; 632cfc7381bSAlexei Starovoitov } 633f46fe4f8Swenxu if (use_cache) 634f46fe4f8Swenxu dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, 635f46fe4f8Swenxu fl4.saddr); 636f46fe4f8Swenxu } 637cfc7381bSAlexei Starovoitov if (rt->dst.dev == dev) { 638cfc7381bSAlexei Starovoitov ip_rt_put(rt); 639c4794d22SEric Dumazet DEV_STATS_INC(dev, collisions); 640cfc7381bSAlexei Starovoitov goto tx_error; 641cfc7381bSAlexei Starovoitov } 642c8b34e68Swenxu 6435832c4a7SAlexander Lobakin if (test_bit(IP_TUNNEL_DONT_FRAGMENT_BIT, key->tun_flags)) 644c8b34e68Swenxu df = htons(IP_DF); 645c8b34e68Swenxu if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, tunnel_hlen, 646c8b34e68Swenxu key->u.ipv4.dst, true)) { 647c8b34e68Swenxu ip_rt_put(rt); 648c8b34e68Swenxu goto tx_error; 649c8b34e68Swenxu } 650c8b34e68Swenxu 651cfc7381bSAlexei Starovoitov tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); 652cfc7381bSAlexei Starovoitov ttl = key->ttl; 653cfc7381bSAlexei Starovoitov if (ttl == 0) { 654cfc7381bSAlexei Starovoitov if (skb->protocol == htons(ETH_P_IP)) 655cfc7381bSAlexei Starovoitov ttl = inner_iph->ttl; 656cfc7381bSAlexei Starovoitov else if (skb->protocol == htons(ETH_P_IPV6)) 657cfc7381bSAlexei Starovoitov ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit; 658cfc7381bSAlexei Starovoitov else 659cfc7381bSAlexei Starovoitov ttl = ip4_dst_hoplimit(&rt->dst); 660cfc7381bSAlexei Starovoitov } 661c8b34e68Swenxu 662cfc7381bSAlexei Starovoitov headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len; 6635ae1e992SFlorian Westphal if (skb_cow_head(skb, headroom)) { 664cfc7381bSAlexei Starovoitov ip_rt_put(rt); 665cfc7381bSAlexei Starovoitov goto tx_dropped; 666cfc7381bSAlexei Starovoitov } 6675ae1e992SFlorian Westphal 6685ae1e992SFlorian Westphal ip_tunnel_adj_headroom(dev, headroom); 6695ae1e992SFlorian Westphal 6700f693f19SHaishuang Yan iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, proto, tos, ttl, 6710f693f19SHaishuang Yan df, !net_eq(tunnel->net, dev_net(dev))); 672cfc7381bSAlexei Starovoitov return; 673cfc7381bSAlexei Starovoitov tx_error: 674c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_errors); 675cfc7381bSAlexei Starovoitov goto kfree; 676cfc7381bSAlexei Starovoitov tx_dropped: 677c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_dropped); 678cfc7381bSAlexei Starovoitov kfree: 679cfc7381bSAlexei Starovoitov kfree_skb(skb); 680cfc7381bSAlexei Starovoitov } 681cfc7381bSAlexei Starovoitov EXPORT_SYMBOL_GPL(ip_md_tunnel_xmit); 682cfc7381bSAlexei Starovoitov 683c5441932SPravin B Shelar void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, 68456328486STom Herbert const struct iphdr *tnl_params, u8 protocol) 685c5441932SPravin B Shelar { 686c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 687186d9366Swenxu struct ip_tunnel_info *tun_info = NULL; 688c5441932SPravin B Shelar const struct iphdr *inner_iph; 689c5441932SPravin B Shelar unsigned int max_headroom; /* The extra header space needed */ 690186d9366Swenxu struct rtable *rt = NULL; /* Route to the other host */ 6917ae29fd1SMatthias May __be16 payload_protocol; 692186d9366Swenxu bool use_cache = false; 693186d9366Swenxu struct flowi4 fl4; 694186d9366Swenxu bool md = false; 69522fb22eaSTimo Teräs bool connected; 696186d9366Swenxu u8 tos, ttl; 697186d9366Swenxu __be32 dst; 698186d9366Swenxu __be16 df; 699c5441932SPravin B Shelar 700c5441932SPravin B Shelar inner_iph = (const struct iphdr *)skb_inner_network_header(skb); 70122fb22eaSTimo Teräs connected = (tunnel->parms.iph.daddr != 0); 7027ae29fd1SMatthias May payload_protocol = skb_protocol(skb, true); 703c5441932SPravin B Shelar 7045146d1f1SBernie Harris memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 7055146d1f1SBernie Harris 706c5441932SPravin B Shelar dst = tnl_params->daddr; 707c5441932SPravin B Shelar if (dst == 0) { 708c5441932SPravin B Shelar /* NBMA tunnel */ 709c5441932SPravin B Shelar 71051456b29SIan Morris if (!skb_dst(skb)) { 711c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_fifo_errors); 712c5441932SPravin B Shelar goto tx_error; 713c5441932SPravin B Shelar } 714c5441932SPravin B Shelar 715d71b5753Swenxu tun_info = skb_tunnel_info(skb); 716d71b5753Swenxu if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) && 717d71b5753Swenxu ip_tunnel_info_af(tun_info) == AF_INET && 718186d9366Swenxu tun_info->key.u.ipv4.dst) { 719d71b5753Swenxu dst = tun_info->key.u.ipv4.dst; 720186d9366Swenxu md = true; 721186d9366Swenxu connected = true; 7227ae29fd1SMatthias May } else if (payload_protocol == htons(ETH_P_IP)) { 723c5441932SPravin B Shelar rt = skb_rtable(skb); 724c5441932SPravin B Shelar dst = rt_nexthop(rt, inner_iph->daddr); 725c5441932SPravin B Shelar } 726c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 7277ae29fd1SMatthias May else if (payload_protocol == htons(ETH_P_IPV6)) { 728c5441932SPravin B Shelar const struct in6_addr *addr6; 729c5441932SPravin B Shelar struct neighbour *neigh; 730c5441932SPravin B Shelar bool do_tx_error_icmp; 731c5441932SPravin B Shelar int addr_type; 732c5441932SPravin B Shelar 733c5441932SPravin B Shelar neigh = dst_neigh_lookup(skb_dst(skb), 734c5441932SPravin B Shelar &ipv6_hdr(skb)->daddr); 73551456b29SIan Morris if (!neigh) 736c5441932SPravin B Shelar goto tx_error; 737c5441932SPravin B Shelar 738c5441932SPravin B Shelar addr6 = (const struct in6_addr *)&neigh->primary_key; 739c5441932SPravin B Shelar addr_type = ipv6_addr_type(addr6); 740c5441932SPravin B Shelar 741c5441932SPravin B Shelar if (addr_type == IPV6_ADDR_ANY) { 742c5441932SPravin B Shelar addr6 = &ipv6_hdr(skb)->daddr; 743c5441932SPravin B Shelar addr_type = ipv6_addr_type(addr6); 744c5441932SPravin B Shelar } 745c5441932SPravin B Shelar 746c5441932SPravin B Shelar if ((addr_type & IPV6_ADDR_COMPATv4) == 0) 747c5441932SPravin B Shelar do_tx_error_icmp = true; 748c5441932SPravin B Shelar else { 749c5441932SPravin B Shelar do_tx_error_icmp = false; 750c5441932SPravin B Shelar dst = addr6->s6_addr32[3]; 751c5441932SPravin B Shelar } 752c5441932SPravin B Shelar neigh_release(neigh); 753c5441932SPravin B Shelar if (do_tx_error_icmp) 754c5441932SPravin B Shelar goto tx_error_icmp; 755c5441932SPravin B Shelar } 756c5441932SPravin B Shelar #endif 757c5441932SPravin B Shelar else 758c5441932SPravin B Shelar goto tx_error; 7597d442fabSTom Herbert 760186d9366Swenxu if (!md) 7617d442fabSTom Herbert connected = false; 762c5441932SPravin B Shelar } 763c5441932SPravin B Shelar 764c5441932SPravin B Shelar tos = tnl_params->tos; 765c5441932SPravin B Shelar if (tos & 0x1) { 766c5441932SPravin B Shelar tos &= ~0x1; 7677ae29fd1SMatthias May if (payload_protocol == htons(ETH_P_IP)) { 768c5441932SPravin B Shelar tos = inner_iph->tos; 7697d442fabSTom Herbert connected = false; 7707ae29fd1SMatthias May } else if (payload_protocol == htons(ETH_P_IPV6)) { 771c5441932SPravin B Shelar tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); 7727d442fabSTom Herbert connected = false; 7737d442fabSTom Herbert } 774c5441932SPravin B Shelar } 775c5441932SPravin B Shelar 776b0066da5SPetr Machata ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr, 777c2b639f9SIdo Schimmel tunnel->parms.o_key, tos & INET_DSCP_MASK, 778b5a7b661SXiao Liang tunnel->net, READ_ONCE(tunnel->parms.link), 7797ec9fce4SEyal Birger tunnel->fwmark, skb_get_hash(skb), 0); 7807d442fabSTom Herbert 781ac931d4cSChristian Ehrig if (ip_tunnel_encap(skb, &tunnel->encap, &protocol, &fl4) < 0) 78256328486STom Herbert goto tx_error; 78356328486STom Herbert 784186d9366Swenxu if (connected && md) { 785186d9366Swenxu use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); 786186d9366Swenxu if (use_cache) 787186d9366Swenxu rt = dst_cache_get_ip4(&tun_info->dst_cache, 788186d9366Swenxu &fl4.saddr); 789186d9366Swenxu } else { 790186d9366Swenxu rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache, 791186d9366Swenxu &fl4.saddr) : NULL; 792186d9366Swenxu } 7937d442fabSTom Herbert 7947d442fabSTom Herbert if (!rt) { 7957d442fabSTom Herbert rt = ip_route_output_key(tunnel->net, &fl4); 7967d442fabSTom Herbert 797c5441932SPravin B Shelar if (IS_ERR(rt)) { 798c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_carrier_errors); 799c5441932SPravin B Shelar goto tx_error; 800c5441932SPravin B Shelar } 801186d9366Swenxu if (use_cache) 802186d9366Swenxu dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, 803186d9366Swenxu fl4.saddr); 804186d9366Swenxu else if (!md && connected) 805e09acddfSPaolo Abeni dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, 806e09acddfSPaolo Abeni fl4.saddr); 8077d442fabSTom Herbert } 8087d442fabSTom Herbert 8090e6fbc5bSPravin B Shelar if (rt->dst.dev == dev) { 810c5441932SPravin B Shelar ip_rt_put(rt); 811c4794d22SEric Dumazet DEV_STATS_INC(dev, collisions); 812c5441932SPravin B Shelar goto tx_error; 813c5441932SPravin B Shelar } 814c5441932SPravin B Shelar 81550c66167SFlorian Westphal df = tnl_params->frag_off; 8167ae29fd1SMatthias May if (payload_protocol == htons(ETH_P_IP) && !tunnel->ignore_df) 81750c66167SFlorian Westphal df |= (inner_iph->frag_off & htons(IP_DF)); 81850c66167SFlorian Westphal 81950c66167SFlorian Westphal if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, 0, 0, false)) { 820c5441932SPravin B Shelar ip_rt_put(rt); 821c5441932SPravin B Shelar goto tx_error; 822c5441932SPravin B Shelar } 823c5441932SPravin B Shelar 824c5441932SPravin B Shelar if (tunnel->err_count > 0) { 825c5441932SPravin B Shelar if (time_before(jiffies, 826c5441932SPravin B Shelar tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { 827c5441932SPravin B Shelar tunnel->err_count--; 828c5441932SPravin B Shelar 829c5441932SPravin B Shelar dst_link_failure(skb); 830c5441932SPravin B Shelar } else 831c5441932SPravin B Shelar tunnel->err_count = 0; 832c5441932SPravin B Shelar } 833c5441932SPravin B Shelar 834d4a71b15SPravin B Shelar tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); 835c5441932SPravin B Shelar ttl = tnl_params->ttl; 836c5441932SPravin B Shelar if (ttl == 0) { 8377ae29fd1SMatthias May if (payload_protocol == htons(ETH_P_IP)) 838c5441932SPravin B Shelar ttl = inner_iph->ttl; 839c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 8407ae29fd1SMatthias May else if (payload_protocol == htons(ETH_P_IPV6)) 841c5441932SPravin B Shelar ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit; 842c5441932SPravin B Shelar #endif 843c5441932SPravin B Shelar else 844c5441932SPravin B Shelar ttl = ip4_dst_hoplimit(&rt->dst); 845c5441932SPravin B Shelar } 846c5441932SPravin B Shelar 8470e6fbc5bSPravin B Shelar max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr) 8487371e022STom Herbert + rt->dst.header_len + ip_encap_hlen(&tunnel->encap); 8493e08f4a7SSteffen Klassert 8505ae1e992SFlorian Westphal if (skb_cow_head(skb, max_headroom)) { 851586d5fc8SDmitry Popov ip_rt_put(rt); 852c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_dropped); 8533acfa1e7SEric Dumazet kfree_skb(skb); 854c5441932SPravin B Shelar return; 855c5441932SPravin B Shelar } 856c5441932SPravin B Shelar 8575ae1e992SFlorian Westphal ip_tunnel_adj_headroom(dev, max_headroom); 8585ae1e992SFlorian Westphal 859039f5062SPravin B Shelar iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl, 860039f5062SPravin B Shelar df, !net_eq(tunnel->net, dev_net(dev))); 861c5441932SPravin B Shelar return; 862c5441932SPravin B Shelar 863c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 864c5441932SPravin B Shelar tx_error_icmp: 865c5441932SPravin B Shelar dst_link_failure(skb); 866c5441932SPravin B Shelar #endif 867c5441932SPravin B Shelar tx_error: 868c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_errors); 8693acfa1e7SEric Dumazet kfree_skb(skb); 870c5441932SPravin B Shelar } 871c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_xmit); 872c5441932SPravin B Shelar 873c5441932SPravin B Shelar static void ip_tunnel_update(struct ip_tunnel_net *itn, 874c5441932SPravin B Shelar struct ip_tunnel *t, 875c5441932SPravin B Shelar struct net_device *dev, 876117aef12SAlexander Lobakin struct ip_tunnel_parm_kern *p, 8779830ad4cSCraig Gallek bool set_mtu, 8789830ad4cSCraig Gallek __u32 fwmark) 879c5441932SPravin B Shelar { 8802e15ea39SPravin B Shelar ip_tunnel_del(itn, t); 881c5441932SPravin B Shelar t->parms.iph.saddr = p->iph.saddr; 882c5441932SPravin B Shelar t->parms.iph.daddr = p->iph.daddr; 883c5441932SPravin B Shelar t->parms.i_key = p->i_key; 884c5441932SPravin B Shelar t->parms.o_key = p->o_key; 885c5441932SPravin B Shelar if (dev->type != ARPHRD_ETHER) { 8865a1b7e1aSJakub Kicinski __dev_addr_set(dev, &p->iph.saddr, 4); 887c5441932SPravin B Shelar memcpy(dev->broadcast, &p->iph.daddr, 4); 888c5441932SPravin B Shelar } 889c5441932SPravin B Shelar ip_tunnel_add(itn, t); 890c5441932SPravin B Shelar 891c5441932SPravin B Shelar t->parms.iph.ttl = p->iph.ttl; 892c5441932SPravin B Shelar t->parms.iph.tos = p->iph.tos; 893c5441932SPravin B Shelar t->parms.iph.frag_off = p->iph.frag_off; 894c5441932SPravin B Shelar 8959830ad4cSCraig Gallek if (t->parms.link != p->link || t->fwmark != fwmark) { 896c5441932SPravin B Shelar int mtu; 897c5441932SPravin B Shelar 898f694eee9SEric Dumazet WRITE_ONCE(t->parms.link, p->link); 8999830ad4cSCraig Gallek t->fwmark = fwmark; 900c5441932SPravin B Shelar mtu = ip_tunnel_bind_dev(dev); 901c5441932SPravin B Shelar if (set_mtu) 9021eb2cdedSEric Dumazet WRITE_ONCE(dev->mtu, mtu); 903c5441932SPravin B Shelar } 904e09acddfSPaolo Abeni dst_cache_reset(&t->dst_cache); 905c5441932SPravin B Shelar netdev_state_change(dev); 906c5441932SPravin B Shelar } 907c5441932SPravin B Shelar 908117aef12SAlexander Lobakin int ip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm_kern *p, 909117aef12SAlexander Lobakin int cmd) 910c5441932SPravin B Shelar { 911c5441932SPravin B Shelar int err = 0; 9128c923ce2SNicolas Dichtel struct ip_tunnel *t = netdev_priv(dev); 9138c923ce2SNicolas Dichtel struct net *net = t->net; 9148c923ce2SNicolas Dichtel struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id); 915c5441932SPravin B Shelar 916c5441932SPravin B Shelar switch (cmd) { 917c5441932SPravin B Shelar case SIOCGETTUNNEL: 9188c923ce2SNicolas Dichtel if (dev == itn->fb_tunnel_dev) { 919c5441932SPravin B Shelar t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); 92051456b29SIan Morris if (!t) 921c5441932SPravin B Shelar t = netdev_priv(dev); 9228c923ce2SNicolas Dichtel } 923c5441932SPravin B Shelar memcpy(p, &t->parms, sizeof(*p)); 924c5441932SPravin B Shelar break; 925c5441932SPravin B Shelar 926c5441932SPravin B Shelar case SIOCADDTUNNEL: 927c5441932SPravin B Shelar case SIOCCHGTUNNEL: 928c5441932SPravin B Shelar err = -EPERM; 929c5441932SPravin B Shelar if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 930c5441932SPravin B Shelar goto done; 931c5441932SPravin B Shelar if (p->iph.ttl) 932c5441932SPravin B Shelar p->iph.frag_off |= htons(IP_DF); 9335832c4a7SAlexander Lobakin if (!test_bit(IP_TUNNEL_VTI_BIT, p->i_flags)) { 9345832c4a7SAlexander Lobakin if (!test_bit(IP_TUNNEL_KEY_BIT, p->i_flags)) 935c5441932SPravin B Shelar p->i_key = 0; 9365832c4a7SAlexander Lobakin if (!test_bit(IP_TUNNEL_KEY_BIT, p->o_flags)) 937c5441932SPravin B Shelar p->o_key = 0; 9387c8e6b9cSDmitry Popov } 939c5441932SPravin B Shelar 94079134e6cSEric Dumazet t = ip_tunnel_find(itn, p, itn->type); 941c5441932SPravin B Shelar 942d61746b2SSteffen Klassert if (cmd == SIOCADDTUNNEL) { 943d61746b2SSteffen Klassert if (!t) { 944c5441932SPravin B Shelar t = ip_tunnel_create(net, itn, p); 945ee30ef4dSDuan Jiong err = PTR_ERR_OR_ZERO(t); 9466dd3c9ecSFlorian Westphal break; 9476dd3c9ecSFlorian Westphal } 948d61746b2SSteffen Klassert 949d61746b2SSteffen Klassert err = -EEXIST; 950d61746b2SSteffen Klassert break; 951d61746b2SSteffen Klassert } 952c5441932SPravin B Shelar if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { 95300db4124SIan Morris if (t) { 954c5441932SPravin B Shelar if (t->dev != dev) { 955c5441932SPravin B Shelar err = -EEXIST; 956c5441932SPravin B Shelar break; 957c5441932SPravin B Shelar } 958c5441932SPravin B Shelar } else { 959c5441932SPravin B Shelar unsigned int nflags = 0; 960c5441932SPravin B Shelar 961c5441932SPravin B Shelar if (ipv4_is_multicast(p->iph.daddr)) 962c5441932SPravin B Shelar nflags = IFF_BROADCAST; 963c5441932SPravin B Shelar else if (p->iph.daddr) 964c5441932SPravin B Shelar nflags = IFF_POINTOPOINT; 965c5441932SPravin B Shelar 966c5441932SPravin B Shelar if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) { 967c5441932SPravin B Shelar err = -EINVAL; 968c5441932SPravin B Shelar break; 969c5441932SPravin B Shelar } 970c5441932SPravin B Shelar 971c5441932SPravin B Shelar t = netdev_priv(dev); 972c5441932SPravin B Shelar } 973c5441932SPravin B Shelar } 974c5441932SPravin B Shelar 975c5441932SPravin B Shelar if (t) { 976c5441932SPravin B Shelar err = 0; 9779830ad4cSCraig Gallek ip_tunnel_update(itn, t, dev, p, true, 0); 9786dd3c9ecSFlorian Westphal } else { 9796dd3c9ecSFlorian Westphal err = -ENOENT; 9806dd3c9ecSFlorian Westphal } 981c5441932SPravin B Shelar break; 982c5441932SPravin B Shelar 983c5441932SPravin B Shelar case SIOCDELTUNNEL: 984c5441932SPravin B Shelar err = -EPERM; 985c5441932SPravin B Shelar if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 986c5441932SPravin B Shelar goto done; 987c5441932SPravin B Shelar 988c5441932SPravin B Shelar if (dev == itn->fb_tunnel_dev) { 989c5441932SPravin B Shelar err = -ENOENT; 990c5441932SPravin B Shelar t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); 99151456b29SIan Morris if (!t) 992c5441932SPravin B Shelar goto done; 993c5441932SPravin B Shelar err = -EPERM; 994c5441932SPravin B Shelar if (t == netdev_priv(itn->fb_tunnel_dev)) 995c5441932SPravin B Shelar goto done; 996c5441932SPravin B Shelar dev = t->dev; 997c5441932SPravin B Shelar } 998c5441932SPravin B Shelar unregister_netdevice(dev); 999c5441932SPravin B Shelar err = 0; 1000c5441932SPravin B Shelar break; 1001c5441932SPravin B Shelar 1002c5441932SPravin B Shelar default: 1003c5441932SPravin B Shelar err = -EINVAL; 1004c5441932SPravin B Shelar } 1005c5441932SPravin B Shelar 1006c5441932SPravin B Shelar done: 1007c5441932SPravin B Shelar return err; 1008c5441932SPravin B Shelar } 1009607259a6SChristoph Hellwig EXPORT_SYMBOL_GPL(ip_tunnel_ctl); 1010607259a6SChristoph Hellwig 1011117aef12SAlexander Lobakin bool ip_tunnel_parm_from_user(struct ip_tunnel_parm_kern *kp, 1012117aef12SAlexander Lobakin const void __user *data) 1013117aef12SAlexander Lobakin { 1014117aef12SAlexander Lobakin struct ip_tunnel_parm p; 1015117aef12SAlexander Lobakin 1016117aef12SAlexander Lobakin if (copy_from_user(&p, data, sizeof(p))) 1017117aef12SAlexander Lobakin return false; 1018117aef12SAlexander Lobakin 1019117aef12SAlexander Lobakin strscpy(kp->name, p.name); 1020117aef12SAlexander Lobakin kp->link = p.link; 10215832c4a7SAlexander Lobakin ip_tunnel_flags_from_be16(kp->i_flags, p.i_flags); 10225832c4a7SAlexander Lobakin ip_tunnel_flags_from_be16(kp->o_flags, p.o_flags); 1023117aef12SAlexander Lobakin kp->i_key = p.i_key; 1024117aef12SAlexander Lobakin kp->o_key = p.o_key; 1025117aef12SAlexander Lobakin memcpy(&kp->iph, &p.iph, min(sizeof(kp->iph), sizeof(p.iph))); 1026117aef12SAlexander Lobakin 1027117aef12SAlexander Lobakin return true; 1028117aef12SAlexander Lobakin } 1029117aef12SAlexander Lobakin EXPORT_SYMBOL_GPL(ip_tunnel_parm_from_user); 1030117aef12SAlexander Lobakin 1031117aef12SAlexander Lobakin bool ip_tunnel_parm_to_user(void __user *data, struct ip_tunnel_parm_kern *kp) 1032117aef12SAlexander Lobakin { 1033117aef12SAlexander Lobakin struct ip_tunnel_parm p; 1034117aef12SAlexander Lobakin 10355832c4a7SAlexander Lobakin if (!ip_tunnel_flags_is_be16_compat(kp->i_flags) || 10365832c4a7SAlexander Lobakin !ip_tunnel_flags_is_be16_compat(kp->o_flags)) 10375832c4a7SAlexander Lobakin return false; 10385832c4a7SAlexander Lobakin 10395a66cda5SAlexander Lobakin memset(&p, 0, sizeof(p)); 10405a66cda5SAlexander Lobakin 1041117aef12SAlexander Lobakin strscpy(p.name, kp->name); 1042117aef12SAlexander Lobakin p.link = kp->link; 10435832c4a7SAlexander Lobakin p.i_flags = ip_tunnel_flags_to_be16(kp->i_flags); 10445832c4a7SAlexander Lobakin p.o_flags = ip_tunnel_flags_to_be16(kp->o_flags); 1045117aef12SAlexander Lobakin p.i_key = kp->i_key; 1046117aef12SAlexander Lobakin p.o_key = kp->o_key; 1047117aef12SAlexander Lobakin memcpy(&p.iph, &kp->iph, min(sizeof(p.iph), sizeof(kp->iph))); 1048117aef12SAlexander Lobakin 1049117aef12SAlexander Lobakin return !copy_to_user(data, &p, sizeof(p)); 1050117aef12SAlexander Lobakin } 1051117aef12SAlexander Lobakin EXPORT_SYMBOL_GPL(ip_tunnel_parm_to_user); 1052117aef12SAlexander Lobakin 10533e7a1c7cSArnd Bergmann int ip_tunnel_siocdevprivate(struct net_device *dev, struct ifreq *ifr, 10543e7a1c7cSArnd Bergmann void __user *data, int cmd) 1055607259a6SChristoph Hellwig { 1056117aef12SAlexander Lobakin struct ip_tunnel_parm_kern p; 1057607259a6SChristoph Hellwig int err; 1058607259a6SChristoph Hellwig 1059117aef12SAlexander Lobakin if (!ip_tunnel_parm_from_user(&p, data)) 1060607259a6SChristoph Hellwig return -EFAULT; 1061607259a6SChristoph Hellwig err = dev->netdev_ops->ndo_tunnel_ctl(dev, &p, cmd); 1062117aef12SAlexander Lobakin if (!err && !ip_tunnel_parm_to_user(data, &p)) 1063607259a6SChristoph Hellwig return -EFAULT; 1064607259a6SChristoph Hellwig return err; 1065607259a6SChristoph Hellwig } 10663e7a1c7cSArnd Bergmann EXPORT_SYMBOL_GPL(ip_tunnel_siocdevprivate); 1067c5441932SPravin B Shelar 10687e059158SDavid Wragg int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict) 1069c5441932SPravin B Shelar { 1070c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1071c5441932SPravin B Shelar int t_hlen = tunnel->hlen + sizeof(struct iphdr); 107228e104d0SVadim Fedorenko int max_mtu = IP_MAX_MTU - t_hlen; 1073c5441932SPravin B Shelar 10749992a078SHangbin Liu if (dev->type == ARPHRD_ETHER) 10759992a078SHangbin Liu max_mtu -= dev->hard_header_len; 10769992a078SHangbin Liu 1077b96f9afeSJarod Wilson if (new_mtu < ETH_MIN_MTU) 1078c5441932SPravin B Shelar return -EINVAL; 10797e059158SDavid Wragg 10807e059158SDavid Wragg if (new_mtu > max_mtu) { 10817e059158SDavid Wragg if (strict) 10827e059158SDavid Wragg return -EINVAL; 10837e059158SDavid Wragg 10847e059158SDavid Wragg new_mtu = max_mtu; 10857e059158SDavid Wragg } 10867e059158SDavid Wragg 10871eb2cdedSEric Dumazet WRITE_ONCE(dev->mtu, new_mtu); 1088c5441932SPravin B Shelar return 0; 1089c5441932SPravin B Shelar } 10907e059158SDavid Wragg EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu); 10917e059158SDavid Wragg 10927e059158SDavid Wragg int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) 10937e059158SDavid Wragg { 10947e059158SDavid Wragg return __ip_tunnel_change_mtu(dev, new_mtu, true); 10957e059158SDavid Wragg } 1096c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu); 1097c5441932SPravin B Shelar 1098c5441932SPravin B Shelar static void ip_tunnel_dev_free(struct net_device *dev) 1099c5441932SPravin B Shelar { 1100c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1101c5441932SPravin B Shelar 1102c5441932SPravin B Shelar gro_cells_destroy(&tunnel->gro_cells); 1103e09acddfSPaolo Abeni dst_cache_destroy(&tunnel->dst_cache); 1104c5441932SPravin B Shelar } 1105c5441932SPravin B Shelar 1106c5441932SPravin B Shelar void ip_tunnel_dellink(struct net_device *dev, struct list_head *head) 1107c5441932SPravin B Shelar { 1108c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1109c5441932SPravin B Shelar struct ip_tunnel_net *itn; 1110c5441932SPravin B Shelar 11116c742e71SNicolas Dichtel itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id); 1112c5441932SPravin B Shelar 1113c5441932SPravin B Shelar if (itn->fb_tunnel_dev != dev) { 11142e15ea39SPravin B Shelar ip_tunnel_del(itn, netdev_priv(dev)); 1115c5441932SPravin B Shelar unregister_netdevice_queue(dev, head); 1116c5441932SPravin B Shelar } 1117c5441932SPravin B Shelar } 1118c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_dellink); 1119c5441932SPravin B Shelar 11201728d4faSNicolas Dichtel struct net *ip_tunnel_get_link_net(const struct net_device *dev) 11211728d4faSNicolas Dichtel { 11221728d4faSNicolas Dichtel struct ip_tunnel *tunnel = netdev_priv(dev); 11231728d4faSNicolas Dichtel 11249cf621bdSEric Dumazet return READ_ONCE(tunnel->net); 11251728d4faSNicolas Dichtel } 11261728d4faSNicolas Dichtel EXPORT_SYMBOL(ip_tunnel_get_link_net); 11271728d4faSNicolas Dichtel 11281e99584bSNicolas Dichtel int ip_tunnel_get_iflink(const struct net_device *dev) 11291e99584bSNicolas Dichtel { 1130f694eee9SEric Dumazet const struct ip_tunnel *tunnel = netdev_priv(dev); 11311e99584bSNicolas Dichtel 1132f694eee9SEric Dumazet return READ_ONCE(tunnel->parms.link); 11331e99584bSNicolas Dichtel } 11341e99584bSNicolas Dichtel EXPORT_SYMBOL(ip_tunnel_get_iflink); 11351e99584bSNicolas Dichtel 1136c7d03a00SAlexey Dobriyan int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id, 1137c5441932SPravin B Shelar struct rtnl_link_ops *ops, char *devname) 1138c5441932SPravin B Shelar { 1139c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id); 1140117aef12SAlexander Lobakin struct ip_tunnel_parm_kern parms; 11416261d983Sstephen hemminger unsigned int i; 1142c5441932SPravin B Shelar 114379134e6cSEric Dumazet itn->rtnl_link_ops = ops; 11446261d983Sstephen hemminger for (i = 0; i < IP_TNL_HASH_SIZE; i++) 11456261d983Sstephen hemminger INIT_HLIST_HEAD(&itn->tunnels[i]); 1146c5441932SPravin B Shelar 114779134e6cSEric Dumazet if (!ops || !net_has_fallback_tunnels(net)) { 114879134e6cSEric Dumazet struct ip_tunnel_net *it_init_net; 114979134e6cSEric Dumazet 115079134e6cSEric Dumazet it_init_net = net_generic(&init_net, ip_tnl_net_id); 115179134e6cSEric Dumazet itn->type = it_init_net->type; 1152c5441932SPravin B Shelar itn->fb_tunnel_dev = NULL; 1153c5441932SPravin B Shelar return 0; 1154c5441932SPravin B Shelar } 11556261d983Sstephen hemminger 1156c5441932SPravin B Shelar memset(&parms, 0, sizeof(parms)); 1157c5441932SPravin B Shelar if (devname) 1158512b2dc4SXueBing Chen strscpy(parms.name, devname, IFNAMSIZ); 1159c5441932SPravin B Shelar 1160c5441932SPravin B Shelar rtnl_lock(); 1161c5441932SPravin B Shelar itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms); 1162ea857f28SDan Carpenter /* FB netdevice is special: we have one, and only one per netns. 1163ea857f28SDan Carpenter * Allowing to move it to another netns is clearly unsafe. 1164ea857f28SDan Carpenter */ 116567013282SSteffen Klassert if (!IS_ERR(itn->fb_tunnel_dev)) { 11660c493da8SNicolas Dichtel itn->fb_tunnel_dev->netns_immutable = true; 116778ff4be4SSteffen Klassert itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev); 116867013282SSteffen Klassert ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev)); 116979134e6cSEric Dumazet itn->type = itn->fb_tunnel_dev->type; 117067013282SSteffen Klassert } 1171b4de77adSDan Carpenter rtnl_unlock(); 1172c5441932SPravin B Shelar 117327d79f3bSSachin Kamat return PTR_ERR_OR_ZERO(itn->fb_tunnel_dev); 1174c5441932SPravin B Shelar } 1175c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_init_net); 1176c5441932SPravin B Shelar 1177a967e01eSKuniyuki Iwashima void ip_tunnel_delete_net(struct net *net, unsigned int id, 1178a967e01eSKuniyuki Iwashima struct rtnl_link_ops *ops, 1179a967e01eSKuniyuki Iwashima struct list_head *head) 1180c5441932SPravin B Shelar { 1181a967e01eSKuniyuki Iwashima struct ip_tunnel_net *itn = net_generic(net, id); 11826c742e71SNicolas Dichtel struct net_device *dev, *aux; 1183c5441932SPravin B Shelar int h; 1184c5441932SPravin B Shelar 1185a967e01eSKuniyuki Iwashima ASSERT_RTNL_NET(net); 1186a967e01eSKuniyuki Iwashima 11876c742e71SNicolas Dichtel for_each_netdev_safe(net, dev, aux) 11886c742e71SNicolas Dichtel if (dev->rtnl_link_ops == ops) 11896c742e71SNicolas Dichtel unregister_netdevice_queue(dev, head); 11906c742e71SNicolas Dichtel 1191c5441932SPravin B Shelar for (h = 0; h < IP_TNL_HASH_SIZE; h++) { 1192c5441932SPravin B Shelar struct ip_tunnel *t; 1193c5441932SPravin B Shelar struct hlist_node *n; 1194c5441932SPravin B Shelar struct hlist_head *thead = &itn->tunnels[h]; 1195c5441932SPravin B Shelar 1196c5441932SPravin B Shelar hlist_for_each_entry_safe(t, n, thead, hash_node) 11976c742e71SNicolas Dichtel /* If dev is in the same netns, it has already 11986c742e71SNicolas Dichtel * been added to the list by the previous loop. 11996c742e71SNicolas Dichtel */ 12006c742e71SNicolas Dichtel if (!net_eq(dev_net(t->dev), net)) 1201c5441932SPravin B Shelar unregister_netdevice_queue(t->dev, head); 1202c5441932SPravin B Shelar } 1203c5441932SPravin B Shelar } 1204a967e01eSKuniyuki Iwashima EXPORT_SYMBOL_GPL(ip_tunnel_delete_net); 1205c5441932SPravin B Shelar 1206eacb1160SXiao Liang int ip_tunnel_newlink(struct net *net, struct net_device *dev, 1207eacb1160SXiao Liang struct nlattr *tb[], struct ip_tunnel_parm_kern *p, 1208eacb1160SXiao Liang __u32 fwmark) 1209c5441932SPravin B Shelar { 1210c5441932SPravin B Shelar struct ip_tunnel *nt; 1211c5441932SPravin B Shelar struct ip_tunnel_net *itn; 1212c5441932SPravin B Shelar int mtu; 1213c5441932SPravin B Shelar int err; 1214c5441932SPravin B Shelar 1215c5441932SPravin B Shelar nt = netdev_priv(dev); 1216c5441932SPravin B Shelar itn = net_generic(net, nt->ip_tnl_net_id); 1217c5441932SPravin B Shelar 12182e15ea39SPravin B Shelar if (nt->collect_md) { 12192e15ea39SPravin B Shelar if (rtnl_dereference(itn->collect_md_tun)) 12202e15ea39SPravin B Shelar return -EEXIST; 12212e15ea39SPravin B Shelar } else { 1222c5441932SPravin B Shelar if (ip_tunnel_find(itn, p, dev->type)) 1223c5441932SPravin B Shelar return -EEXIST; 12242e15ea39SPravin B Shelar } 1225c5441932SPravin B Shelar 12265e6700b3SNicolas Dichtel nt->net = net; 1227c5441932SPravin B Shelar nt->parms = *p; 12289830ad4cSCraig Gallek nt->fwmark = fwmark; 1229c5441932SPravin B Shelar err = register_netdevice(dev); 1230c5441932SPravin B Shelar if (err) 1231f6cc9c05SPetr Machata goto err_register_netdevice; 1232c5441932SPravin B Shelar 1233c5441932SPravin B Shelar if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS]) 1234c5441932SPravin B Shelar eth_hw_addr_random(dev); 1235c5441932SPravin B Shelar 1236c5441932SPravin B Shelar mtu = ip_tunnel_bind_dev(dev); 123724fc7979SStefano Brivio if (tb[IFLA_MTU]) { 123828e104d0SVadim Fedorenko unsigned int max = IP_MAX_MTU - (nt->hlen + sizeof(struct iphdr)); 123924fc7979SStefano Brivio 12409992a078SHangbin Liu if (dev->type == ARPHRD_ETHER) 12419992a078SHangbin Liu max -= dev->hard_header_len; 12429992a078SHangbin Liu 124328e104d0SVadim Fedorenko mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, max); 12445568cdc3SDavid S. Miller } 12455568cdc3SDavid S. Miller 1246f6cc9c05SPetr Machata err = dev_set_mtu(dev, mtu); 1247f6cc9c05SPetr Machata if (err) 1248f6cc9c05SPetr Machata goto err_dev_set_mtu; 1249c5441932SPravin B Shelar 1250c5441932SPravin B Shelar ip_tunnel_add(itn, nt); 1251f6cc9c05SPetr Machata return 0; 1252f6cc9c05SPetr Machata 1253f6cc9c05SPetr Machata err_dev_set_mtu: 1254f6cc9c05SPetr Machata unregister_netdevice(dev); 1255f6cc9c05SPetr Machata err_register_netdevice: 1256c5441932SPravin B Shelar return err; 1257c5441932SPravin B Shelar } 1258c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_newlink); 1259c5441932SPravin B Shelar 1260c5441932SPravin B Shelar int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], 1261117aef12SAlexander Lobakin struct ip_tunnel_parm_kern *p, __u32 fwmark) 1262c5441932SPravin B Shelar { 12636c742e71SNicolas Dichtel struct ip_tunnel *t; 1264c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 12656c742e71SNicolas Dichtel struct net *net = tunnel->net; 1266c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id); 1267c5441932SPravin B Shelar 1268c5441932SPravin B Shelar if (dev == itn->fb_tunnel_dev) 1269c5441932SPravin B Shelar return -EINVAL; 1270c5441932SPravin B Shelar 1271c5441932SPravin B Shelar t = ip_tunnel_find(itn, p, dev->type); 1272c5441932SPravin B Shelar 1273c5441932SPravin B Shelar if (t) { 1274c5441932SPravin B Shelar if (t->dev != dev) 1275c5441932SPravin B Shelar return -EEXIST; 1276c5441932SPravin B Shelar } else { 12776c742e71SNicolas Dichtel t = tunnel; 1278c5441932SPravin B Shelar 1279c5441932SPravin B Shelar if (dev->type != ARPHRD_ETHER) { 1280c5441932SPravin B Shelar unsigned int nflags = 0; 1281c5441932SPravin B Shelar 1282c5441932SPravin B Shelar if (ipv4_is_multicast(p->iph.daddr)) 1283c5441932SPravin B Shelar nflags = IFF_BROADCAST; 1284c5441932SPravin B Shelar else if (p->iph.daddr) 1285c5441932SPravin B Shelar nflags = IFF_POINTOPOINT; 1286c5441932SPravin B Shelar 1287c5441932SPravin B Shelar if ((dev->flags ^ nflags) & 1288c5441932SPravin B Shelar (IFF_POINTOPOINT | IFF_BROADCAST)) 1289c5441932SPravin B Shelar return -EINVAL; 1290c5441932SPravin B Shelar } 1291c5441932SPravin B Shelar } 1292c5441932SPravin B Shelar 12939830ad4cSCraig Gallek ip_tunnel_update(itn, t, dev, p, !tb[IFLA_MTU], fwmark); 1294c5441932SPravin B Shelar return 0; 1295c5441932SPravin B Shelar } 1296c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_changelink); 1297c5441932SPravin B Shelar 1298c5441932SPravin B Shelar int ip_tunnel_init(struct net_device *dev) 1299c5441932SPravin B Shelar { 1300c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1301c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 13021c213bd2SWANG Cong int err; 1303c5441932SPravin B Shelar 1304cf124db5SDavid S. Miller dev->needs_free_netdev = true; 1305cf124db5SDavid S. Miller dev->priv_destructor = ip_tunnel_dev_free; 130645403b12SBreno Leitao dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; 1307c5441932SPravin B Shelar 1308e09acddfSPaolo Abeni err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); 130945403b12SBreno Leitao if (err) 1310e09acddfSPaolo Abeni return err; 13119a4aa9afSTom Herbert 1312c5441932SPravin B Shelar err = gro_cells_init(&tunnel->gro_cells, dev); 1313c5441932SPravin B Shelar if (err) { 1314e09acddfSPaolo Abeni dst_cache_destroy(&tunnel->dst_cache); 1315c5441932SPravin B Shelar return err; 1316c5441932SPravin B Shelar } 1317c5441932SPravin B Shelar 1318c5441932SPravin B Shelar tunnel->dev = dev; 131982183b03SHongbo Li strscpy(tunnel->parms.name, dev->name); 1320c5441932SPravin B Shelar iph->version = 4; 1321c5441932SPravin B Shelar iph->ihl = 5; 1322c5441932SPravin B Shelar 1323d0f41851SWilliam Dauchy if (tunnel->collect_md) 13242e15ea39SPravin B Shelar netif_keep_dst(dev); 13250bef5120SEric Dumazet netdev_lockdep_set_classes(dev); 1326c5441932SPravin B Shelar return 0; 1327c5441932SPravin B Shelar } 1328c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_init); 1329c5441932SPravin B Shelar 1330c5441932SPravin B Shelar void ip_tunnel_uninit(struct net_device *dev) 1331c5441932SPravin B Shelar { 1332c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 13336c742e71SNicolas Dichtel struct net *net = tunnel->net; 1334c5441932SPravin B Shelar struct ip_tunnel_net *itn; 1335c5441932SPravin B Shelar 1336c5441932SPravin B Shelar itn = net_generic(net, tunnel->ip_tnl_net_id); 13372e15ea39SPravin B Shelar ip_tunnel_del(itn, netdev_priv(dev)); 1338ba61539cSTaehee Yoo if (itn->fb_tunnel_dev == dev) 1339ba61539cSTaehee Yoo WRITE_ONCE(itn->fb_tunnel_dev, NULL); 13407d442fabSTom Herbert 1341e09acddfSPaolo Abeni dst_cache_reset(&tunnel->dst_cache); 1342c5441932SPravin B Shelar } 1343c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_uninit); 1344c5441932SPravin B Shelar 1345c5441932SPravin B Shelar /* Do least required initialization, rest of init is done in tunnel_init call */ 1346c7d03a00SAlexey Dobriyan void ip_tunnel_setup(struct net_device *dev, unsigned int net_id) 1347c5441932SPravin B Shelar { 1348c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1349c5441932SPravin B Shelar tunnel->ip_tnl_net_id = net_id; 1350c5441932SPravin B Shelar } 1351c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_setup); 1352c5441932SPravin B Shelar 1353b058a5d2SBreno Leitao MODULE_DESCRIPTION("IPv4 tunnel implementation library"); 1354c5441932SPravin B Shelar MODULE_LICENSE("GPL"); 1355