aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/fib_rules.h3
-rw-r--r--include/net/rtnetlink.h8
-rw-r--r--net/core/fib_rules.c47
-rw-r--r--net/decnet/dn_rules.c7
-rw-r--r--net/ipv4/fib_rules.c7
-rw-r--r--net/ipv6/fib6_rules.c7
6 files changed, 45 insertions, 34 deletions
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index b2b9ccdf32d6..ff3029fe9656 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -98,7 +98,4 @@ extern int fib_rules_unregister(struct fib_rules_ops *);
98extern int fib_rules_lookup(struct fib_rules_ops *, 98extern int fib_rules_lookup(struct fib_rules_ops *,
99 struct flowi *, int flags, 99 struct flowi *, int flags,
100 struct fib_lookup_arg *); 100 struct fib_lookup_arg *);
101
102extern int fib_rules_dump(struct sk_buff *,
103 struct netlink_callback *, int);
104#endif 101#endif
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index dce7072bd28c..086fa9e89509 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -15,4 +15,12 @@ extern int rtnl_unregister(int protocol, int msgtype);
15extern void rtnl_unregister_all(int protocol); 15extern void rtnl_unregister_all(int protocol);
16extern int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb); 16extern int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb);
17 17
18static inline int rtnl_msg_family(struct nlmsghdr *nlh)
19{
20 if (nlmsg_len(nlh) >= sizeof(struct rtgenmsg))
21 return ((struct rtgenmsg *) nlmsg_data(nlh))->rtgen_family;
22 else
23 return AF_UNSPEC;
24}
25
18#endif 26#endif
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index bf45f24cfea2..fdf05af16ba5 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -393,19 +393,15 @@ nla_put_failure:
393 return -EMSGSIZE; 393 return -EMSGSIZE;
394} 394}
395 395
396int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family) 396static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
397 struct fib_rules_ops *ops)
397{ 398{
398 int idx = 0; 399 int idx = 0;
399 struct fib_rule *rule; 400 struct fib_rule *rule;
400 struct fib_rules_ops *ops;
401
402 ops = lookup_rules_ops(family);
403 if (ops == NULL)
404 return -EAFNOSUPPORT;
405 401
406 rcu_read_lock(); 402 rcu_read_lock();
407 list_for_each_entry_rcu(rule, ops->rules_list, list) { 403 list_for_each_entry_rcu(rule, ops->rules_list, list) {
408 if (idx < cb->args[0]) 404 if (idx < cb->args[1])
409 goto skip; 405 goto skip;
410 406
411 if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).pid, 407 if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).pid,
@@ -416,13 +412,44 @@ skip:
416 idx++; 412 idx++;
417 } 413 }
418 rcu_read_unlock(); 414 rcu_read_unlock();
419 cb->args[0] = idx; 415 cb->args[1] = idx;
420 rules_ops_put(ops); 416 rules_ops_put(ops);
421 417
422 return skb->len; 418 return skb->len;
423} 419}
424 420
425EXPORT_SYMBOL_GPL(fib_rules_dump); 421static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
422{
423 struct fib_rules_ops *ops;
424 int idx = 0, family;
425
426 family = rtnl_msg_family(cb->nlh);
427 if (family != AF_UNSPEC) {
428 /* Protocol specific dump request */
429 ops = lookup_rules_ops(family);
430 if (ops == NULL)
431 return -EAFNOSUPPORT;
432
433 return dump_rules(skb, cb, ops);
434 }
435
436 rcu_read_lock();
437 list_for_each_entry_rcu(ops, &rules_ops, list) {
438 if (idx < cb->args[0] || !try_module_get(ops->owner))
439 goto skip;
440
441 if (dump_rules(skb, cb, ops) < 0)
442 break;
443
444 cb->args[1] = 0;
445 skip:
446 idx++;
447 }
448 rcu_read_unlock();
449 cb->args[0] = idx;
450
451 return skb->len;
452}
426 453
427static void notify_rule_change(int event, struct fib_rule *rule, 454static void notify_rule_change(int event, struct fib_rule *rule,
428 struct fib_rules_ops *ops, struct nlmsghdr *nlh, 455 struct fib_rules_ops *ops, struct nlmsghdr *nlh,
@@ -503,7 +530,7 @@ static int __init fib_rules_init(void)
503{ 530{
504 rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL); 531 rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
505 rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL); 532 rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
506 rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, rtnl_dump_all); 533 rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
507 534
508 return register_netdevice_notifier(&fib_rules_notifier); 535 return register_netdevice_notifier(&fib_rules_notifier);
509} 536}
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index a7a7da9b35c3..fd0cc2aa316c 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -239,11 +239,6 @@ static u32 dn_fib_rule_default_pref(void)
239 return 0; 239 return 0;
240} 240}
241 241
242static int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
243{
244 return fib_rules_dump(skb, cb, AF_DECnet);
245}
246
247static struct fib_rules_ops dn_fib_rules_ops = { 242static struct fib_rules_ops dn_fib_rules_ops = {
248 .family = AF_DECnet, 243 .family = AF_DECnet,
249 .rule_size = sizeof(struct dn_fib_rule), 244 .rule_size = sizeof(struct dn_fib_rule),
@@ -264,12 +259,10 @@ void __init dn_fib_rules_init(void)
264{ 259{
265 list_add_tail(&default_rule.common.list, &dn_fib_rules); 260 list_add_tail(&default_rule.common.list, &dn_fib_rules);
266 fib_rules_register(&dn_fib_rules_ops); 261 fib_rules_register(&dn_fib_rules_ops);
267 rtnl_register(PF_DECnet, RTM_GETRULE, NULL, dn_fib_dump_rules);
268} 262}
269 263
270void __exit dn_fib_rules_cleanup(void) 264void __exit dn_fib_rules_cleanup(void)
271{ 265{
272 rtnl_unregister(PF_DECnet, RTM_GETRULE);
273 fib_rules_unregister(&dn_fib_rules_ops); 266 fib_rules_unregister(&dn_fib_rules_ops);
274} 267}
275 268
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index a7f931ddfaad..b021b3440ca3 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -274,11 +274,6 @@ nla_put_failure:
274 return -ENOBUFS; 274 return -ENOBUFS;
275} 275}
276 276
277static int fib4_rule_dump(struct sk_buff *skb, struct netlink_callback *cb)
278{
279 return fib_rules_dump(skb, cb, AF_INET);
280}
281
282static u32 fib4_rule_default_pref(void) 277static u32 fib4_rule_default_pref(void)
283{ 278{
284 struct list_head *pos; 279 struct list_head *pos;
@@ -327,6 +322,4 @@ void __init fib4_rules_init(void)
327 list_add_tail(&default_rule.common.list, &fib4_rules); 322 list_add_tail(&default_rule.common.list, &fib4_rules);
328 323
329 fib_rules_register(&fib4_rules_ops); 324 fib_rules_register(&fib4_rules_ops);
330
331 rtnl_register(PF_INET, RTM_GETRULE, NULL, fib4_rule_dump);
332} 325}
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index c74da4b6dd2f..dd9720e700ef 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -216,11 +216,6 @@ nla_put_failure:
216 return -ENOBUFS; 216 return -ENOBUFS;
217} 217}
218 218
219static int fib6_rules_dump(struct sk_buff *skb, struct netlink_callback *cb)
220{
221 return fib_rules_dump(skb, cb, AF_INET6);
222}
223
224static u32 fib6_rule_default_pref(void) 219static u32 fib6_rule_default_pref(void)
225{ 220{
226 return 0x3FFF; 221 return 0x3FFF;
@@ -255,11 +250,9 @@ void __init fib6_rules_init(void)
255 list_add_tail(&main_rule.common.list, &fib6_rules); 250 list_add_tail(&main_rule.common.list, &fib6_rules);
256 251
257 fib_rules_register(&fib6_rules_ops); 252 fib_rules_register(&fib6_rules_ops);
258 __rtnl_register(PF_INET6, RTM_GETRULE, NULL, fib6_rules_dump);
259} 253}
260 254
261void fib6_rules_cleanup(void) 255void fib6_rules_cleanup(void)
262{ 256{
263 rtnl_unregister(PF_INET6, RTM_GETRULE);
264 fib_rules_unregister(&fib6_rules_ops); 257 fib_rules_unregister(&fib6_rules_ops);
265} 258}