aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-03-23 04:16:06 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-23 04:16:06 -0500
commita5cdc030030ef5a16e48aebeb65067bdc3120899 (patch)
tree36524250e8564ae4e7f891662dace65fdacff521
parent5e2e71141ca93a3e2543966ced6a6077d4fb8fd8 (diff)
[IPV4]: Add fib rule netlink notifications
To really make sense of route notifications in the presence of multiple tables, userspace also needs to be notified about routing rule updates. Notifications are sent to the so far unused RTNLGRP_NOP1 (now RTNLGRP_RULE) group. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/rtnetlink.h4
-rw-r--r--net/ipv4/fib_rules.c27
2 files changed, 27 insertions, 4 deletions
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index d572d5376319..df0cdd41085c 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -839,6 +839,7 @@ enum
839#define RTMGRP_IPV4_IFADDR 0x10 839#define RTMGRP_IPV4_IFADDR 0x10
840#define RTMGRP_IPV4_MROUTE 0x20 840#define RTMGRP_IPV4_MROUTE 0x20
841#define RTMGRP_IPV4_ROUTE 0x40 841#define RTMGRP_IPV4_ROUTE 0x40
842#define RTMGRP_IPV4_RULE 0x80
842 843
843#define RTMGRP_IPV6_IFADDR 0x100 844#define RTMGRP_IPV6_IFADDR 0x100
844#define RTMGRP_IPV6_MROUTE 0x200 845#define RTMGRP_IPV6_MROUTE 0x200
@@ -869,7 +870,8 @@ enum rtnetlink_groups {
869#define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE 870#define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE
870 RTNLGRP_IPV4_ROUTE, 871 RTNLGRP_IPV4_ROUTE,
871#define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE 872#define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE
872 RTNLGRP_NOP1, 873 RTNLGRP_IPV4_RULE,
874#define RTNLGRP_IPV4_RULE RTNLGRP_IPV4_RULE
873 RTNLGRP_IPV6_IFADDR, 875 RTNLGRP_IPV6_IFADDR,
874#define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR 876#define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR
875 RTNLGRP_IPV6_MROUTE, 877 RTNLGRP_IPV6_MROUTE,
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 768e8f5d7daa..ec566f3e66c7 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -104,6 +104,8 @@ static struct hlist_head fib_rules;
104 104
105/* writer func called from netlink -- rtnl_sem hold*/ 105/* writer func called from netlink -- rtnl_sem hold*/
106 106
107static void rtmsg_rule(int, struct fib_rule *);
108
107int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 109int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
108{ 110{
109 struct rtattr **rta = arg; 111 struct rtattr **rta = arg;
@@ -131,6 +133,7 @@ int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
131 133
132 hlist_del_rcu(&r->hlist); 134 hlist_del_rcu(&r->hlist);
133 r->r_dead = 1; 135 r->r_dead = 1;
136 rtmsg_rule(RTM_DELRULE, r);
134 fib_rule_put(r); 137 fib_rule_put(r);
135 err = 0; 138 err = 0;
136 break; 139 break;
@@ -253,6 +256,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
253 else 256 else
254 hlist_add_before_rcu(&new_r->hlist, &r->hlist); 257 hlist_add_before_rcu(&new_r->hlist, &r->hlist);
255 258
259 rtmsg_rule(RTM_NEWRULE, new_r);
256 return 0; 260 return 0;
257} 261}
258 262
@@ -382,14 +386,14 @@ static struct notifier_block fib_rules_notifier = {
382 386
383static __inline__ int inet_fill_rule(struct sk_buff *skb, 387static __inline__ int inet_fill_rule(struct sk_buff *skb,
384 struct fib_rule *r, 388 struct fib_rule *r,
385 struct netlink_callback *cb, 389 u32 pid, u32 seq, int event,
386 unsigned int flags) 390 unsigned int flags)
387{ 391{
388 struct rtmsg *rtm; 392 struct rtmsg *rtm;
389 struct nlmsghdr *nlh; 393 struct nlmsghdr *nlh;
390 unsigned char *b = skb->tail; 394 unsigned char *b = skb->tail;
391 395
392 nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags); 396 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
393 rtm = NLMSG_DATA(nlh); 397 rtm = NLMSG_DATA(nlh);
394 rtm->rtm_family = AF_INET; 398 rtm->rtm_family = AF_INET;
395 rtm->rtm_dst_len = r->r_dst_len; 399 rtm->rtm_dst_len = r->r_dst_len;
@@ -430,6 +434,21 @@ rtattr_failure:
430 434
431/* callers should hold rtnl semaphore */ 435/* callers should hold rtnl semaphore */
432 436
437static void rtmsg_rule(int event, struct fib_rule *r)
438{
439 int size = NLMSG_SPACE(sizeof(struct rtmsg) + 128);
440 struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
441
442 if (!skb)
443 netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, ENOBUFS);
444 else if (inet_fill_rule(skb, r, 0, 0, event, 0) < 0) {
445 kfree_skb(skb);
446 netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, EINVAL);
447 } else {
448 netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_RULE, GFP_KERNEL);
449 }
450}
451
433int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) 452int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
434{ 453{
435 int idx = 0; 454 int idx = 0;
@@ -442,7 +461,9 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
442 461
443 if (idx < s_idx) 462 if (idx < s_idx)
444 continue; 463 continue;
445 if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0) 464 if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid,
465 cb->nlh->nlmsg_seq,
466 RTM_NEWRULE, NLM_F_MULTI) < 0)
446 break; 467 break;
447 idx++; 468 idx++;
448 } 469 }