Lines Matching +full:dev +full:- +full:active +full:- +full:grp

1 // SPDX-License-Identifier: GPL-2.0-or-later
6 * (c) 2004 Mickael Hoerdt, <hoerdt@clarinet.u-strasbg.fr>
8 * (c) 2004 Jean-Philippe Andriot, <jean-philippe.andriot@6WIND.com>
11 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
69 return rcu_dereference(vif->dev); in vif_dev_read()
91 struct net_device *dev, struct sk_buff *skb,
107 list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list, \
109 list_empty(&net->ipv6.mr6_tables))
117 ret = list_entry_rcu(net->ipv6.mr6_tables.next, in ip6mr_mr_table_iter()
120 ret = list_entry_rcu(mrt->list.next, in ip6mr_mr_table_iter()
123 if (&ret->list == &net->ipv6.mr6_tables) in ip6mr_mr_table_iter()
133 if (mrt->id == id) in __ip6mr_get_table()
162 err = fib_rules_lookup(net->ipv6.mr6_rules_ops, in ip6mr_fib_lookup()
173 struct ip6mr_result *res = arg->result; in ip6mr_rule_action()
176 switch (rule->action) { in ip6mr_rule_action()
180 return -ENETUNREACH; in ip6mr_rule_action()
182 return -EACCES; in ip6mr_rule_action()
185 return -EINVAL; in ip6mr_rule_action()
188 arg->table = fib_rule_get_table(rule, arg); in ip6mr_rule_action()
190 mrt = __ip6mr_get_table(rule->fr_net, arg->table); in ip6mr_rule_action()
192 return -EAGAIN; in ip6mr_rule_action()
193 res->mrt = mrt; in ip6mr_rule_action()
218 frh->dst_len = 0; in ip6mr_rule_fill()
219 frh->src_len = 0; in ip6mr_rule_fill()
220 frh->tos = 0; in ip6mr_rule_fill()
247 INIT_LIST_HEAD(&net->ipv6.mr6_tables); in ip6mr_rules_init()
259 net->ipv6.mr6_rules_ops = ops; in ip6mr_rules_init()
276 list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) { in ip6mr_rules_exit()
277 list_del(&mrt->list); in ip6mr_rules_exit()
280 fib_rules_unregister(net->ipv6.mr6_rules_ops); in ip6mr_rules_exit()
296 return fib_rule_matchall(rule) && rule->action == FR_ACT_TO_TBL && in ip6mr_rule_default()
297 rule->table == RT6_TABLE_DFLT && !rule->l3mdev; in ip6mr_rule_default()
302 for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
308 return net->ipv6.mrt6; in ip6mr_mr_table_iter()
314 return net->ipv6.mrt6; in ip6mr_get_table()
322 *mrt = net->ipv6.mrt6; in ip6mr_fib_lookup()
333 net->ipv6.mrt6 = mrt; in ip6mr_rules_init()
340 ip6mr_free_table(net->ipv6.mrt6); in ip6mr_rules_exit()
341 net->ipv6.mrt6 = NULL; in ip6mr_rules_exit()
359 const struct mfc6_cache_cmp_arg *cmparg = arg->key; in ip6mr_hash_cmp()
362 return !ipv6_addr_equal(&c->mf6c_mcastgrp, &cmparg->mf6c_mcastgrp) || in ip6mr_hash_cmp()
363 !ipv6_addr_equal(&c->mf6c_origin, &cmparg->mf6c_origin); in ip6mr_hash_cmp()
379 list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables); in ip6mr_new_table_set()
407 struct net *net = read_pnet(&mrt->net); in ip6mr_free_table()
411 timer_shutdown_sync(&mrt->ipmr_expire_timer); in ip6mr_free_table()
414 rhltable_destroy(&mrt->mfc_hash); in ip6mr_free_table()
426 struct mr_vif_iter *iter = seq->private; in ip6mr_vif_seq_start()
434 return ERR_PTR(-ENOENT); in ip6mr_vif_seq_start()
437 iter->mrt = mrt; in ip6mr_vif_seq_start()
450 struct mr_vif_iter *iter = seq->private; in ip6mr_vif_seq_show()
451 struct mr_table *mrt = iter->mrt; in ip6mr_vif_seq_show()
462 name = vif_dev ? vif_dev->name : "none"; in ip6mr_vif_seq_show()
465 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n", in ip6mr_vif_seq_show()
466 vif - mrt->vif_table, in ip6mr_vif_seq_show()
467 name, vif->bytes_in, vif->pkt_in, in ip6mr_vif_seq_show()
468 vif->bytes_out, vif->pkt_out, in ip6mr_vif_seq_show()
469 vif->flags); in ip6mr_vif_seq_show()
488 return ERR_PTR(-ENOENT); in ipmr_mfc_seq_start()
504 const struct mr_mfc_iter *it = seq->private; in ipmr_mfc_seq_show()
505 struct mr_table *mrt = it->mrt; in ipmr_mfc_seq_show()
507 seq_printf(seq, "%pI6 %pI6 %-3hd", in ipmr_mfc_seq_show()
508 &mfc->mf6c_mcastgrp, &mfc->mf6c_origin, in ipmr_mfc_seq_show()
509 mfc->_c.mfc_parent); in ipmr_mfc_seq_show()
511 if (it->cache != &mrt->mfc_unres_queue) { in ipmr_mfc_seq_show()
513 atomic_long_read(&mfc->_c.mfc_un.res.pkt), in ipmr_mfc_seq_show()
514 atomic_long_read(&mfc->_c.mfc_un.res.bytes), in ipmr_mfc_seq_show()
515 atomic_long_read(&mfc->_c.mfc_un.res.wrong_if)); in ipmr_mfc_seq_show()
516 for (n = mfc->_c.mfc_un.res.minvif; in ipmr_mfc_seq_show()
517 n < mfc->_c.mfc_un.res.maxvif; n++) { in ipmr_mfc_seq_show()
519 mfc->_c.mfc_un.res.ttls[n] < 255) in ipmr_mfc_seq_show()
521 " %2d:%-3d", n, in ipmr_mfc_seq_show()
522 mfc->_c.mfc_un.res.ttls[n]); in ipmr_mfc_seq_show()
550 struct net *net = dev_net(skb->dev); in pim6_rcv()
553 .flowi6_iif = skb->dev->ifindex, in pim6_rcv()
554 .flowi6_mark = skb->mark, in pim6_rcv()
562 if (pim->type != ((PIM_VERSION << 4) | PIM_TYPE_REGISTER) || in pim6_rcv()
563 (pim->flags & PIM_NULL_REGISTER) || in pim6_rcv()
564 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, in pim6_rcv()
567 csum_fold(skb_checksum(skb, 0, skb->len, 0)))) in pim6_rcv()
574 if (!ipv6_addr_is_multicast(&encap->daddr) || in pim6_rcv()
575 encap->payload_len == 0 || in pim6_rcv()
576 ntohs(encap->payload_len) + sizeof(*pim) > skb->len) in pim6_rcv()
583 reg_vif_num = READ_ONCE(mrt->mroute_reg_vif_num); in pim6_rcv()
585 reg_dev = vif_dev_read(&mrt->vif_table[reg_vif_num]); in pim6_rcv()
590 skb->mac_header = skb->network_header; in pim6_rcv()
591 skb_pull(skb, (u8 *)encap - skb->data); in pim6_rcv()
593 skb->protocol = htons(ETH_P_IPV6); in pim6_rcv()
594 skb->ip_summed = CHECKSUM_NONE; in pim6_rcv()
613 struct net_device *dev) in reg_vif_xmit() argument
615 struct net *net = dev_net(dev); in reg_vif_xmit()
618 .flowi6_oif = dev->ifindex, in reg_vif_xmit()
619 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX, in reg_vif_xmit()
620 .flowi6_mark = skb->mark, in reg_vif_xmit()
629 DEV_STATS_ADD(dev, tx_bytes, skb->len); in reg_vif_xmit()
630 DEV_STATS_INC(dev, tx_packets); in reg_vif_xmit()
632 ip6mr_cache_report(mrt, skb, READ_ONCE(mrt->mroute_reg_vif_num), in reg_vif_xmit()
639 DEV_STATS_INC(dev, tx_errors); in reg_vif_xmit()
644 static int reg_vif_get_iflink(const struct net_device *dev) in reg_vif_get_iflink() argument
654 static void reg_vif_setup(struct net_device *dev) in reg_vif_setup() argument
656 dev->type = ARPHRD_PIMREG; in reg_vif_setup()
657 dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8; in reg_vif_setup()
658 dev->flags = IFF_NOARP; in reg_vif_setup()
659 dev->netdev_ops = &reg_vif_netdev_ops; in reg_vif_setup()
660 dev->needs_free_netdev = true; in reg_vif_setup()
661 dev->netns_immutable = true; in reg_vif_setup()
666 struct net_device *dev; in ip6mr_reg_vif() local
669 if (mrt->id == RT6_TABLE_DFLT) in ip6mr_reg_vif()
672 sprintf(name, "pim6reg%u", mrt->id); in ip6mr_reg_vif()
674 dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup); in ip6mr_reg_vif()
675 if (!dev) in ip6mr_reg_vif()
678 dev_net_set(dev, net); in ip6mr_reg_vif()
680 if (register_netdevice(dev)) { in ip6mr_reg_vif()
681 free_netdev(dev); in ip6mr_reg_vif()
685 if (dev_open(dev, NULL)) in ip6mr_reg_vif()
688 dev_hold(dev); in ip6mr_reg_vif()
689 return dev; in ip6mr_reg_vif()
692 unregister_netdevice(dev); in ip6mr_reg_vif()
705 &net->ipv6.ipmr_seq); in call_ip6mr_vif_entry_notifiers()
713 &mfc->_c, tb_id, &net->ipv6.ipmr_seq); in call_ip6mr_mfc_entry_notifiers()
721 struct net_device *dev; in mif6_delete() local
724 if (vifi < 0 || vifi >= mrt->maxvif) in mif6_delete()
725 return -EADDRNOTAVAIL; in mif6_delete()
727 v = &mrt->vif_table[vifi]; in mif6_delete()
729 dev = rtnl_dereference(v->dev); in mif6_delete()
730 if (!dev) in mif6_delete()
731 return -EADDRNOTAVAIL; in mif6_delete()
733 call_ip6mr_vif_entry_notifiers(read_pnet(&mrt->net), in mif6_delete()
734 FIB_EVENT_VIF_DEL, v, dev, in mif6_delete()
735 vifi, mrt->id); in mif6_delete()
737 RCU_INIT_POINTER(v->dev, NULL); in mif6_delete()
740 if (vifi == mrt->mroute_reg_vif_num) { in mif6_delete()
742 WRITE_ONCE(mrt->mroute_reg_vif_num, -1); in mif6_delete()
746 if (vifi + 1 == mrt->maxvif) { in mif6_delete()
748 for (tmp = vifi - 1; tmp >= 0; tmp--) { in mif6_delete()
752 WRITE_ONCE(mrt->maxvif, tmp + 1); in mif6_delete()
757 dev_set_allmulti(dev, -1); in mif6_delete()
759 in6_dev = __in6_dev_get(dev); in mif6_delete()
761 atomic_dec(&in6_dev->cnf.mc_forwarding); in mif6_delete()
762 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF, in mif6_delete()
764 dev->ifindex, &in6_dev->cnf); in mif6_delete()
767 if ((v->flags & MIFF_REGISTER) && !notify) in mif6_delete()
768 unregister_netdevice_queue(dev, head); in mif6_delete()
770 netdev_put(dev, &v->dev_tracker); in mif6_delete()
783 call_rcu(&c->_c.rcu, ip6mr_cache_free_rcu); in ip6mr_cache_free()
792 struct net *net = read_pnet(&mrt->net); in ip6mr_destroy_unres()
795 atomic_dec(&mrt->cache_resolve_queue_len); in ip6mr_destroy_unres()
797 while ((skb = skb_dequeue(&c->_c.mfc_un.unres.unresolved)) != NULL) { in ip6mr_destroy_unres()
798 if (ipv6_hdr(skb)->version == 0) { in ip6mr_destroy_unres()
801 nlh->nlmsg_type = NLMSG_ERROR; in ip6mr_destroy_unres()
802 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr)); in ip6mr_destroy_unres()
803 skb_trim(skb, nlh->nlmsg_len); in ip6mr_destroy_unres()
804 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -ETIMEDOUT; in ip6mr_destroy_unres()
822 list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) { in ipmr_do_expire_process()
823 if (time_after(c->mfc_un.unres.expires, now)) { in ipmr_do_expire_process()
825 unsigned long interval = c->mfc_un.unres.expires - now; in ipmr_do_expire_process()
831 list_del(&c->list); in ipmr_do_expire_process()
836 if (!list_empty(&mrt->mfc_unres_queue)) in ipmr_do_expire_process()
837 mod_timer(&mrt->ipmr_expire_timer, jiffies + expires); in ipmr_do_expire_process()
845 mod_timer(&mrt->ipmr_expire_timer, jiffies + 1); in ipmr_expire_process()
849 if (!list_empty(&mrt->mfc_unres_queue)) in ipmr_expire_process()
863 cache->mfc_un.res.minvif = MAXMIFS; in ip6mr_update_thresholds()
864 cache->mfc_un.res.maxvif = 0; in ip6mr_update_thresholds()
865 memset(cache->mfc_un.res.ttls, 255, MAXMIFS); in ip6mr_update_thresholds()
867 for (vifi = 0; vifi < mrt->maxvif; vifi++) { in ip6mr_update_thresholds()
870 cache->mfc_un.res.ttls[vifi] = ttls[vifi]; in ip6mr_update_thresholds()
871 if (cache->mfc_un.res.minvif > vifi) in ip6mr_update_thresholds()
872 cache->mfc_un.res.minvif = vifi; in ip6mr_update_thresholds()
873 if (cache->mfc_un.res.maxvif <= vifi) in ip6mr_update_thresholds()
874 cache->mfc_un.res.maxvif = vifi + 1; in ip6mr_update_thresholds()
877 WRITE_ONCE(cache->mfc_un.res.lastuse, jiffies); in ip6mr_update_thresholds()
883 int vifi = vifc->mif6c_mifi; in mif6_add()
884 struct vif_device *v = &mrt->vif_table[vifi]; in mif6_add()
885 struct net_device *dev; in mif6_add() local
891 return -EADDRINUSE; in mif6_add()
893 switch (vifc->mif6c_flags) { in mif6_add()
900 if (mrt->mroute_reg_vif_num >= 0) in mif6_add()
901 return -EADDRINUSE; in mif6_add()
902 dev = ip6mr_reg_vif(net, mrt); in mif6_add()
903 if (!dev) in mif6_add()
904 return -ENOBUFS; in mif6_add()
905 err = dev_set_allmulti(dev, 1); in mif6_add()
907 unregister_netdevice(dev); in mif6_add()
908 dev_put(dev); in mif6_add()
914 dev = dev_get_by_index(net, vifc->mif6c_pifi); in mif6_add()
915 if (!dev) in mif6_add()
916 return -EADDRNOTAVAIL; in mif6_add()
917 err = dev_set_allmulti(dev, 1); in mif6_add()
919 dev_put(dev); in mif6_add()
924 return -EINVAL; in mif6_add()
927 in6_dev = __in6_dev_get(dev); in mif6_add()
929 atomic_inc(&in6_dev->cnf.mc_forwarding); in mif6_add()
930 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF, in mif6_add()
932 dev->ifindex, &in6_dev->cnf); in mif6_add()
936 vif_device_init(v, dev, vifc->vifc_rate_limit, vifc->vifc_threshold, in mif6_add()
937 vifc->mif6c_flags | (!mrtsock ? VIFF_STATIC : 0), in mif6_add()
942 rcu_assign_pointer(v->dev, dev); in mif6_add()
943 netdev_tracker_alloc(dev, &v->dev_tracker, GFP_ATOMIC); in mif6_add()
945 if (v->flags & MIFF_REGISTER) in mif6_add()
946 WRITE_ONCE(mrt->mroute_reg_vif_num, vifi); in mif6_add()
948 if (vifi + 1 > mrt->maxvif) in mif6_add()
949 WRITE_ONCE(mrt->maxvif, vifi + 1); in mif6_add()
952 v, dev, vifi, mrt->id); in mif6_add()
983 /* Look for a (S,G,iif) entry if parent != -1 */
1004 c->_c.mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1; in ip6mr_cache_alloc()
1005 c->_c.mfc_un.res.minvif = MAXMIFS; in ip6mr_cache_alloc()
1006 c->_c.free = ip6mr_cache_free_rcu; in ip6mr_cache_alloc()
1007 refcount_set(&c->_c.mfc_un.res.refcount, 1); in ip6mr_cache_alloc()
1016 skb_queue_head_init(&c->_c.mfc_un.unres.unresolved); in ip6mr_cache_alloc_unres()
1017 c->_c.mfc_un.unres.expires = jiffies + 10 * HZ; in ip6mr_cache_alloc_unres()
1034 while ((skb = __skb_dequeue(&uc->_c.mfc_un.unres.unresolved))) { in ip6mr_cache_resolve()
1035 if (ipv6_hdr(skb)->version == 0) { in ip6mr_cache_resolve()
1039 if (mr_fill_mroute(mrt, skb, &c->_c, in ip6mr_cache_resolve()
1041 nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh; in ip6mr_cache_resolve()
1043 nlh->nlmsg_type = NLMSG_ERROR; in ip6mr_cache_resolve()
1044 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr)); in ip6mr_cache_resolve()
1045 skb_trim(skb, nlh->nlmsg_len); in ip6mr_cache_resolve()
1046 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE; in ip6mr_cache_resolve()
1051 ip6_mr_forward(net, mrt, skb->dev, skb, c); in ip6mr_cache_resolve()
1073 skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt) in ip6mr_cache_report()
1080 return -ENOBUFS; in ip6mr_cache_report()
1085 skb->ip_summed = CHECKSUM_UNNECESSARY; in ip6mr_cache_report()
1091 And all this only to mangle msg->im6_msgtype and in ip6mr_cache_report()
1092 to set msg->im6_mbz to "mbz" :-) in ip6mr_cache_report()
1099 msg->im6_mbz = 0; in ip6mr_cache_report()
1100 msg->im6_msgtype = assert; in ip6mr_cache_report()
1102 msg->im6_mif = mifi; in ip6mr_cache_report()
1104 msg->im6_mif = READ_ONCE(mrt->mroute_reg_vif_num); in ip6mr_cache_report()
1105 msg->im6_pad = 0; in ip6mr_cache_report()
1106 msg->im6_src = ipv6_hdr(pkt)->saddr; in ip6mr_cache_report()
1107 msg->im6_dst = ipv6_hdr(pkt)->daddr; in ip6mr_cache_report()
1109 skb->ip_summed = CHECKSUM_UNNECESSARY; in ip6mr_cache_report()
1128 msg->im6_mbz = 0; in ip6mr_cache_report()
1129 msg->im6_msgtype = assert; in ip6mr_cache_report()
1130 msg->im6_mif = mifi; in ip6mr_cache_report()
1131 msg->im6_pad = 0; in ip6mr_cache_report()
1132 msg->im6_src = ipv6_hdr(pkt)->saddr; in ip6mr_cache_report()
1133 msg->im6_dst = ipv6_hdr(pkt)->daddr; in ip6mr_cache_report()
1136 skb->ip_summed = CHECKSUM_UNNECESSARY; in ip6mr_cache_report()
1139 mroute6_sk = rcu_dereference(mrt->mroute_sk); in ip6mr_cache_report()
1142 return -EINVAL; in ip6mr_cache_report()
1160 struct sk_buff *skb, struct net_device *dev) in ip6mr_cache_unresolved() argument
1167 list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) { in ip6mr_cache_unresolved()
1168 if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) && in ip6mr_cache_unresolved()
1169 ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) { in ip6mr_cache_unresolved()
1185 return -ENOBUFS; in ip6mr_cache_unresolved()
1189 c->_c.mfc_parent = -1; in ip6mr_cache_unresolved()
1190 c->mf6c_origin = ipv6_hdr(skb)->saddr; in ip6mr_cache_unresolved()
1191 c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr; in ip6mr_cache_unresolved()
1199 out - Brad Parker in ip6mr_cache_unresolved()
1208 atomic_inc(&mrt->cache_resolve_queue_len); in ip6mr_cache_unresolved()
1209 list_add(&c->_c.list, &mrt->mfc_unres_queue); in ip6mr_cache_unresolved()
1216 if (c->_c.mfc_un.unres.unresolved.qlen > 3) { in ip6mr_cache_unresolved()
1218 err = -ENOBUFS; in ip6mr_cache_unresolved()
1220 if (dev) { in ip6mr_cache_unresolved()
1221 skb->dev = dev; in ip6mr_cache_unresolved()
1222 skb->skb_iif = dev->ifindex; in ip6mr_cache_unresolved()
1224 skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb); in ip6mr_cache_unresolved()
1243 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr, in ip6mr_mfc_delete()
1244 &mfc->mf6cc_mcastgrp.sin6_addr, parent); in ip6mr_mfc_delete()
1247 return -ENOENT; in ip6mr_mfc_delete()
1248 rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params); in ip6mr_mfc_delete()
1249 list_del_rcu(&c->_c.list); in ip6mr_mfc_delete()
1251 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net), in ip6mr_mfc_delete()
1252 FIB_EVENT_ENTRY_DEL, c, mrt->id); in ip6mr_mfc_delete()
1254 mr_cache_put(&c->_c); in ip6mr_mfc_delete()
1261 struct net_device *dev = netdev_notifier_info_to_dev(ptr); in ip6mr_device_event() local
1262 struct net *net = dev_net(dev); in ip6mr_device_event()
1271 v = &mrt->vif_table[0]; in ip6mr_device_event()
1272 for (ct = 0; ct < mrt->maxvif; ct++, v++) { in ip6mr_device_event()
1273 if (rcu_access_pointer(v->dev) == dev) in ip6mr_device_event()
1283 return READ_ONCE(net->ipv6.ipmr_seq) + ip6mr_rules_seq_read(net); in ip6mr_seq_read()
1308 net->ipv6.ipmr_seq = 0; in ip6mr_notifier_init()
1314 net->ipv6.ip6mr_notifier_ops = ops; in ip6mr_notifier_init()
1321 fib_notifier_ops_unregister(net->ipv6.ip6mr_notifier_ops); in ip6mr_notifier_exit()
1322 net->ipv6.ip6mr_notifier_ops = NULL; in ip6mr_notifier_exit()
1339 err = -ENOMEM; in ip6mr_net_init()
1340 if (!proc_create_net("ip6_mr_vif", 0, net->proc_net, &ip6mr_vif_seq_ops, in ip6mr_net_init()
1343 if (!proc_create_net("ip6_mr_cache", 0, net->proc_net, &ipmr_mfc_seq_ops, in ip6mr_net_init()
1352 remove_proc_entry("ip6_mr_vif", net->proc_net); in ip6mr_net_init()
1366 remove_proc_entry("ip6_mr_cache", net->proc_net); in ip6mr_net_exit()
1367 remove_proc_entry("ip6_mr_vif", net->proc_net); in ip6mr_net_exit()
1400 return -ENOMEM; in ip6_mr_init()
1412 err = -EAGAIN; in ip6_mr_init()
1452 if (mfc->mf6cc_parent >= MAXMIFS) in ip6mr_mfc_add()
1453 return -ENFILE; in ip6mr_mfc_add()
1457 if (IF_ISSET(i, &mfc->mf6cc_ifset)) in ip6mr_mfc_add()
1463 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr, in ip6mr_mfc_add()
1464 &mfc->mf6cc_mcastgrp.sin6_addr, parent); in ip6mr_mfc_add()
1468 c->_c.mfc_parent = mfc->mf6cc_parent; in ip6mr_mfc_add()
1469 ip6mr_update_thresholds(mrt, &c->_c, ttls); in ip6mr_mfc_add()
1471 c->_c.mfc_flags |= MFC_STATIC; in ip6mr_mfc_add()
1474 c, mrt->id); in ip6mr_mfc_add()
1479 if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) && in ip6mr_mfc_add()
1480 !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr)) in ip6mr_mfc_add()
1481 return -EINVAL; in ip6mr_mfc_add()
1485 return -ENOMEM; in ip6mr_mfc_add()
1487 c->mf6c_origin = mfc->mf6cc_origin.sin6_addr; in ip6mr_mfc_add()
1488 c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr; in ip6mr_mfc_add()
1489 c->_c.mfc_parent = mfc->mf6cc_parent; in ip6mr_mfc_add()
1490 ip6mr_update_thresholds(mrt, &c->_c, ttls); in ip6mr_mfc_add()
1492 c->_c.mfc_flags |= MFC_STATIC; in ip6mr_mfc_add()
1494 err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode, in ip6mr_mfc_add()
1501 list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list); in ip6mr_mfc_add()
1508 list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) { in ip6mr_mfc_add()
1510 if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) && in ip6mr_mfc_add()
1511 ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) { in ip6mr_mfc_add()
1512 list_del(&_uc->list); in ip6mr_mfc_add()
1513 atomic_dec(&mrt->cache_resolve_queue_len); in ip6mr_mfc_add()
1518 if (list_empty(&mrt->mfc_unres_queue)) in ip6mr_mfc_add()
1519 timer_delete(&mrt->ipmr_expire_timer); in ip6mr_mfc_add()
1527 c, mrt->id); in ip6mr_mfc_add()
1542 /* Shut down all active vif entries */ in mroute_clean_tables()
1544 for (i = 0; i < mrt->maxvif; i++) { in mroute_clean_tables()
1545 if (((mrt->vif_table[i].flags & VIFF_STATIC) && in mroute_clean_tables()
1547 (!(mrt->vif_table[i].flags & VIFF_STATIC) && !(flags & MRT6_FLUSH_MIFS))) in mroute_clean_tables()
1556 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) { in mroute_clean_tables()
1557 if (((c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC_STATIC)) || in mroute_clean_tables()
1558 (!(c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC))) in mroute_clean_tables()
1560 rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params); in mroute_clean_tables()
1561 list_del_rcu(&c->list); in mroute_clean_tables()
1562 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net), in mroute_clean_tables()
1564 (struct mfc6_cache *)c, mrt->id); in mroute_clean_tables()
1571 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) { in mroute_clean_tables()
1573 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) { in mroute_clean_tables()
1574 list_del(&c->list); in mroute_clean_tables()
1591 if (rtnl_dereference(mrt->mroute_sk)) { in ip6mr_sk_init()
1592 err = -EADDRINUSE; in ip6mr_sk_init()
1594 rcu_assign_pointer(mrt->mroute_sk, sk); in ip6mr_sk_init()
1596 atomic_inc(&net->ipv6.devconf_all->mc_forwarding); in ip6mr_sk_init()
1604 net->ipv6.devconf_all); in ip6mr_sk_init()
1615 int err = -EACCES; in ip6mr_sk_done()
1617 if (sk->sk_type != SOCK_RAW || in ip6mr_sk_done()
1618 inet_sk(sk)->inet_num != IPPROTO_ICMPV6) in ip6mr_sk_done()
1621 devconf = net->ipv6.devconf_all; in ip6mr_sk_done()
1622 if (!devconf || !atomic_read(&devconf->mc_forwarding)) in ip6mr_sk_done()
1627 if (sk == rtnl_dereference(mrt->mroute_sk)) { in ip6mr_sk_done()
1629 RCU_INIT_POINTER(mrt->mroute_sk, NULL); in ip6mr_sk_done()
1634 atomic_dec(&devconf->mc_forwarding); in ip6mr_sk_done()
1639 net->ipv6.devconf_all); in ip6mr_sk_done()
1655 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX, in mroute6_is_socket()
1656 .flowi6_oif = skb->dev->ifindex, in mroute6_is_socket()
1657 .flowi6_mark = skb->mark, in mroute6_is_socket()
1663 return rcu_access_pointer(mrt->mroute_sk); in mroute6_is_socket()
1684 if (sk->sk_type != SOCK_RAW || in ip6_mroute_setsockopt()
1685 inet_sk(sk)->inet_num != IPPROTO_ICMPV6) in ip6_mroute_setsockopt()
1686 return -EOPNOTSUPP; in ip6_mroute_setsockopt()
1688 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); in ip6_mroute_setsockopt()
1690 return -ENOENT; in ip6_mroute_setsockopt()
1693 if (sk != rcu_access_pointer(mrt->mroute_sk) && in ip6_mroute_setsockopt()
1694 !ns_capable(net->user_ns, CAP_NET_ADMIN)) in ip6_mroute_setsockopt()
1695 return -EACCES; in ip6_mroute_setsockopt()
1701 return -EINVAL; in ip6_mroute_setsockopt()
1710 return -EINVAL; in ip6_mroute_setsockopt()
1712 return -EFAULT; in ip6_mroute_setsockopt()
1714 return -ENFILE; in ip6_mroute_setsockopt()
1717 sk == rtnl_dereference(mrt->mroute_sk)); in ip6_mroute_setsockopt()
1723 return -EINVAL; in ip6_mroute_setsockopt()
1725 return -EFAULT; in ip6_mroute_setsockopt()
1737 parent = -1; in ip6_mroute_setsockopt()
1742 return -EINVAL; in ip6_mroute_setsockopt()
1744 return -EFAULT; in ip6_mroute_setsockopt()
1753 rtnl_dereference(mrt->mroute_sk), in ip6_mroute_setsockopt()
1763 return -EINVAL; in ip6_mroute_setsockopt()
1765 return -EFAULT; in ip6_mroute_setsockopt()
1780 return -EINVAL; in ip6_mroute_setsockopt()
1782 return -EFAULT; in ip6_mroute_setsockopt()
1783 mrt->mroute_do_assert = v; in ip6_mroute_setsockopt()
1794 return -EINVAL; in ip6_mroute_setsockopt()
1796 return -EFAULT; in ip6_mroute_setsockopt()
1802 if (v != mrt->mroute_do_pim) { in ip6_mroute_setsockopt()
1803 mrt->mroute_do_pim = v; in ip6_mroute_setsockopt()
1804 mrt->mroute_do_assert = v; in ip6_mroute_setsockopt()
1805 mrt->mroute_do_wrvifwhole = do_wrmifwhole; in ip6_mroute_setsockopt()
1818 return -EINVAL; in ip6_mroute_setsockopt()
1820 return -EFAULT; in ip6_mroute_setsockopt()
1823 return -EINVAL; in ip6_mroute_setsockopt()
1824 if (sk == rcu_access_pointer(mrt->mroute_sk)) in ip6_mroute_setsockopt()
1825 return -EBUSY; in ip6_mroute_setsockopt()
1833 raw6_sk(sk)->ip6mr_table = v; in ip6_mroute_setsockopt()
1843 return -ENOPROTOOPT; in ip6_mroute_setsockopt()
1859 if (sk->sk_type != SOCK_RAW || in ip6_mroute_getsockopt()
1860 inet_sk(sk)->inet_num != IPPROTO_ICMPV6) in ip6_mroute_getsockopt()
1861 return -EOPNOTSUPP; in ip6_mroute_getsockopt()
1863 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); in ip6_mroute_getsockopt()
1865 return -ENOENT; in ip6_mroute_getsockopt()
1873 val = mrt->mroute_do_pim; in ip6_mroute_getsockopt()
1877 val = mrt->mroute_do_assert; in ip6_mroute_getsockopt()
1880 return -ENOPROTOOPT; in ip6_mroute_getsockopt()
1884 return -EFAULT; in ip6_mroute_getsockopt()
1888 return -EINVAL; in ip6_mroute_getsockopt()
1891 return -EFAULT; in ip6_mroute_getsockopt()
1893 return -EFAULT; in ip6_mroute_getsockopt()
1909 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); in ip6mr_ioctl()
1911 return -ENOENT; in ip6mr_ioctl()
1916 if (vr->mifi >= mrt->maxvif) in ip6mr_ioctl()
1917 return -EINVAL; in ip6mr_ioctl()
1918 vr->mifi = array_index_nospec(vr->mifi, mrt->maxvif); in ip6mr_ioctl()
1920 vif = &mrt->vif_table[vr->mifi]; in ip6mr_ioctl()
1921 if (VIF_EXISTS(mrt, vr->mifi)) { in ip6mr_ioctl()
1922 vr->icount = READ_ONCE(vif->pkt_in); in ip6mr_ioctl()
1923 vr->ocount = READ_ONCE(vif->pkt_out); in ip6mr_ioctl()
1924 vr->ibytes = READ_ONCE(vif->bytes_in); in ip6mr_ioctl()
1925 vr->obytes = READ_ONCE(vif->bytes_out); in ip6mr_ioctl()
1930 return -EADDRNOTAVAIL; in ip6mr_ioctl()
1935 c = ip6mr_cache_find(mrt, &sr->src.sin6_addr, in ip6mr_ioctl()
1936 &sr->grp.sin6_addr); in ip6mr_ioctl()
1938 sr->pktcnt = atomic_long_read(&c->_c.mfc_un.res.pkt); in ip6mr_ioctl()
1939 sr->bytecnt = atomic_long_read(&c->_c.mfc_un.res.bytes); in ip6mr_ioctl()
1940 sr->wrong_if = atomic_long_read(&c->_c.mfc_un.res.wrong_if); in ip6mr_ioctl()
1945 return -EADDRNOTAVAIL; in ip6mr_ioctl()
1947 return -ENOIOCTLCMD; in ip6mr_ioctl()
1954 struct sockaddr_in6 grp; member
1977 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); in ip6mr_compat_ioctl()
1979 return -ENOENT; in ip6mr_compat_ioctl()
1984 return -EFAULT; in ip6mr_compat_ioctl()
1985 if (vr.mifi >= mrt->maxvif) in ip6mr_compat_ioctl()
1986 return -EINVAL; in ip6mr_compat_ioctl()
1987 vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif); in ip6mr_compat_ioctl()
1989 vif = &mrt->vif_table[vr.mifi]; in ip6mr_compat_ioctl()
1991 vr.icount = READ_ONCE(vif->pkt_in); in ip6mr_compat_ioctl()
1992 vr.ocount = READ_ONCE(vif->pkt_out); in ip6mr_compat_ioctl()
1993 vr.ibytes = READ_ONCE(vif->bytes_in); in ip6mr_compat_ioctl()
1994 vr.obytes = READ_ONCE(vif->bytes_out); in ip6mr_compat_ioctl()
1998 return -EFAULT; in ip6mr_compat_ioctl()
2002 return -EADDRNOTAVAIL; in ip6mr_compat_ioctl()
2005 return -EFAULT; in ip6mr_compat_ioctl()
2008 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr); in ip6mr_compat_ioctl()
2010 sr.pktcnt = atomic_long_read(&c->_c.mfc_un.res.pkt); in ip6mr_compat_ioctl()
2011 sr.bytecnt = atomic_long_read(&c->_c.mfc_un.res.bytes); in ip6mr_compat_ioctl()
2012 sr.wrong_if = atomic_long_read(&c->_c.mfc_un.res.wrong_if); in ip6mr_compat_ioctl()
2016 return -EFAULT; in ip6mr_compat_ioctl()
2020 return -EADDRNOTAVAIL; in ip6mr_compat_ioctl()
2022 return -ENOIOCTLCMD; in ip6mr_compat_ioctl()
2041 struct vif_device *vif = &mrt->vif_table[vifi]; in ip6mr_prepare_xmit()
2049 return -1; in ip6mr_prepare_xmit()
2052 if (vif->flags & MIFF_REGISTER) { in ip6mr_prepare_xmit()
2053 WRITE_ONCE(vif->pkt_out, vif->pkt_out + 1); in ip6mr_prepare_xmit()
2054 WRITE_ONCE(vif->bytes_out, vif->bytes_out + skb->len); in ip6mr_prepare_xmit()
2055 DEV_STATS_ADD(vif_dev, tx_bytes, skb->len); in ip6mr_prepare_xmit()
2058 return -1; in ip6mr_prepare_xmit()
2065 .flowi6_oif = vif->link, in ip6mr_prepare_xmit()
2066 .daddr = ipv6h->daddr, in ip6mr_prepare_xmit()
2070 if (dst->error) { in ip6mr_prepare_xmit()
2072 return -1; in ip6mr_prepare_xmit()
2086 * not mrouter) cannot join to more than one interface - it will in ip6mr_prepare_xmit()
2089 skb->dev = vif_dev; in ip6mr_prepare_xmit()
2090 WRITE_ONCE(vif->pkt_out, vif->pkt_out + 1); in ip6mr_prepare_xmit()
2091 WRITE_ONCE(vif->bytes_out, vif->bytes_out + skb->len); in ip6mr_prepare_xmit()
2096 return -1; in ip6mr_prepare_xmit()
2099 ipv6h->hop_limit--; in ip6mr_prepare_xmit()
2106 struct net_device *indev = skb->dev; in ip6mr_forward2()
2111 IP6CB(skb)->flags |= IP6SKB_FORWARDED; in ip6mr_forward2()
2114 net, NULL, skb, indev, skb->dev, in ip6mr_forward2()
2136 static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev) in ip6mr_find_vif() argument
2141 for (ct = READ_ONCE(mrt->maxvif) - 1; ct >= 0; ct--) { in ip6mr_find_vif()
2142 if (rcu_access_pointer(mrt->vif_table[ct].dev) == dev) in ip6mr_find_vif()
2150 struct net_device *dev, struct sk_buff *skb, in ip6_mr_forward() argument
2153 int psend = -1; in ip6_mr_forward()
2155 int true_vifi = ip6mr_find_vif(mrt, dev); in ip6_mr_forward()
2157 vif = c->_c.mfc_parent; in ip6_mr_forward()
2158 atomic_long_inc(&c->_c.mfc_un.res.pkt); in ip6_mr_forward()
2159 atomic_long_add(skb->len, &c->_c.mfc_un.res.bytes); in ip6_mr_forward()
2160 WRITE_ONCE(c->_c.mfc_un.res.lastuse, jiffies); in ip6_mr_forward()
2162 if (ipv6_addr_any(&c->mf6c_origin) && true_vifi >= 0) { in ip6_mr_forward()
2170 cache_proxy->_c.mfc_un.res.ttls[true_vifi] < 255) in ip6_mr_forward()
2177 if (rcu_access_pointer(mrt->vif_table[vif].dev) != dev) { in ip6_mr_forward()
2178 atomic_long_inc(&c->_c.mfc_un.res.wrong_if); in ip6_mr_forward()
2180 if (true_vifi >= 0 && mrt->mroute_do_assert && in ip6_mr_forward()
2184 large chunk of pimd to kernel. Ough... --ANK in ip6_mr_forward()
2186 (mrt->mroute_do_pim || in ip6_mr_forward()
2187 c->_c.mfc_un.res.ttls[true_vifi] < 255) && in ip6_mr_forward()
2189 c->_c.mfc_un.res.last_assert + in ip6_mr_forward()
2191 c->_c.mfc_un.res.last_assert = jiffies; in ip6_mr_forward()
2193 if (mrt->mroute_do_wrvifwhole) in ip6_mr_forward()
2201 WRITE_ONCE(mrt->vif_table[vif].pkt_in, in ip6_mr_forward()
2202 mrt->vif_table[vif].pkt_in + 1); in ip6_mr_forward()
2203 WRITE_ONCE(mrt->vif_table[vif].bytes_in, in ip6_mr_forward()
2204 mrt->vif_table[vif].bytes_in + skb->len); in ip6_mr_forward()
2209 if (ipv6_addr_any(&c->mf6c_origin) && in ip6_mr_forward()
2210 ipv6_addr_any(&c->mf6c_mcastgrp)) { in ip6_mr_forward()
2212 true_vifi != c->_c.mfc_parent && in ip6_mr_forward()
2213 ipv6_hdr(skb)->hop_limit > in ip6_mr_forward()
2214 c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) { in ip6_mr_forward()
2219 psend = c->_c.mfc_parent; in ip6_mr_forward()
2224 for (ct = c->_c.mfc_un.res.maxvif - 1; in ip6_mr_forward()
2225 ct >= c->_c.mfc_un.res.minvif; ct--) { in ip6_mr_forward()
2227 if ((!ipv6_addr_any(&c->mf6c_origin) || ct != true_vifi) && in ip6_mr_forward()
2228 ipv6_hdr(skb)->hop_limit > c->_c.mfc_un.res.ttls[ct]) { in ip6_mr_forward()
2229 if (psend != -1) { in ip6_mr_forward()
2238 if (psend != -1) { in ip6_mr_forward()
2249 struct net_device *dev, struct sk_buff *skb, in ip6_mr_output_finish() argument
2252 int psend = -1; in ip6_mr_output_finish()
2257 atomic_long_inc(&c->_c.mfc_un.res.pkt); in ip6_mr_output_finish()
2258 atomic_long_add(skb->len, &c->_c.mfc_un.res.bytes); in ip6_mr_output_finish()
2259 WRITE_ONCE(c->_c.mfc_un.res.lastuse, jiffies); in ip6_mr_output_finish()
2262 if (ipv6_addr_any(&c->mf6c_origin) && in ip6_mr_output_finish()
2263 ipv6_addr_any(&c->mf6c_mcastgrp)) { in ip6_mr_output_finish()
2264 if (ipv6_hdr(skb)->hop_limit > in ip6_mr_output_finish()
2265 c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) { in ip6_mr_output_finish()
2270 psend = c->_c.mfc_parent; in ip6_mr_output_finish()
2275 for (ct = c->_c.mfc_un.res.maxvif - 1; in ip6_mr_output_finish()
2276 ct >= c->_c.mfc_un.res.minvif; ct--) { in ip6_mr_output_finish()
2277 if (ipv6_hdr(skb)->hop_limit > c->_c.mfc_un.res.ttls[ct]) { in ip6_mr_output_finish()
2278 if (psend != -1) { in ip6_mr_output_finish()
2289 if (psend != -1) { in ip6_mr_output_finish()
2304 struct net_device *dev = skb->dev; in ip6_mr_input() local
2305 struct net *net = dev_net_rcu(dev); in ip6_mr_input()
2309 .flowi6_iif = dev->ifindex, in ip6_mr_input()
2310 .flowi6_mark = skb->mark, in ip6_mr_input()
2314 /* skb->dev passed in is the master dev for vrfs. in ip6_mr_input()
2317 if (netif_is_l3_master(dev)) { in ip6_mr_input()
2318 dev = dev_get_by_index_rcu(net, IPCB(skb)->iif); in ip6_mr_input()
2319 if (!dev) { in ip6_mr_input()
2321 return -ENODEV; in ip6_mr_input()
2332 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); in ip6_mr_input()
2334 int vif = ip6mr_find_vif(mrt, dev); in ip6_mr_input()
2338 &ipv6_hdr(skb)->daddr, in ip6_mr_input()
2348 vif = ip6mr_find_vif(mrt, dev); in ip6_mr_input()
2350 int err = ip6mr_cache_unresolved(mrt, vif, skb, dev); in ip6_mr_input()
2355 return -ENODEV; in ip6_mr_input()
2358 ip6_mr_forward(net, mrt, dev, skb, cache); in ip6_mr_input()
2365 struct net_device *dev = skb_dst(skb)->dev; in ip6_mr_output() local
2368 .flowi6_mark = skb->mark, in ip6_mr_output()
2377 if (IP6CB(skb)->flags & IP6SKB_FORWARDED) in ip6_mr_output()
2379 if (!(IP6CB(skb)->flags & IP6SKB_MCROUTE)) in ip6_mr_output()
2389 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); in ip6_mr_output()
2391 vif = ip6mr_find_vif(mrt, dev); in ip6_mr_output()
2394 &ipv6_hdr(skb)->daddr, in ip6_mr_output()
2400 vif = ip6mr_find_vif(mrt, dev); in ip6_mr_output()
2402 return ip6mr_cache_unresolved(mrt, vif, skb, dev); in ip6_mr_output()
2407 vif = cache->_c.mfc_parent; in ip6_mr_output()
2408 if (rcu_access_pointer(mrt->vif_table[vif].dev) != dev) in ip6_mr_output()
2411 ip6_mr_output_finish(net, mrt, dev, skb, cache); in ip6_mr_output()
2430 return -ENOENT; in ip6mr_get_route()
2433 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr); in ip6mr_get_route()
2434 if (!cache && skb->dev) { in ip6mr_get_route()
2435 int vif = ip6mr_find_vif(mrt, skb->dev); in ip6mr_get_route()
2438 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr, in ip6mr_get_route()
2445 struct net_device *dev; in ip6mr_get_route() local
2448 dev = skb->dev; in ip6mr_get_route()
2449 if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) { in ip6mr_get_route()
2451 return -ENODEV; in ip6mr_get_route()
2458 return -ENOMEM; in ip6mr_get_route()
2468 iph->version = 0; in ip6mr_get_route()
2469 iph->priority = 0; in ip6mr_get_route()
2470 iph->flow_lbl[0] = 0; in ip6mr_get_route()
2471 iph->flow_lbl[1] = 0; in ip6mr_get_route()
2472 iph->flow_lbl[2] = 0; in ip6mr_get_route()
2473 iph->payload_len = 0; in ip6mr_get_route()
2474 iph->nexthdr = IPPROTO_NONE; in ip6mr_get_route()
2475 iph->hop_limit = 0; in ip6mr_get_route()
2476 iph->saddr = rt->rt6i_src.addr; in ip6mr_get_route()
2477 iph->daddr = rt->rt6i_dst.addr; in ip6mr_get_route()
2479 err = ip6mr_cache_unresolved(mrt, vif, skb2, dev); in ip6mr_get_route()
2485 err = mr_fill_mroute(mrt, skb, &cache->_c, rtm); in ip6mr_get_route()
2500 return -EMSGSIZE; in ip6mr_fill_mroute()
2503 rtm->rtm_family = RTNL_FAMILY_IP6MR; in ip6mr_fill_mroute()
2504 rtm->rtm_dst_len = 128; in ip6mr_fill_mroute()
2505 rtm->rtm_src_len = 128; in ip6mr_fill_mroute()
2506 rtm->rtm_tos = 0; in ip6mr_fill_mroute()
2507 rtm->rtm_table = mrt->id; in ip6mr_fill_mroute()
2508 if (nla_put_u32(skb, RTA_TABLE, mrt->id)) in ip6mr_fill_mroute()
2510 rtm->rtm_type = RTN_MULTICAST; in ip6mr_fill_mroute()
2511 rtm->rtm_scope = RT_SCOPE_UNIVERSE; in ip6mr_fill_mroute()
2512 if (c->_c.mfc_flags & MFC_STATIC) in ip6mr_fill_mroute()
2513 rtm->rtm_protocol = RTPROT_STATIC; in ip6mr_fill_mroute()
2515 rtm->rtm_protocol = RTPROT_MROUTED; in ip6mr_fill_mroute()
2516 rtm->rtm_flags = 0; in ip6mr_fill_mroute()
2518 if (nla_put_in6_addr(skb, RTA_SRC, &c->mf6c_origin) || in ip6mr_fill_mroute()
2519 nla_put_in6_addr(skb, RTA_DST, &c->mf6c_mcastgrp)) in ip6mr_fill_mroute()
2521 err = mr_fill_mroute(mrt, skb, &c->_c, rtm); in ip6mr_fill_mroute()
2523 if (err < 0 && err != -ENOENT) in ip6mr_fill_mroute()
2531 return -EMSGSIZE; in ip6mr_fill_mroute()
2566 struct net *net = read_pnet(&mrt->net); in mr6_netlink_event()
2568 int err = -ENOBUFS; in mr6_netlink_event()
2570 skb = nlmsg_new(mr6_msgsize(mfc->_c.mfc_parent >= MAXMIFS, mrt->maxvif), in mr6_netlink_event()
2606 struct net *net = read_pnet(&mrt->net); in mrt6msg_netlink_event()
2614 payloadlen = pkt->len - sizeof(struct mrt6msg); in mrt6msg_netlink_event()
2626 rtgenm->rtgen_family = RTNL_FAMILY_IP6MR; in mrt6msg_netlink_event()
2627 if (nla_put_u8(skb, IP6MRA_CREPORT_MSGTYPE, msg->im6_msgtype) || in mrt6msg_netlink_event()
2628 nla_put_u32(skb, IP6MRA_CREPORT_MIF_ID, msg->im6_mif) || in mrt6msg_netlink_event()
2630 &msg->im6_src) || in mrt6msg_netlink_event()
2632 &msg->im6_dst)) in mrt6msg_netlink_event()
2649 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE_R, -ENOBUFS); in mrt6msg_netlink_event()
2672 if ((rtm->rtm_src_len && rtm->rtm_src_len != 128) || in ip6mr_rtm_valid_getroute_req()
2673 (rtm->rtm_dst_len && rtm->rtm_dst_len != 128) || in ip6mr_rtm_valid_getroute_req()
2674 rtm->rtm_tos || rtm->rtm_table || rtm->rtm_protocol || in ip6mr_rtm_valid_getroute_req()
2675 rtm->rtm_scope || rtm->rtm_type || rtm->rtm_flags) { in ip6mr_rtm_valid_getroute_req()
2678 return -EINVAL; in ip6mr_rtm_valid_getroute_req()
2681 if ((tb[RTA_SRC] && !rtm->rtm_src_len) || in ip6mr_rtm_valid_getroute_req()
2682 (tb[RTA_DST] && !rtm->rtm_dst_len)) { in ip6mr_rtm_valid_getroute_req()
2684 return -EINVAL; in ip6mr_rtm_valid_getroute_req()
2693 struct net *net = sock_net(in_skb->sk); in ip6mr_rtm_getroute()
2694 struct in6_addr src = {}, grp = {}; in ip6mr_rtm_getroute() local
2709 grp = nla_get_in6_addr(tb[RTA_DST]); in ip6mr_rtm_getroute()
2715 return -ENOENT; in ip6mr_rtm_getroute()
2720 cache = ip6mr_cache_find(mrt, &src, &grp); in ip6mr_rtm_getroute()
2724 return -ENOENT; in ip6mr_rtm_getroute()
2727 skb = nlmsg_new(mr6_msgsize(false, mrt->maxvif), GFP_KERNEL); in ip6mr_rtm_getroute()
2729 return -ENOBUFS; in ip6mr_rtm_getroute()
2732 nlh->nlmsg_seq, cache, RTM_NEWROUTE, 0); in ip6mr_rtm_getroute()
2743 const struct nlmsghdr *nlh = cb->nlh; in ip6mr_rtm_dumproute()
2749 if (cb->strict_check) { in ip6mr_rtm_dumproute()
2750 err = ip_valid_fib_dump_req(sock_net(skb->sk), nlh, in ip6mr_rtm_dumproute()
2759 mrt = __ip6mr_get_table(sock_net(skb->sk), filter.table_id); in ip6mr_rtm_dumproute()
2761 if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IP6MR) in ip6mr_rtm_dumproute()
2762 return skb->len; in ip6mr_rtm_dumproute()
2764 NL_SET_ERR_MSG_MOD(cb->extack, "MR table does not exist"); in ip6mr_rtm_dumproute()
2765 return -ENOENT; in ip6mr_rtm_dumproute()
2769 return skb->len ? : err; in ip6mr_rtm_dumproute()