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