rtnetlink.c (2f7043a37708110aa98262b91702da6bc32e17b6) | rtnetlink.c (d0225784be6c9bdfb05149ebc30bf9fc1fdbce3a) |
---|---|
1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * Routing netlink socket interface: protocol independent part. 7 * 8 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> --- 48 unchanged lines hidden (view full) --- 57#include <net/pkt_sched.h> 58#include <net/fib_rules.h> 59#include <net/rtnetlink.h> 60#include <net/net_namespace.h> 61 62struct rtnl_link { 63 rtnl_doit_func doit; 64 rtnl_dumpit_func dumpit; | 1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * Routing netlink socket interface: protocol independent part. 7 * 8 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> --- 48 unchanged lines hidden (view full) --- 57#include <net/pkt_sched.h> 58#include <net/fib_rules.h> 59#include <net/rtnetlink.h> 60#include <net/net_namespace.h> 61 62struct rtnl_link { 63 rtnl_doit_func doit; 64 rtnl_dumpit_func dumpit; |
65 rtnl_calcit_func calcit; | 65 unsigned int flags; |
66}; 67 68static DEFINE_MUTEX(rtnl_mutex); 69 70void rtnl_lock(void) 71{ 72 mutex_lock(&rtnl_mutex); 73} --- 48 unchanged lines hidden (view full) --- 122#ifdef CONFIG_PROVE_LOCKING 123bool lockdep_rtnl_is_held(void) 124{ 125 return lockdep_is_held(&rtnl_mutex); 126} 127EXPORT_SYMBOL(lockdep_rtnl_is_held); 128#endif /* #ifdef CONFIG_PROVE_LOCKING */ 129 | 66}; 67 68static DEFINE_MUTEX(rtnl_mutex); 69 70void rtnl_lock(void) 71{ 72 mutex_lock(&rtnl_mutex); 73} --- 48 unchanged lines hidden (view full) --- 122#ifdef CONFIG_PROVE_LOCKING 123bool lockdep_rtnl_is_held(void) 124{ 125 return lockdep_is_held(&rtnl_mutex); 126} 127EXPORT_SYMBOL(lockdep_rtnl_is_held); 128#endif /* #ifdef CONFIG_PROVE_LOCKING */ 129 |
130static struct rtnl_link *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1]; | 130static struct rtnl_link __rcu *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1]; 131static refcount_t rtnl_msg_handlers_ref[RTNL_FAMILY_MAX + 1]; |
131 132static inline int rtm_msgindex(int msgtype) 133{ 134 int msgindex = msgtype - RTM_BASE; 135 136 /* 137 * msgindex < 0 implies someone tried to register a netlink 138 * control code. msgindex >= RTM_NR_MSGTYPES may indicate that 139 * the message type has not been added to linux/rtnetlink.h 140 */ 141 BUG_ON(msgindex < 0 || msgindex >= RTM_NR_MSGTYPES); 142 143 return msgindex; 144} 145 | 132 133static inline int rtm_msgindex(int msgtype) 134{ 135 int msgindex = msgtype - RTM_BASE; 136 137 /* 138 * msgindex < 0 implies someone tried to register a netlink 139 * control code. msgindex >= RTM_NR_MSGTYPES may indicate that 140 * the message type has not been added to linux/rtnetlink.h 141 */ 142 BUG_ON(msgindex < 0 || msgindex >= RTM_NR_MSGTYPES); 143 144 return msgindex; 145} 146 |
146static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex) 147{ 148 struct rtnl_link *tab; 149 150 if (protocol <= RTNL_FAMILY_MAX) 151 tab = rtnl_msg_handlers[protocol]; 152 else 153 tab = NULL; 154 155 if (tab == NULL || tab[msgindex].doit == NULL) 156 tab = rtnl_msg_handlers[PF_UNSPEC]; 157 158 return tab[msgindex].doit; 159} 160 161static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex) 162{ 163 struct rtnl_link *tab; 164 165 if (protocol <= RTNL_FAMILY_MAX) 166 tab = rtnl_msg_handlers[protocol]; 167 else 168 tab = NULL; 169 170 if (tab == NULL || tab[msgindex].dumpit == NULL) 171 tab = rtnl_msg_handlers[PF_UNSPEC]; 172 173 return tab[msgindex].dumpit; 174} 175 176static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex) 177{ 178 struct rtnl_link *tab; 179 180 if (protocol <= RTNL_FAMILY_MAX) 181 tab = rtnl_msg_handlers[protocol]; 182 else 183 tab = NULL; 184 185 if (tab == NULL || tab[msgindex].calcit == NULL) 186 tab = rtnl_msg_handlers[PF_UNSPEC]; 187 188 return tab[msgindex].calcit; 189} 190 | |
191/** 192 * __rtnl_register - Register a rtnetlink message type 193 * @protocol: Protocol family or PF_UNSPEC 194 * @msgtype: rtnetlink message type 195 * @doit: Function pointer called for each request message 196 * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message | 147/** 148 * __rtnl_register - Register a rtnetlink message type 149 * @protocol: Protocol family or PF_UNSPEC 150 * @msgtype: rtnetlink message type 151 * @doit: Function pointer called for each request message 152 * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message |
197 * @calcit: Function pointer to calc size of dump message | 153 * @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions |
198 * 199 * Registers the specified function pointers (at least one of them has 200 * to be non-NULL) to be called whenever a request message for the 201 * specified protocol family and message type is received. 202 * 203 * The special protocol family PF_UNSPEC may be used to define fallback 204 * function pointers for the case when no entry for the specific protocol 205 * family exists. 206 * 207 * Returns 0 on success or a negative error code. 208 */ 209int __rtnl_register(int protocol, int msgtype, 210 rtnl_doit_func doit, rtnl_dumpit_func dumpit, | 154 * 155 * Registers the specified function pointers (at least one of them has 156 * to be non-NULL) to be called whenever a request message for the 157 * specified protocol family and message type is received. 158 * 159 * The special protocol family PF_UNSPEC may be used to define fallback 160 * function pointers for the case when no entry for the specific protocol 161 * family exists. 162 * 163 * Returns 0 on success or a negative error code. 164 */ 165int __rtnl_register(int protocol, int msgtype, 166 rtnl_doit_func doit, rtnl_dumpit_func dumpit, |
211 rtnl_calcit_func calcit) | 167 unsigned int flags) |
212{ 213 struct rtnl_link *tab; 214 int msgindex; 215 216 BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); 217 msgindex = rtm_msgindex(msgtype); 218 | 168{ 169 struct rtnl_link *tab; 170 int msgindex; 171 172 BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); 173 msgindex = rtm_msgindex(msgtype); 174 |
219 tab = rtnl_msg_handlers[protocol]; | 175 tab = rcu_dereference_raw(rtnl_msg_handlers[protocol]); |
220 if (tab == NULL) { 221 tab = kcalloc(RTM_NR_MSGTYPES, sizeof(*tab), GFP_KERNEL); 222 if (tab == NULL) 223 return -ENOBUFS; 224 | 176 if (tab == NULL) { 177 tab = kcalloc(RTM_NR_MSGTYPES, sizeof(*tab), GFP_KERNEL); 178 if (tab == NULL) 179 return -ENOBUFS; 180 |
225 rtnl_msg_handlers[protocol] = tab; | 181 rcu_assign_pointer(rtnl_msg_handlers[protocol], tab); |
226 } 227 228 if (doit) 229 tab[msgindex].doit = doit; | 182 } 183 184 if (doit) 185 tab[msgindex].doit = doit; |
230 | |
231 if (dumpit) 232 tab[msgindex].dumpit = dumpit; | 186 if (dumpit) 187 tab[msgindex].dumpit = dumpit; |
188 tab[msgindex].flags |= flags; |
|
233 | 189 |
234 if (calcit) 235 tab[msgindex].calcit = calcit; 236 | |
237 return 0; 238} 239EXPORT_SYMBOL_GPL(__rtnl_register); 240 241/** 242 * rtnl_register - Register a rtnetlink message type 243 * 244 * Identical to __rtnl_register() but panics on failure. This is useful 245 * as failure of this function is very unlikely, it can only happen due 246 * to lack of memory when allocating the chain to store all message 247 * handlers for a protocol. Meant for use in init functions where lack 248 * of memory implies no sense in continuing. 249 */ 250void rtnl_register(int protocol, int msgtype, 251 rtnl_doit_func doit, rtnl_dumpit_func dumpit, | 190 return 0; 191} 192EXPORT_SYMBOL_GPL(__rtnl_register); 193 194/** 195 * rtnl_register - Register a rtnetlink message type 196 * 197 * Identical to __rtnl_register() but panics on failure. This is useful 198 * as failure of this function is very unlikely, it can only happen due 199 * to lack of memory when allocating the chain to store all message 200 * handlers for a protocol. Meant for use in init functions where lack 201 * of memory implies no sense in continuing. 202 */ 203void rtnl_register(int protocol, int msgtype, 204 rtnl_doit_func doit, rtnl_dumpit_func dumpit, |
252 rtnl_calcit_func calcit) | 205 unsigned int flags) |
253{ | 206{ |
254 if (__rtnl_register(protocol, msgtype, doit, dumpit, calcit) < 0) | 207 if (__rtnl_register(protocol, msgtype, doit, dumpit, flags) < 0) |
255 panic("Unable to register rtnetlink message handler, " 256 "protocol = %d, message type = %d\n", 257 protocol, msgtype); 258} 259EXPORT_SYMBOL_GPL(rtnl_register); 260 261/** 262 * rtnl_unregister - Unregister a rtnetlink message type 263 * @protocol: Protocol family or PF_UNSPEC 264 * @msgtype: rtnetlink message type 265 * 266 * Returns 0 on success or a negative error code. 267 */ 268int rtnl_unregister(int protocol, int msgtype) 269{ | 208 panic("Unable to register rtnetlink message handler, " 209 "protocol = %d, message type = %d\n", 210 protocol, msgtype); 211} 212EXPORT_SYMBOL_GPL(rtnl_register); 213 214/** 215 * rtnl_unregister - Unregister a rtnetlink message type 216 * @protocol: Protocol family or PF_UNSPEC 217 * @msgtype: rtnetlink message type 218 * 219 * Returns 0 on success or a negative error code. 220 */ 221int rtnl_unregister(int protocol, int msgtype) 222{ |
223 struct rtnl_link *handlers; |
|
270 int msgindex; 271 272 BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); 273 msgindex = rtm_msgindex(msgtype); 274 | 224 int msgindex; 225 226 BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); 227 msgindex = rtm_msgindex(msgtype); 228 |
275 if (rtnl_msg_handlers[protocol] == NULL) | 229 rtnl_lock(); 230 handlers = rtnl_dereference(rtnl_msg_handlers[protocol]); 231 if (!handlers) { 232 rtnl_unlock(); |
276 return -ENOENT; | 233 return -ENOENT; |
234 } |
|
277 | 235 |
278 rtnl_msg_handlers[protocol][msgindex].doit = NULL; 279 rtnl_msg_handlers[protocol][msgindex].dumpit = NULL; 280 rtnl_msg_handlers[protocol][msgindex].calcit = NULL; | 236 handlers[msgindex].doit = NULL; 237 handlers[msgindex].dumpit = NULL; 238 handlers[msgindex].flags = 0; 239 rtnl_unlock(); |
281 282 return 0; 283} 284EXPORT_SYMBOL_GPL(rtnl_unregister); 285 286/** 287 * rtnl_unregister_all - Unregister all rtnetlink message type of a protocol 288 * @protocol : Protocol family or PF_UNSPEC 289 * 290 * Identical to calling rtnl_unregster() for all registered message types 291 * of a certain protocol family. 292 */ 293void rtnl_unregister_all(int protocol) 294{ | 240 241 return 0; 242} 243EXPORT_SYMBOL_GPL(rtnl_unregister); 244 245/** 246 * rtnl_unregister_all - Unregister all rtnetlink message type of a protocol 247 * @protocol : Protocol family or PF_UNSPEC 248 * 249 * Identical to calling rtnl_unregster() for all registered message types 250 * of a certain protocol family. 251 */ 252void rtnl_unregister_all(int protocol) 253{ |
254 struct rtnl_link *handlers; 255 |
|
295 BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); 296 | 256 BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); 257 |
297 kfree(rtnl_msg_handlers[protocol]); 298 rtnl_msg_handlers[protocol] = NULL; | 258 rtnl_lock(); 259 handlers = rtnl_dereference(rtnl_msg_handlers[protocol]); 260 RCU_INIT_POINTER(rtnl_msg_handlers[protocol], NULL); 261 rtnl_unlock(); 262 263 synchronize_net(); 264 265 while (refcount_read(&rtnl_msg_handlers_ref[protocol]) > 1) 266 schedule(); 267 kfree(handlers); |
299} 300EXPORT_SYMBOL_GPL(rtnl_unregister_all); 301 302static LIST_HEAD(link_ops); 303 304static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) 305{ 306 const struct rtnl_link_ops *ops; --- 121 unchanged lines hidden (view full) --- 428 mutex_unlock(&net_mutex); 429} 430EXPORT_SYMBOL_GPL(rtnl_link_unregister); 431 432static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) 433{ 434 struct net_device *master_dev; 435 const struct rtnl_link_ops *ops; | 268} 269EXPORT_SYMBOL_GPL(rtnl_unregister_all); 270 271static LIST_HEAD(link_ops); 272 273static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) 274{ 275 const struct rtnl_link_ops *ops; --- 121 unchanged lines hidden (view full) --- 397 mutex_unlock(&net_mutex); 398} 399EXPORT_SYMBOL_GPL(rtnl_link_unregister); 400 401static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) 402{ 403 struct net_device *master_dev; 404 const struct rtnl_link_ops *ops; |
405 size_t size = 0; |
|
436 | 406 |
437 master_dev = netdev_master_upper_dev_get((struct net_device *) dev); | 407 rcu_read_lock(); 408 409 master_dev = netdev_master_upper_dev_get_rcu((struct net_device *)dev); |
438 if (!master_dev) | 410 if (!master_dev) |
439 return 0; | 411 goto out; 412 |
440 ops = master_dev->rtnl_link_ops; 441 if (!ops || !ops->get_slave_size) | 413 ops = master_dev->rtnl_link_ops; 414 if (!ops || !ops->get_slave_size) |
442 return 0; | 415 goto out; |
443 /* IFLA_INFO_SLAVE_DATA + nested data */ | 416 /* IFLA_INFO_SLAVE_DATA + nested data */ |
444 return nla_total_size(sizeof(struct nlattr)) + | 417 size = nla_total_size(sizeof(struct nlattr)) + |
445 ops->get_slave_size(master_dev, dev); | 418 ops->get_slave_size(master_dev, dev); |
419 420out: 421 rcu_read_unlock(); 422 return size; |
|
446} 447 448static size_t rtnl_link_get_size(const struct net_device *dev) 449{ 450 const struct rtnl_link_ops *ops = dev->rtnl_link_ops; 451 size_t size; 452 453 if (!ops) --- 1185 unchanged lines hidden (view full) --- 1639 unsigned int flags = NLM_F_MULTI; 1640 int master_idx = 0; 1641 int err; 1642 int hdrlen; 1643 1644 s_h = cb->args[0]; 1645 s_idx = cb->args[1]; 1646 | 423} 424 425static size_t rtnl_link_get_size(const struct net_device *dev) 426{ 427 const struct rtnl_link_ops *ops = dev->rtnl_link_ops; 428 size_t size; 429 430 if (!ops) --- 1185 unchanged lines hidden (view full) --- 1616 unsigned int flags = NLM_F_MULTI; 1617 int master_idx = 0; 1618 int err; 1619 int hdrlen; 1620 1621 s_h = cb->args[0]; 1622 s_idx = cb->args[1]; 1623 |
1647 cb->seq = net->dev_base_seq; 1648 | |
1649 /* A hack to preserve kernel<->userspace interface. 1650 * The correct header is ifinfomsg. It is consistent with rtnl_getlink. 1651 * However, before Linux v3.9 the code here assumed rtgenmsg and that's 1652 * what iproute2 < v3.9.0 used. 1653 * We can detect the old iproute2. Even including the IFLA_EXT_MASK 1654 * attribute, its netlink message is shorter than struct ifinfomsg. 1655 */ 1656 hdrlen = nlmsg_len(cb->nlh) < sizeof(struct ifinfomsg) ? --- 29 unchanged lines hidden (view full) --- 1686 ext_filter_mask, 0); 1687 1688 if (err < 0) { 1689 if (likely(skb->len)) 1690 goto out; 1691 1692 goto out_err; 1693 } | 1624 /* A hack to preserve kernel<->userspace interface. 1625 * The correct header is ifinfomsg. It is consistent with rtnl_getlink. 1626 * However, before Linux v3.9 the code here assumed rtgenmsg and that's 1627 * what iproute2 < v3.9.0 used. 1628 * We can detect the old iproute2. Even including the IFLA_EXT_MASK 1629 * attribute, its netlink message is shorter than struct ifinfomsg. 1630 */ 1631 hdrlen = nlmsg_len(cb->nlh) < sizeof(struct ifinfomsg) ? --- 29 unchanged lines hidden (view full) --- 1661 ext_filter_mask, 0); 1662 1663 if (err < 0) { 1664 if (likely(skb->len)) 1665 goto out; 1666 1667 goto out_err; 1668 } |
1694 1695 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | |
1696cont: 1697 idx++; 1698 } 1699 } 1700out: 1701 err = skb->len; 1702out_err: 1703 cb->args[1] = idx; 1704 cb->args[0] = h; | 1669cont: 1670 idx++; 1671 } 1672 } 1673out: 1674 err = skb->len; 1675out_err: 1676 cb->args[1] = idx; 1677 cb->args[0] = h; |
1678 cb->seq = net->dev_base_seq; 1679 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
|
1705 1706 return err; 1707} 1708 1709int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len, 1710 struct netlink_ext_ack *exterr) 1711{ 1712 return nla_parse(tb, IFLA_MAX, head, len, ifla_policy, exterr); --- 1113 unchanged lines hidden (view full) --- 2826 } 2827 2828 if (!ext_filter_mask) 2829 return NLMSG_GOODSIZE; 2830 /* 2831 * traverse the list of net devices and compute the minimum 2832 * buffer size based upon the filter mask. 2833 */ | 1680 1681 return err; 1682} 1683 1684int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len, 1685 struct netlink_ext_ack *exterr) 1686{ 1687 return nla_parse(tb, IFLA_MAX, head, len, ifla_policy, exterr); --- 1113 unchanged lines hidden (view full) --- 2801 } 2802 2803 if (!ext_filter_mask) 2804 return NLMSG_GOODSIZE; 2805 /* 2806 * traverse the list of net devices and compute the minimum 2807 * buffer size based upon the filter mask. 2808 */ |
2834 list_for_each_entry(dev, &net->dev_base_head, dev_list) { | 2809 rcu_read_lock(); 2810 for_each_netdev_rcu(net, dev) { |
2835 min_ifinfo_dump_size = max_t(u16, min_ifinfo_dump_size, 2836 if_nlmsg_size(dev, 2837 ext_filter_mask)); 2838 } | 2811 min_ifinfo_dump_size = max_t(u16, min_ifinfo_dump_size, 2812 if_nlmsg_size(dev, 2813 ext_filter_mask)); 2814 } |
2815 rcu_read_unlock(); |
|
2839 2840 return nlmsg_total_size(min_ifinfo_dump_size); 2841} 2842 2843static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) 2844{ 2845 int idx; 2846 int s_idx = cb->family; 2847 2848 if (s_idx == 0) 2849 s_idx = 1; | 2816 2817 return nlmsg_total_size(min_ifinfo_dump_size); 2818} 2819 2820static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) 2821{ 2822 int idx; 2823 int s_idx = cb->family; 2824 2825 if (s_idx == 0) 2826 s_idx = 1; |
2827 |
|
2850 for (idx = 1; idx <= RTNL_FAMILY_MAX; idx++) { 2851 int type = cb->nlh->nlmsg_type-RTM_BASE; | 2828 for (idx = 1; idx <= RTNL_FAMILY_MAX; idx++) { 2829 int type = cb->nlh->nlmsg_type-RTM_BASE; |
2830 struct rtnl_link *handlers; 2831 rtnl_dumpit_func dumpit; 2832 |
|
2852 if (idx < s_idx || idx == PF_PACKET) 2853 continue; | 2833 if (idx < s_idx || idx == PF_PACKET) 2834 continue; |
2854 if (rtnl_msg_handlers[idx] == NULL || 2855 rtnl_msg_handlers[idx][type].dumpit == NULL) | 2835 2836 handlers = rtnl_dereference(rtnl_msg_handlers[idx]); 2837 if (!handlers) |
2856 continue; | 2838 continue; |
2839 2840 dumpit = READ_ONCE(handlers[type].dumpit); 2841 if (!dumpit) 2842 continue; 2843 |
|
2857 if (idx > s_idx) { 2858 memset(&cb->args[0], 0, sizeof(cb->args)); 2859 cb->prev_seq = 0; 2860 cb->seq = 0; 2861 } | 2844 if (idx > s_idx) { 2845 memset(&cb->args[0], 0, sizeof(cb->args)); 2846 cb->prev_seq = 0; 2847 cb->seq = 0; 2848 } |
2862 if (rtnl_msg_handlers[idx][type].dumpit(skb, cb)) | 2849 if (dumpit(skb, cb)) |
2863 break; 2864 } 2865 cb->family = idx; 2866 2867 return skb->len; 2868} 2869 2870struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev, --- 1286 unchanged lines hidden (view full) --- 4157} 4158 4159/* Process one rtnetlink message. */ 4160 4161static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, 4162 struct netlink_ext_ack *extack) 4163{ 4164 struct net *net = sock_net(skb->sk); | 2850 break; 2851 } 2852 cb->family = idx; 2853 2854 return skb->len; 2855} 2856 2857struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev, --- 1286 unchanged lines hidden (view full) --- 4144} 4145 4146/* Process one rtnetlink message. */ 4147 4148static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, 4149 struct netlink_ext_ack *extack) 4150{ 4151 struct net *net = sock_net(skb->sk); |
4152 struct rtnl_link *handlers; 4153 int err = -EOPNOTSUPP; |
|
4165 rtnl_doit_func doit; | 4154 rtnl_doit_func doit; |
4155 unsigned int flags; |
|
4166 int kind; 4167 int family; 4168 int type; | 4156 int kind; 4157 int family; 4158 int type; |
4169 int err; | |
4170 4171 type = nlh->nlmsg_type; 4172 if (type > RTM_MAX) 4173 return -EOPNOTSUPP; 4174 4175 type -= RTM_BASE; 4176 4177 /* All the messages must have at least 1 byte length */ 4178 if (nlmsg_len(nlh) < sizeof(struct rtgenmsg)) 4179 return 0; 4180 4181 family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family; 4182 kind = type&3; 4183 4184 if (kind != 2 && !netlink_net_capable(skb, CAP_NET_ADMIN)) 4185 return -EPERM; 4186 | 4159 4160 type = nlh->nlmsg_type; 4161 if (type > RTM_MAX) 4162 return -EOPNOTSUPP; 4163 4164 type -= RTM_BASE; 4165 4166 /* All the messages must have at least 1 byte length */ 4167 if (nlmsg_len(nlh) < sizeof(struct rtgenmsg)) 4168 return 0; 4169 4170 family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family; 4171 kind = type&3; 4172 4173 if (kind != 2 && !netlink_net_capable(skb, CAP_NET_ADMIN)) 4174 return -EPERM; 4175 |
4176 if (family >= ARRAY_SIZE(rtnl_msg_handlers)) 4177 family = PF_UNSPEC; 4178 4179 rcu_read_lock(); 4180 handlers = rcu_dereference(rtnl_msg_handlers[family]); 4181 if (!handlers) { 4182 family = PF_UNSPEC; 4183 handlers = rcu_dereference(rtnl_msg_handlers[family]); 4184 } 4185 |
|
4187 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 4188 struct sock *rtnl; 4189 rtnl_dumpit_func dumpit; | 4186 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 4187 struct sock *rtnl; 4188 rtnl_dumpit_func dumpit; |
4190 rtnl_calcit_func calcit; | |
4191 u16 min_dump_alloc = 0; 4192 | 4189 u16 min_dump_alloc = 0; 4190 |
4193 dumpit = rtnl_get_dumpit(family, type); 4194 if (dumpit == NULL) 4195 return -EOPNOTSUPP; 4196 calcit = rtnl_get_calcit(family, type); 4197 if (calcit) 4198 min_dump_alloc = calcit(skb, nlh); | 4191 dumpit = READ_ONCE(handlers[type].dumpit); 4192 if (!dumpit) { 4193 family = PF_UNSPEC; 4194 handlers = rcu_dereference(rtnl_msg_handlers[PF_UNSPEC]); 4195 if (!handlers) 4196 goto err_unlock; |
4199 | 4197 |
4200 __rtnl_unlock(); | 4198 dumpit = READ_ONCE(handlers[type].dumpit); 4199 if (!dumpit) 4200 goto err_unlock; 4201 } 4202 4203 refcount_inc(&rtnl_msg_handlers_ref[family]); 4204 4205 if (type == RTM_GETLINK - RTM_BASE) 4206 min_dump_alloc = rtnl_calcit(skb, nlh); 4207 4208 rcu_read_unlock(); 4209 |
4201 rtnl = net->rtnl; 4202 { 4203 struct netlink_dump_control c = { 4204 .dump = dumpit, 4205 .min_dump_alloc = min_dump_alloc, 4206 }; 4207 err = netlink_dump_start(rtnl, skb, nlh, &c); 4208 } | 4210 rtnl = net->rtnl; 4211 { 4212 struct netlink_dump_control c = { 4213 .dump = dumpit, 4214 .min_dump_alloc = min_dump_alloc, 4215 }; 4216 err = netlink_dump_start(rtnl, skb, nlh, &c); 4217 } |
4209 rtnl_lock(); | 4218 refcount_dec(&rtnl_msg_handlers_ref[family]); |
4210 return err; 4211 } 4212 | 4219 return err; 4220 } 4221 |
4213 doit = rtnl_get_doit(family, type); 4214 if (doit == NULL) 4215 return -EOPNOTSUPP; | 4222 doit = READ_ONCE(handlers[type].doit); 4223 if (!doit) { 4224 family = PF_UNSPEC; 4225 handlers = rcu_dereference(rtnl_msg_handlers[family]); 4226 } |
4216 | 4227 |
4217 return doit(skb, nlh, extack); | 4228 flags = READ_ONCE(handlers[type].flags); 4229 if (flags & RTNL_FLAG_DOIT_UNLOCKED) { 4230 refcount_inc(&rtnl_msg_handlers_ref[family]); 4231 doit = READ_ONCE(handlers[type].doit); 4232 rcu_read_unlock(); 4233 if (doit) 4234 err = doit(skb, nlh, extack); 4235 refcount_dec(&rtnl_msg_handlers_ref[family]); 4236 return err; 4237 } 4238 4239 rcu_read_unlock(); 4240 4241 rtnl_lock(); 4242 handlers = rtnl_dereference(rtnl_msg_handlers[family]); 4243 if (handlers) { 4244 doit = READ_ONCE(handlers[type].doit); 4245 if (doit) 4246 err = doit(skb, nlh, extack); 4247 } 4248 rtnl_unlock(); 4249 return err; 4250 4251err_unlock: 4252 rcu_read_unlock(); 4253 return -EOPNOTSUPP; |
4218} 4219 4220static void rtnetlink_rcv(struct sk_buff *skb) 4221{ | 4254} 4255 4256static void rtnetlink_rcv(struct sk_buff *skb) 4257{ |
4222 rtnl_lock(); | |
4223 netlink_rcv_skb(skb, &rtnetlink_rcv_msg); | 4258 netlink_rcv_skb(skb, &rtnetlink_rcv_msg); |
4224 rtnl_unlock(); | |
4225} 4226 4227static int rtnetlink_bind(struct net *net, int group) 4228{ 4229 switch (group) { 4230 case RTNLGRP_IPV4_MROUTE_R: 4231 case RTNLGRP_IPV6_MROUTE_R: 4232 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) --- 56 unchanged lines hidden (view full) --- 4289 4290static struct pernet_operations rtnetlink_net_ops = { 4291 .init = rtnetlink_net_init, 4292 .exit = rtnetlink_net_exit, 4293}; 4294 4295void __init rtnetlink_init(void) 4296{ | 4259} 4260 4261static int rtnetlink_bind(struct net *net, int group) 4262{ 4263 switch (group) { 4264 case RTNLGRP_IPV4_MROUTE_R: 4265 case RTNLGRP_IPV6_MROUTE_R: 4266 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) --- 56 unchanged lines hidden (view full) --- 4323 4324static struct pernet_operations rtnetlink_net_ops = { 4325 .init = rtnetlink_net_init, 4326 .exit = rtnetlink_net_exit, 4327}; 4328 4329void __init rtnetlink_init(void) 4330{ |
4331 int i; 4332 4333 for (i = 0; i < ARRAY_SIZE(rtnl_msg_handlers_ref); i++) 4334 refcount_set(&rtnl_msg_handlers_ref[i], 1); 4335 |
|
4297 if (register_pernet_subsys(&rtnetlink_net_ops)) 4298 panic("rtnetlink_init: cannot initialize rtnetlink\n"); 4299 4300 register_netdevice_notifier(&rtnetlink_dev_notifier); 4301 4302 rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, | 4336 if (register_pernet_subsys(&rtnetlink_net_ops)) 4337 panic("rtnetlink_init: cannot initialize rtnetlink\n"); 4338 4339 register_netdevice_notifier(&rtnetlink_dev_notifier); 4340 4341 rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, |
4303 rtnl_dump_ifinfo, rtnl_calcit); 4304 rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL); 4305 rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL); 4306 rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL); | 4342 rtnl_dump_ifinfo, 0); 4343 rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, 0); 4344 rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, 0); 4345 rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, 0); |
4307 | 4346 |
4308 rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL); 4309 rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL); 4310 rtnl_register(PF_UNSPEC, RTM_GETNETCONF, NULL, rtnl_dump_all, NULL); | 4347 rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, 0); 4348 rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, 0); 4349 rtnl_register(PF_UNSPEC, RTM_GETNETCONF, NULL, rtnl_dump_all, 0); |
4311 | 4350 |
4312 rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, NULL); 4313 rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, NULL); 4314 rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, NULL); | 4351 rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, 0); 4352 rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, 0); 4353 rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, 0); |
4315 | 4354 |
4316 rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, NULL); 4317 rtnl_register(PF_BRIDGE, RTM_DELLINK, rtnl_bridge_dellink, NULL, NULL); 4318 rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, NULL); | 4355 rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, 0); 4356 rtnl_register(PF_BRIDGE, RTM_DELLINK, rtnl_bridge_dellink, NULL, 0); 4357 rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, 0); |
4319 4320 rtnl_register(PF_UNSPEC, RTM_GETSTATS, rtnl_stats_get, rtnl_stats_dump, | 4358 4359 rtnl_register(PF_UNSPEC, RTM_GETSTATS, rtnl_stats_get, rtnl_stats_dump, |
4321 NULL); | 4360 0); |
4322} | 4361} |