|
@@ -8,40 +8,31 @@
|
|
|
#include <net/af_unix.h>
|
|
|
#include <net/tcp_states.h>
|
|
|
|
|
|
-#define UNIX_DIAG_PUT(skb, attrtype, attrlen) \
|
|
|
- RTA_DATA(__RTA_PUT(skb, attrtype, attrlen))
|
|
|
-
|
|
|
static int sk_diag_dump_name(struct sock *sk, struct sk_buff *nlskb)
|
|
|
{
|
|
|
struct unix_address *addr = unix_sk(sk)->addr;
|
|
|
- char *s;
|
|
|
-
|
|
|
- if (addr) {
|
|
|
- s = UNIX_DIAG_PUT(nlskb, UNIX_DIAG_NAME, addr->len - sizeof(short));
|
|
|
- memcpy(s, addr->name->sun_path, addr->len - sizeof(short));
|
|
|
- }
|
|
|
|
|
|
- return 0;
|
|
|
+ if (!addr)
|
|
|
+ return 0;
|
|
|
|
|
|
-rtattr_failure:
|
|
|
- return -EMSGSIZE;
|
|
|
+ return nla_put(nlskb, UNIX_DIAG_NAME, addr->len - sizeof(short),
|
|
|
+ addr->name->sun_path);
|
|
|
}
|
|
|
|
|
|
static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb)
|
|
|
{
|
|
|
struct dentry *dentry = unix_sk(sk)->path.dentry;
|
|
|
- struct unix_diag_vfs *uv;
|
|
|
|
|
|
if (dentry) {
|
|
|
- uv = UNIX_DIAG_PUT(nlskb, UNIX_DIAG_VFS, sizeof(*uv));
|
|
|
- uv->udiag_vfs_ino = dentry->d_inode->i_ino;
|
|
|
- uv->udiag_vfs_dev = dentry->d_sb->s_dev;
|
|
|
+ struct unix_diag_vfs uv = {
|
|
|
+ .udiag_vfs_ino = dentry->d_inode->i_ino,
|
|
|
+ .udiag_vfs_dev = dentry->d_sb->s_dev,
|
|
|
+ };
|
|
|
+
|
|
|
+ return nla_put(nlskb, UNIX_DIAG_VFS, sizeof(uv), &uv);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
-
|
|
|
-rtattr_failure:
|
|
|
- return -EMSGSIZE;
|
|
|
}
|
|
|
|
|
|
static int sk_diag_dump_peer(struct sock *sk, struct sk_buff *nlskb)
|
|
@@ -56,24 +47,28 @@ static int sk_diag_dump_peer(struct sock *sk, struct sk_buff *nlskb)
|
|
|
unix_state_unlock(peer);
|
|
|
sock_put(peer);
|
|
|
|
|
|
- RTA_PUT_U32(nlskb, UNIX_DIAG_PEER, ino);
|
|
|
+ return nla_put_u32(nlskb, UNIX_DIAG_PEER, ino);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
-rtattr_failure:
|
|
|
- return -EMSGSIZE;
|
|
|
}
|
|
|
|
|
|
static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb)
|
|
|
{
|
|
|
struct sk_buff *skb;
|
|
|
+ struct nlattr *attr;
|
|
|
u32 *buf;
|
|
|
int i;
|
|
|
|
|
|
if (sk->sk_state == TCP_LISTEN) {
|
|
|
spin_lock(&sk->sk_receive_queue.lock);
|
|
|
- buf = UNIX_DIAG_PUT(nlskb, UNIX_DIAG_ICONS,
|
|
|
- sk->sk_receive_queue.qlen * sizeof(u32));
|
|
|
+
|
|
|
+ attr = nla_reserve(nlskb, UNIX_DIAG_ICONS,
|
|
|
+ sk->sk_receive_queue.qlen * sizeof(u32));
|
|
|
+ if (!attr)
|
|
|
+ goto errout;
|
|
|
+
|
|
|
+ buf = nla_data(attr);
|
|
|
i = 0;
|
|
|
skb_queue_walk(&sk->sk_receive_queue, skb) {
|
|
|
struct sock *req, *peer;
|
|
@@ -94,45 +89,38 @@ static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
-rtattr_failure:
|
|
|
+errout:
|
|
|
spin_unlock(&sk->sk_receive_queue.lock);
|
|
|
return -EMSGSIZE;
|
|
|
}
|
|
|
|
|
|
static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb)
|
|
|
{
|
|
|
- struct unix_diag_rqlen *rql;
|
|
|
-
|
|
|
- rql = UNIX_DIAG_PUT(nlskb, UNIX_DIAG_RQLEN, sizeof(*rql));
|
|
|
+ struct unix_diag_rqlen rql;
|
|
|
|
|
|
if (sk->sk_state == TCP_LISTEN) {
|
|
|
- rql->udiag_rqueue = sk->sk_receive_queue.qlen;
|
|
|
- rql->udiag_wqueue = sk->sk_max_ack_backlog;
|
|
|
+ rql.udiag_rqueue = sk->sk_receive_queue.qlen;
|
|
|
+ rql.udiag_wqueue = sk->sk_max_ack_backlog;
|
|
|
} else {
|
|
|
- rql->udiag_rqueue = (__u32)unix_inq_len(sk);
|
|
|
- rql->udiag_wqueue = (__u32)unix_outq_len(sk);
|
|
|
+ rql.udiag_rqueue = (u32) unix_inq_len(sk);
|
|
|
+ rql.udiag_wqueue = (u32) unix_outq_len(sk);
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
-
|
|
|
-rtattr_failure:
|
|
|
- return -EMSGSIZE;
|
|
|
+ return nla_put(nlskb, UNIX_DIAG_RQLEN, sizeof(rql), &rql);
|
|
|
}
|
|
|
|
|
|
static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req,
|
|
|
u32 pid, u32 seq, u32 flags, int sk_ino)
|
|
|
{
|
|
|
- unsigned char *b = skb_tail_pointer(skb);
|
|
|
struct nlmsghdr *nlh;
|
|
|
struct unix_diag_msg *rep;
|
|
|
|
|
|
- nlh = nlmsg_put(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep), 0);
|
|
|
+ nlh = nlmsg_put(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep),
|
|
|
+ flags);
|
|
|
if (!nlh)
|
|
|
- goto out_nlmsg_trim;
|
|
|
- nlh->nlmsg_flags = flags;
|
|
|
+ return -EMSGSIZE;
|
|
|
|
|
|
rep = nlmsg_data(nlh);
|
|
|
-
|
|
|
rep->udiag_family = AF_UNIX;
|
|
|
rep->udiag_type = sk->sk_type;
|
|
|
rep->udiag_state = sk->sk_state;
|
|
@@ -163,11 +151,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
|
|
|
sock_diag_put_meminfo(sk, skb, UNIX_DIAG_MEMINFO))
|
|
|
goto out_nlmsg_trim;
|
|
|
|
|
|
- nlh->nlmsg_len = skb_tail_pointer(skb) - b;
|
|
|
- return skb->len;
|
|
|
+ return nlmsg_end(skb, nlh);
|
|
|
|
|
|
out_nlmsg_trim:
|
|
|
- nlmsg_trim(skb, b);
|
|
|
+ nlmsg_cancel(skb, nlh);
|
|
|
return -EMSGSIZE;
|
|
|
}
|
|
|
|
|
@@ -272,15 +259,14 @@ static int unix_diag_get_exact(struct sk_buff *in_skb,
|
|
|
extra_len = 256;
|
|
|
again:
|
|
|
err = -ENOMEM;
|
|
|
- rep = alloc_skb(NLMSG_SPACE((sizeof(struct unix_diag_msg) + extra_len)),
|
|
|
- GFP_KERNEL);
|
|
|
+ rep = nlmsg_new(sizeof(struct unix_diag_msg) + extra_len, GFP_KERNEL);
|
|
|
if (!rep)
|
|
|
goto out;
|
|
|
|
|
|
err = sk_diag_fill(sk, rep, req, NETLINK_CB(in_skb).pid,
|
|
|
nlh->nlmsg_seq, 0, req->udiag_ino);
|
|
|
if (err < 0) {
|
|
|
- kfree_skb(rep);
|
|
|
+ nlmsg_free(rep);
|
|
|
extra_len += 256;
|
|
|
if (extra_len >= PAGE_SIZE)
|
|
|
goto out;
|