|
21 | 21 | static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
|
22 | 22 | const struct nlmsghdr *nlh, struct inet_diag_req *req)
|
23 | 23 | {
|
24 |
| - return 0; |
| 24 | + int err = -EINVAL; |
| 25 | + struct sock *sk; |
| 26 | + struct sk_buff *rep; |
| 27 | + |
| 28 | + if (req->sdiag_family == AF_INET) |
| 29 | + sk = __udp4_lib_lookup(&init_net, |
| 30 | + req->id.idiag_src[0], req->id.idiag_sport, |
| 31 | + req->id.idiag_dst[0], req->id.idiag_dport, |
| 32 | + req->id.idiag_if, tbl); |
| 33 | + else if (req->sdiag_family == AF_INET6) |
| 34 | + sk = __udp6_lib_lookup(&init_net, |
| 35 | + (struct in6_addr *)req->id.idiag_src, |
| 36 | + req->id.idiag_sport, |
| 37 | + (struct in6_addr *)req->id.idiag_dst, |
| 38 | + req->id.idiag_dport, |
| 39 | + req->id.idiag_if, tbl); |
| 40 | + else |
| 41 | + goto out_nosk; |
| 42 | + |
| 43 | + err = -ENOENT; |
| 44 | + if (sk == NULL) |
| 45 | + goto out_nosk; |
| 46 | + |
| 47 | + err = inet_diag_check_cookie(sk, req); |
| 48 | + if (err) |
| 49 | + goto out; |
| 50 | + |
| 51 | + err = -ENOMEM; |
| 52 | + rep = alloc_skb(NLMSG_SPACE((sizeof(struct inet_diag_msg) + |
| 53 | + sizeof(struct inet_diag_meminfo) + |
| 54 | + 64)), GFP_KERNEL); |
| 55 | + if (!rep) |
| 56 | + goto out; |
| 57 | + |
| 58 | + err = inet_sk_diag_fill(sk, NULL, rep, req, |
| 59 | + NETLINK_CB(in_skb).pid, |
| 60 | + nlh->nlmsg_seq, 0, nlh); |
| 61 | + if (err < 0) { |
| 62 | + WARN_ON(err == -EMSGSIZE); |
| 63 | + kfree_skb(rep); |
| 64 | + goto out; |
| 65 | + } |
| 66 | + err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, |
| 67 | + MSG_DONTWAIT); |
| 68 | + if (err > 0) |
| 69 | + err = 0; |
| 70 | +out: |
| 71 | + if (sk) |
| 72 | + sock_put(sk); |
| 73 | +out_nosk: |
| 74 | + return err; |
25 | 75 | }
|
26 | 76 |
|
27 | 77 | static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlink_callback *cb,
|
|
0 commit comments