Hi Dave,

following is a patch to add rule change notifications to fib_rules and
two minor coverity fixes to remove the noise from net/.

[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 <[EMAIL PROTECTED]>

---
commit 00edcfde5f7e8449721646e89f9dec2d8edf12de
tree 2bebabedc61d06eb819fe3906438731ec1d12a9d
parent e952f31bce6e9f64db01f607abc46529ba57ac9e
author Patrick McHardy <[EMAIL PROTECTED]> Thu, 23 Mar 2006 05:43:12 +0100
committer Patrick McHardy <[EMAIL PROTECTED]> Thu, 23 Mar 2006 05:43:12 +0100

 include/linux/rtnetlink.h |    4 +++-
 net/ipv4/fib_rules.c      |   27 ++++++++++++++++++++++++---
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index d572d53..df0cdd4 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -839,6 +839,7 @@ enum
 #define RTMGRP_IPV4_IFADDR     0x10
 #define RTMGRP_IPV4_MROUTE     0x20
 #define RTMGRP_IPV4_ROUTE      0x40
+#define RTMGRP_IPV4_RULE       0x80
 
 #define RTMGRP_IPV6_IFADDR     0x100
 #define RTMGRP_IPV6_MROUTE     0x200
@@ -869,7 +870,8 @@ enum rtnetlink_groups {
 #define        RTNLGRP_IPV4_MROUTE     RTNLGRP_IPV4_MROUTE
        RTNLGRP_IPV4_ROUTE,
 #define RTNLGRP_IPV4_ROUTE     RTNLGRP_IPV4_ROUTE
-       RTNLGRP_NOP1,
+       RTNLGRP_IPV4_RULE,
+#define RTNLGRP_IPV4_RULE      RTNLGRP_IPV4_RULE
        RTNLGRP_IPV6_IFADDR,
 #define RTNLGRP_IPV6_IFADDR    RTNLGRP_IPV6_IFADDR
        RTNLGRP_IPV6_MROUTE,
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 768e8f5..ec566f3 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -104,6 +104,8 @@ static struct hlist_head fib_rules;
 
 /* writer func called from netlink -- rtnl_sem hold*/
 
+static void rtmsg_rule(int, struct fib_rule *);
+
 int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
        struct rtattr **rta = arg;
@@ -131,6 +133,7 @@ int inet_rtm_delrule(struct sk_buff *skb
 
                        hlist_del_rcu(&r->hlist);
                        r->r_dead = 1;
+                       rtmsg_rule(RTM_DELRULE, r);
                        fib_rule_put(r);
                        err = 0;
                        break;
@@ -253,6 +256,7 @@ int inet_rtm_newrule(struct sk_buff *skb
        else
                hlist_add_before_rcu(&new_r->hlist, &r->hlist);
 
+       rtmsg_rule(RTM_NEWRULE, new_r);
        return 0;
 }
 
@@ -382,14 +386,14 @@ static struct notifier_block fib_rules_n
 
 static __inline__ int inet_fill_rule(struct sk_buff *skb,
                                     struct fib_rule *r,
-                                    struct netlink_callback *cb,
+                                    u32 pid, u32 seq, int event,
                                     unsigned int flags)
 {
        struct rtmsg *rtm;
        struct nlmsghdr  *nlh;
        unsigned char    *b = skb->tail;
 
-       nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags);
+       nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
        rtm = NLMSG_DATA(nlh);
        rtm->rtm_family = AF_INET;
        rtm->rtm_dst_len = r->r_dst_len;
@@ -430,6 +434,21 @@ rtattr_failure:
 
 /* callers should hold rtnl semaphore */
 
+static void rtmsg_rule(int event, struct fib_rule *r)
+{
+       int size = NLMSG_SPACE(sizeof(struct rtmsg) + 128);
+       struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
+
+       if (!skb)
+               netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, ENOBUFS);
+       else if (inet_fill_rule(skb, r, 0, 0, event, 0) < 0) {
+               kfree_skb(skb);
+               netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, EINVAL);
+       } else {
+               netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_RULE, GFP_KERNEL);
+       }
+}
+
 int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
 {
        int idx = 0;
@@ -442,7 +461,9 @@ int inet_dump_rules(struct sk_buff *skb,
 
                if (idx < s_idx)
                        continue;
-               if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
+               if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid,
+                                  cb->nlh->nlmsg_seq,
+                                  RTM_NEWRULE, NLM_F_MULTI) < 0)
                        break;
                idx++;
        }

Reply via email to