]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/lsfd-sock-xinfo.c
lsblk: rename sortdata to rawdata
[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;
3f3da329
MY
541 char shutdown_chars[3] = { 0 };
542
543 if (!unix_shutdown_chars(((struct unix_xinfo *)sock->xinfo), shutdown_chars)) {
544 shutdown_chars[0] = '?';
545 shutdown_chars[1] = '?';
546 }
547 xasprintf(&str, "%d,%s,%d%c%c",
548 sock->file.proc->pid, sock->file.proc->command, sock->file.association,
549 shutdown_chars[0], shutdown_chars[1]);
550
f9771d8d
MY
551 return str;
552}
553
554static struct ipc *unix_get_peer_ipc(struct unix_xinfo *ux,
555 struct sock *sock)
556{
557 struct unix_ipc *unix_ipc;
558 struct sock dummy_peer_sock;
559
560 unix_ipc = ux->unix_ipc;
561 if (!unix_ipc)
562 return NULL;
563
564 unix_make_dumy_sock(sock, unix_ipc->ipeer, &dummy_peer_sock);
565 return get_ipc(&dummy_peer_sock.file);
566}
567
2e38e61c
MY
568static bool unix_fill_column(struct proc *proc __attribute__((__unused__)),
569 struct sock_xinfo *sock_xinfo,
f9771d8d 570 struct sock *sock,
2e38e61c
MY
571 struct libscols_line *ln __attribute__((__unused__)),
572 int column_id,
573 size_t column_index __attribute__((__unused__)),
574 char **str)
575{
576 struct unix_xinfo *ux = (struct unix_xinfo *)sock_xinfo;
f9771d8d
MY
577 struct ipc *peer_ipc;
578 struct list_head *e;
426ff07f 579 char shutdown_chars[3] = { 0 };
2e38e61c 580
854ddd0d 581 switch (column_id) {
2e38e61c
MY
582 case COL_UNIX_PATH:
583 if (*ux->path) {
e0dc84da 584 *str = xstrdup(ux->path);
2e38e61c
MY
585 return true;
586 }
587 break;
f9771d8d
MY
588 case COL_ENDPOINTS:
589 peer_ipc = unix_get_peer_ipc(ux, sock);
590 if (!peer_ipc)
591 break;
592
593 list_for_each_backwardly(e, &peer_ipc->endpoints) {
594 struct sock *peer_sock = list_entry(e, struct sock, endpoint.endpoints);
595 char *estr;
596
597 if (*str)
598 xstrputc(str, '\n');
599 estr = unix_xstrendpoint(peer_sock);
600 xstrappend(str, estr);
601 free(estr);
602 }
603 if (*str)
604 return true;
605 break;
426ff07f
MY
606 case COL_SOCK_SHUTDOWN:
607 if (unix_shutdown_chars(ux, shutdown_chars)) {
608 *str = xstrdup(shutdown_chars);
609 return true;
610 }
611 break;
2e38e61c
MY
612 }
613
614 return false;
615}
616
54a06438 617static const struct sock_xinfo_class unix_xinfo_class = {
2e38e61c
MY
618 .get_name = unix_get_name,
619 .get_type = unix_get_type,
620 .get_state = unix_get_state,
45d61bff 621 .get_listening = unix_get_listening,
2e38e61c 622 .fill_column = unix_fill_column,
f9771d8d 623 .get_ipc_class = unix_get_ipc_class,
2e38e61c
MY
624 .free = NULL,
625};
626
e8e14a28 627/* UNIX_LINE_LEN need at least 54 + 21 + UNIX_PATH_MAX + 1.
eeaf7677
MY
628 *
629 * An actual number must be used in this definition
630 * since UNIX_LINE_LEN is specified as an argument for
631 * stringify_value().
632 */
2e38e61c
MY
633#define UNIX_LINE_LEN 256
634static void load_xinfo_from_proc_unix(ino_t netns_inode)
635{
636 char line[UNIX_LINE_LEN];
637 FILE *unix_fp;
638
639 unix_fp = fopen("/proc/net/unix", "r");
640 if (!unix_fp)
641 return;
642
643 if (fgets(line, sizeof(line), unix_fp) == NULL)
644 goto out;
b3649945 645 if (!(line[0] == 'N' && line[1] == 'u' && line[2] == 'm'))
2e38e61c
MY
646 /* Unexpected line */
647 goto out;
648
649 while (fgets(line, sizeof(line), unix_fp)) {
650 uint64_t flags;
651 uint32_t type;
652 unsigned int st;
653 unsigned long inode;
2e38e61c 654 struct unix_xinfo *ux;
eeaf7677 655 char path[UNIX_LINE_LEN + 1] = { 0 };
91a484fe 656
2e38e61c 657
eeaf7677
MY
658 if (sscanf(line, "%*x: %*x %*x %" SCNx64 " %x %x %lu %"
659 stringify_value(UNIX_LINE_LEN) "[^\n]",
2e38e61c
MY
660 &flags, &type, &st, &inode, path) < 4)
661 continue;
662
663 if (inode == 0)
664 continue;
665
8ff22ccb 666 ux = xcalloc(1, sizeof(*ux));
2e38e61c
MY
667 ux->sock.class = &unix_xinfo_class;
668 ux->sock.inode = (ino_t)inode;
669 ux->sock.netns_inode = netns_inode;
670
671 ux->acceptcon = !!flags;
672 ux->type = type;
673 ux->st = st;
91a484fe 674 xstrncpy(ux->path, path, sizeof(ux->path));
2e38e61c 675
2ac8d1a3 676 add_sock_info(&ux->sock);
2e38e61c
MY
677 }
678
679 out:
680 fclose(unix_fp);
681}
7b2a9be0 682
5468bb45
MY
683/* The path name extracted from /proc/net/unix is unreliable; the line oriented interface cannot
684 * represent a file name including newlines. With unix_refill_name(), we patch the path
685 * member of unix_xinfos with information received via netlink diag interface. */
686static void unix_refill_name(struct sock_xinfo *xinfo, const char *name, size_t len)
687{
688 struct unix_xinfo *ux = (struct unix_xinfo *)xinfo;
689 size_t min_len;
690
691 if (len == 0)
692 return;
693
694 min_len = min(sizeof(ux->path) - 1, len);
695 memcpy(ux->path, name, min_len);
696 if (ux->path[0] == '\0') {
697 ux->path[0] = '@';
698 }
699 ux->path[min_len] = '\0';
700}
701
702static bool handle_diag_unix(ino_t netns __attribute__((__unused__)),
703 size_t nlmsg_len, void *nlmsg_data)
704{
705 const struct unix_diag_msg *diag = nlmsg_data;
706 size_t rta_len;
707 ino_t inode;
708 struct sock_xinfo *xinfo;
f9771d8d 709 struct unix_xinfo *unix_xinfo;
5468bb45
MY
710
711 if (diag->udiag_family != AF_UNIX)
712 return false;
713
714 if (nlmsg_len < NLMSG_LENGTH(sizeof(*diag)))
715 return false;
716
717 inode = (ino_t)diag->udiag_ino;
718 xinfo = get_sock_xinfo(inode);
719
720 if (xinfo == NULL)
721 /* The socket is found in the diag response
722 but not in the proc fs. */
723 return true;
724
725 if (xinfo->class != &unix_xinfo_class)
726 return true;
f9771d8d 727 unix_xinfo = (struct unix_xinfo *)xinfo;
5468bb45
MY
728
729 rta_len = nlmsg_len - NLMSG_LENGTH(sizeof(*diag));
730 for (struct rtattr *attr = (struct rtattr *)(diag + 1);
731 RTA_OK(attr, rta_len);
732 attr = RTA_NEXT(attr, rta_len)) {
733 size_t len = RTA_PAYLOAD(attr);
734
735 switch (attr->rta_type) {
736 case UNIX_DIAG_NAME:
737 unix_refill_name(xinfo, RTA_DATA(attr), len);
738 break;
f9771d8d 739
426ff07f
MY
740 case UNIX_DIAG_SHUTDOWN:
741 if (len < 1)
742 break;
743
744 unix_xinfo->shutdown_mask = *(uint8_t *)RTA_DATA(attr);
745 set_shutdown_mask(unix_xinfo->shutdown_mask);
746 break;
747
f9771d8d
MY
748 case UNIX_DIAG_PEER:
749 if (len < 4)
750 break;
751
752 unix_xinfo->unix_ipc = (struct unix_ipc *)new_ipc(&unix_ipc_class);
753 unix_xinfo->unix_ipc->inode = inode;
754 unix_xinfo->unix_ipc->ipeer = (ino_t)(*(uint32_t *)RTA_DATA(attr));
755 add_ipc(&unix_xinfo->unix_ipc->ipc, inode % UINT_MAX);
756 break;
5468bb45
MY
757 }
758 }
759 return true;
760}
761
762static void load_xinfo_from_diag_unix(int diagsd, ino_t netns)
763{
764 struct unix_diag_req udr = {
765 .sdiag_family = AF_UNIX,
766 .udiag_states = -1, /* set the all bits. */
426ff07f 767 .udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER | UNIX_DIAG_SHUTDOWN,
5468bb45
MY
768 };
769
770 send_diag_request(diagsd, &udr, sizeof(udr), handle_diag_unix, netns);
771}
772
7b2a9be0
MY
773/*
774 * AF_INET
775 */
776struct inet_xinfo {
777 struct sock_xinfo sock;
643f30c7
MY
778 struct in_addr local_addr;
779 struct in_addr remote_addr;
7b2a9be0
MY
780};
781
9020c2e0 782static uint32_t kernel32_to_cpu(enum sysfs_byteorder byteorder, uint32_t v)
7b2a9be0 783{
9020c2e0
MY
784 if (byteorder == SYSFS_BYTEORDER_LITTLE)
785 return le32_to_cpu(v);
786 else
787 return be32_to_cpu(v);
7b2a9be0
MY
788}
789
1656da13
MY
790/*
791 * AF_INET6
792 */
793struct inet6_xinfo {
794 struct sock_xinfo sock;
795 struct in6_addr local_addr;
796 struct in6_addr remote_addr;
797};
798
7b2a9be0 799/*
4a2b51c1 800 * L4 abstract-layer for protocols stacked on IP and IP6.
7b2a9be0 801 */
303b41fe 802enum l4_state {
7b2a9be0
MY
803 /*
804 * Taken from linux/include/net/tcp_states.h.
805 * (GPL-2.0-or-later)
303b41fe
MY
806 *
807 * UDP and RAW sockets also uses the contents in Linux.
7b2a9be0
MY
808 */
809 TCP_ESTABLISHED = 1,
810 TCP_SYN_SENT,
811 TCP_SYN_RECV,
812 TCP_FIN_WAIT1,
813 TCP_FIN_WAIT2,
814 TCP_TIME_WAIT,
815 TCP_CLOSE,
816 TCP_CLOSE_WAIT,
817 TCP_LAST_ACK,
818 TCP_LISTEN,
819 TCP_CLOSING,
820 TCP_NEW_SYN_RECV,
821
822 TCP_MAX_STATES /* Leave at the end! */
823};
824
303b41fe 825static const char *l4_decode_state(enum l4_state st)
7b2a9be0 826{
86242cb0 827 const char * const table [] = {
7b2a9be0
MY
828 [TCP_ESTABLISHED] = "established",
829 [TCP_SYN_SENT] = "syn-sent",
830 [TCP_SYN_RECV] = "syn-recv",
831 [TCP_FIN_WAIT1] = "fin-wait1",
832 [TCP_FIN_WAIT2] = "fin-wait2",
833 [TCP_TIME_WAIT] = "time-wait",
834 [TCP_CLOSE] = "close",
835 [TCP_CLOSE_WAIT] = "close-wait",
836 [TCP_LAST_ACK] = "last-ack",
837 [TCP_LISTEN] = "listen",
838 [TCP_CLOSING] = "closing",
839 [TCP_NEW_SYN_RECV] = "new-syn-recv",
840 };
841
842 if (st < TCP_MAX_STATES)
843 return table[st];
844 return "unknown";
845}
846
4a2b51c1 847struct l4_xinfo {
1656da13
MY
848 union {
849 struct inet_xinfo inet;
850 struct inet6_xinfo inet6;
851 };
303b41fe 852 enum l4_state st;
4a2b51c1
MY
853};
854
2a4f2b1b 855enum l4_side { L4_LOCAL, L4_REMOTE };
1656da13 856enum l3_decorator { L3_DECO_START, L3_DECO_END };
2a4f2b1b 857
4a2b51c1
MY
858struct l4_xinfo_class {
859 struct sock_xinfo_class sock;
19e40223
MY
860 struct sock_xinfo *(*scan_line)(const struct sock_xinfo_class *,
861 char *,
862 ino_t,
863 enum sysfs_byteorder);
2a4f2b1b
MY
864 void * (*get_addr)(struct l4_xinfo *, enum l4_side);
865 bool (*is_any_addr)(void *);
866 int family;
1656da13 867 const char *l3_decorator[2];
4a2b51c1
MY
868};
869
838fa270
MY
870#define l3_fill_column_handler(L3, SOCK_XINFO, COLUMN_ID, STR) __extension__ \
871 ({ \
872 struct l4_xinfo_class *class = (struct l4_xinfo_class *)SOCK_XINFO->class; \
873 struct l4_xinfo *l4 = (struct l4_xinfo *)SOCK_XINFO; \
874 void *n = NULL; \
875 char s[BUFSIZ]; \
876 bool r = false; \
877 \
878 switch (COLUMN_ID) { \
879 case COL_##L3##_LADDR: \
880 n = class->get_addr(l4, L4_LOCAL); \
881 break; \
882 case COL_##L3##_RADDR: \
883 n = class->get_addr(l4, L4_REMOTE); \
884 break; \
885 default: \
886 break; \
887 } \
888 \
889 if (n && inet_ntop(class->family, n, s, sizeof(s))) { \
e0dc84da 890 *STR = xstrdup(s); \
838fa270
MY
891 r = true; \
892 } \
893 r; \
894 })
895
7b2a9be0
MY
896/*
897 * TCP
898 */
899struct tcp_xinfo {
4a2b51c1 900 struct l4_xinfo l4;
7b2a9be0
MY
901 uint16_t local_port;
902 uint16_t remote_port;
7b2a9be0
MY
903};
904
7b2a9be0
MY
905static char *tcp_get_name(struct sock_xinfo *sock_xinfo,
906 struct sock *sock __attribute__((__unused__)))
907{
908 char *str = NULL;
7b2a9be0 909 struct tcp_xinfo *tcp = ((struct tcp_xinfo *)sock_xinfo);
8db07ebc 910 struct l4_xinfo *l4 = &tcp->l4;
303b41fe 911 const char *st_str = l4_decode_state(l4->st);
838fa270
MY
912 struct l4_xinfo_class *class = (struct l4_xinfo_class *)sock_xinfo->class;
913 void *laddr = class->get_addr(l4, L4_LOCAL);
914 void *raddr = class->get_addr(l4, L4_REMOTE);
915 char local_s[BUFSIZ];
916 char remote_s[BUFSIZ];
1656da13
MY
917 const char *start = class->l3_decorator[L3_DECO_START];
918 const char *end = class->l3_decorator[L3_DECO_END];
7b2a9be0 919
838fa270 920 if (!inet_ntop(class->family, laddr, local_s, sizeof(local_s)))
3b182ee7
MY
921 xasprintf(&str, "state=%s", st_str);
922 else if (l4->st == TCP_LISTEN
838fa270 923 || !inet_ntop(class->family, raddr, remote_s, sizeof(remote_s)))
b4e39841 924 xasprintf(&str, "state=%s laddr=%s%s%s:%"PRIu16,
3b182ee7 925 st_str,
1656da13 926 start, local_s, end, tcp->local_port);
7b2a9be0 927 else
b4e39841 928 xasprintf(&str, "state=%s laddr=%s%s%s:%"PRIu16" raddr=%s%s%s:%"PRIu16,
3b182ee7 929 st_str,
1656da13
MY
930 start, local_s, end, tcp->local_port,
931 start, remote_s, end, tcp->remote_port);
7b2a9be0
MY
932 return str;
933}
934
935static char *tcp_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
936 struct sock *sock __attribute__((__unused__)))
937{
e0dc84da 938 return xstrdup("stream");
7b2a9be0
MY
939}
940
941static char *tcp_get_state(struct sock_xinfo *sock_xinfo,
942 struct sock *sock __attribute__((__unused__)))
943{
e0dc84da 944 return xstrdup(l4_decode_state(((struct l4_xinfo *)sock_xinfo)->st));
7b2a9be0
MY
945}
946
947static bool tcp_get_listening(struct sock_xinfo *sock_xinfo,
948 struct sock *sock __attribute__((__unused__)))
949{
8db07ebc 950 return ((struct l4_xinfo *)sock_xinfo)->st == TCP_LISTEN;
7b2a9be0
MY
951}
952
838fa270
MY
953#define l4_fill_column_handler(L4, SOCK_XINFO, COLUMN_ID, STR) __extension__ \
954 ({ \
955 struct l4_xinfo_class *class = (struct l4_xinfo_class *)SOCK_XINFO->class; \
956 struct tcp_xinfo *tcp = (struct tcp_xinfo *)SOCK_XINFO; \
957 struct l4_xinfo *l4 = &tcp->l4; \
958 void *n = NULL; \
92a0dbce 959 bool has_laddr = false; \
73df46fc 960 unsigned short p; \
92a0dbce 961 bool has_lport = false; \
838fa270
MY
962 char s[BUFSIZ]; \
963 bool r = true; \
92a0dbce 964 \
838fa270 965 switch (COLUMN_ID) { \
cda2b2a0 966 case COL_##L4##_LADDR: \
838fa270 967 n = class->get_addr(l4, L4_LOCAL); \
92a0dbce 968 has_laddr = true; \
73df46fc 969 p = tcp->local_port; \
92a0dbce 970 /* FALL THROUGH */ \
cda2b2a0 971 case COL_##L4##_RADDR: \
92a0dbce 972 if (!has_laddr) { \
838fa270 973 n = class->get_addr(l4, L4_REMOTE); \
73df46fc 974 p = tcp->remote_port; \
92a0dbce 975 } \
838fa270 976 if (n && inet_ntop(class->family, n, s, sizeof(s))) \
b4e39841 977 xasprintf(STR, "%s%s%s:%"PRIu16, \
1656da13
MY
978 class->l3_decorator[L3_DECO_START], \
979 s, \
980 class->l3_decorator[L3_DECO_END], \
981 p); \
92a0dbce 982 break; \
cda2b2a0 983 case COL_##L4##_LPORT: \
73df46fc 984 p = tcp->local_port; \
92a0dbce
MY
985 has_lport = true; \
986 /* FALL THROUGH */ \
cda2b2a0 987 case COL_##L4##_RPORT: \
92a0dbce 988 if (!has_lport) \
73df46fc 989 p = tcp->remote_port; \
b4e39841 990 xasprintf(STR, "%"PRIu16, p); \
92a0dbce
MY
991 break; \
992 default: \
838fa270
MY
993 r = false; \
994 break; \
92a0dbce 995 } \
838fa270
MY
996 r; \
997 })
7b2a9be0 998
19e40223
MY
999static struct sock_xinfo *tcp_xinfo_scan_line(const struct sock_xinfo_class *class,
1000 char * line,
1001 ino_t netns_inode,
1002 enum sysfs_byteorder byteorder)
1003{
1004 unsigned long local_addr;
1005 unsigned long local_port;
1006 unsigned long remote_addr;
1007 unsigned long remote_port;
1008 unsigned long st;
1009 unsigned long long inode;
1010 struct tcp_xinfo *tcp;
1011 struct inet_xinfo *inet;
1012 struct sock_xinfo *sock;
1013
1014 if (sscanf(line, "%*d: %lx:%lx %lx:%lx %lx %*x:%*x %*x:%*x %*x %*u %*u %lld",
1015 &local_addr, &local_port, &remote_addr, &remote_port,
1016 &st, &inode) != 6)
1017 return NULL;
1018
1019 if (inode == 0)
1020 return NULL;
1021
8ff22ccb 1022 tcp = xcalloc(1, sizeof(*tcp));
19e40223
MY
1023 inet = &tcp->l4.inet;
1024 sock = &inet->sock;
1025 sock->class = class;
1026 sock->inode = (ino_t)inode;
1027 sock->netns_inode = netns_inode;
1028 inet->local_addr.s_addr = kernel32_to_cpu(byteorder, local_addr);
1029 tcp->local_port = local_port;
1030 inet->remote_addr.s_addr = kernel32_to_cpu(byteorder, remote_addr);
1031 tcp->remote_port = remote_port;
8db07ebc 1032 tcp->l4.st = st;
19e40223
MY
1033
1034 return sock;
1035}
1036
2a4f2b1b
MY
1037static void *tcp_xinfo_get_addr(struct l4_xinfo *l4, enum l4_side side)
1038{
1039 return (side == L4_LOCAL)
1040 ? &l4->inet.local_addr
1041 : &l4->inet.remote_addr;
1042}
1043
1044static bool tcp_xinfo_is_any_addr(void *addr)
1045{
1046 return ((struct in_addr *)addr)->s_addr == INADDR_ANY;
1047}
1048
838fa270
MY
1049static bool tcp_fill_column(struct proc *proc __attribute__((__unused__)),
1050 struct sock_xinfo *sock_xinfo,
1051 struct sock *sock __attribute__((__unused__)),
1052 struct libscols_line *ln __attribute__((__unused__)),
1053 int column_id,
1054 size_t column_index __attribute__((__unused__)),
1055 char **str)
1056{
1057 return l3_fill_column_handler(INET, sock_xinfo, column_id, str)
1058 || l4_fill_column_handler(TCP, sock_xinfo, column_id, str);
1059}
1060
4a2b51c1
MY
1061static const struct l4_xinfo_class tcp_xinfo_class = {
1062 .sock = {
1063 .get_name = tcp_get_name,
1064 .get_type = tcp_get_type,
1065 .get_state = tcp_get_state,
1066 .get_listening = tcp_get_listening,
1067 .fill_column = tcp_fill_column,
1068 .free = NULL,
1069 },
19e40223 1070 .scan_line = tcp_xinfo_scan_line,
2a4f2b1b
MY
1071 .get_addr = tcp_xinfo_get_addr,
1072 .is_any_addr = tcp_xinfo_is_any_addr,
1073 .family = AF_INET,
1656da13 1074 .l3_decorator = {"", ""},
7b2a9be0
MY
1075};
1076
cda2b2a0 1077static bool L4_verify_initial_line(const char *line)
58d2f31e
MY
1078{
1079 /* At least we expect two white spaces. */
cb097fb7 1080 if (strncmp(line, " ", 2) != 0)
58d2f31e
MY
1081 return false;
1082 line += 2;
1083
1084 /* Skip white spaces. */
4658bfb1 1085 line = skip_space(line);
58d2f31e 1086
621cf7e9 1087 return strncmp(line, "sl", 2) == 0;
db79a100
TW
1088}
1089
7b2a9be0 1090#define TCP_LINE_LEN 256
cda2b2a0 1091static void load_xinfo_from_proc_inet_L4(ino_t netns_inode, const char *proc_file,
891b24b7
MY
1092 const struct l4_xinfo_class *class,
1093 enum sysfs_byteorder byteorder)
7b2a9be0
MY
1094{
1095 char line[TCP_LINE_LEN];
1096 FILE *tcp_fp;
1097
92a0dbce 1098 tcp_fp = fopen(proc_file, "r");
7b2a9be0
MY
1099 if (!tcp_fp)
1100 return;
1101
1102 if (fgets(line, sizeof(line), tcp_fp) == NULL)
1103 goto out;
cda2b2a0 1104 if (!L4_verify_initial_line(line))
7b2a9be0
MY
1105 /* Unexpected line */
1106 goto out;
1107
1108 while (fgets(line, sizeof(line), tcp_fp)) {
19e40223
MY
1109 struct sock_xinfo *sock = class->scan_line(&class->sock, line, netns_inode, byteorder);
1110 if (sock)
1111 add_sock_info(sock);
7b2a9be0
MY
1112 }
1113
1114 out:
1115 fclose(tcp_fp);
1116}
92a0dbce 1117
891b24b7 1118static void load_xinfo_from_proc_tcp(ino_t netns_inode, enum sysfs_byteorder byteorder)
92a0dbce 1119{
cda2b2a0 1120 load_xinfo_from_proc_inet_L4(netns_inode,
58d2f31e 1121 "/proc/net/tcp",
891b24b7
MY
1122 &tcp_xinfo_class,
1123 byteorder);
92a0dbce
MY
1124}
1125
1126/*
1127 * UDP
1128 */
1129static char *udp_get_name(struct sock_xinfo *sock_xinfo,
1130 struct sock *sock __attribute__((__unused__)))
1131{
1132 char *str = NULL;
92a0dbce 1133 struct tcp_xinfo *tcp = ((struct tcp_xinfo *)sock_xinfo);
8db07ebc 1134 struct l4_xinfo *l4 = &tcp->l4;
8db07ebc 1135 unsigned int st = l4->st;
303b41fe 1136 const char *st_str = l4_decode_state(st);
838fa270
MY
1137 struct l4_xinfo_class *class = (struct l4_xinfo_class *)sock_xinfo->class;
1138 void *laddr = class->get_addr(l4, L4_LOCAL);
1139 void *raddr = class->get_addr(l4, L4_REMOTE);
1140 char local_s[BUFSIZ];
1141 char remote_s[BUFSIZ];
28cf2b21
MY
1142 const char *start = class->l3_decorator[L3_DECO_START];
1143 const char *end = class->l3_decorator[L3_DECO_END];
92a0dbce 1144
838fa270 1145 if (!inet_ntop(class->family, laddr, local_s, sizeof(local_s)))
3b182ee7 1146 xasprintf(&str, "state=%s", st_str);
838fa270
MY
1147 else if ((class->is_any_addr(raddr) && tcp->remote_port == 0)
1148 || !inet_ntop(class->family, raddr, remote_s, sizeof(remote_s)))
28cf2b21 1149 xasprintf(&str, "state=%s laddr=%s%s%s:%"PRIu16,
3b182ee7 1150 st_str,
28cf2b21 1151 start, local_s, end, tcp->local_port);
92a0dbce 1152 else
28cf2b21 1153 xasprintf(&str, "state=%s laddr=%s%s%s:%"PRIu16" raddr=%s%s%s:%"PRIu16,
3b182ee7 1154 st_str,
28cf2b21
MY
1155 start, local_s, end, tcp->local_port,
1156 start, remote_s, end, tcp->remote_port);
92a0dbce
MY
1157 return str;
1158}
1159
1160static char *udp_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
1161 struct sock *sock __attribute__((__unused__)))
1162{
e0dc84da 1163 return xstrdup("dgram");
92a0dbce
MY
1164}
1165
838fa270
MY
1166static bool udp_fill_column(struct proc *proc __attribute__((__unused__)),
1167 struct sock_xinfo *sock_xinfo,
1168 struct sock *sock __attribute__((__unused__)),
1169 struct libscols_line *ln __attribute__((__unused__)),
1170 int column_id,
1171 size_t column_index __attribute__((__unused__)),
1172 char **str)
1173{
1174 return l3_fill_column_handler(INET, sock_xinfo, column_id, str)
1175 || l4_fill_column_handler(UDP, sock_xinfo, column_id, str);
1176}
1177
4a2b51c1
MY
1178static const struct l4_xinfo_class udp_xinfo_class = {
1179 .sock = {
1180 .get_name = udp_get_name,
1181 .get_type = udp_get_type,
1182 .get_state = tcp_get_state,
1183 .get_listening = NULL,
1184 .fill_column = udp_fill_column,
1185 .free = NULL,
1186 },
19e40223 1187 .scan_line = tcp_xinfo_scan_line,
2a4f2b1b
MY
1188 .get_addr = tcp_xinfo_get_addr,
1189 .is_any_addr = tcp_xinfo_is_any_addr,
1190 .family = AF_INET,
1656da13 1191 .l3_decorator = {"", ""},
92a0dbce
MY
1192};
1193
891b24b7 1194static void load_xinfo_from_proc_udp(ino_t netns_inode, enum sysfs_byteorder byteorder)
92a0dbce 1195{
cda2b2a0 1196 load_xinfo_from_proc_inet_L4(netns_inode,
92a0dbce 1197 "/proc/net/udp",
891b24b7
MY
1198 &udp_xinfo_class,
1199 byteorder);
92a0dbce 1200}
0188afb3 1201
c779f412
MY
1202/*
1203 * UDP-Lite
1204 */
1205static bool udplite_fill_column(struct proc *proc __attribute__((__unused__)),
1206 struct sock_xinfo *sock_xinfo,
1207 struct sock *sock __attribute__((__unused__)),
1208 struct libscols_line *ln __attribute__((__unused__)),
1209 int column_id,
1210 size_t column_index __attribute__((__unused__)),
1211 char **str)
1212{
1213 return l3_fill_column_handler(INET, sock_xinfo, column_id, str)
1214 || l4_fill_column_handler(UDPLITE, sock_xinfo, column_id, str);
1215}
1216
1217static const struct l4_xinfo_class udplite_xinfo_class = {
1218 .sock = {
1219 .get_name = udp_get_name,
1220 .get_type = udp_get_type,
1221 .get_state = tcp_get_state,
1222 .get_listening = NULL,
1223 .fill_column = udplite_fill_column,
1224 .free = NULL,
1225 },
1226 .scan_line = tcp_xinfo_scan_line,
1227 .get_addr = tcp_xinfo_get_addr,
1228 .is_any_addr = tcp_xinfo_is_any_addr,
1229 .family = AF_INET,
1230 .l3_decorator = {"", ""},
1231};
1232
891b24b7 1233static void load_xinfo_from_proc_udplite(ino_t netns_inode, enum sysfs_byteorder byteorder)
c779f412
MY
1234{
1235 load_xinfo_from_proc_inet_L4(netns_inode,
1236 "/proc/net/udplite",
891b24b7
MY
1237 &udplite_xinfo_class,
1238 byteorder);
c779f412
MY
1239}
1240
0188afb3
MY
1241/*
1242 * RAW
1243 */
1244struct raw_xinfo {
1245 struct l4_xinfo l4;
1246 uint16_t protocol;
1247};
1248
a7cba6f3
MY
1249static char *raw_get_name_common(struct sock_xinfo *sock_xinfo,
1250 struct sock *sock __attribute__((__unused__)),
1251 const char *port_label)
0188afb3
MY
1252{
1253 char *str = NULL;
1254 struct l4_xinfo_class *class = (struct l4_xinfo_class *)sock_xinfo->class;
1255 struct raw_xinfo *raw = ((struct raw_xinfo *)sock_xinfo);
1256 struct l4_xinfo *l4 = &raw->l4;
303b41fe 1257 const char *st_str = l4_decode_state(l4->st);
0188afb3
MY
1258 void *laddr = class->get_addr(l4, L4_LOCAL);
1259 void *raddr = class->get_addr(l4, L4_REMOTE);
1260 char local_s[BUFSIZ];
1261 char remote_s[BUFSIZ];
1262
1263 if (!inet_ntop(class->family, laddr, local_s, sizeof(local_s)))
1264 xasprintf(&str, "state=%s", st_str);
1265 else if (class->is_any_addr(raddr)
1266 || !inet_ntop(class->family, raddr, remote_s, sizeof(remote_s)))
a7cba6f3 1267 xasprintf(&str, "state=%s %s=%"PRIu16" laddr=%s",
0188afb3 1268 st_str,
a7cba6f3 1269 port_label,
0188afb3
MY
1270 raw->protocol, local_s);
1271 else
a7cba6f3 1272 xasprintf(&str, "state=%s %s=%"PRIu16" laddr=%s raddr=%s",
0188afb3 1273 st_str,
a7cba6f3 1274 port_label,
0188afb3
MY
1275 raw->protocol, local_s, remote_s);
1276 return str;
1277}
1278
a7cba6f3
MY
1279static char *raw_get_name(struct sock_xinfo *sock_xinfo,
1280 struct sock *sock __attribute__((__unused__)))
1281{
1282 return raw_get_name_common(sock_xinfo, sock, "protocol");
1283}
1284
0188afb3
MY
1285static char *raw_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
1286 struct sock *sock __attribute__((__unused__)))
1287{
e0dc84da 1288 return xstrdup("raw");
0188afb3
MY
1289}
1290
1291static bool raw_fill_column(struct proc *proc __attribute__((__unused__)),
1292 struct sock_xinfo *sock_xinfo,
1293 struct sock *sock __attribute__((__unused__)),
1294 struct libscols_line *ln __attribute__((__unused__)),
1295 int column_id,
1296 size_t column_index __attribute__((__unused__)),
1297 char **str)
1298{
1299 if (l3_fill_column_handler(INET, sock_xinfo, column_id, str))
1300 return true;
1301
1302 if (column_id == COL_RAW_PROTOCOL) {
b4e39841 1303 xasprintf(str, "%"PRIu16,
73df46fc 1304 ((struct raw_xinfo *)sock_xinfo)->protocol);
0188afb3
MY
1305 return true;
1306 }
1307
1308 return false;
1309}
1310
1311static struct sock_xinfo *raw_xinfo_scan_line(const struct sock_xinfo_class *class,
1312 char * line,
1313 ino_t netns_inode,
1314 enum sysfs_byteorder byteorder)
1315{
1316 unsigned long local_addr;
1317 unsigned long protocol;
1318 unsigned long remote_addr;
1319 unsigned long st;
1320 unsigned long long inode;
1321 struct raw_xinfo *raw;
1322 struct inet_xinfo *inet;
1323 struct sock_xinfo *sock;
1324
1325 if (sscanf(line, "%*d: %lx:%lx %lx:%*x %lx %*x:%*x %*x:%*x %*x %*u %*u %lld",
1326 &local_addr, &protocol, &remote_addr,
1327 &st, &inode) != 5)
1328 return NULL;
1329
1330 if (inode == 0)
1331 return NULL;
1332
8ff22ccb 1333 raw = xcalloc(1, sizeof(*raw));
0188afb3
MY
1334 inet = &raw->l4.inet;
1335 sock = &inet->sock;
1336 sock->class = class;
1337 sock->inode = (ino_t)inode;
1338 sock->netns_inode = netns_inode;
1339 inet->local_addr.s_addr = kernel32_to_cpu(byteorder, local_addr);
1340 inet->remote_addr.s_addr = kernel32_to_cpu(byteorder, remote_addr);
1341 raw->protocol = protocol;
1342 raw->l4.st = st;
1343
1344 return sock;
1345}
1346
1347static const struct l4_xinfo_class raw_xinfo_class = {
1348 .sock = {
1349 .get_name = raw_get_name,
1350 .get_type = raw_get_type,
1351 .get_state = tcp_get_state,
1352 .get_listening = NULL,
1353 .fill_column = raw_fill_column,
1354 .free = NULL,
1355 },
1356 .scan_line = raw_xinfo_scan_line,
1357 .get_addr = tcp_xinfo_get_addr,
1358 .is_any_addr = tcp_xinfo_is_any_addr,
1359 .family = AF_INET,
1656da13 1360 .l3_decorator = {"", ""},
0188afb3
MY
1361};
1362
891b24b7 1363static void load_xinfo_from_proc_raw(ino_t netns_inode, enum sysfs_byteorder byteorder)
0188afb3
MY
1364{
1365 load_xinfo_from_proc_inet_L4(netns_inode,
1366 "/proc/net/raw",
891b24b7
MY
1367 &raw_xinfo_class,
1368 byteorder);
0188afb3 1369}
1656da13 1370
a7cba6f3
MY
1371/*
1372 * PING
1373 */
1374static char *ping_get_name(struct sock_xinfo *sock_xinfo,
1375 struct sock *sock __attribute__((__unused__)))
1376{
1377 return raw_get_name_common(sock_xinfo, sock, "id");
1378}
1379
1380static char *ping_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
1381 struct sock *sock __attribute__((__unused__)))
1382{
e0dc84da 1383 return xstrdup("dgram");
a7cba6f3
MY
1384}
1385
1386static bool ping_fill_column(struct proc *proc __attribute__((__unused__)),
1387 struct sock_xinfo *sock_xinfo,
1388 struct sock *sock __attribute__((__unused__)),
1389 struct libscols_line *ln __attribute__((__unused__)),
1390 int column_id,
1391 size_t column_index __attribute__((__unused__)),
1392 char **str)
1393{
1394 if (l3_fill_column_handler(INET, sock_xinfo, column_id, str))
1395 return true;
1396
1397 if (column_id == COL_PING_ID) {
1398 xasprintf(str, "%"PRIu16,
1399 ((struct raw_xinfo *)sock_xinfo)->protocol);
1400 return true;
1401 }
1402
1403 return false;
1404}
1405
1406static const struct l4_xinfo_class ping_xinfo_class = {
1407 .sock = {
1408 .get_name = ping_get_name,
1409 .get_type = ping_get_type,
1410 .get_state = tcp_get_state,
1411 .get_listening = NULL,
1412 .fill_column = ping_fill_column,
1413 .free = NULL,
1414 },
1415 .scan_line = raw_xinfo_scan_line,
1416 .get_addr = tcp_xinfo_get_addr,
1417 .is_any_addr = tcp_xinfo_is_any_addr,
1418 .family = AF_INET,
1419 .l3_decorator = {"", ""},
1420};
1421
891b24b7 1422static void load_xinfo_from_proc_icmp(ino_t netns_inode, enum sysfs_byteorder byteorder)
a7cba6f3
MY
1423{
1424 load_xinfo_from_proc_inet_L4(netns_inode,
1425 "/proc/net/icmp",
891b24b7
MY
1426 &ping_xinfo_class,
1427 byteorder);
a7cba6f3
MY
1428}
1429
1656da13
MY
1430/*
1431 * TCP6
1432 */
1433static struct sock_xinfo *tcp6_xinfo_scan_line(const struct sock_xinfo_class *class,
1434 char * line,
1435 ino_t netns_inode,
1436 enum sysfs_byteorder byteorder)
1437{
1438 uint32_t local_addr[4];
1439 unsigned int local_port;
1440 uint32_t remote_addr[4];
1441 unsigned int remote_port;
1442 unsigned int st;
1443 unsigned long inode;
1444 struct tcp_xinfo *tcp;
1445 struct inet6_xinfo *inet6;
1446 struct sock_xinfo *sock;
1447
1448 if (sscanf(line,
1449 "%*d: "
1450 "%08x%08x%08x%08x:%04x "
1451 "%08x%08x%08x%08x:%04x "
1452 "%x %*x:%*x %*x:%*x %*x %*u %*d %lu ",
1453 local_addr+0, local_addr+1, local_addr+2, local_addr+3, &local_port,
1454 remote_addr+0, remote_addr+1, remote_addr+2, remote_addr+3, &remote_port,
1455 &st, &inode) != 12)
1456 return NULL;
1457
1458 if (inode == 0)
1459 return NULL;
1460
8ff22ccb 1461 tcp = xmalloc(sizeof(*tcp));
1656da13
MY
1462 inet6 = &tcp->l4.inet6;
1463 sock = &inet6->sock;
1464 sock->class = class;
1465 sock->inode = (ino_t)inode;
1466 sock->netns_inode = netns_inode;
1467 tcp->local_port = local_port;
1468 for (int i = 0; i < 4; i++) {
1469 inet6->local_addr.s6_addr32[i] = kernel32_to_cpu(byteorder, local_addr[i]);
1470 inet6->remote_addr.s6_addr32[i] = kernel32_to_cpu(byteorder, remote_addr[i]);
1471 }
1472 tcp->remote_port = remote_port;
1473 tcp->l4.st = st;
1474
1475 return sock;
1476}
1477
1478static bool tcp6_fill_column(struct proc *proc __attribute__((__unused__)),
1479 struct sock_xinfo *sock_xinfo,
1480 struct sock *sock __attribute__((__unused__)),
1481 struct libscols_line *ln __attribute__((__unused__)),
1482 int column_id,
1483 size_t column_index __attribute__((__unused__)),
1484 char **str)
1485{
1486 return l3_fill_column_handler(INET6, sock_xinfo, column_id, str)
1487 || l4_fill_column_handler(TCP, sock_xinfo, column_id, str);
1488}
1489
1490static void *tcp6_xinfo_get_addr(struct l4_xinfo * l4, enum l4_side side)
1491{
1492 return (side == L4_LOCAL)
1493 ? &l4->inet6.local_addr
1494 : &l4->inet6.remote_addr;
1495}
1496
1497static bool tcp6_xinfo_is_any_addr(void *addr)
1498{
1499 return IN6_ARE_ADDR_EQUAL(addr, &(struct in6_addr)IN6ADDR_ANY_INIT);
1500}
1501
1502static const struct l4_xinfo_class tcp6_xinfo_class = {
1503 .sock = {
1504 .get_name = tcp_get_name,
1505 .get_type = tcp_get_type,
1506 .get_state = tcp_get_state,
1507 .get_listening = tcp_get_listening,
1508 .fill_column = tcp6_fill_column,
1509 .free = NULL,
1510 },
1511 .scan_line = tcp6_xinfo_scan_line,
1512 .get_addr = tcp6_xinfo_get_addr,
1513 .is_any_addr = tcp6_xinfo_is_any_addr,
1514 .family = AF_INET6,
1515 .l3_decorator = {"[", "]"},
1516};
1517
891b24b7 1518static void load_xinfo_from_proc_tcp6(ino_t netns_inode, enum sysfs_byteorder byteorder)
1656da13
MY
1519{
1520 load_xinfo_from_proc_inet_L4(netns_inode,
1521 "/proc/net/tcp6",
891b24b7
MY
1522 &tcp6_xinfo_class,
1523 byteorder);
1656da13 1524}
28cf2b21
MY
1525
1526/*
1527 * UDP6
1528 */
1529static bool udp6_fill_column(struct proc *proc __attribute__((__unused__)),
1530 struct sock_xinfo *sock_xinfo,
1531 struct sock *sock __attribute__((__unused__)),
1532 struct libscols_line *ln __attribute__((__unused__)),
1533 int column_id,
1534 size_t column_index __attribute__((__unused__)),
1535 char **str)
1536{
1537 return l3_fill_column_handler(INET6, sock_xinfo, column_id, str)
1538 || l4_fill_column_handler(UDP, sock_xinfo, column_id, str);
1539}
1540
1541static const struct l4_xinfo_class udp6_xinfo_class = {
1542 .sock = {
1543 .get_name = udp_get_name,
1544 .get_type = udp_get_type,
1545 .get_state = tcp_get_state,
1546 .get_listening = NULL,
1547 .fill_column = udp6_fill_column,
1548 .free = NULL,
1549 },
1550 .scan_line = tcp6_xinfo_scan_line,
1551 .get_addr = tcp6_xinfo_get_addr,
1552 .is_any_addr = tcp6_xinfo_is_any_addr,
1553 .family = AF_INET6,
1554 .l3_decorator = {"[", "]"},
1555};
1556
891b24b7 1557static void load_xinfo_from_proc_udp6(ino_t netns_inode, enum sysfs_byteorder byteorder)
28cf2b21
MY
1558{
1559 load_xinfo_from_proc_inet_L4(netns_inode,
1560 "/proc/net/udp6",
891b24b7
MY
1561 &udp6_xinfo_class,
1562 byteorder);
28cf2b21 1563}
2dd373c3 1564
93bca151
MY
1565/*
1566 * UDPLITEv6
1567 */
1568static bool udplite6_fill_column(struct proc *proc __attribute__((__unused__)),
1569 struct sock_xinfo *sock_xinfo,
1570 struct sock *sock __attribute__((__unused__)),
1571 struct libscols_line *ln __attribute__((__unused__)),
1572 int column_id,
1573 size_t column_index __attribute__((__unused__)),
1574 char **str)
1575{
1576 return l3_fill_column_handler(INET6, sock_xinfo, column_id, str)
1577 || l4_fill_column_handler(UDPLITE, sock_xinfo, column_id, str);
1578}
1579
1580static const struct l4_xinfo_class udplite6_xinfo_class = {
1581 .sock = {
1582 .get_name = udp_get_name,
1583 .get_type = udp_get_type,
1584 .get_state = tcp_get_state,
1585 .get_listening = NULL,
1586 .fill_column = udplite6_fill_column,
1587 .free = NULL,
1588 },
1589 .scan_line = tcp6_xinfo_scan_line,
1590 .get_addr = tcp6_xinfo_get_addr,
1591 .is_any_addr = tcp6_xinfo_is_any_addr,
1592 .family = AF_INET6,
1593 .l3_decorator = {"[", "]"},
1594};
1595
891b24b7 1596static void load_xinfo_from_proc_udplite6(ino_t netns_inode, enum sysfs_byteorder byteorder)
93bca151
MY
1597{
1598 load_xinfo_from_proc_inet_L4(netns_inode,
1599 "/proc/net/udplite6",
891b24b7
MY
1600 &udplite6_xinfo_class,
1601 byteorder);
93bca151
MY
1602}
1603
2dd373c3
MY
1604/*
1605 * RAW6
1606 */
1607static struct sock_xinfo *raw6_xinfo_scan_line(const struct sock_xinfo_class *class,
1608 char * line,
1609 ino_t netns_inode,
1610 enum sysfs_byteorder byteorder)
1611{
1612 uint32_t local_addr[4];
1613 unsigned int protocol;
1614 uint32_t remote_addr[4];
1615 unsigned int st;
1616 unsigned long inode;
1617 struct raw_xinfo *raw;
1618 struct inet6_xinfo *inet6;
1619 struct sock_xinfo *sock;
1620
1621 if (sscanf(line,
1622 "%*d: "
1623 "%08x%08x%08x%08x:%04x "
1624 "%08x%08x%08x%08x:0000 "
1625 "%x %*x:%*x %*x:%*x %*x %*u %*d %lu ",
1626 local_addr+0, local_addr+1, local_addr+2, local_addr+3, &protocol,
1627 remote_addr+0, remote_addr+1, remote_addr+2, remote_addr+3,
1628 &st, &inode) != 11)
1629 return NULL;
1630
1631 if (inode == 0)
1632 return NULL;
1633
1634 raw = xmalloc(sizeof(*raw));
1635 inet6 = &raw->l4.inet6;
1636 sock = &inet6->sock;
1637 sock->class = class;
1638 sock->inode = (ino_t)inode;
1639 sock->netns_inode = netns_inode;
1640 for (int i = 0; i < 4; i++) {
1641 inet6->local_addr.s6_addr32[i] = kernel32_to_cpu(byteorder, local_addr[i]);
1642 inet6->remote_addr.s6_addr32[i] = kernel32_to_cpu(byteorder, remote_addr[i]);
1643 }
1644 raw->protocol = protocol;
1645 raw->l4.st = st;
1646
1647 return sock;
1648}
1649
1650static bool raw6_fill_column(struct proc *proc __attribute__((__unused__)),
1651 struct sock_xinfo *sock_xinfo,
1652 struct sock *sock __attribute__((__unused__)),
1653 struct libscols_line *ln __attribute__((__unused__)),
1654 int column_id,
1655 size_t column_index __attribute__((__unused__)),
1656 char **str)
1657{
1658 struct raw_xinfo *raw;
1659
1660 if (l3_fill_column_handler(INET6, sock_xinfo, column_id, str))
1661 return true;
1662
1663 raw = (struct raw_xinfo *)sock_xinfo;
1664 if (column_id == COL_RAW_PROTOCOL) {
1665 xasprintf(str, "%"PRIu16, raw->protocol);
1666 return true;
1667 }
1668
1669 return false;
1670}
1671
1672static const struct l4_xinfo_class raw6_xinfo_class = {
1673 .sock = {
1674 .get_name = raw_get_name,
1675 .get_type = raw_get_type,
1676 .get_state = tcp_get_state,
1677 .get_listening = NULL,
1678 .fill_column = raw6_fill_column,
1679 .free = NULL,
1680 },
1681 .scan_line = raw6_xinfo_scan_line,
1682 .get_addr = tcp6_xinfo_get_addr,
1683 .is_any_addr = tcp6_xinfo_is_any_addr,
1684 .family = AF_INET6,
1685 .l3_decorator = {"[", "]"},
1686};
1687
891b24b7 1688static void load_xinfo_from_proc_raw6(ino_t netns_inode, enum sysfs_byteorder byteorder)
2dd373c3
MY
1689{
1690 load_xinfo_from_proc_inet_L4(netns_inode,
1691 "/proc/net/raw6",
891b24b7
MY
1692 &raw6_xinfo_class,
1693 byteorder);
2dd373c3 1694}
0b1dfd03
MY
1695
1696/*
1697 * PINGv6
1698 */
1699static bool ping6_fill_column(struct proc *proc __attribute__((__unused__)),
1700 struct sock_xinfo *sock_xinfo,
1701 struct sock *sock __attribute__((__unused__)),
1702 struct libscols_line *ln __attribute__((__unused__)),
1703 int column_id,
1704 size_t column_index __attribute__((__unused__)),
1705 char **str)
1706{
1707 if (l3_fill_column_handler(INET6, sock_xinfo, column_id, str))
1708 return true;
1709
1710 if (column_id == COL_PING_ID) {
1711 xasprintf(str, "%"PRIu16,
1712 ((struct raw_xinfo *)sock_xinfo)->protocol);
1713 return true;
1714 }
1715
1716 return false;
1717}
1718
1719static const struct l4_xinfo_class ping6_xinfo_class = {
1720 .sock = {
1721 .get_name = ping_get_name,
1722 .get_type = ping_get_type,
1723 .get_state = tcp_get_state,
1724 .get_listening = NULL,
1725 .fill_column = ping6_fill_column,
1726 .free = NULL,
1727 },
1728 .scan_line = raw6_xinfo_scan_line,
1729 .get_addr = tcp6_xinfo_get_addr,
1730 .is_any_addr = tcp6_xinfo_is_any_addr,
1731 .family = AF_INET6,
1732 .l3_decorator = {"[", "]"},
1733};
1734
891b24b7 1735static void load_xinfo_from_proc_icmp6(ino_t netns_inode, enum sysfs_byteorder byteorder)
0b1dfd03
MY
1736{
1737 load_xinfo_from_proc_inet_L4(netns_inode,
1738 "/proc/net/icmp6",
891b24b7
MY
1739 &ping6_xinfo_class,
1740 byteorder);
0b1dfd03 1741}
b53cc896
MY
1742
1743/*
1744 * NETLINK
1745 */
1746struct netlink_xinfo {
1747 struct sock_xinfo sock;
1748 uint16_t protocol;
1749 uint32_t lportid; /* netlink_diag may provide rportid. */
1750 uint32_t groups;
1751};
1752
1753static const char *netlink_decode_protocol(uint16_t protocol)
1754{
1755 switch (protocol) {
1756 case NETLINK_ROUTE:
1757 return "route";
1758 case NETLINK_UNUSED:
1759 return "unused";
1760 case NETLINK_USERSOCK:
1761 return "usersock";
1762 case NETLINK_FIREWALL:
1763 return "firewall";
1764 case NETLINK_SOCK_DIAG:
1765 return "sock_diag";
1766 case NETLINK_NFLOG:
1767 return "nflog";
1768 case NETLINK_XFRM:
1769 return "xfrm";
1770 case NETLINK_SELINUX:
1771 return "selinux";
1772 case NETLINK_ISCSI:
1773 return "iscsi";
1774 case NETLINK_AUDIT:
1775 return "audit";
1776 case NETLINK_FIB_LOOKUP:
1777 return "fib_lookup";
1778 case NETLINK_CONNECTOR:
1779 return "connector";
1780 case NETLINK_NETFILTER:
1781 return "netfilter";
1782 case NETLINK_IP6_FW:
1783 return "ip6_fw";
1784 case NETLINK_DNRTMSG:
1785 return "dnrtmsg";
1786 case NETLINK_KOBJECT_UEVENT:
1787 return "kobject_uevent";
1788 case NETLINK_GENERIC:
1789 return "generic";
1790 case NETLINK_SCSITRANSPORT:
1791 return "scsitransport";
1792 case NETLINK_ECRYPTFS:
1793 return "ecryptfs";
1794 case NETLINK_RDMA:
1795 return "rdma";
1796 case NETLINK_CRYPTO:
1797 return "crypto";
1798#ifdef NETLINK_SMC
1799 case NETLINK_SMC:
1800 return "smc";
1801#endif
1802 default:
1803 return "unknown";
1804 }
1805}
1806
1807static char *netlink_get_name(struct sock_xinfo *sock_xinfo,
1808 struct sock *sock __attribute__((__unused__)))
1809{
1810 struct netlink_xinfo *nl = (struct netlink_xinfo *)sock_xinfo;
1811 char *str = NULL;
1812 const char *protocol = netlink_decode_protocol(nl->protocol);
1813
1814 if (nl->groups)
1815 xasprintf(&str, "protocol=%s lport=%"PRIu16 " groups=%"PRIu32,
1816 protocol,
1817 nl->lportid, nl->groups);
1818 else
1819 xasprintf(&str, "protocol=%s lport=%"PRIu16,
1820 protocol,
1821 nl->lportid);
1822 return str;
1823}
1824
1825static char *netlink_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
1826 struct sock *sock __attribute__((__unused__)))
1827{
e0dc84da 1828 return xstrdup("raw");
b53cc896
MY
1829}
1830
1831static bool netlink_fill_column(struct proc *proc __attribute__((__unused__)),
1832 struct sock_xinfo *sock_xinfo,
1833 struct sock *sock __attribute__((__unused__)),
1834 struct libscols_line *ln __attribute__((__unused__)),
1835 int column_id,
1836 size_t column_index __attribute__((__unused__)),
1837 char **str)
1838{
1839 struct netlink_xinfo *nl = (struct netlink_xinfo *)sock_xinfo;
1840
1841 switch (column_id) {
1842 case COL_NETLINK_GROUPS:
1843 xasprintf(str, "%"PRIu32, nl->groups);
1844 return true;
1845 case COL_NETLINK_LPORT:
1846 xasprintf(str, "%"PRIu32, nl->lportid);
1847 return true;
1848 case COL_NETLINK_PROTOCOL:
e0dc84da 1849 *str = xstrdup(netlink_decode_protocol(nl->protocol));
b53cc896
MY
1850 return true;
1851 }
1852
1853 return false;
1854}
1855
1856static const struct sock_xinfo_class netlink_xinfo_class = {
1857 .get_name = netlink_get_name,
1858 .get_type = netlink_get_type,
1859 .get_state = NULL,
1860 .get_listening = NULL,
1861 .fill_column = netlink_fill_column,
1862 .free = NULL,
1863};
1864
1865static void load_xinfo_from_proc_netlink(ino_t netns_inode)
1866{
1867 char line[BUFSIZ];
1868 FILE *netlink_fp;
1869
1870 netlink_fp = fopen("/proc/net/netlink", "r");
1871 if (!netlink_fp)
1872 return;
1873
1874 if (fgets(line, sizeof(line), netlink_fp) == NULL)
1875 goto out;
1876 if (!(line[0] == 's' && line[1] == 'k'))
1877 /* Unexpected line */
1878 goto out;
1879
1880 while (fgets(line, sizeof(line), netlink_fp)) {
1881 uint16_t protocol;
1882 uint32_t lportid;
1883 uint32_t groups;
1884 unsigned long inode;
1885 struct netlink_xinfo *nl;
1886
1887 if (sscanf(line, "%*x %" SCNu16 " %" SCNu32 " %" SCNx32 " %*d %*d %*d %*d %*u %lu",
1888 &protocol, &lportid, &groups, &inode) < 4)
1889 continue;
1890
1891 if (inode == 0)
1892 continue;
1893
1894 nl = xcalloc(1, sizeof(*nl));
1895 nl->sock.class = &netlink_xinfo_class;
1896 nl->sock.inode = (ino_t)inode;
1897 nl->sock.netns_inode = netns_inode;
1898
1899 nl->protocol = protocol;
1900 nl->lportid = lportid;
1901 nl->groups = groups;
1902
1903 add_sock_info(&nl->sock);
1904 }
1905
1906 out:
1907 fclose(netlink_fp);
1908}
adfc156a
MY
1909
1910/*
1911 * PACKET
1912 */
1913struct packet_xinfo {
1914 struct sock_xinfo sock;
1915 uint16_t type;
1916 uint16_t protocol;
1917 unsigned int iface;
1918};
1919
1920static const char *packet_decode_protocol(uint16_t proto)
1921{
1922 switch (proto) {
1923 case 0:
1924 return NULL;
1925 case ETH_P_802_3:
1926 return "802_3";
1927 case ETH_P_AX25:
1928 return "ax25";
1929 case ETH_P_ALL:
1930 return "all";
1931 case ETH_P_802_2:
1932 return "802_2";
1933 case ETH_P_SNAP:
1934 return "snap";
1935 case ETH_P_DDCMP:
1936 return "ddcmp";
1937 case ETH_P_WAN_PPP:
1938 return "wan_ppp";
1939 case ETH_P_PPP_MP:
1940 return "ppp_mp";
1941 case ETH_P_LOCALTALK:
1942 return "localtalk";
1943 case ETH_P_CAN:
1944 return "can";
1945 case ETH_P_CANFD:
1946 return "canfd";
1947#ifdef ETH_P_CANXL
1948 case ETH_P_CANXL:
1949 return "canxl";
1950#endif
1951 case ETH_P_PPPTALK:
1952 return "ppptalk";
1953 case ETH_P_TR_802_2:
1954 return "tr_802_2";
1955 case ETH_P_MOBITEX:
1956 return "mobitex";
1957 case ETH_P_CONTROL:
1958 return "control";
1959 case ETH_P_IRDA:
1960 return "irda";
1961 case ETH_P_ECONET:
1962 return "econet";
1963 case ETH_P_HDLC:
1964 return "hdlc";
1965 case ETH_P_ARCNET:
1966 return "arcnet";
1967 case ETH_P_DSA:
1968 return "dsa";
1969 case ETH_P_TRAILER:
1970 return "trailer";
1971 case ETH_P_PHONET:
1972 return "phonet";
1973 case ETH_P_IEEE802154:
1974 return "ieee802154";
1975 case ETH_P_CAIF:
1976 return "caif";
1977#ifdef ETH_P_XDSA
1978 case ETH_P_XDSA:
1979 return "xdsa";
1980#endif
1981#ifdef ETH_P_MAP
1982 case ETH_P_MAP:
1983 return "map";
1984#endif
1985#ifdef ETH_P_MCTP
1986 case ETH_P_MCTP:
1987 return "mctp";
1988#endif
1989 case ETH_P_LOOP:
1990 return "loop";
1991 case ETH_P_PUP:
1992 return "pup";
1993 case ETH_P_PUPAT:
1994 return "pupat";
1995#ifdef ETH_P_TSN
1996 case ETH_P_TSN:
1997 return "tsn";
1998#endif
1999#ifdef ETH_P_ERSPAN2
2000 case ETH_P_ERSPAN2:
2001 return "erspan2";
2002#endif
2003 case ETH_P_IP:
2004 return "ip";
2005 case ETH_P_X25:
2006 return "x25";
2007 case ETH_P_ARP:
2008 return "arp";
2009 case ETH_P_BPQ:
2010 return "bpq";
2011 case ETH_P_IEEEPUP:
2012 return "ieeepup";
2013 case ETH_P_IEEEPUPAT:
2014 return "ieeepupat";
2015 case ETH_P_BATMAN:
2016 return "batman";
2017 case ETH_P_DEC:
2018 return "dec";
2019 case ETH_P_DNA_DL:
2020 return "dna_dl";
2021 case ETH_P_DNA_RC:
2022 return "dna_rc";
2023 case ETH_P_DNA_RT:
2024 return "dna_rt";
2025 case ETH_P_LAT:
2026 return "lat";
2027 case ETH_P_DIAG:
2028 return "diag";
2029 case ETH_P_CUST:
2030 return "cust";
2031 case ETH_P_SCA:
2032 return "sca";
2033 case ETH_P_TEB:
2034 return "teb";
2035 case ETH_P_RARP:
2036 return "rarp";
2037 case ETH_P_ATALK:
2038 return "atalk";
2039 case ETH_P_AARP:
2040 return "aarp";
2041 case ETH_P_8021Q:
2042 return "8021q";
2043#ifdef ETH_P_ERSPAN
2044 case ETH_P_ERSPAN:
2045 return "erspan";
2046#endif
2047 case ETH_P_IPX:
2048 return "ipx";
2049 case ETH_P_IPV6:
2050 return "ipv6";
2051 case ETH_P_PAUSE:
2052 return "pause";
2053 case ETH_P_SLOW:
2054 return "slow";
2055 case ETH_P_WCCP:
2056 return "wccp";
2057 case ETH_P_MPLS_UC:
2058 return "mpls_uc";
2059 case ETH_P_MPLS_MC:
2060 return "mpls_mc";
2061 case ETH_P_ATMMPOA:
2062 return "atmmpoa";
2063#ifdef ETH_P_PPP_DISC
2064 case ETH_P_PPP_DISC:
2065 return "ppp_disc";
2066#endif
2067#ifdef ETH_P_PPP_SES
2068 case ETH_P_PPP_SES:
2069 return "ppp_ses";
2070#endif
2071 case ETH_P_LINK_CTL:
2072 return "link_ctl";
2073 case ETH_P_ATMFATE:
2074 return "atmfate";
2075 case ETH_P_PAE:
2076 return "pae";
2077#ifdef ETH_P_PROFINET
2078 case ETH_P_PROFINET:
2079 return "profinet";
2080#endif
2081#ifdef ETH_P_REALTEK
2082 case ETH_P_REALTEK:
2083 return "realtek";
2084#endif
2085 case ETH_P_AOE:
2086 return "aoe";
2087#ifdef ETH_P_ETHERCAT
2088 case ETH_P_ETHERCAT:
2089 return "ethercat";
2090#endif
2091 case ETH_P_8021AD:
2092 return "8021ad";
2093 case ETH_P_802_EX1:
2094 return "802_ex1";
2095#ifdef ETH_P_PREAUTH
2096 case ETH_P_PREAUTH:
2097 return "preauth";
2098#endif
2099 case ETH_P_TIPC:
2100 return "tipc";
2101#ifdef ETH_P_LLDP
2102 case ETH_P_LLDP:
2103 return "lldp";
2104#endif
2105#ifdef ETH_P_MRP
2106 case ETH_P_MRP:
2107 return "mrp";
2108#endif
2109#ifdef ETH_P_MACSEC
2110 case ETH_P_MACSEC:
2111 return "macsec";
2112#endif
2113 case ETH_P_8021AH:
2114 return "8021ah";
2115#ifdef ETH_P_MVRP
2116 case ETH_P_MVRP:
2117 return "mvrp";
2118#endif
2119 case ETH_P_1588:
2120 return "1588";
2121#ifdef ETH_P_NCSI
2122 case ETH_P_NCSI:
2123 return "ncsi";
2124#endif
2125#ifdef ETH_P_PRP
2126 case ETH_P_PRP:
2127 return "prp";
2128#endif
2129#ifdef ETH_P_CFM
2130 case ETH_P_CFM:
2131 return "cfm";
2132#endif
2133 case ETH_P_FCOE:
2134 return "fcoe";
2135#ifdef ETH_P_IBOE
2136 case ETH_P_IBOE:
2137 return "iboe";
2138#endif
2139 case ETH_P_TDLS:
2140 return "tdls";
2141 case ETH_P_FIP:
2142 return "fip";
2143#ifdef ETH_P_80221
2144 case ETH_P_80221:
2145 return "80221";
2146#endif
2147#ifdef ETH_P_HSR
2148 case ETH_P_HSR:
2149 return "hsr";
2150#endif
2151#ifdef ETH_P_NSH
2152 case ETH_P_NSH:
2153 return "nsh";
2154#endif
2155#ifdef ETH_P_LOOPBACK
2156 case ETH_P_LOOPBACK:
2157 return "loopback";
2158#endif
2159 case ETH_P_QINQ1:
2160 return "qinq1";
2161 case ETH_P_QINQ2:
2162 return "qinq2";
2163 case ETH_P_QINQ3:
2164 return "qinq3";
2165 case ETH_P_EDSA:
2166 return "edsa";
2167#ifdef ETH_P_DSA_8021Q
2168 case ETH_P_DSA_8021Q:
2169 return "dsa_8021q";
2170#endif
2171#ifdef ETH_P_DSA_A5PSW
2172 case ETH_P_DSA_A5PSW:
2173 return "dsa_a5psw";
2174#endif
2175#ifdef ETH_P_IFE
2176 case ETH_P_IFE:
2177 return "ife";
2178#endif
2179 case ETH_P_AF_IUCV:
2180 return "af_iucv";
2181#ifdef ETH_P_802_3_MIN
2182 case ETH_P_802_3_MIN:
2183 return "802_3_min";
2184#endif
2185 default:
2186 return "unknown";
2187 }
2188}
2189
2190static char *packet_get_name(struct sock_xinfo *sock_xinfo,
2191 struct sock *sock __attribute__((__unused__)))
2192{
2193 struct packet_xinfo *pkt = (struct packet_xinfo *)sock_xinfo;
2194 char *str = NULL;
2195 const char *type = sock_decode_type(pkt->type);
2196 const char *proto = packet_decode_protocol(pkt->protocol);
2197 const char *iface = get_iface_name(sock_xinfo->netns_inode,
2198 pkt->iface);
2199
2200 if (iface && proto)
2201 xasprintf(&str, "type=%s protocol=%s iface=%s",
2202 type, proto, iface);
2203 else if (proto)
2204 xasprintf(&str, "type=%s protocol=%s",
2205 type, proto);
2206 else if (iface)
2207 xasprintf(&str, "type=%s iface=%s",
2208 type, iface);
2209 else
2210 xasprintf(&str, "type=%s", type);
2211
2212 return str;
2213}
2214
2215static char *packet_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
2216 struct sock *sock __attribute__((__unused__)))
2217{
2218 const char *str;
2219 struct packet_xinfo *pkt = (struct packet_xinfo *)sock_xinfo;
2220
2221 str = sock_decode_type(pkt->type);
2222 return xstrdup(str);
2223}
2224
2225static bool packet_fill_column(struct proc *proc __attribute__((__unused__)),
2226 struct sock_xinfo *sock_xinfo,
2227 struct sock *sock __attribute__((__unused__)),
2228 struct libscols_line *ln __attribute__((__unused__)),
2229 int column_id,
2230 size_t column_index __attribute__((__unused__)),
2231 char **str)
2232{
2233 struct packet_xinfo *pkt = (struct packet_xinfo *)sock_xinfo;
2234
2235 switch (column_id) {
2236 case COL_PACKET_IFACE: {
2237 const char *iface;
2238 iface = get_iface_name(sock_xinfo->netns_inode,
2239 pkt->iface);
2240 if (iface) {
2241 *str = xstrdup(iface);
2242 return true;
2243 }
2244 break;
2245 }
2246 case COL_PACKET_PROTOCOL: {
2247 const char *proto;
2248 proto = packet_decode_protocol(pkt->protocol);
2249 if (proto) {
2250 *str = xstrdup(proto);
2251 return true;
2252 }
2253 break;
2254 }
2255 default:
2256 break;
2257 }
2258 return false;
2259}
2260
2261static const struct sock_xinfo_class packet_xinfo_class = {
2262 .get_name = packet_get_name,
2263 .get_type = packet_get_type,
2264 .get_state = NULL,
2265 .get_listening = NULL,
2266 .fill_column = packet_fill_column,
2267 .free = NULL,
2268};
2269
2270static void load_xinfo_from_proc_packet(ino_t netns_inode)
2271{
2272 char line[BUFSIZ];
2273 FILE *packet_fp;
2274
2275 packet_fp = fopen("/proc/net/packet", "r");
2276 if (!packet_fp)
2277 return;
2278
2279 if (fgets(line, sizeof(line), packet_fp) == NULL)
2280 goto out;
2281 if (!(line[0] == 's' && line[1] == 'k'))
2282 /* Unexpected line */
2283 goto out;
2284
2285 while (fgets(line, sizeof(line), packet_fp)) {
2286 uint16_t type;
2287 uint16_t protocol;
2288 unsigned int iface;
2289 unsigned long inode;
2290 struct packet_xinfo *pkt;
2291
2292 if (sscanf(line, "%*x %*d %" SCNu16 " %" SCNu16 " %u %*d %*d %*d %lu",
2293 &type, &protocol, &iface, &inode) < 4)
2294 continue;
2295
2296 pkt = xcalloc(1, sizeof(*pkt));
2297 pkt->sock.class = &packet_xinfo_class;
2298 pkt->sock.inode = (ino_t)inode;
2299 pkt->sock.netns_inode = netns_inode;
2300
2301 pkt->type = type;
2302 pkt->protocol = protocol;
2303 pkt->iface = iface;
2304
2305 add_sock_info(&pkt->sock);
2306 }
2307
2308 out:
2309 fclose(packet_fp);
2310}