aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2009-02-25 02:18:28 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-25 02:18:28 -0500
commit1ce85fe402137824246bad03ff85f3913d565c17 (patch)
tree3a54c150e9616709a8f65270cd1f4aeecac4d48e /net/core
parent4fb0a54a55d34c28dc53c39567ce171166572699 (diff)
netlink: change nlmsg_notify() return value logic
This patch changes the return value of nlmsg_notify() as follows: If NETLINK_BROADCAST_ERROR is set by any of the listeners and an error in the delivery happened, return the broadcast error; else if there are no listeners apart from the socket that requested a change with the echo flag, return the result of the unicast notification. Thus, with this patch, the unicast notification is handled in the same way of a broadcast listener that has set the NETLINK_BROADCAST_ERROR socket flag. This patch is useful in case that the caller of nlmsg_notify() wants to know the result of the delivery of a netlink notification (including the broadcast delivery) and take any action in case that the delivery failed. For example, ctnetlink can drop packets if the event delivery failed to provide reliable logging and state-synchronization at the cost of dropping packets. This patch also modifies the rtnetlink code to ignore the return value of rtnl_notify() in all callers. The function rtnl_notify() (before this patch) returned the error of the unicast notification which makes rtnl_set_sk_err() reports errors to all listeners. This is not of any help since the origin of the change (the socket that requested the echoing) notices the ENOBUFS error if the notification fails and should resync itself. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Acked-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/fib_rules.c3
-rw-r--r--net/core/neighbour.c3
-rw-r--r--net/core/rtnetlink.c9
3 files changed, 9 insertions, 6 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 32b3a0152d7a..98691e1466b8 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -588,7 +588,8 @@ static void notify_rule_change(int event, struct fib_rule *rule,
588 goto errout; 588 goto errout;
589 } 589 }
590 590
591 err = rtnl_notify(skb, net, pid, ops->nlgroup, nlh, GFP_KERNEL); 591 rtnl_notify(skb, net, pid, ops->nlgroup, nlh, GFP_KERNEL);
592 return;
592errout: 593errout:
593 if (err < 0) 594 if (err < 0)
594 rtnl_set_sk_err(net, ops->nlgroup, err); 595 rtnl_set_sk_err(net, ops->nlgroup, err);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 278a142d1047..e1144cb94b99 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2534,7 +2534,8 @@ static void __neigh_notify(struct neighbour *n, int type, int flags)
2534 kfree_skb(skb); 2534 kfree_skb(skb);
2535 goto errout; 2535 goto errout;
2536 } 2536 }
2537 err = rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); 2537 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2538 return;
2538errout: 2539errout:
2539 if (err < 0) 2540 if (err < 0)
2540 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); 2541 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 790dd205bb5d..d78030f88bd0 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -455,8 +455,8 @@ int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid)
455 return nlmsg_unicast(rtnl, skb, pid); 455 return nlmsg_unicast(rtnl, skb, pid);
456} 456}
457 457
458int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, 458void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
459 struct nlmsghdr *nlh, gfp_t flags) 459 struct nlmsghdr *nlh, gfp_t flags)
460{ 460{
461 struct sock *rtnl = net->rtnl; 461 struct sock *rtnl = net->rtnl;
462 int report = 0; 462 int report = 0;
@@ -464,7 +464,7 @@ int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
464 if (nlh) 464 if (nlh)
465 report = nlmsg_report(nlh); 465 report = nlmsg_report(nlh);
466 466
467 return nlmsg_notify(rtnl, skb, pid, group, report, flags); 467 nlmsg_notify(rtnl, skb, pid, group, report, flags);
468} 468}
469 469
470void rtnl_set_sk_err(struct net *net, u32 group, int error) 470void rtnl_set_sk_err(struct net *net, u32 group, int error)
@@ -1246,7 +1246,8 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
1246 kfree_skb(skb); 1246 kfree_skb(skb);
1247 goto errout; 1247 goto errout;
1248 } 1248 }
1249 err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); 1249 rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
1250 return;
1250errout: 1251errout:
1251 if (err < 0) 1252 if (err < 0)
1252 rtnl_set_sk_err(net, RTNLGRP_LINK, err); 1253 rtnl_set_sk_err(net, RTNLGRP_LINK, err);