Blame view
net/core/rtnetlink.c
106 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. * * Routing netlink socket interface: protocol independent part. * * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Fixes: * Vitaly E. Lavrov RTA_OK arithmetics was wrong. */ |
ee5d032f7 xdp: add HW offlo... |
18 |
#include <linux/bitops.h> |
1da177e4c Linux-2.6.12-rc2 |
19 20 21 22 23 |
#include <linux/errno.h> #include <linux/module.h> #include <linux/types.h> #include <linux/socket.h> #include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
24 25 26 27 28 29 30 31 32 33 34 35 |
#include <linux/timer.h> #include <linux/string.h> #include <linux/sockios.h> #include <linux/net.h> #include <linux/fcntl.h> #include <linux/mm.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/capability.h> #include <linux/skbuff.h> #include <linux/init.h> #include <linux/security.h> |
6756ae4b4 [NET]: Convert RT... |
36 |
#include <linux/mutex.h> |
1823730fb [IPv4]: Move inte... |
37 |
#include <linux/if_addr.h> |
77162022a net: add generic ... |
38 |
#include <linux/if_bridge.h> |
f6f6424ba net: make vid as ... |
39 |
#include <linux/if_vlan.h> |
ebc08a6f4 rtnetlink: Add VF... |
40 |
#include <linux/pci.h> |
77162022a net: add generic ... |
41 |
#include <linux/etherdevice.h> |
58038695e net: Add IFLA_XDP... |
42 |
#include <linux/bpf.h> |
1da177e4c Linux-2.6.12-rc2 |
43 |
|
7c0f6ba68 Replace <asm/uacc... |
44 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
45 46 47 |
#include <linux/inet.h> #include <linux/netdevice.h> |
82f284129 rtnl: expose phys... |
48 |
#include <net/switchdev.h> |
1da177e4c Linux-2.6.12-rc2 |
49 50 51 52 53 |
#include <net/ip.h> #include <net/protocol.h> #include <net/arp.h> #include <net/route.h> #include <net/udp.h> |
ea6976399 net: tcp: add RTA... |
54 |
#include <net/tcp.h> |
1da177e4c Linux-2.6.12-rc2 |
55 56 |
#include <net/sock.h> #include <net/pkt_sched.h> |
14c0b97dd [NET]: Protocol I... |
57 |
#include <net/fib_rules.h> |
e28498638 [RTNL]: Message h... |
58 |
#include <net/rtnetlink.h> |
30ffee848 net: move and exp... |
59 |
#include <net/net_namespace.h> |
1da177e4c Linux-2.6.12-rc2 |
60 |
|
e0d087af7 rtnetlink: Cleanups |
61 |
struct rtnl_link { |
e28498638 [RTNL]: Message h... |
62 63 |
rtnl_doit_func doit; rtnl_dumpit_func dumpit; |
62256f98f rtnetlink: add RT... |
64 |
unsigned int flags; |
e28498638 [RTNL]: Message h... |
65 |
}; |
6756ae4b4 [NET]: Convert RT... |
66 |
static DEFINE_MUTEX(rtnl_mutex); |
1da177e4c Linux-2.6.12-rc2 |
67 68 69 |
void rtnl_lock(void) { |
6756ae4b4 [NET]: Convert RT... |
70 |
mutex_lock(&rtnl_mutex); |
1da177e4c Linux-2.6.12-rc2 |
71 |
} |
e0d087af7 rtnetlink: Cleanups |
72 |
EXPORT_SYMBOL(rtnl_lock); |
1da177e4c Linux-2.6.12-rc2 |
73 |
|
1b5c5493e net_sched: add th... |
74 75 76 77 78 79 80 81 82 |
static struct sk_buff *defer_kfree_skb_list; void rtnl_kfree_skbs(struct sk_buff *head, struct sk_buff *tail) { if (head && tail) { tail->next = defer_kfree_skb_list; defer_kfree_skb_list = head; } } EXPORT_SYMBOL(rtnl_kfree_skbs); |
6756ae4b4 [NET]: Convert RT... |
83 |
void __rtnl_unlock(void) |
1da177e4c Linux-2.6.12-rc2 |
84 |
{ |
1b5c5493e net_sched: add th... |
85 86 87 |
struct sk_buff *head = defer_kfree_skb_list; defer_kfree_skb_list = NULL; |
6756ae4b4 [NET]: Convert RT... |
88 |
mutex_unlock(&rtnl_mutex); |
1b5c5493e net_sched: add th... |
89 90 91 92 93 94 95 96 |
while (head) { struct sk_buff *next = head->next; kfree_skb(head); cond_resched(); head = next; } |
1da177e4c Linux-2.6.12-rc2 |
97 |
} |
6756ae4b4 [NET]: Convert RT... |
98 |
|
1da177e4c Linux-2.6.12-rc2 |
99 100 |
void rtnl_unlock(void) { |
58ec3b4db net: Fix netdev_r... |
101 |
/* This fellow will unlock it for us. */ |
1da177e4c Linux-2.6.12-rc2 |
102 103 |
netdev_run_todo(); } |
e0d087af7 rtnetlink: Cleanups |
104 |
EXPORT_SYMBOL(rtnl_unlock); |
1da177e4c Linux-2.6.12-rc2 |
105 |
|
6756ae4b4 [NET]: Convert RT... |
106 107 108 109 |
int rtnl_trylock(void) { return mutex_trylock(&rtnl_mutex); } |
e0d087af7 rtnetlink: Cleanups |
110 |
EXPORT_SYMBOL(rtnl_trylock); |
6756ae4b4 [NET]: Convert RT... |
111 |
|
c9c1014b2 [RTNETLINK]: Fix ... |
112 113 114 115 |
int rtnl_is_locked(void) { return mutex_is_locked(&rtnl_mutex); } |
e0d087af7 rtnetlink: Cleanups |
116 |
EXPORT_SYMBOL(rtnl_is_locked); |
c9c1014b2 [RTNETLINK]: Fix ... |
117 |
|
a898def29 net: Add checking... |
118 |
#ifdef CONFIG_PROVE_LOCKING |
0cbf33437 net/core: lockdep... |
119 |
bool lockdep_rtnl_is_held(void) |
a898def29 net: Add checking... |
120 121 122 123 124 |
{ return lockdep_is_held(&rtnl_mutex); } EXPORT_SYMBOL(lockdep_rtnl_is_held); #endif /* #ifdef CONFIG_PROVE_LOCKING */ |
6853dd488 rtnetlink: protec... |
125 |
static struct rtnl_link __rcu *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1]; |
019a31699 rtnetlink: add re... |
126 |
static refcount_t rtnl_msg_handlers_ref[RTNL_FAMILY_MAX + 1]; |
e28498638 [RTNL]: Message h... |
127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
static inline int rtm_msgindex(int msgtype) { int msgindex = msgtype - RTM_BASE; /* * msgindex < 0 implies someone tried to register a netlink * control code. msgindex >= RTM_NR_MSGTYPES may indicate that * the message type has not been added to linux/rtnetlink.h */ BUG_ON(msgindex < 0 || msgindex >= RTM_NR_MSGTYPES); return msgindex; } |
e28498638 [RTNL]: Message h... |
141 142 143 144 145 146 |
/** * __rtnl_register - Register a rtnetlink message type * @protocol: Protocol family or PF_UNSPEC * @msgtype: rtnetlink message type * @doit: Function pointer called for each request message * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message |
b97bac64a rtnetlink: make r... |
147 |
* @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions |
e28498638 [RTNL]: Message h... |
148 149 150 151 152 153 154 155 156 157 158 159 |
* * Registers the specified function pointers (at least one of them has * to be non-NULL) to be called whenever a request message for the * specified protocol family and message type is received. * * The special protocol family PF_UNSPEC may be used to define fallback * function pointers for the case when no entry for the specific protocol * family exists. * * Returns 0 on success or a negative error code. */ int __rtnl_register(int protocol, int msgtype, |
c7ac8679b rtnetlink: Comput... |
160 |
rtnl_doit_func doit, rtnl_dumpit_func dumpit, |
b97bac64a rtnetlink: make r... |
161 |
unsigned int flags) |
e28498638 [RTNL]: Message h... |
162 163 164 |
{ struct rtnl_link *tab; int msgindex; |
25239cee7 net: rtnetlink: d... |
165 |
BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
e28498638 [RTNL]: Message h... |
166 |
msgindex = rtm_msgindex(msgtype); |
377cb2488 rtnetlink: use rc... |
167 |
tab = rcu_dereference_raw(rtnl_msg_handlers[protocol]); |
e28498638 [RTNL]: Message h... |
168 169 170 171 |
if (tab == NULL) { tab = kcalloc(RTM_NR_MSGTYPES, sizeof(*tab), GFP_KERNEL); if (tab == NULL) return -ENOBUFS; |
6853dd488 rtnetlink: protec... |
172 |
rcu_assign_pointer(rtnl_msg_handlers[protocol], tab); |
e28498638 [RTNL]: Message h... |
173 174 175 176 |
} if (doit) tab[msgindex].doit = doit; |
e28498638 [RTNL]: Message h... |
177 178 |
if (dumpit) tab[msgindex].dumpit = dumpit; |
62256f98f rtnetlink: add RT... |
179 |
tab[msgindex].flags |= flags; |
e28498638 [RTNL]: Message h... |
180 181 182 |
return 0; } |
e28498638 [RTNL]: Message h... |
183 184 185 186 187 188 189 190 191 |
EXPORT_SYMBOL_GPL(__rtnl_register); /** * rtnl_register - Register a rtnetlink message type * * Identical to __rtnl_register() but panics on failure. This is useful * as failure of this function is very unlikely, it can only happen due * to lack of memory when allocating the chain to store all message * handlers for a protocol. Meant for use in init functions where lack |
25985edce Fix common misspe... |
192 |
* of memory implies no sense in continuing. |
e28498638 [RTNL]: Message h... |
193 194 |
*/ void rtnl_register(int protocol, int msgtype, |
c7ac8679b rtnetlink: Comput... |
195 |
rtnl_doit_func doit, rtnl_dumpit_func dumpit, |
b97bac64a rtnetlink: make r... |
196 |
unsigned int flags) |
e28498638 [RTNL]: Message h... |
197 |
{ |
b97bac64a rtnetlink: make r... |
198 |
if (__rtnl_register(protocol, msgtype, doit, dumpit, flags) < 0) |
e28498638 [RTNL]: Message h... |
199 200 201 202 203 |
panic("Unable to register rtnetlink message handler, " "protocol = %d, message type = %d ", protocol, msgtype); } |
e28498638 [RTNL]: Message h... |
204 205 206 207 208 209 210 211 212 213 214 |
EXPORT_SYMBOL_GPL(rtnl_register); /** * rtnl_unregister - Unregister a rtnetlink message type * @protocol: Protocol family or PF_UNSPEC * @msgtype: rtnetlink message type * * Returns 0 on success or a negative error code. */ int rtnl_unregister(int protocol, int msgtype) { |
6853dd488 rtnetlink: protec... |
215 |
struct rtnl_link *handlers; |
e28498638 [RTNL]: Message h... |
216 |
int msgindex; |
25239cee7 net: rtnetlink: d... |
217 |
BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
e28498638 [RTNL]: Message h... |
218 |
msgindex = rtm_msgindex(msgtype); |
6853dd488 rtnetlink: protec... |
219 220 221 222 |
rtnl_lock(); handlers = rtnl_dereference(rtnl_msg_handlers[protocol]); if (!handlers) { rtnl_unlock(); |
e28498638 [RTNL]: Message h... |
223 |
return -ENOENT; |
6853dd488 rtnetlink: protec... |
224 |
} |
e28498638 [RTNL]: Message h... |
225 |
|
6853dd488 rtnetlink: protec... |
226 227 |
handlers[msgindex].doit = NULL; handlers[msgindex].dumpit = NULL; |
62256f98f rtnetlink: add RT... |
228 |
handlers[msgindex].flags = 0; |
6853dd488 rtnetlink: protec... |
229 |
rtnl_unlock(); |
e28498638 [RTNL]: Message h... |
230 231 232 |
return 0; } |
e28498638 [RTNL]: Message h... |
233 234 235 236 237 238 239 240 241 242 243 |
EXPORT_SYMBOL_GPL(rtnl_unregister); /** * rtnl_unregister_all - Unregister all rtnetlink message type of a protocol * @protocol : Protocol family or PF_UNSPEC * * Identical to calling rtnl_unregster() for all registered message types * of a certain protocol family. */ void rtnl_unregister_all(int protocol) { |
019a31699 rtnetlink: add re... |
244 |
struct rtnl_link *handlers; |
25239cee7 net: rtnetlink: d... |
245 |
BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
e28498638 [RTNL]: Message h... |
246 |
|
019a31699 rtnetlink: add re... |
247 |
rtnl_lock(); |
6853dd488 rtnetlink: protec... |
248 249 |
handlers = rtnl_dereference(rtnl_msg_handlers[protocol]); RCU_INIT_POINTER(rtnl_msg_handlers[protocol], NULL); |
019a31699 rtnetlink: add re... |
250 |
rtnl_unlock(); |
6853dd488 rtnetlink: protec... |
251 |
synchronize_net(); |
d38a65125 rtnetlink: init h... |
252 |
while (refcount_read(&rtnl_msg_handlers_ref[protocol]) > 1) |
019a31699 rtnetlink: add re... |
253 254 |
schedule(); kfree(handlers); |
e28498638 [RTNL]: Message h... |
255 |
} |
e28498638 [RTNL]: Message h... |
256 |
EXPORT_SYMBOL_GPL(rtnl_unregister_all); |
1da177e4c Linux-2.6.12-rc2 |
257 |
|
38f7b870d [RTNETLINK]: Link... |
258 |
static LIST_HEAD(link_ops); |
c63044f0d rtnetlink: rtnl_l... |
259 260 261 262 263 264 265 266 267 268 |
static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) { const struct rtnl_link_ops *ops; list_for_each_entry(ops, &link_ops, list) { if (!strcmp(ops->kind, kind)) return ops; } return NULL; } |
38f7b870d [RTNETLINK]: Link... |
269 270 271 272 273 274 275 276 277 278 279 280 |
/** * __rtnl_link_register - Register rtnl_link_ops with rtnetlink. * @ops: struct rtnl_link_ops * to register * * The caller must hold the rtnl_mutex. This function should be used * by drivers that create devices during module initialization. It * must be called before registering the devices. * * Returns 0 on success or a negative error code. */ int __rtnl_link_register(struct rtnl_link_ops *ops) { |
c63044f0d rtnetlink: rtnl_l... |
281 282 |
if (rtnl_link_ops_get(ops->kind)) return -EEXIST; |
b0ab2fabb rtnetlink: allow ... |
283 284 285 286 287 288 |
/* The check for setup is here because if ops * does not have that filled up, it is not possible * to use the ops for creating device. So do not * fill up dellink as well. That disables rtnl_dellink. */ if (ops->setup && !ops->dellink) |
23289a37e net: add a list_h... |
289 |
ops->dellink = unregister_netdevice_queue; |
2d85cba2b [RTNETLINK]: rtnl... |
290 |
|
38f7b870d [RTNETLINK]: Link... |
291 292 293 |
list_add_tail(&ops->list, &link_ops); return 0; } |
38f7b870d [RTNETLINK]: Link... |
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
EXPORT_SYMBOL_GPL(__rtnl_link_register); /** * rtnl_link_register - Register rtnl_link_ops with rtnetlink. * @ops: struct rtnl_link_ops * to register * * Returns 0 on success or a negative error code. */ int rtnl_link_register(struct rtnl_link_ops *ops) { int err; rtnl_lock(); err = __rtnl_link_register(ops); rtnl_unlock(); return err; } |
38f7b870d [RTNETLINK]: Link... |
311 |
EXPORT_SYMBOL_GPL(rtnl_link_register); |
669f87baa [RTNL]: Introduce... |
312 313 314 |
static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) { struct net_device *dev; |
23289a37e net: add a list_h... |
315 |
LIST_HEAD(list_kill); |
669f87baa [RTNL]: Introduce... |
316 |
for_each_netdev(net, dev) { |
23289a37e net: add a list_h... |
317 318 |
if (dev->rtnl_link_ops == ops) ops->dellink(dev, &list_kill); |
669f87baa [RTNL]: Introduce... |
319 |
} |
23289a37e net: add a list_h... |
320 |
unregister_netdevice_many(&list_kill); |
669f87baa [RTNL]: Introduce... |
321 |
} |
38f7b870d [RTNETLINK]: Link... |
322 323 324 325 |
/** * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. * @ops: struct rtnl_link_ops * to unregister * |
2d85cba2b [RTNETLINK]: rtnl... |
326 |
* The caller must hold the rtnl_mutex. |
38f7b870d [RTNETLINK]: Link... |
327 328 329 |
*/ void __rtnl_link_unregister(struct rtnl_link_ops *ops) { |
881d966b4 [NET]: Make the d... |
330 |
struct net *net; |
2d85cba2b [RTNETLINK]: rtnl... |
331 |
|
881d966b4 [NET]: Make the d... |
332 |
for_each_net(net) { |
669f87baa [RTNL]: Introduce... |
333 |
__rtnl_kill_links(net, ops); |
2d85cba2b [RTNETLINK]: rtnl... |
334 |
} |
38f7b870d [RTNETLINK]: Link... |
335 336 |
list_del(&ops->list); } |
38f7b870d [RTNETLINK]: Link... |
337 |
EXPORT_SYMBOL_GPL(__rtnl_link_unregister); |
200b916f3 rtnetlink: wait f... |
338 339 340 341 342 343 344 |
/* Return with the rtnl_lock held when there are no network * devices unregistering in any network namespace. */ static void rtnl_lock_unregistering_all(void) { struct net *net; bool unregistering; |
ff960a731 netdev, sched/wai... |
345 |
DEFINE_WAIT_FUNC(wait, woken_wake_function); |
200b916f3 rtnetlink: wait f... |
346 |
|
ff960a731 netdev, sched/wai... |
347 |
add_wait_queue(&netdev_unregistering_wq, &wait); |
200b916f3 rtnetlink: wait f... |
348 |
for (;;) { |
200b916f3 rtnetlink: wait f... |
349 350 351 352 353 354 355 356 357 358 359 |
unregistering = false; rtnl_lock(); for_each_net(net) { if (net->dev_unreg_count > 0) { unregistering = true; break; } } if (!unregistering) break; __rtnl_unlock(); |
ff960a731 netdev, sched/wai... |
360 361 |
wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); |
200b916f3 rtnetlink: wait f... |
362 |
} |
ff960a731 netdev, sched/wai... |
363 |
remove_wait_queue(&netdev_unregistering_wq, &wait); |
200b916f3 rtnetlink: wait f... |
364 |
} |
38f7b870d [RTNETLINK]: Link... |
365 366 367 368 369 370 |
/** * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. * @ops: struct rtnl_link_ops * to unregister */ void rtnl_link_unregister(struct rtnl_link_ops *ops) { |
200b916f3 rtnetlink: wait f... |
371 372 373 |
/* Close the race with cleanup_net() */ mutex_lock(&net_mutex); rtnl_lock_unregistering_all(); |
38f7b870d [RTNETLINK]: Link... |
374 375 |
__rtnl_link_unregister(ops); rtnl_unlock(); |
200b916f3 rtnetlink: wait f... |
376 |
mutex_unlock(&net_mutex); |
38f7b870d [RTNETLINK]: Link... |
377 |
} |
38f7b870d [RTNETLINK]: Link... |
378 |
EXPORT_SYMBOL_GPL(rtnl_link_unregister); |
ba7d49b1f rtnetlink: provid... |
379 380 381 382 |
static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) { struct net_device *master_dev; const struct rtnl_link_ops *ops; |
8515ae384 rtnetlink: switch... |
383 |
size_t size = 0; |
ba7d49b1f rtnetlink: provid... |
384 |
|
8515ae384 rtnetlink: switch... |
385 386 387 |
rcu_read_lock(); master_dev = netdev_master_upper_dev_get_rcu((struct net_device *)dev); |
ba7d49b1f rtnetlink: provid... |
388 |
if (!master_dev) |
8515ae384 rtnetlink: switch... |
389 |
goto out; |
ba7d49b1f rtnetlink: provid... |
390 |
ops = master_dev->rtnl_link_ops; |
6049f2530 rtnetlink: fix oo... |
391 |
if (!ops || !ops->get_slave_size) |
8515ae384 rtnetlink: switch... |
392 |
goto out; |
ba7d49b1f rtnetlink: provid... |
393 |
/* IFLA_INFO_SLAVE_DATA + nested data */ |
8515ae384 rtnetlink: switch... |
394 |
size = nla_total_size(sizeof(struct nlattr)) + |
ba7d49b1f rtnetlink: provid... |
395 |
ops->get_slave_size(master_dev, dev); |
8515ae384 rtnetlink: switch... |
396 397 398 399 |
out: rcu_read_unlock(); return size; |
ba7d49b1f rtnetlink: provid... |
400 |
} |
38f7b870d [RTNETLINK]: Link... |
401 402 403 404 405 406 407 |
static size_t rtnl_link_get_size(const struct net_device *dev) { const struct rtnl_link_ops *ops = dev->rtnl_link_ops; size_t size; if (!ops) return 0; |
369cf77a6 rtnetlink: Fix me... |
408 409 |
size = nla_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */ nla_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_KIND */ |
38f7b870d [RTNETLINK]: Link... |
410 411 412 |
if (ops->get_size) /* IFLA_INFO_DATA + nested data */ |
369cf77a6 rtnetlink: Fix me... |
413 |
size += nla_total_size(sizeof(struct nlattr)) + |
38f7b870d [RTNETLINK]: Link... |
414 415 416 |
ops->get_size(dev); if (ops->get_xstats_size) |
369cf77a6 rtnetlink: Fix me... |
417 418 |
/* IFLA_INFO_XSTATS */ size += nla_total_size(ops->get_xstats_size(dev)); |
38f7b870d [RTNETLINK]: Link... |
419 |
|
ba7d49b1f rtnetlink: provid... |
420 |
size += rtnl_link_get_slave_info_data_size(dev); |
38f7b870d [RTNETLINK]: Link... |
421 422 |
return size; } |
f8ff182c7 rtnetlink: Link a... |
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
static LIST_HEAD(rtnl_af_ops); static const struct rtnl_af_ops *rtnl_af_lookup(const int family) { const struct rtnl_af_ops *ops; list_for_each_entry(ops, &rtnl_af_ops, list) { if (ops->family == family) return ops; } return NULL; } /** |
f8ff182c7 rtnetlink: Link a... |
438 439 440 441 442 |
* rtnl_af_register - Register rtnl_af_ops with rtnetlink. * @ops: struct rtnl_af_ops * to register * * Returns 0 on success or a negative error code. */ |
3678a9d86 netlink: cleanup ... |
443 |
void rtnl_af_register(struct rtnl_af_ops *ops) |
f8ff182c7 rtnetlink: Link a... |
444 |
{ |
f8ff182c7 rtnetlink: Link a... |
445 |
rtnl_lock(); |
3678a9d86 netlink: cleanup ... |
446 |
list_add_tail(&ops->list, &rtnl_af_ops); |
f8ff182c7 rtnetlink: Link a... |
447 |
rtnl_unlock(); |
f8ff182c7 rtnetlink: Link a... |
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
} EXPORT_SYMBOL_GPL(rtnl_af_register); /** * __rtnl_af_unregister - Unregister rtnl_af_ops from rtnetlink. * @ops: struct rtnl_af_ops * to unregister * * The caller must hold the rtnl_mutex. */ void __rtnl_af_unregister(struct rtnl_af_ops *ops) { list_del(&ops->list); } EXPORT_SYMBOL_GPL(__rtnl_af_unregister); /** * rtnl_af_unregister - Unregister rtnl_af_ops from rtnetlink. * @ops: struct rtnl_af_ops * to unregister */ void rtnl_af_unregister(struct rtnl_af_ops *ops) { rtnl_lock(); __rtnl_af_unregister(ops); rtnl_unlock(); } EXPORT_SYMBOL_GPL(rtnl_af_unregister); |
b1974ed05 netlink: Rightsiz... |
474 475 |
static size_t rtnl_link_get_af_size(const struct net_device *dev, u32 ext_filter_mask) |
f8ff182c7 rtnetlink: Link a... |
476 477 478 479 480 481 482 483 484 485 486 |
{ struct rtnl_af_ops *af_ops; size_t size; /* IFLA_AF_SPEC */ size = nla_total_size(sizeof(struct nlattr)); list_for_each_entry(af_ops, &rtnl_af_ops, list) { if (af_ops->get_link_af_size) { /* AF_* + nested data */ size += nla_total_size(sizeof(struct nlattr)) + |
b1974ed05 netlink: Rightsiz... |
487 |
af_ops->get_link_af_size(dev, ext_filter_mask); |
f8ff182c7 rtnetlink: Link a... |
488 489 490 491 492 |
} } return size; } |
ba7d49b1f rtnetlink: provid... |
493 |
static bool rtnl_have_link_slave_info(const struct net_device *dev) |
38f7b870d [RTNETLINK]: Link... |
494 |
{ |
ba7d49b1f rtnetlink: provid... |
495 |
struct net_device *master_dev; |
38f7b870d [RTNETLINK]: Link... |
496 |
|
ba7d49b1f rtnetlink: provid... |
497 |
master_dev = netdev_master_upper_dev_get((struct net_device *) dev); |
813f020c5 rtnetlink: remove... |
498 |
if (master_dev && master_dev->rtnl_link_ops) |
ba7d49b1f rtnetlink: provid... |
499 500 501 502 503 504 505 506 507 508 509 |
return true; return false; } static int rtnl_link_slave_info_fill(struct sk_buff *skb, const struct net_device *dev) { struct net_device *master_dev; const struct rtnl_link_ops *ops; struct nlattr *slave_data; int err; |
38f7b870d [RTNETLINK]: Link... |
510 |
|
ba7d49b1f rtnetlink: provid... |
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 |
master_dev = netdev_master_upper_dev_get((struct net_device *) dev); if (!master_dev) return 0; ops = master_dev->rtnl_link_ops; if (!ops) return 0; if (nla_put_string(skb, IFLA_INFO_SLAVE_KIND, ops->kind) < 0) return -EMSGSIZE; if (ops->fill_slave_info) { slave_data = nla_nest_start(skb, IFLA_INFO_SLAVE_DATA); if (!slave_data) return -EMSGSIZE; err = ops->fill_slave_info(skb, master_dev, dev); if (err < 0) goto err_cancel_slave_data; nla_nest_end(skb, slave_data); } return 0; err_cancel_slave_data: nla_nest_cancel(skb, slave_data); return err; } static int rtnl_link_info_fill(struct sk_buff *skb, const struct net_device *dev) { const struct rtnl_link_ops *ops = dev->rtnl_link_ops; struct nlattr *data; int err; if (!ops) return 0; |
38f7b870d [RTNETLINK]: Link... |
544 |
if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0) |
ba7d49b1f rtnetlink: provid... |
545 |
return -EMSGSIZE; |
38f7b870d [RTNETLINK]: Link... |
546 547 548 |
if (ops->fill_xstats) { err = ops->fill_xstats(skb, dev); if (err < 0) |
ba7d49b1f rtnetlink: provid... |
549 |
return err; |
38f7b870d [RTNETLINK]: Link... |
550 551 552 |
} if (ops->fill_info) { data = nla_nest_start(skb, IFLA_INFO_DATA); |
ba7d49b1f rtnetlink: provid... |
553 554 |
if (data == NULL) return -EMSGSIZE; |
38f7b870d [RTNETLINK]: Link... |
555 556 557 558 559 |
err = ops->fill_info(skb, dev); if (err < 0) goto err_cancel_data; nla_nest_end(skb, data); } |
38f7b870d [RTNETLINK]: Link... |
560 561 562 563 |
return 0; err_cancel_data: nla_nest_cancel(skb, data); |
ba7d49b1f rtnetlink: provid... |
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 |
return err; } static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev) { struct nlattr *linkinfo; int err = -EMSGSIZE; linkinfo = nla_nest_start(skb, IFLA_LINKINFO); if (linkinfo == NULL) goto out; err = rtnl_link_info_fill(skb, dev); if (err < 0) goto err_cancel_link; err = rtnl_link_slave_info_fill(skb, dev); if (err < 0) goto err_cancel_link; nla_nest_end(skb, linkinfo); return 0; |
38f7b870d [RTNETLINK]: Link... |
586 587 588 589 590 |
err_cancel_link: nla_nest_cancel(skb, linkinfo); out: return err; } |
95c961747 net: cleanup unsi... |
591 |
int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned int group, int echo) |
1da177e4c Linux-2.6.12-rc2 |
592 |
{ |
97c53cacf [NET]: Make rtnet... |
593 |
struct sock *rtnl = net->rtnl; |
1da177e4c Linux-2.6.12-rc2 |
594 |
int err = 0; |
ac6d439d2 [NETLINK]: Conver... |
595 |
NETLINK_CB(skb).dst_group = group; |
1da177e4c Linux-2.6.12-rc2 |
596 |
if (echo) |
633547973 net: convert sk_b... |
597 |
refcount_inc(&skb->users); |
1da177e4c Linux-2.6.12-rc2 |
598 599 600 601 602 |
netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL); if (echo) err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT); return err; } |
97c53cacf [NET]: Make rtnet... |
603 |
int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid) |
2942e9005 [RTNETLINK]: Use ... |
604 |
{ |
97c53cacf [NET]: Make rtnet... |
605 |
struct sock *rtnl = net->rtnl; |
2942e9005 [RTNETLINK]: Use ... |
606 607 |
return nlmsg_unicast(rtnl, skb, pid); } |
e0d087af7 rtnetlink: Cleanups |
608 |
EXPORT_SYMBOL(rtnl_unicast); |
2942e9005 [RTNETLINK]: Use ... |
609 |
|
1ce85fe40 netlink: change n... |
610 611 |
void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, struct nlmsghdr *nlh, gfp_t flags) |
97676b6b5 [RTNETLINK]: Add ... |
612 |
{ |
97c53cacf [NET]: Make rtnet... |
613 |
struct sock *rtnl = net->rtnl; |
97676b6b5 [RTNETLINK]: Add ... |
614 615 616 617 |
int report = 0; if (nlh) report = nlmsg_report(nlh); |
1ce85fe40 netlink: change n... |
618 |
nlmsg_notify(rtnl, skb, pid, group, report, flags); |
97676b6b5 [RTNETLINK]: Add ... |
619 |
} |
e0d087af7 rtnetlink: Cleanups |
620 |
EXPORT_SYMBOL(rtnl_notify); |
97676b6b5 [RTNETLINK]: Add ... |
621 |
|
97c53cacf [NET]: Make rtnet... |
622 |
void rtnl_set_sk_err(struct net *net, u32 group, int error) |
97676b6b5 [RTNETLINK]: Add ... |
623 |
{ |
97c53cacf [NET]: Make rtnet... |
624 |
struct sock *rtnl = net->rtnl; |
97676b6b5 [RTNETLINK]: Add ... |
625 626 |
netlink_set_err(rtnl, 0, group, error); } |
e0d087af7 rtnetlink: Cleanups |
627 |
EXPORT_SYMBOL(rtnl_set_sk_err); |
97676b6b5 [RTNETLINK]: Add ... |
628 |
|
1da177e4c Linux-2.6.12-rc2 |
629 630 |
int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) { |
2d7202bfd [IPv6] route: Con... |
631 632 633 634 635 636 637 638 639 |
struct nlattr *mx; int i, valid = 0; mx = nla_nest_start(skb, RTA_METRICS); if (mx == NULL) return -ENOBUFS; for (i = 0; i < RTAX_MAX; i++) { if (metrics[i]) { |
ea6976399 net: tcp: add RTA... |
640 641 642 643 644 645 646 647 |
if (i == RTAX_CC_ALGO - 1) { char tmp[TCP_CA_NAME_MAX], *name; name = tcp_ca_get_name_by_key(metrics[i], tmp); if (!name) continue; if (nla_put_string(skb, i + 1, name)) goto nla_put_failure; |
c3a8d9474 tcp: use dctcp if... |
648 649 |
} else if (i == RTAX_FEATURES - 1) { u32 user_features = metrics[i] & RTAX_FEATURE_MASK; |
f8edcd127 net: rtnetlink: D... |
650 651 |
if (!user_features) continue; |
c3a8d9474 tcp: use dctcp if... |
652 653 654 |
BUILD_BUG_ON(RTAX_FEATURE_MASK & DST_FEATURE_MASK); if (nla_put_u32(skb, i + 1, user_features)) goto nla_put_failure; |
ea6976399 net: tcp: add RTA... |
655 656 657 658 |
} else { if (nla_put_u32(skb, i + 1, metrics[i])) goto nla_put_failure; } |
2d7202bfd [IPv6] route: Con... |
659 |
valid++; |
2d7202bfd [IPv6] route: Con... |
660 |
} |
1da177e4c Linux-2.6.12-rc2 |
661 |
} |
1da177e4c Linux-2.6.12-rc2 |
662 |
|
a57d27fc7 [RTNETLINK]: Don'... |
663 664 665 666 |
if (!valid) { nla_nest_cancel(skb, mx); return 0; } |
2d7202bfd [IPv6] route: Con... |
667 668 669 670 |
return nla_nest_end(skb, mx); nla_put_failure: |
bc3ed28ca netlink: Improve ... |
671 672 |
nla_nest_cancel(skb, mx); return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
673 |
} |
e0d087af7 rtnetlink: Cleanups |
674 |
EXPORT_SYMBOL(rtnetlink_put_metrics); |
1da177e4c Linux-2.6.12-rc2 |
675 |
|
e3703b3de [RTNETLINK]: Add ... |
676 |
int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, |
87a50699c rtnetlink: Remove... |
677 |
long expires, u32 error) |
e3703b3de [RTNETLINK]: Add ... |
678 679 |
{ struct rta_cacheinfo ci = { |
a399a8053 time: jiffies_del... |
680 |
.rta_lastuse = jiffies_delta_to_clock_t(jiffies - dst->lastuse), |
e3703b3de [RTNETLINK]: Add ... |
681 682 683 684 |
.rta_used = dst->__use, .rta_clntref = atomic_read(&(dst->__refcnt)), .rta_error = error, .rta_id = id, |
e3703b3de [RTNETLINK]: Add ... |
685 |
}; |
8253947e2 ipv6: fix incorre... |
686 687 |
if (expires) { unsigned long clock; |
e3703b3de [RTNETLINK]: Add ... |
688 |
|
8253947e2 ipv6: fix incorre... |
689 690 691 692 |
clock = jiffies_to_clock_t(abs(expires)); clock = min_t(unsigned long, clock, INT_MAX); ci.rta_expires = (expires > 0) ? clock : -clock; } |
e3703b3de [RTNETLINK]: Add ... |
693 694 |
return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci); } |
e3703b3de [RTNETLINK]: Add ... |
695 |
EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); |
1da177e4c Linux-2.6.12-rc2 |
696 |
|
93b2d4a20 Revert "[RTNETLIN... |
697 |
static void set_operstate(struct net_device *dev, unsigned char transition) |
b00055aac [NET] core: add R... |
698 699 |
{ unsigned char operstate = dev->operstate; |
e0d087af7 rtnetlink: Cleanups |
700 |
switch (transition) { |
b00055aac [NET] core: add R... |
701 702 703 704 705 706 707 708 709 710 711 712 |
case IF_OPER_UP: if ((operstate == IF_OPER_DORMANT || operstate == IF_OPER_UNKNOWN) && !netif_dormant(dev)) operstate = IF_OPER_UP; break; case IF_OPER_DORMANT: if (operstate == IF_OPER_UP || operstate == IF_OPER_UNKNOWN) operstate = IF_OPER_DORMANT; break; |
3ff50b799 [NET]: cleanup ex... |
713 |
} |
b00055aac [NET] core: add R... |
714 715 716 717 718 |
if (dev->operstate != operstate) { write_lock_bh(&dev_base_lock); dev->operstate = operstate; write_unlock_bh(&dev_base_lock); |
93b2d4a20 Revert "[RTNETLIN... |
719 720 |
netdev_state_change(dev); } |
b00055aac [NET] core: add R... |
721 |
} |
b1beb681c net: fix rtnetlin... |
722 723 724 725 726 |
static unsigned int rtnl_dev_get_flags(const struct net_device *dev) { return (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI)) | (dev->gflags & (IFF_PROMISC | IFF_ALLMULTI)); } |
3729d5021 rtnetlink: suppor... |
727 728 729 730 731 732 733 734 |
static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, const struct ifinfomsg *ifm) { unsigned int flags = ifm->ifi_flags; /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ if (ifm->ifi_change) flags = (flags & ifm->ifi_change) | |
b1beb681c net: fix rtnetlin... |
735 |
(rtnl_dev_get_flags(dev) & ~ifm->ifi_change); |
3729d5021 rtnetlink: suppor... |
736 737 738 |
return flags; } |
b60c5115f [NET]: Convert li... |
739 |
static void copy_rtnl_link_stats(struct rtnl_link_stats *a, |
be1f3c2c0 net: Enable 64-bi... |
740 |
const struct rtnl_link_stats64 *b) |
1da177e4c Linux-2.6.12-rc2 |
741 |
{ |
b60c5115f [NET]: Convert li... |
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 |
a->rx_packets = b->rx_packets; a->tx_packets = b->tx_packets; a->rx_bytes = b->rx_bytes; a->tx_bytes = b->tx_bytes; a->rx_errors = b->rx_errors; a->tx_errors = b->tx_errors; a->rx_dropped = b->rx_dropped; a->tx_dropped = b->tx_dropped; a->multicast = b->multicast; a->collisions = b->collisions; a->rx_length_errors = b->rx_length_errors; a->rx_over_errors = b->rx_over_errors; a->rx_crc_errors = b->rx_crc_errors; a->rx_frame_errors = b->rx_frame_errors; a->rx_fifo_errors = b->rx_fifo_errors; a->rx_missed_errors = b->rx_missed_errors; a->tx_aborted_errors = b->tx_aborted_errors; a->tx_carrier_errors = b->tx_carrier_errors; a->tx_fifo_errors = b->tx_fifo_errors; a->tx_heartbeat_errors = b->tx_heartbeat_errors; a->tx_window_errors = b->tx_window_errors; a->rx_compressed = b->rx_compressed; a->tx_compressed = b->tx_compressed; |
6e7333d31 net: add rx_nohan... |
769 770 |
a->rx_nohandler = b->rx_nohandler; |
10708f37a net: core: add IF... |
771 |
} |
c02db8c62 rtnetlink: make S... |
772 |
/* All VF info */ |
115c9b819 rtnetlink: Fix pr... |
773 774 |
static inline int rtnl_vfinfo_size(const struct net_device *dev, u32 ext_filter_mask) |
ebc08a6f4 rtnetlink: Add VF... |
775 |
{ |
9af15c382 device: Implement... |
776 |
if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF)) { |
c02db8c62 rtnetlink: make S... |
777 |
int num_vfs = dev_num_vf(dev->dev.parent); |
7e75f74a1 rtnetlink: fix rt... |
778 |
size_t size = nla_total_size(0); |
045de01a1 netlink: bug fix:... |
779 |
size += num_vfs * |
7e75f74a1 rtnetlink: fix rt... |
780 781 782 783 |
(nla_total_size(0) + nla_total_size(sizeof(struct ifla_vf_mac)) + nla_total_size(sizeof(struct ifla_vf_vlan)) + nla_total_size(0) + /* nest IFLA_VF_VLAN_LIST */ |
79aab093a net: Update API f... |
784 785 |
nla_total_size(MAX_VLAN_LIST_LEN * sizeof(struct ifla_vf_vlan_info)) + |
ed616689a net-next:v4: Add ... |
786 |
nla_total_size(sizeof(struct ifla_vf_spoofchk)) + |
7e75f74a1 rtnetlink: fix rt... |
787 |
nla_total_size(sizeof(struct ifla_vf_tx_rate)) + |
945a36761 rtnetlink: fix VF... |
788 |
nla_total_size(sizeof(struct ifla_vf_rate)) + |
01a3d7968 if_link: Add an a... |
789 |
nla_total_size(sizeof(struct ifla_vf_link_state)) + |
3b766cd83 net/core: Add rea... |
790 |
nla_total_size(sizeof(struct ifla_vf_rss_query_en)) + |
7e75f74a1 rtnetlink: fix rt... |
791 |
nla_total_size(0) + /* nest IFLA_VF_STATS */ |
3b766cd83 net/core: Add rea... |
792 |
/* IFLA_VF_STATS_RX_PACKETS */ |
343a6d8e4 rtnl: use nla_put... |
793 |
nla_total_size_64bit(sizeof(__u64)) + |
3b766cd83 net/core: Add rea... |
794 |
/* IFLA_VF_STATS_TX_PACKETS */ |
343a6d8e4 rtnl: use nla_put... |
795 |
nla_total_size_64bit(sizeof(__u64)) + |
3b766cd83 net/core: Add rea... |
796 |
/* IFLA_VF_STATS_RX_BYTES */ |
343a6d8e4 rtnl: use nla_put... |
797 |
nla_total_size_64bit(sizeof(__u64)) + |
3b766cd83 net/core: Add rea... |
798 |
/* IFLA_VF_STATS_TX_BYTES */ |
343a6d8e4 rtnl: use nla_put... |
799 |
nla_total_size_64bit(sizeof(__u64)) + |
3b766cd83 net/core: Add rea... |
800 |
/* IFLA_VF_STATS_BROADCAST */ |
343a6d8e4 rtnl: use nla_put... |
801 |
nla_total_size_64bit(sizeof(__u64)) + |
3b766cd83 net/core: Add rea... |
802 |
/* IFLA_VF_STATS_MULTICAST */ |
343a6d8e4 rtnl: use nla_put... |
803 |
nla_total_size_64bit(sizeof(__u64)) + |
dd461d6aa if_link: Add cont... |
804 |
nla_total_size(sizeof(struct ifla_vf_trust))); |
c02db8c62 rtnetlink: make S... |
805 806 |
return size; } else |
ebc08a6f4 rtnetlink: Add VF... |
807 808 |
return 0; } |
c53864fd6 rtnetlink: Only s... |
809 810 |
static size_t rtnl_port_size(const struct net_device *dev, u32 ext_filter_mask) |
57b610805 net: Add netlink ... |
811 812 813 |
{ size_t port_size = nla_total_size(4) /* PORT_VF */ + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */ |
57b610805 net: Add netlink ... |
814 815 816 817 818 819 820 821 822 |
+ nla_total_size(PORT_UUID_MAX) /* PORT_INSTANCE_UUID */ + nla_total_size(PORT_UUID_MAX) /* PORT_HOST_UUID */ + nla_total_size(1) /* PROT_VDP_REQUEST */ + nla_total_size(2); /* PORT_VDP_RESPONSE */ size_t vf_ports_size = nla_total_size(sizeof(struct nlattr)); size_t vf_port_size = nla_total_size(sizeof(struct nlattr)) + port_size; size_t port_self_size = nla_total_size(sizeof(struct nlattr)) + port_size; |
c53864fd6 rtnetlink: Only s... |
823 824 |
if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent || !(ext_filter_mask & RTEXT_FILTER_VF)) |
57b610805 net: Add netlink ... |
825 826 827 828 829 830 831 |
return 0; if (dev_num_vf(dev->dev.parent)) return port_self_size + vf_ports_size + vf_port_size * dev_num_vf(dev->dev.parent); else return port_self_size; } |
b5cdae329 net: Generic XDP |
832 |
static size_t rtnl_xdp_size(void) |
d1fdd9138 rtnl: add option ... |
833 |
{ |
b3cfaa31e rtnetlink: fix rt... |
834 |
size_t xdp_size = nla_total_size(0) + /* nest IFLA_XDP */ |
58038695e net: Add IFLA_XDP... |
835 836 |
nla_total_size(1) + /* XDP_ATTACHED */ nla_total_size(4); /* XDP_PROG_ID */ |
d1fdd9138 rtnl: add option ... |
837 |
|
b5cdae329 net: Generic XDP |
838 |
return xdp_size; |
d1fdd9138 rtnl: add option ... |
839 |
} |
115c9b819 rtnetlink: Fix pr... |
840 841 |
static noinline size_t if_nlmsg_size(const struct net_device *dev, u32 ext_filter_mask) |
339bf98ff [NETLINK]: Do pre... |
842 843 844 |
{ return NLMSG_ALIGN(sizeof(struct ifinfomsg)) + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ |
0b815a1a6 net: network devi... |
845 |
+ nla_total_size(IFALIASZ) /* IFLA_IFALIAS */ |
339bf98ff [NETLINK]: Do pre... |
846 |
+ nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ |
270cb4d05 rtnl: align nlatt... |
847 |
+ nla_total_size_64bit(sizeof(struct rtnl_link_ifmap)) |
339bf98ff [NETLINK]: Do pre... |
848 |
+ nla_total_size(sizeof(struct rtnl_link_stats)) |
35c584595 net: Add helpers ... |
849 |
+ nla_total_size_64bit(sizeof(struct rtnl_link_stats64)) |
339bf98ff [NETLINK]: Do pre... |
850 851 852 853 854 855 856 |
+ nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */ + nla_total_size(4) /* IFLA_TXQLEN */ + nla_total_size(4) /* IFLA_WEIGHT */ + nla_total_size(4) /* IFLA_MTU */ + nla_total_size(4) /* IFLA_LINK */ + nla_total_size(4) /* IFLA_MASTER */ |
9a57247f3 rtnl: expose carr... |
857 |
+ nla_total_size(1) /* IFLA_CARRIER */ |
edbc0bb3f net: Report dev->... |
858 |
+ nla_total_size(4) /* IFLA_PROMISCUITY */ |
76ff5cc91 rtnl: allow to sp... |
859 860 |
+ nla_total_size(4) /* IFLA_NUM_TX_QUEUES */ + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */ |
6919756ca net/rtnetlink: fi... |
861 862 |
+ nla_total_size(4) /* IFLA_GSO_MAX_SEGS */ + nla_total_size(4) /* IFLA_GSO_MAX_SIZE */ |
339bf98ff [NETLINK]: Do pre... |
863 |
+ nla_total_size(1) /* IFLA_OPERSTATE */ |
38f7b870d [RTNETLINK]: Link... |
864 |
+ nla_total_size(1) /* IFLA_LINKMODE */ |
2d3b479df net-sysfs: expose... |
865 |
+ nla_total_size(4) /* IFLA_CARRIER_CHANGES */ |
d37512a27 rtnl: add link ne... |
866 |
+ nla_total_size(4) /* IFLA_LINK_NETNSID */ |
db833d40a rtnetlink: add IF... |
867 |
+ nla_total_size(4) /* IFLA_GROUP */ |
115c9b819 rtnetlink: Fix pr... |
868 869 870 |
+ nla_total_size(ext_filter_mask & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ |
c53864fd6 rtnetlink: Only s... |
871 |
+ rtnl_port_size(dev, ext_filter_mask) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ |
f8ff182c7 rtnetlink: Link a... |
872 |
+ rtnl_link_get_size(dev) /* IFLA_LINKINFO */ |
b1974ed05 netlink: Rightsiz... |
873 |
+ rtnl_link_get_af_size(dev, ext_filter_mask) /* IFLA_AF_SPEC */ |
82f284129 rtnl: expose phys... |
874 |
+ nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_PORT_ID */ |
88d6378bd netlink: changes ... |
875 |
+ nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_SWITCH_ID */ |
c57c7a95d rtnl: fix msg siz... |
876 |
+ nla_total_size(IFNAMSIZ) /* IFLA_PHYS_PORT_NAME */ |
b5cdae329 net: Generic XDP |
877 |
+ rtnl_xdp_size() /* IFLA_XDP */ |
3d3ea5af5 rtnl: Add support... |
878 |
+ nla_total_size(4) /* IFLA_EVENT */ |
88d6378bd netlink: changes ... |
879 |
+ nla_total_size(1); /* IFLA_PROTO_DOWN */ |
339bf98ff [NETLINK]: Do pre... |
880 |
} |
57b610805 net: Add netlink ... |
881 882 883 884 885 886 887 888 889 890 891 892 893 |
static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev) { struct nlattr *vf_ports; struct nlattr *vf_port; int vf; int err; vf_ports = nla_nest_start(skb, IFLA_VF_PORTS); if (!vf_ports) return -EMSGSIZE; for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) { vf_port = nla_nest_start(skb, IFLA_VF_PORT); |
8ca941835 netlink: bug fix:... |
894 895 |
if (!vf_port) goto nla_put_failure; |
a6574349d rtnetlink: Stop u... |
896 897 |
if (nla_put_u32(skb, IFLA_PORT_VF, vf)) goto nla_put_failure; |
57b610805 net: Add netlink ... |
898 |
err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb); |
8ca941835 netlink: bug fix:... |
899 900 |
if (err == -EMSGSIZE) goto nla_put_failure; |
57b610805 net: Add netlink ... |
901 |
if (err) { |
57b610805 net: Add netlink ... |
902 903 904 905 906 907 908 909 910 |
nla_nest_cancel(skb, vf_port); continue; } nla_nest_end(skb, vf_port); } nla_nest_end(skb, vf_ports); return 0; |
8ca941835 netlink: bug fix:... |
911 912 913 914 |
nla_put_failure: nla_nest_cancel(skb, vf_ports); return -EMSGSIZE; |
57b610805 net: Add netlink ... |
915 916 917 918 919 920 921 922 923 924 925 926 927 928 |
} static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev) { struct nlattr *port_self; int err; port_self = nla_nest_start(skb, IFLA_PORT_SELF); if (!port_self) return -EMSGSIZE; err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb); if (err) { nla_nest_cancel(skb, port_self); |
8ca941835 netlink: bug fix:... |
929 |
return (err == -EMSGSIZE) ? err : 0; |
57b610805 net: Add netlink ... |
930 931 932 933 934 935 |
} nla_nest_end(skb, port_self); return 0; } |
c53864fd6 rtnetlink: Only s... |
936 937 |
static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev, u32 ext_filter_mask) |
57b610805 net: Add netlink ... |
938 939 |
{ int err; |
c53864fd6 rtnetlink: Only s... |
940 941 |
if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent || !(ext_filter_mask & RTEXT_FILTER_VF)) |
57b610805 net: Add netlink ... |
942 943 944 945 946 947 948 949 950 951 952 953 954 955 |
return 0; err = rtnl_port_self_fill(skb, dev); if (err) return err; if (dev_num_vf(dev->dev.parent)) { err = rtnl_vf_ports_fill(skb, dev); if (err) return err; } return 0; } |
66cae9ed6 rtnl: export phys... |
956 957 958 |
static int rtnl_phys_port_id_fill(struct sk_buff *skb, struct net_device *dev) { int err; |
02637fce3 net: rename netde... |
959 |
struct netdev_phys_item_id ppid; |
66cae9ed6 rtnl: export phys... |
960 961 962 963 964 965 966 967 968 969 970 971 972 |
err = dev_get_phys_port_id(dev, &ppid); if (err) { if (err == -EOPNOTSUPP) return 0; return err; } if (nla_put(skb, IFLA_PHYS_PORT_ID, ppid.id_len, ppid.id)) return -EMSGSIZE; return 0; } |
db24a9044 net: add support ... |
973 974 975 976 977 978 979 980 981 982 983 |
static int rtnl_phys_port_name_fill(struct sk_buff *skb, struct net_device *dev) { char name[IFNAMSIZ]; int err; err = dev_get_phys_port_name(dev, name, sizeof(name)); if (err) { if (err == -EOPNOTSUPP) return 0; return err; } |
77ef033b6 rtnetlink: NUL-te... |
984 |
if (nla_put_string(skb, IFLA_PHYS_PORT_NAME, name)) |
db24a9044 net: add support ... |
985 986 987 988 |
return -EMSGSIZE; return 0; } |
82f284129 rtnl: expose phys... |
989 990 991 |
static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev) { int err; |
f8e20a9f8 switchdev: conver... |
992 |
struct switchdev_attr attr = { |
6ff64f6f9 switchdev: Pass o... |
993 |
.orig_dev = dev, |
1f8683987 switchdev: rename... |
994 |
.id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, |
f8e20a9f8 switchdev: conver... |
995 996 |
.flags = SWITCHDEV_F_NO_RECURSE, }; |
82f284129 rtnl: expose phys... |
997 |
|
f8e20a9f8 switchdev: conver... |
998 |
err = switchdev_port_attr_get(dev, &attr); |
82f284129 rtnl: expose phys... |
999 1000 1001 1002 1003 |
if (err) { if (err == -EOPNOTSUPP) return 0; return err; } |
42275bd8f switchdev: don't ... |
1004 1005 |
if (nla_put(skb, IFLA_PHYS_SWITCH_ID, attr.u.ppid.id_len, attr.u.ppid.id)) |
82f284129 rtnl: expose phys... |
1006 1007 1008 1009 |
return -EMSGSIZE; return 0; } |
b22b941b2 rtnetlink: fix fr... |
1010 1011 1012 |
static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb, struct net_device *dev) { |
550bce59b rtnetlink: rtnl_f... |
1013 |
struct rtnl_link_stats64 *sp; |
b22b941b2 rtnetlink: fix fr... |
1014 |
struct nlattr *attr; |
18402843b net: Align IFLA_S... |
1015 |
|
58414d32a rtnl: use the new... |
1016 1017 |
attr = nla_reserve_64bit(skb, IFLA_STATS64, sizeof(struct rtnl_link_stats64), IFLA_PAD); |
b22b941b2 rtnetlink: fix fr... |
1018 1019 |
if (!attr) return -EMSGSIZE; |
550bce59b rtnetlink: rtnl_f... |
1020 1021 |
sp = nla_data(attr); dev_get_stats(dev, sp); |
b22b941b2 rtnetlink: fix fr... |
1022 |
|
550bce59b rtnetlink: rtnl_f... |
1023 1024 |
attr = nla_reserve(skb, IFLA_STATS, sizeof(struct rtnl_link_stats)); |
b22b941b2 rtnetlink: fix fr... |
1025 1026 |
if (!attr) return -EMSGSIZE; |
550bce59b rtnetlink: rtnl_f... |
1027 |
copy_rtnl_link_stats(nla_data(attr), sp); |
b22b941b2 rtnetlink: fix fr... |
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 |
return 0; } static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, struct net_device *dev, int vfs_num, struct nlattr *vfinfo) { struct ifla_vf_rss_query_en vf_rss_query_en; |
79aab093a net: Update API f... |
1038 |
struct nlattr *vf, *vfstats, *vfvlanlist; |
b22b941b2 rtnetlink: fix fr... |
1039 |
struct ifla_vf_link_state vf_linkstate; |
79aab093a net: Update API f... |
1040 |
struct ifla_vf_vlan_info vf_vlan_info; |
b22b941b2 rtnetlink: fix fr... |
1041 1042 1043 1044 1045 1046 |
struct ifla_vf_spoofchk vf_spoofchk; struct ifla_vf_tx_rate vf_tx_rate; struct ifla_vf_stats vf_stats; struct ifla_vf_trust vf_trust; struct ifla_vf_vlan vf_vlan; struct ifla_vf_rate vf_rate; |
b22b941b2 rtnetlink: fix fr... |
1047 1048 |
struct ifla_vf_mac vf_mac; struct ifla_vf_info ivi; |
0eed9cf58 net: Zero ifla_vf... |
1049 |
memset(&ivi, 0, sizeof(ivi)); |
b22b941b2 rtnetlink: fix fr... |
1050 1051 1052 1053 1054 1055 1056 1057 |
/* Not all SR-IOV capable drivers support the * spoofcheck and "RSS query enable" query. Preset to * -1 so the user space tool can detect that the driver * didn't report anything. */ ivi.spoofchk = -1; ivi.rss_query_en = -1; ivi.trusted = -1; |
b22b941b2 rtnetlink: fix fr... |
1058 1059 1060 1061 |
/* The default value for VF link state is "auto" * IFLA_VF_LINK_STATE_AUTO which equals zero */ ivi.linkstate = 0; |
79aab093a net: Update API f... |
1062 1063 |
/* VLAN Protocol by default is 802.1Q */ ivi.vlan_proto = htons(ETH_P_8021Q); |
b22b941b2 rtnetlink: fix fr... |
1064 1065 |
if (dev->netdev_ops->ndo_get_vf_config(dev, vfs_num, &ivi)) return 0; |
775f4f055 net: rtnl: info l... |
1066 |
memset(&vf_vlan_info, 0, sizeof(vf_vlan_info)); |
b22b941b2 rtnetlink: fix fr... |
1067 1068 |
vf_mac.vf = vf_vlan.vf = |
79aab093a net: Update API f... |
1069 |
vf_vlan_info.vf = |
b22b941b2 rtnetlink: fix fr... |
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 |
vf_rate.vf = vf_tx_rate.vf = vf_spoofchk.vf = vf_linkstate.vf = vf_rss_query_en.vf = vf_trust.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; |
79aab093a net: Update API f... |
1080 1081 1082 |
vf_vlan_info.vlan = ivi.vlan; vf_vlan_info.qos = ivi.qos; vf_vlan_info.vlan_proto = ivi.vlan_proto; |
b22b941b2 rtnetlink: fix fr... |
1083 1084 1085 1086 1087 1088 1089 1090 |
vf_tx_rate.rate = ivi.max_tx_rate; vf_rate.min_tx_rate = ivi.min_tx_rate; vf_rate.max_tx_rate = ivi.max_tx_rate; vf_spoofchk.setting = ivi.spoofchk; vf_linkstate.link_state = ivi.linkstate; vf_rss_query_en.setting = ivi.rss_query_en; vf_trust.setting = ivi.trusted; vf = nla_nest_start(skb, IFLA_VF_INFO); |
79aab093a net: Update API f... |
1091 1092 |
if (!vf) goto nla_put_vfinfo_failure; |
b22b941b2 rtnetlink: fix fr... |
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 |
if (nla_put(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac) || nla_put(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan) || nla_put(skb, IFLA_VF_RATE, sizeof(vf_rate), &vf_rate) || nla_put(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate) || nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk), &vf_spoofchk) || nla_put(skb, IFLA_VF_LINK_STATE, sizeof(vf_linkstate), &vf_linkstate) || nla_put(skb, IFLA_VF_RSS_QUERY_EN, sizeof(vf_rss_query_en), &vf_rss_query_en) || nla_put(skb, IFLA_VF_TRUST, sizeof(vf_trust), &vf_trust)) |
79aab093a net: Update API f... |
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 |
goto nla_put_vf_failure; vfvlanlist = nla_nest_start(skb, IFLA_VF_VLAN_LIST); if (!vfvlanlist) goto nla_put_vf_failure; if (nla_put(skb, IFLA_VF_VLAN_INFO, sizeof(vf_vlan_info), &vf_vlan_info)) { nla_nest_cancel(skb, vfvlanlist); goto nla_put_vf_failure; } nla_nest_end(skb, vfvlanlist); |
b22b941b2 rtnetlink: fix fr... |
1118 1119 1120 1121 1122 |
memset(&vf_stats, 0, sizeof(vf_stats)); if (dev->netdev_ops->ndo_get_vf_stats) dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num, &vf_stats); vfstats = nla_nest_start(skb, IFLA_VF_STATS); |
79aab093a net: Update API f... |
1123 1124 |
if (!vfstats) goto nla_put_vf_failure; |
343a6d8e4 rtnl: use nla_put... |
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 |
if (nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_PACKETS, vf_stats.rx_packets, IFLA_VF_STATS_PAD) || nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_PACKETS, vf_stats.tx_packets, IFLA_VF_STATS_PAD) || nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_BYTES, vf_stats.rx_bytes, IFLA_VF_STATS_PAD) || nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_BYTES, vf_stats.tx_bytes, IFLA_VF_STATS_PAD) || nla_put_u64_64bit(skb, IFLA_VF_STATS_BROADCAST, vf_stats.broadcast, IFLA_VF_STATS_PAD) || nla_put_u64_64bit(skb, IFLA_VF_STATS_MULTICAST, |
79aab093a net: Update API f... |
1136 1137 1138 1139 |
vf_stats.multicast, IFLA_VF_STATS_PAD)) { nla_nest_cancel(skb, vfstats); goto nla_put_vf_failure; } |
b22b941b2 rtnetlink: fix fr... |
1140 1141 1142 |
nla_nest_end(skb, vfstats); nla_nest_end(skb, vf); return 0; |
79aab093a net: Update API f... |
1143 1144 1145 1146 1147 1148 |
nla_put_vf_failure: nla_nest_cancel(skb, vf); nla_put_vfinfo_failure: nla_nest_cancel(skb, vfinfo); return -EMSGSIZE; |
b22b941b2 rtnetlink: fix fr... |
1149 1150 1151 1152 |
} static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev) { |
5f8e44741 net: fix infoleak... |
1153 1154 1155 1156 1157 1158 1159 1160 1161 |
struct rtnl_link_ifmap map; memset(&map, 0, sizeof(map)); map.mem_start = dev->mem_start; map.mem_end = dev->mem_end; map.base_addr = dev->base_addr; map.irq = dev->irq; map.dma = dev->dma; map.port = dev->if_port; |
270cb4d05 rtnl: align nlatt... |
1162 |
if (nla_put_64bit(skb, IFLA_MAP, sizeof(map), &map, IFLA_PAD)) |
b22b941b2 rtnetlink: fix fr... |
1163 1164 1165 1166 |
return -EMSGSIZE; return 0; } |
58038695e net: Add IFLA_XDP... |
1167 |
static u8 rtnl_xdp_attached_mode(struct net_device *dev, u32 *prog_id) |
d67b9cd28 xdp: refine xdp a... |
1168 1169 |
{ const struct net_device_ops *ops = dev->netdev_ops; |
58038695e net: Add IFLA_XDP... |
1170 |
const struct bpf_prog *generic_xdp_prog; |
d67b9cd28 xdp: refine xdp a... |
1171 1172 |
ASSERT_RTNL(); |
58038695e net: Add IFLA_XDP... |
1173 1174 1175 1176 |
*prog_id = 0; generic_xdp_prog = rtnl_dereference(dev->xdp_prog); if (generic_xdp_prog) { *prog_id = generic_xdp_prog->aux->id; |
d67b9cd28 xdp: refine xdp a... |
1177 |
return XDP_ATTACHED_SKB; |
58038695e net: Add IFLA_XDP... |
1178 |
} |
ce158e580 xdp: add reportin... |
1179 1180 |
if (!ops->ndo_xdp) return XDP_ATTACHED_NONE; |
d67b9cd28 xdp: refine xdp a... |
1181 |
|
ce158e580 xdp: add reportin... |
1182 |
return __dev_xdp_attached(dev, ops->ndo_xdp, prog_id); |
d67b9cd28 xdp: refine xdp a... |
1183 |
} |
d1fdd9138 rtnl: add option ... |
1184 1185 |
static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev) { |
d1fdd9138 rtnl: add option ... |
1186 |
struct nlattr *xdp; |
58038695e net: Add IFLA_XDP... |
1187 |
u32 prog_id; |
d1fdd9138 rtnl: add option ... |
1188 |
int err; |
d1fdd9138 rtnl: add option ... |
1189 1190 1191 |
xdp = nla_nest_start(skb, IFLA_XDP); if (!xdp) return -EMSGSIZE; |
d67b9cd28 xdp: refine xdp a... |
1192 1193 |
err = nla_put_u8(skb, IFLA_XDP_ATTACHED, |
58038695e net: Add IFLA_XDP... |
1194 |
rtnl_xdp_attached_mode(dev, &prog_id)); |
d1fdd9138 rtnl: add option ... |
1195 1196 |
if (err) goto err_cancel; |
58038695e net: Add IFLA_XDP... |
1197 1198 1199 1200 1201 |
if (prog_id) { err = nla_put_u32(skb, IFLA_XDP_PROG_ID, prog_id); if (err) goto err_cancel; } |
d1fdd9138 rtnl: add option ... |
1202 1203 1204 1205 1206 1207 1208 |
nla_nest_end(skb, xdp); return 0; err_cancel: nla_nest_cancel(skb, xdp); return err; } |
3d3ea5af5 rtnl: Add support... |
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 |
static u32 rtnl_get_event(unsigned long event) { u32 rtnl_event_type = IFLA_EVENT_NONE; switch (event) { case NETDEV_REBOOT: rtnl_event_type = IFLA_EVENT_REBOOT; break; case NETDEV_FEAT_CHANGE: rtnl_event_type = IFLA_EVENT_FEATURES; break; case NETDEV_BONDING_FAILOVER: rtnl_event_type = IFLA_EVENT_BONDING_FAILOVER; break; case NETDEV_NOTIFY_PEERS: rtnl_event_type = IFLA_EVENT_NOTIFY_PEERS; break; case NETDEV_RESEND_IGMP: rtnl_event_type = IFLA_EVENT_IGMP_RESEND; break; case NETDEV_CHANGEINFODATA: rtnl_event_type = IFLA_EVENT_BONDING_OPTIONS; break; default: break; } return rtnl_event_type; } |
b60c5115f [NET]: Convert li... |
1238 |
static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, |
575c3e2a0 [RTNETLINK]: Remo... |
1239 |
int type, u32 pid, u32 seq, u32 change, |
3d3ea5af5 rtnl: Add support... |
1240 1241 |
unsigned int flags, u32 ext_filter_mask, u32 event) |
b60c5115f [NET]: Convert li... |
1242 1243 1244 |
{ struct ifinfomsg *ifm; struct nlmsghdr *nlh; |
b22b941b2 rtnetlink: fix fr... |
1245 |
struct nlattr *af_spec; |
f8ff182c7 rtnetlink: Link a... |
1246 |
struct rtnl_af_ops *af_ops; |
898e50617 rtnetlink: remove... |
1247 |
struct net_device *upper_dev = netdev_master_upper_dev_get(dev); |
1da177e4c Linux-2.6.12-rc2 |
1248 |
|
2907c35ff net: hold rtnl ag... |
1249 |
ASSERT_RTNL(); |
b60c5115f [NET]: Convert li... |
1250 1251 |
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); if (nlh == NULL) |
26932566a [NETLINK]: Don't ... |
1252 |
return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
1253 |
|
b60c5115f [NET]: Convert li... |
1254 1255 1256 1257 1258 1259 1260 |
ifm = nlmsg_data(nlh); ifm->ifi_family = AF_UNSPEC; ifm->__ifi_pad = 0; ifm->ifi_type = dev->type; ifm->ifi_index = dev->ifindex; ifm->ifi_flags = dev_get_flags(dev); ifm->ifi_change = change; |
a6574349d rtnetlink: Stop u... |
1261 1262 1263 1264 1265 1266 1267 |
if (nla_put_string(skb, IFLA_IFNAME, dev->name) || nla_put_u32(skb, IFLA_TXQLEN, dev->tx_queue_len) || nla_put_u8(skb, IFLA_OPERSTATE, netif_running(dev) ? dev->operstate : IF_OPER_DOWN) || nla_put_u8(skb, IFLA_LINKMODE, dev->link_mode) || nla_put_u32(skb, IFLA_MTU, dev->mtu) || nla_put_u32(skb, IFLA_GROUP, dev->group) || |
edbc0bb3f net: Report dev->... |
1268 |
nla_put_u32(skb, IFLA_PROMISCUITY, dev->promiscuity) || |
76ff5cc91 rtnl: allow to sp... |
1269 |
nla_put_u32(skb, IFLA_NUM_TX_QUEUES, dev->num_tx_queues) || |
c70ce028e net/rtnetlink: ad... |
1270 1271 |
nla_put_u32(skb, IFLA_GSO_MAX_SEGS, dev->gso_max_segs) || nla_put_u32(skb, IFLA_GSO_MAX_SIZE, dev->gso_max_size) || |
1d69c2b34 rtnl: Add #ifdef ... |
1272 |
#ifdef CONFIG_RPS |
76ff5cc91 rtnl: allow to sp... |
1273 |
nla_put_u32(skb, IFLA_NUM_RX_QUEUES, dev->num_rx_queues) || |
1d69c2b34 rtnl: Add #ifdef ... |
1274 |
#endif |
a54acb3a6 dev: introduce de... |
1275 1276 |
(dev->ifindex != dev_get_iflink(dev) && nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) || |
898e50617 rtnetlink: remove... |
1277 1278 |
(upper_dev && nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex)) || |
9a57247f3 rtnl: expose carr... |
1279 |
nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) || |
a6574349d rtnetlink: Stop u... |
1280 1281 1282 |
(dev->qdisc && nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || (dev->ifalias && |
2d3b479df net-sysfs: expose... |
1283 1284 |
nla_put_string(skb, IFLA_IFALIAS, dev->ifalias)) || nla_put_u32(skb, IFLA_CARRIER_CHANGES, |
88d6378bd netlink: changes ... |
1285 1286 |
atomic_read(&dev->carrier_changes)) || nla_put_u8(skb, IFLA_PROTO_DOWN, dev->proto_down)) |
a6574349d rtnetlink: Stop u... |
1287 |
goto nla_put_failure; |
0b815a1a6 net: network devi... |
1288 |
|
3d3ea5af5 rtnl: Add support... |
1289 1290 1291 1292 |
if (event != IFLA_EVENT_NONE) { if (nla_put_u32(skb, IFLA_EVENT, event)) goto nla_put_failure; } |
b22b941b2 rtnetlink: fix fr... |
1293 1294 |
if (rtnl_fill_link_ifmap(skb, dev)) goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
1295 1296 |
if (dev->addr_len) { |
a6574349d rtnetlink: Stop u... |
1297 1298 1299 |
if (nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr) || nla_put(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast)) goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
1300 |
} |
66cae9ed6 rtnl: export phys... |
1301 1302 |
if (rtnl_phys_port_id_fill(skb, dev)) goto nla_put_failure; |
db24a9044 net: add support ... |
1303 1304 |
if (rtnl_phys_port_name_fill(skb, dev)) goto nla_put_failure; |
82f284129 rtnl: expose phys... |
1305 1306 |
if (rtnl_phys_switch_id_fill(skb, dev)) goto nla_put_failure; |
b22b941b2 rtnetlink: fix fr... |
1307 |
if (rtnl_fill_stats(skb, dev)) |
10708f37a net: core: add IF... |
1308 |
goto nla_put_failure; |
10708f37a net: core: add IF... |
1309 |
|
a6574349d rtnetlink: Stop u... |
1310 1311 1312 |
if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF) && nla_put_u32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent))) goto nla_put_failure; |
57b610805 net: Add netlink ... |
1313 |
|
b22b941b2 rtnetlink: fix fr... |
1314 1315 |
if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent && ext_filter_mask & RTEXT_FILTER_VF) { |
ebc08a6f4 rtnetlink: Add VF... |
1316 |
int i; |
b22b941b2 rtnetlink: fix fr... |
1317 |
struct nlattr *vfinfo; |
c02db8c62 rtnetlink: make S... |
1318 |
int num_vfs = dev_num_vf(dev->dev.parent); |
c02db8c62 rtnetlink: make S... |
1319 1320 1321 1322 |
vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); if (!vfinfo) goto nla_put_failure; for (i = 0; i < num_vfs; i++) { |
b22b941b2 rtnetlink: fix fr... |
1323 |
if (rtnl_fill_vfinfo(skb, dev, i, vfinfo)) |
3b766cd83 net/core: Add rea... |
1324 |
goto nla_put_failure; |
ebc08a6f4 rtnetlink: Add VF... |
1325 |
} |
b22b941b2 rtnetlink: fix fr... |
1326 |
|
c02db8c62 rtnetlink: make S... |
1327 |
nla_nest_end(skb, vfinfo); |
ebc08a6f4 rtnetlink: Add VF... |
1328 |
} |
57b610805 net: Add netlink ... |
1329 |
|
c53864fd6 rtnetlink: Only s... |
1330 |
if (rtnl_port_fill(skb, dev, ext_filter_mask)) |
57b610805 net: Add netlink ... |
1331 |
goto nla_put_failure; |
d1fdd9138 rtnl: add option ... |
1332 1333 |
if (rtnl_xdp_fill(skb, dev)) goto nla_put_failure; |
ba7d49b1f rtnetlink: provid... |
1334 |
if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) { |
38f7b870d [RTNETLINK]: Link... |
1335 1336 1337 |
if (rtnl_link_fill(skb, dev) < 0) goto nla_put_failure; } |
d37512a27 rtnl: add link ne... |
1338 1339 1340 1341 1342 |
if (dev->rtnl_link_ops && dev->rtnl_link_ops->get_link_net) { struct net *link_net = dev->rtnl_link_ops->get_link_net(dev); if (!net_eq(dev_net(dev), link_net)) { |
7a0877d4b netns: rename pee... |
1343 |
int id = peernet2id_alloc(dev_net(dev), link_net); |
d37512a27 rtnl: add link ne... |
1344 1345 1346 1347 1348 |
if (nla_put_s32(skb, IFLA_LINK_NETNSID, id)) goto nla_put_failure; } } |
f8ff182c7 rtnetlink: Link a... |
1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 |
if (!(af_spec = nla_nest_start(skb, IFLA_AF_SPEC))) goto nla_put_failure; list_for_each_entry(af_ops, &rtnl_af_ops, list) { if (af_ops->fill_link_af) { struct nlattr *af; int err; if (!(af = nla_nest_start(skb, af_ops->family))) goto nla_put_failure; |
d5566fd72 rtnetlink: RTEXT_... |
1359 |
err = af_ops->fill_link_af(skb, dev, ext_filter_mask); |
f8ff182c7 rtnetlink: Link a... |
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 |
/* * Caller may return ENODATA to indicate that there * was no data to be dumped. This is not an error, it * means we should trim the attribute header and * continue. */ if (err == -ENODATA) nla_nest_cancel(skb, af); else if (err < 0) goto nla_put_failure; nla_nest_end(skb, af); } } nla_nest_end(skb, af_spec); |
053c095a8 netlink: make nlm... |
1377 1378 |
nlmsg_end(skb, nlh); return 0; |
b60c5115f [NET]: Convert li... |
1379 1380 |
nla_put_failure: |
26932566a [NETLINK]: Don't ... |
1381 1382 |
nlmsg_cancel(skb, nlh); return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
1383 |
} |
f7b12606b rtnl: make ifla_p... |
1384 |
static const struct nla_policy ifla_policy[IFLA_MAX+1] = { |
5176f91ea [NETLINK]: Make u... |
1385 |
[IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, |
38f7b870d [RTNETLINK]: Link... |
1386 1387 |
[IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
5176f91ea [NETLINK]: Make u... |
1388 |
[IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, |
da5e0494c [NET]: Convert li... |
1389 |
[IFLA_MTU] = { .type = NLA_U32 }, |
76e87306c [RTNL]: Add missi... |
1390 |
[IFLA_LINK] = { .type = NLA_U32 }, |
fbaec0ea5 rtnetlink: implem... |
1391 |
[IFLA_MASTER] = { .type = NLA_U32 }, |
9a57247f3 rtnl: expose carr... |
1392 |
[IFLA_CARRIER] = { .type = NLA_U8 }, |
da5e0494c [NET]: Convert li... |
1393 1394 1395 1396 |
[IFLA_TXQLEN] = { .type = NLA_U32 }, [IFLA_WEIGHT] = { .type = NLA_U32 }, [IFLA_OPERSTATE] = { .type = NLA_U8 }, [IFLA_LINKMODE] = { .type = NLA_U8 }, |
76e87306c [RTNL]: Add missi... |
1397 |
[IFLA_LINKINFO] = { .type = NLA_NESTED }, |
d8a5ec672 [NET]: netlink su... |
1398 |
[IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
f06305294 net: Allow settin... |
1399 |
[IFLA_NET_NS_FD] = { .type = NLA_U32 }, |
2459b4c63 net: enable inter... |
1400 1401 1402 1403 |
/* IFLA_IFALIAS is a string, but policy is set to NLA_BINARY to * allow 0-length string (needed to remove an alias). */ [IFLA_IFALIAS] = { .type = NLA_BINARY, .len = IFALIASZ - 1 }, |
c02db8c62 rtnetlink: make S... |
1404 |
[IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, |
57b610805 net: Add netlink ... |
1405 1406 |
[IFLA_VF_PORTS] = { .type = NLA_NESTED }, [IFLA_PORT_SELF] = { .type = NLA_NESTED }, |
f8ff182c7 rtnetlink: Link a... |
1407 |
[IFLA_AF_SPEC] = { .type = NLA_NESTED }, |
115c9b819 rtnetlink: Fix pr... |
1408 |
[IFLA_EXT_MASK] = { .type = NLA_U32 }, |
edbc0bb3f net: Report dev->... |
1409 |
[IFLA_PROMISCUITY] = { .type = NLA_U32 }, |
76ff5cc91 rtnl: allow to sp... |
1410 1411 |
[IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, |
02637fce3 net: rename netde... |
1412 |
[IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN }, |
2d3b479df net-sysfs: expose... |
1413 |
[IFLA_CARRIER_CHANGES] = { .type = NLA_U32 }, /* ignored */ |
82f284129 rtnl: expose phys... |
1414 |
[IFLA_PHYS_SWITCH_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN }, |
317f4810e rtnl: allow to cr... |
1415 |
[IFLA_LINK_NETNSID] = { .type = NLA_S32 }, |
88d6378bd netlink: changes ... |
1416 |
[IFLA_PROTO_DOWN] = { .type = NLA_U8 }, |
d1fdd9138 rtnl: add option ... |
1417 |
[IFLA_XDP] = { .type = NLA_NESTED }, |
3d3ea5af5 rtnl: Add support... |
1418 |
[IFLA_EVENT] = { .type = NLA_U32 }, |
db833d40a rtnetlink: add IF... |
1419 |
[IFLA_GROUP] = { .type = NLA_U32 }, |
da5e0494c [NET]: Convert li... |
1420 |
}; |
38f7b870d [RTNETLINK]: Link... |
1421 1422 1423 |
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { [IFLA_INFO_KIND] = { .type = NLA_STRING }, [IFLA_INFO_DATA] = { .type = NLA_NESTED }, |
ba7d49b1f rtnetlink: provid... |
1424 1425 |
[IFLA_INFO_SLAVE_KIND] = { .type = NLA_STRING }, [IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED }, |
38f7b870d [RTNETLINK]: Link... |
1426 |
}; |
c02db8c62 rtnetlink: make S... |
1427 |
static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { |
364d5716a rtnetlink: ifla_v... |
1428 1429 |
[IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) }, [IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) }, |
79aab093a net: Update API f... |
1430 |
[IFLA_VF_VLAN_LIST] = { .type = NLA_NESTED }, |
364d5716a rtnetlink: ifla_v... |
1431 1432 1433 1434 |
[IFLA_VF_TX_RATE] = { .len = sizeof(struct ifla_vf_tx_rate) }, [IFLA_VF_SPOOFCHK] = { .len = sizeof(struct ifla_vf_spoofchk) }, [IFLA_VF_RATE] = { .len = sizeof(struct ifla_vf_rate) }, [IFLA_VF_LINK_STATE] = { .len = sizeof(struct ifla_vf_link_state) }, |
01a3d7968 if_link: Add an a... |
1435 |
[IFLA_VF_RSS_QUERY_EN] = { .len = sizeof(struct ifla_vf_rss_query_en) }, |
3b766cd83 net/core: Add rea... |
1436 |
[IFLA_VF_STATS] = { .type = NLA_NESTED }, |
dd461d6aa if_link: Add cont... |
1437 |
[IFLA_VF_TRUST] = { .len = sizeof(struct ifla_vf_trust) }, |
cc8e27cc9 net/core: Add sup... |
1438 1439 |
[IFLA_VF_IB_NODE_GUID] = { .len = sizeof(struct ifla_vf_guid) }, [IFLA_VF_IB_PORT_GUID] = { .len = sizeof(struct ifla_vf_guid) }, |
3b766cd83 net/core: Add rea... |
1440 |
}; |
57b610805 net: Add netlink ... |
1441 1442 1443 1444 |
static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { [IFLA_PORT_VF] = { .type = NLA_U32 }, [IFLA_PORT_PROFILE] = { .type = NLA_STRING, .len = PORT_PROFILE_MAX }, |
57b610805 net: Add netlink ... |
1445 1446 1447 1448 1449 1450 |
[IFLA_PORT_INSTANCE_UUID] = { .type = NLA_BINARY, .len = PORT_UUID_MAX }, [IFLA_PORT_HOST_UUID] = { .type = NLA_STRING, .len = PORT_UUID_MAX }, [IFLA_PORT_REQUEST] = { .type = NLA_U8, }, [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, |
025331df3 rtnl: don't accou... |
1451 1452 1453 1454 1455 1456 1457 |
/* Unused, but we need to keep it here since user space could * fill it. It's also broken with regard to NLA_BINARY use in * combination with structs. */ [IFLA_PORT_VSI_TYPE] = { .type = NLA_BINARY, .len = sizeof(struct ifla_port_vsi) }, |
57b610805 net: Add netlink ... |
1458 |
}; |
d1fdd9138 rtnl: add option ... |
1459 1460 1461 |
static const struct nla_policy ifla_xdp_policy[IFLA_XDP_MAX + 1] = { [IFLA_XDP_FD] = { .type = NLA_S32 }, [IFLA_XDP_ATTACHED] = { .type = NLA_U8 }, |
85de8576a bpf, xdp: allow t... |
1462 |
[IFLA_XDP_FLAGS] = { .type = NLA_U32 }, |
58038695e net: Add IFLA_XDP... |
1463 |
[IFLA_XDP_PROG_ID] = { .type = NLA_U32 }, |
d1fdd9138 rtnl: add option ... |
1464 |
}; |
dc599f76c net: Add support ... |
1465 1466 1467 1468 |
static const struct rtnl_link_ops *linkinfo_to_kind_ops(const struct nlattr *nla) { const struct rtnl_link_ops *ops = NULL; struct nlattr *linfo[IFLA_INFO_MAX + 1]; |
fceb6435e netlink: pass ext... |
1469 1470 |
if (nla_parse_nested(linfo, IFLA_INFO_MAX, nla, ifla_info_policy, NULL) < 0) |
dc599f76c net: Add support ... |
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 |
return NULL; if (linfo[IFLA_INFO_KIND]) { char kind[MODULE_NAME_LEN]; nla_strlcpy(kind, linfo[IFLA_INFO_KIND], sizeof(kind)); ops = rtnl_link_ops_get(kind); } return ops; } static bool link_master_filtered(struct net_device *dev, int master_idx) { struct net_device *master; if (!master_idx) return false; master = netdev_master_upper_dev_get(dev); if (!master || master->ifindex != master_idx) return true; return false; } static bool link_kind_filtered(const struct net_device *dev, const struct rtnl_link_ops *kind_ops) { if (kind_ops && dev->rtnl_link_ops != kind_ops) return true; return false; } static bool link_dump_filtered(struct net_device *dev, int master_idx, const struct rtnl_link_ops *kind_ops) { if (link_master_filtered(dev, master_idx) || link_kind_filtered(dev, kind_ops)) return true; return false; } |
f7b12606b rtnl: make ifla_p... |
1516 1517 1518 1519 1520 1521 1522 1523 1524 |
static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); int h, s_h; int idx = 0, s_idx; struct net_device *dev; struct hlist_head *head; struct nlattr *tb[IFLA_MAX+1]; u32 ext_filter_mask = 0; |
dc599f76c net: Add support ... |
1525 1526 1527 |
const struct rtnl_link_ops *kind_ops = NULL; unsigned int flags = NLM_F_MULTI; int master_idx = 0; |
973462bbd rtnetlink: Warn w... |
1528 |
int err; |
e5eca6d41 rtnetlink: fix us... |
1529 |
int hdrlen; |
f7b12606b rtnl: make ifla_p... |
1530 1531 1532 |
s_h = cb->args[0]; s_idx = cb->args[1]; |
e5eca6d41 rtnetlink: fix us... |
1533 1534 1535 1536 1537 1538 1539 1540 1541 |
/* A hack to preserve kernel<->userspace interface. * The correct header is ifinfomsg. It is consistent with rtnl_getlink. * However, before Linux v3.9 the code here assumed rtgenmsg and that's * what iproute2 < v3.9.0 used. * We can detect the old iproute2. Even including the IFLA_EXT_MASK * attribute, its netlink message is shorter than struct ifinfomsg. */ hdrlen = nlmsg_len(cb->nlh) < sizeof(struct ifinfomsg) ? sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg); |
fceb6435e netlink: pass ext... |
1542 1543 |
if (nlmsg_parse(cb->nlh, hdrlen, tb, IFLA_MAX, ifla_policy, NULL) >= 0) { |
f7b12606b rtnl: make ifla_p... |
1544 1545 |
if (tb[IFLA_EXT_MASK]) ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); |
dc599f76c net: Add support ... |
1546 1547 1548 1549 1550 1551 1552 1553 1554 |
if (tb[IFLA_MASTER]) master_idx = nla_get_u32(tb[IFLA_MASTER]); if (tb[IFLA_LINKINFO]) kind_ops = linkinfo_to_kind_ops(tb[IFLA_LINKINFO]); if (master_idx || kind_ops) flags |= NLM_F_DUMP_FILTERED; |
f7b12606b rtnl: make ifla_p... |
1555 1556 1557 1558 1559 |
} for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { idx = 0; head = &net->dev_index_head[h]; |
cac5e65e8 net: do not use r... |
1560 |
hlist_for_each_entry(dev, head, index_hlist) { |
dc599f76c net: Add support ... |
1561 |
if (link_dump_filtered(dev, master_idx, kind_ops)) |
3f0ae05d6 rtnl: fix the loo... |
1562 |
goto cont; |
f7b12606b rtnl: make ifla_p... |
1563 1564 |
if (idx < s_idx) goto cont; |
973462bbd rtnetlink: Warn w... |
1565 1566 1567 |
err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 0, |
dc599f76c net: Add support ... |
1568 |
flags, |
3d3ea5af5 rtnl: Add support... |
1569 |
ext_filter_mask, 0); |
973462bbd rtnetlink: Warn w... |
1570 |
|
f6c5775ff net: Improve hand... |
1571 1572 1573 1574 1575 1576 |
if (err < 0) { if (likely(skb->len)) goto out; goto out_err; } |
f7b12606b rtnl: make ifla_p... |
1577 1578 1579 1580 1581 |
cont: idx++; } } out: |
f6c5775ff net: Improve hand... |
1582 1583 |
err = skb->len; out_err: |
f7b12606b rtnl: make ifla_p... |
1584 1585 |
cb->args[1] = idx; cb->args[0] = h; |
d0225784b rtnelink: Move li... |
1586 1587 |
cb->seq = net->dev_base_seq; nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
f7b12606b rtnl: make ifla_p... |
1588 |
|
f6c5775ff net: Improve hand... |
1589 |
return err; |
f7b12606b rtnl: make ifla_p... |
1590 |
} |
fceb6435e netlink: pass ext... |
1591 1592 |
int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len, struct netlink_ext_ack *exterr) |
f7b12606b rtnl: make ifla_p... |
1593 |
{ |
fceb6435e netlink: pass ext... |
1594 |
return nla_parse(tb, IFLA_MAX, head, len, ifla_policy, exterr); |
f7b12606b rtnl: make ifla_p... |
1595 1596 |
} EXPORT_SYMBOL(rtnl_nla_parse_ifla); |
81adee47d net: Support spec... |
1597 1598 1599 1600 1601 1602 1603 1604 |
struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) { struct net *net; /* Examine the link attributes and figure out which * network namespace we are talking about. */ if (tb[IFLA_NET_NS_PID]) net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); |
f06305294 net: Allow settin... |
1605 1606 |
else if (tb[IFLA_NET_NS_FD]) net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD])); |
81adee47d net: Support spec... |
1607 1608 1609 1610 1611 |
else net = get_net(src_net); return net; } EXPORT_SYMBOL(rtnl_link_get_net); |
1840bb13c [RTNL]: Validate ... |
1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 |
static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) { if (dev) { if (tb[IFLA_ADDRESS] && nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) return -EINVAL; if (tb[IFLA_BROADCAST] && nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) return -EINVAL; } |
cf7afbfeb rtnl: make link a... |
1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 |
if (tb[IFLA_AF_SPEC]) { struct nlattr *af; int rem, err; nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { const struct rtnl_af_ops *af_ops; if (!(af_ops = rtnl_af_lookup(nla_type(af)))) return -EAFNOSUPPORT; if (!af_ops->set_link_af) return -EOPNOTSUPP; if (af_ops->validate_link_af) { |
6d3a9a685 net: fix validate... |
1637 |
err = af_ops->validate_link_af(dev, af); |
cf7afbfeb rtnl: make link a... |
1638 1639 1640 1641 1642 |
if (err < 0) return err; } } } |
1840bb13c [RTNL]: Validate ... |
1643 1644 |
return 0; } |
cc8e27cc9 net/core: Add sup... |
1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 |
static int handle_infiniband_guid(struct net_device *dev, struct ifla_vf_guid *ivt, int guid_type) { const struct net_device_ops *ops = dev->netdev_ops; return ops->ndo_set_vf_guid(dev, ivt->vf, ivt->guid, guid_type); } static int handle_vf_guid(struct net_device *dev, struct ifla_vf_guid *ivt, int guid_type) { if (dev->type != ARPHRD_INFINIBAND) return -EOPNOTSUPP; return handle_infiniband_guid(dev, ivt, guid_type); } |
4f7d2cdfd rtnetlink: verify... |
1660 |
static int do_setvfinfo(struct net_device *dev, struct nlattr **tb) |
c02db8c62 rtnetlink: make S... |
1661 |
{ |
c02db8c62 rtnetlink: make S... |
1662 |
const struct net_device_ops *ops = dev->netdev_ops; |
4f7d2cdfd rtnetlink: verify... |
1663 |
int err = -EINVAL; |
c02db8c62 rtnetlink: make S... |
1664 |
|
4f7d2cdfd rtnetlink: verify... |
1665 1666 |
if (tb[IFLA_VF_MAC]) { struct ifla_vf_mac *ivm = nla_data(tb[IFLA_VF_MAC]); |
01a3d7968 if_link: Add an a... |
1667 |
|
4f7d2cdfd rtnetlink: verify... |
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 |
err = -EOPNOTSUPP; if (ops->ndo_set_vf_mac) err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac); if (err < 0) return err; } if (tb[IFLA_VF_VLAN]) { struct ifla_vf_vlan *ivv = nla_data(tb[IFLA_VF_VLAN]); err = -EOPNOTSUPP; if (ops->ndo_set_vf_vlan) err = ops->ndo_set_vf_vlan(dev, ivv->vf, ivv->vlan, |
79aab093a net: Update API f... |
1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 |
ivv->qos, htons(ETH_P_8021Q)); if (err < 0) return err; } if (tb[IFLA_VF_VLAN_LIST]) { struct ifla_vf_vlan_info *ivvl[MAX_VLAN_LIST_LEN]; struct nlattr *attr; int rem, len = 0; err = -EOPNOTSUPP; if (!ops->ndo_set_vf_vlan) return err; nla_for_each_nested(attr, tb[IFLA_VF_VLAN_LIST], rem) { if (nla_type(attr) != IFLA_VF_VLAN_INFO || nla_len(attr) < NLA_HDRLEN) { return -EINVAL; } if (len >= MAX_VLAN_LIST_LEN) return -EOPNOTSUPP; ivvl[len] = nla_data(attr); len++; } |
fa34cd94f net: rtnl: avoid ... |
1708 1709 |
if (len == 0) return -EINVAL; |
79aab093a net: Update API f... |
1710 1711 |
err = ops->ndo_set_vf_vlan(dev, ivvl[0]->vf, ivvl[0]->vlan, ivvl[0]->qos, ivvl[0]->vlan_proto); |
4f7d2cdfd rtnetlink: verify... |
1712 1713 |
if (err < 0) return err; |
c02db8c62 rtnetlink: make S... |
1714 |
} |
4f7d2cdfd rtnetlink: verify... |
1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 |
if (tb[IFLA_VF_TX_RATE]) { struct ifla_vf_tx_rate *ivt = nla_data(tb[IFLA_VF_TX_RATE]); struct ifla_vf_info ivf; err = -EOPNOTSUPP; if (ops->ndo_get_vf_config) err = ops->ndo_get_vf_config(dev, ivt->vf, &ivf); if (err < 0) return err; err = -EOPNOTSUPP; if (ops->ndo_set_vf_rate) err = ops->ndo_set_vf_rate(dev, ivt->vf, ivf.min_tx_rate, ivt->rate); if (err < 0) return err; } if (tb[IFLA_VF_RATE]) { struct ifla_vf_rate *ivt = nla_data(tb[IFLA_VF_RATE]); err = -EOPNOTSUPP; if (ops->ndo_set_vf_rate) err = ops->ndo_set_vf_rate(dev, ivt->vf, ivt->min_tx_rate, ivt->max_tx_rate); if (err < 0) return err; } if (tb[IFLA_VF_SPOOFCHK]) { struct ifla_vf_spoofchk *ivs = nla_data(tb[IFLA_VF_SPOOFCHK]); err = -EOPNOTSUPP; if (ops->ndo_set_vf_spoofchk) err = ops->ndo_set_vf_spoofchk(dev, ivs->vf, ivs->setting); if (err < 0) return err; } if (tb[IFLA_VF_LINK_STATE]) { struct ifla_vf_link_state *ivl = nla_data(tb[IFLA_VF_LINK_STATE]); err = -EOPNOTSUPP; if (ops->ndo_set_vf_link_state) err = ops->ndo_set_vf_link_state(dev, ivl->vf, ivl->link_state); if (err < 0) return err; } if (tb[IFLA_VF_RSS_QUERY_EN]) { struct ifla_vf_rss_query_en *ivrssq_en; err = -EOPNOTSUPP; ivrssq_en = nla_data(tb[IFLA_VF_RSS_QUERY_EN]); if (ops->ndo_set_vf_rss_query_en) err = ops->ndo_set_vf_rss_query_en(dev, ivrssq_en->vf, ivrssq_en->setting); if (err < 0) return err; } |
dd461d6aa if_link: Add cont... |
1780 1781 1782 1783 1784 1785 1786 1787 1788 |
if (tb[IFLA_VF_TRUST]) { struct ifla_vf_trust *ivt = nla_data(tb[IFLA_VF_TRUST]); err = -EOPNOTSUPP; if (ops->ndo_set_vf_trust) err = ops->ndo_set_vf_trust(dev, ivt->vf, ivt->setting); if (err < 0) return err; } |
cc8e27cc9 net/core: Add sup... |
1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 |
if (tb[IFLA_VF_IB_NODE_GUID]) { struct ifla_vf_guid *ivt = nla_data(tb[IFLA_VF_IB_NODE_GUID]); if (!ops->ndo_set_vf_guid) return -EOPNOTSUPP; return handle_vf_guid(dev, ivt, IFLA_VF_IB_NODE_GUID); } if (tb[IFLA_VF_IB_PORT_GUID]) { struct ifla_vf_guid *ivt = nla_data(tb[IFLA_VF_IB_PORT_GUID]); if (!ops->ndo_set_vf_guid) return -EOPNOTSUPP; return handle_vf_guid(dev, ivt, IFLA_VF_IB_PORT_GUID); } |
c02db8c62 rtnetlink: make S... |
1806 1807 |
return err; } |
fbaec0ea5 rtnetlink: implem... |
1808 1809 |
static int do_set_master(struct net_device *dev, int ifindex) { |
898e50617 rtnetlink: remove... |
1810 |
struct net_device *upper_dev = netdev_master_upper_dev_get(dev); |
fbaec0ea5 rtnetlink: implem... |
1811 1812 |
const struct net_device_ops *ops; int err; |
898e50617 rtnetlink: remove... |
1813 1814 |
if (upper_dev) { if (upper_dev->ifindex == ifindex) |
fbaec0ea5 rtnetlink: implem... |
1815 |
return 0; |
898e50617 rtnetlink: remove... |
1816 |
ops = upper_dev->netdev_ops; |
fbaec0ea5 rtnetlink: implem... |
1817 |
if (ops->ndo_del_slave) { |
898e50617 rtnetlink: remove... |
1818 |
err = ops->ndo_del_slave(upper_dev, dev); |
fbaec0ea5 rtnetlink: implem... |
1819 1820 1821 1822 1823 1824 1825 1826 |
if (err) return err; } else { return -EOPNOTSUPP; } } if (ifindex) { |
898e50617 rtnetlink: remove... |
1827 1828 |
upper_dev = __dev_get_by_index(dev_net(dev), ifindex); if (!upper_dev) |
fbaec0ea5 rtnetlink: implem... |
1829 |
return -EINVAL; |
898e50617 rtnetlink: remove... |
1830 |
ops = upper_dev->netdev_ops; |
fbaec0ea5 rtnetlink: implem... |
1831 |
if (ops->ndo_add_slave) { |
898e50617 rtnetlink: remove... |
1832 |
err = ops->ndo_add_slave(upper_dev, dev); |
fbaec0ea5 rtnetlink: implem... |
1833 1834 1835 1836 1837 1838 1839 1840 |
if (err) return err; } else { return -EOPNOTSUPP; } } return 0; } |
90c325e3b rtnl/do_setlink()... |
1841 |
#define DO_SETLINK_MODIFIED 0x01 |
ba9989069 rtnl/do_setlink()... |
1842 1843 |
/* notify flag means notify + modified. */ #define DO_SETLINK_NOTIFY 0x03 |
90f62cf30 net: Use netlink_... |
1844 1845 |
static int do_setlink(const struct sk_buff *skb, struct net_device *dev, struct ifinfomsg *ifm, |
ddf9f9707 xdp: propagate ex... |
1846 |
struct netlink_ext_ack *extack, |
90c325e3b rtnl/do_setlink()... |
1847 |
struct nlattr **tb, char *ifname, int status) |
1da177e4c Linux-2.6.12-rc2 |
1848 |
{ |
d314774cf netdev: network d... |
1849 |
const struct net_device_ops *ops = dev->netdev_ops; |
0157f60c0 [RTNETLINK]: Spli... |
1850 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
1851 |
|
c931c9aee rtnetlink: valida... |
1852 1853 1854 |
err = validate_linkmsg(dev, tb); if (err < 0) return err; |
f06305294 net: Allow settin... |
1855 |
if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) { |
81adee47d net: Support spec... |
1856 |
struct net *net = rtnl_link_get_net(dev_net(dev), tb); |
d8a5ec672 [NET]: netlink su... |
1857 1858 1859 1860 |
if (IS_ERR(net)) { err = PTR_ERR(net); goto errout; } |
90f62cf30 net: Use netlink_... |
1861 |
if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) { |
e0ebde0e1 rtnetlink: releas... |
1862 |
put_net(net); |
b51642f6d net: Enable a use... |
1863 1864 1865 |
err = -EPERM; goto errout; } |
d8a5ec672 [NET]: netlink su... |
1866 1867 1868 1869 |
err = dev_change_net_namespace(dev, net, ifname); put_net(net); if (err) goto errout; |
90c325e3b rtnl/do_setlink()... |
1870 |
status |= DO_SETLINK_MODIFIED; |
d8a5ec672 [NET]: netlink su... |
1871 |
} |
da5e0494c [NET]: Convert li... |
1872 |
if (tb[IFLA_MAP]) { |
1da177e4c Linux-2.6.12-rc2 |
1873 1874 |
struct rtnl_link_ifmap *u_map; struct ifmap k_map; |
d314774cf netdev: network d... |
1875 |
if (!ops->ndo_set_config) { |
1da177e4c Linux-2.6.12-rc2 |
1876 |
err = -EOPNOTSUPP; |
0157f60c0 [RTNETLINK]: Spli... |
1877 |
goto errout; |
1da177e4c Linux-2.6.12-rc2 |
1878 1879 1880 1881 |
} if (!netif_device_present(dev)) { err = -ENODEV; |
0157f60c0 [RTNETLINK]: Spli... |
1882 |
goto errout; |
1da177e4c Linux-2.6.12-rc2 |
1883 |
} |
1da177e4c Linux-2.6.12-rc2 |
1884 |
|
da5e0494c [NET]: Convert li... |
1885 |
u_map = nla_data(tb[IFLA_MAP]); |
1da177e4c Linux-2.6.12-rc2 |
1886 1887 1888 1889 1890 1891 |
k_map.mem_start = (unsigned long) u_map->mem_start; k_map.mem_end = (unsigned long) u_map->mem_end; k_map.base_addr = (unsigned short) u_map->base_addr; k_map.irq = (unsigned char) u_map->irq; k_map.dma = (unsigned char) u_map->dma; k_map.port = (unsigned char) u_map->port; |
d314774cf netdev: network d... |
1892 |
err = ops->ndo_set_config(dev, &k_map); |
da5e0494c [NET]: Convert li... |
1893 |
if (err < 0) |
0157f60c0 [RTNETLINK]: Spli... |
1894 |
goto errout; |
1da177e4c Linux-2.6.12-rc2 |
1895 |
|
ba9989069 rtnl/do_setlink()... |
1896 |
status |= DO_SETLINK_NOTIFY; |
1da177e4c Linux-2.6.12-rc2 |
1897 |
} |
da5e0494c [NET]: Convert li... |
1898 |
if (tb[IFLA_ADDRESS]) { |
70f8e78e1 [RTNETLINK]: Fix ... |
1899 1900 |
struct sockaddr *sa; int len; |
153711f94 rtnetlink: alloca... |
1901 1902 |
len = sizeof(sa_family_t) + max_t(size_t, dev->addr_len, sizeof(*sa)); |
70f8e78e1 [RTNETLINK]: Fix ... |
1903 1904 1905 |
sa = kmalloc(len, GFP_KERNEL); if (!sa) { err = -ENOMEM; |
0157f60c0 [RTNETLINK]: Spli... |
1906 |
goto errout; |
70f8e78e1 [RTNETLINK]: Fix ... |
1907 1908 |
} sa->sa_family = dev->type; |
da5e0494c [NET]: Convert li... |
1909 |
memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), |
70f8e78e1 [RTNETLINK]: Fix ... |
1910 |
dev->addr_len); |
e7c3273ec rtnl: use dev_set... |
1911 |
err = dev_set_mac_address(dev, sa); |
70f8e78e1 [RTNETLINK]: Fix ... |
1912 |
kfree(sa); |
1da177e4c Linux-2.6.12-rc2 |
1913 |
if (err) |
0157f60c0 [RTNETLINK]: Spli... |
1914 |
goto errout; |
90c325e3b rtnl/do_setlink()... |
1915 |
status |= DO_SETLINK_MODIFIED; |
1da177e4c Linux-2.6.12-rc2 |
1916 |
} |
da5e0494c [NET]: Convert li... |
1917 1918 1919 |
if (tb[IFLA_MTU]) { err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); if (err < 0) |
0157f60c0 [RTNETLINK]: Spli... |
1920 |
goto errout; |
90c325e3b rtnl/do_setlink()... |
1921 |
status |= DO_SETLINK_MODIFIED; |
1da177e4c Linux-2.6.12-rc2 |
1922 |
} |
cbda10fa9 net_device: add s... |
1923 1924 |
if (tb[IFLA_GROUP]) { dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP])); |
ba9989069 rtnl/do_setlink()... |
1925 |
status |= DO_SETLINK_NOTIFY; |
cbda10fa9 net_device: add s... |
1926 |
} |
da5e0494c [NET]: Convert li... |
1927 1928 1929 1930 1931 |
/* * Interface selected by interface index but interface * name provided implies that a name change has been * requested. */ |
51055be81 [RTNETLINK]: ifin... |
1932 |
if (ifm->ifi_index > 0 && ifname[0]) { |
da5e0494c [NET]: Convert li... |
1933 1934 |
err = dev_change_name(dev, ifname); if (err < 0) |
0157f60c0 [RTNETLINK]: Spli... |
1935 |
goto errout; |
90c325e3b rtnl/do_setlink()... |
1936 |
status |= DO_SETLINK_MODIFIED; |
1da177e4c Linux-2.6.12-rc2 |
1937 |
} |
0b815a1a6 net: network devi... |
1938 1939 1940 1941 1942 |
if (tb[IFLA_IFALIAS]) { err = dev_set_alias(dev, nla_data(tb[IFLA_IFALIAS]), nla_len(tb[IFLA_IFALIAS])); if (err < 0) goto errout; |
ba9989069 rtnl/do_setlink()... |
1943 |
status |= DO_SETLINK_NOTIFY; |
0b815a1a6 net: network devi... |
1944 |
} |
da5e0494c [NET]: Convert li... |
1945 1946 |
if (tb[IFLA_BROADCAST]) { nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); |
e7c3273ec rtnl: use dev_set... |
1947 |
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
1da177e4c Linux-2.6.12-rc2 |
1948 |
} |
83b496e92 [RTNETLINK]: Allo... |
1949 |
if (ifm->ifi_flags || ifm->ifi_change) { |
3729d5021 rtnetlink: suppor... |
1950 |
err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); |
5f9021cfd rtnetlink: propag... |
1951 1952 |
if (err < 0) goto errout; |
83b496e92 [RTNETLINK]: Allo... |
1953 |
} |
1da177e4c Linux-2.6.12-rc2 |
1954 |
|
fbaec0ea5 rtnetlink: implem... |
1955 1956 1957 1958 |
if (tb[IFLA_MASTER]) { err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER])); if (err) goto errout; |
90c325e3b rtnl/do_setlink()... |
1959 |
status |= DO_SETLINK_MODIFIED; |
fbaec0ea5 rtnetlink: implem... |
1960 |
} |
9a57247f3 rtnl: expose carr... |
1961 1962 1963 1964 |
if (tb[IFLA_CARRIER]) { err = dev_change_carrier(dev, nla_get_u8(tb[IFLA_CARRIER])); if (err) goto errout; |
90c325e3b rtnl/do_setlink()... |
1965 |
status |= DO_SETLINK_MODIFIED; |
9a57247f3 rtnl: expose carr... |
1966 |
} |
5d1180fca rtnl/do_setlink()... |
1967 |
if (tb[IFLA_TXQLEN]) { |
0cd295035 net: make struct ... |
1968 1969 |
unsigned int value = nla_get_u32(tb[IFLA_TXQLEN]); unsigned int orig_len = dev->tx_queue_len; |
08294a26e net: introduce NE... |
1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 |
if (dev->tx_queue_len ^ value) { dev->tx_queue_len = value; err = call_netdevice_notifiers( NETDEV_CHANGE_TX_QUEUE_LEN, dev); err = notifier_to_errno(err); if (err) { dev->tx_queue_len = orig_len; goto errout; } |
2d7f669b4 rtnetlink: do not... |
1980 |
status |= DO_SETLINK_MODIFIED; |
08294a26e net: introduce NE... |
1981 |
} |
5d1180fca rtnl/do_setlink()... |
1982 |
} |
b00055aac [NET] core: add R... |
1983 |
|
da5e0494c [NET]: Convert li... |
1984 |
if (tb[IFLA_OPERSTATE]) |
93b2d4a20 Revert "[RTNETLIN... |
1985 |
set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); |
b00055aac [NET] core: add R... |
1986 |
|
da5e0494c [NET]: Convert li... |
1987 |
if (tb[IFLA_LINKMODE]) { |
1889b0e7e rtnl/do_setlink()... |
1988 |
unsigned char value = nla_get_u8(tb[IFLA_LINKMODE]); |
93b2d4a20 Revert "[RTNETLIN... |
1989 |
write_lock_bh(&dev_base_lock); |
1889b0e7e rtnl/do_setlink()... |
1990 |
if (dev->link_mode ^ value) |
ba9989069 rtnl/do_setlink()... |
1991 |
status |= DO_SETLINK_NOTIFY; |
1889b0e7e rtnl/do_setlink()... |
1992 |
dev->link_mode = value; |
93b2d4a20 Revert "[RTNETLIN... |
1993 |
write_unlock_bh(&dev_base_lock); |
b00055aac [NET] core: add R... |
1994 |
} |
c02db8c62 rtnetlink: make S... |
1995 |
if (tb[IFLA_VFINFO_LIST]) { |
4f7d2cdfd rtnetlink: verify... |
1996 |
struct nlattr *vfinfo[IFLA_VF_MAX + 1]; |
c02db8c62 rtnetlink: make S... |
1997 1998 |
struct nlattr *attr; int rem; |
4f7d2cdfd rtnetlink: verify... |
1999 |
|
c02db8c62 rtnetlink: make S... |
2000 |
nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { |
4f7d2cdfd rtnetlink: verify... |
2001 2002 |
if (nla_type(attr) != IFLA_VF_INFO || nla_len(attr) < NLA_HDRLEN) { |
253683bbf rtnetlink: Fix er... |
2003 |
err = -EINVAL; |
c02db8c62 rtnetlink: make S... |
2004 |
goto errout; |
253683bbf rtnetlink: Fix er... |
2005 |
} |
4f7d2cdfd rtnetlink: verify... |
2006 |
err = nla_parse_nested(vfinfo, IFLA_VF_MAX, attr, |
fceb6435e netlink: pass ext... |
2007 |
ifla_vf_policy, NULL); |
4f7d2cdfd rtnetlink: verify... |
2008 2009 2010 |
if (err < 0) goto errout; err = do_setvfinfo(dev, vfinfo); |
c02db8c62 rtnetlink: make S... |
2011 2012 |
if (err < 0) goto errout; |
ba9989069 rtnl/do_setlink()... |
2013 |
status |= DO_SETLINK_NOTIFY; |
c02db8c62 rtnetlink: make S... |
2014 |
} |
ebc08a6f4 rtnetlink: Add VF... |
2015 |
} |
1da177e4c Linux-2.6.12-rc2 |
2016 |
err = 0; |
57b610805 net: Add netlink ... |
2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 |
if (tb[IFLA_VF_PORTS]) { struct nlattr *port[IFLA_PORT_MAX+1]; struct nlattr *attr; int vf; int rem; err = -EOPNOTSUPP; if (!ops->ndo_set_vf_port) goto errout; nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) { |
035d210f9 rtnetlink: reject... |
2028 2029 2030 2031 2032 2033 |
if (nla_type(attr) != IFLA_VF_PORT || nla_len(attr) < NLA_HDRLEN) { err = -EINVAL; goto errout; } err = nla_parse_nested(port, IFLA_PORT_MAX, attr, |
fceb6435e netlink: pass ext... |
2034 |
ifla_port_policy, NULL); |
57b610805 net: Add netlink ... |
2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 |
if (err < 0) goto errout; if (!port[IFLA_PORT_VF]) { err = -EOPNOTSUPP; goto errout; } vf = nla_get_u32(port[IFLA_PORT_VF]); err = ops->ndo_set_vf_port(dev, vf, port); if (err < 0) goto errout; |
ba9989069 rtnl/do_setlink()... |
2045 |
status |= DO_SETLINK_NOTIFY; |
57b610805 net: Add netlink ... |
2046 2047 2048 2049 2050 2051 2052 2053 |
} } err = 0; if (tb[IFLA_PORT_SELF]) { struct nlattr *port[IFLA_PORT_MAX+1]; err = nla_parse_nested(port, IFLA_PORT_MAX, |
fceb6435e netlink: pass ext... |
2054 2055 |
tb[IFLA_PORT_SELF], ifla_port_policy, NULL); |
57b610805 net: Add netlink ... |
2056 2057 2058 2059 2060 2061 2062 2063 |
if (err < 0) goto errout; err = -EOPNOTSUPP; if (ops->ndo_set_vf_port) err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port); if (err < 0) goto errout; |
ba9989069 rtnl/do_setlink()... |
2064 |
status |= DO_SETLINK_NOTIFY; |
57b610805 net: Add netlink ... |
2065 |
} |
f8ff182c7 rtnetlink: Link a... |
2066 2067 2068 2069 2070 2071 2072 2073 2074 |
if (tb[IFLA_AF_SPEC]) { struct nlattr *af; int rem; nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { const struct rtnl_af_ops *af_ops; if (!(af_ops = rtnl_af_lookup(nla_type(af)))) |
cf7afbfeb rtnl: make link a... |
2075 |
BUG(); |
f8ff182c7 rtnetlink: Link a... |
2076 |
|
cf7afbfeb rtnl: make link a... |
2077 |
err = af_ops->set_link_af(dev, af); |
f8ff182c7 rtnetlink: Link a... |
2078 2079 |
if (err < 0) goto errout; |
ba9989069 rtnl/do_setlink()... |
2080 |
status |= DO_SETLINK_NOTIFY; |
f8ff182c7 rtnetlink: Link a... |
2081 2082 |
} } |
57b610805 net: Add netlink ... |
2083 |
err = 0; |
88d6378bd netlink: changes ... |
2084 2085 2086 2087 2088 2089 2090 |
if (tb[IFLA_PROTO_DOWN]) { err = dev_change_proto_down(dev, nla_get_u8(tb[IFLA_PROTO_DOWN])); if (err) goto errout; status |= DO_SETLINK_NOTIFY; } |
d1fdd9138 rtnl: add option ... |
2091 2092 |
if (tb[IFLA_XDP]) { struct nlattr *xdp[IFLA_XDP_MAX + 1]; |
85de8576a bpf, xdp: allow t... |
2093 |
u32 xdp_flags = 0; |
d1fdd9138 rtnl: add option ... |
2094 2095 |
err = nla_parse_nested(xdp, IFLA_XDP_MAX, tb[IFLA_XDP], |
fceb6435e netlink: pass ext... |
2096 |
ifla_xdp_policy, NULL); |
d1fdd9138 rtnl: add option ... |
2097 2098 |
if (err < 0) goto errout; |
58038695e net: Add IFLA_XDP... |
2099 |
if (xdp[IFLA_XDP_ATTACHED] || xdp[IFLA_XDP_PROG_ID]) { |
262d86250 rtnl: protect do_... |
2100 2101 2102 |
err = -EINVAL; goto errout; } |
85de8576a bpf, xdp: allow t... |
2103 2104 2105 2106 2107 2108 2109 |
if (xdp[IFLA_XDP_FLAGS]) { xdp_flags = nla_get_u32(xdp[IFLA_XDP_FLAGS]); if (xdp_flags & ~XDP_FLAGS_MASK) { err = -EINVAL; goto errout; } |
ee5d032f7 xdp: add HW offlo... |
2110 |
if (hweight32(xdp_flags & XDP_FLAGS_MODES) > 1) { |
0489df9a4 xdp: add flag to ... |
2111 2112 2113 |
err = -EINVAL; goto errout; } |
85de8576a bpf, xdp: allow t... |
2114 |
} |
d1fdd9138 rtnl: add option ... |
2115 |
if (xdp[IFLA_XDP_FD]) { |
ddf9f9707 xdp: propagate ex... |
2116 |
err = dev_change_xdp_fd(dev, extack, |
85de8576a bpf, xdp: allow t... |
2117 2118 |
nla_get_s32(xdp[IFLA_XDP_FD]), xdp_flags); |
d1fdd9138 rtnl: add option ... |
2119 2120 2121 2122 2123 |
if (err) goto errout; status |= DO_SETLINK_NOTIFY; } } |
0157f60c0 [RTNETLINK]: Spli... |
2124 |
errout: |
ba9989069 rtnl/do_setlink()... |
2125 |
if (status & DO_SETLINK_MODIFIED) { |
64ff90cc2 rtnetlink: check ... |
2126 |
if ((status & DO_SETLINK_NOTIFY) == DO_SETLINK_NOTIFY) |
ba9989069 rtnl/do_setlink()... |
2127 2128 2129 2130 2131 2132 2133 |
netdev_state_change(dev); if (err < 0) net_warn_ratelimited("A link change request failed with some changes committed already. Interface %s may have been left with an inconsistent configuration, please check. ", dev->name); } |
da5e0494c [NET]: Convert li... |
2134 |
|
0157f60c0 [RTNETLINK]: Spli... |
2135 2136 |
return err; } |
1da177e4c Linux-2.6.12-rc2 |
2137 |
|
c21ef3e34 net: rtnetlink: p... |
2138 2139 |
static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
0157f60c0 [RTNETLINK]: Spli... |
2140 |
{ |
3b1e0a655 [NET] NETNS: Omit... |
2141 |
struct net *net = sock_net(skb->sk); |
0157f60c0 [RTNETLINK]: Spli... |
2142 2143 2144 2145 2146 |
struct ifinfomsg *ifm; struct net_device *dev; int err; struct nlattr *tb[IFLA_MAX+1]; char ifname[IFNAMSIZ]; |
c21ef3e34 net: rtnetlink: p... |
2147 2148 |
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack); |
0157f60c0 [RTNETLINK]: Spli... |
2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 |
if (err < 0) goto errout; if (tb[IFLA_IFNAME]) nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); else ifname[0] = '\0'; err = -EINVAL; ifm = nlmsg_data(nlh); if (ifm->ifi_index > 0) |
a3d128912 rtnetlink: rtnl_s... |
2160 |
dev = __dev_get_by_index(net, ifm->ifi_index); |
0157f60c0 [RTNETLINK]: Spli... |
2161 |
else if (tb[IFLA_IFNAME]) |
a3d128912 rtnetlink: rtnl_s... |
2162 |
dev = __dev_get_by_name(net, ifname); |
0157f60c0 [RTNETLINK]: Spli... |
2163 2164 2165 2166 2167 2168 2169 |
else goto errout; if (dev == NULL) { err = -ENODEV; goto errout; } |
ddf9f9707 xdp: propagate ex... |
2170 |
err = do_setlink(skb, dev, ifm, extack, tb, ifname, 0); |
da5e0494c [NET]: Convert li... |
2171 |
errout: |
1da177e4c Linux-2.6.12-rc2 |
2172 2173 |
return err; } |
66400d543 net: allow to del... |
2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 |
static int rtnl_group_dellink(const struct net *net, int group) { struct net_device *dev, *aux; LIST_HEAD(list_kill); bool found = false; if (!group) return -EPERM; for_each_netdev(net, dev) { if (dev->group == group) { const struct rtnl_link_ops *ops; found = true; ops = dev->rtnl_link_ops; if (!ops || !ops->dellink) return -EOPNOTSUPP; } } if (!found) return -ENODEV; for_each_netdev_safe(net, dev, aux) { if (dev->group == group) { const struct rtnl_link_ops *ops; ops = dev->rtnl_link_ops; ops->dellink(dev, &list_kill); } } unregister_netdevice_many(&list_kill); return 0; } |
614732eaa openvswitch: Use ... |
2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 |
int rtnl_delete_link(struct net_device *dev) { const struct rtnl_link_ops *ops; LIST_HEAD(list_kill); ops = dev->rtnl_link_ops; if (!ops || !ops->dellink) return -EOPNOTSUPP; ops->dellink(dev, &list_kill); unregister_netdevice_many(&list_kill); return 0; } EXPORT_SYMBOL_GPL(rtnl_delete_link); |
c21ef3e34 net: rtnetlink: p... |
2224 2225 |
static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
38f7b870d [RTNETLINK]: Link... |
2226 |
{ |
3b1e0a655 [NET] NETNS: Omit... |
2227 |
struct net *net = sock_net(skb->sk); |
38f7b870d [RTNETLINK]: Link... |
2228 2229 2230 2231 2232 |
struct net_device *dev; struct ifinfomsg *ifm; char ifname[IFNAMSIZ]; struct nlattr *tb[IFLA_MAX+1]; int err; |
c21ef3e34 net: rtnetlink: p... |
2233 |
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack); |
38f7b870d [RTNETLINK]: Link... |
2234 2235 2236 2237 2238 2239 2240 2241 |
if (err < 0) return err; if (tb[IFLA_IFNAME]) nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); ifm = nlmsg_data(nlh); if (ifm->ifi_index > 0) |
881d966b4 [NET]: Make the d... |
2242 |
dev = __dev_get_by_index(net, ifm->ifi_index); |
38f7b870d [RTNETLINK]: Link... |
2243 |
else if (tb[IFLA_IFNAME]) |
881d966b4 [NET]: Make the d... |
2244 |
dev = __dev_get_by_name(net, ifname); |
66400d543 net: allow to del... |
2245 2246 |
else if (tb[IFLA_GROUP]) return rtnl_group_dellink(net, nla_get_u32(tb[IFLA_GROUP])); |
38f7b870d [RTNETLINK]: Link... |
2247 2248 2249 2250 2251 |
else return -EINVAL; if (!dev) return -ENODEV; |
614732eaa openvswitch: Use ... |
2252 |
return rtnl_delete_link(dev); |
38f7b870d [RTNETLINK]: Link... |
2253 |
} |
3729d5021 rtnetlink: suppor... |
2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 |
int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) { unsigned int old_flags; int err; old_flags = dev->flags; if (ifm && (ifm->ifi_flags || ifm->ifi_change)) { err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); if (err < 0) return err; } |
23557c5d3 rtnetlink: add rt... |
2265 2266 2267 2268 2269 2270 |
if (dev->rtnl_link_state == RTNL_LINK_INITIALIZED) { __dev_notify_flags(dev, old_flags, 0U); } else { dev->rtnl_link_state = RTNL_LINK_INITIALIZED; __dev_notify_flags(dev, old_flags, ~0U); } |
3729d5021 rtnetlink: suppor... |
2271 2272 2273 |
return 0; } EXPORT_SYMBOL(rtnl_configure_link); |
c07135633 rtnelink: remove ... |
2274 |
struct net_device *rtnl_create_link(struct net *net, |
78ebb0d00 rtnetlink: Mark n... |
2275 |
const char *ifname, unsigned char name_assign_type, |
5517750f0 net: rtnetlink - ... |
2276 |
const struct rtnl_link_ops *ops, struct nlattr *tb[]) |
e71992889 [RTNETLINK]: Intr... |
2277 |
{ |
e71992889 [RTNETLINK]: Intr... |
2278 |
struct net_device *dev; |
d40156aa5 rtnl: allow to sp... |
2279 2280 |
unsigned int num_tx_queues = 1; unsigned int num_rx_queues = 1; |
e71992889 [RTNETLINK]: Intr... |
2281 |
|
76ff5cc91 rtnl: allow to sp... |
2282 2283 2284 |
if (tb[IFLA_NUM_TX_QUEUES]) num_tx_queues = nla_get_u32(tb[IFLA_NUM_TX_QUEUES]); else if (ops->get_num_tx_queues) |
d40156aa5 rtnl: allow to sp... |
2285 |
num_tx_queues = ops->get_num_tx_queues(); |
76ff5cc91 rtnl: allow to sp... |
2286 2287 2288 2289 |
if (tb[IFLA_NUM_RX_QUEUES]) num_rx_queues = nla_get_u32(tb[IFLA_NUM_RX_QUEUES]); else if (ops->get_num_rx_queues) |
d40156aa5 rtnl: allow to sp... |
2290 |
num_rx_queues = ops->get_num_rx_queues(); |
efacb309b rtnetlink & bondi... |
2291 |
|
a8b0f004e rtnl: limit IFLA_... |
2292 2293 2294 2295 2296 |
if (num_tx_queues < 1 || num_tx_queues > 4096) return ERR_PTR(-EINVAL); if (num_rx_queues < 1 || num_rx_queues > 4096) return ERR_PTR(-EINVAL); |
5517750f0 net: rtnetlink - ... |
2297 |
dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type, |
c835a6773 net: set name_ass... |
2298 |
ops->setup, num_tx_queues, num_rx_queues); |
e71992889 [RTNETLINK]: Intr... |
2299 |
if (!dev) |
d1892e4ec rtnl: simplify er... |
2300 |
return ERR_PTR(-ENOMEM); |
e71992889 [RTNETLINK]: Intr... |
2301 |
|
81adee47d net: Support spec... |
2302 2303 |
dev_net_set(dev, net); dev->rtnl_link_ops = ops; |
3729d5021 rtnetlink: suppor... |
2304 |
dev->rtnl_link_state = RTNL_LINK_INITIALIZING; |
81adee47d net: Support spec... |
2305 |
|
e71992889 [RTNETLINK]: Intr... |
2306 2307 |
if (tb[IFLA_MTU]) dev->mtu = nla_get_u32(tb[IFLA_MTU]); |
2afb9b533 ethtool: set addr... |
2308 |
if (tb[IFLA_ADDRESS]) { |
e71992889 [RTNETLINK]: Intr... |
2309 2310 |
memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), nla_len(tb[IFLA_ADDRESS])); |
2afb9b533 ethtool: set addr... |
2311 2312 |
dev->addr_assign_type = NET_ADDR_SET; } |
e71992889 [RTNETLINK]: Intr... |
2313 2314 2315 2316 2317 2318 |
if (tb[IFLA_BROADCAST]) memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]), nla_len(tb[IFLA_BROADCAST])); if (tb[IFLA_TXQLEN]) dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); if (tb[IFLA_OPERSTATE]) |
93b2d4a20 Revert "[RTNETLIN... |
2319 |
set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); |
e71992889 [RTNETLINK]: Intr... |
2320 2321 |
if (tb[IFLA_LINKMODE]) dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); |
ffa934f19 rtnetlink: fix li... |
2322 2323 |
if (tb[IFLA_GROUP]) dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP])); |
e71992889 [RTNETLINK]: Intr... |
2324 2325 |
return dev; |
e71992889 [RTNETLINK]: Intr... |
2326 |
} |
e0d087af7 rtnetlink: Cleanups |
2327 |
EXPORT_SYMBOL(rtnl_create_link); |
e71992889 [RTNETLINK]: Intr... |
2328 |
|
90f62cf30 net: Use netlink_... |
2329 2330 |
static int rtnl_group_changelink(const struct sk_buff *skb, struct net *net, int group, |
e7ed828f1 netlink: support ... |
2331 |
struct ifinfomsg *ifm, |
ddf9f9707 xdp: propagate ex... |
2332 |
struct netlink_ext_ack *extack, |
e7ed828f1 netlink: support ... |
2333 2334 |
struct nlattr **tb) { |
d079535d5 net: use for_each... |
2335 |
struct net_device *dev, *aux; |
e7ed828f1 netlink: support ... |
2336 |
int err; |
d079535d5 net: use for_each... |
2337 |
for_each_netdev_safe(net, dev, aux) { |
e7ed828f1 netlink: support ... |
2338 |
if (dev->group == group) { |
ddf9f9707 xdp: propagate ex... |
2339 |
err = do_setlink(skb, dev, ifm, extack, tb, NULL, 0); |
e7ed828f1 netlink: support ... |
2340 2341 2342 2343 2344 2345 2346 |
if (err < 0) return err; } } return 0; } |
c21ef3e34 net: rtnetlink: p... |
2347 2348 |
static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
38f7b870d [RTNETLINK]: Link... |
2349 |
{ |
3b1e0a655 [NET] NETNS: Omit... |
2350 |
struct net *net = sock_net(skb->sk); |
38f7b870d [RTNETLINK]: Link... |
2351 |
const struct rtnl_link_ops *ops; |
ba7d49b1f rtnetlink: provid... |
2352 |
const struct rtnl_link_ops *m_ops = NULL; |
38f7b870d [RTNETLINK]: Link... |
2353 |
struct net_device *dev; |
ba7d49b1f rtnetlink: provid... |
2354 |
struct net_device *master_dev = NULL; |
38f7b870d [RTNETLINK]: Link... |
2355 2356 2357 2358 2359 |
struct ifinfomsg *ifm; char kind[MODULE_NAME_LEN]; char ifname[IFNAMSIZ]; struct nlattr *tb[IFLA_MAX+1]; struct nlattr *linkinfo[IFLA_INFO_MAX+1]; |
5517750f0 net: rtnetlink - ... |
2360 |
unsigned char name_assign_type = NET_NAME_USER; |
38f7b870d [RTNETLINK]: Link... |
2361 |
int err; |
95a5afca4 net: Remove CONFI... |
2362 |
#ifdef CONFIG_MODULES |
38f7b870d [RTNETLINK]: Link... |
2363 |
replay: |
8072f085d [RTNETLINK]: Fix ... |
2364 |
#endif |
c21ef3e34 net: rtnetlink: p... |
2365 |
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack); |
38f7b870d [RTNETLINK]: Link... |
2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 |
if (err < 0) return err; if (tb[IFLA_IFNAME]) nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); else ifname[0] = '\0'; ifm = nlmsg_data(nlh); if (ifm->ifi_index > 0) |
881d966b4 [NET]: Make the d... |
2376 |
dev = __dev_get_by_index(net, ifm->ifi_index); |
e7ed828f1 netlink: support ... |
2377 2378 2379 |
else { if (ifname[0]) dev = __dev_get_by_name(net, ifname); |
e7ed828f1 netlink: support ... |
2380 2381 2382 |
else dev = NULL; } |
38f7b870d [RTNETLINK]: Link... |
2383 |
|
ba7d49b1f rtnetlink: provid... |
2384 2385 2386 2387 2388 |
if (dev) { master_dev = netdev_master_upper_dev_get(dev); if (master_dev) m_ops = master_dev->rtnl_link_ops; } |
e0d087af7 rtnetlink: Cleanups |
2389 2390 |
err = validate_linkmsg(dev, tb); if (err < 0) |
1840bb13c [RTNL]: Validate ... |
2391 |
return err; |
38f7b870d [RTNETLINK]: Link... |
2392 2393 |
if (tb[IFLA_LINKINFO]) { err = nla_parse_nested(linkinfo, IFLA_INFO_MAX, |
fceb6435e netlink: pass ext... |
2394 2395 |
tb[IFLA_LINKINFO], ifla_info_policy, NULL); |
38f7b870d [RTNETLINK]: Link... |
2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 |
if (err < 0) return err; } else memset(linkinfo, 0, sizeof(linkinfo)); if (linkinfo[IFLA_INFO_KIND]) { nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind)); ops = rtnl_link_ops_get(kind); } else { kind[0] = '\0'; ops = NULL; } if (1) { |
4e10fd5b4 rtnetlink: avoid ... |
2410 2411 |
struct nlattr *attr[ops ? ops->maxtype + 1 : 1]; struct nlattr *slave_attr[m_ops ? m_ops->slave_maxtype + 1 : 1]; |
ba7d49b1f rtnetlink: provid... |
2412 2413 |
struct nlattr **data = NULL; struct nlattr **slave_data = NULL; |
317f4810e rtnl: allow to cr... |
2414 |
struct net *dest_net, *link_net = NULL; |
38f7b870d [RTNETLINK]: Link... |
2415 2416 2417 2418 2419 |
if (ops) { if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { err = nla_parse_nested(attr, ops->maxtype, linkinfo[IFLA_INFO_DATA], |
fceb6435e netlink: pass ext... |
2420 |
ops->policy, NULL); |
38f7b870d [RTNETLINK]: Link... |
2421 2422 2423 2424 2425 |
if (err < 0) return err; data = attr; } if (ops->validate) { |
a8b8a889e net: add netlink_... |
2426 |
err = ops->validate(tb, data, extack); |
38f7b870d [RTNETLINK]: Link... |
2427 2428 2429 2430 |
if (err < 0) return err; } } |
ba7d49b1f rtnetlink: provid... |
2431 2432 2433 2434 2435 2436 |
if (m_ops) { if (m_ops->slave_maxtype && linkinfo[IFLA_INFO_SLAVE_DATA]) { err = nla_parse_nested(slave_attr, m_ops->slave_maxtype, linkinfo[IFLA_INFO_SLAVE_DATA], |
fceb6435e netlink: pass ext... |
2437 2438 |
m_ops->slave_policy, NULL); |
ba7d49b1f rtnetlink: provid... |
2439 2440 2441 2442 2443 |
if (err < 0) return err; slave_data = slave_attr; } if (m_ops->slave_validate) { |
d116ffc77 net: add netlink_... |
2444 2445 |
err = m_ops->slave_validate(tb, slave_data, extack); |
ba7d49b1f rtnetlink: provid... |
2446 2447 2448 2449 |
if (err < 0) return err; } } |
38f7b870d [RTNETLINK]: Link... |
2450 |
if (dev) { |
90c325e3b rtnl/do_setlink()... |
2451 |
int status = 0; |
38f7b870d [RTNETLINK]: Link... |
2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 |
if (nlh->nlmsg_flags & NLM_F_EXCL) return -EEXIST; if (nlh->nlmsg_flags & NLM_F_REPLACE) return -EOPNOTSUPP; if (linkinfo[IFLA_INFO_DATA]) { if (!ops || ops != dev->rtnl_link_ops || !ops->changelink) return -EOPNOTSUPP; |
ad744b223 net: add netlink_... |
2462 |
err = ops->changelink(dev, tb, data, extack); |
38f7b870d [RTNETLINK]: Link... |
2463 2464 |
if (err < 0) return err; |
ba9989069 rtnl/do_setlink()... |
2465 |
status |= DO_SETLINK_NOTIFY; |
38f7b870d [RTNETLINK]: Link... |
2466 |
} |
ba7d49b1f rtnetlink: provid... |
2467 2468 2469 2470 2471 |
if (linkinfo[IFLA_INFO_SLAVE_DATA]) { if (!m_ops || !m_ops->slave_changelink) return -EOPNOTSUPP; err = m_ops->slave_changelink(master_dev, dev, |
17dd0ec47 net: add netlink_... |
2472 2473 |
tb, slave_data, extack); |
ba7d49b1f rtnetlink: provid... |
2474 2475 |
if (err < 0) return err; |
ba9989069 rtnl/do_setlink()... |
2476 |
status |= DO_SETLINK_NOTIFY; |
ba7d49b1f rtnetlink: provid... |
2477 |
} |
ddf9f9707 xdp: propagate ex... |
2478 2479 |
return do_setlink(skb, dev, ifm, extack, tb, ifname, status); |
38f7b870d [RTNETLINK]: Link... |
2480 |
} |
ffa934f19 rtnetlink: fix li... |
2481 2482 |
if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { if (ifm->ifi_index == 0 && tb[IFLA_GROUP]) |
90f62cf30 net: Use netlink_... |
2483 |
return rtnl_group_changelink(skb, net, |
ffa934f19 rtnetlink: fix li... |
2484 |
nla_get_u32(tb[IFLA_GROUP]), |
ddf9f9707 xdp: propagate ex... |
2485 |
ifm, extack, tb); |
38f7b870d [RTNETLINK]: Link... |
2486 |
return -ENODEV; |
ffa934f19 rtnetlink: fix li... |
2487 |
} |
38f7b870d [RTNETLINK]: Link... |
2488 |
|
160ca0142 rtnetlink: Handle... |
2489 |
if (tb[IFLA_MAP] || tb[IFLA_PROTINFO]) |
38f7b870d [RTNETLINK]: Link... |
2490 2491 2492 |
return -EOPNOTSUPP; if (!ops) { |
95a5afca4 net: Remove CONFI... |
2493 |
#ifdef CONFIG_MODULES |
38f7b870d [RTNETLINK]: Link... |
2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 |
if (kind[0]) { __rtnl_unlock(); request_module("rtnl-link-%s", kind); rtnl_lock(); ops = rtnl_link_ops_get(kind); if (ops) goto replay; } #endif return -EOPNOTSUPP; } |
b0ab2fabb rtnetlink: allow ... |
2505 2506 |
if (!ops->setup) return -EOPNOTSUPP; |
5517750f0 net: rtnetlink - ... |
2507 |
if (!ifname[0]) { |
38f7b870d [RTNETLINK]: Link... |
2508 |
snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); |
5517750f0 net: rtnetlink - ... |
2509 2510 |
name_assign_type = NET_NAME_ENUM; } |
e71992889 [RTNETLINK]: Intr... |
2511 |
|
81adee47d net: Support spec... |
2512 |
dest_net = rtnl_link_get_net(net, tb); |
13ad17745 net: Fix ip link ... |
2513 2514 |
if (IS_ERR(dest_net)) return PTR_ERR(dest_net); |
505ce4154 net: Verify permi... |
2515 2516 2517 |
err = -EPERM; if (!netlink_ns_capable(skb, dest_net->user_ns, CAP_NET_ADMIN)) goto out; |
317f4810e rtnl: allow to cr... |
2518 2519 2520 2521 2522 2523 2524 2525 |
if (tb[IFLA_LINK_NETNSID]) { int id = nla_get_s32(tb[IFLA_LINK_NETNSID]); link_net = get_net_ns_by_id(dest_net, id); if (!link_net) { err = -EINVAL; goto out; } |
06615bed6 net: Verify permi... |
2526 2527 2528 |
err = -EPERM; if (!netlink_ns_capable(skb, link_net->user_ns, CAP_NET_ADMIN)) goto out; |
317f4810e rtnl: allow to cr... |
2529 2530 2531 2532 |
} dev = rtnl_create_link(link_net ? : dest_net, ifname, name_assign_type, ops, tb); |
9c7dafbfa net: Allow to cre... |
2533 |
if (IS_ERR(dev)) { |
e71992889 [RTNETLINK]: Intr... |
2534 |
err = PTR_ERR(dev); |
9c7dafbfa net: Allow to cre... |
2535 2536 2537 2538 |
goto out; } dev->ifindex = ifm->ifi_index; |
0e0eee246 net: correct erro... |
2539 |
if (ops->newlink) { |
7a3f4a185 net: add netlink_... |
2540 2541 |
err = ops->newlink(link_net ? : net, dev, tb, data, extack); |
0e0eee246 net: correct erro... |
2542 |
/* Drivers should call free_netdev() in ->destructor |
e51fb1523 rtnetlink: fix a ... |
2543 2544 |
* and unregister it on failure after registration * so that device could be finally freed in rtnl_unlock. |
0e0eee246 net: correct erro... |
2545 |
*/ |
e51fb1523 rtnetlink: fix a ... |
2546 2547 2548 2549 |
if (err < 0) { /* If device is not registered at all, free it now */ if (dev->reg_state == NETREG_UNINITIALIZED) free_netdev(dev); |
0e0eee246 net: correct erro... |
2550 |
goto out; |
e51fb1523 rtnetlink: fix a ... |
2551 |
} |
0e0eee246 net: correct erro... |
2552 |
} else { |
2d85cba2b [RTNETLINK]: rtnl... |
2553 |
err = register_netdevice(dev); |
0e0eee246 net: correct erro... |
2554 2555 2556 2557 |
if (err < 0) { free_netdev(dev); goto out; } |
fce9b9be8 rtnetlink: remove... |
2558 |
} |
3729d5021 rtnetlink: suppor... |
2559 |
err = rtnl_configure_link(dev, ifm); |
436389007 net: Handle unreg... |
2560 2561 |
if (err < 0) goto out_unregister; |
bdef279b9 rtnl: fix error p... |
2562 |
if (link_net) { |
317f4810e rtnl: allow to cr... |
2563 |
err = dev_change_net_namespace(dev, dest_net, ifname); |
bdef279b9 rtnl: fix error p... |
2564 |
if (err < 0) |
436389007 net: Handle unreg... |
2565 |
goto out_unregister; |
bdef279b9 rtnl: fix error p... |
2566 |
} |
160ca0142 rtnetlink: Handle... |
2567 2568 2569 2570 2571 |
if (tb[IFLA_MASTER]) { err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER])); if (err) goto out_unregister; } |
3729d5021 rtnetlink: suppor... |
2572 |
out: |
317f4810e rtnl: allow to cr... |
2573 2574 |
if (link_net) put_net(link_net); |
81adee47d net: Support spec... |
2575 |
put_net(dest_net); |
38f7b870d [RTNETLINK]: Link... |
2576 |
return err; |
436389007 net: Handle unreg... |
2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 |
out_unregister: if (ops->newlink) { LIST_HEAD(list_kill); ops->dellink(dev, &list_kill); unregister_netdevice_many(&list_kill); } else { unregister_netdevice(dev); } goto out; |
38f7b870d [RTNETLINK]: Link... |
2587 2588 |
} } |
c21ef3e34 net: rtnetlink: p... |
2589 2590 |
static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
711e2c33a [PATCH] WE-20 for... |
2591 |
{ |
3b1e0a655 [NET] NETNS: Omit... |
2592 |
struct net *net = sock_net(skb->sk); |
b60c5115f [NET]: Convert li... |
2593 |
struct ifinfomsg *ifm; |
a3d128912 rtnetlink: rtnl_s... |
2594 |
char ifname[IFNAMSIZ]; |
b60c5115f [NET]: Convert li... |
2595 2596 2597 |
struct nlattr *tb[IFLA_MAX+1]; struct net_device *dev = NULL; struct sk_buff *nskb; |
339bf98ff [NETLINK]: Do pre... |
2598 |
int err; |
115c9b819 rtnetlink: Fix pr... |
2599 |
u32 ext_filter_mask = 0; |
711e2c33a [PATCH] WE-20 for... |
2600 |
|
c21ef3e34 net: rtnetlink: p... |
2601 |
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack); |
b60c5115f [NET]: Convert li... |
2602 |
if (err < 0) |
9918f2309 [RTNETLINK]: Poss... |
2603 |
return err; |
b60c5115f [NET]: Convert li... |
2604 |
|
a3d128912 rtnetlink: rtnl_s... |
2605 2606 |
if (tb[IFLA_IFNAME]) nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); |
115c9b819 rtnetlink: Fix pr... |
2607 2608 |
if (tb[IFLA_EXT_MASK]) ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); |
b60c5115f [NET]: Convert li... |
2609 |
ifm = nlmsg_data(nlh); |
a3d128912 rtnetlink: rtnl_s... |
2610 2611 2612 2613 2614 |
if (ifm->ifi_index > 0) dev = __dev_get_by_index(net, ifm->ifi_index); else if (tb[IFLA_IFNAME]) dev = __dev_get_by_name(net, ifname); else |
711e2c33a [PATCH] WE-20 for... |
2615 |
return -EINVAL; |
711e2c33a [PATCH] WE-20 for... |
2616 |
|
a3d128912 rtnetlink: rtnl_s... |
2617 2618 |
if (dev == NULL) return -ENODEV; |
115c9b819 rtnetlink: Fix pr... |
2619 |
nskb = nlmsg_new(if_nlmsg_size(dev, ext_filter_mask), GFP_KERNEL); |
a3d128912 rtnetlink: rtnl_s... |
2620 2621 |
if (nskb == NULL) return -ENOBUFS; |
b60c5115f [NET]: Convert li... |
2622 |
|
15e473046 netlink: Rename p... |
2623 |
err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).portid, |
3d3ea5af5 rtnl: Add support... |
2624 |
nlh->nlmsg_seq, 0, 0, ext_filter_mask, 0); |
26932566a [NETLINK]: Don't ... |
2625 2626 2627 2628 |
if (err < 0) { /* -EMSGSIZE implies BUG in if_nlmsg_size */ WARN_ON(err == -EMSGSIZE); kfree_skb(nskb); |
a3d128912 rtnetlink: rtnl_s... |
2629 |
} else |
15e473046 netlink: Rename p... |
2630 |
err = rtnl_unicast(nskb, net, NETLINK_CB(skb).portid); |
711e2c33a [PATCH] WE-20 for... |
2631 |
|
b60c5115f [NET]: Convert li... |
2632 |
return err; |
711e2c33a [PATCH] WE-20 for... |
2633 |
} |
711e2c33a [PATCH] WE-20 for... |
2634 |
|
115c9b819 rtnetlink: Fix pr... |
2635 |
static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh) |
c7ac8679b rtnetlink: Comput... |
2636 |
{ |
115c9b819 rtnetlink: Fix pr... |
2637 2638 2639 2640 2641 |
struct net *net = sock_net(skb->sk); struct net_device *dev; struct nlattr *tb[IFLA_MAX+1]; u32 ext_filter_mask = 0; u16 min_ifinfo_dump_size = 0; |
e5eca6d41 rtnetlink: fix us... |
2642 2643 2644 2645 2646 |
int hdrlen; /* Same kernel<->userspace interface hack as in rtnl_dump_ifinfo. */ hdrlen = nlmsg_len(nlh) < sizeof(struct ifinfomsg) ? sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg); |
115c9b819 rtnetlink: Fix pr... |
2647 |
|
fceb6435e netlink: pass ext... |
2648 |
if (nlmsg_parse(nlh, hdrlen, tb, IFLA_MAX, ifla_policy, NULL) >= 0) { |
a4b64fbe4 rtnetlink: fix rt... |
2649 2650 2651 |
if (tb[IFLA_EXT_MASK]) ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); } |
115c9b819 rtnetlink: Fix pr... |
2652 2653 2654 2655 2656 2657 2658 |
if (!ext_filter_mask) return NLMSG_GOODSIZE; /* * traverse the list of net devices and compute the minimum * buffer size based upon the filter mask. */ |
6853dd488 rtnetlink: protec... |
2659 2660 |
rcu_read_lock(); for_each_netdev_rcu(net, dev) { |
115c9b819 rtnetlink: Fix pr... |
2661 2662 2663 2664 |
min_ifinfo_dump_size = max_t(u16, min_ifinfo_dump_size, if_nlmsg_size(dev, ext_filter_mask)); } |
6853dd488 rtnetlink: protec... |
2665 |
rcu_read_unlock(); |
115c9b819 rtnetlink: Fix pr... |
2666 |
|
93af20565 rtnetlink: fix th... |
2667 |
return nlmsg_total_size(min_ifinfo_dump_size); |
c7ac8679b rtnetlink: Comput... |
2668 |
} |
42bad1da5 [NETLINK]: Possib... |
2669 |
static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) |
1da177e4c Linux-2.6.12-rc2 |
2670 2671 2672 2673 2674 2675 |
{ int idx; int s_idx = cb->family; if (s_idx == 0) s_idx = 1; |
6853dd488 rtnetlink: protec... |
2676 |
|
25239cee7 net: rtnetlink: d... |
2677 |
for (idx = 1; idx <= RTNL_FAMILY_MAX; idx++) { |
1da177e4c Linux-2.6.12-rc2 |
2678 |
int type = cb->nlh->nlmsg_type-RTM_BASE; |
6853dd488 rtnetlink: protec... |
2679 2680 |
struct rtnl_link *handlers; rtnl_dumpit_func dumpit; |
1da177e4c Linux-2.6.12-rc2 |
2681 2682 |
if (idx < s_idx || idx == PF_PACKET) continue; |
6853dd488 rtnetlink: protec... |
2683 2684 2685 |
handlers = rtnl_dereference(rtnl_msg_handlers[idx]); if (!handlers) |
1da177e4c Linux-2.6.12-rc2 |
2686 |
continue; |
6853dd488 rtnetlink: protec... |
2687 2688 2689 2690 |
dumpit = READ_ONCE(handlers[type].dumpit); if (!dumpit) continue; |
0465277f6 ipv4: provide add... |
2691 |
if (idx > s_idx) { |
1da177e4c Linux-2.6.12-rc2 |
2692 |
memset(&cb->args[0], 0, sizeof(cb->args)); |
0465277f6 ipv4: provide add... |
2693 2694 2695 |
cb->prev_seq = 0; cb->seq = 0; } |
6853dd488 rtnetlink: protec... |
2696 |
if (dumpit(skb, cb)) |
1da177e4c Linux-2.6.12-rc2 |
2697 2698 2699 2700 2701 2702 |
break; } cb->family = idx; return skb->len; } |
395eea6cc rtnetlink: delay ... |
2703 |
struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev, |
3d3ea5af5 rtnl: Add support... |
2704 2705 |
unsigned int change, u32 event, gfp_t flags) |
1da177e4c Linux-2.6.12-rc2 |
2706 |
{ |
c346dca10 [NET] NETNS: Omit... |
2707 |
struct net *net = dev_net(dev); |
1da177e4c Linux-2.6.12-rc2 |
2708 |
struct sk_buff *skb; |
0ec6d3f46 [NET] link: Conve... |
2709 |
int err = -ENOBUFS; |
c7ac8679b rtnetlink: Comput... |
2710 |
size_t if_info_size; |
1da177e4c Linux-2.6.12-rc2 |
2711 |
|
7f2940540 net: fix rtnl not... |
2712 |
skb = nlmsg_new((if_info_size = if_nlmsg_size(dev, 0)), flags); |
0ec6d3f46 [NET] link: Conve... |
2713 2714 |
if (skb == NULL) goto errout; |
1da177e4c Linux-2.6.12-rc2 |
2715 |
|
3d3ea5af5 rtnl: Add support... |
2716 |
err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0, 0, event); |
26932566a [NETLINK]: Don't ... |
2717 2718 2719 2720 2721 2722 |
if (err < 0) { /* -EMSGSIZE implies BUG in if_nlmsg_size() */ WARN_ON(err == -EMSGSIZE); kfree_skb(skb); goto errout; } |
395eea6cc rtnetlink: delay ... |
2723 |
return skb; |
0ec6d3f46 [NET] link: Conve... |
2724 2725 |
errout: if (err < 0) |
4b3da706b [NET]: Make the n... |
2726 |
rtnl_set_sk_err(net, RTNLGRP_LINK, err); |
395eea6cc rtnetlink: delay ... |
2727 2728 2729 2730 2731 2732 2733 2734 2735 |
return NULL; } void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev, gfp_t flags) { struct net *net = dev_net(dev); rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, flags); } |
3d3ea5af5 rtnl: Add support... |
2736 2737 2738 |
static void rtmsg_ifinfo_event(int type, struct net_device *dev, unsigned int change, u32 event, gfp_t flags) |
395eea6cc rtnetlink: delay ... |
2739 2740 |
{ struct sk_buff *skb; |
ed2a80ab7 rtnl/bond: don't ... |
2741 2742 |
if (dev->reg_state != NETREG_REGISTERED) return; |
3d3ea5af5 rtnl: Add support... |
2743 |
skb = rtmsg_ifinfo_build_skb(type, dev, change, event, flags); |
395eea6cc rtnetlink: delay ... |
2744 2745 |
if (skb) rtmsg_ifinfo_send(skb, dev, flags); |
1da177e4c Linux-2.6.12-rc2 |
2746 |
} |
3d3ea5af5 rtnl: Add support... |
2747 2748 2749 2750 |
void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change, gfp_t flags) { |
8c6c918da rtnetlink: use th... |
2751 |
rtmsg_ifinfo_event(type, dev, change, rtnl_get_event(0), flags); |
3d3ea5af5 rtnl: Add support... |
2752 |
} |
471cb5a33 bonding: remove u... |
2753 |
EXPORT_SYMBOL(rtmsg_ifinfo); |
1da177e4c Linux-2.6.12-rc2 |
2754 |
|
d83b06036 net: add fdb gene... |
2755 2756 |
static int nlmsg_populate_fdb_fill(struct sk_buff *skb, struct net_device *dev, |
1e53d5bb8 net: Pass VLAN ID... |
2757 |
u8 *addr, u16 vid, u32 pid, u32 seq, |
1c104a6be rtnetlink: fix fd... |
2758 |
int type, unsigned int flags, |
b3379041d net: Pass ndm_sta... |
2759 |
int nlflags, u16 ndm_state) |
d83b06036 net: add fdb gene... |
2760 2761 2762 |
{ struct nlmsghdr *nlh; struct ndmsg *ndm; |
1c104a6be rtnetlink: fix fd... |
2763 |
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), nlflags); |
d83b06036 net: add fdb gene... |
2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 |
if (!nlh) return -EMSGSIZE; ndm = nlmsg_data(nlh); ndm->ndm_family = AF_BRIDGE; ndm->ndm_pad1 = 0; ndm->ndm_pad2 = 0; ndm->ndm_flags = flags; ndm->ndm_type = 0; ndm->ndm_ifindex = dev->ifindex; |
b3379041d net: Pass ndm_sta... |
2774 |
ndm->ndm_state = ndm_state; |
d83b06036 net: add fdb gene... |
2775 2776 2777 |
if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) goto nla_put_failure; |
1e53d5bb8 net: Pass VLAN ID... |
2778 2779 2780 |
if (vid) if (nla_put(skb, NDA_VLAN, sizeof(u16), &vid)) goto nla_put_failure; |
d83b06036 net: add fdb gene... |
2781 |
|
053c095a8 netlink: make nlm... |
2782 2783 |
nlmsg_end(skb, nlh); return 0; |
d83b06036 net: add fdb gene... |
2784 2785 2786 2787 2788 |
nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; } |
3ff661c38 net: rtnetlink no... |
2789 2790 |
static inline size_t rtnl_fdb_nlmsg_size(void) { |
f82ef3e10 rtnetlink: fix FD... |
2791 2792 2793 2794 |
return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN) + /* NDA_LLADDR */ nla_total_size(sizeof(u16)) + /* NDA_VLAN */ 0; |
3ff661c38 net: rtnetlink no... |
2795 |
} |
b3379041d net: Pass ndm_sta... |
2796 2797 |
static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type, u16 ndm_state) |
3ff661c38 net: rtnetlink no... |
2798 2799 2800 2801 2802 2803 2804 2805 |
{ struct net *net = dev_net(dev); struct sk_buff *skb; int err = -ENOBUFS; skb = nlmsg_new(rtnl_fdb_nlmsg_size(), GFP_ATOMIC); if (!skb) goto errout; |
1e53d5bb8 net: Pass VLAN ID... |
2806 |
err = nlmsg_populate_fdb_fill(skb, dev, addr, vid, |
b3379041d net: Pass ndm_sta... |
2807 |
0, 0, type, NTF_SELF, 0, ndm_state); |
3ff661c38 net: rtnetlink no... |
2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 |
if (err < 0) { kfree_skb(skb); goto errout; } rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); return; errout: rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); } |
090096bf3 net: generic fdb ... |
2818 2819 2820 2821 2822 2823 |
/** * ndo_dflt_fdb_add - default netdevice operation to add an FDB entry */ int ndo_dflt_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, |
f6f6424ba net: make vid as ... |
2824 |
const unsigned char *addr, u16 vid, |
090096bf3 net: generic fdb ... |
2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 |
u16 flags) { int err = -EINVAL; /* If aging addresses are supported device will need to * implement its own handler for this. */ if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) { pr_info("%s: FDB only supports static addresses ", dev->name); return err; } |
65891feac net: Disallow pro... |
2837 2838 2839 2840 2841 |
if (vid) { pr_info("%s: vlans aren't supported yet for dev_uc|mc_add() ", dev->name); return err; } |
090096bf3 net: generic fdb ... |
2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 |
if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) err = dev_uc_add_excl(dev, addr); else if (is_multicast_ether_addr(addr)) err = dev_mc_add_excl(dev, addr); /* Only return duplicate errors if NLM_F_EXCL is set */ if (err == -EEXIST && !(flags & NLM_F_EXCL)) err = 0; return err; } EXPORT_SYMBOL(ndo_dflt_fdb_add); |
f6f6424ba net: make vid as ... |
2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 |
static int fdb_vid_parse(struct nlattr *vlan_attr, u16 *p_vid) { u16 vid = 0; if (vlan_attr) { if (nla_len(vlan_attr) != sizeof(u16)) { pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid vlan "); return -EINVAL; } vid = nla_get_u16(vlan_attr); if (!vid || vid >= VLAN_VID_MASK) { pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid vlan id %d ", vid); return -EINVAL; } } *p_vid = vid; return 0; } |
c21ef3e34 net: rtnetlink: p... |
2877 2878 |
static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
77162022a net: add generic ... |
2879 2880 |
{ struct net *net = sock_net(skb->sk); |
77162022a net: add generic ... |
2881 2882 2883 2884 |
struct ndmsg *ndm; struct nlattr *tb[NDA_MAX+1]; struct net_device *dev; u8 *addr; |
f6f6424ba net: make vid as ... |
2885 |
u16 vid; |
77162022a net: add generic ... |
2886 |
int err; |
c21ef3e34 net: rtnetlink: p... |
2887 |
err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack); |
77162022a net: add generic ... |
2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 |
if (err < 0) return err; ndm = nlmsg_data(nlh); if (ndm->ndm_ifindex == 0) { pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid ifindex "); return -EINVAL; } dev = __dev_get_by_index(net, ndm->ndm_ifindex); if (dev == NULL) { pr_info("PF_BRIDGE: RTM_NEWNEIGH with unknown ifindex "); return -ENODEV; } if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) { pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid address "); return -EINVAL; } |
4ca72d633 rtnetlink: Disall... |
2910 2911 2912 2913 |
if (dev->type != ARPHRD_ETHER) { NL_SET_ERR_MSG(extack, "FDB add only supported for Ethernet devices"); return -EINVAL; } |
77162022a net: add generic ... |
2914 |
addr = nla_data(tb[NDA_LLADDR]); |
77162022a net: add generic ... |
2915 |
|
f6f6424ba net: make vid as ... |
2916 2917 2918 |
err = fdb_vid_parse(tb[NDA_VLAN], &vid); if (err) return err; |
77162022a net: add generic ... |
2919 2920 2921 2922 2923 |
err = -EOPNOTSUPP; /* Support fdb on master device the net/bridge default case */ if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) && (dev->priv_flags & IFF_BRIDGE_PORT)) { |
898e50617 rtnetlink: remove... |
2924 2925 |
struct net_device *br_dev = netdev_master_upper_dev_get(dev); const struct net_device_ops *ops = br_dev->netdev_ops; |
f6f6424ba net: make vid as ... |
2926 2927 |
err = ops->ndo_fdb_add(ndm, tb, dev, addr, vid, nlh->nlmsg_flags); |
77162022a net: add generic ... |
2928 2929 2930 2931 2932 2933 2934 |
if (err) goto out; else ndm->ndm_flags &= ~NTF_MASTER; } /* Embedded bridge, macvlan, and any other device support */ |
090096bf3 net: generic fdb ... |
2935 2936 2937 |
if ((ndm->ndm_flags & NTF_SELF)) { if (dev->netdev_ops->ndo_fdb_add) err = dev->netdev_ops->ndo_fdb_add(ndm, tb, dev, addr, |
f6f6424ba net: make vid as ... |
2938 |
vid, |
090096bf3 net: generic fdb ... |
2939 2940 |
nlh->nlmsg_flags); else |
f6f6424ba net: make vid as ... |
2941 |
err = ndo_dflt_fdb_add(ndm, tb, dev, addr, vid, |
090096bf3 net: generic fdb ... |
2942 |
nlh->nlmsg_flags); |
77162022a net: add generic ... |
2943 |
|
3ff661c38 net: rtnetlink no... |
2944 |
if (!err) { |
b3379041d net: Pass ndm_sta... |
2945 2946 |
rtnl_fdb_notify(dev, addr, vid, RTM_NEWNEIGH, ndm->ndm_state); |
77162022a net: add generic ... |
2947 |
ndm->ndm_flags &= ~NTF_SELF; |
3ff661c38 net: rtnetlink no... |
2948 |
} |
77162022a net: add generic ... |
2949 2950 2951 2952 |
} out: return err; } |
090096bf3 net: generic fdb ... |
2953 2954 2955 2956 2957 2958 |
/** * ndo_dflt_fdb_del - default netdevice operation to delete an FDB entry */ int ndo_dflt_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, |
f6f6424ba net: make vid as ... |
2959 |
const unsigned char *addr, u16 vid) |
090096bf3 net: generic fdb ... |
2960 |
{ |
c8a89c4a1 rtnetlink: Drop u... |
2961 |
int err = -EINVAL; |
090096bf3 net: generic fdb ... |
2962 2963 2964 2965 |
/* If aging addresses are supported device will need to * implement its own handler for this. */ |
645359930 rtnetlink: Fix in... |
2966 |
if (!(ndm->ndm_state & NUD_PERMANENT)) { |
090096bf3 net: generic fdb ... |
2967 2968 |
pr_info("%s: FDB only supports static addresses ", dev->name); |
c8a89c4a1 rtnetlink: Drop u... |
2969 |
return err; |
090096bf3 net: generic fdb ... |
2970 2971 2972 2973 2974 2975 |
} if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) err = dev_uc_del(dev, addr); else if (is_multicast_ether_addr(addr)) err = dev_mc_del(dev, addr); |
090096bf3 net: generic fdb ... |
2976 2977 2978 2979 |
return err; } EXPORT_SYMBOL(ndo_dflt_fdb_del); |
c21ef3e34 net: rtnetlink: p... |
2980 2981 |
static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
77162022a net: add generic ... |
2982 2983 2984 |
{ struct net *net = sock_net(skb->sk); struct ndmsg *ndm; |
1690be63a bridge: Add vlan ... |
2985 |
struct nlattr *tb[NDA_MAX+1]; |
77162022a net: add generic ... |
2986 2987 2988 |
struct net_device *dev; int err = -EINVAL; __u8 *addr; |
f6f6424ba net: make vid as ... |
2989 |
u16 vid; |
77162022a net: add generic ... |
2990 |
|
90f62cf30 net: Use netlink_... |
2991 |
if (!netlink_capable(skb, CAP_NET_ADMIN)) |
1690be63a bridge: Add vlan ... |
2992 |
return -EPERM; |
c21ef3e34 net: rtnetlink: p... |
2993 |
err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack); |
1690be63a bridge: Add vlan ... |
2994 2995 |
if (err < 0) return err; |
77162022a net: add generic ... |
2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 |
ndm = nlmsg_data(nlh); if (ndm->ndm_ifindex == 0) { pr_info("PF_BRIDGE: RTM_DELNEIGH with invalid ifindex "); return -EINVAL; } dev = __dev_get_by_index(net, ndm->ndm_ifindex); if (dev == NULL) { pr_info("PF_BRIDGE: RTM_DELNEIGH with unknown ifindex "); return -ENODEV; } |
1690be63a bridge: Add vlan ... |
3010 3011 3012 3013 3014 |
if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) { pr_info("PF_BRIDGE: RTM_DELNEIGH with invalid address "); return -EINVAL; } |
4ca72d633 rtnetlink: Disall... |
3015 3016 3017 3018 |
if (dev->type != ARPHRD_ETHER) { NL_SET_ERR_MSG(extack, "FDB delete only supported for Ethernet devices"); return -EINVAL; } |
1690be63a bridge: Add vlan ... |
3019 |
addr = nla_data(tb[NDA_LLADDR]); |
77162022a net: add generic ... |
3020 |
|
f6f6424ba net: make vid as ... |
3021 3022 3023 |
err = fdb_vid_parse(tb[NDA_VLAN], &vid); if (err) return err; |
77162022a net: add generic ... |
3024 3025 3026 3027 3028 |
err = -EOPNOTSUPP; /* Support fdb on master device the net/bridge default case */ if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) && (dev->priv_flags & IFF_BRIDGE_PORT)) { |
898e50617 rtnetlink: remove... |
3029 3030 |
struct net_device *br_dev = netdev_master_upper_dev_get(dev); const struct net_device_ops *ops = br_dev->netdev_ops; |
77162022a net: add generic ... |
3031 |
|
898e50617 rtnetlink: remove... |
3032 |
if (ops->ndo_fdb_del) |
f6f6424ba net: make vid as ... |
3033 |
err = ops->ndo_fdb_del(ndm, tb, dev, addr, vid); |
77162022a net: add generic ... |
3034 3035 3036 3037 3038 3039 3040 3041 |
if (err) goto out; else ndm->ndm_flags &= ~NTF_MASTER; } /* Embedded bridge, macvlan, and any other device support */ |
090096bf3 net: generic fdb ... |
3042 3043 |
if (ndm->ndm_flags & NTF_SELF) { if (dev->netdev_ops->ndo_fdb_del) |
f6f6424ba net: make vid as ... |
3044 3045 |
err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr, vid); |
090096bf3 net: generic fdb ... |
3046 |
else |
f6f6424ba net: make vid as ... |
3047 |
err = ndo_dflt_fdb_del(ndm, tb, dev, addr, vid); |
77162022a net: add generic ... |
3048 |
|
3ff661c38 net: rtnetlink no... |
3049 |
if (!err) { |
b3379041d net: Pass ndm_sta... |
3050 3051 |
rtnl_fdb_notify(dev, addr, vid, RTM_DELNEIGH, ndm->ndm_state); |
77162022a net: add generic ... |
3052 |
ndm->ndm_flags &= ~NTF_SELF; |
3ff661c38 net: rtnetlink no... |
3053 |
} |
77162022a net: add generic ... |
3054 3055 3056 3057 |
} out: return err; } |
d83b06036 net: add fdb gene... |
3058 3059 3060 3061 3062 3063 3064 3065 |
static int nlmsg_populate_fdb(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev, int *idx, struct netdev_hw_addr_list *list) { struct netdev_hw_addr *ha; int err; |
15e473046 netlink: Rename p... |
3066 |
u32 portid, seq; |
d83b06036 net: add fdb gene... |
3067 |
|
15e473046 netlink: Rename p... |
3068 |
portid = NETLINK_CB(cb->skb).portid; |
d83b06036 net: add fdb gene... |
3069 3070 3071 |
seq = cb->nlh->nlmsg_seq; list_for_each_entry(ha, &list->list, list) { |
d297653dd rtnetlink: fdb du... |
3072 |
if (*idx < cb->args[2]) |
d83b06036 net: add fdb gene... |
3073 |
goto skip; |
1e53d5bb8 net: Pass VLAN ID... |
3074 |
err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, 0, |
a7a558fe4 rtnetlink: Use nl... |
3075 |
portid, seq, |
1c104a6be rtnetlink: fix fd... |
3076 |
RTM_NEWNEIGH, NTF_SELF, |
b3379041d net: Pass ndm_sta... |
3077 |
NLM_F_MULTI, NUD_PERMANENT); |
d83b06036 net: add fdb gene... |
3078 3079 3080 3081 3082 3083 3084 3085 3086 |
if (err < 0) return err; skip: *idx += 1; } return 0; } /** |
2c53040f0 net: Fix (nearly-... |
3087 |
* ndo_dflt_fdb_dump - default netdevice operation to dump an FDB table. |
d83b06036 net: add fdb gene... |
3088 3089 3090 3091 |
* @nlh: netlink message header * @dev: netdevice * * Default netdevice operation to dump the existing unicast address list. |
91f3e7b17 net: rtnetlink: f... |
3092 |
* Returns number of addresses from list put in skb. |
d83b06036 net: add fdb gene... |
3093 3094 3095 3096 |
*/ int ndo_dflt_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev, |
5d5eacb34 bridge: fdb dumpi... |
3097 |
struct net_device *filter_dev, |
d297653dd rtnetlink: fdb du... |
3098 |
int *idx) |
d83b06036 net: add fdb gene... |
3099 3100 |
{ int err; |
22fa15e6f rtnetlink: ndo_df... |
3101 3102 |
if (dev->type != ARPHRD_ETHER) return -EINVAL; |
d83b06036 net: add fdb gene... |
3103 |
netif_addr_lock_bh(dev); |
d297653dd rtnetlink: fdb du... |
3104 |
err = nlmsg_populate_fdb(skb, cb, dev, idx, &dev->uc); |
d83b06036 net: add fdb gene... |
3105 3106 |
if (err) goto out; |
2934c9dbd rtnetlink: return... |
3107 |
err = nlmsg_populate_fdb(skb, cb, dev, idx, &dev->mc); |
d83b06036 net: add fdb gene... |
3108 3109 |
out: netif_addr_unlock_bh(dev); |
d297653dd rtnetlink: fdb du... |
3110 |
return err; |
d83b06036 net: add fdb gene... |
3111 3112 |
} EXPORT_SYMBOL(ndo_dflt_fdb_dump); |
77162022a net: add generic ... |
3113 3114 |
static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) { |
77162022a net: add generic ... |
3115 |
struct net_device *dev; |
5e6d24358 bridge: netlink d... |
3116 |
struct nlattr *tb[IFLA_MAX+1]; |
5e6d24358 bridge: netlink d... |
3117 3118 3119 3120 3121 |
struct net_device *br_dev = NULL; const struct net_device_ops *ops = NULL; const struct net_device_ops *cops = NULL; struct ifinfomsg *ifm = nlmsg_data(cb->nlh); struct net *net = sock_net(skb->sk); |
d297653dd rtnetlink: fdb du... |
3122 |
struct hlist_head *head; |
5e6d24358 bridge: netlink d... |
3123 3124 |
int brport_idx = 0; int br_idx = 0; |
d297653dd rtnetlink: fdb du... |
3125 3126 3127 3128 |
int h, s_h; int idx = 0, s_idx; int err = 0; int fidx = 0; |
5e6d24358 bridge: netlink d... |
3129 |
|
5f999abba rtnetlink: fix rt... |
3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 |
/* A hack to preserve kernel<->userspace interface. * Before Linux v4.12 this code accepted ndmsg since iproute2 v3.3.0. * However, ndmsg is shorter than ifinfomsg thus nlmsg_parse() bails. * So, check for ndmsg with an optional u32 attribute (not used here). * Fortunately these sizes don't conflict with the size of ifinfomsg * with an optional attribute. */ if (nlmsg_len(cb->nlh) != sizeof(struct ndmsg) && (nlmsg_len(cb->nlh) != sizeof(struct ndmsg) + nla_attr_size(sizeof(u32)))) { err = nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, ifla_policy, NULL); if (err < 0) { return -EINVAL; } else if (err == 0) { if (tb[IFLA_MASTER]) br_idx = nla_get_u32(tb[IFLA_MASTER]); } |
5e6d24358 bridge: netlink d... |
3148 |
|
5f999abba rtnetlink: fix rt... |
3149 3150 |
brport_idx = ifm->ifi_index; } |
5e6d24358 bridge: netlink d... |
3151 3152 3153 3154 3155 3156 3157 |
if (br_idx) { br_dev = __dev_get_by_index(net, br_idx); if (!br_dev) return -ENODEV; ops = br_dev->netdev_ops; |
5e6d24358 bridge: netlink d... |
3158 |
} |
d297653dd rtnetlink: fdb du... |
3159 3160 |
s_h = cb->args[0]; s_idx = cb->args[1]; |
5e6d24358 bridge: netlink d... |
3161 |
|
d297653dd rtnetlink: fdb du... |
3162 3163 3164 3165 |
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { idx = 0; head = &net->dev_index_head[h]; hlist_for_each_entry(dev, head, index_hlist) { |
5e6d24358 bridge: netlink d... |
3166 |
|
d297653dd rtnetlink: fdb du... |
3167 |
if (brport_idx && (dev->ifindex != brport_idx)) |
5e6d24358 bridge: netlink d... |
3168 |
continue; |
d297653dd rtnetlink: fdb du... |
3169 3170 3171 3172 3173 3174 3175 3176 3177 |
if (!br_idx) { /* user did not specify a specific bridge */ if (dev->priv_flags & IFF_BRIDGE_PORT) { br_dev = netdev_master_upper_dev_get(dev); cops = br_dev->netdev_ops; } } else { if (dev != br_dev && !(dev->priv_flags & IFF_BRIDGE_PORT)) continue; |
5e6d24358 bridge: netlink d... |
3178 |
|
d297653dd rtnetlink: fdb du... |
3179 3180 3181 3182 3183 |
if (br_dev != netdev_master_upper_dev_get(dev) && !(dev->priv_flags & IFF_EBRIDGE)) continue; cops = ops; } |
77162022a net: add generic ... |
3184 |
|
d297653dd rtnetlink: fdb du... |
3185 3186 |
if (idx < s_idx) goto cont; |
77162022a net: add generic ... |
3187 |
|
d297653dd rtnetlink: fdb du... |
3188 3189 3190 3191 3192 3193 3194 3195 3196 |
if (dev->priv_flags & IFF_BRIDGE_PORT) { if (cops && cops->ndo_fdb_dump) { err = cops->ndo_fdb_dump(skb, cb, br_dev, dev, &fidx); if (err == -EMSGSIZE) goto out; } } |
5e6d24358 bridge: netlink d... |
3197 |
|
d297653dd rtnetlink: fdb du... |
3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 |
if (dev->netdev_ops->ndo_fdb_dump) err = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, NULL, &fidx); else err = ndo_dflt_fdb_dump(skb, cb, dev, NULL, &fidx); if (err == -EMSGSIZE) goto out; cops = NULL; /* reset fdb offset to 0 for rest of the interfaces */ cb->args[2] = 0; fidx = 0; cont: idx++; } |
77162022a net: add generic ... |
3216 |
} |
77162022a net: add generic ... |
3217 |
|
d297653dd rtnetlink: fdb du... |
3218 3219 3220 3221 |
out: cb->args[0] = h; cb->args[1] = idx; cb->args[2] = fidx; |
77162022a net: add generic ... |
3222 3223 |
return skb->len; } |
2c3c031c8 bridge: add brpor... |
3224 3225 3226 3227 3228 3229 3230 |
static int brport_nla_put_flag(struct sk_buff *skb, u32 flags, u32 mask, unsigned int attrnum, unsigned int flag) { if (mask & flag) return nla_put_u8(skb, attrnum, !!(flags & flag)); return 0; } |
815cccbf1 ixgbe: add setlin... |
3231 |
int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, |
2c3c031c8 bridge: add brpor... |
3232 |
struct net_device *dev, u16 mode, |
7d4f8d871 switchdev; add VL... |
3233 3234 3235 3236 3237 |
u32 flags, u32 mask, int nlflags, u32 filter_mask, int (*vlan_fill)(struct sk_buff *skb, struct net_device *dev, u32 filter_mask)) |
815cccbf1 ixgbe: add setlin... |
3238 3239 3240 3241 |
{ struct nlmsghdr *nlh; struct ifinfomsg *ifm; struct nlattr *br_afspec; |
2c3c031c8 bridge: add brpor... |
3242 |
struct nlattr *protinfo; |
815cccbf1 ixgbe: add setlin... |
3243 |
u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; |
898e50617 rtnetlink: remove... |
3244 |
struct net_device *br_dev = netdev_master_upper_dev_get(dev); |
7d4f8d871 switchdev; add VL... |
3245 |
int err = 0; |
815cccbf1 ixgbe: add setlin... |
3246 |
|
46c264daa bridge/nl: remove... |
3247 |
nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), nlflags); |
815cccbf1 ixgbe: add setlin... |
3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 |
if (nlh == NULL) return -EMSGSIZE; ifm = nlmsg_data(nlh); ifm->ifi_family = AF_BRIDGE; ifm->__ifi_pad = 0; ifm->ifi_type = dev->type; ifm->ifi_index = dev->ifindex; ifm->ifi_flags = dev_get_flags(dev); ifm->ifi_change = 0; if (nla_put_string(skb, IFLA_IFNAME, dev->name) || nla_put_u32(skb, IFLA_MTU, dev->mtu) || nla_put_u8(skb, IFLA_OPERSTATE, operstate) || |
898e50617 rtnetlink: remove... |
3263 3264 |
(br_dev && nla_put_u32(skb, IFLA_MASTER, br_dev->ifindex)) || |
815cccbf1 ixgbe: add setlin... |
3265 3266 |
(dev->addr_len && nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) || |
a54acb3a6 dev: introduce de... |
3267 3268 |
(dev->ifindex != dev_get_iflink(dev) && nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev)))) |
815cccbf1 ixgbe: add setlin... |
3269 3270 3271 3272 3273 |
goto nla_put_failure; br_afspec = nla_nest_start(skb, IFLA_AF_SPEC); if (!br_afspec) goto nla_put_failure; |
1d460b988 rocker: remove sw... |
3274 |
if (nla_put_u16(skb, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF)) { |
815cccbf1 ixgbe: add setlin... |
3275 3276 3277 |
nla_nest_cancel(skb, br_afspec); goto nla_put_failure; } |
1d460b988 rocker: remove sw... |
3278 3279 3280 3281 3282 3283 3284 |
if (mode != BRIDGE_MODE_UNDEF) { if (nla_put_u16(skb, IFLA_BRIDGE_MODE, mode)) { nla_nest_cancel(skb, br_afspec); goto nla_put_failure; } } |
7d4f8d871 switchdev; add VL... |
3285 3286 3287 3288 3289 3290 3291 |
if (vlan_fill) { err = vlan_fill(skb, dev, filter_mask); if (err) { nla_nest_cancel(skb, br_afspec); goto nla_put_failure; } } |
815cccbf1 ixgbe: add setlin... |
3292 |
nla_nest_end(skb, br_afspec); |
2c3c031c8 bridge: add brpor... |
3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 |
protinfo = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED); if (!protinfo) goto nla_put_failure; if (brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE) || brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_GUARD, BR_BPDU_GUARD) || brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE) || brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK) || brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_LEARNING, BR_LEARNING) || brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_LEARNING_SYNC, BR_LEARNING_SYNC) || brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD) || brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_PROXYARP, BR_PROXYARP)) { nla_nest_cancel(skb, protinfo); goto nla_put_failure; } nla_nest_end(skb, protinfo); |
053c095a8 netlink: make nlm... |
3319 3320 |
nlmsg_end(skb, nlh); return 0; |
815cccbf1 ixgbe: add setlin... |
3321 3322 |
nla_put_failure: nlmsg_cancel(skb, nlh); |
7d4f8d871 switchdev; add VL... |
3323 |
return err ? err : -EMSGSIZE; |
815cccbf1 ixgbe: add setlin... |
3324 |
} |
7d4f8d871 switchdev; add VL... |
3325 |
EXPORT_SYMBOL_GPL(ndo_dflt_bridge_getlink); |
815cccbf1 ixgbe: add setlin... |
3326 |
|
e5a55a898 net: create gener... |
3327 3328 3329 3330 3331 3332 3333 |
static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); struct net_device *dev; int idx = 0; u32 portid = NETLINK_CB(cb->skb).portid; u32 seq = cb->nlh->nlmsg_seq; |
6cbdceeb1 bridge: Dump vlan... |
3334 |
u32 filter_mask = 0; |
d64f69b03 rtnetlink: catch ... |
3335 |
int err; |
6cbdceeb1 bridge: Dump vlan... |
3336 |
|
aa68c20ff bridge: Sanitize ... |
3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 |
if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) { struct nlattr *extfilt; extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg), IFLA_EXT_MASK); if (extfilt) { if (nla_len(extfilt) < sizeof(filter_mask)) return -EINVAL; filter_mask = nla_get_u32(extfilt); } } |
e5a55a898 net: create gener... |
3349 3350 3351 3352 |
rcu_read_lock(); for_each_netdev_rcu(net, dev) { const struct net_device_ops *ops = dev->netdev_ops; |
898e50617 rtnetlink: remove... |
3353 |
struct net_device *br_dev = netdev_master_upper_dev_get(dev); |
e5a55a898 net: create gener... |
3354 |
|
898e50617 rtnetlink: remove... |
3355 |
if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) { |
d64f69b03 rtnetlink: catch ... |
3356 3357 3358 3359 |
if (idx >= cb->args[0]) { err = br_dev->netdev_ops->ndo_bridge_getlink( skb, portid, seq, dev, filter_mask, NLM_F_MULTI); |
f6c5775ff net: Improve hand... |
3360 3361 3362 3363 3364 3365 |
if (err < 0 && err != -EOPNOTSUPP) { if (likely(skb->len)) break; goto out_err; } |
d64f69b03 rtnetlink: catch ... |
3366 |
} |
25b1e6792 net: Fix continue... |
3367 |
idx++; |
e5a55a898 net: create gener... |
3368 3369 3370 |
} if (ops->ndo_bridge_getlink) { |
d64f69b03 rtnetlink: catch ... |
3371 3372 3373 3374 3375 |
if (idx >= cb->args[0]) { err = ops->ndo_bridge_getlink(skb, portid, seq, dev, filter_mask, NLM_F_MULTI); |
f6c5775ff net: Improve hand... |
3376 3377 3378 3379 3380 3381 |
if (err < 0 && err != -EOPNOTSUPP) { if (likely(skb->len)) break; goto out_err; } |
d64f69b03 rtnetlink: catch ... |
3382 |
} |
25b1e6792 net: Fix continue... |
3383 |
idx++; |
e5a55a898 net: create gener... |
3384 3385 |
} } |
f6c5775ff net: Improve hand... |
3386 3387 |
err = skb->len; out_err: |
e5a55a898 net: create gener... |
3388 3389 |
rcu_read_unlock(); cb->args[0] = idx; |
f6c5775ff net: Improve hand... |
3390 |
return err; |
e5a55a898 net: create gener... |
3391 |
} |
2469ffd72 net: set and quer... |
3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 |
static inline size_t bridge_nlmsg_size(void) { return NLMSG_ALIGN(sizeof(struct ifinfomsg)) + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ + nla_total_size(sizeof(u32)) /* IFLA_MASTER */ + nla_total_size(sizeof(u32)) /* IFLA_MTU */ + nla_total_size(sizeof(u32)) /* IFLA_LINK */ + nla_total_size(sizeof(u32)) /* IFLA_OPERSTATE */ + nla_total_size(sizeof(u8)) /* IFLA_PROTINFO */ + nla_total_size(sizeof(struct nlattr)) /* IFLA_AF_SPEC */ + nla_total_size(sizeof(u16)) /* IFLA_BRIDGE_FLAGS */ + nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_MODE */ } |
02dba4388 bridge: fix setli... |
3406 |
static int rtnl_bridge_notify(struct net_device *dev) |
2469ffd72 net: set and quer... |
3407 3408 |
{ struct net *net = dev_net(dev); |
2469ffd72 net: set and quer... |
3409 3410 |
struct sk_buff *skb; int err = -EOPNOTSUPP; |
02dba4388 bridge: fix setli... |
3411 3412 |
if (!dev->netdev_ops->ndo_bridge_getlink) return 0; |
2469ffd72 net: set and quer... |
3413 3414 3415 3416 3417 |
skb = nlmsg_new(bridge_nlmsg_size(), GFP_ATOMIC); if (!skb) { err = -ENOMEM; goto errout; } |
46c264daa bridge/nl: remove... |
3418 |
err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0); |
02dba4388 bridge: fix setli... |
3419 3420 |
if (err < 0) goto errout; |
2469ffd72 net: set and quer... |
3421 |
|
59ccaaaa4 bridge: dont send... |
3422 3423 |
if (!skb->len) goto errout; |
2469ffd72 net: set and quer... |
3424 3425 3426 3427 3428 |
rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); return 0; errout: WARN_ON(err == -EMSGSIZE); kfree_skb(skb); |
59ccaaaa4 bridge: dont send... |
3429 3430 |
if (err) rtnl_set_sk_err(net, RTNLGRP_LINK, err); |
2469ffd72 net: set and quer... |
3431 3432 |
return err; } |
c21ef3e34 net: rtnetlink: p... |
3433 3434 |
static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
e5a55a898 net: create gener... |
3435 3436 3437 3438 |
{ struct net *net = sock_net(skb->sk); struct ifinfomsg *ifm; struct net_device *dev; |
2469ffd72 net: set and quer... |
3439 3440 |
struct nlattr *br_spec, *attr = NULL; int rem, err = -EOPNOTSUPP; |
4de8b4137 bridge: remove of... |
3441 |
u16 flags = 0; |
c38e01b8b net: fix bridge n... |
3442 |
bool have_flags = false; |
e5a55a898 net: create gener... |
3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 |
if (nlmsg_len(nlh) < sizeof(*ifm)) return -EINVAL; ifm = nlmsg_data(nlh); if (ifm->ifi_family != AF_BRIDGE) return -EPFNOSUPPORT; dev = __dev_get_by_index(net, ifm->ifi_index); if (!dev) { pr_info("PF_BRIDGE: RTM_SETLINK with unknown ifindex "); return -ENODEV; } |
2469ffd72 net: set and quer... |
3457 3458 3459 3460 |
br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); if (br_spec) { nla_for_each_nested(attr, br_spec, rem) { if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { |
6e8d1c554 bridge: Validate ... |
3461 3462 |
if (nla_len(attr) < sizeof(flags)) return -EINVAL; |
c38e01b8b net: fix bridge n... |
3463 |
have_flags = true; |
2469ffd72 net: set and quer... |
3464 3465 3466 3467 3468 3469 3470 |
flags = nla_get_u16(attr); break; } } } if (!flags || (flags & BRIDGE_FLAGS_MASTER)) { |
898e50617 rtnetlink: remove... |
3471 3472 3473 |
struct net_device *br_dev = netdev_master_upper_dev_get(dev); if (!br_dev || !br_dev->netdev_ops->ndo_bridge_setlink) { |
2469ffd72 net: set and quer... |
3474 3475 3476 |
err = -EOPNOTSUPP; goto out; } |
add511b38 bridge: add flags... |
3477 |
err = br_dev->netdev_ops->ndo_bridge_setlink(dev, nlh, flags); |
e5a55a898 net: create gener... |
3478 3479 |
if (err) goto out; |
2469ffd72 net: set and quer... |
3480 3481 |
flags &= ~BRIDGE_FLAGS_MASTER; |
e5a55a898 net: create gener... |
3482 |
} |
2469ffd72 net: set and quer... |
3483 3484 3485 3486 |
if ((flags & BRIDGE_FLAGS_SELF)) { if (!dev->netdev_ops->ndo_bridge_setlink) err = -EOPNOTSUPP; else |
add511b38 bridge: add flags... |
3487 3488 |
err = dev->netdev_ops->ndo_bridge_setlink(dev, nlh, flags); |
02dba4388 bridge: fix setli... |
3489 |
if (!err) { |
2469ffd72 net: set and quer... |
3490 |
flags &= ~BRIDGE_FLAGS_SELF; |
02dba4388 bridge: fix setli... |
3491 3492 3493 3494 3495 3496 |
/* Generate event to notify upper layer of bridge * change */ err = rtnl_bridge_notify(dev); } |
2469ffd72 net: set and quer... |
3497 |
} |
e5a55a898 net: create gener... |
3498 |
|
c38e01b8b net: fix bridge n... |
3499 |
if (have_flags) |
2469ffd72 net: set and quer... |
3500 |
memcpy(nla_data(attr), &flags, sizeof(flags)); |
e5a55a898 net: create gener... |
3501 3502 3503 |
out: return err; } |
c21ef3e34 net: rtnetlink: p... |
3504 3505 |
static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
407af3299 bridge: Add netli... |
3506 3507 3508 3509 3510 3511 |
{ struct net *net = sock_net(skb->sk); struct ifinfomsg *ifm; struct net_device *dev; struct nlattr *br_spec, *attr = NULL; int rem, err = -EOPNOTSUPP; |
4de8b4137 bridge: remove of... |
3512 |
u16 flags = 0; |
407af3299 bridge: Add netli... |
3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 |
bool have_flags = false; if (nlmsg_len(nlh) < sizeof(*ifm)) return -EINVAL; ifm = nlmsg_data(nlh); if (ifm->ifi_family != AF_BRIDGE) return -EPFNOSUPPORT; dev = __dev_get_by_index(net, ifm->ifi_index); if (!dev) { pr_info("PF_BRIDGE: RTM_SETLINK with unknown ifindex "); return -ENODEV; } br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); if (br_spec) { nla_for_each_nested(attr, br_spec, rem) { if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { |
6e8d1c554 bridge: Validate ... |
3533 3534 |
if (nla_len(attr) < sizeof(flags)) return -EINVAL; |
407af3299 bridge: Add netli... |
3535 3536 3537 3538 3539 3540 |
have_flags = true; flags = nla_get_u16(attr); break; } } } |
407af3299 bridge: Add netli... |
3541 3542 3543 3544 3545 3546 3547 |
if (!flags || (flags & BRIDGE_FLAGS_MASTER)) { struct net_device *br_dev = netdev_master_upper_dev_get(dev); if (!br_dev || !br_dev->netdev_ops->ndo_bridge_dellink) { err = -EOPNOTSUPP; goto out; } |
add511b38 bridge: add flags... |
3548 |
err = br_dev->netdev_ops->ndo_bridge_dellink(dev, nlh, flags); |
407af3299 bridge: Add netli... |
3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 |
if (err) goto out; flags &= ~BRIDGE_FLAGS_MASTER; } if ((flags & BRIDGE_FLAGS_SELF)) { if (!dev->netdev_ops->ndo_bridge_dellink) err = -EOPNOTSUPP; else |
add511b38 bridge: add flags... |
3559 3560 |
err = dev->netdev_ops->ndo_bridge_dellink(dev, nlh, flags); |
407af3299 bridge: Add netli... |
3561 |
|
02dba4388 bridge: fix setli... |
3562 |
if (!err) { |
407af3299 bridge: Add netli... |
3563 |
flags &= ~BRIDGE_FLAGS_SELF; |
02dba4388 bridge: fix setli... |
3564 3565 3566 3567 3568 3569 |
/* Generate event to notify upper layer of bridge * change */ err = rtnl_bridge_notify(dev); } |
407af3299 bridge: Add netli... |
3570 3571 3572 3573 |
} if (have_flags) memcpy(nla_data(attr), &flags, sizeof(flags)); |
407af3299 bridge: Add netli... |
3574 3575 3576 |
out: return err; } |
e8872a25a net: rtnetlink: a... |
3577 3578 3579 3580 3581 |
static bool stats_attr_valid(unsigned int mask, int attrid, int idxattr) { return (mask & IFLA_STATS_FILTER_BIT(attrid)) && (!idxattr || idxattr == attrid); } |
69ae6ad2f net: core: Add of... |
3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 |
#define IFLA_OFFLOAD_XSTATS_FIRST (IFLA_OFFLOAD_XSTATS_UNSPEC + 1) static int rtnl_get_offload_stats_attr_size(int attr_id) { switch (attr_id) { case IFLA_OFFLOAD_XSTATS_CPU_HIT: return sizeof(struct rtnl_link_stats64); } return 0; } static int rtnl_get_offload_stats(struct sk_buff *skb, struct net_device *dev, int *prividx) { struct nlattr *attr = NULL; int attr_id, size; void *attr_data; int err; if (!(dev->netdev_ops && dev->netdev_ops->ndo_has_offload_stats && dev->netdev_ops->ndo_get_offload_stats)) return -ENODATA; for (attr_id = IFLA_OFFLOAD_XSTATS_FIRST; attr_id <= IFLA_OFFLOAD_XSTATS_MAX; attr_id++) { if (attr_id < *prividx) continue; size = rtnl_get_offload_stats_attr_size(attr_id); if (!size) continue; |
3df5b3c67 net: Add net-devi... |
3613 |
if (!dev->netdev_ops->ndo_has_offload_stats(dev, attr_id)) |
69ae6ad2f net: core: Add of... |
3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 |
continue; attr = nla_reserve_64bit(skb, attr_id, size, IFLA_OFFLOAD_XSTATS_UNSPEC); if (!attr) goto nla_put_failure; attr_data = nla_data(attr); memset(attr_data, 0, size); err = dev->netdev_ops->ndo_get_offload_stats(attr_id, dev, attr_data); if (err) goto get_offload_stats_failure; } if (!attr) return -ENODATA; *prividx = 0; return 0; nla_put_failure: err = -EMSGSIZE; get_offload_stats_failure: *prividx = attr_id; return err; } static int rtnl_get_offload_stats_size(const struct net_device *dev) { int nla_size = 0; int attr_id; int size; if (!(dev->netdev_ops && dev->netdev_ops->ndo_has_offload_stats && dev->netdev_ops->ndo_get_offload_stats)) return 0; for (attr_id = IFLA_OFFLOAD_XSTATS_FIRST; attr_id <= IFLA_OFFLOAD_XSTATS_MAX; attr_id++) { |
3df5b3c67 net: Add net-devi... |
3654 |
if (!dev->netdev_ops->ndo_has_offload_stats(dev, attr_id)) |
69ae6ad2f net: core: Add of... |
3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 |
continue; size = rtnl_get_offload_stats_attr_size(attr_id); nla_size += nla_total_size_64bit(size); } if (nla_size != 0) nla_size += nla_total_size(0); return nla_size; } |
10c9ead9f rtnetlink: add ne... |
3665 3666 |
static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev, int type, u32 pid, u32 seq, u32 change, |
e8872a25a net: rtnetlink: a... |
3667 3668 |
unsigned int flags, unsigned int filter_mask, int *idxattr, int *prividx) |
10c9ead9f rtnetlink: add ne... |
3669 3670 3671 3672 |
{ struct if_stats_msg *ifsm; struct nlmsghdr *nlh; struct nlattr *attr; |
e8872a25a net: rtnetlink: a... |
3673 |
int s_prividx = *prividx; |
69ae6ad2f net: core: Add of... |
3674 |
int err; |
10c9ead9f rtnetlink: add ne... |
3675 3676 3677 3678 3679 3680 3681 3682 |
ASSERT_RTNL(); nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifsm), flags); if (!nlh) return -EMSGSIZE; ifsm = nlmsg_data(nlh); |
ce024f42c net: rtnetlink: f... |
3683 3684 3685 |
ifsm->family = PF_UNSPEC; ifsm->pad1 = 0; ifsm->pad2 = 0; |
10c9ead9f rtnetlink: add ne... |
3686 3687 |
ifsm->ifindex = dev->ifindex; ifsm->filter_mask = filter_mask; |
e8872a25a net: rtnetlink: a... |
3688 |
if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_64, *idxattr)) { |
10c9ead9f rtnetlink: add ne... |
3689 |
struct rtnl_link_stats64 *sp; |
10c9ead9f rtnetlink: add ne... |
3690 |
|
58414d32a rtnl: use the new... |
3691 3692 3693 |
attr = nla_reserve_64bit(skb, IFLA_STATS_LINK_64, sizeof(struct rtnl_link_stats64), IFLA_STATS_UNSPEC); |
10c9ead9f rtnetlink: add ne... |
3694 3695 3696 3697 3698 3699 |
if (!attr) goto nla_put_failure; sp = nla_data(attr); dev_get_stats(dev, sp); } |
97a47facf net: rtnetlink: a... |
3700 3701 3702 3703 |
if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_XSTATS, *idxattr)) { const struct rtnl_link_ops *ops = dev->rtnl_link_ops; if (ops && ops->fill_linkxstats) { |
97a47facf net: rtnetlink: a... |
3704 3705 3706 3707 3708 |
*idxattr = IFLA_STATS_LINK_XSTATS; attr = nla_nest_start(skb, IFLA_STATS_LINK_XSTATS); if (!attr) goto nla_put_failure; |
80e73cc56 net: rtnetlink: a... |
3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 |
err = ops->fill_linkxstats(skb, dev, prividx, *idxattr); nla_nest_end(skb, attr); if (err) goto nla_put_failure; *idxattr = 0; } } if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_XSTATS_SLAVE, *idxattr)) { const struct rtnl_link_ops *ops = NULL; const struct net_device *master; master = netdev_master_upper_dev_get(dev); if (master) ops = master->rtnl_link_ops; if (ops && ops->fill_linkxstats) { |
80e73cc56 net: rtnetlink: a... |
3726 3727 3728 3729 3730 3731 3732 |
*idxattr = IFLA_STATS_LINK_XSTATS_SLAVE; attr = nla_nest_start(skb, IFLA_STATS_LINK_XSTATS_SLAVE); if (!attr) goto nla_put_failure; err = ops->fill_linkxstats(skb, dev, prividx, *idxattr); |
97a47facf net: rtnetlink: a... |
3733 3734 3735 3736 3737 3738 |
nla_nest_end(skb, attr); if (err) goto nla_put_failure; *idxattr = 0; } } |
69ae6ad2f net: core: Add of... |
3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 |
if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, *idxattr)) { *idxattr = IFLA_STATS_LINK_OFFLOAD_XSTATS; attr = nla_nest_start(skb, IFLA_STATS_LINK_OFFLOAD_XSTATS); if (!attr) goto nla_put_failure; err = rtnl_get_offload_stats(skb, dev, prividx); if (err == -ENODATA) nla_nest_cancel(skb, attr); else nla_nest_end(skb, attr); if (err && err != -ENODATA) goto nla_put_failure; *idxattr = 0; } |
aefb4d4ad net: AF-specific ... |
3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 |
if (stats_attr_valid(filter_mask, IFLA_STATS_AF_SPEC, *idxattr)) { struct rtnl_af_ops *af_ops; *idxattr = IFLA_STATS_AF_SPEC; attr = nla_nest_start(skb, IFLA_STATS_AF_SPEC); if (!attr) goto nla_put_failure; list_for_each_entry(af_ops, &rtnl_af_ops, list) { if (af_ops->fill_stats_af) { struct nlattr *af; int err; af = nla_nest_start(skb, af_ops->family); if (!af) goto nla_put_failure; err = af_ops->fill_stats_af(skb, dev); if (err == -ENODATA) nla_nest_cancel(skb, af); else if (err < 0) goto nla_put_failure; nla_nest_end(skb, af); } } nla_nest_end(skb, attr); *idxattr = 0; } |
10c9ead9f rtnetlink: add ne... |
3788 3789 3790 3791 3792 |
nlmsg_end(skb, nlh); return 0; nla_put_failure: |
e8872a25a net: rtnetlink: a... |
3793 3794 3795 3796 3797 |
/* not a multi message or no progress mean a real error */ if (!(flags & NLM_F_MULTI) || s_prividx == *prividx) nlmsg_cancel(skb, nlh); else nlmsg_end(skb, nlh); |
10c9ead9f rtnetlink: add ne... |
3798 3799 3800 |
return -EMSGSIZE; } |
10c9ead9f rtnetlink: add ne... |
3801 3802 3803 3804 |
static size_t if_nlmsg_stats_size(const struct net_device *dev, u32 filter_mask) { size_t size = 0; |
e8872a25a net: rtnetlink: a... |
3805 |
if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_64, 0)) |
10c9ead9f rtnetlink: add ne... |
3806 |
size += nla_total_size_64bit(sizeof(struct rtnl_link_stats64)); |
97a47facf net: rtnetlink: a... |
3807 3808 |
if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_XSTATS, 0)) { const struct rtnl_link_ops *ops = dev->rtnl_link_ops; |
80e73cc56 net: rtnetlink: a... |
3809 |
int attr = IFLA_STATS_LINK_XSTATS; |
97a47facf net: rtnetlink: a... |
3810 3811 |
if (ops && ops->get_linkxstats_size) { |
80e73cc56 net: rtnetlink: a... |
3812 3813 |
size += nla_total_size(ops->get_linkxstats_size(dev, attr)); |
97a47facf net: rtnetlink: a... |
3814 3815 3816 3817 |
/* for IFLA_STATS_LINK_XSTATS */ size += nla_total_size(0); } } |
80e73cc56 net: rtnetlink: a... |
3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 |
if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_XSTATS_SLAVE, 0)) { struct net_device *_dev = (struct net_device *)dev; const struct rtnl_link_ops *ops = NULL; const struct net_device *master; /* netdev_master_upper_dev_get can't take const */ master = netdev_master_upper_dev_get(_dev); if (master) ops = master->rtnl_link_ops; if (ops && ops->get_linkxstats_size) { int attr = IFLA_STATS_LINK_XSTATS_SLAVE; size += nla_total_size(ops->get_linkxstats_size(dev, attr)); /* for IFLA_STATS_LINK_XSTATS_SLAVE */ size += nla_total_size(0); } } |
69ae6ad2f net: core: Add of... |
3836 3837 |
if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0)) size += rtnl_get_offload_stats_size(dev); |
aefb4d4ad net: AF-specific ... |
3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 |
if (stats_attr_valid(filter_mask, IFLA_STATS_AF_SPEC, 0)) { struct rtnl_af_ops *af_ops; /* for IFLA_STATS_AF_SPEC */ size += nla_total_size(0); list_for_each_entry(af_ops, &rtnl_af_ops, list) { if (af_ops->get_stats_af_size) { size += nla_total_size( af_ops->get_stats_af_size(dev)); /* for AF_* */ size += nla_total_size(0); } } } |
10c9ead9f rtnetlink: add ne... |
3854 3855 |
return size; } |
c21ef3e34 net: rtnetlink: p... |
3856 3857 |
static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
10c9ead9f rtnetlink: add ne... |
3858 3859 |
{ struct net *net = sock_net(skb->sk); |
10c9ead9f rtnetlink: add ne... |
3860 |
struct net_device *dev = NULL; |
e8872a25a net: rtnetlink: a... |
3861 3862 |
int idxattr = 0, prividx = 0; struct if_stats_msg *ifsm; |
10c9ead9f rtnetlink: add ne... |
3863 3864 3865 |
struct sk_buff *nskb; u32 filter_mask; int err; |
4775cc1f2 rtnl: stats - add... |
3866 3867 |
if (nlmsg_len(nlh) < sizeof(*ifsm)) return -EINVAL; |
10c9ead9f rtnetlink: add ne... |
3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 |
ifsm = nlmsg_data(nlh); if (ifsm->ifindex > 0) dev = __dev_get_by_index(net, ifsm->ifindex); else return -EINVAL; if (!dev) return -ENODEV; filter_mask = ifsm->filter_mask; if (!filter_mask) return -EINVAL; nskb = nlmsg_new(if_nlmsg_stats_size(dev, filter_mask), GFP_KERNEL); if (!nskb) return -ENOBUFS; err = rtnl_fill_statsinfo(nskb, dev, RTM_NEWSTATS, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, |
e8872a25a net: rtnetlink: a... |
3887 |
0, filter_mask, &idxattr, &prividx); |
10c9ead9f rtnetlink: add ne... |
3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 |
if (err < 0) { /* -EMSGSIZE implies BUG in if_nlmsg_stats_size */ WARN_ON(err == -EMSGSIZE); kfree_skb(nskb); } else { err = rtnl_unicast(nskb, net, NETLINK_CB(skb).portid); } return err; } static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb) { |
e8872a25a net: rtnetlink: a... |
3901 |
int h, s_h, err, s_idx, s_idxattr, s_prividx; |
10c9ead9f rtnetlink: add ne... |
3902 |
struct net *net = sock_net(skb->sk); |
e8872a25a net: rtnetlink: a... |
3903 |
unsigned int flags = NLM_F_MULTI; |
10c9ead9f rtnetlink: add ne... |
3904 |
struct if_stats_msg *ifsm; |
10c9ead9f rtnetlink: add ne... |
3905 |
struct hlist_head *head; |
e8872a25a net: rtnetlink: a... |
3906 |
struct net_device *dev; |
10c9ead9f rtnetlink: add ne... |
3907 |
u32 filter_mask = 0; |
e8872a25a net: rtnetlink: a... |
3908 |
int idx = 0; |
10c9ead9f rtnetlink: add ne... |
3909 3910 3911 |
s_h = cb->args[0]; s_idx = cb->args[1]; |
e8872a25a net: rtnetlink: a... |
3912 3913 |
s_idxattr = cb->args[2]; s_prividx = cb->args[3]; |
10c9ead9f rtnetlink: add ne... |
3914 3915 |
cb->seq = net->dev_base_seq; |
4775cc1f2 rtnl: stats - add... |
3916 3917 |
if (nlmsg_len(cb->nlh) < sizeof(*ifsm)) return -EINVAL; |
10c9ead9f rtnetlink: add ne... |
3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 |
ifsm = nlmsg_data(cb->nlh); filter_mask = ifsm->filter_mask; if (!filter_mask) return -EINVAL; for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { idx = 0; head = &net->dev_index_head[h]; hlist_for_each_entry(dev, head, index_hlist) { if (idx < s_idx) goto cont; err = rtnl_fill_statsinfo(skb, dev, RTM_NEWSTATS, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 0, |
e8872a25a net: rtnetlink: a... |
3932 3933 |
flags, filter_mask, &s_idxattr, &s_prividx); |
10c9ead9f rtnetlink: add ne... |
3934 3935 3936 3937 3938 3939 3940 |
/* If we ran out of room on the first message, * we're in trouble */ WARN_ON((err == -EMSGSIZE) && (skb->len == 0)); if (err < 0) goto out; |
e8872a25a net: rtnetlink: a... |
3941 3942 |
s_prividx = 0; s_idxattr = 0; |
10c9ead9f rtnetlink: add ne... |
3943 3944 3945 3946 3947 3948 |
nl_dump_check_consistent(cb, nlmsg_hdr(skb)); cont: idx++; } } out: |
e8872a25a net: rtnetlink: a... |
3949 3950 |
cb->args[3] = s_prividx; cb->args[2] = s_idxattr; |
10c9ead9f rtnetlink: add ne... |
3951 3952 3953 3954 3955 |
cb->args[1] = idx; cb->args[0] = h; return skb->len; } |
1da177e4c Linux-2.6.12-rc2 |
3956 |
/* Process one rtnetlink message. */ |
2d4bc9336 netlink: extended... |
3957 3958 |
static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
3959 |
{ |
3b1e0a655 [NET] NETNS: Omit... |
3960 |
struct net *net = sock_net(skb->sk); |
6853dd488 rtnetlink: protec... |
3961 3962 |
struct rtnl_link *handlers; int err = -EOPNOTSUPP; |
e28498638 [RTNL]: Message h... |
3963 |
rtnl_doit_func doit; |
62256f98f rtnetlink: add RT... |
3964 |
unsigned int flags; |
617cfc753 net/rtnetlink: re... |
3965 |
int kind; |
1da177e4c Linux-2.6.12-rc2 |
3966 3967 |
int family; int type; |
1da177e4c Linux-2.6.12-rc2 |
3968 |
|
1da177e4c Linux-2.6.12-rc2 |
3969 |
type = nlh->nlmsg_type; |
1da177e4c Linux-2.6.12-rc2 |
3970 |
if (type > RTM_MAX) |
038890fed [RTNL]: Improve e... |
3971 |
return -EOPNOTSUPP; |
1da177e4c Linux-2.6.12-rc2 |
3972 3973 3974 3975 |
type -= RTM_BASE; /* All the messages must have at least 1 byte length */ |
573ce260b net-next: replace... |
3976 |
if (nlmsg_len(nlh) < sizeof(struct rtgenmsg)) |
1da177e4c Linux-2.6.12-rc2 |
3977 |
return 0; |
573ce260b net-next: replace... |
3978 |
family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family; |
1da177e4c Linux-2.6.12-rc2 |
3979 |
kind = type&3; |
90f62cf30 net: Use netlink_... |
3980 |
if (kind != 2 && !netlink_net_capable(skb, CAP_NET_ADMIN)) |
1d00a4eb4 [NETLINK]: Remove... |
3981 |
return -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
3982 |
|
5c2bb9b6e rtnetlink: do not... |
3983 |
if (family >= ARRAY_SIZE(rtnl_msg_handlers)) |
6853dd488 rtnetlink: protec... |
3984 3985 3986 3987 3988 3989 3990 3991 |
family = PF_UNSPEC; rcu_read_lock(); handlers = rcu_dereference(rtnl_msg_handlers[family]); if (!handlers) { family = PF_UNSPEC; handlers = rcu_dereference(rtnl_msg_handlers[family]); } |
b8f3ab429 Revert "netlink: ... |
3992 |
if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { |
97c53cacf [NET]: Make rtnet... |
3993 |
struct sock *rtnl; |
e28498638 [RTNL]: Message h... |
3994 |
rtnl_dumpit_func dumpit; |
c7ac8679b rtnetlink: Comput... |
3995 |
u16 min_dump_alloc = 0; |
1da177e4c Linux-2.6.12-rc2 |
3996 |
|
6853dd488 rtnetlink: protec... |
3997 3998 3999 4000 4001 4002 |
dumpit = READ_ONCE(handlers[type].dumpit); if (!dumpit) { family = PF_UNSPEC; handlers = rcu_dereference(rtnl_msg_handlers[PF_UNSPEC]); if (!handlers) goto err_unlock; |
0cc09020a rtnetlink: small ... |
4003 |
|
6853dd488 rtnetlink: protec... |
4004 4005 4006 4007 |
dumpit = READ_ONCE(handlers[type].dumpit); if (!dumpit) goto err_unlock; } |
e1fa6d216 rtnetlink: call r... |
4008 |
|
019a31699 rtnetlink: add re... |
4009 |
refcount_inc(&rtnl_msg_handlers_ref[family]); |
5c2bb9b6e rtnetlink: do not... |
4010 |
if (type == RTM_GETLINK - RTM_BASE) |
e1fa6d216 rtnetlink: call r... |
4011 |
min_dump_alloc = rtnl_calcit(skb, nlh); |
9ac4a1698 [RTNETLINK]: Use ... |
4012 |
|
6853dd488 rtnetlink: protec... |
4013 |
rcu_read_unlock(); |
97c53cacf [NET]: Make rtnet... |
4014 |
rtnl = net->rtnl; |
80d326fab netlink: add netl... |
4015 4016 4017 4018 4019 4020 4021 |
{ struct netlink_dump_control c = { .dump = dumpit, .min_dump_alloc = min_dump_alloc, }; err = netlink_dump_start(rtnl, skb, nlh, &c); } |
019a31699 rtnetlink: add re... |
4022 |
refcount_dec(&rtnl_msg_handlers_ref[family]); |
2907c35ff net: hold rtnl ag... |
4023 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
4024 |
} |
8caa38b56 rtnetlink: fallba... |
4025 4026 4027 4028 4029 |
doit = READ_ONCE(handlers[type].doit); if (!doit) { family = PF_UNSPEC; handlers = rcu_dereference(rtnl_msg_handlers[family]); } |
62256f98f rtnetlink: add RT... |
4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 |
flags = READ_ONCE(handlers[type].flags); if (flags & RTNL_FLAG_DOIT_UNLOCKED) { refcount_inc(&rtnl_msg_handlers_ref[family]); doit = READ_ONCE(handlers[type].doit); rcu_read_unlock(); if (doit) err = doit(skb, nlh, extack); refcount_dec(&rtnl_msg_handlers_ref[family]); return err; } |
6853dd488 rtnetlink: protec... |
4040 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
4041 |
|
6853dd488 rtnetlink: protec... |
4042 4043 4044 4045 4046 4047 4048 |
rtnl_lock(); handlers = rtnl_dereference(rtnl_msg_handlers[family]); if (handlers) { doit = READ_ONCE(handlers[type].doit); if (doit) err = doit(skb, nlh, extack); } |
0cc09020a rtnetlink: small ... |
4049 |
rtnl_unlock(); |
0cc09020a rtnetlink: small ... |
4050 4051 4052 |
return err; err_unlock: |
6853dd488 rtnetlink: protec... |
4053 |
rcu_read_unlock(); |
0cc09020a rtnetlink: small ... |
4054 |
return -EOPNOTSUPP; |
1da177e4c Linux-2.6.12-rc2 |
4055 |
} |
cd40b7d39 [NET]: make netli... |
4056 |
static void rtnetlink_rcv(struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
4057 |
{ |
cd40b7d39 [NET]: make netli... |
4058 |
netlink_rcv_skb(skb, &rtnetlink_rcv_msg); |
1da177e4c Linux-2.6.12-rc2 |
4059 |
} |
5f729eaab rtnetlink: add re... |
4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 |
static int rtnetlink_bind(struct net *net, int group) { switch (group) { case RTNLGRP_IPV4_MROUTE_R: case RTNLGRP_IPV6_MROUTE_R: if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) return -EPERM; break; } return 0; } |
1da177e4c Linux-2.6.12-rc2 |
4071 4072 |
static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr) { |
351638e7d net: pass info st... |
4073 |
struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
e9dc86534 [NET]: Make devic... |
4074 |
|
1da177e4c Linux-2.6.12-rc2 |
4075 |
switch (event) { |
5138e86f1 rtnetlink: Conver... |
4076 |
case NETDEV_REBOOT: |
8a212589f rtnetlink: bring ... |
4077 |
case NETDEV_CHANGEMTU: |
3753654e5 Revert "rtnetlink... |
4078 |
case NETDEV_CHANGEADDR: |
5138e86f1 rtnetlink: Conver... |
4079 4080 4081 |
case NETDEV_CHANGENAME: case NETDEV_FEAT_CHANGE: case NETDEV_BONDING_FAILOVER: |
e6e665944 rtnetlink: bring ... |
4082 |
case NETDEV_POST_TYPE_CHANGE: |
5138e86f1 rtnetlink: Conver... |
4083 |
case NETDEV_NOTIFY_PEERS: |
dc709f375 rtnetlink: bring ... |
4084 |
case NETDEV_CHANGEUPPER: |
5138e86f1 rtnetlink: Conver... |
4085 |
case NETDEV_RESEND_IGMP: |
5138e86f1 rtnetlink: Conver... |
4086 |
case NETDEV_CHANGEINFODATA: |
ebdcf0450 rtnetlink: bring ... |
4087 |
case NETDEV_CHANGE_TX_QUEUE_LEN: |
3d3ea5af5 rtnl: Add support... |
4088 4089 |
rtmsg_ifinfo_event(RTM_NEWLINK, dev, 0, rtnl_get_event(event), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
4090 4091 |
break; default: |
1da177e4c Linux-2.6.12-rc2 |
4092 4093 4094 4095 4096 4097 4098 4099 |
break; } return NOTIFY_DONE; } static struct notifier_block rtnetlink_dev_notifier = { .notifier_call = rtnetlink_event, }; |
97c53cacf [NET]: Make rtnet... |
4100 |
|
2c8c1e729 net: spread __net... |
4101 |
static int __net_init rtnetlink_net_init(struct net *net) |
97c53cacf [NET]: Make rtnet... |
4102 4103 |
{ struct sock *sk; |
a31f2d17b netlink: add netl... |
4104 4105 4106 4107 |
struct netlink_kernel_cfg cfg = { .groups = RTNLGRP_MAX, .input = rtnetlink_rcv, .cb_mutex = &rtnl_mutex, |
9785e10ae netlink: kill net... |
4108 |
.flags = NL_CFG_F_NONROOT_RECV, |
5f729eaab rtnetlink: add re... |
4109 |
.bind = rtnetlink_bind, |
a31f2d17b netlink: add netl... |
4110 |
}; |
9f00d9776 netlink: hide str... |
4111 |
sk = netlink_kernel_create(net, NETLINK_ROUTE, &cfg); |
97c53cacf [NET]: Make rtnet... |
4112 4113 |
if (!sk) return -ENOMEM; |
97c53cacf [NET]: Make rtnet... |
4114 4115 4116 |
net->rtnl = sk; return 0; } |
2c8c1e729 net: spread __net... |
4117 |
static void __net_exit rtnetlink_net_exit(struct net *net) |
97c53cacf [NET]: Make rtnet... |
4118 |
{ |
775516bfa [NETNS]: Namespac... |
4119 4120 |
netlink_kernel_release(net->rtnl); net->rtnl = NULL; |
97c53cacf [NET]: Make rtnet... |
4121 4122 4123 4124 4125 4126 |
} static struct pernet_operations rtnetlink_net_ops = { .init = rtnetlink_net_init, .exit = rtnetlink_net_exit, }; |
1da177e4c Linux-2.6.12-rc2 |
4127 4128 |
void __init rtnetlink_init(void) { |
d38a65125 rtnetlink: init h... |
4129 4130 4131 4132 |
int i; for (i = 0; i < ARRAY_SIZE(rtnl_msg_handlers_ref); i++) refcount_set(&rtnl_msg_handlers_ref[i], 1); |
97c53cacf [NET]: Make rtnet... |
4133 |
if (register_pernet_subsys(&rtnetlink_net_ops)) |
1da177e4c Linux-2.6.12-rc2 |
4134 4135 |
panic("rtnetlink_init: cannot initialize rtnetlink "); |
97c53cacf [NET]: Make rtnet... |
4136 |
|
1da177e4c Linux-2.6.12-rc2 |
4137 |
register_netdevice_notifier(&rtnetlink_dev_notifier); |
340d17fc9 [NET] link: Use r... |
4138 |
|
c7ac8679b rtnetlink: Comput... |
4139 |
rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, |
b97bac64a rtnetlink: make r... |
4140 4141 4142 4143 |
rtnl_dump_ifinfo, 0); rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, 0); rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, 0); rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, 0); |
687ad8cc6 [RTNL]: Use rtnl ... |
4144 |
|
b97bac64a rtnetlink: make r... |
4145 4146 4147 |
rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, 0); rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, 0); rtnl_register(PF_UNSPEC, RTM_GETNETCONF, NULL, rtnl_dump_all, 0); |
77162022a net: add generic ... |
4148 |
|
b97bac64a rtnetlink: make r... |
4149 4150 4151 |
rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, 0); rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, 0); rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, 0); |
e5a55a898 net: create gener... |
4152 |
|
b97bac64a rtnetlink: make r... |
4153 4154 4155 |
rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, 0); rtnl_register(PF_BRIDGE, RTM_DELLINK, rtnl_bridge_dellink, NULL, 0); rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, 0); |
10c9ead9f rtnetlink: add ne... |
4156 4157 |
rtnl_register(PF_UNSPEC, RTM_GETSTATS, rtnl_stats_get, rtnl_stats_dump, |
b97bac64a rtnetlink: make r... |
4158 |
0); |
1da177e4c Linux-2.6.12-rc2 |
4159 |
} |