1 #include <linux/types.h> 2 #include <linux/spinlock.h> 3 #include <linux/sock_diag.h> 4 #include <linux/unix_diag.h> 5 #include <linux/skbuff.h> 6 #include <net/netlink.h> 7 #include <net/af_unix.h> 8 #include <net/tcp_states.h> 9 10 #define UNIX_DIAG_PUT(skb, attrtype, attrlen) \ 11 RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) 12 13 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req, 14 u32 pid, u32 seq, u32 flags, int sk_ino) 15 { 16 unsigned char *b = skb_tail_pointer(skb); 17 struct nlmsghdr *nlh; 18 struct unix_diag_msg *rep; 19 20 nlh = NLMSG_PUT(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep)); 21 nlh->nlmsg_flags = flags; 22 23 rep = NLMSG_DATA(nlh); 24 25 rep->udiag_family = AF_UNIX; 26 rep->udiag_type = sk->sk_type; 27 rep->udiag_state = sk->sk_state; 28 rep->udiag_ino = sk_ino; 29 sock_diag_save_cookie(sk, rep->udiag_cookie); 30 31 nlh->nlmsg_len = skb_tail_pointer(skb) - b; 32 return skb->len; 33 34 nlmsg_failure: 35 nlmsg_trim(skb, b); 36 return -EMSGSIZE; 37 } 38 39 static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req, 40 u32 pid, u32 seq, u32 flags) 41 { 42 int sk_ino; 43 44 unix_state_lock(sk); 45 sk_ino = sock_i_ino(sk); 46 unix_state_unlock(sk); 47 48 if (!sk_ino) 49 return 0; 50 51 return sk_diag_fill(sk, skb, req, pid, seq, flags, sk_ino); 52 } 53 54 static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) 55 { 56 struct unix_diag_req *req; 57 int num, s_num, slot, s_slot; 58 59 req = NLMSG_DATA(cb->nlh); 60 61 s_slot = cb->args[0]; 62 num = s_num = cb->args[1]; 63 64 spin_lock(&unix_table_lock); 65 for (slot = s_slot; slot <= UNIX_HASH_SIZE; s_num = 0, slot++) { 66 struct sock *sk; 67 struct hlist_node *node; 68 69 num = 0; 70 sk_for_each(sk, node, &unix_socket_table[slot]) { 71 if (num < s_num) 72 goto next; 73 if (!(req->udiag_states & (1 << sk->sk_state))) 74 goto next; 75 if (sk_diag_dump(sk, skb, req, 76 NETLINK_CB(cb->skb).pid, 77 cb->nlh->nlmsg_seq, 78 NLM_F_MULTI) < 0) 79 goto done; 80 next: 81 num++; 82 } 83 } 84 done: 85 spin_unlock(&unix_table_lock); 86 cb->args[0] = slot; 87 cb->args[1] = num; 88 89 return skb->len; 90 } 91 92 static struct sock *unix_lookup_by_ino(int ino) 93 { 94 int i; 95 struct sock *sk; 96 97 spin_lock(&unix_table_lock); 98 for (i = 0; i <= UNIX_HASH_SIZE; i++) { 99 struct hlist_node *node; 100 101 sk_for_each(sk, node, &unix_socket_table[i]) 102 if (ino == sock_i_ino(sk)) { 103 sock_hold(sk); 104 spin_unlock(&unix_table_lock); 105 106 return sk; 107 } 108 } 109 110 spin_unlock(&unix_table_lock); 111 return NULL; 112 } 113 114 static int unix_diag_get_exact(struct sk_buff *in_skb, 115 const struct nlmsghdr *nlh, 116 struct unix_diag_req *req) 117 { 118 int err = -EINVAL; 119 struct sock *sk; 120 struct sk_buff *rep; 121 unsigned int extra_len; 122 123 if (req->udiag_ino == 0) 124 goto out_nosk; 125 126 sk = unix_lookup_by_ino(req->udiag_ino); 127 err = -ENOENT; 128 if (sk == NULL) 129 goto out_nosk; 130 131 err = sock_diag_check_cookie(sk, req->udiag_cookie); 132 if (err) 133 goto out; 134 135 extra_len = 256; 136 again: 137 err = -ENOMEM; 138 rep = alloc_skb(NLMSG_SPACE((sizeof(struct unix_diag_msg) + extra_len)), 139 GFP_KERNEL); 140 if (!rep) 141 goto out; 142 143 err = sk_diag_fill(sk, rep, req, NETLINK_CB(in_skb).pid, 144 nlh->nlmsg_seq, 0, req->udiag_ino); 145 if (err < 0) { 146 kfree_skb(rep); 147 extra_len += 256; 148 if (extra_len >= PAGE_SIZE) 149 goto out; 150 151 goto again; 152 } 153 err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, 154 MSG_DONTWAIT); 155 if (err > 0) 156 err = 0; 157 out: 158 if (sk) 159 sock_put(sk); 160 out_nosk: 161 return err; 162 } 163 164 static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) 165 { 166 int hdrlen = sizeof(struct unix_diag_req); 167 168 if (nlmsg_len(h) < hdrlen) 169 return -EINVAL; 170 171 if (h->nlmsg_flags & NLM_F_DUMP) 172 return netlink_dump_start(sock_diag_nlsk, skb, h, 173 unix_diag_dump, NULL, 0); 174 else 175 return unix_diag_get_exact(skb, h, (struct unix_diag_req *)NLMSG_DATA(h)); 176 } 177 178 static struct sock_diag_handler unix_diag_handler = { 179 .family = AF_UNIX, 180 .dump = unix_diag_handler_dump, 181 }; 182 183 static int __init unix_diag_init(void) 184 { 185 return sock_diag_register(&unix_diag_handler); 186 } 187 188 static void __exit unix_diag_exit(void) 189 { 190 sock_diag_unregister(&unix_diag_handler); 191 } 192 193 module_init(unix_diag_init); 194 module_exit(unix_diag_exit); 195 MODULE_LICENSE("GPL"); 196 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 1 /* AF_LOCAL */); 197