2 * lsfd-sock-xinfo.c - read various information from files under /proc/net/
4 * Copyright (C) 2022 Red Hat, Inc. All rights reserved.
5 * Written by Masatake YAMATO <yamato@redhat.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it would be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <arpa/inet.h> /* inet_ntop */
22 #include <netinet/in.h> /* in6_addr */
23 #include <fcntl.h> /* open(2) */
24 #include <inttypes.h> /* SCNu16 */
25 #include <linux/net.h> /* SS_* */
26 #include <linux/un.h> /* UNIX_PATH_MAX */
27 #include <sched.h> /* for setns(2) */
31 #include <sys/socket.h> /* SOCK_* */
35 #include "libsmartcols.h"
40 #include "lsfd-sock.h"
42 static void load_xinfo_from_proc_unix(ino_t netns_inode
);
43 static void load_xinfo_from_proc_raw(ino_t netns_inode
);
44 static void load_xinfo_from_proc_tcp(ino_t netns_inode
);
45 static void load_xinfo_from_proc_udp(ino_t netns_inode
);
46 static void load_xinfo_from_proc_tcp6(ino_t netns_inode
);
48 static int self_netns_fd
= -1;
49 static struct stat self_netns_sb
;
51 static void *xinfo_tree
; /* for tsearch/tfind */
52 static void *netns_tree
;
54 static int netns_compare(const void *a
, const void *b
)
56 if (*(ino_t
*)a
< *(ino_t
*)b
)
58 else if (*(ino_t
*)a
> *(ino_t
*)b
)
64 static bool is_sock_xinfo_loaded(ino_t netns
)
66 return tfind(&netns
, &netns_tree
, netns_compare
)? true: false;
69 static void mark_sock_xinfo_loaded(ino_t ino
)
71 ino_t
*netns
= xmalloc(sizeof(ino
));
75 tmp
= tsearch(netns
, &netns_tree
, netns_compare
);
77 errx(EXIT_FAILURE
, _("failed to allocate memory"));
80 static void load_sock_xinfo_no_nsswitch(ino_t netns
)
82 load_xinfo_from_proc_unix(netns
);
83 load_xinfo_from_proc_tcp(netns
);
84 load_xinfo_from_proc_udp(netns
);
85 load_xinfo_from_proc_raw(netns
);
86 load_xinfo_from_proc_tcp6(netns
);
89 static void load_sock_xinfo_with_fd(int fd
, ino_t netns
)
91 if (setns(fd
, CLONE_NEWNET
) == 0) {
92 load_sock_xinfo_no_nsswitch(netns
);
93 setns(self_netns_fd
, CLONE_NEWNET
);
97 void load_sock_xinfo(struct path_cxt
*pc
, const char *name
, ino_t netns
)
99 if (self_netns_fd
== -1)
102 if (!is_sock_xinfo_loaded(netns
)) {
105 mark_sock_xinfo_loaded(netns
);
106 fd
= ul_path_open(pc
, O_RDONLY
, name
);
110 load_sock_xinfo_with_fd(fd
, netns
);
115 void initialize_sock_xinfos(void)
121 self_netns_fd
= open("/proc/self/ns/net", O_RDONLY
);
123 if (self_netns_fd
< 0)
124 load_sock_xinfo_no_nsswitch(0);
126 if (fstat(self_netns_fd
, &self_netns_sb
) == 0) {
127 mark_sock_xinfo_loaded(self_netns_sb
.st_ino
);
128 load_sock_xinfo_no_nsswitch(self_netns_sb
.st_ino
);
132 /* Load /proc/net/{unix,...} of the network namespace
133 * specified with netns files under /var/run/netns/.
135 * `ip netns' command pins a network namespace on
138 pc
= ul_new_path("/var/run/netns");
140 err(EXIT_FAILURE
, _("failed to alloc path context for /var/run/netns"));
141 dir
= ul_path_opendir(pc
, NULL
);
146 while ((d
= readdir(dir
))) {
149 if (ul_path_stat(pc
, &sb
, 0, d
->d_name
) < 0)
151 if (is_sock_xinfo_loaded(sb
.st_ino
))
153 mark_sock_xinfo_loaded(sb
.st_ino
);
154 fd
= ul_path_open(pc
, O_RDONLY
, d
->d_name
);
157 load_sock_xinfo_with_fd(fd
, sb
.st_ino
);
164 static void free_sock_xinfo(void *node
)
166 struct sock_xinfo
*xinfo
= node
;
167 if (xinfo
->class->free
)
168 xinfo
->class->free(xinfo
);
172 void finalize_sock_xinfos(void)
174 if (self_netns_fd
!= -1)
175 close(self_netns_fd
);
176 tdestroy(netns_tree
, free
);
177 tdestroy(xinfo_tree
, free_sock_xinfo
);
180 static int xinfo_compare(const void *a
, const void *b
)
182 if (((struct sock_xinfo
*)a
)->inode
< ((struct sock_xinfo
*)b
)->inode
)
184 if (((struct sock_xinfo
*)a
)->inode
> ((struct sock_xinfo
*)b
)->inode
)
189 static void add_sock_info(struct sock_xinfo
*xinfo
)
191 struct sock_xinfo
**tmp
= tsearch(xinfo
, &xinfo_tree
, xinfo_compare
);
194 errx(EXIT_FAILURE
, _("failed to allocate memory"));
197 struct sock_xinfo
*get_sock_xinfo(ino_t netns_inode
)
199 struct sock_xinfo
**xinfo
= tfind(&netns_inode
, &xinfo_tree
, xinfo_compare
);
206 bool is_nsfs_dev(dev_t dev
)
208 return dev
== self_netns_sb
.st_dev
;
211 static const char *sock_decode_type(uint16_t type
)
234 * Protocol specific code
241 struct sock_xinfo sock
;
242 int acceptcon
; /* flags */
252 static const char *unix_decode_state(uint8_t st
)
258 return "unconnected";
263 case SS_DISCONNECTING
:
264 return "disconnecting";
270 static char *unix_get_name(struct sock_xinfo
*sock_xinfo
,
273 struct unix_xinfo
*ux
= (struct unix_xinfo
*)sock_xinfo
;
274 const char *state
= unix_decode_state(ux
->st
);
277 if (sock
->protoname
&& (strcmp(sock
->protoname
, "UNIX-STREAM") == 0))
278 xasprintf(&str
, "state=%s%s%s",
279 (ux
->acceptcon
)? "listen": state
,
280 *(ux
->path
)? " path=": "",
281 *(ux
->path
)? ux
->path
: "");
283 xasprintf(&str
, "state=%s%s%s type=%s",
284 (ux
->acceptcon
)? "listen": state
,
285 *(ux
->path
)? " path=": "",
286 *(ux
->path
)? ux
->path
: "",
287 sock_decode_type(ux
->type
));
291 static char *unix_get_type(struct sock_xinfo
*sock_xinfo
,
292 struct sock
*sock
__attribute__((__unused__
)))
295 struct unix_xinfo
*ux
= (struct unix_xinfo
*)sock_xinfo
;
297 str
= sock_decode_type(ux
->type
);
301 static char *unix_get_state(struct sock_xinfo
*sock_xinfo
,
302 struct sock
*sock
__attribute__((__unused__
)))
305 struct unix_xinfo
*ux
= (struct unix_xinfo
*)sock_xinfo
;
308 return strdup("listen");
310 str
= unix_decode_state(ux
->st
);
314 static bool unix_get_listening(struct sock_xinfo
*sock_xinfo
,
315 struct sock
*sock
__attribute__((__unused__
)))
317 struct unix_xinfo
*ux
= (struct unix_xinfo
*)sock_xinfo
;
319 return ux
->acceptcon
;
322 static bool unix_fill_column(struct proc
*proc
__attribute__((__unused__
)),
323 struct sock_xinfo
*sock_xinfo
,
324 struct sock
*sock
__attribute__((__unused__
)),
325 struct libscols_line
*ln
__attribute__((__unused__
)),
327 size_t column_index
__attribute__((__unused__
)),
330 struct unix_xinfo
*ux
= (struct unix_xinfo
*)sock_xinfo
;
335 *str
= strdup(ux
->path
);
344 static const struct sock_xinfo_class unix_xinfo_class
= {
345 .get_name
= unix_get_name
,
346 .get_type
= unix_get_type
,
347 .get_state
= unix_get_state
,
348 .get_listening
= unix_get_listening
,
349 .fill_column
= unix_fill_column
,
353 /* #define UNIX_LINE_LEN 54 + 21 + UNIX_LINE_LEN + 1
355 * An actual number must be used in this definition
356 * since UNIX_LINE_LEN is specified as an argument for
359 #define UNIX_LINE_LEN 256
360 static void load_xinfo_from_proc_unix(ino_t netns_inode
)
362 char line
[UNIX_LINE_LEN
];
365 unix_fp
= fopen("/proc/net/unix", "r");
369 if (fgets(line
, sizeof(line
), unix_fp
) == NULL
)
371 if (!(line
[0] == 'N' && line
[1] == 'u' && line
[2] == 'm'))
372 /* Unexpected line */
375 while (fgets(line
, sizeof(line
), unix_fp
)) {
380 struct unix_xinfo
*ux
;
381 char path
[UNIX_LINE_LEN
+ 1] = { 0 };
384 if (sscanf(line
, "%*x: %*x %*x %" SCNx64
" %x %x %lu %"
385 stringify_value(UNIX_LINE_LEN
) "[^\n]",
386 &flags
, &type
, &st
, &inode
, path
) < 4)
392 ux
= xcalloc(1, sizeof(*ux
));
393 ux
->sock
.class = &unix_xinfo_class
;
394 ux
->sock
.inode
= (ino_t
)inode
;
395 ux
->sock
.netns_inode
= netns_inode
;
397 ux
->acceptcon
= !!flags
;
400 xstrncpy(ux
->path
, path
, sizeof(ux
->path
));
402 add_sock_info((struct sock_xinfo
*)ux
);
413 struct sock_xinfo sock
;
414 struct in_addr local_addr
;
415 struct in_addr remote_addr
;
418 static uint32_t kernel32_to_cpu(enum sysfs_byteorder byteorder
, uint32_t v
)
420 if (byteorder
== SYSFS_BYTEORDER_LITTLE
)
421 return le32_to_cpu(v
);
423 return be32_to_cpu(v
);
430 struct sock_xinfo sock
;
431 struct in6_addr local_addr
;
432 struct in6_addr remote_addr
;
436 * L4 abstract-layer for protocols stacked on IP and IP6.
440 * Taken from linux/include/net/tcp_states.h.
443 * UDP and RAW sockets also uses the contents in Linux.
458 TCP_MAX_STATES
/* Leave at the end! */
461 static const char *l4_decode_state(enum l4_state st
)
463 const char * table
[] = {
464 [TCP_ESTABLISHED
] = "established",
465 [TCP_SYN_SENT
] = "syn-sent",
466 [TCP_SYN_RECV
] = "syn-recv",
467 [TCP_FIN_WAIT1
] = "fin-wait1",
468 [TCP_FIN_WAIT2
] = "fin-wait2",
469 [TCP_TIME_WAIT
] = "time-wait",
470 [TCP_CLOSE
] = "close",
471 [TCP_CLOSE_WAIT
] = "close-wait",
472 [TCP_LAST_ACK
] = "last-ack",
473 [TCP_LISTEN
] = "listen",
474 [TCP_CLOSING
] = "closing",
475 [TCP_NEW_SYN_RECV
] = "new-syn-recv",
478 if (st
< TCP_MAX_STATES
)
485 struct inet_xinfo inet
;
486 struct inet6_xinfo inet6
;
491 enum l4_side
{ L4_LOCAL
, L4_REMOTE
};
492 enum l3_decorator
{ L3_DECO_START
, L3_DECO_END
};
494 struct l4_xinfo_class
{
495 struct sock_xinfo_class sock
;
496 struct sock_xinfo
*(*scan_line
)(const struct sock_xinfo_class
*,
499 enum sysfs_byteorder
);
500 void * (*get_addr
)(struct l4_xinfo
*, enum l4_side
);
501 bool (*is_any_addr
)(void *);
503 const char *l3_decorator
[2];
506 #define l3_fill_column_handler(L3, SOCK_XINFO, COLUMN_ID, STR) __extension__ \
508 struct l4_xinfo_class *class = (struct l4_xinfo_class *)SOCK_XINFO->class; \
509 struct l4_xinfo *l4 = (struct l4_xinfo *)SOCK_XINFO; \
514 switch (COLUMN_ID) { \
515 case COL_##L3##_LADDR: \
516 n = class->get_addr(l4, L4_LOCAL); \
518 case COL_##L3##_RADDR: \
519 n = class->get_addr(l4, L4_REMOTE); \
525 if (n && inet_ntop(class->family, n, s, sizeof(s))) { \
538 uint16_t remote_port
;
541 static char *tcp_get_name(struct sock_xinfo
*sock_xinfo
,
542 struct sock
*sock
__attribute__((__unused__
)))
545 struct tcp_xinfo
*tcp
= ((struct tcp_xinfo
*)sock_xinfo
);
546 struct l4_xinfo
*l4
= &tcp
->l4
;
547 const char *st_str
= l4_decode_state(l4
->st
);
548 struct l4_xinfo_class
*class = (struct l4_xinfo_class
*)sock_xinfo
->class;
549 void *laddr
= class->get_addr(l4
, L4_LOCAL
);
550 void *raddr
= class->get_addr(l4
, L4_REMOTE
);
551 char local_s
[BUFSIZ
];
552 char remote_s
[BUFSIZ
];
553 const char *start
= class->l3_decorator
[L3_DECO_START
];
554 const char *end
= class->l3_decorator
[L3_DECO_END
];
556 if (!inet_ntop(class->family
, laddr
, local_s
, sizeof(local_s
)))
557 xasprintf(&str
, "state=%s", st_str
);
558 else if (l4
->st
== TCP_LISTEN
559 || !inet_ntop(class->family
, raddr
, remote_s
, sizeof(remote_s
)))
560 xasprintf(&str
, "state=%s laddr=%s%s%s:%"SCNu16
,
562 start
, local_s
, end
, tcp
->local_port
);
564 xasprintf(&str
, "state=%s laddr=%s%s%s:%"SCNu16
" raddr=%s%s%s:%"SCNu16
,
566 start
, local_s
, end
, tcp
->local_port
,
567 start
, remote_s
, end
, tcp
->remote_port
);
571 static char *tcp_get_type(struct sock_xinfo
*sock_xinfo
__attribute__((__unused__
)),
572 struct sock
*sock
__attribute__((__unused__
)))
574 return strdup("stream");
577 static char *tcp_get_state(struct sock_xinfo
*sock_xinfo
,
578 struct sock
*sock
__attribute__((__unused__
)))
580 return strdup(l4_decode_state(((struct l4_xinfo
*)sock_xinfo
)->st
));
583 static bool tcp_get_listening(struct sock_xinfo
*sock_xinfo
,
584 struct sock
*sock
__attribute__((__unused__
)))
586 return ((struct l4_xinfo
*)sock_xinfo
)->st
== TCP_LISTEN
;
589 #define l4_fill_column_handler(L4, SOCK_XINFO, COLUMN_ID, STR) __extension__ \
591 struct l4_xinfo_class *class = (struct l4_xinfo_class *)SOCK_XINFO->class; \
592 struct tcp_xinfo *tcp = (struct tcp_xinfo *)SOCK_XINFO; \
593 struct l4_xinfo *l4 = &tcp->l4; \
595 bool has_laddr = false; \
597 bool has_lport = false; \
601 switch (COLUMN_ID) { \
602 case COL_##L4##_LADDR: \
603 n = class->get_addr(l4, L4_LOCAL); \
605 p = tcp->local_port; \
607 case COL_##L4##_RADDR: \
609 n = class->get_addr(l4, L4_REMOTE); \
610 p = tcp->remote_port; \
612 if (n && inet_ntop(class->family, n, s, sizeof(s))) \
613 xasprintf(STR, "%s%s%s:%"SCNu16, \
614 class->l3_decorator[L3_DECO_START], \
616 class->l3_decorator[L3_DECO_END], \
619 case COL_##L4##_LPORT: \
620 p = tcp->local_port; \
623 case COL_##L4##_RPORT: \
625 p = tcp->remote_port; \
626 xasprintf(STR, "%"SCNu16, p); \
635 static struct sock_xinfo
*tcp_xinfo_scan_line(const struct sock_xinfo_class
*class,
638 enum sysfs_byteorder byteorder
)
640 unsigned long local_addr
;
641 unsigned long local_port
;
642 unsigned long remote_addr
;
643 unsigned long remote_port
;
645 unsigned long long inode
;
646 struct tcp_xinfo
*tcp
;
647 struct inet_xinfo
*inet
;
648 struct sock_xinfo
*sock
;
650 if (sscanf(line
, "%*d: %lx:%lx %lx:%lx %lx %*x:%*x %*x:%*x %*x %*u %*u %lld",
651 &local_addr
, &local_port
, &remote_addr
, &remote_port
,
658 tcp
= xcalloc(1, sizeof(*tcp
));
659 inet
= &tcp
->l4
.inet
;
662 sock
->inode
= (ino_t
)inode
;
663 sock
->netns_inode
= netns_inode
;
664 inet
->local_addr
.s_addr
= kernel32_to_cpu(byteorder
, local_addr
);
665 tcp
->local_port
= local_port
;
666 inet
->remote_addr
.s_addr
= kernel32_to_cpu(byteorder
, remote_addr
);
667 tcp
->remote_port
= remote_port
;
673 static void *tcp_xinfo_get_addr(struct l4_xinfo
*l4
, enum l4_side side
)
675 return (side
== L4_LOCAL
)
676 ? &l4
->inet
.local_addr
677 : &l4
->inet
.remote_addr
;
680 static bool tcp_xinfo_is_any_addr(void *addr
)
682 return ((struct in_addr
*)addr
)->s_addr
== INADDR_ANY
;
685 static bool tcp_fill_column(struct proc
*proc
__attribute__((__unused__
)),
686 struct sock_xinfo
*sock_xinfo
,
687 struct sock
*sock
__attribute__((__unused__
)),
688 struct libscols_line
*ln
__attribute__((__unused__
)),
690 size_t column_index
__attribute__((__unused__
)),
693 return l3_fill_column_handler(INET
, sock_xinfo
, column_id
, str
)
694 || l4_fill_column_handler(TCP
, sock_xinfo
, column_id
, str
);
697 static const struct l4_xinfo_class tcp_xinfo_class
= {
699 .get_name
= tcp_get_name
,
700 .get_type
= tcp_get_type
,
701 .get_state
= tcp_get_state
,
702 .get_listening
= tcp_get_listening
,
703 .fill_column
= tcp_fill_column
,
706 .scan_line
= tcp_xinfo_scan_line
,
707 .get_addr
= tcp_xinfo_get_addr
,
708 .is_any_addr
= tcp_xinfo_is_any_addr
,
710 .l3_decorator
= {"", ""},
713 static bool L4_verify_initial_line(const char *line
)
715 /* At least we expect two white spaces. */
716 if (strncmp(line
, " ", 2) != 0)
720 /* Skip white spaces. */
721 line
= skip_space(line
);
723 return strncmp(line
, "sl", 2) == 0;
726 #define TCP_LINE_LEN 256
727 static void load_xinfo_from_proc_inet_L4(ino_t netns_inode
, const char *proc_file
,
728 const struct l4_xinfo_class
*class)
730 char line
[TCP_LINE_LEN
];
733 tcp_fp
= fopen(proc_file
, "r");
737 if (fgets(line
, sizeof(line
), tcp_fp
) == NULL
)
739 if (!L4_verify_initial_line(line
))
740 /* Unexpected line */
743 enum sysfs_byteorder byteorder
= sysfs_get_byteorder(NULL
);
745 while (fgets(line
, sizeof(line
), tcp_fp
)) {
746 struct sock_xinfo
*sock
= class->scan_line(&class->sock
, line
, netns_inode
, byteorder
);
755 static void load_xinfo_from_proc_tcp(ino_t netns_inode
)
757 load_xinfo_from_proc_inet_L4(netns_inode
,
765 static char *udp_get_name(struct sock_xinfo
*sock_xinfo
,
766 struct sock
*sock
__attribute__((__unused__
)))
769 struct tcp_xinfo
*tcp
= ((struct tcp_xinfo
*)sock_xinfo
);
770 struct l4_xinfo
*l4
= &tcp
->l4
;
771 unsigned int st
= l4
->st
;
772 const char *st_str
= l4_decode_state(st
);
773 struct l4_xinfo_class
*class = (struct l4_xinfo_class
*)sock_xinfo
->class;
774 void *laddr
= class->get_addr(l4
, L4_LOCAL
);
775 void *raddr
= class->get_addr(l4
, L4_REMOTE
);
776 char local_s
[BUFSIZ
];
777 char remote_s
[BUFSIZ
];
779 if (!inet_ntop(class->family
, laddr
, local_s
, sizeof(local_s
)))
780 xasprintf(&str
, "state=%s", st_str
);
781 else if ((class->is_any_addr(raddr
) && tcp
->remote_port
== 0)
782 || !inet_ntop(class->family
, raddr
, remote_s
, sizeof(remote_s
)))
783 xasprintf(&str
, "state=%s laddr=%s:%"SCNu16
,
785 local_s
, tcp
->local_port
);
787 xasprintf(&str
, "state=%s laddr=%s:%"SCNu16
" raddr=%s:%"SCNu16
,
789 local_s
, tcp
->local_port
,
790 remote_s
, tcp
->remote_port
);
794 static char *udp_get_type(struct sock_xinfo
*sock_xinfo
__attribute__((__unused__
)),
795 struct sock
*sock
__attribute__((__unused__
)))
797 return strdup("dgram");
800 static bool udp_fill_column(struct proc
*proc
__attribute__((__unused__
)),
801 struct sock_xinfo
*sock_xinfo
,
802 struct sock
*sock
__attribute__((__unused__
)),
803 struct libscols_line
*ln
__attribute__((__unused__
)),
805 size_t column_index
__attribute__((__unused__
)),
808 return l3_fill_column_handler(INET
, sock_xinfo
, column_id
, str
)
809 || l4_fill_column_handler(UDP
, sock_xinfo
, column_id
, str
);
812 static const struct l4_xinfo_class udp_xinfo_class
= {
814 .get_name
= udp_get_name
,
815 .get_type
= udp_get_type
,
816 .get_state
= tcp_get_state
,
817 .get_listening
= NULL
,
818 .fill_column
= udp_fill_column
,
821 .scan_line
= tcp_xinfo_scan_line
,
822 .get_addr
= tcp_xinfo_get_addr
,
823 .is_any_addr
= tcp_xinfo_is_any_addr
,
825 .l3_decorator
= {"", ""},
828 static void load_xinfo_from_proc_udp(ino_t netns_inode
)
830 load_xinfo_from_proc_inet_L4(netns_inode
,
843 static char *raw_get_name(struct sock_xinfo
*sock_xinfo
,
844 struct sock
*sock
__attribute__((__unused__
)))
847 struct l4_xinfo_class
*class = (struct l4_xinfo_class
*)sock_xinfo
->class;
848 struct raw_xinfo
*raw
= ((struct raw_xinfo
*)sock_xinfo
);
849 struct l4_xinfo
*l4
= &raw
->l4
;
850 const char *st_str
= l4_decode_state(l4
->st
);
851 void *laddr
= class->get_addr(l4
, L4_LOCAL
);
852 void *raddr
= class->get_addr(l4
, L4_REMOTE
);
853 char local_s
[BUFSIZ
];
854 char remote_s
[BUFSIZ
];
856 if (!inet_ntop(class->family
, laddr
, local_s
, sizeof(local_s
)))
857 xasprintf(&str
, "state=%s", st_str
);
858 else if (class->is_any_addr(raddr
)
859 || !inet_ntop(class->family
, raddr
, remote_s
, sizeof(remote_s
)))
860 xasprintf(&str
, "state=%s protocol=%"SCNu16
" laddr=%s",
862 raw
->protocol
, local_s
);
864 xasprintf(&str
, "state=%s protocol=%"SCNu16
" laddr=%s raddr=%s",
866 raw
->protocol
, local_s
, remote_s
);
870 static char *raw_get_type(struct sock_xinfo
*sock_xinfo
__attribute__((__unused__
)),
871 struct sock
*sock
__attribute__((__unused__
)))
873 return strdup("raw");
876 static bool raw_fill_column(struct proc
*proc
__attribute__((__unused__
)),
877 struct sock_xinfo
*sock_xinfo
,
878 struct sock
*sock
__attribute__((__unused__
)),
879 struct libscols_line
*ln
__attribute__((__unused__
)),
881 size_t column_index
__attribute__((__unused__
)),
884 if (l3_fill_column_handler(INET
, sock_xinfo
, column_id
, str
))
887 if (column_id
== COL_RAW_PROTOCOL
) {
888 xasprintf(str
, "%"SCNu16
,
889 ((struct raw_xinfo
*)sock_xinfo
)->protocol
);
896 static struct sock_xinfo
*raw_xinfo_scan_line(const struct sock_xinfo_class
*class,
899 enum sysfs_byteorder byteorder
)
901 unsigned long local_addr
;
902 unsigned long protocol
;
903 unsigned long remote_addr
;
905 unsigned long long inode
;
906 struct raw_xinfo
*raw
;
907 struct inet_xinfo
*inet
;
908 struct sock_xinfo
*sock
;
910 if (sscanf(line
, "%*d: %lx:%lx %lx:%*x %lx %*x:%*x %*x:%*x %*x %*u %*u %lld",
911 &local_addr
, &protocol
, &remote_addr
,
918 raw
= xcalloc(1, sizeof(*raw
));
919 inet
= &raw
->l4
.inet
;
922 sock
->inode
= (ino_t
)inode
;
923 sock
->netns_inode
= netns_inode
;
924 inet
->local_addr
.s_addr
= kernel32_to_cpu(byteorder
, local_addr
);
925 inet
->remote_addr
.s_addr
= kernel32_to_cpu(byteorder
, remote_addr
);
926 raw
->protocol
= protocol
;
932 static const struct l4_xinfo_class raw_xinfo_class
= {
934 .get_name
= raw_get_name
,
935 .get_type
= raw_get_type
,
936 .get_state
= tcp_get_state
,
937 .get_listening
= NULL
,
938 .fill_column
= raw_fill_column
,
941 .scan_line
= raw_xinfo_scan_line
,
942 .get_addr
= tcp_xinfo_get_addr
,
943 .is_any_addr
= tcp_xinfo_is_any_addr
,
945 .l3_decorator
= {"", ""},
948 static void load_xinfo_from_proc_raw(ino_t netns_inode
)
950 load_xinfo_from_proc_inet_L4(netns_inode
,
958 static struct sock_xinfo
*tcp6_xinfo_scan_line(const struct sock_xinfo_class
*class,
961 enum sysfs_byteorder byteorder
)
963 uint32_t local_addr
[4];
964 unsigned int local_port
;
965 uint32_t remote_addr
[4];
966 unsigned int remote_port
;
969 struct tcp_xinfo
*tcp
;
970 struct inet6_xinfo
*inet6
;
971 struct sock_xinfo
*sock
;
975 "%08x%08x%08x%08x:%04x "
976 "%08x%08x%08x%08x:%04x "
977 "%x %*x:%*x %*x:%*x %*x %*u %*d %lu ",
978 local_addr
+0, local_addr
+1, local_addr
+2, local_addr
+3, &local_port
,
979 remote_addr
+0, remote_addr
+1, remote_addr
+2, remote_addr
+3, &remote_port
,
986 tcp
= xmalloc(sizeof(*tcp
));
987 inet6
= &tcp
->l4
.inet6
;
990 sock
->inode
= (ino_t
)inode
;
991 sock
->netns_inode
= netns_inode
;
992 tcp
->local_port
= local_port
;
993 for (int i
= 0; i
< 4; i
++) {
994 inet6
->local_addr
.s6_addr32
[i
] = kernel32_to_cpu(byteorder
, local_addr
[i
]);
995 inet6
->remote_addr
.s6_addr32
[i
] = kernel32_to_cpu(byteorder
, remote_addr
[i
]);
997 tcp
->remote_port
= remote_port
;
1003 static bool tcp6_fill_column(struct proc
*proc
__attribute__((__unused__
)),
1004 struct sock_xinfo
*sock_xinfo
,
1005 struct sock
*sock
__attribute__((__unused__
)),
1006 struct libscols_line
*ln
__attribute__((__unused__
)),
1008 size_t column_index
__attribute__((__unused__
)),
1011 return l3_fill_column_handler(INET6
, sock_xinfo
, column_id
, str
)
1012 || l4_fill_column_handler(TCP
, sock_xinfo
, column_id
, str
);
1015 static void *tcp6_xinfo_get_addr(struct l4_xinfo
* l4
, enum l4_side side
)
1017 return (side
== L4_LOCAL
)
1018 ? &l4
->inet6
.local_addr
1019 : &l4
->inet6
.remote_addr
;
1022 static bool tcp6_xinfo_is_any_addr(void *addr
)
1024 return IN6_ARE_ADDR_EQUAL(addr
, &(struct in6_addr
)IN6ADDR_ANY_INIT
);
1027 static const struct l4_xinfo_class tcp6_xinfo_class
= {
1029 .get_name
= tcp_get_name
,
1030 .get_type
= tcp_get_type
,
1031 .get_state
= tcp_get_state
,
1032 .get_listening
= tcp_get_listening
,
1033 .fill_column
= tcp6_fill_column
,
1036 .scan_line
= tcp6_xinfo_scan_line
,
1037 .get_addr
= tcp6_xinfo_get_addr
,
1038 .is_any_addr
= tcp6_xinfo_is_any_addr
,
1040 .l3_decorator
= {"[", "]"},
1043 static void load_xinfo_from_proc_tcp6(ino_t netns_inode
)
1045 load_xinfo_from_proc_inet_L4(netns_inode
,