1SOCK_DIAG(7) Linux Programmer's Manual SOCK_DIAG(7)
2
3
4
6 sock_diag - obtaining information about sockets
7
9 #include <sys/socket.h>
10 #include <linux/sock_diag.h>
11 #include <linux/unix_diag.h> /* for UNIX domain sockets */
12 #include <linux/inet_diag.h> /* for IPv4 and IPv6 sockets */
13
14 diag_socket = socket(AF_NETLINK, socket_type, NETLINK_SOCK_DIAG);
15
17 The sock_diag netlink subsystem provides a mechanism for obtaining
18 information about sockets of various address families from the kernel.
19 This subsystem can be used to obtain information about individual sock‐
20 ets or request a list of sockets.
21
22 In the request, the caller can specify additional information it would
23 like to obtain about the socket, for example, memory information or
24 information specific to the address family.
25
26 When requesting a list of sockets, the caller can specify filters that
27 would be applied by the kernel to select a subset of sockets to report.
28 For now, there is only the ability to filter sockets by state (con‐
29 nected, listening, and so on.)
30
31 Note that sock_diag reports only those sockets that have a name; that
32 is, either sockets bound explicitly with bind(2) or sockets that were
33 automatically bound to an address (e.g., by connect(2)). This is the
34 same set of sockets that is available via /proc/net/unix,
35 /proc/net/tcp, /proc/net/udp, and so on.
36
37 Request
38 The request starts with a struct nlmsghdr header described in
39 netlink(7) with nlmsg_type field set to SOCK_DIAG_BY_FAMILY. It is
40 followed by a header specific to the address family that starts with a
41 common part shared by all address families:
42
43 struct sock_diag_req {
44 __u8 sdiag_family;
45 __u8 sdiag_protocol;
46 };
47
48 The fields of this structure are as follows:
49
50 sdiag_family
51 An address family. It should be set to the appropriate AF_*
52 constant.
53
54 sdiag_protocol
55 Depends on sdiag_family. It should be set to the appropriate
56 IPPROTO_* constant for AF_INET and AF_INET6, and to 0 otherwise.
57
58 If the nlmsg_flags field of the struct nlmsghdr header has the
59 NLM_F_DUMP flag set, it means that a list of sockets is being
60 requested; otherwise it is a query about an individual socket.
61
62 Response
63 The response starts with a struct nlmsghdr header and is followed by an
64 array of objects specific to the address family. The array is to be
65 accessed with the standard NLMSG_* macros from the netlink(3) API.
66
67 Each object is the NLA (netlink attributes) list that is to be accessed
68 with the RTA_* macros from rtnetlink(3) API.
69
70 UNIX domain sockets
71 For UNIX domain sockets the request is represented in the following
72 structure:
73
74 struct unix_diag_req {
75 __u8 sdiag_family;
76 __u8 sdiag_protocol;
77 __u16 pad;
78 __u32 udiag_states;
79 __u32 udiag_ino;
80 __u32 udiag_show;
81 __u32 udiag_cookie[2];
82 };
83
84 The fields of this structure are as follows:
85
86 sdiag_family
87 The address family; it should be set to AF_UNIX.
88
89 sdiag_protocol
90 pad These fields should be set to 0.
91
92 udiag_states
93 This is a bit mask that defines a filter of sockets states.
94 Only those sockets whose states are in this mask will be
95 reported. Ignored when querying for an individual socket. Sup‐
96 ported values are:
97
98 1 << TCP_ESTABLISHED
99
100 1 << TCP_LISTEN
101
102 udiag_ino
103 This is an inode number when querying for an individual socket.
104 Ignored when querying for a list of sockets.
105
106 udiag_show
107 This is a set of flags defining what kind of information to
108 report. Each requested kind of information is reported back as
109 a netlink attribute as described below:
110
111 UDIAG_SHOW_NAME
112 The attribute reported in answer to this request is
113 UNIX_DIAG_NAME. The payload associated with this
114 attribute is the pathname to which the socket was bound
115 (a sequence of bytes up to UNIX_PATH_MAX length).
116
117 UDIAG_SHOW_VFS
118 The attribute reported in answer to this request is
119 UNIX_DIAG_VFS. The payload associated with this
120 attribute is represented in the following structure:
121
122 struct unix_diag_vfs {
123 __u32 udiag_vfs_dev;
124 __u32 udiag_vfs_ino;
125 };
126
127 The fields of this structure are as follows:
128
129 udiag_vfs_dev
130 The device number of the corresponding on-disk
131 socket inode.
132
133 udiag_vfs_ino
134 The inode number of the corresponding on-disk
135 socket inode.
136
137 UDIAG_SHOW_PEER
138 The attribute reported in answer to this request is
139 UNIX_DIAG_PEER. The payload associated with this
140 attribute is a __u32 value which is the peer's inode num‐
141 ber. This attribute is reported for connected sockets
142 only.
143
144 UDIAG_SHOW_ICONS
145 The attribute reported in answer to this request is
146 UNIX_DIAG_ICONS. The payload associated with this
147 attribute is an array of __u32 values which are inode
148 numbers of sockets that has passed the connect(2) call,
149 but hasn't been processed with accept(2) yet. This
150 attribute is reported for listening sockets only.
151
152 UDIAG_SHOW_RQLEN
153 The attribute reported in answer to this request is
154 UNIX_DIAG_RQLEN. The payload associated with this
155 attribute is represented in the following structure:
156
157 struct unix_diag_rqlen {
158 __u32 udiag_rqueue;
159 __u32 udiag_wqueue;
160 };
161
162 The fields of this structure are as follows:
163
164 udiag_rqueue
165 For listening sockets: the number of pending con‐
166 nections. The length of the array associated with
167 the UNIX_DIAG_ICONS response attribute is equal to
168 this value.
169
170 For established sockets: the amount of data in
171 incoming queue.
172
173 udiag_wqueue
174 For listening sockets: the backlog length which
175 equals to the value passed as the second argument
176 to listen(2).
177
178 For established sockets: the amount of memory
179 available for sending.
180
181 UDIAG_SHOW_MEMINFO
182 The attribute reported in answer to this request is
183 UNIX_DIAG_MEMINFO. The payload associated with this
184 attribute is an array of __u32 values described below in
185 the subsection "Socket memory information".
186
187 The following attributes are reported back without any specific
188 request:
189
190 UNIX_DIAG_SHUTDOWN
191 The payload associated with this attribute is __u8 value
192 which represents bits of shutdown(2) state.
193
194 udiag_cookie
195 This is an array of opaque identifiers that could be used along
196 with udiag_ino to specify an individual socket. It is ignored
197 when querying for a list of sockets, as well as when all its
198 elements are set to -1.
199
200 The response to a query for UNIX domain sockets is represented as an
201 array of
202
203 struct unix_diag_msg {
204 __u8 udiag_family;
205 __u8 udiag_type;
206 __u8 udiag_state;
207 __u8 pad;
208 __u32 udiag_ino;
209 __u32 udiag_cookie[2];
210 };
211
212 followed by netlink attributes.
213
214 The fields of this structure are as follows:
215
216 udiag_family
217 This field has the same meaning as in struct unix_diag_req.
218
219 udiag_type
220 This is set to one of SOCK_PACKET, SOCK_STREAM, or SOCK_SEQ‐
221 PACKET.
222
223 udiag_state
224 This is set to one of TCP_LISTEN or TCP_ESTABLISHED.
225
226 pad This field is set to 0.
227
228 udiag_ino
229 This is the socket inode number.
230
231 udiag_cookie
232 This is an array of opaque identifiers that could be used in
233 subsequent queries.
234
235 IPv4 and IPv6 sockets
236 For IPv4 and IPv6 sockets, the request is represented in the following
237 structure:
238
239 struct inet_diag_req_v2 {
240 __u8 sdiag_family;
241 __u8 sdiag_protocol;
242 __u8 idiag_ext;
243 __u8 pad;
244 __u32 idiag_states;
245 struct inet_diag_sockid id;
246 };
247
248 where struct inet_diag_sockid is defined as follows:
249
250 struct inet_diag_sockid {
251 __be16 idiag_sport;
252 __be16 idiag_dport;
253 __be32 idiag_src[4];
254 __be32 idiag_dst[4];
255 __u32 idiag_if;
256 __u32 idiag_cookie[2];
257 };
258
259 The fields of struct inet_diag_req_v2 are as follows:
260
261 sdiag_family
262 This should be set to either AF_INET or AF_INET6 for IPv4 or
263 IPv6 sockets respectively.
264
265 sdiag_protocol
266 This should be set to one of IPPROTO_TCP, IPPROTO_UDP, or
267 IPPROTO_UDPLITE.
268
269 idiag_ext
270 This is a set of flags defining what kind of extended informa‐
271 tion to report. Each requested kind of information is reported
272 back as a netlink attribute as described below:
273
274 INET_DIAG_TOS
275 The payload associated with this attribute is a __u8
276 value which is the TOS of the socket.
277
278 INET_DIAG_TCLASS
279 The payload associated with this attribute is a __u8
280 value which is the TClass of the socket. IPv6 sockets
281 only. For LISTEN and CLOSE sockets, this is followed by
282 INET_DIAG_SKV6ONLY attribute with associated __u8 payload
283 value meaning whether the socket is IPv6-only or not.
284
285 INET_DIAG_MEMINFO
286 The payload associated with this attribute is represented
287 in the following structure:
288
289 struct inet_diag_meminfo {
290 __u32 idiag_rmem;
291 __u32 idiag_wmem;
292 __u32 idiag_fmem;
293 __u32 idiag_tmem;
294 };
295
296 The fields of this structure are as follows:
297
298 idiag_rmem The amount of data in the receive queue.
299
300 idiag_wmem The amount of data that is queued by TCP but
301 not yet sent.
302
303 idiag_fmem The amount of memory scheduled for future use
304 (TCP only).
305
306 idiag_tmem The amount of data in send queue.
307
308 INET_DIAG_SKMEMINFO
309 The payload associated with this attribute is an array of
310 __u32 values described below in the subsection "Socket
311 memory information".
312
313 INET_DIAG_INFO
314 The payload associated with this attribute is specific to
315 the address family. For TCP sockets, it is an object of
316 type struct tcp_info.
317
318 INET_DIAG_CONG
319 The payload associated with this attribute is a string
320 that describes the congestion control algorithm used.
321 For TCP sockets only.
322
323 pad This should be set to 0.
324
325 idiag_states
326 This is a bit mask that defines a filter of socket states. Only
327 those sockets whose states are in this mask will be reported.
328 Ignored when querying for an individual socket.
329
330 id This is a socket ID object that is used in dump requests, in
331 queries about individual sockets, and is reported back in each
332 response. Unlike UNIX domain sockets, IPv4 and IPv6 sockets are
333 identified using addresses and ports. All values are in network
334 byte order.
335
336 The fields of struct inet_diag_sockid are as follows:
337
338 idiag_sport
339 The source port.
340
341 idiag_dport
342 The destination port.
343
344 idiag_src
345 The source address.
346
347 idiag_dst
348 The destination address.
349
350 idiag_if
351 The interface number the socket is bound to.
352
353 idiag_cookie
354 This is an array of opaque identifiers that could be used along
355 with other fields of this structure to specify an individual
356 socket. It is ignored when querying for a list of sockets, as
357 well as when all its elements are set to -1.
358
359 The response to a query for IPv4 or IPv6 sockets is represented as an
360 array of
361
362 struct inet_diag_msg {
363 __u8 idiag_family;
364 __u8 idiag_state;
365 __u8 idiag_timer;
366 __u8 idiag_retrans;
367
368 struct inet_diag_sockid id;
369
370 __u32 idiag_expires;
371 __u32 idiag_rqueue;
372 __u32 idiag_wqueue;
373 __u32 idiag_uid;
374 __u32 idiag_inode;
375 };
376
377 followed by netlink attributes.
378
379 The fields of this structure are as follows:
380
381 idiag_family
382 This is the same field as in struct inet_diag_req_v2.
383
384 idiag_state
385 This denotes socket state as in struct inet_diag_req_v2.
386
387 idiag_timer
388 For TCP sockets, this field describes the type of timer that is
389 currently active for the socket. It is set to one of the fol‐
390 lowing constants:
391
392 0 no timer is active
393 1 a retransmit timer
394 2 a keep-alive timer
395 3 a TIME_WAIT timer
396 4 a zero window probe timer
397
398 For non-TCP sockets, this field is set to 0.
399
400 idiag_retrans
401 For idiag_timer values 1, 2, and 4, this field contains the num‐
402 ber of retransmits. For other idiag_timer values, this field is
403 set to 0.
404
405 idiag_expires
406 For TCP sockets that have an active timer, this field describes
407 its expiration time in milliseconds. For other sockets, this
408 field is set to 0.
409
410 idiag_rqueue
411 For listening sockets: the number of pending connections.
412
413 For other sockets: the amount of data in the incoming queue.
414
415 idiag_wqueue
416 For listening sockets: the backlog length.
417
418 For other sockets: the amount of memory available for sending.
419
420 idiag_uid
421 This is the socket owner UID.
422
423 idiag_inode
424 This is the socket inode number.
425
426 Socket memory information
427 The payload associated with UNIX_DIAG_MEMINFO and INET_DIAG_SKMEMINFO
428 netlink attributes is an array of the following __u32 values:
429
430 SK_MEMINFO_RMEM_ALLOC
431 The amount of data in receive queue.
432
433 SK_MEMINFO_RCVBUF
434 The receive socket buffer as set by SO_RCVBUF.
435
436 SK_MEMINFO_WMEM_ALLOC
437 The amount of data in send queue.
438
439 SK_MEMINFO_SNDBUF
440 The send socket buffer as set by SO_SNDBUF.
441
442 SK_MEMINFO_FWD_ALLOC
443 The amount of memory scheduled for future use (TCP only).
444
445 SK_MEMINFO_WMEM_QUEUED
446 The amount of data queued by TCP, but not yet sent.
447
448 SK_MEMINFO_OPTMEM
449 The amount of memory allocated for the socket's service needs
450 (e.g., socket filter).
451
452 SK_MEMINFO_BACKLOG
453 The amount of packets in the backlog (not yet processed).
454
456 NETLINK_INET_DIAG was introduced in Linux 2.6.14 and supported AF_INET
457 and AF_INET6 sockets only. In Linux 3.3, it was renamed to
458 NETLINK_SOCK_DIAG and extended to support AF_UNIX sockets.
459
460 UNIX_DIAG_MEMINFO and INET_DIAG_SKMEMINFO were introduced in Linux 3.6.
461
463 The NETLINK_SOCK_DIAG API is Linux-specific.
464
466 The following example program prints inode number, peer's inode number,
467 and name of all UNIX domain sockets in the current namespace.
468
469 #include <errno.h>
470 #include <stdio.h>
471 #include <string.h>
472 #include <unistd.h>
473 #include <sys/socket.h>
474 #include <sys/un.h>
475 #include <linux/netlink.h>
476 #include <linux/rtnetlink.h>
477 #include <linux/sock_diag.h>
478 #include <linux/unix_diag.h>
479
480 static int
481 send_query(int fd)
482 {
483 struct sockaddr_nl nladdr = {
484 .nl_family = AF_NETLINK
485 };
486 struct
487 {
488 struct nlmsghdr nlh;
489 struct unix_diag_req udr;
490 } req = {
491 .nlh = {
492 .nlmsg_len = sizeof(req),
493 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
494 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP
495 },
496 .udr = {
497 .sdiag_family = AF_UNIX,
498 .udiag_states = -1,
499 .udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER
500 }
501 };
502 struct iovec iov = {
503 .iov_base = &req,
504 .iov_len = sizeof(req)
505 };
506 struct msghdr msg = {
507 .msg_name = (void *) &nladdr,
508 .msg_namelen = sizeof(nladdr),
509 .msg_iov = &iov,
510 .msg_iovlen = 1
511 };
512
513 for (;;) {
514 if (sendmsg(fd, &msg, 0) < 0) {
515 if (errno == EINTR)
516 continue;
517
518 perror("sendmsg");
519 return -1;
520 }
521
522 return 0;
523 }
524 }
525
526 static int
527 print_diag(const struct unix_diag_msg *diag, unsigned int len)
528 {
529 if (len < NLMSG_LENGTH(sizeof(*diag))) {
530 fputs("short response\n", stderr);
531 return -1;
532 }
533 if (diag->udiag_family != AF_UNIX) {
534 fprintf(stderr, "unexpected family %u\n", diag->udiag_family);
535 return -1;
536 }
537
538 struct rtattr *attr;
539 unsigned int rta_len = len - NLMSG_LENGTH(sizeof(*diag));
540 unsigned int peer = 0;
541 size_t path_len = 0;
542 char path[sizeof(((struct sockaddr_un *) 0)->sun_path) + 1];
543
544 for (attr = (struct rtattr *) (diag + 1);
545 RTA_OK(attr, rta_len); attr = RTA_NEXT(attr, rta_len)) {
546 switch (attr->rta_type) {
547 case UNIX_DIAG_NAME:
548 if (!path_len) {
549 path_len = RTA_PAYLOAD(attr);
550 if (path_len > sizeof(path) - 1)
551 path_len = sizeof(path) - 1;
552 memcpy(path, RTA_DATA(attr), path_len);
553 path[path_len] = '\0';
554 }
555 break;
556
557 case UNIX_DIAG_PEER:
558 if (RTA_PAYLOAD(attr) >= sizeof(peer))
559 peer = *(unsigned int *) RTA_DATA(attr);
560 break;
561 }
562 }
563
564 printf("inode=%u", diag->udiag_ino);
565
566 if (peer)
567 printf(", peer=%u", peer);
568
569 if (path_len)
570 printf(", name=%s%s", *path ? "" : "@",
571 *path ? path : path + 1);
572
573 putchar('\n');
574 return 0;
575 }
576
577 static int
578 receive_responses(int fd)
579 {
580 long buf[8192 / sizeof(long)];
581 struct sockaddr_nl nladdr = {
582 .nl_family = AF_NETLINK
583 };
584 struct iovec iov = {
585 .iov_base = buf,
586 .iov_len = sizeof(buf)
587 };
588 int flags = 0;
589
590 for (;;) {
591 struct msghdr msg = {
592 .msg_name = (void *) &nladdr,
593 .msg_namelen = sizeof(nladdr),
594 .msg_iov = &iov,
595 .msg_iovlen = 1
596 };
597
598 ssize_t ret = recvmsg(fd, &msg, flags);
599
600 if (ret < 0) {
601 if (errno == EINTR)
602 continue;
603
604 perror("recvmsg");
605 return -1;
606 }
607 if (ret == 0)
608 return 0;
609
610 const struct nlmsghdr *h = (struct nlmsghdr *) buf;
611
612 if (!NLMSG_OK(h, ret)) {
613 fputs("!NLMSG_OK\n", stderr);
614 return -1;
615 }
616
617 for (; NLMSG_OK(h, ret); h = NLMSG_NEXT(h, ret)) {
618 if (h->nlmsg_type == NLMSG_DONE)
619 return 0;
620
621 if (h->nlmsg_type == NLMSG_ERROR) {
622 const struct nlmsgerr *err = NLMSG_DATA(h);
623
624 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) {
625 fputs("NLMSG_ERROR\n", stderr);
626 } else {
627 errno = -err->error;
628 perror("NLMSG_ERROR");
629 }
630
631 return -1;
632 }
633
634 if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
635 fprintf(stderr, "unexpected nlmsg_type %u\n",
636 (unsigned) h->nlmsg_type);
637 return -1;
638 }
639
640 if (print_diag(NLMSG_DATA(h), h->nlmsg_len))
641 return -1;
642 }
643 }
644 }
645
646 int
647 main(void)
648 {
649 int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
650
651 if (fd < 0) {
652 perror("socket");
653 return 1;
654 }
655
656 int ret = send_query(fd) || receive_responses(fd);
657
658 close(fd);
659 return ret;
660 }
661
663 netlink(3), rtnetlink(3), netlink(7), tcp(7)
664
666 This page is part of release 5.04 of the Linux man-pages project. A
667 description of the project, information about reporting bugs, and the
668 latest version of this page, can be found at
669 https://www.kernel.org/doc/man-pages/.
670
671
672
673Linux 2019-03-06 SOCK_DIAG(7)