From 3f7aaa552842c3f39035be95caf1edf3c5c745eb Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 9 Dec 2011 06:24:21 +0000 Subject: [PATCH] --- yaml --- r: 278551 b: refs/heads/master c: b6d640c2286d16b15a21a4475c896cdce6a0bbe0 h: refs/heads/master i: 278549: 5f7846b1f0ef01edabd885c0d17a9c5e106e2b2d 278547: f01425cc5828a65a9155d8f12db677b65ec5d975 278543: 8c3f7ad38f78e4bd72d3005eb95ac125a7248423 v: v3 --- [refs] | 2 +- trunk/net/ipv4/udp_diag.c | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 8e7569705258..d6968a46c16a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a925aa00a55e3b72bd38bfdd3d6f97c0d900c949 +refs/heads/master: b6d640c2286d16b15a21a4475c896cdce6a0bbe0 diff --git a/trunk/net/ipv4/udp_diag.c b/trunk/net/ipv4/udp_diag.c index caa164dcd30f..65063444a119 100644 --- a/trunk/net/ipv4/udp_diag.c +++ b/trunk/net/ipv4/udp_diag.c @@ -18,6 +18,17 @@ #include #include +static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, + struct netlink_callback *cb, struct inet_diag_req *req, + struct nlattr *bc) +{ + if (!inet_diag_bc_sk(bc, sk)) + return 0; + + return inet_sk_diag_fill(sk, NULL, skb, req, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); +} + static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, const struct nlmsghdr *nlh, struct inet_diag_req *req) { @@ -77,6 +88,49 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlink_callback *cb, struct inet_diag_req *r, struct nlattr *bc) { + int num, s_num, slot, s_slot; + + s_slot = cb->args[0]; + num = s_num = cb->args[1]; + + for (slot = s_slot; slot <= table->mask; num = s_num = 0, slot++) { + struct sock *sk; + struct hlist_nulls_node *node; + struct udp_hslot *hslot = &table->hash[slot]; + + if (hlist_nulls_empty(&hslot->head)) + continue; + + spin_lock_bh(&hslot->lock); + sk_nulls_for_each(sk, node, &hslot->head) { + struct inet_sock *inet = inet_sk(sk); + + if (num < s_num) + goto next; + if (!(r->idiag_states & (1 << sk->sk_state))) + goto next; + if (r->sdiag_family != AF_UNSPEC && + sk->sk_family != r->sdiag_family) + goto next; + if (r->id.idiag_sport != inet->inet_sport && + r->id.idiag_sport) + goto next; + if (r->id.idiag_dport != inet->inet_dport && + r->id.idiag_dport) + goto next; + + if (sk_diag_dump(sk, skb, cb, r, bc) < 0) { + spin_unlock_bh(&hslot->lock); + goto done; + } +next: + num++; + } + spin_unlock_bh(&hslot->lock); + } +done: + cb->args[0] = slot; + cb->args[1] = num; } static void udp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,