forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
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 }
....@@ -1084,10 +1123,12 @@
10841123
10851124 if (tdev && !netif_is_l3_master(tdev)) {
10861125 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);
10911132 }
10921133 }
10931134
....@@ -1147,7 +1188,53 @@
11471188 netdev_state_change(t->dev);
11481189 return 0;
11491190 }
1150
-#endif
1191
+
1192
+static int
1193
+ipip6_tunnel_get6rd(struct net_device *dev, struct ifreq *ifr)
1194
+{
1195
+ struct ip_tunnel *t = netdev_priv(dev);
1196
+ struct ip_tunnel_6rd ip6rd;
1197
+ struct ip_tunnel_parm p;
1198
+
1199
+ if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
1200
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
1201
+ return -EFAULT;
1202
+ t = ipip6_tunnel_locate(t->net, &p, 0);
1203
+ }
1204
+ if (!t)
1205
+ t = netdev_priv(dev);
1206
+
1207
+ ip6rd.prefix = t->ip6rd.prefix;
1208
+ ip6rd.relay_prefix = t->ip6rd.relay_prefix;
1209
+ ip6rd.prefixlen = t->ip6rd.prefixlen;
1210
+ ip6rd.relay_prefixlen = t->ip6rd.relay_prefixlen;
1211
+ if (copy_to_user(ifr->ifr_ifru.ifru_data, &ip6rd, sizeof(ip6rd)))
1212
+ return -EFAULT;
1213
+ return 0;
1214
+}
1215
+
1216
+static int
1217
+ipip6_tunnel_6rdctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1218
+{
1219
+ struct ip_tunnel *t = netdev_priv(dev);
1220
+ struct ip_tunnel_6rd ip6rd;
1221
+ int err;
1222
+
1223
+ if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN))
1224
+ return -EPERM;
1225
+ if (copy_from_user(&ip6rd, ifr->ifr_ifru.ifru_data, sizeof(ip6rd)))
1226
+ return -EFAULT;
1227
+
1228
+ if (cmd != SIOCDEL6RD) {
1229
+ err = ipip6_tunnel_update_6rd(t, &ip6rd);
1230
+ if (err < 0)
1231
+ return err;
1232
+ } else
1233
+ ipip6_tunnel_clone_6rd(dev, dev_to_sit_net(dev));
1234
+ return 0;
1235
+}
1236
+
1237
+#endif /* CONFIG_IPV6_SIT_6RD */
11511238
11521239 static bool ipip6_valid_ip_proto(u8 ipproto)
11531240 {
....@@ -1160,185 +1247,145 @@
11601247 }
11611248
11621249 static int
1163
-ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1250
+__ipip6_tunnel_ioctl_validate(struct net *net, struct ip_tunnel_parm *p)
11641251 {
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
1252
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1253
+ return -EPERM;
11741254
1255
+ if (!ipip6_valid_ip_proto(p->iph.protocol))
1256
+ return -EINVAL;
1257
+ if (p->iph.version != 4 ||
1258
+ p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF)))
1259
+ return -EINVAL;
1260
+
1261
+ if (p->iph.ttl)
1262
+ p->iph.frag_off |= htons(IP_DF);
1263
+ return 0;
1264
+}
1265
+
1266
+static int
1267
+ipip6_tunnel_get(struct net_device *dev, struct ip_tunnel_parm *p)
1268
+{
1269
+ struct ip_tunnel *t = netdev_priv(dev);
1270
+
1271
+ if (dev == dev_to_sit_net(dev)->fb_tunnel_dev)
1272
+ t = ipip6_tunnel_locate(t->net, p, 0);
1273
+ if (!t)
1274
+ t = netdev_priv(dev);
1275
+ memcpy(p, &t->parms, sizeof(*p));
1276
+ return 0;
1277
+}
1278
+
1279
+static int
1280
+ipip6_tunnel_add(struct net_device *dev, struct ip_tunnel_parm *p)
1281
+{
1282
+ struct ip_tunnel *t = netdev_priv(dev);
1283
+ int err;
1284
+
1285
+ err = __ipip6_tunnel_ioctl_validate(t->net, p);
1286
+ if (err)
1287
+ return err;
1288
+
1289
+ t = ipip6_tunnel_locate(t->net, p, 1);
1290
+ if (!t)
1291
+ return -ENOBUFS;
1292
+ return 0;
1293
+}
1294
+
1295
+static int
1296
+ipip6_tunnel_change(struct net_device *dev, struct ip_tunnel_parm *p)
1297
+{
1298
+ struct ip_tunnel *t = netdev_priv(dev);
1299
+ int err;
1300
+
1301
+ err = __ipip6_tunnel_ioctl_validate(t->net, p);
1302
+ if (err)
1303
+ return err;
1304
+
1305
+ t = ipip6_tunnel_locate(t->net, p, 0);
1306
+ if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
1307
+ if (!t)
1308
+ return -ENOENT;
1309
+ } else {
1310
+ if (t) {
1311
+ if (t->dev != dev)
1312
+ return -EEXIST;
1313
+ } else {
1314
+ if (((dev->flags & IFF_POINTOPOINT) && !p->iph.daddr) ||
1315
+ (!(dev->flags & IFF_POINTOPOINT) && p->iph.daddr))
1316
+ return -EINVAL;
1317
+ t = netdev_priv(dev);
1318
+ }
1319
+
1320
+ ipip6_tunnel_update(t, p, t->fwmark);
1321
+ }
1322
+
1323
+ return 0;
1324
+}
1325
+
1326
+static int
1327
+ipip6_tunnel_del(struct net_device *dev, struct ip_tunnel_parm *p)
1328
+{
1329
+ struct ip_tunnel *t = netdev_priv(dev);
1330
+
1331
+ if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN))
1332
+ return -EPERM;
1333
+
1334
+ if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
1335
+ t = ipip6_tunnel_locate(t->net, p, 0);
1336
+ if (!t)
1337
+ return -ENOENT;
1338
+ if (t == netdev_priv(dev_to_sit_net(dev)->fb_tunnel_dev))
1339
+ return -EPERM;
1340
+ dev = t->dev;
1341
+ }
1342
+ unregister_netdevice(dev);
1343
+ return 0;
1344
+}
1345
+
1346
+static int
1347
+ipip6_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
1348
+{
11751349 switch (cmd) {
11761350 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
- }
1351
+ return ipip6_tunnel_get(dev, p);
1352
+ case SIOCADDTUNNEL:
1353
+ return ipip6_tunnel_add(dev, p);
1354
+ case SIOCCHGTUNNEL:
1355
+ return ipip6_tunnel_change(dev, p);
1356
+ case SIOCDELTUNNEL:
1357
+ return ipip6_tunnel_del(dev, p);
1358
+ default:
1359
+ return -EINVAL;
1360
+ }
1361
+}
11891362
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
-
1363
+static int
1364
+ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1365
+{
1366
+ switch (cmd) {
1367
+ case SIOCGETTUNNEL:
12101368 case SIOCADDTUNNEL:
12111369 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
-
12571370 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
-
1371
+ return ip_tunnel_ioctl(dev, ifr, cmd);
12791372 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
-
1373
+ return ipip6_tunnel_get_prl(dev, ifr);
12861374 case SIOCADDPRL:
12871375 case SIOCDELPRL:
12881376 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
-
1377
+ return ipip6_tunnel_prl_ctl(dev, ifr, cmd);
13121378 #ifdef CONFIG_IPV6_SIT_6RD
1379
+ case SIOCGET6RD:
1380
+ return ipip6_tunnel_get6rd(dev, ifr);
13131381 case SIOCADD6RD:
13141382 case SIOCCHG6RD:
13151383 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;
1384
+ return ipip6_tunnel_6rdctl(dev, ifr, cmd);
13341385 #endif
1335
-
13361386 default:
1337
- err = -EINVAL;
1387
+ return -EINVAL;
13381388 }
1339
-
1340
-done:
1341
- return err;
13421389 }
13431390
13441391 static const struct net_device_ops ipip6_netdev_ops = {
....@@ -1348,6 +1395,7 @@
13481395 .ndo_do_ioctl = ipip6_tunnel_ioctl,
13491396 .ndo_get_stats64 = ip_tunnel_get_stats64,
13501397 .ndo_get_iflink = ip_tunnel_get_iflink,
1398
+ .ndo_tunnel_ctl = ipip6_tunnel_ctl,
13511399 };
13521400
13531401 static void ipip6_dev_free(struct net_device *dev)
....@@ -1370,6 +1418,7 @@
13701418 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
13711419
13721420 dev->netdev_ops = &ipip6_netdev_ops;
1421
+ dev->header_ops = &ip_tunnel_header_ops;
13731422 dev->needs_free_netdev = true;
13741423 dev->priv_destructor = ipip6_dev_free;
13751424