rtnetlink.c (d2e381c4963663bca6f30c3b996fa4dbafe8fcb5) | rtnetlink.c (8c713dc93ca9a423d6af8849c9254742a1070c37) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * INET An implementation of the TCP/IP protocol suite for the LINUX 4 * operating system. INET is implemented using the BSD Socket 5 * interface as the means of communication with the user level. 6 * 7 * Routing netlink socket interface: protocol independent part. 8 * 9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 10 * 11 * Fixes: | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * INET An implementation of the TCP/IP protocol suite for the LINUX 4 * operating system. INET is implemented using the BSD Socket 5 * interface as the means of communication with the user level. 6 * 7 * Routing netlink socket interface: protocol independent part. 8 * 9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 10 * 11 * Fixes: |
12 * Vitaly E. Lavrov RTA_OK arithmetics was wrong. | 12 * Vitaly E. Lavrov RTA_OK arithmetic was wrong. |
13 */ 14 15#include <linux/bitops.h> 16#include <linux/errno.h> 17#include <linux/module.h> 18#include <linux/types.h> 19#include <linux/socket.h> 20#include <linux/kernel.h> --- 208 unchanged lines hidden (view full) --- 229/** 230 * rtnl_register_module - Register a rtnetlink message type 231 * 232 * @owner: module registering the hook (THIS_MODULE) 233 * @protocol: Protocol family or PF_UNSPEC 234 * @msgtype: rtnetlink message type 235 * @doit: Function pointer called for each request message 236 * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message | 13 */ 14 15#include <linux/bitops.h> 16#include <linux/errno.h> 17#include <linux/module.h> 18#include <linux/types.h> 19#include <linux/socket.h> 20#include <linux/kernel.h> --- 208 unchanged lines hidden (view full) --- 229/** 230 * rtnl_register_module - Register a rtnetlink message type 231 * 232 * @owner: module registering the hook (THIS_MODULE) 233 * @protocol: Protocol family or PF_UNSPEC 234 * @msgtype: rtnetlink message type 235 * @doit: Function pointer called for each request message 236 * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message |
237 * @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions | 237 * @flags: rtnl_link_flags to modify behaviour of doit/dumpit functions |
238 * 239 * Like rtnl_register, but for use by removable modules. 240 */ 241int rtnl_register_module(struct module *owner, 242 int protocol, int msgtype, 243 rtnl_doit_func doit, rtnl_dumpit_func dumpit, 244 unsigned int flags) 245{ 246 return rtnl_register_internal(owner, protocol, msgtype, 247 doit, dumpit, flags); 248} 249EXPORT_SYMBOL_GPL(rtnl_register_module); 250 251/** 252 * rtnl_register - Register a rtnetlink message type 253 * @protocol: Protocol family or PF_UNSPEC 254 * @msgtype: rtnetlink message type 255 * @doit: Function pointer called for each request message 256 * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message | 238 * 239 * Like rtnl_register, but for use by removable modules. 240 */ 241int rtnl_register_module(struct module *owner, 242 int protocol, int msgtype, 243 rtnl_doit_func doit, rtnl_dumpit_func dumpit, 244 unsigned int flags) 245{ 246 return rtnl_register_internal(owner, protocol, msgtype, 247 doit, dumpit, flags); 248} 249EXPORT_SYMBOL_GPL(rtnl_register_module); 250 251/** 252 * rtnl_register - Register a rtnetlink message type 253 * @protocol: Protocol family or PF_UNSPEC 254 * @msgtype: rtnetlink message type 255 * @doit: Function pointer called for each request message 256 * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message |
257 * @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions | 257 * @flags: rtnl_link_flags to modify behaviour of doit/dumpit functions |
258 * 259 * Registers the specified function pointers (at least one of them has 260 * to be non-NULL) to be called whenever a request message for the 261 * specified protocol family and message type is received. 262 * 263 * The special protocol family PF_UNSPEC may be used to define fallback 264 * function pointers for the case when no entry for the specific protocol 265 * family exists. --- 105 unchanged lines hidden (view full) --- 371 * 372 * Returns 0 on success or a negative error code. 373 */ 374int __rtnl_link_register(struct rtnl_link_ops *ops) 375{ 376 if (rtnl_link_ops_get(ops->kind)) 377 return -EEXIST; 378 | 258 * 259 * Registers the specified function pointers (at least one of them has 260 * to be non-NULL) to be called whenever a request message for the 261 * specified protocol family and message type is received. 262 * 263 * The special protocol family PF_UNSPEC may be used to define fallback 264 * function pointers for the case when no entry for the specific protocol 265 * family exists. --- 105 unchanged lines hidden (view full) --- 371 * 372 * Returns 0 on success or a negative error code. 373 */ 374int __rtnl_link_register(struct rtnl_link_ops *ops) 375{ 376 if (rtnl_link_ops_get(ops->kind)) 377 return -EEXIST; 378 |
379 /* The check for setup is here because if ops | 379 /* The check for alloc/setup is here because if ops |
380 * does not have that filled up, it is not possible 381 * to use the ops for creating device. So do not 382 * fill up dellink as well. That disables rtnl_dellink. 383 */ | 380 * does not have that filled up, it is not possible 381 * to use the ops for creating device. So do not 382 * fill up dellink as well. That disables rtnl_dellink. 383 */ |
384 if (ops->setup && !ops->dellink) | 384 if ((ops->alloc || ops->setup) && !ops->dellink) |
385 ops->dellink = unregister_netdevice_queue; 386 387 list_add_tail(&ops->list, &link_ops); 388 return 0; 389} 390EXPORT_SYMBOL_GPL(__rtnl_link_register); 391 392/** --- 145 unchanged lines hidden (view full) --- 538} 539 540static LIST_HEAD(rtnl_af_ops); 541 542static const struct rtnl_af_ops *rtnl_af_lookup(const int family) 543{ 544 const struct rtnl_af_ops *ops; 545 | 385 ops->dellink = unregister_netdevice_queue; 386 387 list_add_tail(&ops->list, &link_ops); 388 return 0; 389} 390EXPORT_SYMBOL_GPL(__rtnl_link_register); 391 392/** --- 145 unchanged lines hidden (view full) --- 538} 539 540static LIST_HEAD(rtnl_af_ops); 541 542static const struct rtnl_af_ops *rtnl_af_lookup(const int family) 543{ 544 const struct rtnl_af_ops *ops; 545 |
546 list_for_each_entry_rcu(ops, &rtnl_af_ops, list) { | 546 ASSERT_RTNL(); 547 548 list_for_each_entry(ops, &rtnl_af_ops, list) { |
547 if (ops->family == family) 548 return ops; 549 } 550 551 return NULL; 552} 553 554/** --- 1714 unchanged lines hidden (view full) --- 2269 2270 if (tb[IFLA_AF_SPEC]) { 2271 struct nlattr *af; 2272 int rem, err; 2273 2274 nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { 2275 const struct rtnl_af_ops *af_ops; 2276 | 549 if (ops->family == family) 550 return ops; 551 } 552 553 return NULL; 554} 555 556/** --- 1714 unchanged lines hidden (view full) --- 2271 2272 if (tb[IFLA_AF_SPEC]) { 2273 struct nlattr *af; 2274 int rem, err; 2275 2276 nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { 2277 const struct rtnl_af_ops *af_ops; 2278 |
2277 rcu_read_lock(); | |
2278 af_ops = rtnl_af_lookup(nla_type(af)); | 2279 af_ops = rtnl_af_lookup(nla_type(af)); |
2279 if (!af_ops) { 2280 rcu_read_unlock(); | 2280 if (!af_ops) |
2281 return -EAFNOSUPPORT; | 2281 return -EAFNOSUPPORT; |
2282 } | |
2283 | 2282 |
2284 if (!af_ops->set_link_af) { 2285 rcu_read_unlock(); | 2283 if (!af_ops->set_link_af) |
2286 return -EOPNOTSUPP; | 2284 return -EOPNOTSUPP; |
2287 } | |
2288 2289 if (af_ops->validate_link_af) { 2290 err = af_ops->validate_link_af(dev, af); | 2285 2286 if (af_ops->validate_link_af) { 2287 err = af_ops->validate_link_af(dev, af); |
2291 if (err < 0) { 2292 rcu_read_unlock(); | 2288 if (err < 0) |
2293 return err; | 2289 return err; |
2294 } | |
2295 } | 2290 } |
2296 2297 rcu_read_unlock(); | |
2298 } 2299 } 2300 2301 return 0; 2302} 2303 2304static int handle_infiniband_guid(struct net_device *dev, struct ifla_vf_guid *ivt, 2305 int guid_type) --- 263 unchanged lines hidden (view full) --- 2569 mask = nla_get_u32(pdreason[IFLA_PROTO_DOWN_REASON_MASK]); 2570 2571 dev_change_proto_down_reason(dev, mask, value); 2572 } 2573 2574 if (nl_proto_down) { 2575 proto_down = nla_get_u8(nl_proto_down); 2576 | 2291 } 2292 } 2293 2294 return 0; 2295} 2296 2297static int handle_infiniband_guid(struct net_device *dev, struct ifla_vf_guid *ivt, 2298 int guid_type) --- 263 unchanged lines hidden (view full) --- 2562 mask = nla_get_u32(pdreason[IFLA_PROTO_DOWN_REASON_MASK]); 2563 2564 dev_change_proto_down_reason(dev, mask, value); 2565 } 2566 2567 if (nl_proto_down) { 2568 proto_down = nla_get_u8(nl_proto_down); 2569 |
2577 /* Dont turn off protodown if there are active reasons */ | 2570 /* Don't turn off protodown if there are active reasons */ |
2578 if (!proto_down && dev->proto_down_reason) { 2579 NL_SET_ERR_MSG(extack, "Cannot clear protodown, active reasons"); 2580 return -EBUSY; 2581 } 2582 err = dev_change_proto_down(dev, 2583 proto_down); 2584 if (err) 2585 return err; --- 277 unchanged lines hidden (view full) --- 2863 2864 if (tb[IFLA_AF_SPEC]) { 2865 struct nlattr *af; 2866 int rem; 2867 2868 nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { 2869 const struct rtnl_af_ops *af_ops; 2870 | 2571 if (!proto_down && dev->proto_down_reason) { 2572 NL_SET_ERR_MSG(extack, "Cannot clear protodown, active reasons"); 2573 return -EBUSY; 2574 } 2575 err = dev_change_proto_down(dev, 2576 proto_down); 2577 if (err) 2578 return err; --- 277 unchanged lines hidden (view full) --- 2856 2857 if (tb[IFLA_AF_SPEC]) { 2858 struct nlattr *af; 2859 int rem; 2860 2861 nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { 2862 const struct rtnl_af_ops *af_ops; 2863 |
2871 rcu_read_lock(); 2872 | |
2873 BUG_ON(!(af_ops = rtnl_af_lookup(nla_type(af)))); 2874 2875 err = af_ops->set_link_af(dev, af, extack); | 2864 BUG_ON(!(af_ops = rtnl_af_lookup(nla_type(af)))); 2865 2866 err = af_ops->set_link_af(dev, af, extack); |
2876 if (err < 0) { 2877 rcu_read_unlock(); | 2867 if (err < 0) |
2878 goto errout; | 2868 goto errout; |
2879 } | |
2880 | 2869 |
2881 rcu_read_unlock(); | |
2882 status |= DO_SETLINK_NOTIFY; 2883 } 2884 } 2885 err = 0; 2886 2887 if (tb[IFLA_PROTO_DOWN] || tb[IFLA_PROTO_DOWN_REASON]) { 2888 err = do_set_proto_down(dev, tb[IFLA_PROTO_DOWN], 2889 tb[IFLA_PROTO_DOWN_REASON], extack); --- 282 unchanged lines hidden (view full) --- 3172 return ERR_PTR(-EINVAL); 3173 } 3174 3175 if (num_rx_queues < 1 || num_rx_queues > 4096) { 3176 NL_SET_ERR_MSG(extack, "Invalid number of receive queues"); 3177 return ERR_PTR(-EINVAL); 3178 } 3179 | 2870 status |= DO_SETLINK_NOTIFY; 2871 } 2872 } 2873 err = 0; 2874 2875 if (tb[IFLA_PROTO_DOWN] || tb[IFLA_PROTO_DOWN_REASON]) { 2876 err = do_set_proto_down(dev, tb[IFLA_PROTO_DOWN], 2877 tb[IFLA_PROTO_DOWN_REASON], extack); --- 282 unchanged lines hidden (view full) --- 3160 return ERR_PTR(-EINVAL); 3161 } 3162 3163 if (num_rx_queues < 1 || num_rx_queues > 4096) { 3164 NL_SET_ERR_MSG(extack, "Invalid number of receive queues"); 3165 return ERR_PTR(-EINVAL); 3166 } 3167 |
3180 dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type, 3181 ops->setup, num_tx_queues, num_rx_queues); | 3168 if (ops->alloc) { 3169 dev = ops->alloc(tb, ifname, name_assign_type, 3170 num_tx_queues, num_rx_queues); 3171 if (IS_ERR(dev)) 3172 return dev; 3173 } else { 3174 dev = alloc_netdev_mqs(ops->priv_size, ifname, 3175 name_assign_type, ops->setup, 3176 num_tx_queues, num_rx_queues); 3177 } 3178 |
3182 if (!dev) 3183 return ERR_PTR(-ENOMEM); 3184 3185 dev_net_set(dev, net); 3186 dev->rtnl_link_ops = ops; 3187 dev->rtnl_link_state = RTNL_LINK_INITIALIZING; 3188 3189 if (tb[IFLA_MTU]) { --- 216 unchanged lines hidden (view full) --- 3406 if (ops) 3407 goto replay; 3408 } 3409#endif 3410 NL_SET_ERR_MSG(extack, "Unknown device type"); 3411 return -EOPNOTSUPP; 3412 } 3413 | 3179 if (!dev) 3180 return ERR_PTR(-ENOMEM); 3181 3182 dev_net_set(dev, net); 3183 dev->rtnl_link_ops = ops; 3184 dev->rtnl_link_state = RTNL_LINK_INITIALIZING; 3185 3186 if (tb[IFLA_MTU]) { --- 216 unchanged lines hidden (view full) --- 3403 if (ops) 3404 goto replay; 3405 } 3406#endif 3407 NL_SET_ERR_MSG(extack, "Unknown device type"); 3408 return -EOPNOTSUPP; 3409 } 3410 |
3414 if (!ops->setup) | 3411 if (!ops->alloc && !ops->setup) |
3415 return -EOPNOTSUPP; 3416 3417 if (!ifname[0]) { 3418 snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); 3419 name_assign_type = NET_NAME_ENUM; 3420 } 3421 3422 dest_net = rtnl_link_get_net_capable(skb, net, tb, CAP_NET_ADMIN); --- 1414 unchanged lines hidden (view full) --- 4837 err = -ENOMEM; 4838 goto errout; 4839 } 4840 4841 err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0); 4842 if (err < 0) 4843 goto errout; 4844 | 3412 return -EOPNOTSUPP; 3413 3414 if (!ifname[0]) { 3415 snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); 3416 name_assign_type = NET_NAME_ENUM; 3417 } 3418 3419 dest_net = rtnl_link_get_net_capable(skb, net, tb, CAP_NET_ADMIN); --- 1414 unchanged lines hidden (view full) --- 4834 err = -ENOMEM; 4835 goto errout; 4836 } 4837 4838 err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0); 4839 if (err < 0) 4840 goto errout; 4841 |
4845 /* Notification info is only filled for bridge ports, not the bridge 4846 * device itself. Therefore, a zero notification length is valid and 4847 * should not result in an error. 4848 */ 4849 if (!skb->len) | 4842 if (!skb->len) { 4843 err = -EINVAL; |
4850 goto errout; | 4844 goto errout; |
4845 } |
|
4851 4852 rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); 4853 return 0; 4854errout: 4855 WARN_ON(err == -EMSGSIZE); 4856 kfree_skb(skb); 4857 if (err) 4858 rtnl_set_sk_err(net, RTNLGRP_LINK, err); --- 832 unchanged lines hidden --- | 4846 4847 rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); 4848 return 0; 4849errout: 4850 WARN_ON(err == -EMSGSIZE); 4851 kfree_skb(skb); 4852 if (err) 4853 rtnl_set_sk_err(net, RTNLGRP_LINK, err); --- 832 unchanged lines hidden --- |