aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/fib_rules.c27
1 files changed, 24 insertions, 3 deletions
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 }