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