blob: f6cc26de5ed304e0d70bce9444bb4201b6172c11 [file] [log] [blame]
Thomas Gleixnerc9422992019-05-29 07:12:43 -07001// SPDX-License-Identifier: GPL-2.0-only
Pravin B Shelarc5441932013-03-25 14:49:35 +00002/*
3 * Copyright (c) 2013 Nicira, Inc.
Pravin B Shelarc5441932013-03-25 14:49:35 +00004 */
5
6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7
8#include <linux/capability.h>
9#include <linux/module.h>
10#include <linux/types.h>
11#include <linux/kernel.h>
12#include <linux/slab.h>
13#include <linux/uaccess.h>
14#include <linux/skbuff.h>
15#include <linux/netdevice.h>
16#include <linux/in.h>
17#include <linux/tcp.h>
18#include <linux/udp.h>
19#include <linux/if_arp.h>
Pravin B Shelarc5441932013-03-25 14:49:35 +000020#include <linux/init.h>
21#include <linux/in6.h>
22#include <linux/inetdevice.h>
23#include <linux/igmp.h>
24#include <linux/netfilter_ipv4.h>
25#include <linux/etherdevice.h>
26#include <linux/if_ether.h>
27#include <linux/if_vlan.h>
28#include <linux/rculist.h>
Sachin Kamat27d79f32014-01-27 12:13:57 +053029#include <linux/err.h>
Pravin B Shelarc5441932013-03-25 14:49:35 +000030
31#include <net/sock.h>
32#include <net/ip.h>
33#include <net/icmp.h>
34#include <net/protocol.h>
35#include <net/ip_tunnels.h>
36#include <net/arp.h>
37#include <net/checksum.h>
38#include <net/dsfield.h>
39#include <net/inet_ecn.h>
40#include <net/xfrm.h>
41#include <net/net_namespace.h>
42#include <net/netns/generic.h>
43#include <net/rtnetlink.h>
Tom Herbert56328482014-09-17 12:25:58 -070044#include <net/udp.h>
Alexei Starovoitovcfc73812016-09-15 13:00:29 -070045#include <net/dst_metadata.h>
Tom Herbert63487ba2014-11-04 09:06:51 -080046
Pravin B Shelarc5441932013-03-25 14:49:35 +000047#if IS_ENABLED(CONFIG_IPV6)
48#include <net/ipv6.h>
49#include <net/ip6_fib.h>
50#include <net/ip6_route.h>
51#endif
52
Duan Jiong967680e2014-01-19 16:43:42 +080053static unsigned int ip_tunnel_hash(__be32 key, __be32 remote)
Pravin B Shelarc5441932013-03-25 14:49:35 +000054{
55 return hash_32((__force u32)key ^ (__force u32)remote,
56 IP_TNL_HASH_BITS);
57}
58
Pravin B Shelarc5441932013-03-25 14:49:35 +000059static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p,
60 __be16 flags, __be32 key)
61{
62 if (p->i_flags & TUNNEL_KEY) {
63 if (flags & TUNNEL_KEY)
64 return key == p->i_key;
65 else
66 /* key expected, none present */
67 return false;
68 } else
69 return !(flags & TUNNEL_KEY);
70}
71
72/* Fallback tunnel: no source, no destination, no key, no options
73
74 Tunnel hash table:
75 We require exact key match i.e. if a key is present in packet
76 it will match only tunnel with the same key; if it is not present,
77 it will match only keyless tunnel.
78
79 All keysless packets, if not matched configured keyless tunnels
80 will match fallback tunnel.
81 Given src, dst and key, find appropriate for input tunnel.
82*/
83struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
84 int link, __be16 flags,
85 __be32 remote, __be32 local,
86 __be32 key)
87{
Pravin B Shelarc5441932013-03-25 14:49:35 +000088 struct ip_tunnel *t, *cand = NULL;
89 struct hlist_head *head;
Taehee Yooba615392020-06-16 16:51:51 +000090 struct net_device *ndev;
91 unsigned int hash;
Pravin B Shelarc5441932013-03-25 14:49:35 +000092
Duan Jiong967680e2014-01-19 16:43:42 +080093 hash = ip_tunnel_hash(key, remote);
Pravin B Shelarc5441932013-03-25 14:49:35 +000094 head = &itn->tunnels[hash];
95
96 hlist_for_each_entry_rcu(t, head, hash_node) {
97 if (local != t->parms.iph.saddr ||
98 remote != t->parms.iph.daddr ||
99 !(t->dev->flags & IFF_UP))
100 continue;
101
102 if (!ip_tunnel_key_match(&t->parms, flags, key))
103 continue;
104
105 if (t->parms.link == link)
106 return t;
107 else
108 cand = t;
109 }
110
111 hlist_for_each_entry_rcu(t, head, hash_node) {
112 if (remote != t->parms.iph.daddr ||
Dmitry Popove0056592014-07-05 02:26:37 +0400113 t->parms.iph.saddr != 0 ||
Pravin B Shelarc5441932013-03-25 14:49:35 +0000114 !(t->dev->flags & IFF_UP))
115 continue;
116
117 if (!ip_tunnel_key_match(&t->parms, flags, key))
118 continue;
119
120 if (t->parms.link == link)
121 return t;
122 else if (!cand)
123 cand = t;
124 }
125
Duan Jiong967680e2014-01-19 16:43:42 +0800126 hash = ip_tunnel_hash(key, 0);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000127 head = &itn->tunnels[hash];
128
129 hlist_for_each_entry_rcu(t, head, hash_node) {
Dmitry Popove0056592014-07-05 02:26:37 +0400130 if ((local != t->parms.iph.saddr || t->parms.iph.daddr != 0) &&
131 (local != t->parms.iph.daddr || !ipv4_is_multicast(local)))
132 continue;
133
134 if (!(t->dev->flags & IFF_UP))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000135 continue;
136
137 if (!ip_tunnel_key_match(&t->parms, flags, key))
138 continue;
139
140 if (t->parms.link == link)
141 return t;
142 else if (!cand)
143 cand = t;
144 }
145
Pravin B Shelarc5441932013-03-25 14:49:35 +0000146 hlist_for_each_entry_rcu(t, head, hash_node) {
William Dauchy25629fd2020-03-27 19:56:39 +0100147 if ((!(flags & TUNNEL_NO_KEY) && t->parms.i_key != key) ||
Dmitry Popove0056592014-07-05 02:26:37 +0400148 t->parms.iph.saddr != 0 ||
149 t->parms.iph.daddr != 0 ||
Pravin B Shelarc5441932013-03-25 14:49:35 +0000150 !(t->dev->flags & IFF_UP))
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 if (cand)
160 return cand;
161
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700162 t = rcu_dereference(itn->collect_md_tun);
Haishuang Yan833a8b42017-09-12 17:47:56 +0800163 if (t && t->dev->flags & IFF_UP)
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700164 return t;
165
Taehee Yooba615392020-06-16 16:51:51 +0000166 ndev = READ_ONCE(itn->fb_tunnel_dev);
167 if (ndev && ndev->flags & IFF_UP)
168 return netdev_priv(ndev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000169
Pravin B Shelarc5441932013-03-25 14:49:35 +0000170 return NULL;
171}
172EXPORT_SYMBOL_GPL(ip_tunnel_lookup);
173
174static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn,
175 struct ip_tunnel_parm *parms)
176{
177 unsigned int h;
178 __be32 remote;
Steffen Klassert6d608f02014-02-21 08:41:09 +0100179 __be32 i_key = parms->i_key;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000180
181 if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr))
182 remote = parms->iph.daddr;
183 else
184 remote = 0;
185
Steffen Klassert6d608f02014-02-21 08:41:09 +0100186 if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI))
187 i_key = 0;
188
189 h = ip_tunnel_hash(i_key, remote);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000190 return &itn->tunnels[h];
191}
192
193static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t)
194{
195 struct hlist_head *head = ip_bucket(itn, &t->parms);
196
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700197 if (t->collect_md)
198 rcu_assign_pointer(itn->collect_md_tun, t);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000199 hlist_add_head_rcu(&t->hash_node, head);
200}
201
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700202static void ip_tunnel_del(struct ip_tunnel_net *itn, struct ip_tunnel *t)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000203{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700204 if (t->collect_md)
205 rcu_assign_pointer(itn->collect_md_tun, NULL);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000206 hlist_del_init_rcu(&t->hash_node);
207}
208
209static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn,
210 struct ip_tunnel_parm *parms,
211 int type)
212{
213 __be32 remote = parms->iph.daddr;
214 __be32 local = parms->iph.saddr;
215 __be32 key = parms->i_key;
Dmitry Popov5ce54af2014-06-08 03:03:08 +0400216 __be16 flags = parms->i_flags;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000217 int link = parms->link;
218 struct ip_tunnel *t = NULL;
219 struct hlist_head *head = ip_bucket(itn, parms);
220
221 hlist_for_each_entry_rcu(t, head, hash_node) {
222 if (local == t->parms.iph.saddr &&
223 remote == t->parms.iph.daddr &&
Pravin B Shelarc5441932013-03-25 14:49:35 +0000224 link == t->parms.link &&
Dmitry Popov5ce54af2014-06-08 03:03:08 +0400225 type == t->dev->type &&
226 ip_tunnel_key_match(&t->parms, flags, key))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000227 break;
228 }
229 return t;
230}
231
232static struct net_device *__ip_tunnel_create(struct net *net,
233 const struct rtnl_link_ops *ops,
234 struct ip_tunnel_parm *parms)
235{
236 int err;
237 struct ip_tunnel *tunnel;
238 struct net_device *dev;
239 char name[IFNAMSIZ];
240
Eric Dumazet9cb726a2018-04-05 06:39:27 -0700241 err = -E2BIG;
242 if (parms->name[0]) {
243 if (!dev_valid_name(parms->name))
Pravin B Shelarc5441932013-03-25 14:49:35 +0000244 goto failed;
Eric Dumazet9cb726a2018-04-05 06:39:27 -0700245 strlcpy(name, parms->name, IFNAMSIZ);
246 } else {
247 if (strlen(ops->kind) > (IFNAMSIZ - 3))
248 goto failed;
Sultan Alsawaf000ade82018-06-06 15:56:54 -0700249 strcpy(name, ops->kind);
250 strcat(name, "%d");
Pravin B Shelarc5441932013-03-25 14:49:35 +0000251 }
252
253 ASSERT_RTNL();
Tom Gundersenc835a672014-07-14 16:37:24 +0200254 dev = alloc_netdev(ops->priv_size, name, NET_NAME_UNKNOWN, ops->setup);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000255 if (!dev) {
256 err = -ENOMEM;
257 goto failed;
258 }
259 dev_net_set(dev, net);
260
261 dev->rtnl_link_ops = ops;
262
263 tunnel = netdev_priv(dev);
264 tunnel->parms = *parms;
Nicolas Dichtel5e6700b2013-06-26 16:11:28 +0200265 tunnel->net = net;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000266
267 err = register_netdevice(dev);
268 if (err)
269 goto failed_free;
270
271 return dev;
272
273failed_free:
274 free_netdev(dev);
275failed:
276 return ERR_PTR(err);
277}
278
Pravin B Shelarc5441932013-03-25 14:49:35 +0000279static int ip_tunnel_bind_dev(struct net_device *dev)
280{
281 struct net_device *tdev = NULL;
282 struct ip_tunnel *tunnel = netdev_priv(dev);
283 const struct iphdr *iph;
284 int hlen = LL_MAX_HEADER;
285 int mtu = ETH_DATA_LEN;
286 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
287
288 iph = &tunnel->parms.iph;
289
290 /* Guess output device to choose reasonable mtu and needed_headroom */
291 if (iph->daddr) {
292 struct flowi4 fl4;
293 struct rtable *rt;
294
Petr Machatab0066da2018-02-27 14:53:38 +0100295 ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
296 iph->saddr, tunnel->parms.o_key,
297 RT_TOS(iph->tos), tunnel->parms.link,
wenxu24ba1442019-02-24 11:36:20 +0800298 tunnel->fwmark, 0);
Tom Herbert7d442fa2014-01-02 11:48:26 -0800299 rt = ip_route_output_key(tunnel->net, &fl4);
300
Pravin B Shelarc5441932013-03-25 14:49:35 +0000301 if (!IS_ERR(rt)) {
302 tdev = rt->dst.dev;
303 ip_rt_put(rt);
304 }
305 if (dev->type != ARPHRD_ETHER)
306 dev->flags |= IFF_POINTOPOINT;
Paolo Abenif27337e2016-04-28 11:04:51 +0200307
308 dst_cache_reset(&tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000309 }
310
311 if (!tdev && tunnel->parms.link)
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200312 tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000313
314 if (tdev) {
315 hlen = tdev->hard_header_len + tdev->needed_headroom;
Nicolas Dichtel82612de2018-05-31 10:59:32 +0200316 mtu = min(tdev->mtu, IP_MAX_MTU);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000317 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000318
319 dev->needed_headroom = t_hlen + hlen;
Vadim Fedorenko28e104d2021-01-30 01:27:47 +0300320 mtu -= t_hlen;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000321
Eric Dumazetb5476022017-12-11 07:17:39 -0800322 if (mtu < IPV4_MIN_MTU)
323 mtu = IPV4_MIN_MTU;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000324
325 return mtu;
326}
327
328static struct ip_tunnel *ip_tunnel_create(struct net *net,
329 struct ip_tunnel_net *itn,
330 struct ip_tunnel_parm *parms)
331{
Julia Lawall4929fd82014-05-15 05:43:20 +0200332 struct ip_tunnel *nt;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000333 struct net_device *dev;
Jarod Wilsonb96f9af2016-10-20 13:55:24 -0400334 int t_hlen;
Petr Machataf6cc9c02018-03-22 19:53:33 +0200335 int mtu;
336 int err;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000337
Eric Dumazet79134e62018-03-08 12:51:41 -0800338 dev = __ip_tunnel_create(net, itn->rtnl_link_ops, parms);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000339 if (IS_ERR(dev))
Florian Westphal6dd3c9e2014-02-14 13:14:39 +0100340 return ERR_CAST(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000341
Petr Machataf6cc9c02018-03-22 19:53:33 +0200342 mtu = ip_tunnel_bind_dev(dev);
343 err = dev_set_mtu(dev, mtu);
344 if (err)
345 goto err_dev_set_mtu;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000346
347 nt = netdev_priv(dev);
Jarod Wilsonb96f9af2016-10-20 13:55:24 -0400348 t_hlen = nt->hlen + sizeof(struct iphdr);
349 dev->min_mtu = ETH_MIN_MTU;
Vadim Fedorenko28e104d2021-01-30 01:27:47 +0300350 dev->max_mtu = IP_MAX_MTU - t_hlen;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000351 ip_tunnel_add(itn, nt);
352 return nt;
Petr Machataf6cc9c02018-03-22 19:53:33 +0200353
354err_dev_set_mtu:
355 unregister_netdevice(dev);
356 return ERR_PTR(err);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000357}
358
359int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700360 const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst,
361 bool log_ecn_error)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000362{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000363 const struct iphdr *iph = ip_hdr(skb);
364 int err;
365
Pravin B Shelarc5441932013-03-25 14:49:35 +0000366#ifdef CONFIG_NET_IPGRE_BROADCAST
367 if (ipv4_is_multicast(iph->daddr)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000368 tunnel->dev->stats.multicast++;
369 skb->pkt_type = PACKET_BROADCAST;
370 }
371#endif
372
373 if ((!(tpi->flags&TUNNEL_CSUM) && (tunnel->parms.i_flags&TUNNEL_CSUM)) ||
374 ((tpi->flags&TUNNEL_CSUM) && !(tunnel->parms.i_flags&TUNNEL_CSUM))) {
375 tunnel->dev->stats.rx_crc_errors++;
376 tunnel->dev->stats.rx_errors++;
377 goto drop;
378 }
379
380 if (tunnel->parms.i_flags&TUNNEL_SEQ) {
381 if (!(tpi->flags&TUNNEL_SEQ) ||
382 (tunnel->i_seqno && (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) {
383 tunnel->dev->stats.rx_fifo_errors++;
384 tunnel->dev->stats.rx_errors++;
385 goto drop;
386 }
387 tunnel->i_seqno = ntohl(tpi->seq) + 1;
388 }
389
Ying Caie96f2e72014-05-04 15:20:04 -0700390 skb_reset_network_header(skb);
391
Pravin B Shelarc5441932013-03-25 14:49:35 +0000392 err = IP_ECN_decapsulate(iph, skb);
393 if (unlikely(err)) {
394 if (log_ecn_error)
395 net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
396 &iph->saddr, iph->tos);
397 if (err > 1) {
398 ++tunnel->dev->stats.rx_frame_errors;
399 ++tunnel->dev->stats.rx_errors;
400 goto drop;
401 }
402 }
403
Fabian Frederick560b50c2020-10-05 22:37:12 +0200404 dev_sw_netstats_rx_add(tunnel->dev, skb->len);
Alexei Starovoitov81b9eab2013-11-12 14:39:13 -0800405 skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev)));
406
Pravin B Shelar3d7b46c2013-06-17 17:50:02 -0700407 if (tunnel->dev->type == ARPHRD_ETHER) {
408 skb->protocol = eth_type_trans(skb, tunnel->dev);
409 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
410 } else {
411 skb->dev = tunnel->dev;
412 }
Nicolas Dichtel64261f22013-08-13 17:51:09 +0200413
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700414 if (tun_dst)
415 skb_dst_set(skb, (struct dst_entry *)tun_dst);
416
Pravin B Shelarc5441932013-03-25 14:49:35 +0000417 gro_cells_receive(&tunnel->gro_cells, skb);
418 return 0;
419
420drop:
Haishuang Yan469f87e2017-06-15 10:29:29 +0800421 if (tun_dst)
422 dst_release((struct dst_entry *)tun_dst);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000423 kfree_skb(skb);
424 return 0;
425}
426EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
427
Tom Herberta8c5f902014-11-12 11:54:09 -0800428int ip_tunnel_encap_add_ops(const struct ip_tunnel_encap_ops *ops,
429 unsigned int num)
430{
Thomas Grafbb1553c2014-12-16 21:05:20 +0100431 if (num >= MAX_IPTUN_ENCAP_OPS)
432 return -ERANGE;
433
Tom Herberta8c5f902014-11-12 11:54:09 -0800434 return !cmpxchg((const struct ip_tunnel_encap_ops **)
435 &iptun_encaps[num],
436 NULL, ops) ? 0 : -1;
437}
438EXPORT_SYMBOL(ip_tunnel_encap_add_ops);
439
440int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *ops,
441 unsigned int num)
442{
443 int ret;
444
Thomas Grafbb1553c2014-12-16 21:05:20 +0100445 if (num >= MAX_IPTUN_ENCAP_OPS)
446 return -ERANGE;
447
Tom Herberta8c5f902014-11-12 11:54:09 -0800448 ret = (cmpxchg((const struct ip_tunnel_encap_ops **)
449 &iptun_encaps[num],
450 ops, NULL) == ops) ? 0 : -1;
451
452 synchronize_net();
453
454 return ret;
455}
456EXPORT_SYMBOL(ip_tunnel_encap_del_ops);
457
Tom Herbert56328482014-09-17 12:25:58 -0700458int ip_tunnel_encap_setup(struct ip_tunnel *t,
459 struct ip_tunnel_encap *ipencap)
460{
461 int hlen;
462
463 memset(&t->encap, 0, sizeof(t->encap));
464
465 hlen = ip_encap_hlen(ipencap);
466 if (hlen < 0)
467 return hlen;
468
469 t->encap.type = ipencap->type;
470 t->encap.sport = ipencap->sport;
471 t->encap.dport = ipencap->dport;
472 t->encap.flags = ipencap->flags;
473
474 t->encap_hlen = hlen;
475 t->hlen = t->encap_hlen + t->tun_hlen;
476
477 return 0;
478}
479EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup);
480
Pravin B Shelar23a36472013-07-02 10:57:33 -0700481static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
Timo Teräsfc24f2b22015-07-07 08:34:13 +0300482 struct rtable *rt, __be16 df,
wenxuc8b34e62019-01-22 18:39:50 +0800483 const struct iphdr *inner_iph,
484 int tunnel_hlen, __be32 dst, bool md)
Pravin B Shelar23a36472013-07-02 10:57:33 -0700485{
486 struct ip_tunnel *tunnel = netdev_priv(dev);
wenxuc8b34e62019-01-22 18:39:50 +0800487 int pkt_size;
Pravin B Shelar23a36472013-07-02 10:57:33 -0700488 int mtu;
489
wenxuc8b34e62019-01-22 18:39:50 +0800490 tunnel_hlen = md ? tunnel_hlen : tunnel->hlen;
Vadim Fedorenko28e104d2021-01-30 01:27:47 +0300491 pkt_size = skb->len - tunnel_hlen;
wenxuc8b34e62019-01-22 18:39:50 +0800492
Pravin B Shelar23a36472013-07-02 10:57:33 -0700493 if (df)
Vadim Fedorenko28e104d2021-01-30 01:27:47 +0300494 mtu = dst_mtu(&rt->dst) - (sizeof(struct iphdr) + tunnel_hlen);
Pravin B Shelar23a36472013-07-02 10:57:33 -0700495 else
Alan Maguiref4b3ec42019-03-06 10:25:42 +0000496 mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
Pravin B Shelar23a36472013-07-02 10:57:33 -0700497
Alan Maguiref4b3ec42019-03-06 10:25:42 +0000498 if (skb_valid_dst(skb))
Hangbin Liu7a1592b2019-12-22 10:51:13 +0800499 skb_dst_update_pmtu_no_confirm(skb, mtu);
Pravin B Shelar23a36472013-07-02 10:57:33 -0700500
501 if (skb->protocol == htons(ETH_P_IP)) {
502 if (!skb_is_gso(skb) &&
Timo Teräsfc24f2b22015-07-07 08:34:13 +0300503 (inner_iph->frag_off & htons(IP_DF)) &&
504 mtu < pkt_size) {
Jason A. Donenfeld43723392021-02-27 01:40:19 +0100505 icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
Pravin B Shelar23a36472013-07-02 10:57:33 -0700506 return -E2BIG;
507 }
508 }
509#if IS_ENABLED(CONFIG_IPV6)
510 else if (skb->protocol == htons(ETH_P_IPV6)) {
Alan Maguiref4b3ec42019-03-06 10:25:42 +0000511 struct rt6_info *rt6;
wenxuc8b34e62019-01-22 18:39:50 +0800512 __be32 daddr;
513
Alan Maguiref4b3ec42019-03-06 10:25:42 +0000514 rt6 = skb_valid_dst(skb) ? (struct rt6_info *)skb_dst(skb) :
515 NULL;
wenxuc8b34e62019-01-22 18:39:50 +0800516 daddr = md ? dst : tunnel->parms.iph.daddr;
Pravin B Shelar23a36472013-07-02 10:57:33 -0700517
518 if (rt6 && mtu < dst_mtu(skb_dst(skb)) &&
519 mtu >= IPV6_MIN_MTU) {
wenxuc8b34e62019-01-22 18:39:50 +0800520 if ((daddr && !ipv4_is_multicast(daddr)) ||
Pravin B Shelar23a36472013-07-02 10:57:33 -0700521 rt6->rt6i_dst.plen == 128) {
522 rt6->rt6i_flags |= RTF_MODIFIED;
523 dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
524 }
525 }
526
527 if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU &&
528 mtu < pkt_size) {
Jason A. Donenfeld43723392021-02-27 01:40:19 +0100529 icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
Pravin B Shelar23a36472013-07-02 10:57:33 -0700530 return -E2BIG;
531 }
532 }
533#endif
534 return 0;
535}
536
wenxuc8b34e62019-01-22 18:39:50 +0800537void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
538 u8 proto, int tunnel_hlen)
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700539{
540 struct ip_tunnel *tunnel = netdev_priv(dev);
541 u32 headroom = sizeof(struct iphdr);
542 struct ip_tunnel_info *tun_info;
543 const struct ip_tunnel_key *key;
544 const struct iphdr *inner_iph;
wenxuf46fe4f2019-01-22 18:39:49 +0800545 struct rtable *rt = NULL;
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700546 struct flowi4 fl4;
547 __be16 df = 0;
548 u8 tos, ttl;
wenxuf46fe4f2019-01-22 18:39:49 +0800549 bool use_cache;
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700550
551 tun_info = skb_tunnel_info(skb);
552 if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
553 ip_tunnel_info_af(tun_info) != AF_INET))
554 goto tx_error;
555 key = &tun_info->key;
556 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
557 inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
558 tos = key->tos;
559 if (tos == 1) {
560 if (skb->protocol == htons(ETH_P_IP))
561 tos = inner_iph->tos;
562 else if (skb->protocol == htons(ETH_P_IPV6))
563 tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
564 }
wenxu6e6b9042019-01-22 18:39:51 +0800565 ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src,
566 tunnel_id_to_key32(key->tun_id), RT_TOS(tos),
wenxu24ba1442019-02-24 11:36:20 +0800567 0, skb->mark, skb_get_hash(skb));
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700568 if (tunnel->encap.type != TUNNEL_ENCAP_NONE)
569 goto tx_error;
wenxuf46fe4f2019-01-22 18:39:49 +0800570
571 use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
572 if (use_cache)
573 rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl4.saddr);
574 if (!rt) {
575 rt = ip_route_output_key(tunnel->net, &fl4);
576 if (IS_ERR(rt)) {
577 dev->stats.tx_carrier_errors++;
578 goto tx_error;
579 }
580 if (use_cache)
581 dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
582 fl4.saddr);
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700583 }
584 if (rt->dst.dev == dev) {
585 ip_rt_put(rt);
586 dev->stats.collisions++;
587 goto tx_error;
588 }
wenxuc8b34e62019-01-22 18:39:50 +0800589
590 if (key->tun_flags & TUNNEL_DONT_FRAGMENT)
591 df = htons(IP_DF);
592 if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, tunnel_hlen,
593 key->u.ipv4.dst, true)) {
594 ip_rt_put(rt);
595 goto tx_error;
596 }
597
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700598 tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
599 ttl = key->ttl;
600 if (ttl == 0) {
601 if (skb->protocol == htons(ETH_P_IP))
602 ttl = inner_iph->ttl;
603 else if (skb->protocol == htons(ETH_P_IPV6))
604 ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
605 else
606 ttl = ip4_dst_hoplimit(&rt->dst);
607 }
wenxuc8b34e62019-01-22 18:39:50 +0800608
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700609 headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len;
610 if (headroom > dev->needed_headroom)
611 dev->needed_headroom = headroom;
612
613 if (skb_cow_head(skb, dev->needed_headroom)) {
614 ip_rt_put(rt);
615 goto tx_dropped;
616 }
Haishuang Yan0f693f12017-09-07 14:08:34 +0800617 iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, proto, tos, ttl,
618 df, !net_eq(tunnel->net, dev_net(dev)));
Alexei Starovoitovcfc73812016-09-15 13:00:29 -0700619 return;
620tx_error:
621 dev->stats.tx_errors++;
622 goto kfree;
623tx_dropped:
624 dev->stats.tx_dropped++;
625kfree:
626 kfree_skb(skb);
627}
628EXPORT_SYMBOL_GPL(ip_md_tunnel_xmit);
629
Pravin B Shelarc5441932013-03-25 14:49:35 +0000630void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
Tom Herbert56328482014-09-17 12:25:58 -0700631 const struct iphdr *tnl_params, u8 protocol)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000632{
633 struct ip_tunnel *tunnel = netdev_priv(dev);
wenxu186d9362019-02-24 08:24:45 +0800634 struct ip_tunnel_info *tun_info = NULL;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000635 const struct iphdr *inner_iph;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000636 unsigned int max_headroom; /* The extra header space needed */
wenxu186d9362019-02-24 08:24:45 +0800637 struct rtable *rt = NULL; /* Route to the other host */
638 bool use_cache = false;
639 struct flowi4 fl4;
640 bool md = false;
Timo Teräs22fb22e2014-05-16 08:34:39 +0300641 bool connected;
wenxu186d9362019-02-24 08:24:45 +0800642 u8 tos, ttl;
643 __be32 dst;
644 __be16 df;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000645
646 inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
Timo Teräs22fb22e2014-05-16 08:34:39 +0300647 connected = (tunnel->parms.iph.daddr != 0);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000648
Bernie Harris5146d1f2016-02-22 12:58:05 +1300649 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
650
Pravin B Shelarc5441932013-03-25 14:49:35 +0000651 dst = tnl_params->daddr;
652 if (dst == 0) {
653 /* NBMA tunnel */
654
Ian Morris51456b22015-04-03 09:17:26 +0100655 if (!skb_dst(skb)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000656 dev->stats.tx_fifo_errors++;
657 goto tx_error;
658 }
659
wenxud71b57532019-01-19 13:11:25 +0800660 tun_info = skb_tunnel_info(skb);
661 if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) &&
662 ip_tunnel_info_af(tun_info) == AF_INET &&
wenxu186d9362019-02-24 08:24:45 +0800663 tun_info->key.u.ipv4.dst) {
wenxud71b57532019-01-19 13:11:25 +0800664 dst = tun_info->key.u.ipv4.dst;
wenxu186d9362019-02-24 08:24:45 +0800665 md = true;
666 connected = true;
667 }
wenxud71b57532019-01-19 13:11:25 +0800668 else if (skb->protocol == htons(ETH_P_IP)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000669 rt = skb_rtable(skb);
670 dst = rt_nexthop(rt, inner_iph->daddr);
671 }
672#if IS_ENABLED(CONFIG_IPV6)
673 else if (skb->protocol == htons(ETH_P_IPV6)) {
674 const struct in6_addr *addr6;
675 struct neighbour *neigh;
676 bool do_tx_error_icmp;
677 int addr_type;
678
679 neigh = dst_neigh_lookup(skb_dst(skb),
680 &ipv6_hdr(skb)->daddr);
Ian Morris51456b22015-04-03 09:17:26 +0100681 if (!neigh)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000682 goto tx_error;
683
684 addr6 = (const struct in6_addr *)&neigh->primary_key;
685 addr_type = ipv6_addr_type(addr6);
686
687 if (addr_type == IPV6_ADDR_ANY) {
688 addr6 = &ipv6_hdr(skb)->daddr;
689 addr_type = ipv6_addr_type(addr6);
690 }
691
692 if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
693 do_tx_error_icmp = true;
694 else {
695 do_tx_error_icmp = false;
696 dst = addr6->s6_addr32[3];
697 }
698 neigh_release(neigh);
699 if (do_tx_error_icmp)
700 goto tx_error_icmp;
701 }
702#endif
703 else
704 goto tx_error;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800705
wenxu186d9362019-02-24 08:24:45 +0800706 if (!md)
707 connected = false;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000708 }
709
710 tos = tnl_params->tos;
711 if (tos & 0x1) {
712 tos &= ~0x1;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800713 if (skb->protocol == htons(ETH_P_IP)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000714 tos = inner_iph->tos;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800715 connected = false;
716 } else if (skb->protocol == htons(ETH_P_IPV6)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000717 tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
Tom Herbert7d442fa2014-01-02 11:48:26 -0800718 connected = false;
719 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000720 }
721
David S. Miller0f3e9c92018-03-06 00:53:44 -0500722 ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
723 tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link,
wenxu24ba1442019-02-24 11:36:20 +0800724 tunnel->fwmark, skb_get_hash(skb));
Tom Herbert7d442fa2014-01-02 11:48:26 -0800725
Tom Herbert56328482014-09-17 12:25:58 -0700726 if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
727 goto tx_error;
728
wenxu186d9362019-02-24 08:24:45 +0800729 if (connected && md) {
730 use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
731 if (use_cache)
732 rt = dst_cache_get_ip4(&tun_info->dst_cache,
733 &fl4.saddr);
734 } else {
735 rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache,
736 &fl4.saddr) : NULL;
737 }
Tom Herbert7d442fa2014-01-02 11:48:26 -0800738
739 if (!rt) {
740 rt = ip_route_output_key(tunnel->net, &fl4);
741
742 if (IS_ERR(rt)) {
743 dev->stats.tx_carrier_errors++;
744 goto tx_error;
745 }
wenxu186d9362019-02-24 08:24:45 +0800746 if (use_cache)
747 dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
748 fl4.saddr);
749 else if (!md && connected)
Paolo Abenie09acdd2016-02-12 15:43:55 +0100750 dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst,
751 fl4.saddr);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000752 }
Tom Herbert7d442fa2014-01-02 11:48:26 -0800753
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700754 if (rt->dst.dev == dev) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000755 ip_rt_put(rt);
756 dev->stats.collisions++;
757 goto tx_error;
758 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000759
Florian Westphal50c66162021-01-06 00:15:22 +0100760 df = tnl_params->frag_off;
761 if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
762 df |= (inner_iph->frag_off & htons(IP_DF));
763
764 if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, 0, 0, false)) {
Pravin B Shelar23a36472013-07-02 10:57:33 -0700765 ip_rt_put(rt);
766 goto tx_error;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000767 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000768
769 if (tunnel->err_count > 0) {
770 if (time_before(jiffies,
771 tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
772 tunnel->err_count--;
773
774 dst_link_failure(skb);
775 } else
776 tunnel->err_count = 0;
777 }
778
Pravin B Shelard4a71b12013-09-25 09:57:47 -0700779 tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000780 ttl = tnl_params->ttl;
781 if (ttl == 0) {
782 if (skb->protocol == htons(ETH_P_IP))
783 ttl = inner_iph->ttl;
784#if IS_ENABLED(CONFIG_IPV6)
785 else if (skb->protocol == htons(ETH_P_IPV6))
786 ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
787#endif
788 else
789 ttl = ip4_dst_hoplimit(&rt->dst);
790 }
791
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700792 max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
Tom Herbert7371e022014-10-03 15:48:07 -0700793 + rt->dst.header_len + ip_encap_hlen(&tunnel->encap);
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200794 if (max_headroom > dev->needed_headroom)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000795 dev->needed_headroom = max_headroom;
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200796
797 if (skb_cow_head(skb, dev->needed_headroom)) {
Dmitry Popov586d5fc2014-06-06 04:34:37 +0400798 ip_rt_put(rt);
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200799 dev->stats.tx_dropped++;
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800800 kfree_skb(skb);
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200801 return;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000802 }
803
Pravin B Shelar039f5062015-12-24 14:34:54 -0800804 iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl,
805 df, !net_eq(tunnel->net, dev_net(dev)));
Pravin B Shelarc5441932013-03-25 14:49:35 +0000806 return;
807
808#if IS_ENABLED(CONFIG_IPV6)
809tx_error_icmp:
810 dst_link_failure(skb);
811#endif
812tx_error:
813 dev->stats.tx_errors++;
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800814 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000815}
816EXPORT_SYMBOL_GPL(ip_tunnel_xmit);
817
818static void ip_tunnel_update(struct ip_tunnel_net *itn,
819 struct ip_tunnel *t,
820 struct net_device *dev,
821 struct ip_tunnel_parm *p,
Craig Gallek9830ad42017-04-19 12:30:54 -0400822 bool set_mtu,
823 __u32 fwmark)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000824{
Pravin B Shelar2e15ea32015-08-07 23:51:42 -0700825 ip_tunnel_del(itn, t);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000826 t->parms.iph.saddr = p->iph.saddr;
827 t->parms.iph.daddr = p->iph.daddr;
828 t->parms.i_key = p->i_key;
829 t->parms.o_key = p->o_key;
830 if (dev->type != ARPHRD_ETHER) {
831 memcpy(dev->dev_addr, &p->iph.saddr, 4);
832 memcpy(dev->broadcast, &p->iph.daddr, 4);
833 }
834 ip_tunnel_add(itn, t);
835
836 t->parms.iph.ttl = p->iph.ttl;
837 t->parms.iph.tos = p->iph.tos;
838 t->parms.iph.frag_off = p->iph.frag_off;
839
Craig Gallek9830ad42017-04-19 12:30:54 -0400840 if (t->parms.link != p->link || t->fwmark != fwmark) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000841 int mtu;
842
843 t->parms.link = p->link;
Craig Gallek9830ad42017-04-19 12:30:54 -0400844 t->fwmark = fwmark;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000845 mtu = ip_tunnel_bind_dev(dev);
846 if (set_mtu)
847 dev->mtu = mtu;
848 }
Paolo Abenie09acdd2016-02-12 15:43:55 +0100849 dst_cache_reset(&t->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000850 netdev_state_change(dev);
851}
852
Christoph Hellwig607259a62020-05-19 15:03:13 +0200853int ip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000854{
855 int err = 0;
Nicolas Dichtel8c923ce2014-04-16 11:19:32 +0200856 struct ip_tunnel *t = netdev_priv(dev);
857 struct net *net = t->net;
858 struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000859
Pravin B Shelarc5441932013-03-25 14:49:35 +0000860 switch (cmd) {
861 case SIOCGETTUNNEL:
Nicolas Dichtel8c923ce2014-04-16 11:19:32 +0200862 if (dev == itn->fb_tunnel_dev) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000863 t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
Ian Morris51456b22015-04-03 09:17:26 +0100864 if (!t)
Nicolas Dichtel8c923ce2014-04-16 11:19:32 +0200865 t = netdev_priv(dev);
866 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000867 memcpy(p, &t->parms, sizeof(*p));
868 break;
869
870 case SIOCADDTUNNEL:
871 case SIOCCHGTUNNEL:
872 err = -EPERM;
873 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
874 goto done;
875 if (p->iph.ttl)
876 p->iph.frag_off |= htons(IP_DF);
Dmitry Popov7c8e6b92014-06-08 02:06:25 +0400877 if (!(p->i_flags & VTI_ISVTI)) {
878 if (!(p->i_flags & TUNNEL_KEY))
879 p->i_key = 0;
880 if (!(p->o_flags & TUNNEL_KEY))
881 p->o_key = 0;
882 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000883
Eric Dumazet79134e62018-03-08 12:51:41 -0800884 t = ip_tunnel_find(itn, p, itn->type);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000885
Steffen Klassertd61746b2014-09-22 09:11:08 +0200886 if (cmd == SIOCADDTUNNEL) {
887 if (!t) {
888 t = ip_tunnel_create(net, itn, p);
889 err = PTR_ERR_OR_ZERO(t);
890 break;
891 }
892
893 err = -EEXIST;
Duan Jiongee30ef4d2014-05-15 13:07:02 +0800894 break;
Florian Westphal6dd3c9e2014-02-14 13:14:39 +0100895 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000896 if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
Ian Morris00db4122015-04-03 09:17:27 +0100897 if (t) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000898 if (t->dev != dev) {
899 err = -EEXIST;
900 break;
901 }
902 } else {
903 unsigned int nflags = 0;
904
905 if (ipv4_is_multicast(p->iph.daddr))
906 nflags = IFF_BROADCAST;
907 else if (p->iph.daddr)
908 nflags = IFF_POINTOPOINT;
909
910 if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
911 err = -EINVAL;
912 break;
913 }
914
915 t = netdev_priv(dev);
916 }
917 }
918
919 if (t) {
920 err = 0;
Craig Gallek9830ad42017-04-19 12:30:54 -0400921 ip_tunnel_update(itn, t, dev, p, true, 0);
Florian Westphal6dd3c9e2014-02-14 13:14:39 +0100922 } else {
923 err = -ENOENT;
924 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000925 break;
926
927 case SIOCDELTUNNEL:
928 err = -EPERM;
929 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
930 goto done;
931
932 if (dev == itn->fb_tunnel_dev) {
933 err = -ENOENT;
934 t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
Ian Morris51456b22015-04-03 09:17:26 +0100935 if (!t)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000936 goto done;
937 err = -EPERM;
938 if (t == netdev_priv(itn->fb_tunnel_dev))
939 goto done;
940 dev = t->dev;
941 }
942 unregister_netdevice(dev);
943 err = 0;
944 break;
945
946 default:
947 err = -EINVAL;
948 }
949
950done:
951 return err;
952}
Christoph Hellwig607259a62020-05-19 15:03:13 +0200953EXPORT_SYMBOL_GPL(ip_tunnel_ctl);
954
955int ip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
956{
957 struct ip_tunnel_parm p;
958 int err;
959
960 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
961 return -EFAULT;
962 err = dev->netdev_ops->ndo_tunnel_ctl(dev, &p, cmd);
963 if (!err && copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
964 return -EFAULT;
965 return err;
966}
Pravin B Shelarc5441932013-03-25 14:49:35 +0000967EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);
968
David Wragg7e059152016-02-10 00:05:58 +0000969int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000970{
971 struct ip_tunnel *tunnel = netdev_priv(dev);
972 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
Vadim Fedorenko28e104d2021-01-30 01:27:47 +0300973 int max_mtu = IP_MAX_MTU - t_hlen;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000974
Jarod Wilsonb96f9af2016-10-20 13:55:24 -0400975 if (new_mtu < ETH_MIN_MTU)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000976 return -EINVAL;
David Wragg7e059152016-02-10 00:05:58 +0000977
978 if (new_mtu > max_mtu) {
979 if (strict)
980 return -EINVAL;
981
982 new_mtu = max_mtu;
983 }
984
Pravin B Shelarc5441932013-03-25 14:49:35 +0000985 dev->mtu = new_mtu;
986 return 0;
987}
David Wragg7e059152016-02-10 00:05:58 +0000988EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu);
989
990int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
991{
992 return __ip_tunnel_change_mtu(dev, new_mtu, true);
993}
Pravin B Shelarc5441932013-03-25 14:49:35 +0000994EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);
995
996static void ip_tunnel_dev_free(struct net_device *dev)
997{
998 struct ip_tunnel *tunnel = netdev_priv(dev);
999
1000 gro_cells_destroy(&tunnel->gro_cells);
Paolo Abenie09acdd2016-02-12 15:43:55 +01001001 dst_cache_destroy(&tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001002 free_percpu(dev->tstats);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001003}
1004
1005void ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
1006{
Pravin B Shelarc5441932013-03-25 14:49:35 +00001007 struct ip_tunnel *tunnel = netdev_priv(dev);
1008 struct ip_tunnel_net *itn;
1009
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001010 itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001011
1012 if (itn->fb_tunnel_dev != dev) {
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001013 ip_tunnel_del(itn, netdev_priv(dev));
Pravin B Shelarc5441932013-03-25 14:49:35 +00001014 unregister_netdevice_queue(dev, head);
1015 }
1016}
1017EXPORT_SYMBOL_GPL(ip_tunnel_dellink);
1018
Nicolas Dichtel1728d4f2015-01-15 15:11:17 +01001019struct net *ip_tunnel_get_link_net(const struct net_device *dev)
1020{
1021 struct ip_tunnel *tunnel = netdev_priv(dev);
1022
1023 return tunnel->net;
1024}
1025EXPORT_SYMBOL(ip_tunnel_get_link_net);
1026
Nicolas Dichtel1e995842015-04-02 17:07:02 +02001027int ip_tunnel_get_iflink(const struct net_device *dev)
1028{
1029 struct ip_tunnel *tunnel = netdev_priv(dev);
1030
1031 return tunnel->parms.link;
1032}
1033EXPORT_SYMBOL(ip_tunnel_get_iflink);
1034
Alexey Dobriyanc7d03a02016-11-17 04:58:21 +03001035int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id,
Pravin B Shelarc5441932013-03-25 14:49:35 +00001036 struct rtnl_link_ops *ops, char *devname)
1037{
1038 struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
1039 struct ip_tunnel_parm parms;
stephen hemminger6261d982013-08-05 22:51:37 -07001040 unsigned int i;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001041
Eric Dumazet79134e62018-03-08 12:51:41 -08001042 itn->rtnl_link_ops = ops;
stephen hemminger6261d982013-08-05 22:51:37 -07001043 for (i = 0; i < IP_TNL_HASH_SIZE; i++)
1044 INIT_HLIST_HEAD(&itn->tunnels[i]);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001045
Eric Dumazet79134e62018-03-08 12:51:41 -08001046 if (!ops || !net_has_fallback_tunnels(net)) {
1047 struct ip_tunnel_net *it_init_net;
1048
1049 it_init_net = net_generic(&init_net, ip_tnl_net_id);
1050 itn->type = it_init_net->type;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001051 itn->fb_tunnel_dev = NULL;
1052 return 0;
1053 }
stephen hemminger6261d982013-08-05 22:51:37 -07001054
Pravin B Shelarc5441932013-03-25 14:49:35 +00001055 memset(&parms, 0, sizeof(parms));
1056 if (devname)
1057 strlcpy(parms.name, devname, IFNAMSIZ);
1058
1059 rtnl_lock();
1060 itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms);
Dan Carpenterea857f22013-08-19 10:05:10 +03001061 /* FB netdevice is special: we have one, and only one per netns.
1062 * Allowing to move it to another netns is clearly unsafe.
1063 */
Steffen Klassert67013282013-10-01 11:34:48 +02001064 if (!IS_ERR(itn->fb_tunnel_dev)) {
Dan Carpenterb4de77a2013-08-23 11:15:37 +03001065 itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
Steffen Klassert78ff4be2014-05-19 11:36:56 +02001066 itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev);
Steffen Klassert67013282013-10-01 11:34:48 +02001067 ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev));
Eric Dumazet79134e62018-03-08 12:51:41 -08001068 itn->type = itn->fb_tunnel_dev->type;
Steffen Klassert67013282013-10-01 11:34:48 +02001069 }
Dan Carpenterb4de77a2013-08-23 11:15:37 +03001070 rtnl_unlock();
Pravin B Shelarc5441932013-03-25 14:49:35 +00001071
Sachin Kamat27d79f32014-01-27 12:13:57 +05301072 return PTR_ERR_OR_ZERO(itn->fb_tunnel_dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001073}
1074EXPORT_SYMBOL_GPL(ip_tunnel_init_net);
1075
Eric Dumazet79134e62018-03-08 12:51:41 -08001076static void ip_tunnel_destroy(struct net *net, struct ip_tunnel_net *itn,
1077 struct list_head *head,
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001078 struct rtnl_link_ops *ops)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001079{
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001080 struct net_device *dev, *aux;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001081 int h;
1082
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001083 for_each_netdev_safe(net, dev, aux)
1084 if (dev->rtnl_link_ops == ops)
1085 unregister_netdevice_queue(dev, head);
1086
Pravin B Shelarc5441932013-03-25 14:49:35 +00001087 for (h = 0; h < IP_TNL_HASH_SIZE; h++) {
1088 struct ip_tunnel *t;
1089 struct hlist_node *n;
1090 struct hlist_head *thead = &itn->tunnels[h];
1091
1092 hlist_for_each_entry_safe(t, n, thead, hash_node)
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001093 /* If dev is in the same netns, it has already
1094 * been added to the list by the previous loop.
1095 */
1096 if (!net_eq(dev_net(t->dev), net))
1097 unregister_netdevice_queue(t->dev, head);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001098 }
Pravin B Shelarc5441932013-03-25 14:49:35 +00001099}
1100
Eric Dumazet64bc1782017-09-19 16:27:09 -07001101void ip_tunnel_delete_nets(struct list_head *net_list, unsigned int id,
1102 struct rtnl_link_ops *ops)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001103{
Eric Dumazet64bc1782017-09-19 16:27:09 -07001104 struct ip_tunnel_net *itn;
1105 struct net *net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001106 LIST_HEAD(list);
1107
1108 rtnl_lock();
Eric Dumazet64bc1782017-09-19 16:27:09 -07001109 list_for_each_entry(net, net_list, exit_list) {
1110 itn = net_generic(net, id);
Eric Dumazet79134e62018-03-08 12:51:41 -08001111 ip_tunnel_destroy(net, itn, &list, ops);
Eric Dumazet64bc1782017-09-19 16:27:09 -07001112 }
Pravin B Shelarc5441932013-03-25 14:49:35 +00001113 unregister_netdevice_many(&list);
1114 rtnl_unlock();
Pravin B Shelarc5441932013-03-25 14:49:35 +00001115}
Eric Dumazet64bc1782017-09-19 16:27:09 -07001116EXPORT_SYMBOL_GPL(ip_tunnel_delete_nets);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001117
1118int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
Craig Gallek9830ad42017-04-19 12:30:54 -04001119 struct ip_tunnel_parm *p, __u32 fwmark)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001120{
1121 struct ip_tunnel *nt;
1122 struct net *net = dev_net(dev);
1123 struct ip_tunnel_net *itn;
1124 int mtu;
1125 int err;
1126
1127 nt = netdev_priv(dev);
1128 itn = net_generic(net, nt->ip_tnl_net_id);
1129
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001130 if (nt->collect_md) {
1131 if (rtnl_dereference(itn->collect_md_tun))
1132 return -EEXIST;
1133 } else {
1134 if (ip_tunnel_find(itn, p, dev->type))
1135 return -EEXIST;
1136 }
Pravin B Shelarc5441932013-03-25 14:49:35 +00001137
Nicolas Dichtel5e6700b2013-06-26 16:11:28 +02001138 nt->net = net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001139 nt->parms = *p;
Craig Gallek9830ad42017-04-19 12:30:54 -04001140 nt->fwmark = fwmark;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001141 err = register_netdevice(dev);
1142 if (err)
Petr Machataf6cc9c02018-03-22 19:53:33 +02001143 goto err_register_netdevice;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001144
1145 if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
1146 eth_hw_addr_random(dev);
1147
1148 mtu = ip_tunnel_bind_dev(dev);
Stefano Brivio24fc7972018-03-15 17:16:28 +01001149 if (tb[IFLA_MTU]) {
Vadim Fedorenko28e104d2021-01-30 01:27:47 +03001150 unsigned int max = IP_MAX_MTU - (nt->hlen + sizeof(struct iphdr));
Stefano Brivio24fc7972018-03-15 17:16:28 +01001151
Vadim Fedorenko28e104d2021-01-30 01:27:47 +03001152 mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, max);
Petr Machataf6cc9c02018-03-22 19:53:33 +02001153 }
Pravin B Shelarc5441932013-03-25 14:49:35 +00001154
David S. Miller5568cdc2018-03-29 11:42:14 -04001155 err = dev_set_mtu(dev, mtu);
1156 if (err)
1157 goto err_dev_set_mtu;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001158
1159 ip_tunnel_add(itn, nt);
Petr Machataf6cc9c02018-03-22 19:53:33 +02001160 return 0;
1161
1162err_dev_set_mtu:
1163 unregister_netdevice(dev);
1164err_register_netdevice:
Pravin B Shelarc5441932013-03-25 14:49:35 +00001165 return err;
1166}
1167EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
1168
1169int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
Craig Gallek9830ad42017-04-19 12:30:54 -04001170 struct ip_tunnel_parm *p, __u32 fwmark)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001171{
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001172 struct ip_tunnel *t;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001173 struct ip_tunnel *tunnel = netdev_priv(dev);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001174 struct net *net = tunnel->net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001175 struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
1176
1177 if (dev == itn->fb_tunnel_dev)
1178 return -EINVAL;
1179
Pravin B Shelarc5441932013-03-25 14:49:35 +00001180 t = ip_tunnel_find(itn, p, dev->type);
1181
1182 if (t) {
1183 if (t->dev != dev)
1184 return -EEXIST;
1185 } else {
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001186 t = tunnel;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001187
1188 if (dev->type != ARPHRD_ETHER) {
1189 unsigned int nflags = 0;
1190
1191 if (ipv4_is_multicast(p->iph.daddr))
1192 nflags = IFF_BROADCAST;
1193 else if (p->iph.daddr)
1194 nflags = IFF_POINTOPOINT;
1195
1196 if ((dev->flags ^ nflags) &
1197 (IFF_POINTOPOINT | IFF_BROADCAST))
1198 return -EINVAL;
1199 }
1200 }
1201
Craig Gallek9830ad42017-04-19 12:30:54 -04001202 ip_tunnel_update(itn, t, dev, p, !tb[IFLA_MTU], fwmark);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001203 return 0;
1204}
1205EXPORT_SYMBOL_GPL(ip_tunnel_changelink);
1206
1207int ip_tunnel_init(struct net_device *dev)
1208{
1209 struct ip_tunnel *tunnel = netdev_priv(dev);
1210 struct iphdr *iph = &tunnel->parms.iph;
WANG Cong1c213bd2014-02-13 11:46:28 -08001211 int err;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001212
David S. Millercf124db2017-05-08 12:52:56 -04001213 dev->needs_free_netdev = true;
1214 dev->priv_destructor = ip_tunnel_dev_free;
WANG Cong1c213bd2014-02-13 11:46:28 -08001215 dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001216 if (!dev->tstats)
1217 return -ENOMEM;
1218
Paolo Abenie09acdd2016-02-12 15:43:55 +01001219 err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
1220 if (err) {
Tom Herbert9a4aa9a2014-01-02 11:48:33 -08001221 free_percpu(dev->tstats);
Paolo Abenie09acdd2016-02-12 15:43:55 +01001222 return err;
Tom Herbert9a4aa9a2014-01-02 11:48:33 -08001223 }
1224
Pravin B Shelarc5441932013-03-25 14:49:35 +00001225 err = gro_cells_init(&tunnel->gro_cells, dev);
1226 if (err) {
Paolo Abenie09acdd2016-02-12 15:43:55 +01001227 dst_cache_destroy(&tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001228 free_percpu(dev->tstats);
1229 return err;
1230 }
1231
1232 tunnel->dev = dev;
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001233 tunnel->net = dev_net(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001234 strcpy(tunnel->parms.name, dev->name);
1235 iph->version = 4;
1236 iph->ihl = 5;
1237
William Dauchyd0f41852020-01-21 15:26:24 +01001238 if (tunnel->collect_md)
Pravin B Shelar2e15ea32015-08-07 23:51:42 -07001239 netif_keep_dst(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001240 return 0;
1241}
1242EXPORT_SYMBOL_GPL(ip_tunnel_init);
1243
1244void ip_tunnel_uninit(struct net_device *dev)
1245{
Pravin B Shelarc5441932013-03-25 14:49:35 +00001246 struct ip_tunnel *tunnel = netdev_priv(dev);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001247 struct net *net = tunnel->net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001248 struct ip_tunnel_net *itn;
1249
1250 itn = net_generic(net, tunnel->ip_tnl_net_id);
Taehee Yooba615392020-06-16 16:51:51 +00001251 ip_tunnel_del(itn, netdev_priv(dev));
1252 if (itn->fb_tunnel_dev == dev)
1253 WRITE_ONCE(itn->fb_tunnel_dev, NULL);
Tom Herbert7d442fa2014-01-02 11:48:26 -08001254
Paolo Abenie09acdd2016-02-12 15:43:55 +01001255 dst_cache_reset(&tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001256}
1257EXPORT_SYMBOL_GPL(ip_tunnel_uninit);
1258
1259/* Do least required initialization, rest of init is done in tunnel_init call */
Alexey Dobriyanc7d03a02016-11-17 04:58:21 +03001260void ip_tunnel_setup(struct net_device *dev, unsigned int net_id)
Pravin B Shelarc5441932013-03-25 14:49:35 +00001261{
1262 struct ip_tunnel *tunnel = netdev_priv(dev);
1263 tunnel->ip_tnl_net_id = net_id;
1264}
1265EXPORT_SYMBOL_GPL(ip_tunnel_setup);
1266
1267MODULE_LICENSE("GPL");