]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/lsfd-sock-xinfo.c
Merge branch 'getwc' of https://github.com/t-8ch/util-linux
[thirdparty/util-linux.git] / misc-utils / lsfd-sock-xinfo.c
CommitLineData
0ee16e43 1/*
5468bb45 2 * lsfd-sock-xinfo.c - read various information from files under /proc/net/ and NETLINK_SOCK_DIAG
0ee16e43
MY
3 *
4 * Copyright (C) 2022 Red Hat, Inc. All rights reserved.
5 * Written by Masatake YAMATO <yamato@redhat.com>
6 *
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.
11 *
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.
16 *
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
20 */
7b2a9be0 21#include <arpa/inet.h> /* inet_ntop */
1656da13 22#include <netinet/in.h> /* in6_addr */
2e38e61c 23#include <fcntl.h> /* open(2) */
97f54385 24#include <ifaddrs.h> /* getifaddrs */
73df46fc 25#include <inttypes.h> /* SCNu16 */
97f54385 26#include <net/if.h> /* if_nametoindex */
adfc156a 27#include <linux/if_ether.h> /* ETH_P_* */
2e38e61c 28#include <linux/net.h> /* SS_* */
5468bb45
MY
29#include <linux/netlink.h> /* NETLINK_*, NLMSG_* */
30#include <linux/rtnetlink.h> /* RTA_*, struct rtattr, */
31#include <linux/sock_diag.h> /* SOCK_DIAG_BY_FAMILY */
2e38e61c 32#include <linux/un.h> /* UNIX_PATH_MAX */
5468bb45
MY
33#include <linux/unix_diag.h> /* UNIX_DIAG_*, UDIAG_SHOW_*,
34 struct unix_diag_req */
0ee16e43 35#include <sched.h> /* for setns(2) */
cb3126e1 36#include <search.h> /* tfind, tsearch */
2e38e61c
MY
37#include <stdint.h>
38#include <string.h>
39#include <sys/socket.h> /* SOCK_* */
0ee16e43 40
db79a100
TW
41#include "sysfs.h"
42#include "bitops.h"
0ee16e43
MY
43
44#include "lsfd.h"
45#include "lsfd-sock.h"
46
891b24b7
MY
47static void load_xinfo_from_proc_icmp(ino_t netns_inode, enum sysfs_byteorder byteorder);
48static void load_xinfo_from_proc_icmp6(ino_t netns_inode, enum sysfs_byteorder byteorder);
2e38e61c 49static void load_xinfo_from_proc_unix(ino_t netns_inode);
891b24b7
MY
50static void load_xinfo_from_proc_raw(ino_t netns_inode, enum sysfs_byteorder byteorder);
51static void load_xinfo_from_proc_tcp(ino_t netns_inode, enum sysfs_byteorder byteorder);
52static void load_xinfo_from_proc_udp(ino_t netns_inode, enum sysfs_byteorder byteorder);
53static void load_xinfo_from_proc_udplite(ino_t netns_inode, enum sysfs_byteorder byteorder);
54static void load_xinfo_from_proc_tcp6(ino_t netns_inode, enum sysfs_byteorder byteorder);
55static void load_xinfo_from_proc_udp6(ino_t netns_inode, enum sysfs_byteorder byteorder);
56static void load_xinfo_from_proc_udplite6(ino_t netns_inode, enum sysfs_byteorder byteorder);
57static void load_xinfo_from_proc_raw6(ino_t netns_inode, enum sysfs_byteorder byteorder);
b53cc896 58static void load_xinfo_from_proc_netlink(ino_t netns_inode);
adfc156a 59static void load_xinfo_from_proc_packet(ino_t netns_inode);
2e38e61c 60
5468bb45
MY
61static void load_xinfo_from_diag_unix(int diag, ino_t netns_inode);
62
0ee16e43 63static int self_netns_fd = -1;
44f9aec7 64static struct stat self_netns_sb;
0ee16e43
MY
65
66static void *xinfo_tree; /* for tsearch/tfind */
67static void *netns_tree;
68
97f54385
MY
69struct iface {
70 unsigned int index;
71 char name[IF_NAMESIZE];
72};
73
74static const char *get_iface_name(ino_t netns, unsigned int iface_index);
75
e6e551e8
MY
76struct netns {
77 ino_t inode;
97f54385 78 struct iface *ifaces;
e6e551e8
MY
79};
80
0ee16e43
MY
81static int netns_compare(const void *a, const void *b)
82{
e6e551e8
MY
83 const struct netns *netns_a = a;
84 const struct netns *netns_b = b;
85
86 return netns_a->inode - netns_b->inode;
87}
88
89static void netns_free(void *netns)
90{
97f54385
MY
91 struct netns *nsobj = netns;
92
93 free(nsobj->ifaces);
e6e551e8 94 free(netns);
0ee16e43
MY
95}
96
97f54385
MY
97/*
98 * iface index -> iface name mappings
99 */
100static void load_ifaces_from_getifaddrs(struct netns *nsobj)
101{
102 struct ifaddrs *ifa_list;
103 struct ifaddrs *ifa;
104 size_t i, count = 0;
105
106 if (getifaddrs(&ifa_list) < 0)
107 return;
108
109 for (ifa = ifa_list; ifa != NULL; ifa = ifa->ifa_next)
110 count++;
111
112 nsobj->ifaces = xcalloc(count + 1, sizeof(*nsobj->ifaces));
113
114 for (ifa = ifa_list, i = 0; ifa != NULL; ifa = ifa->ifa_next, i++) {
115 unsigned int if_index = if_nametoindex(ifa->ifa_name);
116
117 nsobj->ifaces[i].index = if_index;
118 strncpy(nsobj->ifaces[i].name, ifa->ifa_name, IF_NAMESIZE - 1);
119 /* The slot for the last byte is already filled by calloc. */
120 }
121 /* nsobj->ifaces[count] is the sentinel value. */
122
123 freeifaddrs(ifa_list);
124
125 return;
126}
127
128static const char *get_iface_name(ino_t netns, unsigned int iface_index)
129{
816109f6
TW
130 struct netns key = { .inode = netns };
131 struct netns **nsobj = tfind(&key, &netns_tree, netns_compare);
97f54385
MY
132 if (!nsobj)
133 return NULL;
134
135 for (size_t i = 0; (*nsobj)->ifaces[i].index; i++) {
136 if ((*nsobj)->ifaces[i].index == iface_index)
137 return (*nsobj)->ifaces[i].name;
138 }
139
140 return NULL;
141}
142
0ee16e43
MY
143static bool is_sock_xinfo_loaded(ino_t netns)
144{
816109f6
TW
145 struct netns key = { .inode = netns };
146 return tfind(&key, &netns_tree, netns_compare)? true: false;
0ee16e43
MY
147}
148
e6e551e8 149static struct netns *mark_sock_xinfo_loaded(ino_t ino)
0ee16e43 150{
97f54385 151 struct netns *netns = xcalloc(1, sizeof(*netns));
0ee16e43
MY
152 ino_t **tmp;
153
e6e551e8 154 netns->inode = ino;
0ee16e43
MY
155 tmp = tsearch(netns, &netns_tree, netns_compare);
156 if (tmp == NULL)
157 errx(EXIT_FAILURE, _("failed to allocate memory"));
e6e551e8 158 return *(struct netns **)tmp;
0ee16e43
MY
159}
160
e6e551e8 161static void load_sock_xinfo_no_nsswitch(struct netns *nsobj)
0ee16e43 162{
e6e551e8 163 ino_t netns = nsobj? nsobj->inode: 0;
5468bb45 164 int diagsd;
891b24b7 165 enum sysfs_byteorder byteorder = sysfs_get_byteorder(NULL);
e6e551e8 166
2e38e61c 167 load_xinfo_from_proc_unix(netns);
891b24b7
MY
168 load_xinfo_from_proc_tcp(netns, byteorder);
169 load_xinfo_from_proc_udp(netns, byteorder);
170 load_xinfo_from_proc_udplite(netns, byteorder);
171 load_xinfo_from_proc_raw(netns, byteorder);
172 load_xinfo_from_proc_tcp6(netns, byteorder);
173 load_xinfo_from_proc_udp6(netns, byteorder);
174 load_xinfo_from_proc_udplite6(netns, byteorder);
175 load_xinfo_from_proc_raw6(netns, byteorder);
176 load_xinfo_from_proc_icmp(netns, byteorder);
177 load_xinfo_from_proc_icmp6(netns, byteorder);
b53cc896 178 load_xinfo_from_proc_netlink(netns);
adfc156a 179 load_xinfo_from_proc_packet(netns);
97f54385 180
5468bb45 181 diagsd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_SOCK_DIAG);
497ada31
MY
182 DBG(ENDPOINTS, ul_debug("made a diagnose socket [fd=%d; %s]", diagsd,
183 (diagsd >= 0)? "successful": strerror(errno)));
5468bb45
MY
184 if (diagsd >= 0) {
185 load_xinfo_from_diag_unix(diagsd, netns);
186 close(diagsd);
497ada31 187 DBG(ENDPOINTS, ul_debug("close the diagnose socket"));
5468bb45
MY
188 }
189
97f54385
MY
190 if (nsobj)
191 load_ifaces_from_getifaddrs(nsobj);
0ee16e43
MY
192}
193
e6e551e8 194static void load_sock_xinfo_with_fd(int fd, struct netns *nsobj)
0ee16e43 195{
b3649945 196 if (setns(fd, CLONE_NEWNET) == 0) {
e6e551e8 197 load_sock_xinfo_no_nsswitch(nsobj);
b3649945 198 setns(self_netns_fd, CLONE_NEWNET);
0ee16e43
MY
199 }
200}
201
202void load_sock_xinfo(struct path_cxt *pc, const char *name, ino_t netns)
203{
204 if (self_netns_fd == -1)
205 return;
206
207 if (!is_sock_xinfo_loaded(netns)) {
208 int fd;
e6e551e8 209 struct netns *nsobj = mark_sock_xinfo_loaded(netns);
0ee16e43
MY
210 fd = ul_path_open(pc, O_RDONLY, name);
211 if (fd < 0)
212 return;
213
e6e551e8 214 load_sock_xinfo_with_fd(fd, nsobj);
0ee16e43
MY
215 close(fd);
216 }
217}
218
219void initialize_sock_xinfos(void)
220{
221 struct path_cxt *pc;
222 DIR *dir;
223 struct dirent *d;
224
225 self_netns_fd = open("/proc/self/ns/net", O_RDONLY);
226
227 if (self_netns_fd < 0)
e6e551e8 228 load_sock_xinfo_no_nsswitch(NULL);
0ee16e43
MY
229 else {
230 if (fstat(self_netns_fd, &self_netns_sb) == 0) {
916b44a5 231 unsigned long m;
e6e551e8
MY
232 struct netns *nsobj = mark_sock_xinfo_loaded(self_netns_sb.st_ino);
233 load_sock_xinfo_no_nsswitch(nsobj);
916b44a5
MY
234
235 m = minor(self_netns_sb.st_dev);
236 add_nodev(m, "nsfs");
0ee16e43
MY
237 }
238 }
239
240 /* Load /proc/net/{unix,...} of the network namespace
241 * specified with netns files under /var/run/netns/.
242 *
243 * `ip netns' command pins a network namespace on
244 * /var/run/netns.
245 */
246 pc = ul_new_path("/var/run/netns");
247 if (!pc)
248 err(EXIT_FAILURE, _("failed to alloc path context for /var/run/netns"));
249 dir = ul_path_opendir(pc, NULL);
250 if (dir == NULL) {
251 ul_unref_path(pc);
252 return;
253 }
254 while ((d = readdir(dir))) {
255 struct stat sb;
256 int fd;
e6e551e8 257 struct netns *nsobj;
0ee16e43
MY
258 if (ul_path_stat(pc, &sb, 0, d->d_name) < 0)
259 continue;
260 if (is_sock_xinfo_loaded(sb.st_ino))
261 continue;
e6e551e8 262 nsobj = mark_sock_xinfo_loaded(sb.st_ino);
0ee16e43
MY
263 fd = ul_path_open(pc, O_RDONLY, d->d_name);
264 if (fd < 0)
265 continue;
e6e551e8 266 load_sock_xinfo_with_fd(fd, nsobj);
0ee16e43
MY
267 close(fd);
268 }
269 closedir(dir);
270 ul_unref_path(pc);
271}
272
b3649945 273static void free_sock_xinfo(void *node)
0ee16e43
MY
274{
275 struct sock_xinfo *xinfo = node;
276 if (xinfo->class->free)
b3649945 277 xinfo->class->free(xinfo);
0ee16e43
MY
278 free(node);
279}
280
281void finalize_sock_xinfos(void)
282{
283 if (self_netns_fd != -1)
284 close(self_netns_fd);
e6e551e8 285 tdestroy(netns_tree, netns_free);
0ee16e43
MY
286 tdestroy(xinfo_tree, free_sock_xinfo);
287}
288
289static int xinfo_compare(const void *a, const void *b)
290{
0caccbf1 291 return ((struct sock_xinfo *)a)->inode - ((struct sock_xinfo *)b)->inode;
0ee16e43
MY
292}
293
2e38e61c
MY
294static void add_sock_info(struct sock_xinfo *xinfo)
295{
296 struct sock_xinfo **tmp = tsearch(xinfo, &xinfo_tree, xinfo_compare);
297
298 if (tmp == NULL)
299 errx(EXIT_FAILURE, _("failed to allocate memory"));
300}
301
b8bcca67 302struct sock_xinfo *get_sock_xinfo(ino_t inode)
0ee16e43 303{
816109f6
TW
304 struct sock_xinfo key = { .inode = inode };
305 struct sock_xinfo **xinfo = tfind(&key, &xinfo_tree, xinfo_compare);
0ee16e43
MY
306
307 if (xinfo)
308 return *xinfo;
309 return NULL;
310}
311
312bool is_nsfs_dev(dev_t dev)
313{
621cf7e9 314 return dev == self_netns_sb.st_dev;
0ee16e43 315}
2e38e61c
MY
316
317static const char *sock_decode_type(uint16_t type)
318{
319 switch (type) {
320 case SOCK_STREAM:
321 return "stream";
322 case SOCK_DGRAM:
323 return "dgram";
324 case SOCK_RAW:
325 return "raw";
326 case SOCK_RDM:
327 return "rdm";
328 case SOCK_SEQPACKET:
329 return "seqpacket";
330 case SOCK_DCCP:
331 return "dccp";
332 case SOCK_PACKET:
333 return "packet";
334 default:
335 return "unknown";
336 }
337}
338
5468bb45
MY
339static void send_diag_request(int diagsd, void *req, size_t req_size,
340 bool (*cb)(ino_t, size_t, void *),
341 ino_t netns)
342{
497ada31 343 int r;
5468bb45
MY
344 struct sockaddr_nl nladdr = {
345 .nl_family = AF_NETLINK,
346 };
347
348 struct nlmsghdr nlh = {
349 .nlmsg_len = sizeof(nlh) + req_size,
350 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
351 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
352 };
353
354 struct iovec iovecs[] = {
355 { &nlh, sizeof(nlh) },
356 { req, req_size },
357 };
358
359 const struct msghdr mhd = {
360 .msg_namelen = sizeof(nladdr),
361 .msg_name = &nladdr,
362 .msg_iovlen = ARRAY_SIZE(iovecs),
363 .msg_iov = iovecs,
364 };
365
7cde78d7 366 __attribute__((aligned(sizeof(void *)))) uint8_t buf[8192];
5468bb45 367
497ada31
MY
368 r = sendmsg(diagsd, &mhd, 0);
369 DBG(ENDPOINTS, ul_debug("sendmsg [rc=%d; %s]",
370 r, (r >= 0)? "successful": strerror(errno)));
371 if (r < 0)
5468bb45
MY
372 return;
373
374 for (;;) {
375 const struct nlmsghdr *h;
497ada31
MY
376 r = recvfrom(diagsd, buf, sizeof(buf), 0, NULL, NULL);
377 DBG(ENDPOINTS, ul_debug("recvfrom [rc=%d; %s]",
378 r, (r >= 0)? "successful": strerror(errno)));
5468bb45
MY
379 if (r < 0)
380 return;
381
382 h = (void *) buf;
497ada31 383 DBG(ENDPOINTS, ul_debug(" OK: %d", NLMSG_OK(h, (size_t)r)));
5468bb45
MY
384 if (!NLMSG_OK(h, (size_t)r))
385 return;
386
387 for (; NLMSG_OK(h, (size_t)r); h = NLMSG_NEXT(h, r)) {
497ada31
MY
388 if (h->nlmsg_type == NLMSG_DONE) {
389 DBG(ENDPOINTS, ul_debug(" DONE"));
5468bb45 390 return;
497ada31
MY
391 }
392 if (h->nlmsg_type == NLMSG_ERROR) {
393 struct nlmsgerr *e = (struct nlmsgerr *)NLMSG_DATA(h);
394 DBG(ENDPOINTS, ul_debug(" ERROR: %s",
395 strerror(- e->error)));
5468bb45 396 return;
497ada31 397 }
5468bb45
MY
398
399 if (h->nlmsg_type == SOCK_DIAG_BY_FAMILY) {
497ada31 400 DBG(ENDPOINTS, ul_debug(" FAMILY"));
5468bb45
MY
401 if (!cb(netns, h->nlmsg_len, NLMSG_DATA(h)))
402 return;
403 }
497ada31 404 DBG(ENDPOINTS, ul_debug(" NEXT"));
5468bb45 405 }
497ada31 406 DBG(ENDPOINTS, ul_debug(" OK: 0"));
5468bb45
MY
407 }
408}
409
2e38e61c
MY
410/*
411 * Protocol specific code
412 */
413
414/*
415 * UNIX
416 */
f9771d8d
MY
417struct unix_ipc {
418 struct ipc ipc;
419 ino_t inode;
420 ino_t ipeer;
421};
422
2e38e61c
MY
423struct unix_xinfo {
424 struct sock_xinfo sock;
425 int acceptcon; /* flags */
426 uint16_t type;
427 uint8_t st;
426ff07f
MY
428#define is_shutdown_mask_set(mask) ((mask) & (1 << 2))
429#define set_shutdown_mask(mask) ((mask) |= (1 << 2))
430 uint8_t shutdown_mask:3;
f9771d8d 431 struct unix_ipc *unix_ipc;
2e38e61c
MY
432 char path[
433 UNIX_PATH_MAX
434 + 1 /* for @ */
435 + 1 /* \0? */
436 ];
437};
438
439static const char *unix_decode_state(uint8_t st)
440{
441 switch (st) {
442 case SS_FREE:
443 return "free";
444 case SS_UNCONNECTED:
445 return "unconnected";
446 case SS_CONNECTING:
447 return "connecting";
448 case SS_CONNECTED:
449 return "connected";
450 case SS_DISCONNECTING:
451 return "disconnecting";
452 default:
453 return "unknown";
454 }
455}
456
457static char *unix_get_name(struct sock_xinfo *sock_xinfo,
458 struct sock *sock)
459{
460 struct unix_xinfo *ux = (struct unix_xinfo *)sock_xinfo;
461 const char *state = unix_decode_state(ux->st);
462 char *str = NULL;
463
464 if (sock->protoname && (strcmp(sock->protoname, "UNIX-STREAM") == 0))
465 xasprintf(&str, "state=%s%s%s",
466 (ux->acceptcon)? "listen": state,
467 *(ux->path)? " path=": "",
468 *(ux->path)? ux->path: "");
469 else
470 xasprintf(&str, "state=%s%s%s type=%s",
471 (ux->acceptcon)? "listen": state,
472 *(ux->path)? " path=": "",
473 *(ux->path)? ux->path: "",
474 sock_decode_type(ux->type));
475 return str;
476}
477
478static char *unix_get_type(struct sock_xinfo *sock_xinfo,
479 struct sock *sock __attribute__((__unused__)))
480{
481 const char *str;
482 struct unix_xinfo *ux = (struct unix_xinfo *)sock_xinfo;
483
484 str = sock_decode_type(ux->type);
e0dc84da 485 return xstrdup(str);
2e38e61c
MY
486}
487
488static char *unix_get_state(struct sock_xinfo *sock_xinfo,
489 struct sock *sock __attribute__((__unused__)))
490{
491 const char *str;
492 struct unix_xinfo *ux = (struct unix_xinfo *)sock_xinfo;
493
494 if (ux->acceptcon)
e0dc84da 495 return xstrdup("listen");
2e38e61c
MY
496
497 str = unix_decode_state(ux->st);
e0dc84da 498 return xstrdup(str);
2e38e61c
MY
499}
500
45d61bff
MY
501static bool unix_get_listening(struct sock_xinfo *sock_xinfo,
502 struct sock *sock __attribute__((__unused__)))
503{
504 struct unix_xinfo *ux = (struct unix_xinfo *)sock_xinfo;
505
506 return ux->acceptcon;
507}
508
f9771d8d
MY
509static unsigned int unix_get_hash(struct file *file)
510{
511 return (unsigned int)(file->stat.st_ino % UINT_MAX);
512}
513
514static bool unix_is_suitable_ipc(struct ipc *ipc, struct file *file)
515{
516 return ((struct unix_ipc *)ipc)->inode == file->stat.st_ino;
517}
518
519/* For looking up an ipc struct for a sock inode, we need a sock strcuct
520 * for the inode. See the signature o get_ipc().
521 *
522 * However, there is a case that we have no sock strcuct for the inode;
523 * in the context we know only the sock inode.
d7afda83 524 * For the case, unix_make_dummy_sock() provides the way to make a
f9771d8d
MY
525 * dummy sock struct for the inode.
526 */
d7afda83 527static void unix_make_dummy_sock(struct sock *original, ino_t ino, struct sock *dummy)
f9771d8d
MY
528{
529 *dummy = *original;
530 dummy->file.stat.st_ino = ino;
531}
532
533static struct ipc_class unix_ipc_class = {
534 .size = sizeof(struct unix_ipc),
535 .get_hash = unix_get_hash,
536 .is_suitable_ipc = unix_is_suitable_ipc,
537 .free = NULL,
538};
539
540static struct ipc_class *unix_get_ipc_class(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
541 struct sock *sock __attribute__((__unused__)))
542{
543 return &unix_ipc_class;
544}
545
426ff07f
MY
546static bool unix_shutdown_chars(struct unix_xinfo *ux, char rw[2])
547{
548 uint8_t mask = ux->shutdown_mask;
549
550 if (is_shutdown_mask_set(mask)) {
551 rw[0] = ((mask & (1 << 0))? '-': 'r');
552 rw[1] = ((mask & (1 << 1))? '-': 'w');
553 return true;
554 }
555
556 return false;
557}
558
f9771d8d
MY
559static inline char *unix_xstrendpoint(struct sock *sock)
560{
561 char *str = NULL;
3f3da329
MY
562 char shutdown_chars[3] = { 0 };
563
564 if (!unix_shutdown_chars(((struct unix_xinfo *)sock->xinfo), shutdown_chars)) {
565 shutdown_chars[0] = '?';
566 shutdown_chars[1] = '?';
567 }
568 xasprintf(&str, "%d,%s,%d%c%c",
569 sock->file.proc->pid, sock->file.proc->command, sock->file.association,
570 shutdown_chars[0], shutdown_chars[1]);
571
f9771d8d
MY
572 return str;
573}
574
575static struct ipc *unix_get_peer_ipc(struct unix_xinfo *ux,
576 struct sock *sock)
577{
578 struct unix_ipc *unix_ipc;
579 struct sock dummy_peer_sock;
580
581 unix_ipc = ux->unix_ipc;
582 if (!unix_ipc)
583 return NULL;
584
d7afda83 585 unix_make_dummy_sock(sock, unix_ipc->ipeer, &dummy_peer_sock);
f9771d8d
MY
586 return get_ipc(&dummy_peer_sock.file);
587}
588
2e38e61c
MY
589static bool unix_fill_column(struct proc *proc __attribute__((__unused__)),
590 struct sock_xinfo *sock_xinfo,
f9771d8d 591 struct sock *sock,
2e38e61c
MY
592 struct libscols_line *ln __attribute__((__unused__)),
593 int column_id,
594 size_t column_index __attribute__((__unused__)),
595 char **str)
596{
597 struct unix_xinfo *ux = (struct unix_xinfo *)sock_xinfo;
f9771d8d
MY
598 struct ipc *peer_ipc;
599 struct list_head *e;
426ff07f 600 char shutdown_chars[3] = { 0 };
2e38e61c 601
854ddd0d 602 switch (column_id) {
2e38e61c
MY
603 case COL_UNIX_PATH:
604 if (*ux->path) {
e0dc84da 605 *str = xstrdup(ux->path);
2e38e61c
MY
606 return true;
607 }
608 break;
f9771d8d
MY
609 case COL_ENDPOINTS:
610 peer_ipc = unix_get_peer_ipc(ux, sock);
611 if (!peer_ipc)
612 break;
613
614 list_for_each_backwardly(e, &peer_ipc->endpoints) {
615 struct sock *peer_sock = list_entry(e, struct sock, endpoint.endpoints);
616 char *estr;
617
618 if (*str)
619 xstrputc(str, '\n');
620 estr = unix_xstrendpoint(peer_sock);
621 xstrappend(str, estr);
622 free(estr);
623 }
624 if (*str)
625 return true;
626 break;
426ff07f
MY
627 case COL_SOCK_SHUTDOWN:
628 if (unix_shutdown_chars(ux, shutdown_chars)) {
629 *str = xstrdup(shutdown_chars);
630 return true;
631 }
632 break;
2e38e61c
MY
633 }
634
635 return false;
636}
637
54a06438 638static const struct sock_xinfo_class unix_xinfo_class = {
2e38e61c
MY
639 .get_name = unix_get_name,
640 .get_type = unix_get_type,
641 .get_state = unix_get_state,
45d61bff 642 .get_listening = unix_get_listening,
2e38e61c 643 .fill_column = unix_fill_column,
f9771d8d 644 .get_ipc_class = unix_get_ipc_class,
2e38e61c
MY
645 .free = NULL,
646};
647
e8e14a28 648/* UNIX_LINE_LEN need at least 54 + 21 + UNIX_PATH_MAX + 1.
eeaf7677
MY
649 *
650 * An actual number must be used in this definition
651 * since UNIX_LINE_LEN is specified as an argument for
652 * stringify_value().
653 */
2e38e61c
MY
654#define UNIX_LINE_LEN 256
655static void load_xinfo_from_proc_unix(ino_t netns_inode)
656{
657 char line[UNIX_LINE_LEN];
658 FILE *unix_fp;
659
660 unix_fp = fopen("/proc/net/unix", "r");
497ada31
MY
661 DBG(ENDPOINTS, ul_debug("open /proc/net/unix [fp=%p; %s]", unix_fp,
662 unix_fp? "successful": strerror(errno)));
2e38e61c
MY
663 if (!unix_fp)
664 return;
665
666 if (fgets(line, sizeof(line), unix_fp) == NULL)
667 goto out;
b3649945 668 if (!(line[0] == 'N' && line[1] == 'u' && line[2] == 'm'))
2e38e61c
MY
669 /* Unexpected line */
670 goto out;
671
672 while (fgets(line, sizeof(line), unix_fp)) {
673 uint64_t flags;
674 uint32_t type;
675 unsigned int st;
676 unsigned long inode;
2e38e61c 677 struct unix_xinfo *ux;
eeaf7677 678 char path[UNIX_LINE_LEN + 1] = { 0 };
497ada31 679 int r;
91a484fe 680
497ada31 681 DBG(ENDPOINTS, ul_debug(" line: %s", line));
2e38e61c 682
497ada31 683 r = sscanf(line, "%*x: %*x %*x %" SCNx64 " %x %x %lu %"
eeaf7677 684 stringify_value(UNIX_LINE_LEN) "[^\n]",
497ada31
MY
685 &flags, &type, &st, &inode, path);
686 DBG(ENDPOINTS, ul_debug(" scanf: %d", r));
687 if (r < 4)
2e38e61c
MY
688 continue;
689
497ada31 690 DBG(ENDPOINTS, ul_debug(" inode: %lu", inode));
2e38e61c
MY
691 if (inode == 0)
692 continue;
693
8ff22ccb 694 ux = xcalloc(1, sizeof(*ux));
2e38e61c
MY
695 ux->sock.class = &unix_xinfo_class;
696 ux->sock.inode = (ino_t)inode;
697 ux->sock.netns_inode = netns_inode;
698
699 ux->acceptcon = !!flags;
700 ux->type = type;
701 ux->st = st;
91a484fe 702 xstrncpy(ux->path, path, sizeof(ux->path));
2e38e61c 703
497ada31 704 DBG(ENDPOINTS, ul_debug(" path: %s", ux->path));
2ac8d1a3 705 add_sock_info(&ux->sock);
2e38e61c
MY
706 }
707
708 out:
497ada31 709 DBG(ENDPOINTS, ul_debug("close /proc/net/unix"));
2e38e61c
MY
710 fclose(unix_fp);
711}
7b2a9be0 712
5468bb45
MY
713/* The path name extracted from /proc/net/unix is unreliable; the line oriented interface cannot
714 * represent a file name including newlines. With unix_refill_name(), we patch the path
715 * member of unix_xinfos with information received via netlink diag interface. */
716static void unix_refill_name(struct sock_xinfo *xinfo, const char *name, size_t len)
717{
718 struct unix_xinfo *ux = (struct unix_xinfo *)xinfo;
719 size_t min_len;
720
721 if (len == 0)
722 return;
723
724 min_len = min(sizeof(ux->path) - 1, len);
725 memcpy(ux->path, name, min_len);
726 if (ux->path[0] == '\0') {
727 ux->path[0] = '@';
728 }
729 ux->path[min_len] = '\0';
730}
731
732static bool handle_diag_unix(ino_t netns __attribute__((__unused__)),
733 size_t nlmsg_len, void *nlmsg_data)
734{
735 const struct unix_diag_msg *diag = nlmsg_data;
736 size_t rta_len;
737 ino_t inode;
738 struct sock_xinfo *xinfo;
f9771d8d 739 struct unix_xinfo *unix_xinfo;
5468bb45
MY
740
741 if (diag->udiag_family != AF_UNIX)
742 return false;
497ada31
MY
743 DBG(ENDPOINTS, ul_debug(" UNIX"));
744 DBG(ENDPOINTS, ul_debug(" LEN: %zu (>= %zu)", nlmsg_len,
745 (size_t)(NLMSG_LENGTH(sizeof(*diag)))));
5468bb45
MY
746
747 if (nlmsg_len < NLMSG_LENGTH(sizeof(*diag)))
748 return false;
749
750 inode = (ino_t)diag->udiag_ino;
751 xinfo = get_sock_xinfo(inode);
752
497ada31
MY
753 DBG(ENDPOINTS, ul_debug(" inode: %llu", (unsigned long long)inode));
754 DBG(ENDPOINTS, ul_debug(" xinfo: %p", xinfo));
755
5468bb45
MY
756 if (xinfo == NULL)
757 /* The socket is found in the diag response
758 but not in the proc fs. */
759 return true;
760
497ada31
MY
761 DBG(ENDPOINTS, ul_debug(" xinfo->class == &unix_xinfo_class: %d",
762 xinfo->class == &unix_xinfo_class));
5468bb45
MY
763 if (xinfo->class != &unix_xinfo_class)
764 return true;
f9771d8d 765 unix_xinfo = (struct unix_xinfo *)xinfo;
5468bb45
MY
766
767 rta_len = nlmsg_len - NLMSG_LENGTH(sizeof(*diag));
497ada31 768 DBG(ENDPOINTS, ul_debug(" rta_len: %zu", rta_len));
5468bb45
MY
769 for (struct rtattr *attr = (struct rtattr *)(diag + 1);
770 RTA_OK(attr, rta_len);
771 attr = RTA_NEXT(attr, rta_len)) {
772 size_t len = RTA_PAYLOAD(attr);
773
497ada31
MY
774 DBG(ENDPOINTS, ul_debug(" len = %2zu, type: %d",
775 rta_len, attr->rta_type));
5468bb45
MY
776 switch (attr->rta_type) {
777 case UNIX_DIAG_NAME:
778 unix_refill_name(xinfo, RTA_DATA(attr), len);
779 break;
f9771d8d 780
426ff07f
MY
781 case UNIX_DIAG_SHUTDOWN:
782 if (len < 1)
783 break;
784
785 unix_xinfo->shutdown_mask = *(uint8_t *)RTA_DATA(attr);
786 set_shutdown_mask(unix_xinfo->shutdown_mask);
787 break;
788
f9771d8d
MY
789 case UNIX_DIAG_PEER:
790 if (len < 4)
791 break;
792
793 unix_xinfo->unix_ipc = (struct unix_ipc *)new_ipc(&unix_ipc_class);
794 unix_xinfo->unix_ipc->inode = inode;
795 unix_xinfo->unix_ipc->ipeer = (ino_t)(*(uint32_t *)RTA_DATA(attr));
796 add_ipc(&unix_xinfo->unix_ipc->ipc, inode % UINT_MAX);
797 break;
5468bb45
MY
798 }
799 }
800 return true;
801}
802
803static void load_xinfo_from_diag_unix(int diagsd, ino_t netns)
804{
805 struct unix_diag_req udr = {
806 .sdiag_family = AF_UNIX,
807 .udiag_states = -1, /* set the all bits. */
426ff07f 808 .udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER | UNIX_DIAG_SHUTDOWN,
5468bb45
MY
809 };
810
811 send_diag_request(diagsd, &udr, sizeof(udr), handle_diag_unix, netns);
812}
813
7b2a9be0
MY
814/*
815 * AF_INET
816 */
817struct inet_xinfo {
818 struct sock_xinfo sock;
643f30c7
MY
819 struct in_addr local_addr;
820 struct in_addr remote_addr;
7b2a9be0
MY
821};
822
9020c2e0 823static uint32_t kernel32_to_cpu(enum sysfs_byteorder byteorder, uint32_t v)
7b2a9be0 824{
9020c2e0
MY
825 if (byteorder == SYSFS_BYTEORDER_LITTLE)
826 return le32_to_cpu(v);
827 else
828 return be32_to_cpu(v);
7b2a9be0
MY
829}
830
1656da13
MY
831/*
832 * AF_INET6
833 */
834struct inet6_xinfo {
835 struct sock_xinfo sock;
836 struct in6_addr local_addr;
837 struct in6_addr remote_addr;
838};
839
7b2a9be0 840/*
4a2b51c1 841 * L4 abstract-layer for protocols stacked on IP and IP6.
7b2a9be0 842 */
303b41fe 843enum l4_state {
7b2a9be0
MY
844 /*
845 * Taken from linux/include/net/tcp_states.h.
846 * (GPL-2.0-or-later)
303b41fe
MY
847 *
848 * UDP and RAW sockets also uses the contents in Linux.
7b2a9be0
MY
849 */
850 TCP_ESTABLISHED = 1,
851 TCP_SYN_SENT,
852 TCP_SYN_RECV,
853 TCP_FIN_WAIT1,
854 TCP_FIN_WAIT2,
855 TCP_TIME_WAIT,
856 TCP_CLOSE,
857 TCP_CLOSE_WAIT,
858 TCP_LAST_ACK,
859 TCP_LISTEN,
860 TCP_CLOSING,
861 TCP_NEW_SYN_RECV,
862
863 TCP_MAX_STATES /* Leave at the end! */
864};
865
303b41fe 866static const char *l4_decode_state(enum l4_state st)
7b2a9be0 867{
86242cb0 868 const char * const table [] = {
7b2a9be0
MY
869 [TCP_ESTABLISHED] = "established",
870 [TCP_SYN_SENT] = "syn-sent",
871 [TCP_SYN_RECV] = "syn-recv",
872 [TCP_FIN_WAIT1] = "fin-wait1",
873 [TCP_FIN_WAIT2] = "fin-wait2",
874 [TCP_TIME_WAIT] = "time-wait",
875 [TCP_CLOSE] = "close",
876 [TCP_CLOSE_WAIT] = "close-wait",
877 [TCP_LAST_ACK] = "last-ack",
878 [TCP_LISTEN] = "listen",
879 [TCP_CLOSING] = "closing",
880 [TCP_NEW_SYN_RECV] = "new-syn-recv",
881 };
882
883 if (st < TCP_MAX_STATES)
884 return table[st];
885 return "unknown";
886}
887
4a2b51c1 888struct l4_xinfo {
1656da13
MY
889 union {
890 struct inet_xinfo inet;
891 struct inet6_xinfo inet6;
892 };
303b41fe 893 enum l4_state st;
4a2b51c1
MY
894};
895
2a4f2b1b 896enum l4_side { L4_LOCAL, L4_REMOTE };
1656da13 897enum l3_decorator { L3_DECO_START, L3_DECO_END };
2a4f2b1b 898
4a2b51c1
MY
899struct l4_xinfo_class {
900 struct sock_xinfo_class sock;
19e40223
MY
901 struct sock_xinfo *(*scan_line)(const struct sock_xinfo_class *,
902 char *,
903 ino_t,
904 enum sysfs_byteorder);
2a4f2b1b
MY
905 void * (*get_addr)(struct l4_xinfo *, enum l4_side);
906 bool (*is_any_addr)(void *);
907 int family;
1656da13 908 const char *l3_decorator[2];
4a2b51c1
MY
909};
910
838fa270
MY
911#define l3_fill_column_handler(L3, SOCK_XINFO, COLUMN_ID, STR) __extension__ \
912 ({ \
913 struct l4_xinfo_class *class = (struct l4_xinfo_class *)SOCK_XINFO->class; \
914 struct l4_xinfo *l4 = (struct l4_xinfo *)SOCK_XINFO; \
915 void *n = NULL; \
916 char s[BUFSIZ]; \
917 bool r = false; \
918 \
919 switch (COLUMN_ID) { \
920 case COL_##L3##_LADDR: \
921 n = class->get_addr(l4, L4_LOCAL); \
922 break; \
923 case COL_##L3##_RADDR: \
924 n = class->get_addr(l4, L4_REMOTE); \
925 break; \
926 default: \
927 break; \
928 } \
929 \
930 if (n && inet_ntop(class->family, n, s, sizeof(s))) { \
e0dc84da 931 *STR = xstrdup(s); \
838fa270
MY
932 r = true; \
933 } \
934 r; \
935 })
936
7b2a9be0
MY
937/*
938 * TCP
939 */
940struct tcp_xinfo {
4a2b51c1 941 struct l4_xinfo l4;
7b2a9be0
MY
942 uint16_t local_port;
943 uint16_t remote_port;
7b2a9be0
MY
944};
945
7b2a9be0
MY
946static char *tcp_get_name(struct sock_xinfo *sock_xinfo,
947 struct sock *sock __attribute__((__unused__)))
948{
949 char *str = NULL;
7b2a9be0 950 struct tcp_xinfo *tcp = ((struct tcp_xinfo *)sock_xinfo);
8db07ebc 951 struct l4_xinfo *l4 = &tcp->l4;
303b41fe 952 const char *st_str = l4_decode_state(l4->st);
838fa270
MY
953 struct l4_xinfo_class *class = (struct l4_xinfo_class *)sock_xinfo->class;
954 void *laddr = class->get_addr(l4, L4_LOCAL);
955 void *raddr = class->get_addr(l4, L4_REMOTE);
956 char local_s[BUFSIZ];
957 char remote_s[BUFSIZ];
1656da13
MY
958 const char *start = class->l3_decorator[L3_DECO_START];
959 const char *end = class->l3_decorator[L3_DECO_END];
7b2a9be0 960
838fa270 961 if (!inet_ntop(class->family, laddr, local_s, sizeof(local_s)))
3b182ee7
MY
962 xasprintf(&str, "state=%s", st_str);
963 else if (l4->st == TCP_LISTEN
838fa270 964 || !inet_ntop(class->family, raddr, remote_s, sizeof(remote_s)))
b4e39841 965 xasprintf(&str, "state=%s laddr=%s%s%s:%"PRIu16,
3b182ee7 966 st_str,
1656da13 967 start, local_s, end, tcp->local_port);
7b2a9be0 968 else
b4e39841 969 xasprintf(&str, "state=%s laddr=%s%s%s:%"PRIu16" raddr=%s%s%s:%"PRIu16,
3b182ee7 970 st_str,
1656da13
MY
971 start, local_s, end, tcp->local_port,
972 start, remote_s, end, tcp->remote_port);
7b2a9be0
MY
973 return str;
974}
975
976static char *tcp_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
977 struct sock *sock __attribute__((__unused__)))
978{
e0dc84da 979 return xstrdup("stream");
7b2a9be0
MY
980}
981
982static char *tcp_get_state(struct sock_xinfo *sock_xinfo,
983 struct sock *sock __attribute__((__unused__)))
984{
e0dc84da 985 return xstrdup(l4_decode_state(((struct l4_xinfo *)sock_xinfo)->st));
7b2a9be0
MY
986}
987
988static bool tcp_get_listening(struct sock_xinfo *sock_xinfo,
989 struct sock *sock __attribute__((__unused__)))
990{
8db07ebc 991 return ((struct l4_xinfo *)sock_xinfo)->st == TCP_LISTEN;
7b2a9be0
MY
992}
993
838fa270
MY
994#define l4_fill_column_handler(L4, SOCK_XINFO, COLUMN_ID, STR) __extension__ \
995 ({ \
996 struct l4_xinfo_class *class = (struct l4_xinfo_class *)SOCK_XINFO->class; \
997 struct tcp_xinfo *tcp = (struct tcp_xinfo *)SOCK_XINFO; \
998 struct l4_xinfo *l4 = &tcp->l4; \
999 void *n = NULL; \
92a0dbce 1000 bool has_laddr = false; \
73df46fc 1001 unsigned short p; \
92a0dbce 1002 bool has_lport = false; \
838fa270
MY
1003 char s[BUFSIZ]; \
1004 bool r = true; \
92a0dbce 1005 \
838fa270 1006 switch (COLUMN_ID) { \
cda2b2a0 1007 case COL_##L4##_LADDR: \
838fa270 1008 n = class->get_addr(l4, L4_LOCAL); \
92a0dbce 1009 has_laddr = true; \
73df46fc 1010 p = tcp->local_port; \
92a0dbce 1011 /* FALL THROUGH */ \
cda2b2a0 1012 case COL_##L4##_RADDR: \
92a0dbce 1013 if (!has_laddr) { \
838fa270 1014 n = class->get_addr(l4, L4_REMOTE); \
73df46fc 1015 p = tcp->remote_port; \
92a0dbce 1016 } \
838fa270 1017 if (n && inet_ntop(class->family, n, s, sizeof(s))) \
b4e39841 1018 xasprintf(STR, "%s%s%s:%"PRIu16, \
1656da13
MY
1019 class->l3_decorator[L3_DECO_START], \
1020 s, \
1021 class->l3_decorator[L3_DECO_END], \
1022 p); \
92a0dbce 1023 break; \
cda2b2a0 1024 case COL_##L4##_LPORT: \
73df46fc 1025 p = tcp->local_port; \
92a0dbce
MY
1026 has_lport = true; \
1027 /* FALL THROUGH */ \
cda2b2a0 1028 case COL_##L4##_RPORT: \
92a0dbce 1029 if (!has_lport) \
73df46fc 1030 p = tcp->remote_port; \
b4e39841 1031 xasprintf(STR, "%"PRIu16, p); \
92a0dbce
MY
1032 break; \
1033 default: \
838fa270
MY
1034 r = false; \
1035 break; \
92a0dbce 1036 } \
838fa270
MY
1037 r; \
1038 })
7b2a9be0 1039
19e40223
MY
1040static struct sock_xinfo *tcp_xinfo_scan_line(const struct sock_xinfo_class *class,
1041 char * line,
1042 ino_t netns_inode,
1043 enum sysfs_byteorder byteorder)
1044{
1045 unsigned long local_addr;
1046 unsigned long local_port;
1047 unsigned long remote_addr;
1048 unsigned long remote_port;
1049 unsigned long st;
1050 unsigned long long inode;
1051 struct tcp_xinfo *tcp;
1052 struct inet_xinfo *inet;
1053 struct sock_xinfo *sock;
1054
1055 if (sscanf(line, "%*d: %lx:%lx %lx:%lx %lx %*x:%*x %*x:%*x %*x %*u %*u %lld",
1056 &local_addr, &local_port, &remote_addr, &remote_port,
1057 &st, &inode) != 6)
1058 return NULL;
1059
1060 if (inode == 0)
1061 return NULL;
1062
8ff22ccb 1063 tcp = xcalloc(1, sizeof(*tcp));
19e40223
MY
1064 inet = &tcp->l4.inet;
1065 sock = &inet->sock;
1066 sock->class = class;
1067 sock->inode = (ino_t)inode;
1068 sock->netns_inode = netns_inode;
1069 inet->local_addr.s_addr = kernel32_to_cpu(byteorder, local_addr);
1070 tcp->local_port = local_port;
1071 inet->remote_addr.s_addr = kernel32_to_cpu(byteorder, remote_addr);
1072 tcp->remote_port = remote_port;
8db07ebc 1073 tcp->l4.st = st;
19e40223
MY
1074
1075 return sock;
1076}
1077
2a4f2b1b
MY
1078static void *tcp_xinfo_get_addr(struct l4_xinfo *l4, enum l4_side side)
1079{
1080 return (side == L4_LOCAL)
1081 ? &l4->inet.local_addr
1082 : &l4->inet.remote_addr;
1083}
1084
1085static bool tcp_xinfo_is_any_addr(void *addr)
1086{
1087 return ((struct in_addr *)addr)->s_addr == INADDR_ANY;
1088}
1089
838fa270
MY
1090static bool tcp_fill_column(struct proc *proc __attribute__((__unused__)),
1091 struct sock_xinfo *sock_xinfo,
1092 struct sock *sock __attribute__((__unused__)),
1093 struct libscols_line *ln __attribute__((__unused__)),
1094 int column_id,
1095 size_t column_index __attribute__((__unused__)),
1096 char **str)
1097{
1098 return l3_fill_column_handler(INET, sock_xinfo, column_id, str)
1099 || l4_fill_column_handler(TCP, sock_xinfo, column_id, str);
1100}
1101
4a2b51c1
MY
1102static const struct l4_xinfo_class tcp_xinfo_class = {
1103 .sock = {
1104 .get_name = tcp_get_name,
1105 .get_type = tcp_get_type,
1106 .get_state = tcp_get_state,
1107 .get_listening = tcp_get_listening,
1108 .fill_column = tcp_fill_column,
1109 .free = NULL,
1110 },
19e40223 1111 .scan_line = tcp_xinfo_scan_line,
2a4f2b1b
MY
1112 .get_addr = tcp_xinfo_get_addr,
1113 .is_any_addr = tcp_xinfo_is_any_addr,
1114 .family = AF_INET,
1656da13 1115 .l3_decorator = {"", ""},
7b2a9be0
MY
1116};
1117
cda2b2a0 1118static bool L4_verify_initial_line(const char *line)
58d2f31e
MY
1119{
1120 /* At least we expect two white spaces. */
cb097fb7 1121 if (strncmp(line, " ", 2) != 0)
58d2f31e
MY
1122 return false;
1123 line += 2;
1124
1125 /* Skip white spaces. */
4658bfb1 1126 line = skip_space(line);
58d2f31e 1127
621cf7e9 1128 return strncmp(line, "sl", 2) == 0;
db79a100
TW
1129}
1130
7b2a9be0 1131#define TCP_LINE_LEN 256
cda2b2a0 1132static void load_xinfo_from_proc_inet_L4(ino_t netns_inode, const char *proc_file,
891b24b7
MY
1133 const struct l4_xinfo_class *class,
1134 enum sysfs_byteorder byteorder)
7b2a9be0
MY
1135{
1136 char line[TCP_LINE_LEN];
1137 FILE *tcp_fp;
1138
92a0dbce 1139 tcp_fp = fopen(proc_file, "r");
7b2a9be0
MY
1140 if (!tcp_fp)
1141 return;
1142
1143 if (fgets(line, sizeof(line), tcp_fp) == NULL)
1144 goto out;
cda2b2a0 1145 if (!L4_verify_initial_line(line))
7b2a9be0
MY
1146 /* Unexpected line */
1147 goto out;
1148
1149 while (fgets(line, sizeof(line), tcp_fp)) {
19e40223
MY
1150 struct sock_xinfo *sock = class->scan_line(&class->sock, line, netns_inode, byteorder);
1151 if (sock)
1152 add_sock_info(sock);
7b2a9be0
MY
1153 }
1154
1155 out:
1156 fclose(tcp_fp);
1157}
92a0dbce 1158
891b24b7 1159static void load_xinfo_from_proc_tcp(ino_t netns_inode, enum sysfs_byteorder byteorder)
92a0dbce 1160{
cda2b2a0 1161 load_xinfo_from_proc_inet_L4(netns_inode,
58d2f31e 1162 "/proc/net/tcp",
891b24b7
MY
1163 &tcp_xinfo_class,
1164 byteorder);
92a0dbce
MY
1165}
1166
1167/*
1168 * UDP
1169 */
1170static char *udp_get_name(struct sock_xinfo *sock_xinfo,
1171 struct sock *sock __attribute__((__unused__)))
1172{
1173 char *str = NULL;
92a0dbce 1174 struct tcp_xinfo *tcp = ((struct tcp_xinfo *)sock_xinfo);
8db07ebc 1175 struct l4_xinfo *l4 = &tcp->l4;
8db07ebc 1176 unsigned int st = l4->st;
303b41fe 1177 const char *st_str = l4_decode_state(st);
838fa270
MY
1178 struct l4_xinfo_class *class = (struct l4_xinfo_class *)sock_xinfo->class;
1179 void *laddr = class->get_addr(l4, L4_LOCAL);
1180 void *raddr = class->get_addr(l4, L4_REMOTE);
1181 char local_s[BUFSIZ];
1182 char remote_s[BUFSIZ];
28cf2b21
MY
1183 const char *start = class->l3_decorator[L3_DECO_START];
1184 const char *end = class->l3_decorator[L3_DECO_END];
92a0dbce 1185
838fa270 1186 if (!inet_ntop(class->family, laddr, local_s, sizeof(local_s)))
3b182ee7 1187 xasprintf(&str, "state=%s", st_str);
838fa270
MY
1188 else if ((class->is_any_addr(raddr) && tcp->remote_port == 0)
1189 || !inet_ntop(class->family, raddr, remote_s, sizeof(remote_s)))
28cf2b21 1190 xasprintf(&str, "state=%s laddr=%s%s%s:%"PRIu16,
3b182ee7 1191 st_str,
28cf2b21 1192 start, local_s, end, tcp->local_port);
92a0dbce 1193 else
28cf2b21 1194 xasprintf(&str, "state=%s laddr=%s%s%s:%"PRIu16" raddr=%s%s%s:%"PRIu16,
3b182ee7 1195 st_str,
28cf2b21
MY
1196 start, local_s, end, tcp->local_port,
1197 start, remote_s, end, tcp->remote_port);
92a0dbce
MY
1198 return str;
1199}
1200
1201static char *udp_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
1202 struct sock *sock __attribute__((__unused__)))
1203{
e0dc84da 1204 return xstrdup("dgram");
92a0dbce
MY
1205}
1206
838fa270
MY
1207static bool udp_fill_column(struct proc *proc __attribute__((__unused__)),
1208 struct sock_xinfo *sock_xinfo,
1209 struct sock *sock __attribute__((__unused__)),
1210 struct libscols_line *ln __attribute__((__unused__)),
1211 int column_id,
1212 size_t column_index __attribute__((__unused__)),
1213 char **str)
1214{
1215 return l3_fill_column_handler(INET, sock_xinfo, column_id, str)
1216 || l4_fill_column_handler(UDP, sock_xinfo, column_id, str);
1217}
1218
4a2b51c1
MY
1219static const struct l4_xinfo_class udp_xinfo_class = {
1220 .sock = {
1221 .get_name = udp_get_name,
1222 .get_type = udp_get_type,
1223 .get_state = tcp_get_state,
1224 .get_listening = NULL,
1225 .fill_column = udp_fill_column,
1226 .free = NULL,
1227 },
19e40223 1228 .scan_line = tcp_xinfo_scan_line,
2a4f2b1b
MY
1229 .get_addr = tcp_xinfo_get_addr,
1230 .is_any_addr = tcp_xinfo_is_any_addr,
1231 .family = AF_INET,
1656da13 1232 .l3_decorator = {"", ""},
92a0dbce
MY
1233};
1234
891b24b7 1235static void load_xinfo_from_proc_udp(ino_t netns_inode, enum sysfs_byteorder byteorder)
92a0dbce 1236{
cda2b2a0 1237 load_xinfo_from_proc_inet_L4(netns_inode,
92a0dbce 1238 "/proc/net/udp",
891b24b7
MY
1239 &udp_xinfo_class,
1240 byteorder);
92a0dbce 1241}
0188afb3 1242
c779f412
MY
1243/*
1244 * UDP-Lite
1245 */
1246static bool udplite_fill_column(struct proc *proc __attribute__((__unused__)),
1247 struct sock_xinfo *sock_xinfo,
1248 struct sock *sock __attribute__((__unused__)),
1249 struct libscols_line *ln __attribute__((__unused__)),
1250 int column_id,
1251 size_t column_index __attribute__((__unused__)),
1252 char **str)
1253{
1254 return l3_fill_column_handler(INET, sock_xinfo, column_id, str)
1255 || l4_fill_column_handler(UDPLITE, sock_xinfo, column_id, str);
1256}
1257
1258static const struct l4_xinfo_class udplite_xinfo_class = {
1259 .sock = {
1260 .get_name = udp_get_name,
1261 .get_type = udp_get_type,
1262 .get_state = tcp_get_state,
1263 .get_listening = NULL,
1264 .fill_column = udplite_fill_column,
1265 .free = NULL,
1266 },
1267 .scan_line = tcp_xinfo_scan_line,
1268 .get_addr = tcp_xinfo_get_addr,
1269 .is_any_addr = tcp_xinfo_is_any_addr,
1270 .family = AF_INET,
1271 .l3_decorator = {"", ""},
1272};
1273
891b24b7 1274static void load_xinfo_from_proc_udplite(ino_t netns_inode, enum sysfs_byteorder byteorder)
c779f412
MY
1275{
1276 load_xinfo_from_proc_inet_L4(netns_inode,
1277 "/proc/net/udplite",
891b24b7
MY
1278 &udplite_xinfo_class,
1279 byteorder);
c779f412
MY
1280}
1281
0188afb3
MY
1282/*
1283 * RAW
1284 */
1285struct raw_xinfo {
1286 struct l4_xinfo l4;
1287 uint16_t protocol;
1288};
1289
a7cba6f3
MY
1290static char *raw_get_name_common(struct sock_xinfo *sock_xinfo,
1291 struct sock *sock __attribute__((__unused__)),
1292 const char *port_label)
0188afb3
MY
1293{
1294 char *str = NULL;
1295 struct l4_xinfo_class *class = (struct l4_xinfo_class *)sock_xinfo->class;
1296 struct raw_xinfo *raw = ((struct raw_xinfo *)sock_xinfo);
1297 struct l4_xinfo *l4 = &raw->l4;
303b41fe 1298 const char *st_str = l4_decode_state(l4->st);
0188afb3
MY
1299 void *laddr = class->get_addr(l4, L4_LOCAL);
1300 void *raddr = class->get_addr(l4, L4_REMOTE);
1301 char local_s[BUFSIZ];
1302 char remote_s[BUFSIZ];
1303
1304 if (!inet_ntop(class->family, laddr, local_s, sizeof(local_s)))
1305 xasprintf(&str, "state=%s", st_str);
1306 else if (class->is_any_addr(raddr)
1307 || !inet_ntop(class->family, raddr, remote_s, sizeof(remote_s)))
a7cba6f3 1308 xasprintf(&str, "state=%s %s=%"PRIu16" laddr=%s",
0188afb3 1309 st_str,
a7cba6f3 1310 port_label,
0188afb3
MY
1311 raw->protocol, local_s);
1312 else
a7cba6f3 1313 xasprintf(&str, "state=%s %s=%"PRIu16" laddr=%s raddr=%s",
0188afb3 1314 st_str,
a7cba6f3 1315 port_label,
0188afb3
MY
1316 raw->protocol, local_s, remote_s);
1317 return str;
1318}
1319
a7cba6f3
MY
1320static char *raw_get_name(struct sock_xinfo *sock_xinfo,
1321 struct sock *sock __attribute__((__unused__)))
1322{
1323 return raw_get_name_common(sock_xinfo, sock, "protocol");
1324}
1325
0188afb3
MY
1326static char *raw_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
1327 struct sock *sock __attribute__((__unused__)))
1328{
e0dc84da 1329 return xstrdup("raw");
0188afb3
MY
1330}
1331
1332static bool raw_fill_column(struct proc *proc __attribute__((__unused__)),
1333 struct sock_xinfo *sock_xinfo,
1334 struct sock *sock __attribute__((__unused__)),
1335 struct libscols_line *ln __attribute__((__unused__)),
1336 int column_id,
1337 size_t column_index __attribute__((__unused__)),
1338 char **str)
1339{
1340 if (l3_fill_column_handler(INET, sock_xinfo, column_id, str))
1341 return true;
1342
1343 if (column_id == COL_RAW_PROTOCOL) {
b4e39841 1344 xasprintf(str, "%"PRIu16,
73df46fc 1345 ((struct raw_xinfo *)sock_xinfo)->protocol);
0188afb3
MY
1346 return true;
1347 }
1348
1349 return false;
1350}
1351
1352static struct sock_xinfo *raw_xinfo_scan_line(const struct sock_xinfo_class *class,
1353 char * line,
1354 ino_t netns_inode,
1355 enum sysfs_byteorder byteorder)
1356{
1357 unsigned long local_addr;
1358 unsigned long protocol;
1359 unsigned long remote_addr;
1360 unsigned long st;
1361 unsigned long long inode;
1362 struct raw_xinfo *raw;
1363 struct inet_xinfo *inet;
1364 struct sock_xinfo *sock;
1365
1366 if (sscanf(line, "%*d: %lx:%lx %lx:%*x %lx %*x:%*x %*x:%*x %*x %*u %*u %lld",
1367 &local_addr, &protocol, &remote_addr,
1368 &st, &inode) != 5)
1369 return NULL;
1370
1371 if (inode == 0)
1372 return NULL;
1373
8ff22ccb 1374 raw = xcalloc(1, sizeof(*raw));
0188afb3
MY
1375 inet = &raw->l4.inet;
1376 sock = &inet->sock;
1377 sock->class = class;
1378 sock->inode = (ino_t)inode;
1379 sock->netns_inode = netns_inode;
1380 inet->local_addr.s_addr = kernel32_to_cpu(byteorder, local_addr);
1381 inet->remote_addr.s_addr = kernel32_to_cpu(byteorder, remote_addr);
1382 raw->protocol = protocol;
1383 raw->l4.st = st;
1384
1385 return sock;
1386}
1387
1388static const struct l4_xinfo_class raw_xinfo_class = {
1389 .sock = {
1390 .get_name = raw_get_name,
1391 .get_type = raw_get_type,
1392 .get_state = tcp_get_state,
1393 .get_listening = NULL,
1394 .fill_column = raw_fill_column,
1395 .free = NULL,
1396 },
1397 .scan_line = raw_xinfo_scan_line,
1398 .get_addr = tcp_xinfo_get_addr,
1399 .is_any_addr = tcp_xinfo_is_any_addr,
1400 .family = AF_INET,
1656da13 1401 .l3_decorator = {"", ""},
0188afb3
MY
1402};
1403
891b24b7 1404static void load_xinfo_from_proc_raw(ino_t netns_inode, enum sysfs_byteorder byteorder)
0188afb3
MY
1405{
1406 load_xinfo_from_proc_inet_L4(netns_inode,
1407 "/proc/net/raw",
891b24b7
MY
1408 &raw_xinfo_class,
1409 byteorder);
0188afb3 1410}
1656da13 1411
a7cba6f3
MY
1412/*
1413 * PING
1414 */
1415static char *ping_get_name(struct sock_xinfo *sock_xinfo,
1416 struct sock *sock __attribute__((__unused__)))
1417{
1418 return raw_get_name_common(sock_xinfo, sock, "id");
1419}
1420
1421static char *ping_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
1422 struct sock *sock __attribute__((__unused__)))
1423{
e0dc84da 1424 return xstrdup("dgram");
a7cba6f3
MY
1425}
1426
1427static bool ping_fill_column(struct proc *proc __attribute__((__unused__)),
1428 struct sock_xinfo *sock_xinfo,
1429 struct sock *sock __attribute__((__unused__)),
1430 struct libscols_line *ln __attribute__((__unused__)),
1431 int column_id,
1432 size_t column_index __attribute__((__unused__)),
1433 char **str)
1434{
1435 if (l3_fill_column_handler(INET, sock_xinfo, column_id, str))
1436 return true;
1437
1438 if (column_id == COL_PING_ID) {
1439 xasprintf(str, "%"PRIu16,
1440 ((struct raw_xinfo *)sock_xinfo)->protocol);
1441 return true;
1442 }
1443
1444 return false;
1445}
1446
1447static const struct l4_xinfo_class ping_xinfo_class = {
1448 .sock = {
1449 .get_name = ping_get_name,
1450 .get_type = ping_get_type,
1451 .get_state = tcp_get_state,
1452 .get_listening = NULL,
1453 .fill_column = ping_fill_column,
1454 .free = NULL,
1455 },
1456 .scan_line = raw_xinfo_scan_line,
1457 .get_addr = tcp_xinfo_get_addr,
1458 .is_any_addr = tcp_xinfo_is_any_addr,
1459 .family = AF_INET,
1460 .l3_decorator = {"", ""},
1461};
1462
891b24b7 1463static void load_xinfo_from_proc_icmp(ino_t netns_inode, enum sysfs_byteorder byteorder)
a7cba6f3
MY
1464{
1465 load_xinfo_from_proc_inet_L4(netns_inode,
1466 "/proc/net/icmp",
891b24b7
MY
1467 &ping_xinfo_class,
1468 byteorder);
a7cba6f3
MY
1469}
1470
1656da13
MY
1471/*
1472 * TCP6
1473 */
1474static struct sock_xinfo *tcp6_xinfo_scan_line(const struct sock_xinfo_class *class,
1475 char * line,
1476 ino_t netns_inode,
1477 enum sysfs_byteorder byteorder)
1478{
1479 uint32_t local_addr[4];
1480 unsigned int local_port;
1481 uint32_t remote_addr[4];
1482 unsigned int remote_port;
1483 unsigned int st;
1484 unsigned long inode;
1485 struct tcp_xinfo *tcp;
1486 struct inet6_xinfo *inet6;
1487 struct sock_xinfo *sock;
1488
1489 if (sscanf(line,
1490 "%*d: "
1491 "%08x%08x%08x%08x:%04x "
1492 "%08x%08x%08x%08x:%04x "
1493 "%x %*x:%*x %*x:%*x %*x %*u %*d %lu ",
1494 local_addr+0, local_addr+1, local_addr+2, local_addr+3, &local_port,
1495 remote_addr+0, remote_addr+1, remote_addr+2, remote_addr+3, &remote_port,
1496 &st, &inode) != 12)
1497 return NULL;
1498
1499 if (inode == 0)
1500 return NULL;
1501
8ff22ccb 1502 tcp = xmalloc(sizeof(*tcp));
1656da13
MY
1503 inet6 = &tcp->l4.inet6;
1504 sock = &inet6->sock;
1505 sock->class = class;
1506 sock->inode = (ino_t)inode;
1507 sock->netns_inode = netns_inode;
1508 tcp->local_port = local_port;
1509 for (int i = 0; i < 4; i++) {
1510 inet6->local_addr.s6_addr32[i] = kernel32_to_cpu(byteorder, local_addr[i]);
1511 inet6->remote_addr.s6_addr32[i] = kernel32_to_cpu(byteorder, remote_addr[i]);
1512 }
1513 tcp->remote_port = remote_port;
1514 tcp->l4.st = st;
1515
1516 return sock;
1517}
1518
1519static bool tcp6_fill_column(struct proc *proc __attribute__((__unused__)),
1520 struct sock_xinfo *sock_xinfo,
1521 struct sock *sock __attribute__((__unused__)),
1522 struct libscols_line *ln __attribute__((__unused__)),
1523 int column_id,
1524 size_t column_index __attribute__((__unused__)),
1525 char **str)
1526{
1527 return l3_fill_column_handler(INET6, sock_xinfo, column_id, str)
1528 || l4_fill_column_handler(TCP, sock_xinfo, column_id, str);
1529}
1530
1531static void *tcp6_xinfo_get_addr(struct l4_xinfo * l4, enum l4_side side)
1532{
1533 return (side == L4_LOCAL)
1534 ? &l4->inet6.local_addr
1535 : &l4->inet6.remote_addr;
1536}
1537
1538static bool tcp6_xinfo_is_any_addr(void *addr)
1539{
1540 return IN6_ARE_ADDR_EQUAL(addr, &(struct in6_addr)IN6ADDR_ANY_INIT);
1541}
1542
1543static const struct l4_xinfo_class tcp6_xinfo_class = {
1544 .sock = {
1545 .get_name = tcp_get_name,
1546 .get_type = tcp_get_type,
1547 .get_state = tcp_get_state,
1548 .get_listening = tcp_get_listening,
1549 .fill_column = tcp6_fill_column,
1550 .free = NULL,
1551 },
1552 .scan_line = tcp6_xinfo_scan_line,
1553 .get_addr = tcp6_xinfo_get_addr,
1554 .is_any_addr = tcp6_xinfo_is_any_addr,
1555 .family = AF_INET6,
1556 .l3_decorator = {"[", "]"},
1557};
1558
891b24b7 1559static void load_xinfo_from_proc_tcp6(ino_t netns_inode, enum sysfs_byteorder byteorder)
1656da13
MY
1560{
1561 load_xinfo_from_proc_inet_L4(netns_inode,
1562 "/proc/net/tcp6",
891b24b7
MY
1563 &tcp6_xinfo_class,
1564 byteorder);
1656da13 1565}
28cf2b21
MY
1566
1567/*
1568 * UDP6
1569 */
1570static bool udp6_fill_column(struct proc *proc __attribute__((__unused__)),
1571 struct sock_xinfo *sock_xinfo,
1572 struct sock *sock __attribute__((__unused__)),
1573 struct libscols_line *ln __attribute__((__unused__)),
1574 int column_id,
1575 size_t column_index __attribute__((__unused__)),
1576 char **str)
1577{
1578 return l3_fill_column_handler(INET6, sock_xinfo, column_id, str)
1579 || l4_fill_column_handler(UDP, sock_xinfo, column_id, str);
1580}
1581
1582static const struct l4_xinfo_class udp6_xinfo_class = {
1583 .sock = {
1584 .get_name = udp_get_name,
1585 .get_type = udp_get_type,
1586 .get_state = tcp_get_state,
1587 .get_listening = NULL,
1588 .fill_column = udp6_fill_column,
1589 .free = NULL,
1590 },
1591 .scan_line = tcp6_xinfo_scan_line,
1592 .get_addr = tcp6_xinfo_get_addr,
1593 .is_any_addr = tcp6_xinfo_is_any_addr,
1594 .family = AF_INET6,
1595 .l3_decorator = {"[", "]"},
1596};
1597
891b24b7 1598static void load_xinfo_from_proc_udp6(ino_t netns_inode, enum sysfs_byteorder byteorder)
28cf2b21
MY
1599{
1600 load_xinfo_from_proc_inet_L4(netns_inode,
1601 "/proc/net/udp6",
891b24b7
MY
1602 &udp6_xinfo_class,
1603 byteorder);
28cf2b21 1604}
2dd373c3 1605
93bca151
MY
1606/*
1607 * UDPLITEv6
1608 */
1609static bool udplite6_fill_column(struct proc *proc __attribute__((__unused__)),
1610 struct sock_xinfo *sock_xinfo,
1611 struct sock *sock __attribute__((__unused__)),
1612 struct libscols_line *ln __attribute__((__unused__)),
1613 int column_id,
1614 size_t column_index __attribute__((__unused__)),
1615 char **str)
1616{
1617 return l3_fill_column_handler(INET6, sock_xinfo, column_id, str)
1618 || l4_fill_column_handler(UDPLITE, sock_xinfo, column_id, str);
1619}
1620
1621static const struct l4_xinfo_class udplite6_xinfo_class = {
1622 .sock = {
1623 .get_name = udp_get_name,
1624 .get_type = udp_get_type,
1625 .get_state = tcp_get_state,
1626 .get_listening = NULL,
1627 .fill_column = udplite6_fill_column,
1628 .free = NULL,
1629 },
1630 .scan_line = tcp6_xinfo_scan_line,
1631 .get_addr = tcp6_xinfo_get_addr,
1632 .is_any_addr = tcp6_xinfo_is_any_addr,
1633 .family = AF_INET6,
1634 .l3_decorator = {"[", "]"},
1635};
1636
891b24b7 1637static void load_xinfo_from_proc_udplite6(ino_t netns_inode, enum sysfs_byteorder byteorder)
93bca151
MY
1638{
1639 load_xinfo_from_proc_inet_L4(netns_inode,
1640 "/proc/net/udplite6",
891b24b7
MY
1641 &udplite6_xinfo_class,
1642 byteorder);
93bca151
MY
1643}
1644
2dd373c3
MY
1645/*
1646 * RAW6
1647 */
1648static struct sock_xinfo *raw6_xinfo_scan_line(const struct sock_xinfo_class *class,
1649 char * line,
1650 ino_t netns_inode,
1651 enum sysfs_byteorder byteorder)
1652{
1653 uint32_t local_addr[4];
1654 unsigned int protocol;
1655 uint32_t remote_addr[4];
1656 unsigned int st;
1657 unsigned long inode;
1658 struct raw_xinfo *raw;
1659 struct inet6_xinfo *inet6;
1660 struct sock_xinfo *sock;
1661
1662 if (sscanf(line,
1663 "%*d: "
1664 "%08x%08x%08x%08x:%04x "
1665 "%08x%08x%08x%08x:0000 "
1666 "%x %*x:%*x %*x:%*x %*x %*u %*d %lu ",
1667 local_addr+0, local_addr+1, local_addr+2, local_addr+3, &protocol,
1668 remote_addr+0, remote_addr+1, remote_addr+2, remote_addr+3,
1669 &st, &inode) != 11)
1670 return NULL;
1671
1672 if (inode == 0)
1673 return NULL;
1674
1675 raw = xmalloc(sizeof(*raw));
1676 inet6 = &raw->l4.inet6;
1677 sock = &inet6->sock;
1678 sock->class = class;
1679 sock->inode = (ino_t)inode;
1680 sock->netns_inode = netns_inode;
1681 for (int i = 0; i < 4; i++) {
1682 inet6->local_addr.s6_addr32[i] = kernel32_to_cpu(byteorder, local_addr[i]);
1683 inet6->remote_addr.s6_addr32[i] = kernel32_to_cpu(byteorder, remote_addr[i]);
1684 }
1685 raw->protocol = protocol;
1686 raw->l4.st = st;
1687
1688 return sock;
1689}
1690
1691static bool raw6_fill_column(struct proc *proc __attribute__((__unused__)),
1692 struct sock_xinfo *sock_xinfo,
1693 struct sock *sock __attribute__((__unused__)),
1694 struct libscols_line *ln __attribute__((__unused__)),
1695 int column_id,
1696 size_t column_index __attribute__((__unused__)),
1697 char **str)
1698{
1699 struct raw_xinfo *raw;
1700
1701 if (l3_fill_column_handler(INET6, sock_xinfo, column_id, str))
1702 return true;
1703
1704 raw = (struct raw_xinfo *)sock_xinfo;
1705 if (column_id == COL_RAW_PROTOCOL) {
1706 xasprintf(str, "%"PRIu16, raw->protocol);
1707 return true;
1708 }
1709
1710 return false;
1711}
1712
1713static const struct l4_xinfo_class raw6_xinfo_class = {
1714 .sock = {
1715 .get_name = raw_get_name,
1716 .get_type = raw_get_type,
1717 .get_state = tcp_get_state,
1718 .get_listening = NULL,
1719 .fill_column = raw6_fill_column,
1720 .free = NULL,
1721 },
1722 .scan_line = raw6_xinfo_scan_line,
1723 .get_addr = tcp6_xinfo_get_addr,
1724 .is_any_addr = tcp6_xinfo_is_any_addr,
1725 .family = AF_INET6,
1726 .l3_decorator = {"[", "]"},
1727};
1728
891b24b7 1729static void load_xinfo_from_proc_raw6(ino_t netns_inode, enum sysfs_byteorder byteorder)
2dd373c3
MY
1730{
1731 load_xinfo_from_proc_inet_L4(netns_inode,
1732 "/proc/net/raw6",
891b24b7
MY
1733 &raw6_xinfo_class,
1734 byteorder);
2dd373c3 1735}
0b1dfd03
MY
1736
1737/*
1738 * PINGv6
1739 */
1740static bool ping6_fill_column(struct proc *proc __attribute__((__unused__)),
1741 struct sock_xinfo *sock_xinfo,
1742 struct sock *sock __attribute__((__unused__)),
1743 struct libscols_line *ln __attribute__((__unused__)),
1744 int column_id,
1745 size_t column_index __attribute__((__unused__)),
1746 char **str)
1747{
1748 if (l3_fill_column_handler(INET6, sock_xinfo, column_id, str))
1749 return true;
1750
1751 if (column_id == COL_PING_ID) {
1752 xasprintf(str, "%"PRIu16,
1753 ((struct raw_xinfo *)sock_xinfo)->protocol);
1754 return true;
1755 }
1756
1757 return false;
1758}
1759
1760static const struct l4_xinfo_class ping6_xinfo_class = {
1761 .sock = {
1762 .get_name = ping_get_name,
1763 .get_type = ping_get_type,
1764 .get_state = tcp_get_state,
1765 .get_listening = NULL,
1766 .fill_column = ping6_fill_column,
1767 .free = NULL,
1768 },
1769 .scan_line = raw6_xinfo_scan_line,
1770 .get_addr = tcp6_xinfo_get_addr,
1771 .is_any_addr = tcp6_xinfo_is_any_addr,
1772 .family = AF_INET6,
1773 .l3_decorator = {"[", "]"},
1774};
1775
891b24b7 1776static void load_xinfo_from_proc_icmp6(ino_t netns_inode, enum sysfs_byteorder byteorder)
0b1dfd03
MY
1777{
1778 load_xinfo_from_proc_inet_L4(netns_inode,
1779 "/proc/net/icmp6",
891b24b7
MY
1780 &ping6_xinfo_class,
1781 byteorder);
0b1dfd03 1782}
b53cc896
MY
1783
1784/*
1785 * NETLINK
1786 */
1787struct netlink_xinfo {
1788 struct sock_xinfo sock;
1789 uint16_t protocol;
1790 uint32_t lportid; /* netlink_diag may provide rportid. */
1791 uint32_t groups;
1792};
1793
1794static const char *netlink_decode_protocol(uint16_t protocol)
1795{
1796 switch (protocol) {
1797 case NETLINK_ROUTE:
1798 return "route";
1799 case NETLINK_UNUSED:
1800 return "unused";
1801 case NETLINK_USERSOCK:
1802 return "usersock";
1803 case NETLINK_FIREWALL:
1804 return "firewall";
1805 case NETLINK_SOCK_DIAG:
1806 return "sock_diag";
1807 case NETLINK_NFLOG:
1808 return "nflog";
1809 case NETLINK_XFRM:
1810 return "xfrm";
1811 case NETLINK_SELINUX:
1812 return "selinux";
1813 case NETLINK_ISCSI:
1814 return "iscsi";
1815 case NETLINK_AUDIT:
1816 return "audit";
1817 case NETLINK_FIB_LOOKUP:
1818 return "fib_lookup";
1819 case NETLINK_CONNECTOR:
1820 return "connector";
1821 case NETLINK_NETFILTER:
1822 return "netfilter";
1823 case NETLINK_IP6_FW:
1824 return "ip6_fw";
1825 case NETLINK_DNRTMSG:
1826 return "dnrtmsg";
1827 case NETLINK_KOBJECT_UEVENT:
1828 return "kobject_uevent";
1829 case NETLINK_GENERIC:
1830 return "generic";
1831 case NETLINK_SCSITRANSPORT:
1832 return "scsitransport";
1833 case NETLINK_ECRYPTFS:
1834 return "ecryptfs";
1835 case NETLINK_RDMA:
1836 return "rdma";
1837 case NETLINK_CRYPTO:
1838 return "crypto";
1839#ifdef NETLINK_SMC
1840 case NETLINK_SMC:
1841 return "smc";
1842#endif
1843 default:
1844 return "unknown";
1845 }
1846}
1847
1848static char *netlink_get_name(struct sock_xinfo *sock_xinfo,
1849 struct sock *sock __attribute__((__unused__)))
1850{
1851 struct netlink_xinfo *nl = (struct netlink_xinfo *)sock_xinfo;
1852 char *str = NULL;
1853 const char *protocol = netlink_decode_protocol(nl->protocol);
1854
1855 if (nl->groups)
1856 xasprintf(&str, "protocol=%s lport=%"PRIu16 " groups=%"PRIu32,
1857 protocol,
1858 nl->lportid, nl->groups);
1859 else
1860 xasprintf(&str, "protocol=%s lport=%"PRIu16,
1861 protocol,
1862 nl->lportid);
1863 return str;
1864}
1865
1866static char *netlink_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
1867 struct sock *sock __attribute__((__unused__)))
1868{
e0dc84da 1869 return xstrdup("raw");
b53cc896
MY
1870}
1871
1872static bool netlink_fill_column(struct proc *proc __attribute__((__unused__)),
1873 struct sock_xinfo *sock_xinfo,
1874 struct sock *sock __attribute__((__unused__)),
1875 struct libscols_line *ln __attribute__((__unused__)),
1876 int column_id,
1877 size_t column_index __attribute__((__unused__)),
1878 char **str)
1879{
1880 struct netlink_xinfo *nl = (struct netlink_xinfo *)sock_xinfo;
1881
1882 switch (column_id) {
1883 case COL_NETLINK_GROUPS:
1884 xasprintf(str, "%"PRIu32, nl->groups);
1885 return true;
1886 case COL_NETLINK_LPORT:
1887 xasprintf(str, "%"PRIu32, nl->lportid);
1888 return true;
1889 case COL_NETLINK_PROTOCOL:
e0dc84da 1890 *str = xstrdup(netlink_decode_protocol(nl->protocol));
b53cc896
MY
1891 return true;
1892 }
1893
1894 return false;
1895}
1896
1897static const struct sock_xinfo_class netlink_xinfo_class = {
1898 .get_name = netlink_get_name,
1899 .get_type = netlink_get_type,
1900 .get_state = NULL,
1901 .get_listening = NULL,
1902 .fill_column = netlink_fill_column,
1903 .free = NULL,
1904};
1905
1906static void load_xinfo_from_proc_netlink(ino_t netns_inode)
1907{
1908 char line[BUFSIZ];
1909 FILE *netlink_fp;
1910
1911 netlink_fp = fopen("/proc/net/netlink", "r");
1912 if (!netlink_fp)
1913 return;
1914
1915 if (fgets(line, sizeof(line), netlink_fp) == NULL)
1916 goto out;
1917 if (!(line[0] == 's' && line[1] == 'k'))
1918 /* Unexpected line */
1919 goto out;
1920
1921 while (fgets(line, sizeof(line), netlink_fp)) {
1922 uint16_t protocol;
1923 uint32_t lportid;
1924 uint32_t groups;
1925 unsigned long inode;
1926 struct netlink_xinfo *nl;
1927
1928 if (sscanf(line, "%*x %" SCNu16 " %" SCNu32 " %" SCNx32 " %*d %*d %*d %*d %*u %lu",
1929 &protocol, &lportid, &groups, &inode) < 4)
1930 continue;
1931
1932 if (inode == 0)
1933 continue;
1934
1935 nl = xcalloc(1, sizeof(*nl));
1936 nl->sock.class = &netlink_xinfo_class;
1937 nl->sock.inode = (ino_t)inode;
1938 nl->sock.netns_inode = netns_inode;
1939
1940 nl->protocol = protocol;
1941 nl->lportid = lportid;
1942 nl->groups = groups;
1943
1944 add_sock_info(&nl->sock);
1945 }
1946
1947 out:
1948 fclose(netlink_fp);
1949}
adfc156a
MY
1950
1951/*
1952 * PACKET
1953 */
1954struct packet_xinfo {
1955 struct sock_xinfo sock;
1956 uint16_t type;
1957 uint16_t protocol;
1958 unsigned int iface;
1959};
1960
1961static const char *packet_decode_protocol(uint16_t proto)
1962{
1963 switch (proto) {
1964 case 0:
1965 return NULL;
1966 case ETH_P_802_3:
1967 return "802_3";
1968 case ETH_P_AX25:
1969 return "ax25";
1970 case ETH_P_ALL:
1971 return "all";
1972 case ETH_P_802_2:
1973 return "802_2";
1974 case ETH_P_SNAP:
1975 return "snap";
1976 case ETH_P_DDCMP:
1977 return "ddcmp";
1978 case ETH_P_WAN_PPP:
1979 return "wan_ppp";
1980 case ETH_P_PPP_MP:
1981 return "ppp_mp";
1982 case ETH_P_LOCALTALK:
1983 return "localtalk";
1984 case ETH_P_CAN:
1985 return "can";
1986 case ETH_P_CANFD:
1987 return "canfd";
1988#ifdef ETH_P_CANXL
1989 case ETH_P_CANXL:
1990 return "canxl";
1991#endif
1992 case ETH_P_PPPTALK:
1993 return "ppptalk";
1994 case ETH_P_TR_802_2:
1995 return "tr_802_2";
1996 case ETH_P_MOBITEX:
1997 return "mobitex";
1998 case ETH_P_CONTROL:
1999 return "control";
2000 case ETH_P_IRDA:
2001 return "irda";
2002 case ETH_P_ECONET:
2003 return "econet";
2004 case ETH_P_HDLC:
2005 return "hdlc";
2006 case ETH_P_ARCNET:
2007 return "arcnet";
2008 case ETH_P_DSA:
2009 return "dsa";
2010 case ETH_P_TRAILER:
2011 return "trailer";
2012 case ETH_P_PHONET:
2013 return "phonet";
2014 case ETH_P_IEEE802154:
2015 return "ieee802154";
2016 case ETH_P_CAIF:
2017 return "caif";
2018#ifdef ETH_P_XDSA
2019 case ETH_P_XDSA:
2020 return "xdsa";
2021#endif
2022#ifdef ETH_P_MAP
2023 case ETH_P_MAP:
2024 return "map";
2025#endif
2026#ifdef ETH_P_MCTP
2027 case ETH_P_MCTP:
2028 return "mctp";
2029#endif
2030 case ETH_P_LOOP:
2031 return "loop";
2032 case ETH_P_PUP:
2033 return "pup";
2034 case ETH_P_PUPAT:
2035 return "pupat";
2036#ifdef ETH_P_TSN
2037 case ETH_P_TSN:
2038 return "tsn";
2039#endif
2040#ifdef ETH_P_ERSPAN2
2041 case ETH_P_ERSPAN2:
2042 return "erspan2";
2043#endif
2044 case ETH_P_IP:
2045 return "ip";
2046 case ETH_P_X25:
2047 return "x25";
2048 case ETH_P_ARP:
2049 return "arp";
2050 case ETH_P_BPQ:
2051 return "bpq";
2052 case ETH_P_IEEEPUP:
2053 return "ieeepup";
2054 case ETH_P_IEEEPUPAT:
2055 return "ieeepupat";
2056 case ETH_P_BATMAN:
2057 return "batman";
2058 case ETH_P_DEC:
2059 return "dec";
2060 case ETH_P_DNA_DL:
2061 return "dna_dl";
2062 case ETH_P_DNA_RC:
2063 return "dna_rc";
2064 case ETH_P_DNA_RT:
2065 return "dna_rt";
2066 case ETH_P_LAT:
2067 return "lat";
2068 case ETH_P_DIAG:
2069 return "diag";
2070 case ETH_P_CUST:
2071 return "cust";
2072 case ETH_P_SCA:
2073 return "sca";
2074 case ETH_P_TEB:
2075 return "teb";
2076 case ETH_P_RARP:
2077 return "rarp";
2078 case ETH_P_ATALK:
2079 return "atalk";
2080 case ETH_P_AARP:
2081 return "aarp";
2082 case ETH_P_8021Q:
2083 return "8021q";
2084#ifdef ETH_P_ERSPAN
2085 case ETH_P_ERSPAN:
2086 return "erspan";
2087#endif
2088 case ETH_P_IPX:
2089 return "ipx";
2090 case ETH_P_IPV6:
2091 return "ipv6";
2092 case ETH_P_PAUSE:
2093 return "pause";
2094 case ETH_P_SLOW:
2095 return "slow";
2096 case ETH_P_WCCP:
2097 return "wccp";
2098 case ETH_P_MPLS_UC:
2099 return "mpls_uc";
2100 case ETH_P_MPLS_MC:
2101 return "mpls_mc";
2102 case ETH_P_ATMMPOA:
2103 return "atmmpoa";
2104#ifdef ETH_P_PPP_DISC
2105 case ETH_P_PPP_DISC:
2106 return "ppp_disc";
2107#endif
2108#ifdef ETH_P_PPP_SES
2109 case ETH_P_PPP_SES:
2110 return "ppp_ses";
2111#endif
2112 case ETH_P_LINK_CTL:
2113 return "link_ctl";
2114 case ETH_P_ATMFATE:
2115 return "atmfate";
2116 case ETH_P_PAE:
2117 return "pae";
2118#ifdef ETH_P_PROFINET
2119 case ETH_P_PROFINET:
2120 return "profinet";
2121#endif
2122#ifdef ETH_P_REALTEK
2123 case ETH_P_REALTEK:
2124 return "realtek";
2125#endif
2126 case ETH_P_AOE:
2127 return "aoe";
2128#ifdef ETH_P_ETHERCAT
2129 case ETH_P_ETHERCAT:
2130 return "ethercat";
2131#endif
2132 case ETH_P_8021AD:
2133 return "8021ad";
2134 case ETH_P_802_EX1:
2135 return "802_ex1";
2136#ifdef ETH_P_PREAUTH
2137 case ETH_P_PREAUTH:
2138 return "preauth";
2139#endif
2140 case ETH_P_TIPC:
2141 return "tipc";
2142#ifdef ETH_P_LLDP
2143 case ETH_P_LLDP:
2144 return "lldp";
2145#endif
2146#ifdef ETH_P_MRP
2147 case ETH_P_MRP:
2148 return "mrp";
2149#endif
2150#ifdef ETH_P_MACSEC
2151 case ETH_P_MACSEC:
2152 return "macsec";
2153#endif
2154 case ETH_P_8021AH:
2155 return "8021ah";
2156#ifdef ETH_P_MVRP
2157 case ETH_P_MVRP:
2158 return "mvrp";
2159#endif
2160 case ETH_P_1588:
2161 return "1588";
2162#ifdef ETH_P_NCSI
2163 case ETH_P_NCSI:
2164 return "ncsi";
2165#endif
2166#ifdef ETH_P_PRP
2167 case ETH_P_PRP:
2168 return "prp";
2169#endif
2170#ifdef ETH_P_CFM
2171 case ETH_P_CFM:
2172 return "cfm";
2173#endif
2174 case ETH_P_FCOE:
2175 return "fcoe";
2176#ifdef ETH_P_IBOE
2177 case ETH_P_IBOE:
2178 return "iboe";
2179#endif
2180 case ETH_P_TDLS:
2181 return "tdls";
2182 case ETH_P_FIP:
2183 return "fip";
2184#ifdef ETH_P_80221
2185 case ETH_P_80221:
2186 return "80221";
2187#endif
2188#ifdef ETH_P_HSR
2189 case ETH_P_HSR:
2190 return "hsr";
2191#endif
2192#ifdef ETH_P_NSH
2193 case ETH_P_NSH:
2194 return "nsh";
2195#endif
2196#ifdef ETH_P_LOOPBACK
2197 case ETH_P_LOOPBACK:
2198 return "loopback";
2199#endif
2200 case ETH_P_QINQ1:
2201 return "qinq1";
2202 case ETH_P_QINQ2:
2203 return "qinq2";
2204 case ETH_P_QINQ3:
2205 return "qinq3";
2206 case ETH_P_EDSA:
2207 return "edsa";
2208#ifdef ETH_P_DSA_8021Q
2209 case ETH_P_DSA_8021Q:
2210 return "dsa_8021q";
2211#endif
2212#ifdef ETH_P_DSA_A5PSW
2213 case ETH_P_DSA_A5PSW:
2214 return "dsa_a5psw";
2215#endif
2216#ifdef ETH_P_IFE
2217 case ETH_P_IFE:
2218 return "ife";
2219#endif
2220 case ETH_P_AF_IUCV:
2221 return "af_iucv";
2222#ifdef ETH_P_802_3_MIN
2223 case ETH_P_802_3_MIN:
2224 return "802_3_min";
2225#endif
2226 default:
2227 return "unknown";
2228 }
2229}
2230
2231static char *packet_get_name(struct sock_xinfo *sock_xinfo,
2232 struct sock *sock __attribute__((__unused__)))
2233{
2234 struct packet_xinfo *pkt = (struct packet_xinfo *)sock_xinfo;
2235 char *str = NULL;
2236 const char *type = sock_decode_type(pkt->type);
2237 const char *proto = packet_decode_protocol(pkt->protocol);
2238 const char *iface = get_iface_name(sock_xinfo->netns_inode,
2239 pkt->iface);
2240
2241 if (iface && proto)
2242 xasprintf(&str, "type=%s protocol=%s iface=%s",
2243 type, proto, iface);
2244 else if (proto)
2245 xasprintf(&str, "type=%s protocol=%s",
2246 type, proto);
2247 else if (iface)
2248 xasprintf(&str, "type=%s iface=%s",
2249 type, iface);
2250 else
2251 xasprintf(&str, "type=%s", type);
2252
2253 return str;
2254}
2255
2256static char *packet_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
2257 struct sock *sock __attribute__((__unused__)))
2258{
2259 const char *str;
2260 struct packet_xinfo *pkt = (struct packet_xinfo *)sock_xinfo;
2261
2262 str = sock_decode_type(pkt->type);
2263 return xstrdup(str);
2264}
2265
2266static bool packet_fill_column(struct proc *proc __attribute__((__unused__)),
2267 struct sock_xinfo *sock_xinfo,
2268 struct sock *sock __attribute__((__unused__)),
2269 struct libscols_line *ln __attribute__((__unused__)),
2270 int column_id,
2271 size_t column_index __attribute__((__unused__)),
2272 char **str)
2273{
2274 struct packet_xinfo *pkt = (struct packet_xinfo *)sock_xinfo;
2275
2276 switch (column_id) {
2277 case COL_PACKET_IFACE: {
2278 const char *iface;
2279 iface = get_iface_name(sock_xinfo->netns_inode,
2280 pkt->iface);
2281 if (iface) {
2282 *str = xstrdup(iface);
2283 return true;
2284 }
2285 break;
2286 }
2287 case COL_PACKET_PROTOCOL: {
2288 const char *proto;
2289 proto = packet_decode_protocol(pkt->protocol);
2290 if (proto) {
2291 *str = xstrdup(proto);
2292 return true;
2293 }
2294 break;
2295 }
2296 default:
2297 break;
2298 }
2299 return false;
2300}
2301
2302static const struct sock_xinfo_class packet_xinfo_class = {
2303 .get_name = packet_get_name,
2304 .get_type = packet_get_type,
2305 .get_state = NULL,
2306 .get_listening = NULL,
2307 .fill_column = packet_fill_column,
2308 .free = NULL,
2309};
2310
2311static void load_xinfo_from_proc_packet(ino_t netns_inode)
2312{
2313 char line[BUFSIZ];
2314 FILE *packet_fp;
2315
2316 packet_fp = fopen("/proc/net/packet", "r");
2317 if (!packet_fp)
2318 return;
2319
2320 if (fgets(line, sizeof(line), packet_fp) == NULL)
2321 goto out;
2322 if (!(line[0] == 's' && line[1] == 'k'))
2323 /* Unexpected line */
2324 goto out;
2325
2326 while (fgets(line, sizeof(line), packet_fp)) {
2327 uint16_t type;
2328 uint16_t protocol;
2329 unsigned int iface;
2330 unsigned long inode;
2331 struct packet_xinfo *pkt;
2332
2333 if (sscanf(line, "%*x %*d %" SCNu16 " %" SCNu16 " %u %*d %*d %*d %lu",
2334 &type, &protocol, &iface, &inode) < 4)
2335 continue;
2336
2337 pkt = xcalloc(1, sizeof(*pkt));
2338 pkt->sock.class = &packet_xinfo_class;
2339 pkt->sock.inode = (ino_t)inode;
2340 pkt->sock.netns_inode = netns_inode;
2341
2342 pkt->type = type;
2343 pkt->protocol = protocol;
2344 pkt->iface = iface;
2345
2346 add_sock_info(&pkt->sock);
2347 }
2348
2349 out:
2350 fclose(packet_fp);
2351}