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> 43c5441932SPravin B Shelar #include <net/rtnetlink.h> 4456328486STom Herbert #include <net/udp.h> 45cfc7381bSAlexei Starovoitov #include <net/dst_metadata.h> 4663487babSTom Herbert 47c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 48c5441932SPravin B Shelar #include <net/ipv6.h> 49c5441932SPravin B Shelar #include <net/ip6_fib.h> 50c5441932SPravin B Shelar #include <net/ip6_route.h> 51c5441932SPravin B Shelar #endif 52c5441932SPravin B Shelar 53967680e0SDuan Jiong static unsigned int ip_tunnel_hash(__be32 key, __be32 remote) 54c5441932SPravin B Shelar { 55c5441932SPravin B Shelar return hash_32((__force u32)key ^ (__force u32)remote, 56c5441932SPravin B Shelar IP_TNL_HASH_BITS); 57c5441932SPravin B Shelar } 58c5441932SPravin B Shelar 59c5441932SPravin B Shelar static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p, 60c5441932SPravin B Shelar __be16 flags, __be32 key) 61c5441932SPravin B Shelar { 62c5441932SPravin B Shelar if (p->i_flags & TUNNEL_KEY) { 63c5441932SPravin B Shelar if (flags & TUNNEL_KEY) 64c5441932SPravin B Shelar return key == p->i_key; 65c5441932SPravin B Shelar else 66c5441932SPravin B Shelar /* key expected, none present */ 67c5441932SPravin B Shelar return false; 68c5441932SPravin B Shelar } else 69c5441932SPravin B Shelar return !(flags & TUNNEL_KEY); 70c5441932SPravin B Shelar } 71c5441932SPravin B Shelar 72c5441932SPravin B Shelar /* Fallback tunnel: no source, no destination, no key, no options 73c5441932SPravin B Shelar 74c5441932SPravin B Shelar Tunnel hash table: 75c5441932SPravin B Shelar We require exact key match i.e. if a key is present in packet 76c5441932SPravin B Shelar it will match only tunnel with the same key; if it is not present, 77c5441932SPravin B Shelar it will match only keyless tunnel. 78c5441932SPravin B Shelar 79c5441932SPravin B Shelar All keysless packets, if not matched configured keyless tunnels 80c5441932SPravin B Shelar will match fallback tunnel. 81c5441932SPravin B Shelar Given src, dst and key, find appropriate for input tunnel. 82c5441932SPravin B Shelar */ 83c5441932SPravin B Shelar struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, 84c5441932SPravin B Shelar int link, __be16 flags, 85c5441932SPravin B Shelar __be32 remote, __be32 local, 86c5441932SPravin B Shelar __be32 key) 87c5441932SPravin B Shelar { 88c5441932SPravin B Shelar struct ip_tunnel *t, *cand = NULL; 89c5441932SPravin B Shelar struct hlist_head *head; 90ba61539cSTaehee Yoo struct net_device *ndev; 91ba61539cSTaehee Yoo unsigned int hash; 92c5441932SPravin B Shelar 93967680e0SDuan Jiong hash = ip_tunnel_hash(key, remote); 94c5441932SPravin B Shelar head = &itn->tunnels[hash]; 95c5441932SPravin B Shelar 96c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 97c5441932SPravin B Shelar if (local != t->parms.iph.saddr || 98c5441932SPravin B Shelar remote != t->parms.iph.daddr || 99c5441932SPravin B Shelar !(t->dev->flags & IFF_UP)) 100c5441932SPravin B Shelar continue; 101c5441932SPravin B Shelar 102c5441932SPravin B Shelar if (!ip_tunnel_key_match(&t->parms, flags, key)) 103c5441932SPravin B Shelar continue; 104c5441932SPravin B Shelar 105c5441932SPravin B Shelar if (t->parms.link == link) 106c5441932SPravin B Shelar return t; 107c5441932SPravin B Shelar else 108c5441932SPravin B Shelar cand = t; 109c5441932SPravin B Shelar } 110c5441932SPravin B Shelar 111c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 112c5441932SPravin B Shelar if (remote != t->parms.iph.daddr || 113e0056593SDmitry Popov t->parms.iph.saddr != 0 || 114c5441932SPravin B Shelar !(t->dev->flags & IFF_UP)) 115c5441932SPravin B Shelar continue; 116c5441932SPravin B Shelar 117c5441932SPravin B Shelar if (!ip_tunnel_key_match(&t->parms, flags, key)) 118c5441932SPravin B Shelar continue; 119c5441932SPravin B Shelar 120c5441932SPravin B Shelar if (t->parms.link == link) 121c5441932SPravin B Shelar return t; 122c5441932SPravin B Shelar else if (!cand) 123c5441932SPravin B Shelar cand = t; 124c5441932SPravin B Shelar } 125c5441932SPravin B Shelar 126967680e0SDuan Jiong hash = ip_tunnel_hash(key, 0); 127c5441932SPravin B Shelar head = &itn->tunnels[hash]; 128c5441932SPravin B Shelar 129c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 130e0056593SDmitry Popov if ((local != t->parms.iph.saddr || t->parms.iph.daddr != 0) && 131e0056593SDmitry Popov (local != t->parms.iph.daddr || !ipv4_is_multicast(local))) 132e0056593SDmitry Popov continue; 133e0056593SDmitry Popov 134e0056593SDmitry Popov if (!(t->dev->flags & IFF_UP)) 135c5441932SPravin B Shelar continue; 136c5441932SPravin B Shelar 137c5441932SPravin B Shelar if (!ip_tunnel_key_match(&t->parms, flags, key)) 138c5441932SPravin B Shelar continue; 139c5441932SPravin B Shelar 140c5441932SPravin B Shelar if (t->parms.link == link) 141c5441932SPravin B Shelar return t; 142c5441932SPravin B Shelar else if (!cand) 143c5441932SPravin B Shelar cand = t; 144c5441932SPravin B Shelar } 145c5441932SPravin B Shelar 146c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 14725629fdaSWilliam Dauchy if ((!(flags & TUNNEL_NO_KEY) && t->parms.i_key != key) || 148e0056593SDmitry Popov t->parms.iph.saddr != 0 || 149e0056593SDmitry Popov t->parms.iph.daddr != 0 || 150c5441932SPravin B Shelar !(t->dev->flags & IFF_UP)) 151c5441932SPravin B Shelar continue; 152c5441932SPravin B Shelar 153c5441932SPravin B Shelar if (t->parms.link == link) 154c5441932SPravin B Shelar return t; 155c5441932SPravin B Shelar else if (!cand) 156c5441932SPravin B Shelar cand = t; 157c5441932SPravin B Shelar } 158c5441932SPravin B Shelar 159c5441932SPravin B Shelar if (cand) 160c5441932SPravin B Shelar return cand; 161c5441932SPravin B Shelar 1622e15ea39SPravin B Shelar t = rcu_dereference(itn->collect_md_tun); 163833a8b40SHaishuang Yan if (t && t->dev->flags & IFF_UP) 1642e15ea39SPravin B Shelar return t; 1652e15ea39SPravin B Shelar 166ba61539cSTaehee Yoo ndev = READ_ONCE(itn->fb_tunnel_dev); 167ba61539cSTaehee Yoo if (ndev && ndev->flags & IFF_UP) 168ba61539cSTaehee Yoo return netdev_priv(ndev); 169c5441932SPravin B Shelar 170c5441932SPravin B Shelar return NULL; 171c5441932SPravin B Shelar } 172c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_lookup); 173c5441932SPravin B Shelar 174c5441932SPravin B Shelar static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn, 175c5441932SPravin B Shelar struct ip_tunnel_parm *parms) 176c5441932SPravin B Shelar { 177c5441932SPravin B Shelar unsigned int h; 178c5441932SPravin B Shelar __be32 remote; 1796d608f06SSteffen Klassert __be32 i_key = parms->i_key; 180c5441932SPravin B Shelar 181c5441932SPravin B Shelar if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr)) 182c5441932SPravin B Shelar remote = parms->iph.daddr; 183c5441932SPravin B Shelar else 184c5441932SPravin B Shelar remote = 0; 185c5441932SPravin B Shelar 1866d608f06SSteffen Klassert if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI)) 1876d608f06SSteffen Klassert i_key = 0; 1886d608f06SSteffen Klassert 1896d608f06SSteffen Klassert h = ip_tunnel_hash(i_key, remote); 190c5441932SPravin B Shelar return &itn->tunnels[h]; 191c5441932SPravin B Shelar } 192c5441932SPravin B Shelar 193c5441932SPravin B Shelar static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t) 194c5441932SPravin B Shelar { 195c5441932SPravin B Shelar struct hlist_head *head = ip_bucket(itn, &t->parms); 196c5441932SPravin B Shelar 1972e15ea39SPravin B Shelar if (t->collect_md) 1982e15ea39SPravin B Shelar rcu_assign_pointer(itn->collect_md_tun, t); 199c5441932SPravin B Shelar hlist_add_head_rcu(&t->hash_node, head); 200c5441932SPravin B Shelar } 201c5441932SPravin B Shelar 2022e15ea39SPravin B Shelar static void ip_tunnel_del(struct ip_tunnel_net *itn, struct ip_tunnel *t) 203c5441932SPravin B Shelar { 2042e15ea39SPravin B Shelar if (t->collect_md) 2052e15ea39SPravin B Shelar rcu_assign_pointer(itn->collect_md_tun, NULL); 206c5441932SPravin B Shelar hlist_del_init_rcu(&t->hash_node); 207c5441932SPravin B Shelar } 208c5441932SPravin B Shelar 209c5441932SPravin B Shelar static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn, 210c5441932SPravin B Shelar struct ip_tunnel_parm *parms, 211c5441932SPravin B Shelar int type) 212c5441932SPravin B Shelar { 213c5441932SPravin B Shelar __be32 remote = parms->iph.daddr; 214c5441932SPravin B Shelar __be32 local = parms->iph.saddr; 215c5441932SPravin B Shelar __be32 key = parms->i_key; 2165ce54af1SDmitry Popov __be16 flags = parms->i_flags; 217c5441932SPravin B Shelar int link = parms->link; 218c5441932SPravin B Shelar struct ip_tunnel *t = NULL; 219c5441932SPravin B Shelar struct hlist_head *head = ip_bucket(itn, parms); 220c5441932SPravin B Shelar 221c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 222c5441932SPravin B Shelar if (local == t->parms.iph.saddr && 223c5441932SPravin B Shelar remote == t->parms.iph.daddr && 224c5441932SPravin B Shelar link == t->parms.link && 2255ce54af1SDmitry Popov type == t->dev->type && 2265ce54af1SDmitry Popov ip_tunnel_key_match(&t->parms, flags, key)) 227c5441932SPravin B Shelar break; 228c5441932SPravin B Shelar } 229c5441932SPravin B Shelar return t; 230c5441932SPravin B Shelar } 231c5441932SPravin B Shelar 232c5441932SPravin B Shelar static struct net_device *__ip_tunnel_create(struct net *net, 233c5441932SPravin B Shelar const struct rtnl_link_ops *ops, 234c5441932SPravin B Shelar struct ip_tunnel_parm *parms) 235c5441932SPravin B Shelar { 236c5441932SPravin B Shelar int err; 237c5441932SPravin B Shelar struct ip_tunnel *tunnel; 238c5441932SPravin B Shelar struct net_device *dev; 239c5441932SPravin B Shelar char name[IFNAMSIZ]; 240c5441932SPravin B Shelar 241c5441932SPravin B Shelar err = -E2BIG; 2429cb726a2SEric Dumazet if (parms->name[0]) { 2439cb726a2SEric Dumazet if (!dev_valid_name(parms->name)) 244c5441932SPravin B Shelar goto failed; 2459cb726a2SEric Dumazet strlcpy(name, parms->name, IFNAMSIZ); 2469cb726a2SEric Dumazet } else { 2479cb726a2SEric Dumazet if (strlen(ops->kind) > (IFNAMSIZ - 3)) 2489cb726a2SEric Dumazet goto failed; 249000ade80SSultan Alsawaf strcpy(name, ops->kind); 250000ade80SSultan Alsawaf strcat(name, "%d"); 251c5441932SPravin B Shelar } 252c5441932SPravin B Shelar 253c5441932SPravin B Shelar ASSERT_RTNL(); 254c835a677STom Gundersen dev = alloc_netdev(ops->priv_size, name, NET_NAME_UNKNOWN, ops->setup); 255c5441932SPravin B Shelar if (!dev) { 256c5441932SPravin B Shelar err = -ENOMEM; 257c5441932SPravin B Shelar goto failed; 258c5441932SPravin B Shelar } 259c5441932SPravin B Shelar dev_net_set(dev, net); 260c5441932SPravin B Shelar 261c5441932SPravin B Shelar dev->rtnl_link_ops = ops; 262c5441932SPravin B Shelar 263c5441932SPravin B Shelar tunnel = netdev_priv(dev); 264c5441932SPravin B Shelar tunnel->parms = *parms; 2655e6700b3SNicolas Dichtel tunnel->net = net; 266c5441932SPravin B Shelar 267c5441932SPravin B Shelar err = register_netdevice(dev); 268c5441932SPravin B Shelar if (err) 269c5441932SPravin B Shelar goto failed_free; 270c5441932SPravin B Shelar 271c5441932SPravin B Shelar return dev; 272c5441932SPravin B Shelar 273c5441932SPravin B Shelar failed_free: 274c5441932SPravin B Shelar free_netdev(dev); 275c5441932SPravin B Shelar failed: 276c5441932SPravin B Shelar return ERR_PTR(err); 277c5441932SPravin B Shelar } 278c5441932SPravin B Shelar 279c5441932SPravin B Shelar static int ip_tunnel_bind_dev(struct net_device *dev) 280c5441932SPravin B Shelar { 281c5441932SPravin B Shelar struct net_device *tdev = NULL; 282c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 283c5441932SPravin B Shelar const struct iphdr *iph; 284c5441932SPravin B Shelar int hlen = LL_MAX_HEADER; 285c5441932SPravin B Shelar int mtu = ETH_DATA_LEN; 286c5441932SPravin B Shelar int t_hlen = tunnel->hlen + sizeof(struct iphdr); 287c5441932SPravin B Shelar 288c5441932SPravin B Shelar iph = &tunnel->parms.iph; 289c5441932SPravin B Shelar 290c5441932SPravin B Shelar /* Guess output device to choose reasonable mtu and needed_headroom */ 291c5441932SPravin B Shelar if (iph->daddr) { 292c5441932SPravin B Shelar struct flowi4 fl4; 293c5441932SPravin B Shelar struct rtable *rt; 294c5441932SPravin B Shelar 295b0066da5SPetr Machata ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr, 2967d442fabSTom Herbert iph->saddr, tunnel->parms.o_key, 2979830ad4cSCraig Gallek RT_TOS(iph->tos), tunnel->parms.link, 29824ba1440Swenxu tunnel->fwmark, 0); 2997d442fabSTom Herbert rt = ip_route_output_key(tunnel->net, &fl4); 3007d442fabSTom Herbert 301c5441932SPravin B Shelar if (!IS_ERR(rt)) { 302c5441932SPravin B Shelar tdev = rt->dst.dev; 303c5441932SPravin B Shelar ip_rt_put(rt); 304c5441932SPravin B Shelar } 305c5441932SPravin B Shelar if (dev->type != ARPHRD_ETHER) 306c5441932SPravin B Shelar dev->flags |= IFF_POINTOPOINT; 307f27337e1SPaolo Abeni 308f27337e1SPaolo Abeni dst_cache_reset(&tunnel->dst_cache); 309c5441932SPravin B Shelar } 310c5441932SPravin B Shelar 311c5441932SPravin B Shelar if (!tdev && tunnel->parms.link) 3126c742e71SNicolas Dichtel tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link); 313c5441932SPravin B Shelar 314c5441932SPravin B Shelar if (tdev) { 315c5441932SPravin B Shelar hlen = tdev->hard_header_len + tdev->needed_headroom; 31682612de1SNicolas Dichtel mtu = min(tdev->mtu, IP_MAX_MTU); 317c5441932SPravin B Shelar } 318c5441932SPravin B Shelar 319c5441932SPravin B Shelar dev->needed_headroom = t_hlen + hlen; 3209992a078SHangbin Liu mtu -= t_hlen + (dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0); 321c5441932SPravin B Shelar 322b5476022SEric Dumazet if (mtu < IPV4_MIN_MTU) 323b5476022SEric Dumazet mtu = IPV4_MIN_MTU; 324c5441932SPravin B Shelar 325c5441932SPravin B Shelar return mtu; 326c5441932SPravin B Shelar } 327c5441932SPravin B Shelar 328c5441932SPravin B Shelar static struct ip_tunnel *ip_tunnel_create(struct net *net, 329c5441932SPravin B Shelar struct ip_tunnel_net *itn, 330c5441932SPravin B Shelar struct ip_tunnel_parm *parms) 331c5441932SPravin B Shelar { 3324929fd8cSJulia Lawall struct ip_tunnel *nt; 333c5441932SPravin B Shelar struct net_device *dev; 334b96f9afeSJarod Wilson int t_hlen; 335f6cc9c05SPetr Machata int mtu; 336f6cc9c05SPetr Machata int err; 337c5441932SPravin B Shelar 33879134e6cSEric Dumazet dev = __ip_tunnel_create(net, itn->rtnl_link_ops, parms); 339c5441932SPravin B Shelar if (IS_ERR(dev)) 3406dd3c9ecSFlorian Westphal return ERR_CAST(dev); 341c5441932SPravin B Shelar 342f6cc9c05SPetr Machata mtu = ip_tunnel_bind_dev(dev); 343f6cc9c05SPetr Machata err = dev_set_mtu(dev, mtu); 344f6cc9c05SPetr Machata if (err) 345f6cc9c05SPetr Machata goto err_dev_set_mtu; 346c5441932SPravin B Shelar 347c5441932SPravin B Shelar nt = netdev_priv(dev); 348b96f9afeSJarod Wilson t_hlen = nt->hlen + sizeof(struct iphdr); 349b96f9afeSJarod Wilson dev->min_mtu = ETH_MIN_MTU; 35028e104d0SVadim Fedorenko dev->max_mtu = IP_MAX_MTU - t_hlen; 3519992a078SHangbin Liu if (dev->type == ARPHRD_ETHER) 3529992a078SHangbin Liu dev->max_mtu -= dev->hard_header_len; 3539992a078SHangbin Liu 354c5441932SPravin B Shelar ip_tunnel_add(itn, nt); 355c5441932SPravin B Shelar return nt; 356f6cc9c05SPetr Machata 357f6cc9c05SPetr Machata err_dev_set_mtu: 358f6cc9c05SPetr Machata unregister_netdevice(dev); 359f6cc9c05SPetr Machata return ERR_PTR(err); 360c5441932SPravin B Shelar } 361c5441932SPravin B Shelar 362c5441932SPravin B Shelar int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, 3632e15ea39SPravin B Shelar const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst, 3642e15ea39SPravin B Shelar bool log_ecn_error) 365c5441932SPravin B Shelar { 366c5441932SPravin B Shelar const struct iphdr *iph = ip_hdr(skb); 367c5441932SPravin B Shelar int err; 368c5441932SPravin B Shelar 369c5441932SPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 370c5441932SPravin B Shelar if (ipv4_is_multicast(iph->daddr)) { 371c5441932SPravin B Shelar tunnel->dev->stats.multicast++; 372c5441932SPravin B Shelar skb->pkt_type = PACKET_BROADCAST; 373c5441932SPravin B Shelar } 374c5441932SPravin B Shelar #endif 375c5441932SPravin B Shelar 376c5441932SPravin B Shelar if ((!(tpi->flags&TUNNEL_CSUM) && (tunnel->parms.i_flags&TUNNEL_CSUM)) || 377c5441932SPravin B Shelar ((tpi->flags&TUNNEL_CSUM) && !(tunnel->parms.i_flags&TUNNEL_CSUM))) { 378c5441932SPravin B Shelar tunnel->dev->stats.rx_crc_errors++; 379c5441932SPravin B Shelar tunnel->dev->stats.rx_errors++; 380c5441932SPravin B Shelar goto drop; 381c5441932SPravin B Shelar } 382c5441932SPravin B Shelar 383c5441932SPravin B Shelar if (tunnel->parms.i_flags&TUNNEL_SEQ) { 384c5441932SPravin B Shelar if (!(tpi->flags&TUNNEL_SEQ) || 385c5441932SPravin B Shelar (tunnel->i_seqno && (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) { 386c5441932SPravin B Shelar tunnel->dev->stats.rx_fifo_errors++; 387c5441932SPravin B Shelar tunnel->dev->stats.rx_errors++; 388c5441932SPravin B Shelar goto drop; 389c5441932SPravin B Shelar } 390c5441932SPravin B Shelar tunnel->i_seqno = ntohl(tpi->seq) + 1; 391c5441932SPravin B Shelar } 392c5441932SPravin B Shelar 393227adfb2SGilad Naaman skb_set_network_header(skb, (tunnel->dev->type == ARPHRD_ETHER) ? ETH_HLEN : 0); 394e96f2e7cSYing Cai 395c5441932SPravin B Shelar err = IP_ECN_decapsulate(iph, skb); 396c5441932SPravin B Shelar if (unlikely(err)) { 397c5441932SPravin B Shelar if (log_ecn_error) 398c5441932SPravin B Shelar net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", 399c5441932SPravin B Shelar &iph->saddr, iph->tos); 400c5441932SPravin B Shelar if (err > 1) { 401c5441932SPravin B Shelar ++tunnel->dev->stats.rx_frame_errors; 402c5441932SPravin B Shelar ++tunnel->dev->stats.rx_errors; 403c5441932SPravin B Shelar goto drop; 404c5441932SPravin B Shelar } 405c5441932SPravin B Shelar } 406c5441932SPravin B Shelar 407560b50cfSFabian Frederick dev_sw_netstats_rx_add(tunnel->dev, skb->len); 40881b9eab5SAlexei Starovoitov skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev))); 40981b9eab5SAlexei Starovoitov 4103d7b46cdSPravin B Shelar if (tunnel->dev->type == ARPHRD_ETHER) { 4113d7b46cdSPravin B Shelar skb->protocol = eth_type_trans(skb, tunnel->dev); 4123d7b46cdSPravin B Shelar skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); 4133d7b46cdSPravin B Shelar } else { 4143d7b46cdSPravin B Shelar skb->dev = tunnel->dev; 4153d7b46cdSPravin B Shelar } 41664261f23SNicolas Dichtel 4172e15ea39SPravin B Shelar if (tun_dst) 4182e15ea39SPravin B Shelar skb_dst_set(skb, (struct dst_entry *)tun_dst); 4192e15ea39SPravin B Shelar 420c5441932SPravin B Shelar gro_cells_receive(&tunnel->gro_cells, skb); 421c5441932SPravin B Shelar return 0; 422c5441932SPravin B Shelar 423c5441932SPravin B Shelar drop: 424469f87e1SHaishuang Yan if (tun_dst) 425469f87e1SHaishuang Yan dst_release((struct dst_entry *)tun_dst); 426c5441932SPravin B Shelar kfree_skb(skb); 427c5441932SPravin B Shelar return 0; 428c5441932SPravin B Shelar } 429c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_rcv); 430c5441932SPravin B Shelar 431a8c5f90fSTom Herbert int ip_tunnel_encap_add_ops(const struct ip_tunnel_encap_ops *ops, 432a8c5f90fSTom Herbert unsigned int num) 433a8c5f90fSTom Herbert { 434bb1553c8SThomas Graf if (num >= MAX_IPTUN_ENCAP_OPS) 435bb1553c8SThomas Graf return -ERANGE; 436bb1553c8SThomas Graf 437a8c5f90fSTom Herbert return !cmpxchg((const struct ip_tunnel_encap_ops **) 438a8c5f90fSTom Herbert &iptun_encaps[num], 439a8c5f90fSTom Herbert NULL, ops) ? 0 : -1; 44056328486STom Herbert } 441a8c5f90fSTom Herbert EXPORT_SYMBOL(ip_tunnel_encap_add_ops); 442a8c5f90fSTom Herbert 443a8c5f90fSTom Herbert int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *ops, 444a8c5f90fSTom Herbert unsigned int num) 445a8c5f90fSTom Herbert { 446a8c5f90fSTom Herbert int ret; 447a8c5f90fSTom Herbert 448bb1553c8SThomas Graf if (num >= MAX_IPTUN_ENCAP_OPS) 449bb1553c8SThomas Graf return -ERANGE; 450bb1553c8SThomas Graf 451a8c5f90fSTom Herbert ret = (cmpxchg((const struct ip_tunnel_encap_ops **) 452a8c5f90fSTom Herbert &iptun_encaps[num], 453a8c5f90fSTom Herbert ops, NULL) == ops) ? 0 : -1; 454a8c5f90fSTom Herbert 455a8c5f90fSTom Herbert synchronize_net(); 456a8c5f90fSTom Herbert 457a8c5f90fSTom Herbert return ret; 458a8c5f90fSTom Herbert } 459a8c5f90fSTom Herbert EXPORT_SYMBOL(ip_tunnel_encap_del_ops); 46056328486STom Herbert 46156328486STom Herbert int ip_tunnel_encap_setup(struct ip_tunnel *t, 46256328486STom Herbert struct ip_tunnel_encap *ipencap) 46356328486STom Herbert { 46456328486STom Herbert int hlen; 46556328486STom Herbert 46656328486STom Herbert memset(&t->encap, 0, sizeof(t->encap)); 46756328486STom Herbert 46856328486STom Herbert hlen = ip_encap_hlen(ipencap); 46956328486STom Herbert if (hlen < 0) 47056328486STom Herbert return hlen; 47156328486STom Herbert 47256328486STom Herbert t->encap.type = ipencap->type; 47356328486STom Herbert t->encap.sport = ipencap->sport; 47456328486STom Herbert t->encap.dport = ipencap->dport; 47556328486STom Herbert t->encap.flags = ipencap->flags; 47656328486STom Herbert 47756328486STom Herbert t->encap_hlen = hlen; 47856328486STom Herbert t->hlen = t->encap_hlen + t->tun_hlen; 47956328486STom Herbert 48056328486STom Herbert return 0; 48156328486STom Herbert } 48256328486STom Herbert EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup); 48356328486STom Herbert 48423a3647bSPravin B Shelar static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, 485fc24f2b2STimo Teräs struct rtable *rt, __be16 df, 486c8b34e68Swenxu const struct iphdr *inner_iph, 487c8b34e68Swenxu int tunnel_hlen, __be32 dst, bool md) 48823a3647bSPravin B Shelar { 48923a3647bSPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 490c8b34e68Swenxu int pkt_size; 49123a3647bSPravin B Shelar int mtu; 49223a3647bSPravin B Shelar 493c8b34e68Swenxu tunnel_hlen = md ? tunnel_hlen : tunnel->hlen; 49428e104d0SVadim Fedorenko pkt_size = skb->len - tunnel_hlen; 4959992a078SHangbin Liu pkt_size -= dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0; 496c8b34e68Swenxu 4979992a078SHangbin Liu if (df) { 49828e104d0SVadim Fedorenko mtu = dst_mtu(&rt->dst) - (sizeof(struct iphdr) + tunnel_hlen); 4999992a078SHangbin Liu mtu -= dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0; 5009992a078SHangbin Liu } else { 501f4b3ec4eSAlan Maguire mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; 5029992a078SHangbin Liu } 50323a3647bSPravin B Shelar 504f4b3ec4eSAlan Maguire if (skb_valid_dst(skb)) 5057a1592bcSHangbin Liu skb_dst_update_pmtu_no_confirm(skb, mtu); 50623a3647bSPravin B Shelar 50723a3647bSPravin B Shelar if (skb->protocol == htons(ETH_P_IP)) { 50823a3647bSPravin B Shelar if (!skb_is_gso(skb) && 509fc24f2b2STimo Teräs (inner_iph->frag_off & htons(IP_DF)) && 510fc24f2b2STimo Teräs mtu < pkt_size) { 5114372339eSJason A. Donenfeld icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); 51223a3647bSPravin B Shelar return -E2BIG; 51323a3647bSPravin B Shelar } 51423a3647bSPravin B Shelar } 51523a3647bSPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 51623a3647bSPravin B Shelar else if (skb->protocol == htons(ETH_P_IPV6)) { 517f4b3ec4eSAlan Maguire struct rt6_info *rt6; 518c8b34e68Swenxu __be32 daddr; 519c8b34e68Swenxu 520f4b3ec4eSAlan Maguire rt6 = skb_valid_dst(skb) ? (struct rt6_info *)skb_dst(skb) : 521f4b3ec4eSAlan Maguire NULL; 522c8b34e68Swenxu daddr = md ? dst : tunnel->parms.iph.daddr; 52323a3647bSPravin B Shelar 52423a3647bSPravin B Shelar if (rt6 && mtu < dst_mtu(skb_dst(skb)) && 52523a3647bSPravin B Shelar mtu >= IPV6_MIN_MTU) { 526c8b34e68Swenxu if ((daddr && !ipv4_is_multicast(daddr)) || 52723a3647bSPravin B Shelar rt6->rt6i_dst.plen == 128) { 52823a3647bSPravin B Shelar rt6->rt6i_flags |= RTF_MODIFIED; 52923a3647bSPravin B Shelar dst_metric_set(skb_dst(skb), RTAX_MTU, mtu); 53023a3647bSPravin B Shelar } 53123a3647bSPravin B Shelar } 53223a3647bSPravin B Shelar 53323a3647bSPravin B Shelar if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU && 53423a3647bSPravin B Shelar mtu < pkt_size) { 5354372339eSJason A. Donenfeld icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); 53623a3647bSPravin B Shelar return -E2BIG; 53723a3647bSPravin B Shelar } 53823a3647bSPravin B Shelar } 53923a3647bSPravin B Shelar #endif 54023a3647bSPravin B Shelar return 0; 54123a3647bSPravin B Shelar } 54223a3647bSPravin B Shelar 543c8b34e68Swenxu void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, 544c8b34e68Swenxu u8 proto, int tunnel_hlen) 545cfc7381bSAlexei Starovoitov { 546cfc7381bSAlexei Starovoitov struct ip_tunnel *tunnel = netdev_priv(dev); 547cfc7381bSAlexei Starovoitov u32 headroom = sizeof(struct iphdr); 548cfc7381bSAlexei Starovoitov struct ip_tunnel_info *tun_info; 549cfc7381bSAlexei Starovoitov const struct ip_tunnel_key *key; 550cfc7381bSAlexei Starovoitov const struct iphdr *inner_iph; 551f46fe4f8Swenxu struct rtable *rt = NULL; 552cfc7381bSAlexei Starovoitov struct flowi4 fl4; 553cfc7381bSAlexei Starovoitov __be16 df = 0; 554cfc7381bSAlexei Starovoitov u8 tos, ttl; 555f46fe4f8Swenxu bool use_cache; 556cfc7381bSAlexei Starovoitov 557cfc7381bSAlexei Starovoitov tun_info = skb_tunnel_info(skb); 558cfc7381bSAlexei Starovoitov if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 559cfc7381bSAlexei Starovoitov ip_tunnel_info_af(tun_info) != AF_INET)) 560cfc7381bSAlexei Starovoitov goto tx_error; 561cfc7381bSAlexei Starovoitov key = &tun_info->key; 562cfc7381bSAlexei Starovoitov memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 563cfc7381bSAlexei Starovoitov inner_iph = (const struct iphdr *)skb_inner_network_header(skb); 564cfc7381bSAlexei Starovoitov tos = key->tos; 565cfc7381bSAlexei Starovoitov if (tos == 1) { 566cfc7381bSAlexei Starovoitov if (skb->protocol == htons(ETH_P_IP)) 567cfc7381bSAlexei Starovoitov tos = inner_iph->tos; 568cfc7381bSAlexei Starovoitov else if (skb->protocol == htons(ETH_P_IPV6)) 569cfc7381bSAlexei Starovoitov tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); 570cfc7381bSAlexei Starovoitov } 5716e6b904aSwenxu ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src, 5726e6b904aSwenxu tunnel_id_to_key32(key->tun_id), RT_TOS(tos), 57324ba1440Swenxu 0, skb->mark, skb_get_hash(skb)); 574cfc7381bSAlexei Starovoitov if (tunnel->encap.type != TUNNEL_ENCAP_NONE) 575cfc7381bSAlexei Starovoitov goto tx_error; 576f46fe4f8Swenxu 577f46fe4f8Swenxu use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); 578f46fe4f8Swenxu if (use_cache) 579f46fe4f8Swenxu rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl4.saddr); 580f46fe4f8Swenxu if (!rt) { 581cfc7381bSAlexei Starovoitov rt = ip_route_output_key(tunnel->net, &fl4); 582cfc7381bSAlexei Starovoitov if (IS_ERR(rt)) { 583cfc7381bSAlexei Starovoitov dev->stats.tx_carrier_errors++; 584cfc7381bSAlexei Starovoitov goto tx_error; 585cfc7381bSAlexei Starovoitov } 586f46fe4f8Swenxu if (use_cache) 587f46fe4f8Swenxu dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, 588f46fe4f8Swenxu fl4.saddr); 589f46fe4f8Swenxu } 590cfc7381bSAlexei Starovoitov if (rt->dst.dev == dev) { 591cfc7381bSAlexei Starovoitov ip_rt_put(rt); 592cfc7381bSAlexei Starovoitov dev->stats.collisions++; 593cfc7381bSAlexei Starovoitov goto tx_error; 594cfc7381bSAlexei Starovoitov } 595c8b34e68Swenxu 596c8b34e68Swenxu if (key->tun_flags & TUNNEL_DONT_FRAGMENT) 597c8b34e68Swenxu df = htons(IP_DF); 598c8b34e68Swenxu if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, tunnel_hlen, 599c8b34e68Swenxu key->u.ipv4.dst, true)) { 600c8b34e68Swenxu ip_rt_put(rt); 601c8b34e68Swenxu goto tx_error; 602c8b34e68Swenxu } 603c8b34e68Swenxu 604cfc7381bSAlexei Starovoitov tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); 605cfc7381bSAlexei Starovoitov ttl = key->ttl; 606cfc7381bSAlexei Starovoitov if (ttl == 0) { 607cfc7381bSAlexei Starovoitov if (skb->protocol == htons(ETH_P_IP)) 608cfc7381bSAlexei Starovoitov ttl = inner_iph->ttl; 609cfc7381bSAlexei Starovoitov else if (skb->protocol == htons(ETH_P_IPV6)) 610cfc7381bSAlexei Starovoitov ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit; 611cfc7381bSAlexei Starovoitov else 612cfc7381bSAlexei Starovoitov ttl = ip4_dst_hoplimit(&rt->dst); 613cfc7381bSAlexei Starovoitov } 614c8b34e68Swenxu 615cfc7381bSAlexei Starovoitov headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len; 616cfc7381bSAlexei Starovoitov if (headroom > dev->needed_headroom) 617cfc7381bSAlexei Starovoitov dev->needed_headroom = headroom; 618cfc7381bSAlexei Starovoitov 619cfc7381bSAlexei Starovoitov if (skb_cow_head(skb, dev->needed_headroom)) { 620cfc7381bSAlexei Starovoitov ip_rt_put(rt); 621cfc7381bSAlexei Starovoitov goto tx_dropped; 622cfc7381bSAlexei Starovoitov } 6230f693f19SHaishuang Yan iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, proto, tos, ttl, 6240f693f19SHaishuang Yan df, !net_eq(tunnel->net, dev_net(dev))); 625cfc7381bSAlexei Starovoitov return; 626cfc7381bSAlexei Starovoitov tx_error: 627cfc7381bSAlexei Starovoitov dev->stats.tx_errors++; 628cfc7381bSAlexei Starovoitov goto kfree; 629cfc7381bSAlexei Starovoitov tx_dropped: 630cfc7381bSAlexei Starovoitov dev->stats.tx_dropped++; 631cfc7381bSAlexei Starovoitov kfree: 632cfc7381bSAlexei Starovoitov kfree_skb(skb); 633cfc7381bSAlexei Starovoitov } 634cfc7381bSAlexei Starovoitov EXPORT_SYMBOL_GPL(ip_md_tunnel_xmit); 635cfc7381bSAlexei Starovoitov 636c5441932SPravin B Shelar void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, 63756328486STom Herbert const struct iphdr *tnl_params, u8 protocol) 638c5441932SPravin B Shelar { 639c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 640186d9366Swenxu struct ip_tunnel_info *tun_info = NULL; 641c5441932SPravin B Shelar const struct iphdr *inner_iph; 642c5441932SPravin B Shelar unsigned int max_headroom; /* The extra header space needed */ 643186d9366Swenxu struct rtable *rt = NULL; /* Route to the other host */ 644186d9366Swenxu bool use_cache = false; 645186d9366Swenxu struct flowi4 fl4; 646186d9366Swenxu bool md = false; 64722fb22eaSTimo Teräs bool connected; 648186d9366Swenxu u8 tos, ttl; 649186d9366Swenxu __be32 dst; 650186d9366Swenxu __be16 df; 651c5441932SPravin B Shelar 652c5441932SPravin B Shelar inner_iph = (const struct iphdr *)skb_inner_network_header(skb); 65322fb22eaSTimo Teräs connected = (tunnel->parms.iph.daddr != 0); 654c5441932SPravin B Shelar 6555146d1f1SBernie Harris memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 6565146d1f1SBernie Harris 657c5441932SPravin B Shelar dst = tnl_params->daddr; 658c5441932SPravin B Shelar if (dst == 0) { 659c5441932SPravin B Shelar /* NBMA tunnel */ 660c5441932SPravin B Shelar 66151456b29SIan Morris if (!skb_dst(skb)) { 662c5441932SPravin B Shelar dev->stats.tx_fifo_errors++; 663c5441932SPravin B Shelar goto tx_error; 664c5441932SPravin B Shelar } 665c5441932SPravin B Shelar 666d71b5753Swenxu tun_info = skb_tunnel_info(skb); 667d71b5753Swenxu if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) && 668d71b5753Swenxu ip_tunnel_info_af(tun_info) == AF_INET && 669186d9366Swenxu tun_info->key.u.ipv4.dst) { 670d71b5753Swenxu dst = tun_info->key.u.ipv4.dst; 671186d9366Swenxu md = true; 672186d9366Swenxu connected = true; 673186d9366Swenxu } 674d71b5753Swenxu else if (skb->protocol == htons(ETH_P_IP)) { 675c5441932SPravin B Shelar rt = skb_rtable(skb); 676c5441932SPravin B Shelar dst = rt_nexthop(rt, inner_iph->daddr); 677c5441932SPravin B Shelar } 678c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 679c5441932SPravin B Shelar else if (skb->protocol == htons(ETH_P_IPV6)) { 680c5441932SPravin B Shelar const struct in6_addr *addr6; 681c5441932SPravin B Shelar struct neighbour *neigh; 682c5441932SPravin B Shelar bool do_tx_error_icmp; 683c5441932SPravin B Shelar int addr_type; 684c5441932SPravin B Shelar 685c5441932SPravin B Shelar neigh = dst_neigh_lookup(skb_dst(skb), 686c5441932SPravin B Shelar &ipv6_hdr(skb)->daddr); 68751456b29SIan Morris if (!neigh) 688c5441932SPravin B Shelar goto tx_error; 689c5441932SPravin B Shelar 690c5441932SPravin B Shelar addr6 = (const struct in6_addr *)&neigh->primary_key; 691c5441932SPravin B Shelar addr_type = ipv6_addr_type(addr6); 692c5441932SPravin B Shelar 693c5441932SPravin B Shelar if (addr_type == IPV6_ADDR_ANY) { 694c5441932SPravin B Shelar addr6 = &ipv6_hdr(skb)->daddr; 695c5441932SPravin B Shelar addr_type = ipv6_addr_type(addr6); 696c5441932SPravin B Shelar } 697c5441932SPravin B Shelar 698c5441932SPravin B Shelar if ((addr_type & IPV6_ADDR_COMPATv4) == 0) 699c5441932SPravin B Shelar do_tx_error_icmp = true; 700c5441932SPravin B Shelar else { 701c5441932SPravin B Shelar do_tx_error_icmp = false; 702c5441932SPravin B Shelar dst = addr6->s6_addr32[3]; 703c5441932SPravin B Shelar } 704c5441932SPravin B Shelar neigh_release(neigh); 705c5441932SPravin B Shelar if (do_tx_error_icmp) 706c5441932SPravin B Shelar goto tx_error_icmp; 707c5441932SPravin B Shelar } 708c5441932SPravin B Shelar #endif 709c5441932SPravin B Shelar else 710c5441932SPravin B Shelar goto tx_error; 7117d442fabSTom Herbert 712186d9366Swenxu if (!md) 7137d442fabSTom Herbert connected = false; 714c5441932SPravin B Shelar } 715c5441932SPravin B Shelar 716c5441932SPravin B Shelar tos = tnl_params->tos; 717c5441932SPravin B Shelar if (tos & 0x1) { 718c5441932SPravin B Shelar tos &= ~0x1; 7197d442fabSTom Herbert if (skb->protocol == htons(ETH_P_IP)) { 720c5441932SPravin B Shelar tos = inner_iph->tos; 7217d442fabSTom Herbert connected = false; 7227d442fabSTom Herbert } else if (skb->protocol == htons(ETH_P_IPV6)) { 723c5441932SPravin B Shelar tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); 7247d442fabSTom Herbert connected = false; 7257d442fabSTom Herbert } 726c5441932SPravin B Shelar } 727c5441932SPravin B Shelar 728b0066da5SPetr Machata ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr, 7299830ad4cSCraig Gallek tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link, 73024ba1440Swenxu tunnel->fwmark, skb_get_hash(skb)); 7317d442fabSTom Herbert 73256328486STom Herbert if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) 73356328486STom Herbert goto tx_error; 73456328486STom Herbert 735186d9366Swenxu if (connected && md) { 736186d9366Swenxu use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); 737186d9366Swenxu if (use_cache) 738186d9366Swenxu rt = dst_cache_get_ip4(&tun_info->dst_cache, 739186d9366Swenxu &fl4.saddr); 740186d9366Swenxu } else { 741186d9366Swenxu rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache, 742186d9366Swenxu &fl4.saddr) : NULL; 743186d9366Swenxu } 7447d442fabSTom Herbert 7457d442fabSTom Herbert if (!rt) { 7467d442fabSTom Herbert rt = ip_route_output_key(tunnel->net, &fl4); 7477d442fabSTom Herbert 748c5441932SPravin B Shelar if (IS_ERR(rt)) { 749c5441932SPravin B Shelar dev->stats.tx_carrier_errors++; 750c5441932SPravin B Shelar goto tx_error; 751c5441932SPravin B Shelar } 752186d9366Swenxu if (use_cache) 753186d9366Swenxu dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, 754186d9366Swenxu fl4.saddr); 755186d9366Swenxu else if (!md && connected) 756e09acddfSPaolo Abeni dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, 757e09acddfSPaolo Abeni fl4.saddr); 7587d442fabSTom Herbert } 7597d442fabSTom Herbert 7600e6fbc5bSPravin B Shelar if (rt->dst.dev == dev) { 761c5441932SPravin B Shelar ip_rt_put(rt); 762c5441932SPravin B Shelar dev->stats.collisions++; 763c5441932SPravin B Shelar goto tx_error; 764c5441932SPravin B Shelar } 765c5441932SPravin B Shelar 76650c66167SFlorian Westphal df = tnl_params->frag_off; 76750c66167SFlorian Westphal if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df) 76850c66167SFlorian Westphal df |= (inner_iph->frag_off & htons(IP_DF)); 76950c66167SFlorian Westphal 77050c66167SFlorian Westphal if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, 0, 0, false)) { 771c5441932SPravin B Shelar ip_rt_put(rt); 772c5441932SPravin B Shelar goto tx_error; 773c5441932SPravin B Shelar } 774c5441932SPravin B Shelar 775c5441932SPravin B Shelar if (tunnel->err_count > 0) { 776c5441932SPravin B Shelar if (time_before(jiffies, 777c5441932SPravin B Shelar tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { 778c5441932SPravin B Shelar tunnel->err_count--; 779c5441932SPravin B Shelar 780c5441932SPravin B Shelar dst_link_failure(skb); 781c5441932SPravin B Shelar } else 782c5441932SPravin B Shelar tunnel->err_count = 0; 783c5441932SPravin B Shelar } 784c5441932SPravin B Shelar 785d4a71b15SPravin B Shelar tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); 786c5441932SPravin B Shelar ttl = tnl_params->ttl; 787c5441932SPravin B Shelar if (ttl == 0) { 788c5441932SPravin B Shelar if (skb->protocol == htons(ETH_P_IP)) 789c5441932SPravin B Shelar ttl = inner_iph->ttl; 790c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 791c5441932SPravin B Shelar else if (skb->protocol == htons(ETH_P_IPV6)) 792c5441932SPravin B Shelar ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit; 793c5441932SPravin B Shelar #endif 794c5441932SPravin B Shelar else 795c5441932SPravin B Shelar ttl = ip4_dst_hoplimit(&rt->dst); 796c5441932SPravin B Shelar } 797c5441932SPravin B Shelar 7980e6fbc5bSPravin B Shelar max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr) 7997371e022STom Herbert + rt->dst.header_len + ip_encap_hlen(&tunnel->encap); 8003e08f4a7SSteffen Klassert if (max_headroom > dev->needed_headroom) 801c5441932SPravin B Shelar dev->needed_headroom = max_headroom; 8023e08f4a7SSteffen Klassert 803c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) { 804586d5fc8SDmitry Popov ip_rt_put(rt); 805c5441932SPravin B Shelar dev->stats.tx_dropped++; 8063acfa1e7SEric Dumazet kfree_skb(skb); 807c5441932SPravin B Shelar return; 808c5441932SPravin B Shelar } 809c5441932SPravin B Shelar 810039f5062SPravin B Shelar iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl, 811039f5062SPravin B Shelar df, !net_eq(tunnel->net, dev_net(dev))); 812c5441932SPravin B Shelar return; 813c5441932SPravin B Shelar 814c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 815c5441932SPravin B Shelar tx_error_icmp: 816c5441932SPravin B Shelar dst_link_failure(skb); 817c5441932SPravin B Shelar #endif 818c5441932SPravin B Shelar tx_error: 819c5441932SPravin B Shelar dev->stats.tx_errors++; 8203acfa1e7SEric Dumazet kfree_skb(skb); 821c5441932SPravin B Shelar } 822c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_xmit); 823c5441932SPravin B Shelar 824c5441932SPravin B Shelar static void ip_tunnel_update(struct ip_tunnel_net *itn, 825c5441932SPravin B Shelar struct ip_tunnel *t, 826c5441932SPravin B Shelar struct net_device *dev, 827c5441932SPravin B Shelar struct ip_tunnel_parm *p, 8289830ad4cSCraig Gallek bool set_mtu, 8299830ad4cSCraig Gallek __u32 fwmark) 830c5441932SPravin B Shelar { 8312e15ea39SPravin B Shelar ip_tunnel_del(itn, t); 832c5441932SPravin B Shelar t->parms.iph.saddr = p->iph.saddr; 833c5441932SPravin B Shelar t->parms.iph.daddr = p->iph.daddr; 834c5441932SPravin B Shelar t->parms.i_key = p->i_key; 835c5441932SPravin B Shelar t->parms.o_key = p->o_key; 836c5441932SPravin B Shelar if (dev->type != ARPHRD_ETHER) { 837c5441932SPravin B Shelar memcpy(dev->dev_addr, &p->iph.saddr, 4); 838c5441932SPravin B Shelar memcpy(dev->broadcast, &p->iph.daddr, 4); 839c5441932SPravin B Shelar } 840c5441932SPravin B Shelar ip_tunnel_add(itn, t); 841c5441932SPravin B Shelar 842c5441932SPravin B Shelar t->parms.iph.ttl = p->iph.ttl; 843c5441932SPravin B Shelar t->parms.iph.tos = p->iph.tos; 844c5441932SPravin B Shelar t->parms.iph.frag_off = p->iph.frag_off; 845c5441932SPravin B Shelar 8469830ad4cSCraig Gallek if (t->parms.link != p->link || t->fwmark != fwmark) { 847c5441932SPravin B Shelar int mtu; 848c5441932SPravin B Shelar 849c5441932SPravin B Shelar t->parms.link = p->link; 8509830ad4cSCraig Gallek t->fwmark = fwmark; 851c5441932SPravin B Shelar mtu = ip_tunnel_bind_dev(dev); 852c5441932SPravin B Shelar if (set_mtu) 853c5441932SPravin B Shelar dev->mtu = mtu; 854c5441932SPravin B Shelar } 855e09acddfSPaolo Abeni dst_cache_reset(&t->dst_cache); 856c5441932SPravin B Shelar netdev_state_change(dev); 857c5441932SPravin B Shelar } 858c5441932SPravin B Shelar 859607259a6SChristoph Hellwig int ip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) 860c5441932SPravin B Shelar { 861c5441932SPravin B Shelar int err = 0; 8628c923ce2SNicolas Dichtel struct ip_tunnel *t = netdev_priv(dev); 8638c923ce2SNicolas Dichtel struct net *net = t->net; 8648c923ce2SNicolas Dichtel struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id); 865c5441932SPravin B Shelar 866c5441932SPravin B Shelar switch (cmd) { 867c5441932SPravin B Shelar case SIOCGETTUNNEL: 8688c923ce2SNicolas Dichtel if (dev == itn->fb_tunnel_dev) { 869c5441932SPravin B Shelar t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); 87051456b29SIan Morris if (!t) 871c5441932SPravin B Shelar t = netdev_priv(dev); 8728c923ce2SNicolas Dichtel } 873c5441932SPravin B Shelar memcpy(p, &t->parms, sizeof(*p)); 874c5441932SPravin B Shelar break; 875c5441932SPravin B Shelar 876c5441932SPravin B Shelar case SIOCADDTUNNEL: 877c5441932SPravin B Shelar case SIOCCHGTUNNEL: 878c5441932SPravin B Shelar err = -EPERM; 879c5441932SPravin B Shelar if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 880c5441932SPravin B Shelar goto done; 881c5441932SPravin B Shelar if (p->iph.ttl) 882c5441932SPravin B Shelar p->iph.frag_off |= htons(IP_DF); 8837c8e6b9cSDmitry Popov if (!(p->i_flags & VTI_ISVTI)) { 884c5441932SPravin B Shelar if (!(p->i_flags & TUNNEL_KEY)) 885c5441932SPravin B Shelar p->i_key = 0; 886c5441932SPravin B Shelar if (!(p->o_flags & TUNNEL_KEY)) 887c5441932SPravin B Shelar p->o_key = 0; 8887c8e6b9cSDmitry Popov } 889c5441932SPravin B Shelar 89079134e6cSEric Dumazet t = ip_tunnel_find(itn, p, itn->type); 891c5441932SPravin B Shelar 892d61746b2SSteffen Klassert if (cmd == SIOCADDTUNNEL) { 893d61746b2SSteffen Klassert if (!t) { 894c5441932SPravin B Shelar t = ip_tunnel_create(net, itn, p); 895ee30ef4dSDuan Jiong err = PTR_ERR_OR_ZERO(t); 8966dd3c9ecSFlorian Westphal break; 8976dd3c9ecSFlorian Westphal } 898d61746b2SSteffen Klassert 899d61746b2SSteffen Klassert err = -EEXIST; 900d61746b2SSteffen Klassert break; 901d61746b2SSteffen Klassert } 902c5441932SPravin B Shelar if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { 90300db4124SIan Morris if (t) { 904c5441932SPravin B Shelar if (t->dev != dev) { 905c5441932SPravin B Shelar err = -EEXIST; 906c5441932SPravin B Shelar break; 907c5441932SPravin B Shelar } 908c5441932SPravin B Shelar } else { 909c5441932SPravin B Shelar unsigned int nflags = 0; 910c5441932SPravin B Shelar 911c5441932SPravin B Shelar if (ipv4_is_multicast(p->iph.daddr)) 912c5441932SPravin B Shelar nflags = IFF_BROADCAST; 913c5441932SPravin B Shelar else if (p->iph.daddr) 914c5441932SPravin B Shelar nflags = IFF_POINTOPOINT; 915c5441932SPravin B Shelar 916c5441932SPravin B Shelar if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) { 917c5441932SPravin B Shelar err = -EINVAL; 918c5441932SPravin B Shelar break; 919c5441932SPravin B Shelar } 920c5441932SPravin B Shelar 921c5441932SPravin B Shelar t = netdev_priv(dev); 922c5441932SPravin B Shelar } 923c5441932SPravin B Shelar } 924c5441932SPravin B Shelar 925c5441932SPravin B Shelar if (t) { 926c5441932SPravin B Shelar err = 0; 9279830ad4cSCraig Gallek ip_tunnel_update(itn, t, dev, p, true, 0); 9286dd3c9ecSFlorian Westphal } else { 9296dd3c9ecSFlorian Westphal err = -ENOENT; 9306dd3c9ecSFlorian Westphal } 931c5441932SPravin B Shelar break; 932c5441932SPravin B Shelar 933c5441932SPravin B Shelar case SIOCDELTUNNEL: 934c5441932SPravin B Shelar err = -EPERM; 935c5441932SPravin B Shelar if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 936c5441932SPravin B Shelar goto done; 937c5441932SPravin B Shelar 938c5441932SPravin B Shelar if (dev == itn->fb_tunnel_dev) { 939c5441932SPravin B Shelar err = -ENOENT; 940c5441932SPravin B Shelar t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); 94151456b29SIan Morris if (!t) 942c5441932SPravin B Shelar goto done; 943c5441932SPravin B Shelar err = -EPERM; 944c5441932SPravin B Shelar if (t == netdev_priv(itn->fb_tunnel_dev)) 945c5441932SPravin B Shelar goto done; 946c5441932SPravin B Shelar dev = t->dev; 947c5441932SPravin B Shelar } 948c5441932SPravin B Shelar unregister_netdevice(dev); 949c5441932SPravin B Shelar err = 0; 950c5441932SPravin B Shelar break; 951c5441932SPravin B Shelar 952c5441932SPravin B Shelar default: 953c5441932SPravin B Shelar err = -EINVAL; 954c5441932SPravin B Shelar } 955c5441932SPravin B Shelar 956c5441932SPravin B Shelar done: 957c5441932SPravin B Shelar return err; 958c5441932SPravin B Shelar } 959607259a6SChristoph Hellwig EXPORT_SYMBOL_GPL(ip_tunnel_ctl); 960607259a6SChristoph Hellwig 961607259a6SChristoph Hellwig int ip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 962607259a6SChristoph Hellwig { 963607259a6SChristoph Hellwig struct ip_tunnel_parm p; 964607259a6SChristoph Hellwig int err; 965607259a6SChristoph Hellwig 966607259a6SChristoph Hellwig if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 967607259a6SChristoph Hellwig return -EFAULT; 968607259a6SChristoph Hellwig err = dev->netdev_ops->ndo_tunnel_ctl(dev, &p, cmd); 969607259a6SChristoph Hellwig if (!err && copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) 970607259a6SChristoph Hellwig return -EFAULT; 971607259a6SChristoph Hellwig return err; 972607259a6SChristoph Hellwig } 973c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_ioctl); 974c5441932SPravin B Shelar 9757e059158SDavid Wragg int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict) 976c5441932SPravin B Shelar { 977c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 978c5441932SPravin B Shelar int t_hlen = tunnel->hlen + sizeof(struct iphdr); 97928e104d0SVadim Fedorenko int max_mtu = IP_MAX_MTU - t_hlen; 980c5441932SPravin B Shelar 9819992a078SHangbin Liu if (dev->type == ARPHRD_ETHER) 9829992a078SHangbin Liu max_mtu -= dev->hard_header_len; 9839992a078SHangbin Liu 984b96f9afeSJarod Wilson if (new_mtu < ETH_MIN_MTU) 985c5441932SPravin B Shelar return -EINVAL; 9867e059158SDavid Wragg 9877e059158SDavid Wragg if (new_mtu > max_mtu) { 9887e059158SDavid Wragg if (strict) 9897e059158SDavid Wragg return -EINVAL; 9907e059158SDavid Wragg 9917e059158SDavid Wragg new_mtu = max_mtu; 9927e059158SDavid Wragg } 9937e059158SDavid Wragg 994c5441932SPravin B Shelar dev->mtu = new_mtu; 995c5441932SPravin B Shelar return 0; 996c5441932SPravin B Shelar } 9977e059158SDavid Wragg EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu); 9987e059158SDavid Wragg 9997e059158SDavid Wragg int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) 10007e059158SDavid Wragg { 10017e059158SDavid Wragg return __ip_tunnel_change_mtu(dev, new_mtu, true); 10027e059158SDavid Wragg } 1003c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu); 1004c5441932SPravin B Shelar 1005c5441932SPravin B Shelar static void ip_tunnel_dev_free(struct net_device *dev) 1006c5441932SPravin B Shelar { 1007c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1008c5441932SPravin B Shelar 1009c5441932SPravin B Shelar gro_cells_destroy(&tunnel->gro_cells); 1010e09acddfSPaolo Abeni dst_cache_destroy(&tunnel->dst_cache); 1011c5441932SPravin B Shelar free_percpu(dev->tstats); 1012c5441932SPravin B Shelar } 1013c5441932SPravin B Shelar 1014c5441932SPravin B Shelar void ip_tunnel_dellink(struct net_device *dev, struct list_head *head) 1015c5441932SPravin B Shelar { 1016c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1017c5441932SPravin B Shelar struct ip_tunnel_net *itn; 1018c5441932SPravin B Shelar 10196c742e71SNicolas Dichtel itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id); 1020c5441932SPravin B Shelar 1021c5441932SPravin B Shelar if (itn->fb_tunnel_dev != dev) { 10222e15ea39SPravin B Shelar ip_tunnel_del(itn, netdev_priv(dev)); 1023c5441932SPravin B Shelar unregister_netdevice_queue(dev, head); 1024c5441932SPravin B Shelar } 1025c5441932SPravin B Shelar } 1026c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_dellink); 1027c5441932SPravin B Shelar 10281728d4faSNicolas Dichtel struct net *ip_tunnel_get_link_net(const struct net_device *dev) 10291728d4faSNicolas Dichtel { 10301728d4faSNicolas Dichtel struct ip_tunnel *tunnel = netdev_priv(dev); 10311728d4faSNicolas Dichtel 10321728d4faSNicolas Dichtel return tunnel->net; 10331728d4faSNicolas Dichtel } 10341728d4faSNicolas Dichtel EXPORT_SYMBOL(ip_tunnel_get_link_net); 10351728d4faSNicolas Dichtel 10361e99584bSNicolas Dichtel int ip_tunnel_get_iflink(const struct net_device *dev) 10371e99584bSNicolas Dichtel { 10381e99584bSNicolas Dichtel struct ip_tunnel *tunnel = netdev_priv(dev); 10391e99584bSNicolas Dichtel 10401e99584bSNicolas Dichtel return tunnel->parms.link; 10411e99584bSNicolas Dichtel } 10421e99584bSNicolas Dichtel EXPORT_SYMBOL(ip_tunnel_get_iflink); 10431e99584bSNicolas Dichtel 1044c7d03a00SAlexey Dobriyan int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id, 1045c5441932SPravin B Shelar struct rtnl_link_ops *ops, char *devname) 1046c5441932SPravin B Shelar { 1047c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id); 1048c5441932SPravin B Shelar struct ip_tunnel_parm parms; 10496261d983Sstephen hemminger unsigned int i; 1050c5441932SPravin B Shelar 105179134e6cSEric Dumazet itn->rtnl_link_ops = ops; 10526261d983Sstephen hemminger for (i = 0; i < IP_TNL_HASH_SIZE; i++) 10536261d983Sstephen hemminger INIT_HLIST_HEAD(&itn->tunnels[i]); 1054c5441932SPravin B Shelar 105579134e6cSEric Dumazet if (!ops || !net_has_fallback_tunnels(net)) { 105679134e6cSEric Dumazet struct ip_tunnel_net *it_init_net; 105779134e6cSEric Dumazet 105879134e6cSEric Dumazet it_init_net = net_generic(&init_net, ip_tnl_net_id); 105979134e6cSEric Dumazet itn->type = it_init_net->type; 1060c5441932SPravin B Shelar itn->fb_tunnel_dev = NULL; 1061c5441932SPravin B Shelar return 0; 1062c5441932SPravin B Shelar } 10636261d983Sstephen hemminger 1064c5441932SPravin B Shelar memset(&parms, 0, sizeof(parms)); 1065c5441932SPravin B Shelar if (devname) 1066c5441932SPravin B Shelar strlcpy(parms.name, devname, IFNAMSIZ); 1067c5441932SPravin B Shelar 1068c5441932SPravin B Shelar rtnl_lock(); 1069c5441932SPravin B Shelar itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms); 1070ea857f28SDan Carpenter /* FB netdevice is special: we have one, and only one per netns. 1071ea857f28SDan Carpenter * Allowing to move it to another netns is clearly unsafe. 1072ea857f28SDan Carpenter */ 107367013282SSteffen Klassert if (!IS_ERR(itn->fb_tunnel_dev)) { 1074ea857f28SDan Carpenter itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; 107578ff4be4SSteffen Klassert itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev); 107667013282SSteffen Klassert ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev)); 107779134e6cSEric Dumazet itn->type = itn->fb_tunnel_dev->type; 107867013282SSteffen Klassert } 1079b4de77adSDan Carpenter rtnl_unlock(); 1080c5441932SPravin B Shelar 108127d79f3bSSachin Kamat return PTR_ERR_OR_ZERO(itn->fb_tunnel_dev); 1082c5441932SPravin B Shelar } 1083c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_init_net); 1084c5441932SPravin B Shelar 108579134e6cSEric Dumazet static void ip_tunnel_destroy(struct net *net, struct ip_tunnel_net *itn, 108679134e6cSEric Dumazet struct list_head *head, 10876c742e71SNicolas Dichtel struct rtnl_link_ops *ops) 1088c5441932SPravin B Shelar { 10896c742e71SNicolas Dichtel struct net_device *dev, *aux; 1090c5441932SPravin B Shelar int h; 1091c5441932SPravin B Shelar 10926c742e71SNicolas Dichtel for_each_netdev_safe(net, dev, aux) 10936c742e71SNicolas Dichtel if (dev->rtnl_link_ops == ops) 10946c742e71SNicolas Dichtel unregister_netdevice_queue(dev, head); 10956c742e71SNicolas Dichtel 1096c5441932SPravin B Shelar for (h = 0; h < IP_TNL_HASH_SIZE; h++) { 1097c5441932SPravin B Shelar struct ip_tunnel *t; 1098c5441932SPravin B Shelar struct hlist_node *n; 1099c5441932SPravin B Shelar struct hlist_head *thead = &itn->tunnels[h]; 1100c5441932SPravin B Shelar 1101c5441932SPravin B Shelar hlist_for_each_entry_safe(t, n, thead, hash_node) 11026c742e71SNicolas Dichtel /* If dev is in the same netns, it has already 11036c742e71SNicolas Dichtel * been added to the list by the previous loop. 11046c742e71SNicolas Dichtel */ 11056c742e71SNicolas Dichtel if (!net_eq(dev_net(t->dev), net)) 1106c5441932SPravin B Shelar unregister_netdevice_queue(t->dev, head); 1107c5441932SPravin B Shelar } 1108c5441932SPravin B Shelar } 1109c5441932SPravin B Shelar 111064bc1781SEric Dumazet void ip_tunnel_delete_nets(struct list_head *net_list, unsigned int id, 111164bc1781SEric Dumazet struct rtnl_link_ops *ops) 1112c5441932SPravin B Shelar { 111364bc1781SEric Dumazet struct ip_tunnel_net *itn; 111464bc1781SEric Dumazet struct net *net; 1115c5441932SPravin B Shelar LIST_HEAD(list); 1116c5441932SPravin B Shelar 1117c5441932SPravin B Shelar rtnl_lock(); 111864bc1781SEric Dumazet list_for_each_entry(net, net_list, exit_list) { 111964bc1781SEric Dumazet itn = net_generic(net, id); 112079134e6cSEric Dumazet ip_tunnel_destroy(net, itn, &list, ops); 112164bc1781SEric Dumazet } 1122c5441932SPravin B Shelar unregister_netdevice_many(&list); 1123c5441932SPravin B Shelar rtnl_unlock(); 1124c5441932SPravin B Shelar } 112564bc1781SEric Dumazet EXPORT_SYMBOL_GPL(ip_tunnel_delete_nets); 1126c5441932SPravin B Shelar 1127c5441932SPravin B Shelar int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], 11289830ad4cSCraig Gallek struct ip_tunnel_parm *p, __u32 fwmark) 1129c5441932SPravin B Shelar { 1130c5441932SPravin B Shelar struct ip_tunnel *nt; 1131c5441932SPravin B Shelar struct net *net = dev_net(dev); 1132c5441932SPravin B Shelar struct ip_tunnel_net *itn; 1133c5441932SPravin B Shelar int mtu; 1134c5441932SPravin B Shelar int err; 1135c5441932SPravin B Shelar 1136c5441932SPravin B Shelar nt = netdev_priv(dev); 1137c5441932SPravin B Shelar itn = net_generic(net, nt->ip_tnl_net_id); 1138c5441932SPravin B Shelar 11392e15ea39SPravin B Shelar if (nt->collect_md) { 11402e15ea39SPravin B Shelar if (rtnl_dereference(itn->collect_md_tun)) 11412e15ea39SPravin B Shelar return -EEXIST; 11422e15ea39SPravin B Shelar } else { 1143c5441932SPravin B Shelar if (ip_tunnel_find(itn, p, dev->type)) 1144c5441932SPravin B Shelar return -EEXIST; 11452e15ea39SPravin B Shelar } 1146c5441932SPravin B Shelar 11475e6700b3SNicolas Dichtel nt->net = net; 1148c5441932SPravin B Shelar nt->parms = *p; 11499830ad4cSCraig Gallek nt->fwmark = fwmark; 1150c5441932SPravin B Shelar err = register_netdevice(dev); 1151c5441932SPravin B Shelar if (err) 1152f6cc9c05SPetr Machata goto err_register_netdevice; 1153c5441932SPravin B Shelar 1154c5441932SPravin B Shelar if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS]) 1155c5441932SPravin B Shelar eth_hw_addr_random(dev); 1156c5441932SPravin B Shelar 1157c5441932SPravin B Shelar mtu = ip_tunnel_bind_dev(dev); 115824fc7979SStefano Brivio if (tb[IFLA_MTU]) { 115928e104d0SVadim Fedorenko unsigned int max = IP_MAX_MTU - (nt->hlen + sizeof(struct iphdr)); 116024fc7979SStefano Brivio 11619992a078SHangbin Liu if (dev->type == ARPHRD_ETHER) 11629992a078SHangbin Liu max -= dev->hard_header_len; 11639992a078SHangbin Liu 116428e104d0SVadim Fedorenko mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, max); 11655568cdc3SDavid S. Miller } 11665568cdc3SDavid S. Miller 1167f6cc9c05SPetr Machata err = dev_set_mtu(dev, mtu); 1168f6cc9c05SPetr Machata if (err) 1169f6cc9c05SPetr Machata goto err_dev_set_mtu; 1170c5441932SPravin B Shelar 1171c5441932SPravin B Shelar ip_tunnel_add(itn, nt); 1172f6cc9c05SPetr Machata return 0; 1173f6cc9c05SPetr Machata 1174f6cc9c05SPetr Machata err_dev_set_mtu: 1175f6cc9c05SPetr Machata unregister_netdevice(dev); 1176f6cc9c05SPetr Machata err_register_netdevice: 1177c5441932SPravin B Shelar return err; 1178c5441932SPravin B Shelar } 1179c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_newlink); 1180c5441932SPravin B Shelar 1181c5441932SPravin B Shelar int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], 11829830ad4cSCraig Gallek struct ip_tunnel_parm *p, __u32 fwmark) 1183c5441932SPravin B Shelar { 11846c742e71SNicolas Dichtel struct ip_tunnel *t; 1185c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 11866c742e71SNicolas Dichtel struct net *net = tunnel->net; 1187c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id); 1188c5441932SPravin B Shelar 1189c5441932SPravin B Shelar if (dev == itn->fb_tunnel_dev) 1190c5441932SPravin B Shelar return -EINVAL; 1191c5441932SPravin B Shelar 1192c5441932SPravin B Shelar t = ip_tunnel_find(itn, p, dev->type); 1193c5441932SPravin B Shelar 1194c5441932SPravin B Shelar if (t) { 1195c5441932SPravin B Shelar if (t->dev != dev) 1196c5441932SPravin B Shelar return -EEXIST; 1197c5441932SPravin B Shelar } else { 11986c742e71SNicolas Dichtel t = tunnel; 1199c5441932SPravin B Shelar 1200c5441932SPravin B Shelar if (dev->type != ARPHRD_ETHER) { 1201c5441932SPravin B Shelar unsigned int nflags = 0; 1202c5441932SPravin B Shelar 1203c5441932SPravin B Shelar if (ipv4_is_multicast(p->iph.daddr)) 1204c5441932SPravin B Shelar nflags = IFF_BROADCAST; 1205c5441932SPravin B Shelar else if (p->iph.daddr) 1206c5441932SPravin B Shelar nflags = IFF_POINTOPOINT; 1207c5441932SPravin B Shelar 1208c5441932SPravin B Shelar if ((dev->flags ^ nflags) & 1209c5441932SPravin B Shelar (IFF_POINTOPOINT | IFF_BROADCAST)) 1210c5441932SPravin B Shelar return -EINVAL; 1211c5441932SPravin B Shelar } 1212c5441932SPravin B Shelar } 1213c5441932SPravin B Shelar 12149830ad4cSCraig Gallek ip_tunnel_update(itn, t, dev, p, !tb[IFLA_MTU], fwmark); 1215c5441932SPravin B Shelar return 0; 1216c5441932SPravin B Shelar } 1217c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_changelink); 1218c5441932SPravin B Shelar 1219c5441932SPravin B Shelar int ip_tunnel_init(struct net_device *dev) 1220c5441932SPravin B Shelar { 1221c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1222c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 12231c213bd2SWANG Cong int err; 1224c5441932SPravin B Shelar 1225cf124db5SDavid S. Miller dev->needs_free_netdev = true; 1226cf124db5SDavid S. Miller dev->priv_destructor = ip_tunnel_dev_free; 12271c213bd2SWANG Cong dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 1228c5441932SPravin B Shelar if (!dev->tstats) 1229c5441932SPravin B Shelar return -ENOMEM; 1230c5441932SPravin B Shelar 1231e09acddfSPaolo Abeni err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); 1232e09acddfSPaolo Abeni if (err) { 12339a4aa9afSTom Herbert free_percpu(dev->tstats); 1234e09acddfSPaolo Abeni return err; 12359a4aa9afSTom Herbert } 12369a4aa9afSTom Herbert 1237c5441932SPravin B Shelar err = gro_cells_init(&tunnel->gro_cells, dev); 1238c5441932SPravin B Shelar if (err) { 1239e09acddfSPaolo Abeni dst_cache_destroy(&tunnel->dst_cache); 1240c5441932SPravin B Shelar free_percpu(dev->tstats); 1241c5441932SPravin B Shelar return err; 1242c5441932SPravin B Shelar } 1243c5441932SPravin B Shelar 1244c5441932SPravin B Shelar tunnel->dev = dev; 12456c742e71SNicolas Dichtel tunnel->net = dev_net(dev); 1246c5441932SPravin B Shelar strcpy(tunnel->parms.name, dev->name); 1247c5441932SPravin B Shelar iph->version = 4; 1248c5441932SPravin B Shelar iph->ihl = 5; 1249c5441932SPravin B Shelar 1250d0f41851SWilliam Dauchy if (tunnel->collect_md) 12512e15ea39SPravin B Shelar netif_keep_dst(dev); 1252c5441932SPravin B Shelar return 0; 1253c5441932SPravin B Shelar } 1254c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_init); 1255c5441932SPravin B Shelar 1256c5441932SPravin B Shelar void ip_tunnel_uninit(struct net_device *dev) 1257c5441932SPravin B Shelar { 1258c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 12596c742e71SNicolas Dichtel struct net *net = tunnel->net; 1260c5441932SPravin B Shelar struct ip_tunnel_net *itn; 1261c5441932SPravin B Shelar 1262c5441932SPravin B Shelar itn = net_generic(net, tunnel->ip_tnl_net_id); 12632e15ea39SPravin B Shelar ip_tunnel_del(itn, netdev_priv(dev)); 1264ba61539cSTaehee Yoo if (itn->fb_tunnel_dev == dev) 1265ba61539cSTaehee Yoo WRITE_ONCE(itn->fb_tunnel_dev, NULL); 12667d442fabSTom Herbert 1267e09acddfSPaolo Abeni dst_cache_reset(&tunnel->dst_cache); 1268c5441932SPravin B Shelar } 1269c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_uninit); 1270c5441932SPravin B Shelar 1271c5441932SPravin B Shelar /* Do least required initialization, rest of init is done in tunnel_init call */ 1272c7d03a00SAlexey Dobriyan void ip_tunnel_setup(struct net_device *dev, unsigned int net_id) 1273c5441932SPravin B Shelar { 1274c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1275c5441932SPravin B Shelar tunnel->ip_tnl_net_id = net_id; 1276c5441932SPravin B Shelar } 1277c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_setup); 1278c5441932SPravin B Shelar 1279c5441932SPravin B Shelar MODULE_LICENSE("GPL"); 1280