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