hc
2024-09-20 cf4ce59b3b70238352c7f1729f0f7223214828ad
kernel/net/ipv6/sit.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * IPv6 over IPv4 tunnel device - Simple Internet Transition (SIT)
34 * Linux INET6 implementation
....@@ -5,11 +6,6 @@
56 * Authors:
67 * Pedro Roque <roque@di.fc.ul.pt>
78 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
8
- *
9
- * This program is free software; you can redistribute it and/or
10
- * modify it under the terms of the GNU General Public License
11
- * as published by the Free Software Foundation; either version
12
- * 2 of the License, or (at your option) any later version.
139 *
1410 * Changes:
1511 * Roger Venning <r.venning@telstra.com>: 6to4 support
....@@ -86,6 +82,13 @@
8682
8783 struct net_device *fb_tunnel_dev;
8884 };
85
+
86
+static inline struct sit_net *dev_to_sit_net(struct net_device *dev)
87
+{
88
+ struct ip_tunnel *t = netdev_priv(dev);
89
+
90
+ return net_generic(t->net, sit_net_id);
91
+}
8992
9093 /*
9194 * Must be invoked with rcu_read_lock
....@@ -293,13 +296,17 @@
293296
294297 }
295298
296
-static int ipip6_tunnel_get_prl(struct ip_tunnel *t,
297
- struct ip_tunnel_prl __user *a)
299
+static int ipip6_tunnel_get_prl(struct net_device *dev, struct ifreq *ifr)
298300 {
301
+ struct ip_tunnel_prl __user *a = ifr->ifr_ifru.ifru_data;
302
+ struct ip_tunnel *t = netdev_priv(dev);
299303 struct ip_tunnel_prl kprl, *kp;
300304 struct ip_tunnel_prl_entry *prl;
301305 unsigned int cmax, c = 0, ca, len;
302306 int ret = 0;
307
+
308
+ if (dev == dev_to_sit_net(dev)->fb_tunnel_dev)
309
+ return -EINVAL;
303310
304311 if (copy_from_user(&kprl, a, sizeof(kprl)))
305312 return -EFAULT;
....@@ -314,9 +321,7 @@
314321 kcalloc(cmax, sizeof(*kp), GFP_KERNEL | __GFP_NOWARN) :
315322 NULL;
316323
317
- rcu_read_lock();
318
-
319
- ca = t->prl_count < cmax ? t->prl_count : cmax;
324
+ ca = min(t->prl_count, cmax);
320325
321326 if (!kp) {
322327 /* We don't try hard to allocate much memory for
....@@ -331,7 +336,7 @@
331336 }
332337 }
333338
334
- c = 0;
339
+ rcu_read_lock();
335340 for_each_prl_rcu(t->prl) {
336341 if (c >= cmax)
337342 break;
....@@ -343,7 +348,7 @@
343348 if (kprl.addr != htonl(INADDR_ANY))
344349 break;
345350 }
346
-out:
351
+
347352 rcu_read_unlock();
348353
349354 len = sizeof(*kp) * c;
....@@ -352,7 +357,7 @@
352357 ret = -EFAULT;
353358
354359 kfree(kp);
355
-
360
+out:
356361 return ret;
357362 }
358363
....@@ -440,6 +445,35 @@
440445 }
441446 }
442447 out:
448
+ return err;
449
+}
450
+
451
+static int ipip6_tunnel_prl_ctl(struct net_device *dev, struct ifreq *ifr,
452
+ int cmd)
453
+{
454
+ struct ip_tunnel *t = netdev_priv(dev);
455
+ struct ip_tunnel_prl prl;
456
+ int err;
457
+
458
+ if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN))
459
+ return -EPERM;
460
+ if (dev == dev_to_sit_net(dev)->fb_tunnel_dev)
461
+ return -EINVAL;
462
+
463
+ if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl)))
464
+ return -EFAULT;
465
+
466
+ switch (cmd) {
467
+ case SIOCDELPRL:
468
+ err = ipip6_tunnel_del_prl(t, &prl);
469
+ break;
470
+ case SIOCADDPRL:
471
+ case SIOCCHGPRL:
472
+ err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
473
+ break;
474
+ }
475
+ dst_cache_reset(&t->dst_cache);
476
+ netdev_state_change(dev);
443477 return err;
444478 }
445479
....@@ -532,13 +566,13 @@
532566
533567 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
534568 ipv4_update_pmtu(skb, dev_net(skb->dev), info,
535
- t->parms.link, 0, iph->protocol, 0);
569
+ t->parms.link, iph->protocol);
536570 err = 0;
537571 goto out;
538572 }
539573 if (type == ICMP_REDIRECT) {
540
- ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0,
541
- iph->protocol, 0);
574
+ ipv4_redirect(skb, dev_net(skb->dev), t->parms.link,
575
+ iph->protocol);
542576 err = 0;
543577 goto out;
544578 }
....@@ -902,12 +936,17 @@
902936 RT_TOS(tos), RT_SCOPE_UNIVERSE, IPPROTO_IPV6,
903937 0, dst, tiph->saddr, 0, 0,
904938 sock_net_uid(tunnel->net, NULL));
905
- rt = ip_route_output_flow(tunnel->net, &fl4, NULL);
906939
907
- if (IS_ERR(rt)) {
908
- dev->stats.tx_carrier_errors++;
909
- goto tx_error_icmp;
940
+ rt = dst_cache_get_ip4(&tunnel->dst_cache, &fl4.saddr);
941
+ if (!rt) {
942
+ rt = ip_route_output_flow(tunnel->net, &fl4, NULL);
943
+ if (IS_ERR(rt)) {
944
+ dev->stats.tx_carrier_errors++;
945
+ goto tx_error_icmp;
946
+ }
947
+ dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, fl4.saddr);
910948 }
949
+
911950 if (rt->rt_type != RTN_UNICAST) {
912951 ip_rt_put(rt);
913952 dev->stats.tx_carrier_errors++;
....@@ -944,7 +983,7 @@
944983 skb_dst_update_pmtu_no_confirm(skb, mtu);
945984
946985 if (skb->len > mtu && !skb_is_gso(skb)) {
947
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
986
+ icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
948987 ip_rt_put(rt);
949988 goto tx_error;
950989 }
....@@ -1055,12 +1094,13 @@
10551094
10561095 static void ipip6_tunnel_bind_dev(struct net_device *dev)
10571096 {
1097
+ struct ip_tunnel *tunnel = netdev_priv(dev);
1098
+ int t_hlen = tunnel->hlen + sizeof(struct iphdr);
10581099 struct net_device *tdev = NULL;
1059
- struct ip_tunnel *tunnel;
1100
+ int hlen = LL_MAX_HEADER;
10601101 const struct iphdr *iph;
10611102 struct flowi4 fl4;
10621103
1063
- tunnel = netdev_priv(dev);
10641104 iph = &tunnel->parms.iph;
10651105
10661106 if (iph->daddr) {
....@@ -1083,12 +1123,15 @@
10831123 tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
10841124
10851125 if (tdev && !netif_is_l3_master(tdev)) {
1086
- int t_hlen = tunnel->hlen + sizeof(struct iphdr);
1126
+ int mtu;
10871127
1088
- dev->mtu = tdev->mtu - t_hlen;
1089
- if (dev->mtu < IPV6_MIN_MTU)
1090
- dev->mtu = IPV6_MIN_MTU;
1128
+ mtu = tdev->mtu - t_hlen;
1129
+ if (mtu < IPV6_MIN_MTU)
1130
+ mtu = IPV6_MIN_MTU;
1131
+ WRITE_ONCE(dev->mtu, mtu);
1132
+ hlen = tdev->hard_header_len + tdev->needed_headroom;
10911133 }
1134
+ dev->needed_headroom = t_hlen + hlen;
10921135 }
10931136
10941137 static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p,
....@@ -1147,7 +1190,53 @@
11471190 netdev_state_change(t->dev);
11481191 return 0;
11491192 }
1150
-#endif
1193
+
1194
+static int
1195
+ipip6_tunnel_get6rd(struct net_device *dev, struct ifreq *ifr)
1196
+{
1197
+ struct ip_tunnel *t = netdev_priv(dev);
1198
+ struct ip_tunnel_6rd ip6rd;
1199
+ struct ip_tunnel_parm p;
1200
+
1201
+ if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
1202
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
1203
+ return -EFAULT;
1204
+ t = ipip6_tunnel_locate(t->net, &p, 0);
1205
+ }
1206
+ if (!t)
1207
+ t = netdev_priv(dev);
1208
+
1209
+ ip6rd.prefix = t->ip6rd.prefix;
1210
+ ip6rd.relay_prefix = t->ip6rd.relay_prefix;
1211
+ ip6rd.prefixlen = t->ip6rd.prefixlen;
1212
+ ip6rd.relay_prefixlen = t->ip6rd.relay_prefixlen;
1213
+ if (copy_to_user(ifr->ifr_ifru.ifru_data, &ip6rd, sizeof(ip6rd)))
1214
+ return -EFAULT;
1215
+ return 0;
1216
+}
1217
+
1218
+static int
1219
+ipip6_tunnel_6rdctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1220
+{
1221
+ struct ip_tunnel *t = netdev_priv(dev);
1222
+ struct ip_tunnel_6rd ip6rd;
1223
+ int err;
1224
+
1225
+ if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN))
1226
+ return -EPERM;
1227
+ if (copy_from_user(&ip6rd, ifr->ifr_ifru.ifru_data, sizeof(ip6rd)))
1228
+ return -EFAULT;
1229
+
1230
+ if (cmd != SIOCDEL6RD) {
1231
+ err = ipip6_tunnel_update_6rd(t, &ip6rd);
1232
+ if (err < 0)
1233
+ return err;
1234
+ } else
1235
+ ipip6_tunnel_clone_6rd(dev, dev_to_sit_net(dev));
1236
+ return 0;
1237
+}
1238
+
1239
+#endif /* CONFIG_IPV6_SIT_6RD */
11511240
11521241 static bool ipip6_valid_ip_proto(u8 ipproto)
11531242 {
....@@ -1160,185 +1249,145 @@
11601249 }
11611250
11621251 static int
1163
-ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1252
+__ipip6_tunnel_ioctl_validate(struct net *net, struct ip_tunnel_parm *p)
11641253 {
1165
- int err = 0;
1166
- struct ip_tunnel_parm p;
1167
- struct ip_tunnel_prl prl;
1168
- struct ip_tunnel *t = netdev_priv(dev);
1169
- struct net *net = t->net;
1170
- struct sit_net *sitn = net_generic(net, sit_net_id);
1171
-#ifdef CONFIG_IPV6_SIT_6RD
1172
- struct ip_tunnel_6rd ip6rd;
1173
-#endif
1254
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1255
+ return -EPERM;
11741256
1257
+ if (!ipip6_valid_ip_proto(p->iph.protocol))
1258
+ return -EINVAL;
1259
+ if (p->iph.version != 4 ||
1260
+ p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF)))
1261
+ return -EINVAL;
1262
+
1263
+ if (p->iph.ttl)
1264
+ p->iph.frag_off |= htons(IP_DF);
1265
+ return 0;
1266
+}
1267
+
1268
+static int
1269
+ipip6_tunnel_get(struct net_device *dev, struct ip_tunnel_parm *p)
1270
+{
1271
+ struct ip_tunnel *t = netdev_priv(dev);
1272
+
1273
+ if (dev == dev_to_sit_net(dev)->fb_tunnel_dev)
1274
+ t = ipip6_tunnel_locate(t->net, p, 0);
1275
+ if (!t)
1276
+ t = netdev_priv(dev);
1277
+ memcpy(p, &t->parms, sizeof(*p));
1278
+ return 0;
1279
+}
1280
+
1281
+static int
1282
+ipip6_tunnel_add(struct net_device *dev, struct ip_tunnel_parm *p)
1283
+{
1284
+ struct ip_tunnel *t = netdev_priv(dev);
1285
+ int err;
1286
+
1287
+ err = __ipip6_tunnel_ioctl_validate(t->net, p);
1288
+ if (err)
1289
+ return err;
1290
+
1291
+ t = ipip6_tunnel_locate(t->net, p, 1);
1292
+ if (!t)
1293
+ return -ENOBUFS;
1294
+ return 0;
1295
+}
1296
+
1297
+static int
1298
+ipip6_tunnel_change(struct net_device *dev, struct ip_tunnel_parm *p)
1299
+{
1300
+ struct ip_tunnel *t = netdev_priv(dev);
1301
+ int err;
1302
+
1303
+ err = __ipip6_tunnel_ioctl_validate(t->net, p);
1304
+ if (err)
1305
+ return err;
1306
+
1307
+ t = ipip6_tunnel_locate(t->net, p, 0);
1308
+ if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
1309
+ if (!t)
1310
+ return -ENOENT;
1311
+ } else {
1312
+ if (t) {
1313
+ if (t->dev != dev)
1314
+ return -EEXIST;
1315
+ } else {
1316
+ if (((dev->flags & IFF_POINTOPOINT) && !p->iph.daddr) ||
1317
+ (!(dev->flags & IFF_POINTOPOINT) && p->iph.daddr))
1318
+ return -EINVAL;
1319
+ t = netdev_priv(dev);
1320
+ }
1321
+
1322
+ ipip6_tunnel_update(t, p, t->fwmark);
1323
+ }
1324
+
1325
+ return 0;
1326
+}
1327
+
1328
+static int
1329
+ipip6_tunnel_del(struct net_device *dev, struct ip_tunnel_parm *p)
1330
+{
1331
+ struct ip_tunnel *t = netdev_priv(dev);
1332
+
1333
+ if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN))
1334
+ return -EPERM;
1335
+
1336
+ if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
1337
+ t = ipip6_tunnel_locate(t->net, p, 0);
1338
+ if (!t)
1339
+ return -ENOENT;
1340
+ if (t == netdev_priv(dev_to_sit_net(dev)->fb_tunnel_dev))
1341
+ return -EPERM;
1342
+ dev = t->dev;
1343
+ }
1344
+ unregister_netdevice(dev);
1345
+ return 0;
1346
+}
1347
+
1348
+static int
1349
+ipip6_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
1350
+{
11751351 switch (cmd) {
11761352 case SIOCGETTUNNEL:
1177
-#ifdef CONFIG_IPV6_SIT_6RD
1178
- case SIOCGET6RD:
1179
-#endif
1180
- if (dev == sitn->fb_tunnel_dev) {
1181
- if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
1182
- err = -EFAULT;
1183
- break;
1184
- }
1185
- t = ipip6_tunnel_locate(net, &p, 0);
1186
- if (!t)
1187
- t = netdev_priv(dev);
1188
- }
1353
+ return ipip6_tunnel_get(dev, p);
1354
+ case SIOCADDTUNNEL:
1355
+ return ipip6_tunnel_add(dev, p);
1356
+ case SIOCCHGTUNNEL:
1357
+ return ipip6_tunnel_change(dev, p);
1358
+ case SIOCDELTUNNEL:
1359
+ return ipip6_tunnel_del(dev, p);
1360
+ default:
1361
+ return -EINVAL;
1362
+ }
1363
+}
11891364
1190
- err = -EFAULT;
1191
- if (cmd == SIOCGETTUNNEL) {
1192
- memcpy(&p, &t->parms, sizeof(p));
1193
- if (copy_to_user(ifr->ifr_ifru.ifru_data, &p,
1194
- sizeof(p)))
1195
- goto done;
1196
-#ifdef CONFIG_IPV6_SIT_6RD
1197
- } else {
1198
- ip6rd.prefix = t->ip6rd.prefix;
1199
- ip6rd.relay_prefix = t->ip6rd.relay_prefix;
1200
- ip6rd.prefixlen = t->ip6rd.prefixlen;
1201
- ip6rd.relay_prefixlen = t->ip6rd.relay_prefixlen;
1202
- if (copy_to_user(ifr->ifr_ifru.ifru_data, &ip6rd,
1203
- sizeof(ip6rd)))
1204
- goto done;
1205
-#endif
1206
- }
1207
- err = 0;
1208
- break;
1209
-
1365
+static int
1366
+ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1367
+{
1368
+ switch (cmd) {
1369
+ case SIOCGETTUNNEL:
12101370 case SIOCADDTUNNEL:
12111371 case SIOCCHGTUNNEL:
1212
- err = -EPERM;
1213
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1214
- goto done;
1215
-
1216
- err = -EFAULT;
1217
- if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
1218
- goto done;
1219
-
1220
- err = -EINVAL;
1221
- if (!ipip6_valid_ip_proto(p.iph.protocol))
1222
- goto done;
1223
- if (p.iph.version != 4 ||
1224
- p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
1225
- goto done;
1226
- if (p.iph.ttl)
1227
- p.iph.frag_off |= htons(IP_DF);
1228
-
1229
- t = ipip6_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
1230
-
1231
- if (dev != sitn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
1232
- if (t) {
1233
- if (t->dev != dev) {
1234
- err = -EEXIST;
1235
- break;
1236
- }
1237
- } else {
1238
- if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) ||
1239
- (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) {
1240
- err = -EINVAL;
1241
- break;
1242
- }
1243
- t = netdev_priv(dev);
1244
- }
1245
-
1246
- ipip6_tunnel_update(t, &p, t->fwmark);
1247
- }
1248
-
1249
- if (t) {
1250
- err = 0;
1251
- if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
1252
- err = -EFAULT;
1253
- } else
1254
- err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
1255
- break;
1256
-
12571372 case SIOCDELTUNNEL:
1258
- err = -EPERM;
1259
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1260
- goto done;
1261
-
1262
- if (dev == sitn->fb_tunnel_dev) {
1263
- err = -EFAULT;
1264
- if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
1265
- goto done;
1266
- err = -ENOENT;
1267
- t = ipip6_tunnel_locate(net, &p, 0);
1268
- if (!t)
1269
- goto done;
1270
- err = -EPERM;
1271
- if (t == netdev_priv(sitn->fb_tunnel_dev))
1272
- goto done;
1273
- dev = t->dev;
1274
- }
1275
- unregister_netdevice(dev);
1276
- err = 0;
1277
- break;
1278
-
1373
+ return ip_tunnel_ioctl(dev, ifr, cmd);
12791374 case SIOCGETPRL:
1280
- err = -EINVAL;
1281
- if (dev == sitn->fb_tunnel_dev)
1282
- goto done;
1283
- err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data);
1284
- break;
1285
-
1375
+ return ipip6_tunnel_get_prl(dev, ifr);
12861376 case SIOCADDPRL:
12871377 case SIOCDELPRL:
12881378 case SIOCCHGPRL:
1289
- err = -EPERM;
1290
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1291
- goto done;
1292
- err = -EINVAL;
1293
- if (dev == sitn->fb_tunnel_dev)
1294
- goto done;
1295
- err = -EFAULT;
1296
- if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl)))
1297
- goto done;
1298
-
1299
- switch (cmd) {
1300
- case SIOCDELPRL:
1301
- err = ipip6_tunnel_del_prl(t, &prl);
1302
- break;
1303
- case SIOCADDPRL:
1304
- case SIOCCHGPRL:
1305
- err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
1306
- break;
1307
- }
1308
- dst_cache_reset(&t->dst_cache);
1309
- netdev_state_change(dev);
1310
- break;
1311
-
1379
+ return ipip6_tunnel_prl_ctl(dev, ifr, cmd);
13121380 #ifdef CONFIG_IPV6_SIT_6RD
1381
+ case SIOCGET6RD:
1382
+ return ipip6_tunnel_get6rd(dev, ifr);
13131383 case SIOCADD6RD:
13141384 case SIOCCHG6RD:
13151385 case SIOCDEL6RD:
1316
- err = -EPERM;
1317
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1318
- goto done;
1319
-
1320
- err = -EFAULT;
1321
- if (copy_from_user(&ip6rd, ifr->ifr_ifru.ifru_data,
1322
- sizeof(ip6rd)))
1323
- goto done;
1324
-
1325
- if (cmd != SIOCDEL6RD) {
1326
- err = ipip6_tunnel_update_6rd(t, &ip6rd);
1327
- if (err < 0)
1328
- goto done;
1329
- } else
1330
- ipip6_tunnel_clone_6rd(dev, sitn);
1331
-
1332
- err = 0;
1333
- break;
1386
+ return ipip6_tunnel_6rdctl(dev, ifr, cmd);
13341387 #endif
1335
-
13361388 default:
1337
- err = -EINVAL;
1389
+ return -EINVAL;
13381390 }
1339
-
1340
-done:
1341
- return err;
13421391 }
13431392
13441393 static const struct net_device_ops ipip6_netdev_ops = {
....@@ -1348,6 +1397,7 @@
13481397 .ndo_do_ioctl = ipip6_tunnel_ioctl,
13491398 .ndo_get_stats64 = ip_tunnel_get_stats64,
13501399 .ndo_get_iflink = ip_tunnel_get_iflink,
1400
+ .ndo_tunnel_ctl = ipip6_tunnel_ctl,
13511401 };
13521402
13531403 static void ipip6_dev_free(struct net_device *dev)
....@@ -1370,6 +1420,7 @@
13701420 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
13711421
13721422 dev->netdev_ops = &ipip6_netdev_ops;
1423
+ dev->header_ops = &ip_tunnel_header_ops;
13731424 dev->needs_free_netdev = true;
13741425 dev->priv_destructor = ipip6_dev_free;
13751426