aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2008-03-21 18:46:12 -0400
committerDavid S. Miller <davem@davemloft.net>2008-03-21 18:46:12 -0400
commitb1153f29ee07dc1a788964409255a4b4fae50b98 (patch)
tree3e9c09804e805da77d225a8508c28e064a310c45
parent6f8b13bcb3369a5df2e63acc422bed6098f5b8c4 (diff)
netlink: make socket filters work on netlink
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>
-rw-r--r--net/netlink/af_netlink.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 524e826bb976..86bd8660a8f2 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -886,6 +886,13 @@ retry:
886 if (netlink_is_kernel(sk)) 886 if (netlink_is_kernel(sk))
887 return netlink_unicast_kernel(sk, skb); 887 return netlink_unicast_kernel(sk, skb);
888 888
889 if (sk_filter(sk, skb)) {
890 int err = skb->len;
891 kfree_skb(skb);
892 sock_put(sk);
893 return err;
894 }
895
889 err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk); 896 err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk);
890 if (err == 1) 897 if (err == 1)
891 goto retry; 898 goto retry;
@@ -980,6 +987,9 @@ static inline int do_one_broadcast(struct sock *sk,
980 netlink_overrun(sk); 987 netlink_overrun(sk);
981 /* Clone failed. Notify ALL listeners. */ 988 /* Clone failed. Notify ALL listeners. */
982 p->failure = 1; 989 p->failure = 1;
990 } else if (sk_filter(sk, p->skb2)) {
991 kfree_skb(p->skb2);
992 p->skb2 = NULL;
983 } else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) { 993 } else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
984 netlink_overrun(sk); 994 netlink_overrun(sk);
985 } else { 995 } else {
@@ -1533,8 +1543,13 @@ static int netlink_dump(struct sock *sk)
1533 1543
1534 if (len > 0) { 1544 if (len > 0) {
1535 mutex_unlock(nlk->cb_mutex); 1545 mutex_unlock(nlk->cb_mutex);
1536 skb_queue_tail(&sk->sk_receive_queue, skb); 1546
1537 sk->sk_data_ready(sk, len); 1547 if (sk_filter(sk, skb))
1548 kfree_skb(skb);
1549 else {
1550 skb_queue_tail(&sk->sk_receive_queue, skb);
1551 sk->sk_data_ready(sk, skb->len);
1552 }
1538 return 0; 1553 return 0;
1539 } 1554 }
1540 1555
@@ -1544,8 +1559,12 @@ static int netlink_dump(struct sock *sk)
1544 1559
1545 memcpy(nlmsg_data(nlh), &len, sizeof(len)); 1560 memcpy(nlmsg_data(nlh), &len, sizeof(len));
1546 1561
1547 skb_queue_tail(&sk->sk_receive_queue, skb); 1562 if (sk_filter(sk, skb))
1548 sk->sk_data_ready(sk, skb->len); 1563 kfree_skb(skb);
1564 else {
1565 skb_queue_tail(&sk->sk_receive_queue, skb);
1566 sk->sk_data_ready(sk, skb->len);
1567 }
1549 1568
1550 if (cb->done) 1569 if (cb->done)
1551 cb->done(cb); 1570 cb->done(cb);