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