Skip to content

Commit

Permalink
netlink: make socket filters work on netlink
Browse files Browse the repository at this point in the history
Make socket filters work for netlink unicast and notifications.
This is useful for applications like Zebra that get overrun with
messages that are then ignored.

Note: netlink messages are in host byte order, but packet filter
state machine operations are done as network byte order.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Stephen Hemminger authored and David S. Miller committed Mar 21, 2008
1 parent 6f8b13b commit b1153f2
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions net/netlink/af_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,13 @@ int netlink_unicast(struct sock *ssk, struct sk_buff *skb,
if (netlink_is_kernel(sk))
return netlink_unicast_kernel(sk, skb);

if (sk_filter(sk, skb)) {
int err = skb->len;
kfree_skb(skb);
sock_put(sk);
return err;
}

err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk);
if (err == 1)
goto retry;
Expand Down Expand Up @@ -980,6 +987,9 @@ static inline int do_one_broadcast(struct sock *sk,
netlink_overrun(sk);
/* Clone failed. Notify ALL listeners. */
p->failure = 1;
} else if (sk_filter(sk, p->skb2)) {
kfree_skb(p->skb2);
p->skb2 = NULL;
} else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
netlink_overrun(sk);
} else {
Expand Down Expand Up @@ -1533,8 +1543,13 @@ static int netlink_dump(struct sock *sk)

if (len > 0) {
mutex_unlock(nlk->cb_mutex);
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, len);

if (sk_filter(sk, skb))
kfree_skb(skb);
else {
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, skb->len);
}
return 0;
}

Expand All @@ -1544,8 +1559,12 @@ static int netlink_dump(struct sock *sk)

memcpy(nlmsg_data(nlh), &len, sizeof(len));

skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, skb->len);
if (sk_filter(sk, skb))
kfree_skb(skb);
else {
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, skb->len);
}

if (cb->done)
cb->done(cb);
Expand Down

0 comments on commit b1153f2

Please sign in to comment.