diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2009-02-25 02:18:28 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-25 02:18:28 -0500 |
commit | 1ce85fe402137824246bad03ff85f3913d565c17 (patch) | |
tree | 3a54c150e9616709a8f65270cd1f4aeecac4d48e /net/ipv6 | |
parent | 4fb0a54a55d34c28dc53c39567ce171166572699 (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/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 9 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 6 | ||||
-rw-r--r-- | net/ipv6/route.c | 5 |
3 files changed, 10 insertions, 10 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 03e2a1ad71e9..f8f76d6e21cb 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3638,7 +3638,8 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | |||
3638 | kfree_skb(skb); | 3638 | kfree_skb(skb); |
3639 | goto errout; | 3639 | goto errout; |
3640 | } | 3640 | } |
3641 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3641 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3642 | return; | ||
3642 | errout: | 3643 | errout: |
3643 | if (err < 0) | 3644 | if (err < 0) |
3644 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); | 3645 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
@@ -3849,7 +3850,8 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | |||
3849 | kfree_skb(skb); | 3850 | kfree_skb(skb); |
3850 | goto errout; | 3851 | goto errout; |
3851 | } | 3852 | } |
3852 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3853 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3854 | return; | ||
3853 | errout: | 3855 | errout: |
3854 | if (err < 0) | 3856 | if (err < 0) |
3855 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); | 3857 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
@@ -3919,7 +3921,8 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3919 | kfree_skb(skb); | 3921 | kfree_skb(skb); |
3920 | goto errout; | 3922 | goto errout; |
3921 | } | 3923 | } |
3922 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); | 3924 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); |
3925 | return; | ||
3923 | errout: | 3926 | errout: |
3924 | if (err < 0) | 3927 | if (err < 0) |
3925 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); | 3928 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3cd83b85e9ef..9f061d1adbc2 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1095,11 +1095,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) | |||
1095 | &ipv6_hdr(ra)->saddr); | 1095 | &ipv6_hdr(ra)->saddr); |
1096 | nlmsg_end(skb, nlh); | 1096 | nlmsg_end(skb, nlh); |
1097 | 1097 | ||
1098 | err = rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, | 1098 | rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, GFP_ATOMIC); |
1099 | GFP_ATOMIC); | ||
1100 | if (err < 0) | ||
1101 | goto errout; | ||
1102 | |||
1103 | return; | 1099 | return; |
1104 | 1100 | ||
1105 | nla_put_failure: | 1101 | nla_put_failure: |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c3d486a3edad..1394ddb6e35c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2400,8 +2400,9 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2400 | kfree_skb(skb); | 2400 | kfree_skb(skb); |
2401 | goto errout; | 2401 | goto errout; |
2402 | } | 2402 | } |
2403 | err = rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, | 2403 | rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, |
2404 | info->nlh, gfp_any()); | 2404 | info->nlh, gfp_any()); |
2405 | return; | ||
2405 | errout: | 2406 | errout: |
2406 | if (err < 0) | 2407 | if (err < 0) |
2407 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); | 2408 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); |