Skip to content

Commit be0c22a

Browse files
ummakynesdavem330
authored andcommitted
netlink: add NETLINK_BROADCAST_ERROR socket option
This patch adds NETLINK_BROADCAST_ERROR which is a netlink socket option that the listener can set to make netlink_broadcast() return errors in the delivery to the caller. This option is useful if the caller of netlink_broadcast() do something with the result of the message delivery, like in ctnetlink where it drops a network packet if the event delivery failed, this is used to enable reliable logging and state-synchronization. If this socket option is not set, netlink_broadcast() only reports ESRCH errors and silently ignore ENOBUFS errors, which is what most netlink_broadcast() callers should do. This socket option is based on a suggestion from Patrick McHardy. Patrick McHardy can exchange this patch for a beer from me ;). Signed-off-by: Pablo Neira Ayuso <[email protected]> Acked-by: Patrick McHardy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2d96cf8 commit be0c22a

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

include/linux/netlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ struct nlmsgerr
103103
#define NETLINK_ADD_MEMBERSHIP 1
104104
#define NETLINK_DROP_MEMBERSHIP 2
105105
#define NETLINK_PKTINFO 3
106+
#define NETLINK_BROADCAST_ERROR 4
106107

107108
struct nl_pktinfo
108109
{

net/netlink/af_netlink.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct netlink_sock {
8585

8686
#define NETLINK_KERNEL_SOCKET 0x1
8787
#define NETLINK_RECV_PKTINFO 0x2
88+
#define NETLINK_BROADCAST_SEND_ERROR 0x4
8889

8990
static inline struct netlink_sock *nlk_sk(struct sock *sk)
9091
{
@@ -995,12 +996,15 @@ static inline int do_one_broadcast(struct sock *sk,
995996
netlink_overrun(sk);
996997
/* Clone failed. Notify ALL listeners. */
997998
p->failure = 1;
999+
if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR)
1000+
p->delivery_failure = 1;
9981001
} else if (sk_filter(sk, p->skb2)) {
9991002
kfree_skb(p->skb2);
10001003
p->skb2 = NULL;
10011004
} else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
10021005
netlink_overrun(sk);
1003-
p->delivery_failure = 1;
1006+
if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR)
1007+
p->delivery_failure = 1;
10041008
} else {
10051009
p->congested |= val;
10061010
p->delivered = 1;
@@ -1048,7 +1052,7 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
10481052
if (info.skb2)
10491053
kfree_skb(info.skb2);
10501054

1051-
if (info.delivery_failure || info.failure)
1055+
if (info.delivery_failure)
10521056
return -ENOBUFS;
10531057

10541058
if (info.delivered) {
@@ -1163,6 +1167,13 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
11631167
err = 0;
11641168
break;
11651169
}
1170+
case NETLINK_BROADCAST_ERROR:
1171+
if (val)
1172+
nlk->flags |= NETLINK_BROADCAST_SEND_ERROR;
1173+
else
1174+
nlk->flags &= ~NETLINK_BROADCAST_SEND_ERROR;
1175+
err = 0;
1176+
break;
11661177
default:
11671178
err = -ENOPROTOOPT;
11681179
}
@@ -1195,6 +1206,16 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
11951206
return -EFAULT;
11961207
err = 0;
11971208
break;
1209+
case NETLINK_BROADCAST_ERROR:
1210+
if (len < sizeof(int))
1211+
return -EINVAL;
1212+
len = sizeof(int);
1213+
val = nlk->flags & NETLINK_BROADCAST_SEND_ERROR ? 1 : 0;
1214+
if (put_user(len, optlen) ||
1215+
put_user(val, optval))
1216+
return -EFAULT;
1217+
err = 0;
1218+
break;
11981219
default:
11991220
err = -ENOPROTOOPT;
12001221
}

0 commit comments

Comments
 (0)