hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/net/ipv4/ipmr.c
....@@ -1,13 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * IP multicast routing support for mrouted 3.6/3.8
34 *
45 * (c) 1995 Alan Cox, <alan@lxorguk.ukuu.org.uk>
56 * Linux Consultancy and Custom Driver Development
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License
9
- * as published by the Free Software Foundation; either version
10
- * 2 of the License, or (at your option) any later version.
117 *
128 * Fixes:
139 * Michael Chastain : Incorrect size of copying.
....@@ -23,7 +19,6 @@
2319 * Carlos Picoto : PIMv1 Support
2420 * Pavlin Ivanov Radoslavov: PIMv2 Registers must checksum only PIM header
2521 * Relax this requirement to work with older peers.
26
- *
2722 */
2823
2924 #include <linux/uaccess.h>
....@@ -66,8 +61,7 @@
6661 #include <net/netlink.h>
6762 #include <net/fib_rules.h>
6863 #include <linux/netconf.h>
69
-#include <net/nexthop.h>
70
-#include <net/switchdev.h>
64
+#include <net/rtnh.h>
7165
7266 #include <linux/nospec.h>
7367
....@@ -111,12 +105,14 @@
111105 static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
112106 int cmd);
113107 static void igmpmsg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt);
114
-static void mroute_clean_tables(struct mr_table *mrt, bool all);
108
+static void mroute_clean_tables(struct mr_table *mrt, int flags);
115109 static void ipmr_expire_process(struct timer_list *t);
116110
117111 #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
118
-#define ipmr_for_each_table(mrt, net) \
119
- list_for_each_entry_rcu(mrt, &net->ipv4.mr_tables, list)
112
+#define ipmr_for_each_table(mrt, net) \
113
+ list_for_each_entry_rcu(mrt, &net->ipv4.mr_tables, list, \
114
+ lockdep_rtnl_is_held() || \
115
+ list_empty(&net->ipv4.mr_tables))
120116
121117 static struct mr_table *ipmr_mr_table_iter(struct net *net,
122118 struct mr_table *mrt)
....@@ -286,9 +282,10 @@
286282 rtnl_unlock();
287283 }
288284
289
-static int ipmr_rules_dump(struct net *net, struct notifier_block *nb)
285
+static int ipmr_rules_dump(struct net *net, struct notifier_block *nb,
286
+ struct netlink_ext_ack *extack)
290287 {
291
- return fib_rules_dump(net, nb, RTNL_FAMILY_IPMR);
288
+ return fib_rules_dump(net, nb, RTNL_FAMILY_IPMR, extack);
292289 }
293290
294291 static unsigned int ipmr_rules_seq_read(struct net *net)
....@@ -344,7 +341,8 @@
344341 rtnl_unlock();
345342 }
346343
347
-static int ipmr_rules_dump(struct net *net, struct notifier_block *nb)
344
+static int ipmr_rules_dump(struct net *net, struct notifier_block *nb,
345
+ struct netlink_ext_ack *extack)
348346 {
349347 return 0;
350348 }
....@@ -376,7 +374,6 @@
376374 .key_offset = offsetof(struct mfc_cache, cmparg),
377375 .key_len = sizeof(struct mfc_cache_cmp_arg),
378376 .nelem_hint = 3,
379
- .locks_mul = 1,
380377 .obj_cmpfn = ipmr_hash_cmp,
381378 .automatic_shrinking = true,
382379 };
....@@ -418,43 +415,13 @@
418415 static void ipmr_free_table(struct mr_table *mrt)
419416 {
420417 del_timer_sync(&mrt->ipmr_expire_timer);
421
- mroute_clean_tables(mrt, true);
418
+ mroute_clean_tables(mrt, MRT_FLUSH_VIFS | MRT_FLUSH_VIFS_STATIC |
419
+ MRT_FLUSH_MFC | MRT_FLUSH_MFC_STATIC);
422420 rhltable_destroy(&mrt->mfc_hash);
423421 kfree(mrt);
424422 }
425423
426424 /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */
427
-
428
-static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v)
429
-{
430
- struct net *net = dev_net(dev);
431
-
432
- dev_close(dev);
433
-
434
- dev = __dev_get_by_name(net, "tunl0");
435
- if (dev) {
436
- const struct net_device_ops *ops = dev->netdev_ops;
437
- struct ifreq ifr;
438
- struct ip_tunnel_parm p;
439
-
440
- memset(&p, 0, sizeof(p));
441
- p.iph.daddr = v->vifc_rmt_addr.s_addr;
442
- p.iph.saddr = v->vifc_lcl_addr.s_addr;
443
- p.iph.version = 4;
444
- p.iph.ihl = 5;
445
- p.iph.protocol = IPPROTO_IPIP;
446
- sprintf(p.name, "dvmrp%d", v->vifc_vifi);
447
- ifr.ifr_ifru.ifru_data = (__force void __user *)&p;
448
-
449
- if (ops->ndo_do_ioctl) {
450
- mm_segment_t oldfs = get_fs();
451
-
452
- set_fs(KERNEL_DS);
453
- ops->ndo_do_ioctl(dev, &ifr, SIOCDELTUNNEL);
454
- set_fs(oldfs);
455
- }
456
- }
457
-}
458425
459426 /* Initialize ipmr pimreg/tunnel in_device */
460427 static bool ipmr_init_vif_indev(const struct net_device *dev)
....@@ -475,51 +442,52 @@
475442
476443 static struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v)
477444 {
478
- struct net_device *dev;
445
+ struct net_device *tunnel_dev, *new_dev;
446
+ struct ip_tunnel_parm p = { };
447
+ int err;
479448
480
- dev = __dev_get_by_name(net, "tunl0");
449
+ tunnel_dev = __dev_get_by_name(net, "tunl0");
450
+ if (!tunnel_dev)
451
+ goto out;
481452
482
- if (dev) {
483
- const struct net_device_ops *ops = dev->netdev_ops;
484
- int err;
485
- struct ifreq ifr;
486
- struct ip_tunnel_parm p;
453
+ p.iph.daddr = v->vifc_rmt_addr.s_addr;
454
+ p.iph.saddr = v->vifc_lcl_addr.s_addr;
455
+ p.iph.version = 4;
456
+ p.iph.ihl = 5;
457
+ p.iph.protocol = IPPROTO_IPIP;
458
+ sprintf(p.name, "dvmrp%d", v->vifc_vifi);
487459
488
- memset(&p, 0, sizeof(p));
489
- p.iph.daddr = v->vifc_rmt_addr.s_addr;
490
- p.iph.saddr = v->vifc_lcl_addr.s_addr;
491
- p.iph.version = 4;
492
- p.iph.ihl = 5;
493
- p.iph.protocol = IPPROTO_IPIP;
494
- sprintf(p.name, "dvmrp%d", v->vifc_vifi);
495
- ifr.ifr_ifru.ifru_data = (__force void __user *)&p;
460
+ if (!tunnel_dev->netdev_ops->ndo_tunnel_ctl)
461
+ goto out;
462
+ err = tunnel_dev->netdev_ops->ndo_tunnel_ctl(tunnel_dev, &p,
463
+ SIOCADDTUNNEL);
464
+ if (err)
465
+ goto out;
496466
497
- if (ops->ndo_do_ioctl) {
498
- mm_segment_t oldfs = get_fs();
467
+ new_dev = __dev_get_by_name(net, p.name);
468
+ if (!new_dev)
469
+ goto out;
499470
500
- set_fs(KERNEL_DS);
501
- err = ops->ndo_do_ioctl(dev, &ifr, SIOCADDTUNNEL);
502
- set_fs(oldfs);
503
- } else {
504
- err = -EOPNOTSUPP;
505
- }
506
- dev = NULL;
507
-
508
- if (err == 0 &&
509
- (dev = __dev_get_by_name(net, p.name)) != NULL) {
510
- dev->flags |= IFF_MULTICAST;
511
- if (!ipmr_init_vif_indev(dev))
512
- goto failure;
513
- if (dev_open(dev))
514
- goto failure;
515
- dev_hold(dev);
516
- }
471
+ new_dev->flags |= IFF_MULTICAST;
472
+ if (!ipmr_init_vif_indev(new_dev))
473
+ goto out_unregister;
474
+ if (dev_open(new_dev, NULL))
475
+ goto out_unregister;
476
+ dev_hold(new_dev);
477
+ err = dev_set_allmulti(new_dev, 1);
478
+ if (err) {
479
+ dev_close(new_dev);
480
+ tunnel_dev->netdev_ops->ndo_tunnel_ctl(tunnel_dev, &p,
481
+ SIOCDELTUNNEL);
482
+ dev_put(new_dev);
483
+ new_dev = ERR_PTR(err);
517484 }
518
- return dev;
485
+ return new_dev;
519486
520
-failure:
521
- unregister_netdevice(dev);
522
- return NULL;
487
+out_unregister:
488
+ unregister_netdevice(new_dev);
489
+out:
490
+ return ERR_PTR(-ENOBUFS);
523491 }
524492
525493 #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
....@@ -593,7 +561,7 @@
593561
594562 if (!ipmr_init_vif_indev(dev))
595563 goto failure;
596
- if (dev_open(dev))
564
+ if (dev_open(dev, NULL))
597565 goto failure;
598566
599567 dev_hold(dev);
....@@ -670,7 +638,10 @@
670638
671639 /**
672640 * vif_delete - Delete a VIF entry
641
+ * @mrt: Table to delete from
642
+ * @vifi: VIF identifier to delete
673643 * @notify: Set to 1, if the caller is a notifier_call
644
+ * @head: if unregistering the VIF, place it on this queue
674645 */
675646 static int vif_delete(struct mr_table *mrt, int vifi, int notify,
676647 struct list_head *head)
....@@ -839,10 +810,8 @@
839810 static int vif_add(struct net *net, struct mr_table *mrt,
840811 struct vifctl *vifc, int mrtsock)
841812 {
813
+ struct netdev_phys_item_id ppid = { };
842814 int vifi = vifc->vifc_vifi;
843
- struct switchdev_attr attr = {
844
- .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
845
- };
846815 struct vif_device *v = &mrt->vif_table[vifi];
847816 struct net_device *dev;
848817 struct in_device *in_dev;
....@@ -873,14 +842,8 @@
873842 break;
874843 case VIFF_TUNNEL:
875844 dev = ipmr_new_tunnel(net, vifc);
876
- if (!dev)
877
- return -ENOBUFS;
878
- err = dev_set_allmulti(dev, 1);
879
- if (err) {
880
- ipmr_del_tunnel(dev, vifc);
881
- dev_put(dev);
882
- return err;
883
- }
845
+ if (IS_ERR(dev))
846
+ return PTR_ERR(dev);
884847 break;
885848 case VIFF_USE_IFINDEX:
886849 case 0:
....@@ -921,10 +884,10 @@
921884 vifc->vifc_flags | (!mrtsock ? VIFF_STATIC : 0),
922885 (VIFF_TUNNEL | VIFF_REGISTER));
923886
924
- attr.orig_dev = dev;
925
- if (!switchdev_port_attr_get(dev, &attr)) {
926
- memcpy(v->dev_parent_id.id, attr.u.ppid.id, attr.u.ppid.id_len);
927
- v->dev_parent_id.id_len = attr.u.ppid.id_len;
887
+ err = dev_get_port_parent_id(dev, &ppid, true);
888
+ if (err == 0) {
889
+ memcpy(v->dev_parent_id.id, ppid.id, ppid.id_len);
890
+ v->dev_parent_id.id_len = ppid.id_len;
928891 } else {
929892 v->dev_parent_id.id_len = 0;
930893 }
....@@ -1077,10 +1040,13 @@
10771040 memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr));
10781041 msg->im_msgtype = assert;
10791042 msg->im_mbz = 0;
1080
- if (assert == IGMPMSG_WRVIFWHOLE)
1043
+ if (assert == IGMPMSG_WRVIFWHOLE) {
10811044 msg->im_vif = vifi;
1082
- else
1045
+ msg->im_vif_hi = vifi >> 8;
1046
+ } else {
10831047 msg->im_vif = mrt->mroute_reg_vif_num;
1048
+ msg->im_vif_hi = mrt->mroute_reg_vif_num >> 8;
1049
+ }
10841050 ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2;
10851051 ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) +
10861052 sizeof(struct iphdr));
....@@ -1093,6 +1059,7 @@
10931059 ip_hdr(skb)->protocol = 0;
10941060 msg = (struct igmpmsg *)skb_network_header(skb);
10951061 msg->im_vif = vifi;
1062
+ msg->im_vif_hi = vifi >> 8;
10961063 skb_dst_set(skb, dst_clone(skb_dst(pkt)));
10971064 /* Add our header */
10981065 igmp = skb_put(skb, sizeof(struct igmphdr));
....@@ -1144,8 +1111,8 @@
11441111
11451112 if (!found) {
11461113 /* Create a new entry if allowable */
1147
- if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
1148
- (c = ipmr_cache_alloc_unres()) == NULL) {
1114
+ c = ipmr_cache_alloc_unres();
1115
+ if (!c) {
11491116 spin_unlock_bh(&mfc_unres_lock);
11501117
11511118 kfree_skb(skb);
....@@ -1301,7 +1268,7 @@
13011268 }
13021269
13031270 /* Close the multicast socket, and clear the vif tables etc */
1304
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
1271
+static void mroute_clean_tables(struct mr_table *mrt, int flags)
13051272 {
13061273 struct net *net = read_pnet(&mrt->net);
13071274 struct mr_mfc *c, *tmp;
....@@ -1310,35 +1277,44 @@
13101277 int i;
13111278
13121279 /* Shut down all active vif entries */
1313
- for (i = 0; i < mrt->maxvif; i++) {
1314
- if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
1315
- continue;
1316
- vif_delete(mrt, i, 0, &list);
1280
+ if (flags & (MRT_FLUSH_VIFS | MRT_FLUSH_VIFS_STATIC)) {
1281
+ for (i = 0; i < mrt->maxvif; i++) {
1282
+ if (((mrt->vif_table[i].flags & VIFF_STATIC) &&
1283
+ !(flags & MRT_FLUSH_VIFS_STATIC)) ||
1284
+ (!(mrt->vif_table[i].flags & VIFF_STATIC) && !(flags & MRT_FLUSH_VIFS)))
1285
+ continue;
1286
+ vif_delete(mrt, i, 0, &list);
1287
+ }
1288
+ unregister_netdevice_many(&list);
13171289 }
1318
- unregister_netdevice_many(&list);
13191290
13201291 /* Wipe the cache */
1321
- list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
1322
- if (!all && (c->mfc_flags & MFC_STATIC))
1323
- continue;
1324
- rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params);
1325
- list_del_rcu(&c->list);
1326
- cache = (struct mfc_cache *)c;
1327
- call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
1328
- mrt->id);
1329
- mroute_netlink_event(mrt, cache, RTM_DELROUTE);
1330
- mr_cache_put(c);
1292
+ if (flags & (MRT_FLUSH_MFC | MRT_FLUSH_MFC_STATIC)) {
1293
+ list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
1294
+ if (((c->mfc_flags & MFC_STATIC) && !(flags & MRT_FLUSH_MFC_STATIC)) ||
1295
+ (!(c->mfc_flags & MFC_STATIC) && !(flags & MRT_FLUSH_MFC)))
1296
+ continue;
1297
+ rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params);
1298
+ list_del_rcu(&c->list);
1299
+ cache = (struct mfc_cache *)c;
1300
+ call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
1301
+ mrt->id);
1302
+ mroute_netlink_event(mrt, cache, RTM_DELROUTE);
1303
+ mr_cache_put(c);
1304
+ }
13311305 }
13321306
1333
- if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
1334
- spin_lock_bh(&mfc_unres_lock);
1335
- list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
1336
- list_del(&c->list);
1337
- cache = (struct mfc_cache *)c;
1338
- mroute_netlink_event(mrt, cache, RTM_DELROUTE);
1339
- ipmr_destroy_unres(mrt, cache);
1307
+ if (flags & MRT_FLUSH_MFC) {
1308
+ if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
1309
+ spin_lock_bh(&mfc_unres_lock);
1310
+ list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
1311
+ list_del(&c->list);
1312
+ cache = (struct mfc_cache *)c;
1313
+ mroute_netlink_event(mrt, cache, RTM_DELROUTE);
1314
+ ipmr_destroy_unres(mrt, cache);
1315
+ }
1316
+ spin_unlock_bh(&mfc_unres_lock);
13401317 }
1341
- spin_unlock_bh(&mfc_unres_lock);
13421318 }
13431319 }
13441320
....@@ -1359,7 +1335,7 @@
13591335 NETCONFA_IFINDEX_ALL,
13601336 net->ipv4.devconf_all);
13611337 RCU_INIT_POINTER(mrt->mroute_sk, NULL);
1362
- mroute_clean_tables(mrt, false);
1338
+ mroute_clean_tables(mrt, MRT_FLUSH_VIFS | MRT_FLUSH_MFC);
13631339 }
13641340 }
13651341 rtnl_unlock();
....@@ -1371,7 +1347,7 @@
13711347 * MOSPF/PIM router set up we can clean this up.
13721348 */
13731349
1374
-int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
1350
+int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
13751351 unsigned int optlen)
13761352 {
13771353 struct net *net = sock_net(sk);
....@@ -1443,7 +1419,7 @@
14431419 ret = -EINVAL;
14441420 break;
14451421 }
1446
- if (copy_from_user(&vif, optval, sizeof(vif))) {
1422
+ if (copy_from_sockptr(&vif, optval, sizeof(vif))) {
14471423 ret = -EFAULT;
14481424 break;
14491425 }
....@@ -1464,14 +1440,14 @@
14641440 case MRT_ADD_MFC:
14651441 case MRT_DEL_MFC:
14661442 parent = -1;
1467
- /* fall through */
1443
+ fallthrough;
14681444 case MRT_ADD_MFC_PROXY:
14691445 case MRT_DEL_MFC_PROXY:
14701446 if (optlen != sizeof(mfc)) {
14711447 ret = -EINVAL;
14721448 break;
14731449 }
1474
- if (copy_from_user(&mfc, optval, sizeof(mfc))) {
1450
+ if (copy_from_sockptr(&mfc, optval, sizeof(mfc))) {
14751451 ret = -EFAULT;
14761452 break;
14771453 }
....@@ -1484,13 +1460,24 @@
14841460 sk == rtnl_dereference(mrt->mroute_sk),
14851461 parent);
14861462 break;
1463
+ case MRT_FLUSH:
1464
+ if (optlen != sizeof(val)) {
1465
+ ret = -EINVAL;
1466
+ break;
1467
+ }
1468
+ if (copy_from_sockptr(&val, optval, sizeof(val))) {
1469
+ ret = -EFAULT;
1470
+ break;
1471
+ }
1472
+ mroute_clean_tables(mrt, val);
1473
+ break;
14871474 /* Control PIM assert. */
14881475 case MRT_ASSERT:
14891476 if (optlen != sizeof(val)) {
14901477 ret = -EINVAL;
14911478 break;
14921479 }
1493
- if (get_user(val, (int __user *)optval)) {
1480
+ if (copy_from_sockptr(&val, optval, sizeof(val))) {
14941481 ret = -EFAULT;
14951482 break;
14961483 }
....@@ -1505,7 +1492,7 @@
15051492 ret = -EINVAL;
15061493 break;
15071494 }
1508
- if (get_user(val, (int __user *)optval)) {
1495
+ if (copy_from_sockptr(&val, optval, sizeof(val))) {
15091496 ret = -EFAULT;
15101497 break;
15111498 }
....@@ -1527,7 +1514,7 @@
15271514 ret = -EINVAL;
15281515 break;
15291516 }
1530
- if (get_user(uval, (u32 __user *)optval)) {
1517
+ if (copy_from_sockptr(&uval, optval, sizeof(uval))) {
15311518 ret = -EFAULT;
15321519 break;
15331520 }
....@@ -1784,7 +1771,7 @@
17841771 ip_send_check(iph);
17851772
17861773 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
1787
- nf_reset(skb);
1774
+ nf_reset_ct(skb);
17881775 }
17891776
17901777 static inline int ipmr_forward_finish(struct net *net, struct sock *sk,
....@@ -1808,7 +1795,7 @@
18081795 struct vif_device *out_vif = &mrt->vif_table[out_vifi];
18091796 struct vif_device *in_vif = &mrt->vif_table[in_vifi];
18101797
1811
- if (!skb->offload_mr_fwd_mark)
1798
+ if (!skb->offload_l3_fwd_mark)
18121799 return false;
18131800 if (!out_vif->dev_parent_id.id_len || !in_vif->dev_parent_id.id_len)
18141801 return false;
....@@ -1826,8 +1813,7 @@
18261813 /* Processing handlers for ipmr_forward */
18271814
18281815 static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
1829
- int in_vifi, struct sk_buff *skb,
1830
- struct mfc_cache *c, int vifi)
1816
+ int in_vifi, struct sk_buff *skb, int vifi)
18311817 {
18321818 const struct iphdr *iph = ip_hdr(skb);
18331819 struct vif_device *vif = &mrt->vif_table[vifi];
....@@ -2033,7 +2019,7 @@
20332019
20342020 if (skb2)
20352021 ipmr_queue_xmit(net, mrt, true_vifi,
2036
- skb2, c, psend);
2022
+ skb2, psend);
20372023 }
20382024 psend = ct;
20392025 }
....@@ -2045,9 +2031,9 @@
20452031
20462032 if (skb2)
20472033 ipmr_queue_xmit(net, mrt, true_vifi, skb2,
2048
- c, psend);
2034
+ psend);
20492035 } else {
2050
- ipmr_queue_xmit(net, mrt, true_vifi, skb, c, psend);
2036
+ ipmr_queue_xmit(net, mrt, true_vifi, skb, psend);
20512037 return;
20522038 }
20532039 }
....@@ -2131,7 +2117,7 @@
21312117
21322118 mroute_sk = rcu_dereference(mrt->mroute_sk);
21332119 if (mroute_sk) {
2134
- nf_reset(skb);
2120
+ nf_reset_ct(skb);
21352121 raw_rcv(mroute_sk, skb);
21362122 return 0;
21372123 }
....@@ -2416,6 +2402,7 @@
24162402 + nla_total_size(4) /* IPMRA_CREPORT_VIF_ID */
24172403 + nla_total_size(4) /* IPMRA_CREPORT_SRC_ADDR */
24182404 + nla_total_size(4) /* IPMRA_CREPORT_DST_ADDR */
2405
+ + nla_total_size(4) /* IPMRA_CREPORT_TABLE */
24192406 /* IPMRA_CREPORT_PKT */
24202407 + nla_total_size(payloadlen)
24212408 ;
....@@ -2447,11 +2434,12 @@
24472434 rtgenm = nlmsg_data(nlh);
24482435 rtgenm->rtgen_family = RTNL_FAMILY_IPMR;
24492436 if (nla_put_u8(skb, IPMRA_CREPORT_MSGTYPE, msg->im_msgtype) ||
2450
- nla_put_u32(skb, IPMRA_CREPORT_VIF_ID, msg->im_vif) ||
2437
+ nla_put_u32(skb, IPMRA_CREPORT_VIF_ID, msg->im_vif | (msg->im_vif_hi << 8)) ||
24512438 nla_put_in_addr(skb, IPMRA_CREPORT_SRC_ADDR,
24522439 msg->im_src.s_addr) ||
24532440 nla_put_in_addr(skb, IPMRA_CREPORT_DST_ADDR,
2454
- msg->im_dst.s_addr))
2441
+ msg->im_dst.s_addr) ||
2442
+ nla_put_u32(skb, IPMRA_CREPORT_TABLE, mrt->id))
24552443 goto nla_put_failure;
24562444
24572445 nla = nla_reserve(skb, IPMRA_CREPORT_PKT, payloadlen);
....@@ -2471,6 +2459,61 @@
24712459 rtnl_set_sk_err(net, RTNLGRP_IPV4_MROUTE_R, -ENOBUFS);
24722460 }
24732461
2462
+static int ipmr_rtm_valid_getroute_req(struct sk_buff *skb,
2463
+ const struct nlmsghdr *nlh,
2464
+ struct nlattr **tb,
2465
+ struct netlink_ext_ack *extack)
2466
+{
2467
+ struct rtmsg *rtm;
2468
+ int i, err;
2469
+
2470
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*rtm))) {
2471
+ NL_SET_ERR_MSG(extack, "ipv4: Invalid header for multicast route get request");
2472
+ return -EINVAL;
2473
+ }
2474
+
2475
+ if (!netlink_strict_get_check(skb))
2476
+ return nlmsg_parse_deprecated(nlh, sizeof(*rtm), tb, RTA_MAX,
2477
+ rtm_ipv4_policy, extack);
2478
+
2479
+ rtm = nlmsg_data(nlh);
2480
+ if ((rtm->rtm_src_len && rtm->rtm_src_len != 32) ||
2481
+ (rtm->rtm_dst_len && rtm->rtm_dst_len != 32) ||
2482
+ rtm->rtm_tos || rtm->rtm_table || rtm->rtm_protocol ||
2483
+ rtm->rtm_scope || rtm->rtm_type || rtm->rtm_flags) {
2484
+ NL_SET_ERR_MSG(extack, "ipv4: Invalid values in header for multicast route get request");
2485
+ return -EINVAL;
2486
+ }
2487
+
2488
+ err = nlmsg_parse_deprecated_strict(nlh, sizeof(*rtm), tb, RTA_MAX,
2489
+ rtm_ipv4_policy, extack);
2490
+ if (err)
2491
+ return err;
2492
+
2493
+ if ((tb[RTA_SRC] && !rtm->rtm_src_len) ||
2494
+ (tb[RTA_DST] && !rtm->rtm_dst_len)) {
2495
+ NL_SET_ERR_MSG(extack, "ipv4: rtm_src_len and rtm_dst_len must be 32 for IPv4");
2496
+ return -EINVAL;
2497
+ }
2498
+
2499
+ for (i = 0; i <= RTA_MAX; i++) {
2500
+ if (!tb[i])
2501
+ continue;
2502
+
2503
+ switch (i) {
2504
+ case RTA_SRC:
2505
+ case RTA_DST:
2506
+ case RTA_TABLE:
2507
+ break;
2508
+ default:
2509
+ NL_SET_ERR_MSG(extack, "ipv4: Unsupported attribute in multicast route get request");
2510
+ return -EINVAL;
2511
+ }
2512
+ }
2513
+
2514
+ return 0;
2515
+}
2516
+
24742517 static int ipmr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
24752518 struct netlink_ext_ack *extack)
24762519 {
....@@ -2479,17 +2522,13 @@
24792522 struct sk_buff *skb = NULL;
24802523 struct mfc_cache *cache;
24812524 struct mr_table *mrt;
2482
- struct rtmsg *rtm;
24832525 __be32 src, grp;
24842526 u32 tableid;
24852527 int err;
24862528
2487
- err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX,
2488
- rtm_ipv4_policy, extack);
2529
+ err = ipmr_rtm_valid_getroute_req(in_skb, nlh, tb, extack);
24892530 if (err < 0)
24902531 goto errout;
2491
-
2492
- rtm = nlmsg_data(nlh);
24932532
24942533 src = tb[RTA_SRC] ? nla_get_in_addr(tb[RTA_SRC]) : 0;
24952534 grp = tb[RTA_DST] ? nla_get_in_addr(tb[RTA_DST]) : 0;
....@@ -2534,8 +2573,34 @@
25342573
25352574 static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
25362575 {
2576
+ struct fib_dump_filter filter = {};
2577
+ int err;
2578
+
2579
+ if (cb->strict_check) {
2580
+ err = ip_valid_fib_dump_req(sock_net(skb->sk), cb->nlh,
2581
+ &filter, cb);
2582
+ if (err < 0)
2583
+ return err;
2584
+ }
2585
+
2586
+ if (filter.table_id) {
2587
+ struct mr_table *mrt;
2588
+
2589
+ mrt = ipmr_get_table(sock_net(skb->sk), filter.table_id);
2590
+ if (!mrt) {
2591
+ if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IPMR)
2592
+ return skb->len;
2593
+
2594
+ NL_SET_ERR_MSG(cb->extack, "ipv4: MR table does not exist");
2595
+ return -ENOENT;
2596
+ }
2597
+ err = mr_table_dump(mrt, skb, cb, _ipmr_fill_mroute,
2598
+ &mfc_unres_lock, &filter);
2599
+ return skb->len ? : err;
2600
+ }
2601
+
25372602 return mr_rtm_dumproute(skb, cb, ipmr_mr_table_iter,
2538
- _ipmr_fill_mroute, &mfc_unres_lock);
2603
+ _ipmr_fill_mroute, &mfc_unres_lock, &filter);
25392604 }
25402605
25412606 static const struct nla_policy rtm_ipmr_policy[RTA_MAX + 1] = {
....@@ -2584,8 +2649,8 @@
25842649 struct rtmsg *rtm;
25852650 int ret, rem;
25862651
2587
- ret = nlmsg_validate(nlh, sizeof(*rtm), RTA_MAX, rtm_ipmr_policy,
2588
- extack);
2652
+ ret = nlmsg_validate_deprecated(nlh, sizeof(*rtm), RTA_MAX,
2653
+ rtm_ipmr_policy, extack);
25892654 if (ret < 0)
25902655 goto out;
25912656 rtm = nlmsg_data(nlh);
....@@ -2693,7 +2758,7 @@
26932758 return true;
26942759
26952760 vif = &mrt->vif_table[vifid];
2696
- vif_nest = nla_nest_start(skb, IPMRA_VIF);
2761
+ vif_nest = nla_nest_start_noflag(skb, IPMRA_VIF);
26972762 if (!vif_nest)
26982763 return false;
26992764 if (nla_put_u32(skb, IPMRA_VIFA_IFINDEX, vif->dev->ifindex) ||
....@@ -2717,6 +2782,31 @@
27172782 return true;
27182783 }
27192784
2785
+static int ipmr_valid_dumplink(const struct nlmsghdr *nlh,
2786
+ struct netlink_ext_ack *extack)
2787
+{
2788
+ struct ifinfomsg *ifm;
2789
+
2790
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
2791
+ NL_SET_ERR_MSG(extack, "ipv4: Invalid header for ipmr link dump");
2792
+ return -EINVAL;
2793
+ }
2794
+
2795
+ if (nlmsg_attrlen(nlh, sizeof(*ifm))) {
2796
+ NL_SET_ERR_MSG(extack, "Invalid data after header in ipmr link dump");
2797
+ return -EINVAL;
2798
+ }
2799
+
2800
+ ifm = nlmsg_data(nlh);
2801
+ if (ifm->__ifi_pad || ifm->ifi_type || ifm->ifi_flags ||
2802
+ ifm->ifi_change || ifm->ifi_index) {
2803
+ NL_SET_ERR_MSG(extack, "Invalid values in header for ipmr link dump request");
2804
+ return -EINVAL;
2805
+ }
2806
+
2807
+ return 0;
2808
+}
2809
+
27202810 static int ipmr_rtm_dumplink(struct sk_buff *skb, struct netlink_callback *cb)
27212811 {
27222812 struct net *net = sock_net(skb->sk);
....@@ -2724,6 +2814,13 @@
27242814 unsigned int t = 0, s_t;
27252815 unsigned int e = 0, s_e;
27262816 struct mr_table *mrt;
2817
+
2818
+ if (cb->strict_check) {
2819
+ int err = ipmr_valid_dumplink(cb->nlh, cb->extack);
2820
+
2821
+ if (err < 0)
2822
+ return err;
2823
+ }
27272824
27282825 s_t = cb->args[0];
27292826 s_e = cb->args[1];
....@@ -2745,7 +2842,7 @@
27452842 memset(hdr, 0, sizeof(*hdr));
27462843 hdr->ifi_family = RTNL_FAMILY_IPMR;
27472844
2748
- af = nla_nest_start(skb, IFLA_AF_SPEC);
2845
+ af = nla_nest_start_noflag(skb, IFLA_AF_SPEC);
27492846 if (!af) {
27502847 nlmsg_cancel(skb, nlh);
27512848 goto out;
....@@ -2756,7 +2853,7 @@
27562853 goto out;
27572854 }
27582855
2759
- vifs = nla_nest_start(skb, IPMRA_TABLE_VIFS);
2856
+ vifs = nla_nest_start_noflag(skb, IPMRA_TABLE_VIFS);
27602857 if (!vifs) {
27612858 nla_nest_end(skb, af);
27622859 nlmsg_end(skb, nlh);
....@@ -2923,10 +3020,11 @@
29233020 return net->ipv4.ipmr_seq + ipmr_rules_seq_read(net);
29243021 }
29253022
2926
-static int ipmr_dump(struct net *net, struct notifier_block *nb)
3023
+static int ipmr_dump(struct net *net, struct notifier_block *nb,
3024
+ struct netlink_ext_ack *extack)
29273025 {
29283026 return mr_dump(net, nb, RTNL_FAMILY_IPMR, ipmr_rules_dump,
2929
- ipmr_mr_table_iter, &mrt_lock);
3027
+ ipmr_mr_table_iter, &mrt_lock, extack);
29303028 }
29313029
29323030 static const struct fib_notifier_ops ipmr_notifier_ops_template = {