aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/devinet.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-08-15 03:33:59 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:54:53 -0400
commitd6062cbbd1f5e92c94e5eae9ef1a280ed48d56d5 (patch)
tree1712e15976e15f63e2038772179276ffe926d336 /net/ipv4/devinet.c
parentdc738dd83e88c3c5de55431f8cfb758de5d4df48 (diff)
[IPv4] address: Convert address notification to use rtnl_notify()
Adds support for NLM_F_ECHO allowing applications to easly see which address have been deleted, added, or promoted. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r--net/ipv4/devinet.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 398e7b9ca66b..0487677729cf 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -88,7 +88,7 @@ static struct nla_policy ifa_ipv4_policy[IFA_MAX+1] __read_mostly = {
88 [IFA_LABEL] = { .type = NLA_STRING }, 88 [IFA_LABEL] = { .type = NLA_STRING },
89}; 89};
90 90
91static void rtmsg_ifa(int event, struct in_ifaddr *); 91static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
92 92
93static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); 93static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
94static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, 94static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
@@ -239,8 +239,8 @@ int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
239 return 0; 239 return 0;
240} 240}
241 241
242static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, 242static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
243 int destroy) 243 int destroy, struct nlmsghdr *nlh, u32 pid)
244{ 244{
245 struct in_ifaddr *promote = NULL; 245 struct in_ifaddr *promote = NULL;
246 struct in_ifaddr *ifa, *ifa1 = *ifap; 246 struct in_ifaddr *ifa, *ifa1 = *ifap;
@@ -273,7 +273,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
273 if (!do_promote) { 273 if (!do_promote) {
274 *ifap1 = ifa->ifa_next; 274 *ifap1 = ifa->ifa_next;
275 275
276 rtmsg_ifa(RTM_DELADDR, ifa); 276 rtmsg_ifa(RTM_DELADDR, ifa, nlh, pid);
277 blocking_notifier_call_chain(&inetaddr_chain, 277 blocking_notifier_call_chain(&inetaddr_chain,
278 NETDEV_DOWN, ifa); 278 NETDEV_DOWN, ifa);
279 inet_free_ifa(ifa); 279 inet_free_ifa(ifa);
@@ -298,7 +298,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
298 is valid, it will try to restore deleted routes... Grr. 298 is valid, it will try to restore deleted routes... Grr.
299 So that, this order is correct. 299 So that, this order is correct.
300 */ 300 */
301 rtmsg_ifa(RTM_DELADDR, ifa1); 301 rtmsg_ifa(RTM_DELADDR, ifa1, nlh, pid);
302 blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); 302 blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
303 303
304 if (promote) { 304 if (promote) {
@@ -310,7 +310,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
310 } 310 }
311 311
312 promote->ifa_flags &= ~IFA_F_SECONDARY; 312 promote->ifa_flags &= ~IFA_F_SECONDARY;
313 rtmsg_ifa(RTM_NEWADDR, promote); 313 rtmsg_ifa(RTM_NEWADDR, promote, nlh, pid);
314 blocking_notifier_call_chain(&inetaddr_chain, 314 blocking_notifier_call_chain(&inetaddr_chain,
315 NETDEV_UP, promote); 315 NETDEV_UP, promote);
316 for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { 316 for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) {
@@ -329,7 +329,14 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
329 } 329 }
330} 330}
331 331
332static int inet_insert_ifa(struct in_ifaddr *ifa) 332static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
333 int destroy)
334{
335 __inet_del_ifa(in_dev, ifap, destroy, NULL, 0);
336}
337
338static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
339 u32 pid)
333{ 340{
334 struct in_device *in_dev = ifa->ifa_dev; 341 struct in_device *in_dev = ifa->ifa_dev;
335 struct in_ifaddr *ifa1, **ifap, **last_primary; 342 struct in_ifaddr *ifa1, **ifap, **last_primary;
@@ -374,12 +381,17 @@ static int inet_insert_ifa(struct in_ifaddr *ifa)
374 /* Send message first, then call notifier. 381 /* Send message first, then call notifier.
375 Notifier will trigger FIB update, so that 382 Notifier will trigger FIB update, so that
376 listeners of netlink will know about new ifaddr */ 383 listeners of netlink will know about new ifaddr */
377 rtmsg_ifa(RTM_NEWADDR, ifa); 384 rtmsg_ifa(RTM_NEWADDR, ifa, nlh, pid);
378 blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); 385 blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
379 386
380 return 0; 387 return 0;
381} 388}
382 389
390static int inet_insert_ifa(struct in_ifaddr *ifa)
391{
392 return __inet_insert_ifa(ifa, NULL, 0);
393}
394
383static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) 395static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
384{ 396{
385 struct in_device *in_dev = __in_dev_get_rtnl(dev); 397 struct in_device *in_dev = __in_dev_get_rtnl(dev);
@@ -466,7 +478,7 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
466 !inet_ifa_match(nla_get_u32(tb[IFA_ADDRESS]), ifa))) 478 !inet_ifa_match(nla_get_u32(tb[IFA_ADDRESS]), ifa)))
467 continue; 479 continue;
468 480
469 inet_del_ifa(in_dev, ifap, 1); 481 __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).pid);
470 return 0; 482 return 0;
471 } 483 }
472 484
@@ -558,7 +570,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
558 if (IS_ERR(ifa)) 570 if (IS_ERR(ifa))
559 return PTR_ERR(ifa); 571 return PTR_ERR(ifa);
560 572
561 return inet_insert_ifa(ifa); 573 return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).pid);
562} 574}
563 575
564/* 576/*
@@ -1189,18 +1201,27 @@ done:
1189 return skb->len; 1201 return skb->len;
1190} 1202}
1191 1203
1192static void rtmsg_ifa(int event, struct in_ifaddr* ifa) 1204static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
1205 u32 pid)
1193{ 1206{
1194 struct sk_buff *skb; 1207 struct sk_buff *skb;
1208 u32 seq = nlh ? nlh->nlmsg_seq : 0;
1209 int err = -ENOBUFS;
1195 1210
1196 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1211 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1197 if (skb == NULL) 1212 if (skb == NULL)
1198 netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); 1213 goto errout;
1199 else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) { 1214
1215 err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
1216 if (err < 0) {
1200 kfree_skb(skb); 1217 kfree_skb(skb);
1201 netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); 1218 goto errout;
1202 } else 1219 }
1203 netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_IFADDR, GFP_KERNEL); 1220
1221 err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
1222errout:
1223 if (err < 0)
1224 rtnl_set_sk_err(RTNLGRP_IPV4_IFADDR, err);
1204} 1225}
1205 1226
1206static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = { 1227static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = {