blob: 375d0e516d85f361461660e47ea6c438e4252952 [file] [log] [blame]
Pravin B Shelarc5441932013-03-25 14:49:35 +00001/*
2 * Copyright (c) 2013 Nicira, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301, USA
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/capability.h>
22#include <linux/module.h>
23#include <linux/types.h>
24#include <linux/kernel.h>
25#include <linux/slab.h>
26#include <linux/uaccess.h>
27#include <linux/skbuff.h>
28#include <linux/netdevice.h>
29#include <linux/in.h>
30#include <linux/tcp.h>
31#include <linux/udp.h>
32#include <linux/if_arp.h>
Pravin B Shelarc5441932013-03-25 14:49:35 +000033#include <linux/init.h>
34#include <linux/in6.h>
35#include <linux/inetdevice.h>
36#include <linux/igmp.h>
37#include <linux/netfilter_ipv4.h>
38#include <linux/etherdevice.h>
39#include <linux/if_ether.h>
40#include <linux/if_vlan.h>
41#include <linux/rculist.h>
Sachin Kamat27d79f32014-01-27 12:13:57 +053042#include <linux/err.h>
Pravin B Shelarc5441932013-03-25 14:49:35 +000043
44#include <net/sock.h>
45#include <net/ip.h>
46#include <net/icmp.h>
47#include <net/protocol.h>
48#include <net/ip_tunnels.h>
49#include <net/arp.h>
50#include <net/checksum.h>
51#include <net/dsfield.h>
52#include <net/inet_ecn.h>
53#include <net/xfrm.h>
54#include <net/net_namespace.h>
55#include <net/netns/generic.h>
56#include <net/rtnetlink.h>
Tom Herbert56328482014-09-17 12:25:58 -070057#include <net/udp.h>
Alexei Starovoitovcfc73812016-09-15 13:00:29 -070058#include <net/dst_metadata.h>
Tom Herbert63487ba2014-11-04 09:06:51 -080059
Pravin B Shelarc5441932013-03-25 14:49:35 +000060#if IS_ENABLED(CONFIG_IPV6)
61#include <net/ipv6.h>
62#include <net/ip6_fib.h>
63#include <net/ip6_route.h>
64#endif
65
Duan Jiong967680e2014-01-19 16:43:42 +080066static unsigned int ip_tunnel_hash(__be32 key, __be32 remote)
Pravin B Shelarc5441932013-03-25 14:49:35 +000067{
68 return hash_32((__force u32)key ^ (__force u32)remote,
69 IP_TNL_HASH_BITS);
70}
71
Pravin B Shelarc5441932013-03-25 14:49:35 +000072static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p,
73 __be16 flags, __be32 key)
74{
75 if (p->i_flags & TUNNEL_KEY) {
76 if (flags & TUNNEL_KEY)
77 return key == p->i_key;
78 else
79 /* key expected, none present */
80 return false;
81 } else
82 return !(flags & TUNNEL_KEY);
83}
84
85/* Fallback tunnel: no source, no destination, no key, no options
86
87 Tunnel hash table:
88 We require exact key match i.e. if a key is present in packet
89 it will match only tunnel with the same key; if it is not present,
90 it will match only keyless tunnel.
91
92 All keysless packets, if not matched configured keyless tunnels
93 will match fallback tunnel.
94 Given src, dst and key, find appropriate for input tunnel.
95*/
96struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
97 int link, __be16 flags,
98 __be32 remote, __be32 local,
99 __be32 key)
100{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000101 struct ip_tunnel *t, *cand = NULL;
102 struct hlist_head *head;
Taehee Yoo3ee1d442020-06-16 16:51:51 +0000103 struct net_device *ndev;
104 unsigned int hash;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000105
Duan Jiong967680e2014-01-19 16:43:42 +0800106 hash = ip_tunnel_hash(key, remote);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000107 head = &itn->tunnels[hash];
108
109 hlist_for_each_entry_rcu(t, head, hash_node) {
110 if (local != t->parms.iph.saddr ||
111 remote != t->parms.iph.daddr ||
112 !(t->dev->flags & IFF_UP))
113 continue;
114
115 if (!ip_tunnel_key_match(&t->parms, flags, key))
116 continue;
117
118 if (t->parms.link == link)
119 return t;
120 else
121 cand = t;
122 }
123
124 hlist_for_each_entry_rcu(t, head, hash_node) {
125 if (remote != t->parms.iph.daddr ||
Dmitry Popove0056592014-07-05 02:26:37 +0400126 t->parms.iph.saddr != 0 ||
Pravin B Shelarc5441932013-03-25 14:49:35 +0000127 !(t->dev->flags & IFF_UP))
128 continue;
129
130 if (!ip_tunnel_key_match(&t->parms, flags, key))
131 continue;
132
133 if (t->parms.link == link)
134 return t;
135 else if (!cand)
136 cand = t;
137 }
138
Duan Jiong967680e2014-01-19 16:43:42 +0800139 hash = ip_tunnel_hash(key, 0);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000140 head = &itn->tunnels[hash];
141
142 hlist_for_each_entry_rcu(t, head, hash_node) {
Dmitry Popove0056592014-07-05 02:26:37 +0400143 if ((local != t->parms.iph.saddr || t->parms.iph.daddr != 0) &&
144 (local != t->parms.iph.daddr || !ipv4_is_multicast(local)))
145 continue;
146
147 if (!(t->dev->flags & IFF_UP))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000148 continue;
149
150 if (!ip_tunnel_key_match(&t->parms, flags, key))
151 continue;
152
153 if (t->parms.link == link)
154 return t;
155 else if (!cand)
156 cand = t;
157 }
158
Pravin B Shelarc5441932013-03-25 14:49:35 +0000159 hlist_for_each_entry_rcu(t, head, hash_node) {
William Dauchy48dee022020-03-27 19:56:39 +0100160 if ((!(flags & TUNNEL_NO_KEY) && t->parms.i_key != key) ||
Dmitry Popove0056592014-07-05 02:26:37 +0400161 t->parms.iph.saddr != 0 ||
162 t->parms.iph.daddr != 0 ||
Pravin B Shelarc5441932013-03-25 14:49:35 +0000163 !(t->dev->flags & IFF_UP))
164 continue;
165
166 if (t->parms.link == link)
167 return t;
168 else if (!cand)
169 cand = t;
170 }
171
Pravin B Shelarc5441932013-03-25 14:49:35 +0000172 if (cand)
173 return cand;
174
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700175 t = rcu_dereference(itn->collect_md_tun);
Haishuang Yan833a8b42017-09-12 17:47:56 +0800176 if (t && t->dev->flags & IFF_UP)
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700177 return t;
178
Taehee Yoo3ee1d442020-06-16 16:51:51 +0000179 ndev = READ_ONCE(itn->fb_tunnel_dev);
180 if (ndev && ndev->flags & IFF_UP)
181 return netdev_priv(ndev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000182
Pravin B Shelarc5441932013-03-25 14:49:35 +0000183 return NULL;
184}
185EXPORT_SYMBOL_GPL(ip_tunnel_lookup);
186
187static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn,
188 struct ip_tunnel_parm *parms)
189{
190 unsigned int h;
191 __be32 remote;
Steffen Klassert6d608f02014-02-21 08:41:09 +0100192 __be32 i_key = parms->i_key;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000193
194 if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr))
195 remote = parms->iph.daddr;
196 else
197 remote = 0;
198
Steffen Klassert6d608f02014-02-21 08:41:09 +0100199 if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI))
200 i_key = 0;
201
202 h = ip_tunnel_hash(i_key, remote);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000203 return &itn->tunnels[h];
204}
205
206static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t)
207{
208 struct hlist_head *head = ip_bucket(itn, &t->parms);
209
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700210 if (t->collect_md)
211 rcu_assign_pointer(itn->collect_md_tun, t);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000212 hlist_add_head_rcu(&t->hash_node, head);
213}
214
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700215static void ip_tunnel_del(struct ip_tunnel_net *itn, struct ip_tunnel *t)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000216{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700217 if (t->collect_md)
218 rcu_assign_pointer(itn->collect_md_tun, NULL);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000219 hlist_del_init_rcu(&t->hash_node);
220}
221
222static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn,
223 struct ip_tunnel_parm *parms,
224 int type)
225{
226 __be32 remote = parms->iph.daddr;
227 __be32 local = parms->iph.saddr;
228 __be32 key = parms->i_key;
Dmitry Popov5ce54af2014-06-08 03:03:08 +0400229 __be16 flags = parms->i_flags;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000230 int link = parms->link;
231 struct ip_tunnel *t = NULL;
232 struct hlist_head *head = ip_bucket(itn, parms);
233
234 hlist_for_each_entry_rcu(t, head, hash_node) {
235 if (local == t->parms.iph.saddr &&
236 remote == t->parms.iph.daddr &&
Pravin B Shelarc5441932013-03-25 14:49:35 +0000237 link == t->parms.link &&
Dmitry Popov5ce54af2014-06-08 03:03:08 +0400238 type == t->dev->type &&
239 ip_tunnel_key_match(&t->parms, flags, key))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000240 break;
241 }
242 return t;
243}
244
245static struct net_device *__ip_tunnel_create(struct net *net,
246 const struct rtnl_link_ops *ops,
247 struct ip_tunnel_parm *parms)
248{
249 int err;
250 struct ip_tunnel *tunnel;
251 struct net_device *dev;
252 char name[IFNAMSIZ];
253
Eric Dumazet9cb726a2018-04-05 06:39:27 -0700254 err = -E2BIG;
255 if (parms->name[0]) {
256 if (!dev_valid_name(parms->name))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000257 goto failed;
Eric Dumazet9cb726a2018-04-05 06:39:27 -0700258 strlcpy(name, parms->name, IFNAMSIZ);
259 } else {
260 if (strlen(ops->kind) > (IFNAMSIZ - 3))
261 goto failed;
Sultan Alsawaf000ade82018-06-06 15:56:54 -0700262 strcpy(name, ops->kind);
263 strcat(name, "%d");
Pravin B Shelarc5441932013-03-25 14:49:35 +0000264 }
265
266 ASSERT_RTNL();
Tom Gundersenc835a672014-07-14 16:37:24 +0200267 dev = alloc_netdev(ops->priv_size, name, NET_NAME_UNKNOWN, ops->setup);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000268 if (!dev) {
269 err = -ENOMEM;
270 goto failed;
271 }
272 dev_net_set(dev, net);
273
274 dev->rtnl_link_ops = ops;
275
276 tunnel = netdev_priv(dev);
277 tunnel->parms = *parms;
Nicolas Dichtel5e6700b2013-06-26 16:11:28 +0200278 tunnel->net = net;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000279
280 err = register_netdevice(dev);
281 if (err)
282 goto failed_free;
283
284 return dev;
285
286failed_free:
287 free_netdev(dev);
288failed:
289 return ERR_PTR(err);
290}
291
Pravin B Shelarc5441932013-03-25 14:49:35 +0000292static int ip_tunnel_bind_dev(struct net_device *dev)
293{
294 struct net_device *tdev = NULL;
295 struct ip_tunnel *tunnel = netdev_priv(dev);
296 const struct iphdr *iph;
297 int hlen = LL_MAX_HEADER;
298 int mtu = ETH_DATA_LEN;
299 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
300
301 iph = &tunnel->parms.iph;
302
303 /* Guess output device to choose reasonable mtu and needed_headroom */
304 if (iph->daddr) {
305 struct flowi4 fl4;
306 struct rtable *rt;
307
Petr Machatab0066da2018-02-27 14:53:38 +0100308 ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
309 iph->saddr, tunnel->parms.o_key,
310 RT_TOS(iph->tos), tunnel->parms.link,
311 tunnel->fwmark);
Tom Herbert7d442fa2014-01-02 11:48:26 -0800312 rt = ip_route_output_key(tunnel->net, &fl4);
313
Pravin B Shelarc5441932013-03-25 14:49:35 +0000314 if (!IS_ERR(rt)) {
315 tdev = rt->dst.dev;
316 ip_rt_put(rt);
317 }
318 if (dev->type != ARPHRD_ETHER)
319 dev->flags |= IFF_POINTOPOINT;
Paolo Abenif27337e2016-04-28 11:04:51 +0200320
321 dst_cache_reset(&tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000322 }
323
324 if (!tdev && tunnel->parms.link)
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200325 tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000326
327 if (tdev) {
328 hlen = tdev->hard_header_len + tdev->needed_headroom;
Nicolas Dichtel82612de2018-05-31 10:59:32 +0200329 mtu = min(tdev->mtu, IP_MAX_MTU);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000330 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000331
332 dev->needed_headroom = t_hlen + hlen;
333 mtu -= (dev->hard_header_len + t_hlen);
334
Eric Dumazetb5476022017-12-11 07:17:39 -0800335 if (mtu < IPV4_MIN_MTU)
336 mtu = IPV4_MIN_MTU;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000337
338 return mtu;
339}
340
341static struct ip_tunnel *ip_tunnel_create(struct net *net,
342 struct ip_tunnel_net *itn,
343 struct ip_tunnel_parm *parms)
344{
Julia Lawall4929fd82014-05-15 05:43:20 +0200345 struct ip_tunnel *nt;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000346 struct net_device *dev;
Jarod Wilsonb96f9af2016-10-20 13:55:24 -0400347 int t_hlen;
Petr Machataf6cc9c02018-03-22 19:53:33 +0200348 int mtu;
349 int err;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000350
Eric Dumazet79134e62018-03-08 12:51:41 -0800351 dev = __ip_tunnel_create(net, itn->rtnl_link_ops, parms);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000352 if (IS_ERR(dev))
Florian Westphal6dd3c9e2014-02-14 13:14:39 +0100353 return ERR_CAST(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000354
Petr Machataf6cc9c02018-03-22 19:53:33 +0200355 mtu = ip_tunnel_bind_dev(dev);
356 err = dev_set_mtu(dev, mtu);
357 if (err)
358 goto err_dev_set_mtu;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000359
360 nt = netdev_priv(dev);
Jarod Wilsonb96f9af2016-10-20 13:55:24 -0400361 t_hlen = nt->hlen + sizeof(struct iphdr);
362 dev->min_mtu = ETH_MIN_MTU;
Nicolas Dichtel82612de2018-05-31 10:59:32 +0200363 dev->max_mtu = IP_MAX_MTU - dev->hard_header_len - t_hlen;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000364 ip_tunnel_add(itn, nt);
365 return nt;
Petr Machataf6cc9c02018-03-22 19:53:33 +0200366
367err_dev_set_mtu:
368 unregister_netdevice(dev);
369 return ERR_PTR(err);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000370}
371
372int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700373 const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst,
374 bool log_ecn_error)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000375{
Li RongQing8f849852014-01-04 13:57:59 +0800376 struct pcpu_sw_netstats *tstats;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000377 const struct iphdr *iph = ip_hdr(skb);
378 int err;
379
Pravin B Shelarc5441932013-03-25 14:49:35 +0000380#ifdef CONFIG_NET_IPGRE_BROADCAST
381 if (ipv4_is_multicast(iph->daddr)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000382 tunnel->dev->stats.multicast++;
383 skb->pkt_type = PACKET_BROADCAST;
384 }
385#endif
386
387 if ((!(tpi->flags&TUNNEL_CSUM) && (tunnel->parms.i_flags&TUNNEL_CSUM)) ||
388 ((tpi->flags&TUNNEL_CSUM) && !(tunnel->parms.i_flags&TUNNEL_CSUM))) {
389 tunnel->dev->stats.rx_crc_errors++;
390 tunnel->dev->stats.rx_errors++;
391 goto drop;
392 }
393
394 if (tunnel->parms.i_flags&TUNNEL_SEQ) {
395 if (!(tpi->flags&TUNNEL_SEQ) ||
396 (tunnel->i_seqno && (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) {
397 tunnel->dev->stats.rx_fifo_errors++;
398 tunnel->dev->stats.rx_errors++;
399 goto drop;
400 }
401 tunnel->i_seqno = ntohl(tpi->seq) + 1;
402 }
403
Ying Caie96f2e72014-05-04 15:20:04 -0700404 skb_reset_network_header(skb);
405
Pravin B Shelarc5441932013-03-25 14:49:35 +0000406 err = IP_ECN_decapsulate(iph, skb);
407 if (unlikely(err)) {
408 if (log_ecn_error)
409 net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
410 &iph->saddr, iph->tos);
411 if (err > 1) {
412 ++tunnel->dev->stats.rx_frame_errors;
413 ++tunnel->dev->stats.rx_errors;
414 goto drop;
415 }
416 }
417
418 tstats = this_cpu_ptr(tunnel->dev->tstats);
419 u64_stats_update_begin(&tstats->syncp);
420 tstats->rx_packets++;
421 tstats->rx_bytes += skb->len;
422 u64_stats_update_end(&tstats->syncp);
423
Alexei Starovoitov81b9eab2013-11-12 14:39:13 -0800424 skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev)));
425
Pravin B Shelar3d7b46c2013-06-17 17:50:02 -0700426 if (tunnel->dev->type == ARPHRD_ETHER) {
427 skb->protocol = eth_type_trans(skb, tunnel->dev);
428 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
429 } else {
430 skb->dev = tunnel->dev;
431 }
Nicolas Dichtel64261f22013-08-13 17:51:09 +0200432
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700433 if (tun_dst)
434 skb_dst_set(skb, (struct dst_entry *)tun_dst);
435
Pravin B Shelarc5441932013-03-25 14:49:35 +0000436 gro_cells_receive(&tunnel->gro_cells, skb);
437 return 0;
438
439drop:
Haishuang Yan469f87e2017-06-15 10:29:29 +0800440 if (tun_dst)
441 dst_release((struct dst_entry *)tun_dst);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000442 kfree_skb(skb);
443 return 0;
444}
445EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
446
Tom Herberta8c5f902014-11-12 11:54:09 -0800447int ip_tunnel_encap_add_ops(const struct ip_tunnel_encap_ops *ops,
448 unsigned int num)
449{
Thomas Grafbb1553c2014-12-16 21:05:20 +0100450 if (num >= MAX_IPTUN_ENCAP_OPS)
451 return -ERANGE;
452
Tom Herberta8c5f902014-11-12 11:54:09 -0800453 return !cmpxchg((const struct ip_tunnel_encap_ops **)
454 &iptun_encaps[num],
455 NULL, ops) ? 0 : -1;
456}
457EXPORT_SYMBOL(ip_tunnel_encap_add_ops);
458
459int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *ops,
460 unsigned int num)
461{
462 int ret;
463
Thomas Grafbb1553c2014-12-16 21:05:20 +0100464 if (num >= MAX_IPTUN_ENCAP_OPS)
465 return -ERANGE;
466
Tom Herberta8c5f902014-11-12 11:54:09 -0800467 ret = (cmpxchg((const struct ip_tunnel_encap_ops **)
468 &iptun_encaps[num],
469 ops, NULL) == ops) ? 0 : -1;
470
471 synchronize_net();
472
473 return ret;
474}
475EXPORT_SYMBOL(ip_tunnel_encap_del_ops);
476
Tom Herbert56328482014-09-17 12:25:58 -0700477int ip_tunnel_encap_setup(struct ip_tunnel *t,
478 struct ip_tunnel_encap *ipencap)
479{
480 int hlen;
481
482 memset(&t->encap, 0, sizeof(t->encap));
483
484 hlen = ip_encap_hlen(ipencap);
485 if (hlen < 0)
486 return hlen;
487
488 t->encap.type = ipencap->type;
489 t->encap.sport = ipencap->sport;
490 t->encap.dport = ipencap->dport;
491 t->encap.flags = ipencap->flags;
492
493 t->encap_hlen = hlen;
494 t->hlen = t->encap_hlen + t->tun_hlen;
495
496 return 0;
497}
498EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup);
499
Pravin B Shelar23a36472013-07-02 10:57:33 -0700500static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
Timo Teräsfc24f2b2015-07-07 08:34:13 +0300501 struct rtable *rt, __be16 df,
502 const struct iphdr *inner_iph)
Pravin B Shelar23a36472013-07-02 10:57:33 -0700503{
504 struct ip_tunnel *tunnel = netdev_priv(dev);
Alexander Duyck8c91e162013-07-11 13:12:22 -0700505 int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len;
Pravin B Shelar23a36472013-07-02 10:57:33 -0700506 int mtu;
507
508 if (df)
509 mtu = dst_mtu(&rt->dst) - dev->hard_header_len
510 - sizeof(struct iphdr) - tunnel->hlen;
511 else
512 mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
513
Hangbin Liu2c062782019-12-22 10:51:13 +0800514 skb_dst_update_pmtu_no_confirm(skb, mtu);
Pravin B Shelar23a36472013-07-02 10:57:33 -0700515
516 if (skb->protocol == htons(ETH_P_IP)) {
517 if (!skb_is_gso(skb) &&
Timo Teräsfc24f2b2015-07-07 08:34:13 +0300518 (inner_iph->frag_off & htons(IP_DF)) &&
519 mtu < pkt_size) {
Pravin B Shelar23a36472013-07-02 10:57:33 -0700520 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
521 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
522 return -E2BIG;
523 }
524 }
525#if IS_ENABLED(CONFIG_IPV6)
526 else if (skb->protocol == htons(ETH_P_IPV6)) {
527 struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
528
529 if (rt6 && mtu < dst_mtu(skb_dst(skb)) &&
530 mtu >= IPV6_MIN_MTU) {
531 if ((tunnel->parms.iph.daddr &&
532 !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
533 rt6->rt6i_dst.plen == 128) {
534 rt6->rt6i_flags |= RTF_MODIFIED;
535 dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
536 }
537 }
538
539 if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU &&
540 mtu < pkt_size) {
541 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
542 return -E2BIG;
543 }
544 }
545#endif
546 return 0;
547}
548
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700549void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, u8 proto)
550{
551 struct ip_tunnel *tunnel = netdev_priv(dev);
552 u32 headroom = sizeof(struct iphdr);
553 struct ip_tunnel_info *tun_info;
554 const struct ip_tunnel_key *key;
555 const struct iphdr *inner_iph;
556 struct rtable *rt;
557 struct flowi4 fl4;
558 __be16 df = 0;
559 u8 tos, ttl;
560
561 tun_info = skb_tunnel_info(skb);
562 if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
563 ip_tunnel_info_af(tun_info) != AF_INET))
564 goto tx_error;
565 key = &tun_info->key;
566 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
567 inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
568 tos = key->tos;
569 if (tos == 1) {
570 if (skb->protocol == htons(ETH_P_IP))
571 tos = inner_iph->tos;
572 else if (skb->protocol == htons(ETH_P_IPV6))
573 tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
574 }
wenxu7761d0c2019-01-22 18:39:51 +0800575 ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src,
576 tunnel_id_to_key32(key->tun_id), RT_TOS(tos),
577 0, skb->mark);
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700578 if (tunnel->encap.type != TUNNEL_ENCAP_NONE)
579 goto tx_error;
580 rt = ip_route_output_key(tunnel->net, &fl4);
581 if (IS_ERR(rt)) {
582 dev->stats.tx_carrier_errors++;
583 goto tx_error;
584 }
585 if (rt->dst.dev == dev) {
586 ip_rt_put(rt);
587 dev->stats.collisions++;
588 goto tx_error;
589 }
590 tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
591 ttl = key->ttl;
592 if (ttl == 0) {
593 if (skb->protocol == htons(ETH_P_IP))
594 ttl = inner_iph->ttl;
595 else if (skb->protocol == htons(ETH_P_IPV6))
596 ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
597 else
598 ttl = ip4_dst_hoplimit(&rt->dst);
599 }
600 if (key->tun_flags & TUNNEL_DONT_FRAGMENT)
601 df = htons(IP_DF);
602 else if (skb->protocol == htons(ETH_P_IP))
603 df = inner_iph->frag_off & htons(IP_DF);
604 headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len;
605 if (headroom > dev->needed_headroom)
606 dev->needed_headroom = headroom;
607
608 if (skb_cow_head(skb, dev->needed_headroom)) {
609 ip_rt_put(rt);
610 goto tx_dropped;
611 }
Haishuang Yan0f693f12017-09-07 14:08:34 +0800612 iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, proto, tos, ttl,
613 df, !net_eq(tunnel->net, dev_net(dev)));
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700614 return;
615tx_error:
616 dev->stats.tx_errors++;
617 goto kfree;
618tx_dropped:
619 dev->stats.tx_dropped++;
620kfree:
621 kfree_skb(skb);
622}
623EXPORT_SYMBOL_GPL(ip_md_tunnel_xmit);
624
Pravin B Shelarc5441932013-03-25 14:49:35 +0000625void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
Tom Herbert56328482014-09-17 12:25:58 -0700626 const struct iphdr *tnl_params, u8 protocol)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000627{
628 struct ip_tunnel *tunnel = netdev_priv(dev);
629 const struct iphdr *inner_iph;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000630 struct flowi4 fl4;
631 u8 tos, ttl;
632 __be16 df;
Eric Dumazetb045d372014-02-03 12:52:14 -0800633 struct rtable *rt; /* Route to the other host */
Pravin B Shelarc5441932013-03-25 14:49:35 +0000634 unsigned int max_headroom; /* The extra header space needed */
635 __be32 dst;
Timo Teräs22fb22e2014-05-16 08:34:39 +0300636 bool connected;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000637
638 inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
Timo Teräs22fb22e2014-05-16 08:34:39 +0300639 connected = (tunnel->parms.iph.daddr != 0);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000640
Bernie Harris5146d1f2016-02-22 12:58:05 +1300641 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
642
Pravin B Shelarc5441932013-03-25 14:49:35 +0000643 dst = tnl_params->daddr;
644 if (dst == 0) {
645 /* NBMA tunnel */
wenxu9f1ac492019-01-19 13:11:25 +0800646 struct ip_tunnel_info *tun_info;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000647
Ian Morris51456b22015-04-03 09:17:26 +0100648 if (!skb_dst(skb)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000649 dev->stats.tx_fifo_errors++;
650 goto tx_error;
651 }
652
wenxu9f1ac492019-01-19 13:11:25 +0800653 tun_info = skb_tunnel_info(skb);
654 if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) &&
655 ip_tunnel_info_af(tun_info) == AF_INET &&
656 tun_info->key.u.ipv4.dst)
657 dst = tun_info->key.u.ipv4.dst;
658 else if (skb->protocol == htons(ETH_P_IP)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000659 rt = skb_rtable(skb);
660 dst = rt_nexthop(rt, inner_iph->daddr);
661 }
662#if IS_ENABLED(CONFIG_IPV6)
663 else if (skb->protocol == htons(ETH_P_IPV6)) {
664 const struct in6_addr *addr6;
665 struct neighbour *neigh;
666 bool do_tx_error_icmp;
667 int addr_type;
668
669 neigh = dst_neigh_lookup(skb_dst(skb),
670 &ipv6_hdr(skb)->daddr);
Ian Morris51456b22015-04-03 09:17:26 +0100671 if (!neigh)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000672 goto tx_error;
673
674 addr6 = (const struct in6_addr *)&neigh->primary_key;
675 addr_type = ipv6_addr_type(addr6);
676
677 if (addr_type == IPV6_ADDR_ANY) {
678 addr6 = &ipv6_hdr(skb)->daddr;
679 addr_type = ipv6_addr_type(addr6);
680 }
681
682 if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
683 do_tx_error_icmp = true;
684 else {
685 do_tx_error_icmp = false;
686 dst = addr6->s6_addr32[3];
687 }
688 neigh_release(neigh);
689 if (do_tx_error_icmp)
690 goto tx_error_icmp;
691 }
692#endif
693 else
694 goto tx_error;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800695
696 connected = false;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000697 }
698
699 tos = tnl_params->tos;
700 if (tos & 0x1) {
701 tos &= ~0x1;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800702 if (skb->protocol == htons(ETH_P_IP)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000703 tos = inner_iph->tos;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800704 connected = false;
705 } else if (skb->protocol == htons(ETH_P_IPV6)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000706 tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
Tom Herbert7d442fa2014-01-02 11:48:26 -0800707 connected = false;
708 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000709 }
710
David S. Miller0f3e9c92018-03-06 00:53:44 -0500711 ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
712 tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link,
713 tunnel->fwmark);
Tom Herbert7d442fa2014-01-02 11:48:26 -0800714
Tom Herbert56328482014-09-17 12:25:58 -0700715 if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
716 goto tx_error;
717
Paolo Abenie09acdd2016-02-12 15:43:55 +0100718 rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache, &fl4.saddr) :
719 NULL;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800720
721 if (!rt) {
722 rt = ip_route_output_key(tunnel->net, &fl4);
723
724 if (IS_ERR(rt)) {
725 dev->stats.tx_carrier_errors++;
726 goto tx_error;
727 }
728 if (connected)
Paolo Abenie09acdd2016-02-12 15:43:55 +0100729 dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst,
730 fl4.saddr);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000731 }
Tom Herbert7d442fa2014-01-02 11:48:26 -0800732
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700733 if (rt->dst.dev == dev) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000734 ip_rt_put(rt);
735 dev->stats.collisions++;
736 goto tx_error;
737 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000738
Timo Teräsfc24f2b2015-07-07 08:34:13 +0300739 if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph)) {
Pravin B Shelar23a36472013-07-02 10:57:33 -0700740 ip_rt_put(rt);
741 goto tx_error;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000742 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000743
744 if (tunnel->err_count > 0) {
745 if (time_before(jiffies,
746 tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
747 tunnel->err_count--;
748
749 dst_link_failure(skb);
750 } else
751 tunnel->err_count = 0;
752 }
753
Pravin B Shelard4a71b12013-09-25 09:57:47 -0700754 tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000755 ttl = tnl_params->ttl;
756 if (ttl == 0) {
757 if (skb->protocol == htons(ETH_P_IP))
758 ttl = inner_iph->ttl;
759#if IS_ENABLED(CONFIG_IPV6)
760 else if (skb->protocol == htons(ETH_P_IPV6))
761 ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
762#endif
763 else
764 ttl = ip4_dst_hoplimit(&rt->dst);
765 }
766
Pravin B Shelar23a36472013-07-02 10:57:33 -0700767 df = tnl_params->frag_off;
Philip Prindeville22a59be2016-06-14 15:53:02 -0600768 if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
Pravin B Shelar23a36472013-07-02 10:57:33 -0700769 df |= (inner_iph->frag_off&htons(IP_DF));
770
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700771 max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
Tom Herbert7371e022014-10-03 15:48:07 -0700772 + rt->dst.header_len + ip_encap_hlen(&tunnel->encap);
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200773 if (max_headroom > dev->needed_headroom)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000774 dev->needed_headroom = max_headroom;
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200775
776 if (skb_cow_head(skb, dev->needed_headroom)) {
Dmitry Popov586d5fc2014-06-06 04:34:37 +0400777 ip_rt_put(rt);
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200778 dev->stats.tx_dropped++;
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800779 kfree_skb(skb);
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200780 return;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000781 }
782
Pravin B Shelar039f5062015-12-24 14:34:54 -0800783 iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl,
784 df, !net_eq(tunnel->net, dev_net(dev)));
Pravin B Shelarc5441932013-03-25 14:49:35 +0000785 return;
786
787#if IS_ENABLED(CONFIG_IPV6)
788tx_error_icmp:
789 dst_link_failure(skb);
790#endif
791tx_error:
792 dev->stats.tx_errors++;
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800793 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000794}
795EXPORT_SYMBOL_GPL(ip_tunnel_xmit);
796
797static void ip_tunnel_update(struct ip_tunnel_net *itn,
798 struct ip_tunnel *t,
799 struct net_device *dev,
800 struct ip_tunnel_parm *p,
Craig Gallek9830ad42017-04-19 12:30:54 -0400801 bool set_mtu,
802 __u32 fwmark)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000803{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700804 ip_tunnel_del(itn, t);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000805 t->parms.iph.saddr = p->iph.saddr;
806 t->parms.iph.daddr = p->iph.daddr;
807 t->parms.i_key = p->i_key;
808 t->parms.o_key = p->o_key;
809 if (dev->type != ARPHRD_ETHER) {
810 memcpy(dev->dev_addr, &p->iph.saddr, 4);
811 memcpy(dev->broadcast, &p->iph.daddr, 4);
812 }
813 ip_tunnel_add(itn, t);
814
815 t->parms.iph.ttl = p->iph.ttl;
816 t->parms.iph.tos = p->iph.tos;
817 t->parms.iph.frag_off = p->iph.frag_off;
818
Craig Gallek9830ad42017-04-19 12:30:54 -0400819 if (t->parms.link != p->link || t->fwmark != fwmark) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000820 int mtu;
821
822 t->parms.link = p->link;
Craig Gallek9830ad42017-04-19 12:30:54 -0400823 t->fwmark = fwmark;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000824 mtu = ip_tunnel_bind_dev(dev);
825 if (set_mtu)
826 dev->mtu = mtu;
827 }
Paolo Abenie09acdd2016-02-12 15:43:55 +0100828 dst_cache_reset(&t->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000829 netdev_state_change(dev);
830}
831
832int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
833{
834 int err = 0;
Nicolas Dichtel8c923ce2014-04-16 11:19:32 +0200835 struct ip_tunnel *t = netdev_priv(dev);
836 struct net *net = t->net;
837 struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000838
Pravin B Shelarc5441932013-03-25 14:49:35 +0000839 switch (cmd) {
840 case SIOCGETTUNNEL:
Nicolas Dichtel8c923ce2014-04-16 11:19:32 +0200841 if (dev == itn->fb_tunnel_dev) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000842 t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
Ian Morris51456b22015-04-03 09:17:26 +0100843 if (!t)
Nicolas Dichtel8c923ce2014-04-16 11:19:32 +0200844 t = netdev_priv(dev);
845 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000846 memcpy(p, &t->parms, sizeof(*p));
847 break;
848
849 case SIOCADDTUNNEL:
850 case SIOCCHGTUNNEL:
851 err = -EPERM;
852 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
853 goto done;
854 if (p->iph.ttl)
855 p->iph.frag_off |= htons(IP_DF);
Dmitry Popov7c8e6b92014-06-08 02:06:25 +0400856 if (!(p->i_flags & VTI_ISVTI)) {
857 if (!(p->i_flags & TUNNEL_KEY))
858 p->i_key = 0;
859 if (!(p->o_flags & TUNNEL_KEY))
860 p->o_key = 0;
861 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000862
Eric Dumazet79134e62018-03-08 12:51:41 -0800863 t = ip_tunnel_find(itn, p, itn->type);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000864
Steffen Klassertd61746b2014-09-22 09:11:08 +0200865 if (cmd == SIOCADDTUNNEL) {
866 if (!t) {
867 t = ip_tunnel_create(net, itn, p);
868 err = PTR_ERR_OR_ZERO(t);
869 break;
870 }
871
872 err = -EEXIST;
Duan Jiongee30ef42014-05-15 13:07:02 +0800873 break;
Florian Westphal6dd3c9e2014-02-14 13:14:39 +0100874 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000875 if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
Ian Morris00db4122015-04-03 09:17:27 +0100876 if (t) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000877 if (t->dev != dev) {
878 err = -EEXIST;
879 break;
880 }
881 } else {
882 unsigned int nflags = 0;
883
884 if (ipv4_is_multicast(p->iph.daddr))
885 nflags = IFF_BROADCAST;
886 else if (p->iph.daddr)
887 nflags = IFF_POINTOPOINT;
888
889 if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
890 err = -EINVAL;
891 break;
892 }
893
894 t = netdev_priv(dev);
895 }
896 }
897
898 if (t) {
899 err = 0;
Craig Gallek9830ad42017-04-19 12:30:54 -0400900 ip_tunnel_update(itn, t, dev, p, true, 0);
Florian Westphal6dd3c9e2014-02-14 13:14:39 +0100901 } else {
902 err = -ENOENT;
903 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000904 break;
905
906 case SIOCDELTUNNEL:
907 err = -EPERM;
908 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
909 goto done;
910
911 if (dev == itn->fb_tunnel_dev) {
912 err = -ENOENT;
913 t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
Ian Morris51456b22015-04-03 09:17:26 +0100914 if (!t)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000915 goto done;
916 err = -EPERM;
917 if (t == netdev_priv(itn->fb_tunnel_dev))
918 goto done;
919 dev = t->dev;
920 }
921 unregister_netdevice(dev);
922 err = 0;
923 break;
924
925 default:
926 err = -EINVAL;
927 }
928
929done:
930 return err;
931}
932EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);
933
David Wragg7e059152016-02-10 00:05:58 +0000934int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000935{
936 struct ip_tunnel *tunnel = netdev_priv(dev);
937 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
Nicolas Dichtel82612de2018-05-31 10:59:32 +0200938 int max_mtu = IP_MAX_MTU - dev->hard_header_len - t_hlen;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000939
Jarod Wilsonb96f9af2016-10-20 13:55:24 -0400940 if (new_mtu < ETH_MIN_MTU)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000941 return -EINVAL;
David Wragg7e059152016-02-10 00:05:58 +0000942
943 if (new_mtu > max_mtu) {
944 if (strict)
945 return -EINVAL;
946
947 new_mtu = max_mtu;
948 }
949
Pravin B Shelarc5441932013-03-25 14:49:35 +0000950 dev->mtu = new_mtu;
951 return 0;
952}
David Wragg7e059152016-02-10 00:05:58 +0000953EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu);
954
955int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
956{
957 return __ip_tunnel_change_mtu(dev, new_mtu, true);
958}
Pravin B Shelarc5441932013-03-25 14:49:35 +0000959EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);
960
961static void ip_tunnel_dev_free(struct net_device *dev)
962{
963 struct ip_tunnel *tunnel = netdev_priv(dev);
964
965 gro_cells_destroy(&tunnel->gro_cells);
Paolo Abenie09acdd2016-02-12 15:43:55 +0100966 dst_cache_destroy(&tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000967 free_percpu(dev->tstats);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000968}
969
970void ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
971{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000972 struct ip_tunnel *tunnel = netdev_priv(dev);
973 struct ip_tunnel_net *itn;
974
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200975 itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000976
977 if (itn->fb_tunnel_dev != dev) {
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700978 ip_tunnel_del(itn, netdev_priv(dev));
Pravin B Shelarc5441932013-03-25 14:49:35 +0000979 unregister_netdevice_queue(dev, head);
980 }
981}
982EXPORT_SYMBOL_GPL(ip_tunnel_dellink);
983
Nicolas Dichtel1728d4f2015-01-15 15:11:17 +0100984struct net *ip_tunnel_get_link_net(const struct net_device *dev)
985{
986 struct ip_tunnel *tunnel = netdev_priv(dev);
987
988 return tunnel->net;
989}
990EXPORT_SYMBOL(ip_tunnel_get_link_net);
991
Nicolas Dichtel1e995842015-04-02 17:07:02 +0200992int ip_tunnel_get_iflink(const struct net_device *dev)
993{
994 struct ip_tunnel *tunnel = netdev_priv(dev);
995
996 return tunnel->parms.link;
997}
998EXPORT_SYMBOL(ip_tunnel_get_iflink);
999
Alexey Dobriyanc7d03a02016-11-17 04:58:21 +03001000int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001001 struct rtnl_link_ops *ops, char *devname)
1002{
1003 struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
1004 struct ip_tunnel_parm parms;
stephen hemminger6261d982013-08-05 22:51:37 -07001005 unsigned int i;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001006
Eric Dumazet79134e62018-03-08 12:51:41 -08001007 itn->rtnl_link_ops = ops;
stephen hemminger6261d982013-08-05 22:51:37 -07001008 for (i = 0; i < IP_TNL_HASH_SIZE; i++)
1009 INIT_HLIST_HEAD(&itn->tunnels[i]);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001010
Eric Dumazet79134e62018-03-08 12:51:41 -08001011 if (!ops || !net_has_fallback_tunnels(net)) {
1012 struct ip_tunnel_net *it_init_net;
1013
1014 it_init_net = net_generic(&init_net, ip_tnl_net_id);
1015 itn->type = it_init_net->type;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001016 itn->fb_tunnel_dev = NULL;
1017 return 0;
1018 }
stephen hemminger6261d982013-08-05 22:51:37 -07001019
Pravin B Shelarc5441932013-03-25 14:49:35 +00001020 memset(&parms, 0, sizeof(parms));
1021 if (devname)
1022 strlcpy(parms.name, devname, IFNAMSIZ);
1023
1024 rtnl_lock();
1025 itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms);
Dan Carpenterea857f22013-08-19 10:05:10 +03001026 /* FB netdevice is special: we have one, and only one per netns.
1027 * Allowing to move it to another netns is clearly unsafe.
1028 */
Steffen Klassert67013282013-10-01 11:34:48 +02001029 if (!IS_ERR(itn->fb_tunnel_dev)) {
Dan Carpenterb4de77a2013-08-23 11:15:37 +03001030 itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
Steffen Klassert78ff4be2014-05-19 11:36:56 +02001031 itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev);
Steffen Klassert67013282013-10-01 11:34:48 +02001032 ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev));
Eric Dumazet79134e62018-03-08 12:51:41 -08001033 itn->type = itn->fb_tunnel_dev->type;
Steffen Klassert67013282013-10-01 11:34:48 +02001034 }
Dan Carpenterb4de77a2013-08-23 11:15:37 +03001035 rtnl_unlock();
Pravin B Shelarc5441932013-03-25 14:49:35 +00001036
Sachin Kamat27d79f32014-01-27 12:13:57 +05301037 return PTR_ERR_OR_ZERO(itn->fb_tunnel_dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001038}
1039EXPORT_SYMBOL_GPL(ip_tunnel_init_net);
1040
Eric Dumazet79134e62018-03-08 12:51:41 -08001041static void ip_tunnel_destroy(struct net *net, struct ip_tunnel_net *itn,
1042 struct list_head *head,
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001043 struct rtnl_link_ops *ops)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001044{
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001045 struct net_device *dev, *aux;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001046 int h;
1047
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001048 for_each_netdev_safe(net, dev, aux)
1049 if (dev->rtnl_link_ops == ops)
1050 unregister_netdevice_queue(dev, head);
1051
Pravin B Shelarc5441932013-03-25 14:49:35 +00001052 for (h = 0; h < IP_TNL_HASH_SIZE; h++) {
1053 struct ip_tunnel *t;
1054 struct hlist_node *n;
1055 struct hlist_head *thead = &itn->tunnels[h];
1056
1057 hlist_for_each_entry_safe(t, n, thead, hash_node)
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001058 /* If dev is in the same netns, it has already
1059 * been added to the list by the previous loop.
1060 */
1061 if (!net_eq(dev_net(t->dev), net))
1062 unregister_netdevice_queue(t->dev, head);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001063 }
Pravin B Shelarc5441932013-03-25 14:49:35 +00001064}
1065
Eric Dumazet64bc1782017-09-19 16:27:09 -07001066void ip_tunnel_delete_nets(struct list_head *net_list, unsigned int id,
1067 struct rtnl_link_ops *ops)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001068{
Eric Dumazet64bc1782017-09-19 16:27:09 -07001069 struct ip_tunnel_net *itn;
1070 struct net *net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001071 LIST_HEAD(list);
1072
1073 rtnl_lock();
Eric Dumazet64bc1782017-09-19 16:27:09 -07001074 list_for_each_entry(net, net_list, exit_list) {
1075 itn = net_generic(net, id);
Eric Dumazet79134e62018-03-08 12:51:41 -08001076 ip_tunnel_destroy(net, itn, &list, ops);
Eric Dumazet64bc1782017-09-19 16:27:09 -07001077 }
Pravin B Shelarc5441932013-03-25 14:49:35 +00001078 unregister_netdevice_many(&list);
1079 rtnl_unlock();
Pravin B Shelarc5441932013-03-25 14:49:35 +00001080}
Eric Dumazet64bc1782017-09-19 16:27:09 -07001081EXPORT_SYMBOL_GPL(ip_tunnel_delete_nets);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001082
1083int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
Craig Gallek9830ad42017-04-19 12:30:54 -04001084 struct ip_tunnel_parm *p, __u32 fwmark)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001085{
1086 struct ip_tunnel *nt;
1087 struct net *net = dev_net(dev);
1088 struct ip_tunnel_net *itn;
1089 int mtu;
1090 int err;
1091
1092 nt = netdev_priv(dev);
1093 itn = net_generic(net, nt->ip_tnl_net_id);
1094
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001095 if (nt->collect_md) {
1096 if (rtnl_dereference(itn->collect_md_tun))
1097 return -EEXIST;
1098 } else {
1099 if (ip_tunnel_find(itn, p, dev->type))
1100 return -EEXIST;
1101 }
Pravin B Shelarc5441932013-03-25 14:49:35 +00001102
Nicolas Dichtel5e6700b2013-06-26 16:11:28 +02001103 nt->net = net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001104 nt->parms = *p;
Craig Gallek9830ad42017-04-19 12:30:54 -04001105 nt->fwmark = fwmark;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001106 err = register_netdevice(dev);
1107 if (err)
Petr Machataf6cc9c02018-03-22 19:53:33 +02001108 goto err_register_netdevice;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001109
1110 if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
1111 eth_hw_addr_random(dev);
1112
1113 mtu = ip_tunnel_bind_dev(dev);
Stefano Brivio24fc7972018-03-15 17:16:28 +01001114 if (tb[IFLA_MTU]) {
Nicolas Dichtel82612de2018-05-31 10:59:32 +02001115 unsigned int max = IP_MAX_MTU - dev->hard_header_len - nt->hlen;
Stefano Brivio24fc7972018-03-15 17:16:28 +01001116
David S. Miller5568cdc2018-03-29 11:42:14 -04001117 mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU,
1118 (unsigned int)(max - sizeof(struct iphdr)));
Petr Machataf6cc9c02018-03-22 19:53:33 +02001119 }
Pravin B Shelarc5441932013-03-25 14:49:35 +00001120
David S. Miller5568cdc2018-03-29 11:42:14 -04001121 err = dev_set_mtu(dev, mtu);
1122 if (err)
1123 goto err_dev_set_mtu;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001124
1125 ip_tunnel_add(itn, nt);
Petr Machataf6cc9c02018-03-22 19:53:33 +02001126 return 0;
1127
1128err_dev_set_mtu:
1129 unregister_netdevice(dev);
1130err_register_netdevice:
Pravin B Shelarc5441932013-03-25 14:49:35 +00001131 return err;
1132}
1133EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
1134
1135int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
Craig Gallek9830ad42017-04-19 12:30:54 -04001136 struct ip_tunnel_parm *p, __u32 fwmark)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001137{
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001138 struct ip_tunnel *t;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001139 struct ip_tunnel *tunnel = netdev_priv(dev);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001140 struct net *net = tunnel->net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001141 struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
1142
1143 if (dev == itn->fb_tunnel_dev)
1144 return -EINVAL;
1145
Pravin B Shelarc5441932013-03-25 14:49:35 +00001146 t = ip_tunnel_find(itn, p, dev->type);
1147
1148 if (t) {
1149 if (t->dev != dev)
1150 return -EEXIST;
1151 } else {
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001152 t = tunnel;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001153
1154 if (dev->type != ARPHRD_ETHER) {
1155 unsigned int nflags = 0;
1156
1157 if (ipv4_is_multicast(p->iph.daddr))
1158 nflags = IFF_BROADCAST;
1159 else if (p->iph.daddr)
1160 nflags = IFF_POINTOPOINT;
1161
1162 if ((dev->flags ^ nflags) &
1163 (IFF_POINTOPOINT | IFF_BROADCAST))
1164 return -EINVAL;
1165 }
1166 }
1167
Craig Gallek9830ad42017-04-19 12:30:54 -04001168 ip_tunnel_update(itn, t, dev, p, !tb[IFLA_MTU], fwmark);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001169 return 0;
1170}
1171EXPORT_SYMBOL_GPL(ip_tunnel_changelink);
1172
1173int ip_tunnel_init(struct net_device *dev)
1174{
1175 struct ip_tunnel *tunnel = netdev_priv(dev);
1176 struct iphdr *iph = &tunnel->parms.iph;
WANG Cong1c213bd2014-02-13 11:46:28 -08001177 int err;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001178
David S. Millercf124db2017-05-08 12:52:56 -04001179 dev->needs_free_netdev = true;
1180 dev->priv_destructor = ip_tunnel_dev_free;
WANG Cong1c213bd2014-02-13 11:46:28 -08001181 dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001182 if (!dev->tstats)
1183 return -ENOMEM;
1184
Paolo Abenie09acdd2016-02-12 15:43:55 +01001185 err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
1186 if (err) {
Tom Herbert9a4aa9a2014-01-02 11:48:33 -08001187 free_percpu(dev->tstats);
Paolo Abenie09acdd2016-02-12 15:43:55 +01001188 return err;
Tom Herbert9a4aa9a2014-01-02 11:48:33 -08001189 }
1190
Pravin B Shelarc5441932013-03-25 14:49:35 +00001191 err = gro_cells_init(&tunnel->gro_cells, dev);
1192 if (err) {
Paolo Abenie09acdd2016-02-12 15:43:55 +01001193 dst_cache_destroy(&tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001194 free_percpu(dev->tstats);
1195 return err;
1196 }
1197
1198 tunnel->dev = dev;
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001199 tunnel->net = dev_net(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001200 strcpy(tunnel->parms.name, dev->name);
1201 iph->version = 4;
1202 iph->ihl = 5;
1203
William Dauchy1d3b53f2020-01-21 15:26:24 +01001204 if (tunnel->collect_md)
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001205 netif_keep_dst(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001206 return 0;
1207}
1208EXPORT_SYMBOL_GPL(ip_tunnel_init);
1209
1210void ip_tunnel_uninit(struct net_device *dev)
1211{
Pravin B Shelarc5441932013-03-25 14:49:35 +00001212 struct ip_tunnel *tunnel = netdev_priv(dev);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001213 struct net *net = tunnel->net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001214 struct ip_tunnel_net *itn;
1215
1216 itn = net_generic(net, tunnel->ip_tnl_net_id);
Taehee Yoo3ee1d442020-06-16 16:51:51 +00001217 ip_tunnel_del(itn, netdev_priv(dev));
1218 if (itn->fb_tunnel_dev == dev)
1219 WRITE_ONCE(itn->fb_tunnel_dev, NULL);
Tom Herbert7d442fa2014-01-02 11:48:26 -08001220
Paolo Abenie09acdd2016-02-12 15:43:55 +01001221 dst_cache_reset(&tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001222}
1223EXPORT_SYMBOL_GPL(ip_tunnel_uninit);
1224
1225/* Do least required initialization, rest of init is done in tunnel_init call */
Alexey Dobriyanc7d03a02016-11-17 04:58:21 +03001226void ip_tunnel_setup(struct net_device *dev, unsigned int net_id)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001227{
1228 struct ip_tunnel *tunnel = netdev_priv(dev);
1229 tunnel->ip_tnl_net_id = net_id;
1230}
1231EXPORT_SYMBOL_GPL(ip_tunnel_setup);
1232
1233MODULE_LICENSE("GPL");