1sock_diag(7) Miscellaneous Information 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 in‐
18 formation 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 in‐
24 formation 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 re‐
60 quested; 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 re‐
95 ported. 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 re‐
108 port. Each requested kind of information is reported back as a
109 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 attri‐
114 bute is the pathname to which the socket was bound (a se‐
115 quence 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 attri‐
120 bute 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 attri‐
140 bute is a __u32 value which is the peer's inode number.
141 This attribute is reported for connected sockets only.
142
143 UDIAG_SHOW_ICONS
144 The attribute reported in answer to this request is
145 UNIX_DIAG_ICONS. The payload associated with this attri‐
146 bute is an array of __u32 values which are inode numbers
147 of sockets that has passed the connect(2) call, but
148 hasn't been processed with accept(2) yet. This attribute
149 is reported for listening sockets only.
150
151 UDIAG_SHOW_RQLEN
152 The attribute reported in answer to this request is
153 UNIX_DIAG_RQLEN. The payload associated with this attri‐
154 bute is represented in the following structure:
155
156 struct unix_diag_rqlen {
157 __u32 udiag_rqueue;
158 __u32 udiag_wqueue;
159 };
160
161 The fields of this structure are as follows:
162
163 udiag_rqueue
164 For listening sockets: the number of pending con‐
165 nections. The length of the array associated with
166 the UNIX_DIAG_ICONS response attribute is equal to
167 this value.
168
169 For established sockets: the amount of data in in‐
170 coming queue.
171
172 udiag_wqueue
173 For listening sockets: the backlog length which
174 equals to the value passed as the second argument
175 to listen(2).
176
177 For established sockets: the amount of memory
178 available for sending.
179
180 UDIAG_SHOW_MEMINFO
181 The attribute reported in answer to this request is
182 UNIX_DIAG_MEMINFO. The payload associated with this at‐
183 tribute is an array of __u32 values described below in
184 the subsection "Socket memory information".
185
186 The following attributes are reported back without any specific
187 request:
188
189 UNIX_DIAG_SHUTDOWN
190 The payload associated with this attribute is __u8 value
191 which represents bits of shutdown(2) state.
192
193 udiag_cookie
194 This is an array of opaque identifiers that could be used along
195 with udiag_ino to specify an individual socket. It is ignored
196 when querying for a list of sockets, as well as when all its el‐
197 ements are set to -1.
198
199 The response to a query for UNIX domain sockets is represented as an
200 array of
201
202 struct unix_diag_msg {
203 __u8 udiag_family;
204 __u8 udiag_type;
205 __u8 udiag_state;
206 __u8 pad;
207 __u32 udiag_ino;
208 __u32 udiag_cookie[2];
209 };
210
211 followed by netlink attributes.
212
213 The fields of this structure are as follows:
214
215 udiag_family
216 This field has the same meaning as in struct unix_diag_req.
217
218 udiag_type
219 This is set to one of SOCK_PACKET, SOCK_STREAM, or SOCK_SEQ‐
220 PACKET.
221
222 udiag_state
223 This is set to one of TCP_LISTEN or TCP_ESTABLISHED.
224
225 pad This field is set to 0.
226
227 udiag_ino
228 This is the socket inode number.
229
230 udiag_cookie
231 This is an array of opaque identifiers that could be used in
232 subsequent queries.
233
234 IPv4 and IPv6 sockets
235 For IPv4 and IPv6 sockets, the request is represented in the following
236 structure:
237
238 struct inet_diag_req_v2 {
239 __u8 sdiag_family;
240 __u8 sdiag_protocol;
241 __u8 idiag_ext;
242 __u8 pad;
243 __u32 idiag_states;
244 struct inet_diag_sockid id;
245 };
246
247 where struct inet_diag_sockid is defined as follows:
248
249 struct inet_diag_sockid {
250 __be16 idiag_sport;
251 __be16 idiag_dport;
252 __be32 idiag_src[4];
253 __be32 idiag_dst[4];
254 __u32 idiag_if;
255 __u32 idiag_cookie[2];
256 };
257
258 The fields of struct inet_diag_req_v2 are as follows:
259
260 sdiag_family
261 This should be set to either AF_INET or AF_INET6 for IPv4 or
262 IPv6 sockets respectively.
263
264 sdiag_protocol
265 This should be set to one of IPPROTO_TCP, IPPROTO_UDP, or IP‐
266 PROTO_UDPLITE.
267
268 idiag_ext
269 This is a set of flags defining what kind of extended informa‐
270 tion to report. Each requested kind of information is reported
271 back as a netlink attribute as described below:
272
273 INET_DIAG_TOS
274 The payload associated with this attribute is a __u8
275 value which is the TOS of the socket.
276
277 INET_DIAG_TCLASS
278 The payload associated with this attribute is a __u8
279 value which is the TClass of the socket. IPv6 sockets
280 only. For LISTEN and CLOSE sockets, this is followed by
281 INET_DIAG_SKV6ONLY attribute with associated __u8 payload
282 value meaning whether the socket is IPv6-only or not.
283
284 INET_DIAG_MEMINFO
285 The payload associated with this attribute is represented
286 in the following structure:
287
288 struct inet_diag_meminfo {
289 __u32 idiag_rmem;
290 __u32 idiag_wmem;
291 __u32 idiag_fmem;
292 __u32 idiag_tmem;
293 };
294
295 The fields of this structure are as follows:
296
297 idiag_rmem The amount of data in the receive queue.
298
299 idiag_wmem The amount of data that is queued by TCP but
300 not yet sent.
301
302 idiag_fmem The amount of memory scheduled for future use
303 (TCP only).
304
305 idiag_tmem The amount of data in send queue.
306
307 INET_DIAG_SKMEMINFO
308 The payload associated with this attribute is an array of
309 __u32 values described below in the subsection "Socket
310 memory information".
311
312 INET_DIAG_INFO
313 The payload associated with this attribute is specific to
314 the address family. For TCP sockets, it is an object of
315 type struct tcp_info.
316
317 INET_DIAG_CONG
318 The payload associated with this attribute is a string
319 that describes the congestion control algorithm used.
320 For TCP sockets only.
321
322 pad This should be set to 0.
323
324 idiag_states
325 This is a bit mask that defines a filter of socket states. Only
326 those sockets whose states are in this mask will be reported.
327 Ignored when querying for an individual socket.
328
329 id This is a socket ID object that is used in dump requests, in
330 queries about individual sockets, and is reported back in each
331 response. Unlike UNIX domain sockets, IPv4 and IPv6 sockets are
332 identified using addresses and ports. All values are in network
333 byte order.
334
335 The fields of struct inet_diag_sockid are as follows:
336
337 idiag_sport
338 The source port.
339
340 idiag_dport
341 The destination port.
342
343 idiag_src
344 The source address.
345
346 idiag_dst
347 The destination address.
348
349 idiag_if
350 The interface number the socket is bound to.
351
352 idiag_cookie
353 This is an array of opaque identifiers that could be used along
354 with other fields of this structure to specify an individual
355 socket. It is ignored when querying for a list of sockets, as
356 well as when all its elements are set to -1.
357
358 The response to a query for IPv4 or IPv6 sockets is represented as an
359 array of
360
361 struct inet_diag_msg {
362 __u8 idiag_family;
363 __u8 idiag_state;
364 __u8 idiag_timer;
365 __u8 idiag_retrans;
366
367 struct inet_diag_sockid id;
368
369 __u32 idiag_expires;
370 __u32 idiag_rqueue;
371 __u32 idiag_wqueue;
372 __u32 idiag_uid;
373 __u32 idiag_inode;
374 };
375
376 followed by netlink attributes.
377
378 The fields of this structure are as follows:
379
380 idiag_family
381 This is the same field as in struct inet_diag_req_v2.
382
383 idiag_state
384 This denotes socket state as in struct inet_diag_req_v2.
385
386 idiag_timer
387 For TCP sockets, this field describes the type of timer that is
388 currently active for the socket. It is set to one of the fol‐
389 lowing constants:
390
391 0 no timer is active
392 1 a retransmit timer
393 2 a keep-alive timer
394 3 a TIME_WAIT timer
395 4 a zero window probe timer
396
397 For non-TCP sockets, this field is set to 0.
398
399 idiag_retrans
400 For idiag_timer values 1, 2, and 4, this field contains the num‐
401 ber of retransmits. For other idiag_timer values, this field is
402 set to 0.
403
404 idiag_expires
405 For TCP sockets that have an active timer, this field describes
406 its expiration time in milliseconds. For other sockets, this
407 field is set to 0.
408
409 idiag_rqueue
410 For listening sockets: the number of pending connections.
411
412 For other sockets: the amount of data in the incoming queue.
413
414 idiag_wqueue
415 For listening sockets: the backlog length.
416
417 For other sockets: the amount of memory available for sending.
418
419 idiag_uid
420 This is the socket owner UID.
421
422 idiag_inode
423 This is the socket inode number.
424
425 Socket memory information
426 The payload associated with UNIX_DIAG_MEMINFO and INET_DIAG_SKMEMINFO
427 netlink attributes is an array of the following __u32 values:
428
429 SK_MEMINFO_RMEM_ALLOC
430 The amount of data in receive queue.
431
432 SK_MEMINFO_RCVBUF
433 The receive socket buffer as set by SO_RCVBUF.
434
435 SK_MEMINFO_WMEM_ALLOC
436 The amount of data in send queue.
437
438 SK_MEMINFO_SNDBUF
439 The send socket buffer as set by SO_SNDBUF.
440
441 SK_MEMINFO_FWD_ALLOC
442 The amount of memory scheduled for future use (TCP only).
443
444 SK_MEMINFO_WMEM_QUEUED
445 The amount of data queued by TCP, but not yet sent.
446
447 SK_MEMINFO_OPTMEM
448 The amount of memory allocated for the socket's service needs
449 (e.g., socket filter).
450
451 SK_MEMINFO_BACKLOG
452 The amount of packets in the backlog (not yet processed).
453
455 NETLINK_INET_DIAG was introduced in Linux 2.6.14 and supported AF_INET
456 and AF_INET6 sockets only. In Linux 3.3, it was renamed to
457 NETLINK_SOCK_DIAG and extended to support AF_UNIX sockets.
458
459 UNIX_DIAG_MEMINFO and INET_DIAG_SKMEMINFO were introduced in Linux 3.6.
460
462 Linux.
463
465 The following example program prints inode number, peer's inode number,
466 and name of all UNIX domain sockets in the current namespace.
467
468 #include <errno.h>
469 #include <stdio.h>
470 #include <string.h>
471 #include <unistd.h>
472 #include <sys/socket.h>
473 #include <sys/un.h>
474 #include <linux/netlink.h>
475 #include <linux/rtnetlink.h>
476 #include <linux/sock_diag.h>
477 #include <linux/unix_diag.h>
478
479 static int
480 send_query(int fd)
481 {
482 struct sockaddr_nl nladdr = {
483 .nl_family = AF_NETLINK
484 };
485 struct
486 {
487 struct nlmsghdr nlh;
488 struct unix_diag_req udr;
489 } req = {
490 .nlh = {
491 .nlmsg_len = sizeof(req),
492 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
493 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP
494 },
495 .udr = {
496 .sdiag_family = AF_UNIX,
497 .udiag_states = -1,
498 .udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER
499 }
500 };
501 struct iovec iov = {
502 .iov_base = &req,
503 .iov_len = sizeof(req)
504 };
505 struct msghdr msg = {
506 .msg_name = &nladdr,
507 .msg_namelen = sizeof(nladdr),
508 .msg_iov = &iov,
509 .msg_iovlen = 1
510 };
511
512 for (;;) {
513 if (sendmsg(fd, &msg, 0) < 0) {
514 if (errno == EINTR)
515 continue;
516
517 perror("sendmsg");
518 return -1;
519 }
520
521 return 0;
522 }
523 }
524
525 static int
526 print_diag(const struct unix_diag_msg *diag, unsigned int len)
527 {
528 if (len < NLMSG_LENGTH(sizeof(*diag))) {
529 fputs("short response\n", stderr);
530 return -1;
531 }
532 if (diag->udiag_family != AF_UNIX) {
533 fprintf(stderr, "unexpected family %u\n", diag->udiag_family);
534 return -1;
535 }
536
537 unsigned int rta_len = len - NLMSG_LENGTH(sizeof(*diag));
538 unsigned int peer = 0;
539 size_t path_len = 0;
540 char path[sizeof(((struct sockaddr_un *) 0)->sun_path) + 1];
541
542 for (struct rtattr *attr = (struct rtattr *) (diag + 1);
543 RTA_OK(attr, rta_len); attr = RTA_NEXT(attr, rta_len)) {
544 switch (attr->rta_type) {
545 case UNIX_DIAG_NAME:
546 if (!path_len) {
547 path_len = RTA_PAYLOAD(attr);
548 if (path_len > sizeof(path) - 1)
549 path_len = sizeof(path) - 1;
550 memcpy(path, RTA_DATA(attr), path_len);
551 path[path_len] = '\0';
552 }
553 break;
554
555 case UNIX_DIAG_PEER:
556 if (RTA_PAYLOAD(attr) >= sizeof(peer))
557 peer = *(unsigned int *) RTA_DATA(attr);
558 break;
559 }
560 }
561
562 printf("inode=%u", diag->udiag_ino);
563
564 if (peer)
565 printf(", peer=%u", peer);
566
567 if (path_len)
568 printf(", name=%s%s", *path ? "" : "@",
569 *path ? path : path + 1);
570
571 putchar('\n');
572 return 0;
573 }
574
575 static int
576 receive_responses(int fd)
577 {
578 long buf[8192 / sizeof(long)];
579 struct sockaddr_nl nladdr;
580 struct iovec iov = {
581 .iov_base = buf,
582 .iov_len = sizeof(buf)
583 };
584 int flags = 0;
585
586 for (;;) {
587 struct msghdr msg = {
588 .msg_name = &nladdr,
589 .msg_namelen = sizeof(nladdr),
590 .msg_iov = &iov,
591 .msg_iovlen = 1
592 };
593
594 ssize_t ret = recvmsg(fd, &msg, flags);
595
596 if (ret < 0) {
597 if (errno == EINTR)
598 continue;
599
600 perror("recvmsg");
601 return -1;
602 }
603 if (ret == 0)
604 return 0;
605
606 if (nladdr.nl_family != AF_NETLINK) {
607 fputs("!AF_NETLINK\n", stderr);
608 return -1;
609 }
610
611 const struct nlmsghdr *h = (struct nlmsghdr *) buf;
612
613 if (!NLMSG_OK(h, ret)) {
614 fputs("!NLMSG_OK\n", stderr);
615 return -1;
616 }
617
618 for (; NLMSG_OK(h, ret); h = NLMSG_NEXT(h, ret)) {
619 if (h->nlmsg_type == NLMSG_DONE)
620 return 0;
621
622 if (h->nlmsg_type == NLMSG_ERROR) {
623 const struct nlmsgerr *err = NLMSG_DATA(h);
624
625 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) {
626 fputs("NLMSG_ERROR\n", stderr);
627 } else {
628 errno = -err->error;
629 perror("NLMSG_ERROR");
630 }
631
632 return -1;
633 }
634
635 if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
636 fprintf(stderr, "unexpected nlmsg_type %u\n",
637 (unsigned) h->nlmsg_type);
638 return -1;
639 }
640
641 if (print_diag(NLMSG_DATA(h), h->nlmsg_len))
642 return -1;
643 }
644 }
645 }
646
647 int
648 main(void)
649 {
650 int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
651
652 if (fd < 0) {
653 perror("socket");
654 return 1;
655 }
656
657 int ret = send_query(fd) || receive_responses(fd);
658
659 close(fd);
660 return ret;
661 }
662
664 netlink(3), rtnetlink(3), netlink(7), tcp(7)
665
666
667
668Linux man-pages 6.04 2023-03-30 sock_diag(7)