aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 }