]> git.proxmox.com Git - mirror_iproute2.git/blame - misc/ss.c
Merge branch 'main' into next
[mirror_iproute2.git] / misc / ss.c
CommitLineData
b9de3ecf 1/*
aba5acdf
SH
2 * ss.c "sockstat", socket statistics
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
aba5acdf
SH
15#include <fcntl.h>
16#include <sys/ioctl.h>
17#include <sys/socket.h>
18#include <sys/uio.h>
0bab7630 19#include <sys/sysmacros.h>
aba5acdf
SH
20#include <netinet/in.h>
21#include <string.h>
22#include <errno.h>
23#include <netdb.h>
24#include <arpa/inet.h>
aba5acdf
SH
25#include <dirent.h>
26#include <fnmatch.h>
ab61159a 27#include <getopt.h>
bf4ceee6 28#include <stdbool.h>
6b376ebd 29#include <limits.h>
90351722 30#include <stdarg.h>
aba5acdf 31
7bd91885 32#include "ss_util.h"
aba5acdf
SH
33#include "utils.h"
34#include "rt_names.h"
35#include "ll_map.h"
36#include "libnetlink.h"
95ce04bc 37#include "namespace.h"
fbef6555 38#include "version.h"
31f45088 39#include "rt_names.h"
14f4bda5 40#include "cg_map.h"
aba5acdf 41
9cb1eccf 42#include <linux/tcp.h>
dfbaa90d 43#include <linux/unix_diag.h>
372c30d2
ND
44#include <linux/netdevice.h> /* for MAX_ADDR_LEN */
45#include <linux/filter.h>
2abc3d76 46#include <linux/xdp_diag.h>
372c30d2 47#include <linux/packet_diag.h>
ecb928c8 48#include <linux/netlink_diag.h>
f89d46ad 49#include <linux/sctp.h>
c759116a 50#include <linux/vm_sockets_diag.h>
5caf79a0
GM
51#include <linux/net.h>
52#include <linux/tipc.h>
53#include <linux/tipc_netlink.h>
54#include <linux/tipc_sockets_diag.h>
14cadc70 55#include <linux/tls.h>
712fdd98 56#include <linux/mptcp.h>
aba5acdf 57
9700927a
TDS
58/* AF_VSOCK/PF_VSOCK is only provided since glibc 2.18 */
59#ifndef PF_VSOCK
60#define PF_VSOCK 40
61#endif
62#ifndef AF_VSOCK
63#define AF_VSOCK PF_VSOCK
64#endif
65
9c3be2c0
PA
66#ifndef IPPROTO_MPTCP
67#define IPPROTO_MPTCP 262
68#endif
69
aa5bd6a2
SB
70#define BUF_CHUNK (1024 * 1024) /* Buffer chunk allocation size */
71#define BUF_CHUNKS_MAX 5 /* Maximum number of allocated buffer chunks */
691bd854 72#define LEN_ALIGN(x) (((x) + 1) & ~1)
8a4025f6 73
116ac927
RH
74#if HAVE_SELINUX
75#include <selinux/selinux.h>
76#else
77/* Stubs for SELinux functions */
78static int is_selinux_enabled(void)
79{
80 return -1;
81}
82
83static int getpidcon(pid_t pid, char **context)
84{
85 *context = NULL;
86 return -1;
87}
88
89static int getfilecon(char *path, char **context)
90{
91 *context = NULL;
92 return -1;
93}
94
95static int security_get_initial_context(char *name, char **context)
96{
97 *context = NULL;
98 return -1;
99}
100#endif
101
aba5acdf 102int preferred_family = AF_UNSPEC;
3f7bd0fd 103static int show_options;
acd1e437 104int show_details;
3f7bd0fd
SH
105static int show_users;
106static int show_mem;
107static int show_tcpinfo;
108static int show_bpf;
109static int show_proc_ctx;
110static int show_sock_ctx;
111static int show_header = 1;
112static int follow_events;
113static int sctp_ino;
114static int show_tipcinfo;
0f3f0ca3 115static int show_tos;
14f4bda5 116static int show_cgroup;
296b5de7 117int oneline;
aba5acdf 118
59f46b7b
SB
119enum col_id {
120 COL_NETID,
121 COL_STATE,
122 COL_RECVQ,
123 COL_SENDQ,
124 COL_ADDR,
125 COL_SERV,
126 COL_RADDR,
127 COL_RSERV,
128 COL_EXT,
5883c6eb 129 COL_PROC,
59f46b7b
SB
130 COL_MAX
131};
132
133enum col_align {
134 ALIGN_LEFT,
135 ALIGN_CENTER,
136 ALIGN_RIGHT
137};
138
139struct column {
140 const enum col_align align;
141 const char *header;
142 const char *ldelim;
87b1a7ae
SB
143 int disabled;
144 int width; /* Calculated, including additional layout spacing */
145 int max_len; /* Measured maximum field length in this column */
59f46b7b
SB
146};
147
148static struct column columns[] = {
87b1a7ae
SB
149 { ALIGN_LEFT, "Netid", "", 0, 0, 0 },
150 { ALIGN_LEFT, "State", " ", 0, 0, 0 },
151 { ALIGN_LEFT, "Recv-Q", " ", 0, 0, 0 },
152 { ALIGN_LEFT, "Send-Q", " ", 0, 0, 0 },
153 { ALIGN_RIGHT, "Local Address:", " ", 0, 0, 0 },
154 { ALIGN_LEFT, "Port", "", 0, 0, 0 },
155 { ALIGN_RIGHT, "Peer Address:", " ", 0, 0, 0 },
156 { ALIGN_LEFT, "Port", "", 0, 0, 0 },
5883c6eb 157 { ALIGN_LEFT, "Process", "", 0, 0, 0 },
87b1a7ae 158 { ALIGN_LEFT, "", "", 0, 0, 0 },
59f46b7b
SB
159};
160
161static struct column *current_field = columns;
691bd854
SB
162
163/* Output buffer: chained chunks of BUF_CHUNK bytes. Each field is written to
164 * the buffer as a variable size token. A token consists of a 16 bits length
165 * field, followed by a string which is not NULL-terminated.
166 *
167 * A new chunk is allocated and linked when the current chunk doesn't have
168 * enough room to store the current token as a whole.
169 */
170struct buf_chunk {
171 struct buf_chunk *next; /* Next chained chunk */
172 char *end; /* Current end of content */
173 char data[0];
174};
175
176struct buf_token {
177 uint16_t len; /* Data length, excluding length descriptor */
178 char data[0];
179};
180
181static struct {
182 struct buf_token *cur; /* Position of current token in chunk */
183 struct buf_chunk *head; /* First chunk */
184 struct buf_chunk *tail; /* Current chunk */
aa5bd6a2 185 int chunks; /* Number of allocated chunks */
691bd854 186} buffer;
aba5acdf
SH
187
188static const char *TCP_PROTO = "tcp";
f89d46ad 189static const char *SCTP_PROTO = "sctp";
aba5acdf
SH
190static const char *UDP_PROTO = "udp";
191static const char *RAW_PROTO = "raw";
acd1e437 192static const char *dg_proto;
aba5acdf 193
acd1e437 194enum {
aba5acdf 195 TCP_DB,
9c3be2c0 196 MPTCP_DB,
351efcde 197 DCCP_DB,
aba5acdf
SH
198 UDP_DB,
199 RAW_DB,
200 UNIX_DG_DB,
201 UNIX_ST_DB,
30b669d7 202 UNIX_SQ_DB,
aba5acdf
SH
203 PACKET_DG_DB,
204 PACKET_R_DB,
205 NETLINK_DB,
f89d46ad 206 SCTP_DB,
c759116a
SH
207 VSOCK_ST_DB,
208 VSOCK_DG_DB,
5caf79a0 209 TIPC_DB,
2abc3d76 210 XDP_DB,
aba5acdf
SH
211 MAX_DB
212};
213
214#define PACKET_DBM ((1<<PACKET_DG_DB)|(1<<PACKET_R_DB))
30b669d7 215#define UNIX_DBM ((1<<UNIX_DG_DB)|(1<<UNIX_ST_DB)|(1<<UNIX_SQ_DB))
aba5acdf 216#define ALL_DB ((1<<MAX_DB)-1)
9c3be2c0 217#define INET_L4_DBM ((1<<TCP_DB)|(1<<MPTCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB)|(1<<SCTP_DB))
168d97f9 218#define INET_DBM (INET_L4_DBM | (1<<RAW_DB))
c759116a 219#define VSOCK_DBM ((1<<VSOCK_ST_DB)|(1<<VSOCK_DG_DB))
aba5acdf
SH
220
221enum {
7d105b56
SH
222 SS_UNKNOWN,
223 SS_ESTABLISHED,
224 SS_SYN_SENT,
225 SS_SYN_RECV,
226 SS_FIN_WAIT1,
227 SS_FIN_WAIT2,
228 SS_TIME_WAIT,
229 SS_CLOSE,
230 SS_CLOSE_WAIT,
231 SS_LAST_ACK,
232 SS_LISTEN,
233 SS_CLOSING,
234 SS_MAX
aba5acdf
SH
235};
236
f89d46ad
PS
237enum {
238 SCTP_STATE_CLOSED = 0,
239 SCTP_STATE_COOKIE_WAIT = 1,
240 SCTP_STATE_COOKIE_ECHOED = 2,
241 SCTP_STATE_ESTABLISHED = 3,
242 SCTP_STATE_SHUTDOWN_PENDING = 4,
243 SCTP_STATE_SHUTDOWN_SENT = 5,
244 SCTP_STATE_SHUTDOWN_RECEIVED = 6,
245 SCTP_STATE_SHUTDOWN_ACK_SENT = 7,
246};
247
9db7bf15
VK
248#define SS_ALL ((1 << SS_MAX) - 1)
249#define SS_CONN (SS_ALL & ~((1<<SS_LISTEN)|(1<<SS_CLOSE)|(1<<SS_TIME_WAIT)|(1<<SS_SYN_RECV)))
5caf79a0 250#define TIPC_SS_CONN ((1<<SS_ESTABLISHED)|(1<<SS_LISTEN)|(1<<SS_CLOSE))
aba5acdf
SH
251
252#include "ssfilter.h"
253
acd1e437 254struct filter {
aba5acdf
SH
255 int dbs;
256 int states;
b338a3e7 257 uint64_t families;
aba5acdf 258 struct ssfilter *f;
fb2594c1 259 bool kill;
97352f1b 260 struct rtnl_handle *rth_for_killing;
aba5acdf
SH
261};
262
b338a3e7
SH
263#define FAMILY_MASK(family) ((uint64_t)1 << (family))
264
9db7bf15
VK
265static const struct filter default_dbs[MAX_DB] = {
266 [TCP_DB] = {
267 .states = SS_CONN,
b338a3e7 268 .families = FAMILY_MASK(AF_INET) | FAMILY_MASK(AF_INET6),
9db7bf15 269 },
9c3be2c0
PA
270 [MPTCP_DB] = {
271 .states = SS_CONN,
272 .families = FAMILY_MASK(AF_INET) | FAMILY_MASK(AF_INET6),
273 },
9db7bf15
VK
274 [DCCP_DB] = {
275 .states = SS_CONN,
b338a3e7 276 .families = FAMILY_MASK(AF_INET) | FAMILY_MASK(AF_INET6),
9db7bf15
VK
277 },
278 [UDP_DB] = {
f42a4574 279 .states = (1 << SS_ESTABLISHED),
b338a3e7 280 .families = FAMILY_MASK(AF_INET) | FAMILY_MASK(AF_INET6),
9db7bf15
VK
281 },
282 [RAW_DB] = {
f42a4574 283 .states = (1 << SS_ESTABLISHED),
b338a3e7 284 .families = FAMILY_MASK(AF_INET) | FAMILY_MASK(AF_INET6),
9db7bf15
VK
285 },
286 [UNIX_DG_DB] = {
287 .states = (1 << SS_CLOSE),
b338a3e7 288 .families = FAMILY_MASK(AF_UNIX),
9db7bf15
VK
289 },
290 [UNIX_ST_DB] = {
291 .states = SS_CONN,
b338a3e7 292 .families = FAMILY_MASK(AF_UNIX),
9db7bf15
VK
293 },
294 [UNIX_SQ_DB] = {
295 .states = SS_CONN,
b338a3e7 296 .families = FAMILY_MASK(AF_UNIX),
9db7bf15
VK
297 },
298 [PACKET_DG_DB] = {
299 .states = (1 << SS_CLOSE),
b338a3e7 300 .families = FAMILY_MASK(AF_PACKET),
9db7bf15
VK
301 },
302 [PACKET_R_DB] = {
303 .states = (1 << SS_CLOSE),
b338a3e7 304 .families = FAMILY_MASK(AF_PACKET),
9db7bf15
VK
305 },
306 [NETLINK_DB] = {
307 .states = (1 << SS_CLOSE),
b338a3e7 308 .families = FAMILY_MASK(AF_NETLINK),
9db7bf15 309 },
f89d46ad
PS
310 [SCTP_DB] = {
311 .states = SS_CONN,
b338a3e7 312 .families = FAMILY_MASK(AF_INET) | FAMILY_MASK(AF_INET6),
f89d46ad 313 },
c759116a
SH
314 [VSOCK_ST_DB] = {
315 .states = SS_CONN,
316 .families = FAMILY_MASK(AF_VSOCK),
317 },
318 [VSOCK_DG_DB] = {
319 .states = SS_CONN,
320 .families = FAMILY_MASK(AF_VSOCK),
321 },
5caf79a0
GM
322 [TIPC_DB] = {
323 .states = TIPC_SS_CONN,
324 .families = FAMILY_MASK(AF_TIPC),
325 },
2abc3d76
BT
326 [XDP_DB] = {
327 .states = (1 << SS_CLOSE),
328 .families = FAMILY_MASK(AF_XDP),
329 },
aba5acdf
SH
330};
331
9db7bf15
VK
332static const struct filter default_afs[AF_MAX] = {
333 [AF_INET] = {
334 .dbs = INET_DBM,
335 .states = SS_CONN,
336 },
337 [AF_INET6] = {
338 .dbs = INET_DBM,
339 .states = SS_CONN,
340 },
341 [AF_UNIX] = {
342 .dbs = UNIX_DBM,
343 .states = SS_CONN,
344 },
345 [AF_PACKET] = {
346 .dbs = PACKET_DBM,
347 .states = (1 << SS_CLOSE),
348 },
349 [AF_NETLINK] = {
350 .dbs = (1 << NETLINK_DB),
351 .states = (1 << SS_CLOSE),
352 },
c759116a
SH
353 [AF_VSOCK] = {
354 .dbs = VSOCK_DBM,
355 .states = SS_CONN,
356 },
5caf79a0
GM
357 [AF_TIPC] = {
358 .dbs = (1 << TIPC_DB),
359 .states = TIPC_SS_CONN,
360 },
2abc3d76
BT
361 [AF_XDP] = {
362 .dbs = (1 << XDP_DB),
363 .states = (1 << SS_CLOSE),
364 },
9db7bf15
VK
365};
366
367static int do_default = 1;
368static struct filter current_filter;
369
c121111e 370static void filter_db_set(struct filter *f, int db, bool enable)
9db7bf15 371{
c121111e
PS
372 if (enable) {
373 f->states |= default_dbs[db].states;
374 f->dbs |= 1 << db;
375 } else {
376 f->dbs &= ~(1 << db);
377 }
9db7bf15
VK
378 do_default = 0;
379}
380
67d5fd55
PS
381static int filter_db_parse(struct filter *f, const char *s)
382{
383 const struct {
384 const char *name;
385 int dbs[MAX_DB + 1];
386 } db_name_tbl[] = {
387#define ENTRY(name, ...) { #name, { __VA_ARGS__, MAX_DB } }
9c3be2c0 388 ENTRY(all, UDP_DB, DCCP_DB, TCP_DB, MPTCP_DB, RAW_DB,
67d5fd55
PS
389 UNIX_ST_DB, UNIX_DG_DB, UNIX_SQ_DB,
390 PACKET_R_DB, PACKET_DG_DB, NETLINK_DB,
2abc3d76 391 SCTP_DB, VSOCK_ST_DB, VSOCK_DG_DB, XDP_DB),
9c3be2c0 392 ENTRY(inet, UDP_DB, DCCP_DB, TCP_DB, MPTCP_DB, SCTP_DB, RAW_DB),
67d5fd55
PS
393 ENTRY(udp, UDP_DB),
394 ENTRY(dccp, DCCP_DB),
395 ENTRY(tcp, TCP_DB),
9c3be2c0 396 ENTRY(mptcp, MPTCP_DB),
67d5fd55
PS
397 ENTRY(sctp, SCTP_DB),
398 ENTRY(raw, RAW_DB),
399 ENTRY(unix, UNIX_ST_DB, UNIX_DG_DB, UNIX_SQ_DB),
400 ENTRY(unix_stream, UNIX_ST_DB),
401 ENTRY(u_str, UNIX_ST_DB), /* alias for unix_stream */
402 ENTRY(unix_dgram, UNIX_DG_DB),
403 ENTRY(u_dgr, UNIX_DG_DB), /* alias for unix_dgram */
404 ENTRY(unix_seqpacket, UNIX_SQ_DB),
405 ENTRY(u_seq, UNIX_SQ_DB), /* alias for unix_seqpacket */
406 ENTRY(packet, PACKET_R_DB, PACKET_DG_DB),
407 ENTRY(packet_raw, PACKET_R_DB),
408 ENTRY(p_raw, PACKET_R_DB), /* alias for packet_raw */
409 ENTRY(packet_dgram, PACKET_DG_DB),
410 ENTRY(p_dgr, PACKET_DG_DB), /* alias for packet_dgram */
411 ENTRY(netlink, NETLINK_DB),
412 ENTRY(vsock, VSOCK_ST_DB, VSOCK_DG_DB),
413 ENTRY(vsock_stream, VSOCK_ST_DB),
414 ENTRY(v_str, VSOCK_ST_DB), /* alias for vsock_stream */
415 ENTRY(vsock_dgram, VSOCK_DG_DB),
416 ENTRY(v_dgr, VSOCK_DG_DB), /* alias for vsock_dgram */
2abc3d76 417 ENTRY(xdp, XDP_DB),
67d5fd55
PS
418#undef ENTRY
419 };
420 bool enable = true;
421 unsigned int i;
422 const int *dbp;
423
424 if (s[0] == '!') {
425 enable = false;
426 s++;
427 }
428 for (i = 0; i < ARRAY_SIZE(db_name_tbl); i++) {
429 if (strcmp(s, db_name_tbl[i].name))
430 continue;
431 for (dbp = db_name_tbl[i].dbs; *dbp != MAX_DB; dbp++)
432 filter_db_set(f, *dbp, enable);
433 return 0;
434 }
435 return -1;
436}
437
9db7bf15
VK
438static void filter_af_set(struct filter *f, int af)
439{
1527a17e 440 f->states |= default_afs[af].states;
b338a3e7 441 f->families |= FAMILY_MASK(af);
1527a17e
VK
442 do_default = 0;
443 preferred_family = af;
9db7bf15
VK
444}
445
446static int filter_af_get(struct filter *f, int af)
447{
b338a3e7 448 return !!(f->families & FAMILY_MASK(af));
9db7bf15
VK
449}
450
57ff5a10 451static void filter_states_set(struct filter *f, int states)
9db7bf15 452{
57ff5a10 453 if (states)
9d320e1e 454 f->states = states;
57ff5a10 455}
9db7bf15 456
57ff5a10
VK
457static void filter_merge_defaults(struct filter *f)
458{
459 int db;
460 int af;
9db7bf15 461
57ff5a10
VK
462 for (db = 0; db < MAX_DB; db++) {
463 if (!(f->dbs & (1 << db)))
464 continue;
9db7bf15 465
57ff5a10
VK
466 if (!(default_dbs[db].families & f->families))
467 f->families |= default_dbs[db].families;
468 }
469 for (af = 0; af < AF_MAX; af++) {
b338a3e7 470 if (!(f->families & FAMILY_MASK(af)))
57ff5a10
VK
471 continue;
472
473 if (!(default_afs[af].dbs & f->dbs))
474 f->dbs |= default_afs[af].dbs;
475 }
9db7bf15 476}
aba5acdf 477
ab01dbbb 478static FILE *generic_proc_open(const char *env, const char *name)
aba5acdf 479{
ab01dbbb 480 const char *p = getenv(env);
aba5acdf 481 char store[128];
ab01dbbb 482
aba5acdf
SH
483 if (!p) {
484 p = getenv("PROC_ROOT") ? : "/proc";
485 snprintf(store, sizeof(store)-1, "%s/%s", p, name);
486 p = store;
487 }
ab01dbbb
SH
488
489 return fopen(p, "r");
aba5acdf 490}
0cb74a86
PS
491#define net_tcp_open() generic_proc_open("PROC_NET_TCP", "net/tcp")
492#define net_tcp6_open() generic_proc_open("PROC_NET_TCP6", "net/tcp6")
493#define net_udp_open() generic_proc_open("PROC_NET_UDP", "net/udp")
494#define net_udp6_open() generic_proc_open("PROC_NET_UDP6", "net/udp6")
495#define net_raw_open() generic_proc_open("PROC_NET_RAW", "net/raw")
496#define net_raw6_open() generic_proc_open("PROC_NET_RAW6", "net/raw6")
497#define net_unix_open() generic_proc_open("PROC_NET_UNIX", "net/unix")
498#define net_packet_open() generic_proc_open("PROC_NET_PACKET", \
499 "net/packet")
500#define net_netlink_open() generic_proc_open("PROC_NET_NETLINK", \
501 "net/netlink")
0cb74a86
PS
502#define net_sockstat_open() generic_proc_open("PROC_NET_SOCKSTAT", \
503 "net/sockstat")
504#define net_sockstat6_open() generic_proc_open("PROC_NET_SOCKSTAT6", \
505 "net/sockstat6")
506#define net_snmp_open() generic_proc_open("PROC_NET_SNMP", "net/snmp")
507#define ephemeral_ports_open() generic_proc_open("PROC_IP_LOCAL_PORT_RANGE", \
508 "sys/net/ipv4/ip_local_port_range")
aba5acdf 509
fbc0f876
SF
510struct user_ent {
511 struct user_ent *next;
512 unsigned int ino;
513 int pid;
514 int fd;
116ac927
RH
515 char *process;
516 char *process_ctx;
517 char *socket_ctx;
fbc0f876
SF
518};
519
520#define USER_ENT_HASH_SIZE 256
3f7bd0fd 521static struct user_ent *user_ent_hash[USER_ENT_HASH_SIZE];
fbc0f876
SF
522
523static int user_ent_hashfn(unsigned int ino)
aba5acdf 524{
fbc0f876 525 int val = (ino >> 24) ^ (ino >> 16) ^ (ino >> 8) ^ ino;
aba5acdf 526
fbc0f876
SF
527 return val & (USER_ENT_HASH_SIZE - 1);
528}
529
116ac927
RH
530static void user_ent_add(unsigned int ino, char *process,
531 int pid, int fd,
532 char *proc_ctx,
533 char *sock_ctx)
fbc0f876
SF
534{
535 struct user_ent *p, **pp;
aba5acdf 536
116ac927
RH
537 p = malloc(sizeof(struct user_ent));
538 if (!p) {
539 fprintf(stderr, "ss: failed to malloc buffer\n");
fbc0f876 540 abort();
116ac927 541 }
fbc0f876
SF
542 p->next = NULL;
543 p->ino = ino;
544 p->pid = pid;
545 p->fd = fd;
116ac927
RH
546 p->process = strdup(process);
547 p->process_ctx = strdup(proc_ctx);
548 p->socket_ctx = strdup(sock_ctx);
fbc0f876
SF
549
550 pp = &user_ent_hash[user_ent_hashfn(ino)];
551 p->next = *pp;
552 *pp = p;
553}
aba5acdf 554
116ac927
RH
555static void user_ent_destroy(void)
556{
557 struct user_ent *p, *p_next;
558 int cnt = 0;
559
560 while (cnt != USER_ENT_HASH_SIZE) {
561 p = user_ent_hash[cnt];
562 while (p) {
563 free(p->process);
564 free(p->process_ctx);
565 free(p->socket_ctx);
566 p_next = p->next;
567 free(p);
568 p = p_next;
569 }
570 cnt++;
571 }
572}
573
fbc0f876
SF
574static void user_ent_hash_build(void)
575{
576 const char *root = getenv("PROC_ROOT") ? : "/proc/";
577 struct dirent *d;
578 char name[1024];
579 int nameoff;
580 DIR *dir;
116ac927
RH
581 char *pid_context;
582 char *sock_context;
583 const char *no_ctx = "unavailable";
b25bad2f 584 static int user_ent_hash_build_init;
116ac927
RH
585
586 /* If show_users & show_proc_ctx set only do this once */
587 if (user_ent_hash_build_init != 0)
588 return;
589
590 user_ent_hash_build_init = 1;
fbc0f876 591
18f156bf 592 strlcpy(name, root, sizeof(name));
0ee9052f 593
fbc0f876 594 if (strlen(name) == 0 || name[strlen(name)-1] != '/')
aba5acdf 595 strcat(name, "/");
fbc0f876 596
aba5acdf 597 nameoff = strlen(name);
fbc0f876
SF
598
599 dir = opendir(name);
600 if (!dir)
601 return;
aba5acdf
SH
602
603 while ((d = readdir(dir)) != NULL) {
aba5acdf 604 struct dirent *d1;
aba5acdf 605 char process[16];
116ac927 606 char *p;
fbc0f876
SF
607 int pid, pos;
608 DIR *dir1;
609 char crap;
aba5acdf
SH
610
611 if (sscanf(d->d_name, "%d%c", &pid, &crap) != 1)
612 continue;
613
116ac927
RH
614 if (getpidcon(pid, &pid_context) != 0)
615 pid_context = strdup(no_ctx);
616
0ee9052f 617 snprintf(name + nameoff, sizeof(name) - nameoff, "%d/fd/", pid);
aba5acdf 618 pos = strlen(name);
a02371fb
PS
619 if ((dir1 = opendir(name)) == NULL) {
620 free(pid_context);
aba5acdf 621 continue;
a02371fb 622 }
aba5acdf 623
fbc0f876 624 process[0] = '\0';
116ac927 625 p = process;
aba5acdf
SH
626
627 while ((d1 = readdir(dir1)) != NULL) {
fbc0f876
SF
628 const char *pattern = "socket:[";
629 unsigned int ino;
aba5acdf 630 char lnk[64];
18445b3e 631 int fd;
788731b3 632 ssize_t link_len;
116ac927 633 char tmp[1024];
aba5acdf
SH
634
635 if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1)
636 continue;
637
0ee9052f 638 snprintf(name+pos, sizeof(name) - pos, "%d", fd);
788731b3
TJ
639
640 link_len = readlink(name, lnk, sizeof(lnk)-1);
641 if (link_len == -1)
642 continue;
643 lnk[link_len] = '\0';
644
645 if (strncmp(lnk, pattern, strlen(pattern)))
aba5acdf
SH
646 continue;
647
fbc0f876 648 sscanf(lnk, "socket:[%u]", &ino);
aba5acdf 649
116ac927
RH
650 snprintf(tmp, sizeof(tmp), "%s/%d/fd/%s",
651 root, pid, d1->d_name);
652
653 if (getfilecon(tmp, &sock_context) <= 0)
654 sock_context = strdup(no_ctx);
655
656 if (*p == '\0') {
aba5acdf 657 FILE *fp;
fbc0f876 658
116ac927
RH
659 snprintf(tmp, sizeof(tmp), "%s/%d/stat",
660 root, pid);
aba5acdf 661 if ((fp = fopen(tmp, "r")) != NULL) {
d572ed4d
PS
662 if (fscanf(fp, "%*d (%[^)])", p) < 1)
663 ; /* ignore */
aba5acdf
SH
664 fclose(fp);
665 }
666 }
116ac927
RH
667 user_ent_add(ino, p, pid, fd,
668 pid_context, sock_context);
669 free(sock_context);
aba5acdf 670 }
116ac927 671 free(pid_context);
aba5acdf
SH
672 closedir(dir1);
673 }
674 closedir(dir);
fbc0f876
SF
675}
676
116ac927
RH
677enum entry_types {
678 USERS,
679 PROC_CTX,
680 PROC_SOCK_CTX
681};
682
683#define ENTRY_BUF_SIZE 512
acd1e437 684static int find_entry(unsigned int ino, char **buf, int type)
fbc0f876
SF
685{
686 struct user_ent *p;
687 int cnt = 0;
688 char *ptr;
532ca40a 689 char *new_buf;
116ac927
RH
690 int len, new_buf_len;
691 int buf_used = 0;
692 int buf_len = 0;
fbc0f876
SF
693
694 if (!ino)
695 return 0;
696
697 p = user_ent_hash[user_ent_hashfn(ino)];
116ac927 698 ptr = *buf = NULL;
fbc0f876
SF
699 while (p) {
700 if (p->ino != ino)
701 goto next;
702
116ac927
RH
703 while (1) {
704 ptr = *buf + buf_used;
705 switch (type) {
706 case USERS:
707 len = snprintf(ptr, buf_len - buf_used,
708 "(\"%s\",pid=%d,fd=%d),",
709 p->process, p->pid, p->fd);
710 break;
711 case PROC_CTX:
712 len = snprintf(ptr, buf_len - buf_used,
713 "(\"%s\",pid=%d,proc_ctx=%s,fd=%d),",
714 p->process, p->pid,
715 p->process_ctx, p->fd);
716 break;
717 case PROC_SOCK_CTX:
718 len = snprintf(ptr, buf_len - buf_used,
719 "(\"%s\",pid=%d,proc_ctx=%s,fd=%d,sock_ctx=%s),",
720 p->process, p->pid,
721 p->process_ctx, p->fd,
722 p->socket_ctx);
723 break;
724 default:
725 fprintf(stderr, "ss: invalid type: %d\n", type);
726 abort();
727 }
fbc0f876 728
116ac927
RH
729 if (len < 0 || len >= buf_len - buf_used) {
730 new_buf_len = buf_len + ENTRY_BUF_SIZE;
532ca40a 731 new_buf = realloc(*buf, new_buf_len);
116ac927
RH
732 if (!new_buf) {
733 fprintf(stderr, "ss: failed to malloc buffer\n");
734 abort();
735 }
532ca40a 736 *buf = new_buf;
116ac927
RH
737 buf_len = new_buf_len;
738 continue;
739 } else {
740 buf_used += len;
741 break;
742 }
743 }
fbc0f876 744 cnt++;
116ac927 745next:
fbc0f876
SF
746 p = p->next;
747 }
116ac927
RH
748 if (buf_used) {
749 ptr = *buf + buf_used;
fbc0f876 750 ptr[-1] = '\0';
116ac927 751 }
aba5acdf
SH
752 return cnt;
753}
754
2e7e805d 755static unsigned long long cookie_sk_get(const uint32_t *cookie)
f1b39e1b 756{
2e7e805d 757 return (((unsigned long long)cookie[1] << 31) << 1) | cookie[0];
f1b39e1b
VK
758}
759
f89d46ad
PS
760static const char *sctp_sstate_name[] = {
761 [SCTP_STATE_CLOSED] = "CLOSED",
762 [SCTP_STATE_COOKIE_WAIT] = "COOKIE_WAIT",
763 [SCTP_STATE_COOKIE_ECHOED] = "COOKIE_ECHOED",
764 [SCTP_STATE_ESTABLISHED] = "ESTAB",
765 [SCTP_STATE_SHUTDOWN_PENDING] = "SHUTDOWN_PENDING",
766 [SCTP_STATE_SHUTDOWN_SENT] = "SHUTDOWN_SENT",
767 [SCTP_STATE_SHUTDOWN_RECEIVED] = "SHUTDOWN_RECEIVED",
768 [SCTP_STATE_SHUTDOWN_ACK_SENT] = "ACK_SENT",
769};
770
5caf79a0
GM
771static const char * const stype_nameg[] = {
772 "UNKNOWN",
773 [SOCK_STREAM] = "STREAM",
774 [SOCK_DGRAM] = "DGRAM",
775 [SOCK_RDM] = "RDM",
776 [SOCK_SEQPACKET] = "SEQPACKET",
777};
778
acd1e437 779struct sockstat {
ec4d0d8a
VK
780 struct sockstat *next;
781 unsigned int type;
89f634f9 782 uint16_t prot;
41fe6c34 783 uint16_t raw_prot;
8250bc9f
VK
784 inet_prefix local;
785 inet_prefix remote;
786 int lport;
787 int rport;
788 int state;
789 int rq, wq;
acd1e437
SH
790 unsigned int ino;
791 unsigned int uid;
8250bc9f
VK
792 int refcnt;
793 unsigned int iface;
794 unsigned long long sk;
99bb68ff
VK
795 char *name;
796 char *peer_name;
ec75249b 797 __u32 mark;
14f4bda5 798 __u64 cgroup_id;
055840f2
VK
799};
800
acd1e437 801struct dctcpstat {
055840f2
VK
802 unsigned int ce_state;
803 unsigned int alpha;
804 unsigned int ab_ecn;
805 unsigned int ab_tot;
806 bool enabled;
807};
808
acd1e437 809struct tcpstat {
055840f2 810 struct sockstat ss;
4cbf5224
PS
811 unsigned int timer;
812 unsigned int timeout;
8250bc9f 813 int probes;
d2055ea5 814 char cong_alg[16];
8250bc9f 815 double rto, ato, rtt, rttvar;
d1f338b3 816 int qack, ssthresh, backoff;
8250bc9f
VK
817 double send_bps;
818 int snd_wscale;
819 int rcv_wscale;
820 int mss;
38e6dbc4
ED
821 int rcv_mss;
822 int advmss;
3d791a32 823 unsigned int pmtu;
d1f338b3 824 unsigned int cwnd;
8250bc9f
VK
825 unsigned int lastsnd;
826 unsigned int lastrcv;
827 unsigned int lastack;
828 double pacing_rate;
829 double pacing_rate_max;
2f579872 830 double delivery_rate;
1a4dda71
ED
831 unsigned long long bytes_acked;
832 unsigned long long bytes_received;
ecb435ea
CG
833 unsigned int segs_out;
834 unsigned int segs_in;
414aeec9
MKL
835 unsigned int data_segs_out;
836 unsigned int data_segs_in;
8250bc9f
VK
837 unsigned int unacked;
838 unsigned int retrans;
839 unsigned int retrans_total;
840 unsigned int lost;
841 unsigned int sacked;
842 unsigned int fackets;
843 unsigned int reordering;
9e99e495 844 unsigned int not_sent;
2f4d834b
ED
845 unsigned int delivered;
846 unsigned int delivered_ce;
5eead627
ED
847 unsigned int dsack_dups;
848 unsigned int reord_seen;
8250bc9f 849 double rcv_rtt;
9e99e495 850 double min_rtt;
8250bc9f 851 int rcv_space;
00ac78d3 852 unsigned int rcv_ssthresh;
b6c7fc61
YC
853 unsigned long long busy_time;
854 unsigned long long rwnd_limited;
855 unsigned long long sndbuf_limited;
5eead627
ED
856 unsigned long long bytes_sent;
857 unsigned long long bytes_retrans;
8250bc9f
VK
858 bool has_ts_opt;
859 bool has_sack_opt;
860 bool has_ecn_opt;
861 bool has_ecnseen_opt;
862 bool has_fastopen_opt;
863 bool has_wscale_opt;
2f579872 864 bool app_limited;
8250bc9f 865 struct dctcpstat *dctcp;
2f0f9aef 866 struct tcp_bbr_info *bbr_info;
aba5acdf
SH
867};
868
f89d46ad
PS
869/* SCTP assocs share the same inode number with their parent endpoint. So if we
870 * have seen the inode number before, it must be an assoc instead of the next
871 * endpoint. */
872static bool is_sctp_assoc(struct sockstat *s, const char *sock_name)
873{
874 if (strcmp(sock_name, "sctp"))
875 return false;
876 if (!sctp_ino || sctp_ino != s->ino)
877 return false;
878 return true;
879}
880
be7e4d20
PS
881static const char *unix_netid_name(int type)
882{
883 switch (type) {
884 case SOCK_STREAM:
885 return "u_str";
886 case SOCK_SEQPACKET:
887 return "u_seq";
888 case SOCK_DGRAM:
889 default:
890 return "u_dgr";
891 }
892}
893
894static const char *proto_name(int protocol)
2d791bc8 895{
be7e4d20
PS
896 switch (protocol) {
897 case 0:
898 return "raw";
899 case IPPROTO_UDP:
900 return "udp";
901 case IPPROTO_TCP:
902 return "tcp";
9c3be2c0
PA
903 case IPPROTO_MPTCP:
904 return "mptcp";
be7e4d20
PS
905 case IPPROTO_SCTP:
906 return "sctp";
907 case IPPROTO_DCCP:
908 return "dccp";
572e8936
PS
909 case IPPROTO_ICMPV6:
910 return "icmp6";
be7e4d20
PS
911 }
912
913 return "???";
914}
915
c759116a
SH
916static const char *vsock_netid_name(int type)
917{
918 switch (type) {
919 case SOCK_STREAM:
920 return "v_str";
921 case SOCK_DGRAM:
922 return "v_dgr";
923 default:
924 return "???";
925 }
926}
927
5caf79a0
GM
928static const char *tipc_netid_name(int type)
929{
930 switch (type) {
931 case SOCK_STREAM:
932 return "ti_st";
933 case SOCK_DGRAM:
934 return "ti_dg";
935 case SOCK_RDM:
936 return "ti_rd";
937 case SOCK_SEQPACKET:
938 return "ti_sq";
939 default:
940 return "???";
941 }
942}
943
691bd854
SB
944/* Allocate and initialize a new buffer chunk */
945static struct buf_chunk *buf_chunk_new(void)
946{
947 struct buf_chunk *new = malloc(BUF_CHUNK);
948
949 if (!new)
950 abort();
951
952 new->next = NULL;
953
954 /* This is also the last block */
955 buffer.tail = new;
956
957 /* Next token will be stored at the beginning of chunk data area, and
958 * its initial length is zero.
959 */
960 buffer.cur = (struct buf_token *)new->data;
961 buffer.cur->len = 0;
962
963 new->end = buffer.cur->data;
964
aa5bd6a2
SB
965 buffer.chunks++;
966
691bd854
SB
967 return new;
968}
969
970/* Return available tail room in given chunk */
971static int buf_chunk_avail(struct buf_chunk *chunk)
972{
973 return BUF_CHUNK - offsetof(struct buf_chunk, data) -
974 (chunk->end - chunk->data);
975}
976
977/* Update end pointer and token length, link new chunk if we hit the end of the
978 * current one. Return -EAGAIN if we got a new chunk, caller has to print again.
979 */
980static int buf_update(int len)
981{
982 struct buf_chunk *chunk = buffer.tail;
983 struct buf_token *t = buffer.cur;
984
985 /* Claim success if new content fits in the current chunk, and anyway
986 * if this is the first token in the chunk: in the latter case,
987 * allocating a new chunk won't help, so we'll just cut the output.
988 */
989 if ((len < buf_chunk_avail(chunk) && len != -1 /* glibc < 2.0.6 */) ||
990 t == (struct buf_token *)chunk->data) {
991 len = min(len, buf_chunk_avail(chunk));
992
993 /* Total field length can't exceed 2^16 bytes, cut as needed */
994 len = min(len, USHRT_MAX - t->len);
995
996 chunk->end += len;
997 t->len += len;
998 return 0;
999 }
1000
1001 /* Content truncated, time to allocate more */
1002 chunk->next = buf_chunk_new();
1003
1004 /* Copy current token over to new chunk, including length descriptor */
1005 memcpy(chunk->next->data, t, sizeof(t->len) + t->len);
1006 chunk->next->end += t->len;
1007
1008 /* Discard partially written field in old chunk */
1009 chunk->end -= t->len + sizeof(t->len);
1010
1011 return -EAGAIN;
1012}
1013
1014/* Append content to buffer as part of the current field */
5d5586b0 1015__attribute__((format(printf, 1, 2)))
90351722
SB
1016static void out(const char *fmt, ...)
1017{
59f46b7b 1018 struct column *f = current_field;
90351722 1019 va_list args;
691bd854
SB
1020 char *pos;
1021 int len;
1022
87b1a7ae 1023 if (f->disabled)
691bd854
SB
1024 return;
1025
1026 if (!buffer.head)
1027 buffer.head = buf_chunk_new();
1028
1029again: /* Append to buffer: if we have a new chunk, print again */
90351722 1030
691bd854 1031 pos = buffer.cur->data + buffer.cur->len;
90351722 1032 va_start(args, fmt);
691bd854
SB
1033
1034 /* Limit to tail room. If we hit the limit, buf_update() will tell us */
1035 len = vsnprintf(pos, buf_chunk_avail(buffer.tail), fmt, args);
90351722 1036 va_end(args);
691bd854
SB
1037
1038 if (buf_update(len))
1039 goto again;
90351722
SB
1040}
1041
691bd854 1042static int print_left_spacing(struct column *f, int stored, int printed)
59f46b7b
SB
1043{
1044 int s;
1045
87b1a7ae 1046 if (!f->width || f->align == ALIGN_LEFT)
59f46b7b
SB
1047 return 0;
1048
691bd854 1049 s = f->width - stored - printed;
59f46b7b
SB
1050 if (f->align == ALIGN_CENTER)
1051 /* If count of total spacing is odd, shift right by one */
1052 s = (s + 1) / 2;
1053
1054 if (s > 0)
1055 return printf("%*c", s, ' ');
1056
1057 return 0;
1058}
1059
691bd854 1060static void print_right_spacing(struct column *f, int printed)
59f46b7b
SB
1061{
1062 int s;
1063
87b1a7ae 1064 if (!f->width || f->align == ALIGN_RIGHT)
59f46b7b
SB
1065 return;
1066
691bd854 1067 s = f->width - printed;
59f46b7b
SB
1068 if (f->align == ALIGN_CENTER)
1069 s /= 2;
1070
1071 if (s > 0)
1072 printf("%*c", s, ' ');
1073}
1074
691bd854 1075/* Done with field: update buffer pointer, start new token after current one */
59f46b7b
SB
1076static void field_flush(struct column *f)
1077{
192be8fc
AQ
1078 struct buf_chunk *chunk;
1079 unsigned int pad;
691bd854 1080
87b1a7ae 1081 if (f->disabled)
59f46b7b
SB
1082 return;
1083
192be8fc
AQ
1084 chunk = buffer.tail;
1085 pad = buffer.cur->len % 2;
1086
87b1a7ae
SB
1087 if (buffer.cur->len > f->max_len)
1088 f->max_len = buffer.cur->len;
1089
691bd854
SB
1090 /* We need a new chunk if we can't store the next length descriptor.
1091 * Mind the gap between end of previous token and next aligned position
1092 * for length descriptor.
1093 */
1094 if (buf_chunk_avail(chunk) - pad < sizeof(buffer.cur->len)) {
1095 chunk->end += pad;
1096 chunk->next = buf_chunk_new();
1097 return;
1098 }
59f46b7b 1099
691bd854
SB
1100 buffer.cur = (struct buf_token *)(buffer.cur->data +
1101 LEN_ALIGN(buffer.cur->len));
1102 buffer.cur->len = 0;
1103 buffer.tail->end = buffer.cur->data;
59f46b7b
SB
1104}
1105
1106static int field_is_last(struct column *f)
1107{
1108 return f - columns == COL_MAX - 1;
1109}
1110
691bd854
SB
1111/* Get the next available token in the buffer starting from the current token */
1112static struct buf_token *buf_token_next(struct buf_token *cur)
1113{
1114 struct buf_chunk *chunk = buffer.tail;
1115
1116 /* If we reached the end of chunk contents, get token from next chunk */
1117 if (cur->data + LEN_ALIGN(cur->len) == chunk->end) {
1118 buffer.tail = chunk = chunk->next;
1119 return chunk ? (struct buf_token *)chunk->data : NULL;
1120 }
1121
1122 return (struct buf_token *)(cur->data + LEN_ALIGN(cur->len));
1123}
1124
1125/* Free up all allocated buffer chunks */
1126static void buf_free_all(void)
1127{
1128 struct buf_chunk *tmp;
1129
1130 for (buffer.tail = buffer.head; buffer.tail; ) {
1131 tmp = buffer.tail;
1132 buffer.tail = buffer.tail->next;
1133 free(tmp);
1134 }
1135 buffer.head = NULL;
aa5bd6a2 1136 buffer.chunks = 0;
691bd854
SB
1137}
1138
c4f58629 1139/* Get current screen width, returns -1 if TIOCGWINSZ fails */
32ea3d54
SB
1140static int render_screen_width(void)
1141{
c4f58629 1142 int width = -1;
32ea3d54
SB
1143
1144 if (isatty(STDOUT_FILENO)) {
1145 struct winsize w;
1146
1147 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
1148 if (w.ws_col > 0)
1149 width = w.ws_col;
1150 }
1151 }
1152
1153 return width;
1154}
1155
87b1a7ae
SB
1156/* Calculate column width from contents length. If columns don't fit on one
1157 * line, break them into the least possible amount of lines and keep them
1158 * aligned across lines. Available screen space is equally spread between fields
1159 * as additional spacing.
1160 */
32ea3d54 1161static void render_calc_width(void)
87b1a7ae 1162{
c4f58629 1163 int screen_width, first, len = 0, linecols = 0;
87b1a7ae 1164 struct column *c, *eol = columns - 1;
c4f58629
PJ
1165 bool compact_output = false;
1166
1167 screen_width = render_screen_width();
1168 if (screen_width == -1) {
1169 screen_width = INT_MAX;
1170 compact_output = true;
1171 }
87b1a7ae
SB
1172
1173 /* First pass: set width for each column to measured content length */
1174 for (first = 1, c = columns; c - columns < COL_MAX; c++) {
1175 if (c->disabled)
1176 continue;
1177
1178 if (!first && c->max_len)
1179 c->width = c->max_len + strlen(c->ldelim);
1180 else
1181 c->width = c->max_len;
1182
1183 /* But don't exceed screen size. If we exceed the screen size
1184 * for even a single field, it will just start on a line of its
1185 * own and then naturally wrap.
1186 */
1187 c->width = min(c->width, screen_width);
1188
1189 if (c->width)
1190 first = 0;
1191 }
1192
c4f58629
PJ
1193 if (compact_output) {
1194 /* Compact output, skip extending columns. */
1195 return;
1196 }
1197
87b1a7ae
SB
1198 /* Second pass: find out newlines and distribute available spacing */
1199 for (c = columns; c - columns < COL_MAX; c++) {
1200 int pad, spacing, rem, last;
1201 struct column *tmp;
1202
1203 if (!c->width)
1204 continue;
1205
1206 linecols++;
1207 len += c->width;
1208
1209 for (last = 1, tmp = c + 1; tmp - columns < COL_MAX; tmp++) {
1210 if (tmp->width) {
1211 last = 0;
1212 break;
1213 }
1214 }
1215
1216 if (!last && len < screen_width) {
1217 /* Columns fit on screen so far, nothing to do yet */
1218 continue;
1219 }
1220
1221 if (len == screen_width) {
1222 /* Exact fit, just start with new line */
1223 goto newline;
1224 }
1225
1226 if (len > screen_width) {
1227 /* Screen width exceeded: go back one column */
1228 len -= c->width;
1229 c--;
1230 linecols--;
1231 }
1232
1233 /* Distribute remaining space to columns on this line */
1234 pad = screen_width - len;
1235 spacing = pad / linecols;
1236 rem = pad % linecols;
1237 for (tmp = c; tmp > eol; tmp--) {
1238 if (!tmp->width)
1239 continue;
1240
1241 tmp->width += spacing;
1242 if (rem) {
1243 tmp->width++;
1244 rem--;
1245 }
1246 }
1247
1248newline:
1249 /* Line break: reset line counters, mark end-of-line */
1250 eol = c;
1251 len = 0;
1252 linecols = 0;
1253 }
1254}
1255
691bd854 1256/* Render buffered output with spacing and delimiters, then free up buffers */
32ea3d54 1257static void render(void)
691bd854 1258{
eb8559ef 1259 struct buf_token *token;
87b1a7ae 1260 int printed, line_started = 0;
691bd854
SB
1261 struct column *f;
1262
eb8559ef
JPB
1263 if (!buffer.head)
1264 return;
1265
1266 token = (struct buf_token *)buffer.head->data;
1267
691bd854
SB
1268 /* Ensure end alignment of last token, it wasn't necessarily flushed */
1269 buffer.tail->end += buffer.cur->len % 2;
1270
32ea3d54 1271 render_calc_width();
87b1a7ae 1272
691bd854
SB
1273 /* Rewind and replay */
1274 buffer.tail = buffer.head;
1275
1276 f = columns;
1277 while (!f->width)
1278 f++;
1279
1280 while (token) {
1281 /* Print left delimiter only if we already started a line */
1282 if (line_started++)
00240899 1283 printed = printf("%s", f->ldelim);
691bd854
SB
1284 else
1285 printed = 0;
1286
1287 /* Print field content from token data with spacing */
1288 printed += print_left_spacing(f, token->len, printed);
1289 printed += fwrite(token->data, 1, token->len, stdout);
1290 print_right_spacing(f, printed);
1291
691bd854
SB
1292 /* Go to next non-empty field, deal with end-of-line */
1293 do {
1294 if (field_is_last(f)) {
87b1a7ae 1295 printf("\n");
691bd854
SB
1296 f = columns;
1297 line_started = 0;
1298 } else {
1299 f++;
1300 }
87b1a7ae 1301 } while (f->disabled);
691bd854
SB
1302
1303 token = buf_token_next(token);
1304 }
9eee92a4
BV
1305 /* Deal with final end-of-line when the last non-empty field printed
1306 * is not the last field.
1307 */
1308 if (line_started)
1309 printf("\n");
691bd854
SB
1310
1311 buf_free_all();
32ea3d54 1312 current_field = columns;
691bd854
SB
1313}
1314
aa5bd6a2
SB
1315/* Move to next field, and render buffer if we reached the maximum number of
1316 * chunks, at the last field in a line.
1317 */
1318static void field_next(void)
1319{
1320 if (field_is_last(current_field) && buffer.chunks >= BUF_CHUNKS_MAX) {
1321 render();
1322 return;
1323 }
1324
1325 field_flush(current_field);
1326 if (field_is_last(current_field))
1327 current_field = columns;
1328 else
1329 current_field++;
1330}
1331
1332/* Walk through fields and flush them until we reach the desired one */
1333static void field_set(enum col_id id)
1334{
1335 while (id != current_field - columns)
1336 field_next();
1337}
1338
1339/* Print header for all non-empty columns */
1340static void print_header(void)
1341{
1342 while (!field_is_last(current_field)) {
1343 if (!current_field->disabled)
1344 out("%s", current_field->header);
1345 field_next();
1346 }
1347}
1348
be7e4d20
PS
1349static void sock_state_print(struct sockstat *s)
1350{
1351 const char *sock_name;
1882c0db
PS
1352 static const char * const sstate_name[] = {
1353 "UNKNOWN",
1354 [SS_ESTABLISHED] = "ESTAB",
1355 [SS_SYN_SENT] = "SYN-SENT",
1356 [SS_SYN_RECV] = "SYN-RECV",
1357 [SS_FIN_WAIT1] = "FIN-WAIT-1",
1358 [SS_FIN_WAIT2] = "FIN-WAIT-2",
1359 [SS_TIME_WAIT] = "TIME-WAIT",
1360 [SS_CLOSE] = "UNCONN",
1361 [SS_CLOSE_WAIT] = "CLOSE-WAIT",
1362 [SS_LAST_ACK] = "LAST-ACK",
1363 [SS_LISTEN] = "LISTEN",
1364 [SS_CLOSING] = "CLOSING",
1365 };
be7e4d20
PS
1366
1367 switch (s->local.family) {
1368 case AF_UNIX:
1369 sock_name = unix_netid_name(s->type);
1370 break;
1371 case AF_INET:
1372 case AF_INET6:
1373 sock_name = proto_name(s->type);
1374 break;
1375 case AF_PACKET:
1376 sock_name = s->type == SOCK_RAW ? "p_raw" : "p_dgr";
1377 break;
1378 case AF_NETLINK:
1379 sock_name = "nl";
1380 break;
5caf79a0
GM
1381 case AF_TIPC:
1382 sock_name = tipc_netid_name(s->type);
1383 break;
c759116a
SH
1384 case AF_VSOCK:
1385 sock_name = vsock_netid_name(s->type);
1386 break;
2abc3d76
BT
1387 case AF_XDP:
1388 sock_name = "xdp";
1389 break;
be7e4d20
PS
1390 default:
1391 sock_name = "unknown";
1392 }
1393
59f46b7b
SB
1394 if (is_sctp_assoc(s, sock_name)) {
1395 field_set(COL_STATE); /* Empty Netid field */
1396 out("`- %s", sctp_sstate_name[s->state]);
1397 } else {
1398 field_set(COL_NETID);
1399 out("%s", sock_name);
1400 field_set(COL_STATE);
1401 out("%s", sstate_name[s->state]);
f89d46ad 1402 }
2d791bc8 1403
59f46b7b
SB
1404 field_set(COL_RECVQ);
1405 out("%-6d", s->rq);
1406 field_set(COL_SENDQ);
1407 out("%-6d", s->wq);
1408 field_set(COL_ADDR);
2d791bc8
VK
1409}
1410
f1b39e1b
VK
1411static void sock_details_print(struct sockstat *s)
1412{
1413 if (s->uid)
90351722 1414 out(" uid:%u", s->uid);
f1b39e1b 1415
90351722
SB
1416 out(" ino:%u", s->ino);
1417 out(" sk:%llx", s->sk);
ec75249b
LC
1418
1419 if (s->mark)
90351722 1420 out(" fwmark:0x%x", s->mark);
14f4bda5
DY
1421
1422 if (s->cgroup_id)
1423 out(" cgroup:%s", cg_id_to_path(s->cgroup_id));
f1b39e1b
VK
1424}
1425
b217df10
VK
1426static void sock_addr_print(const char *addr, char *delim, const char *port,
1427 const char *ifname)
1428{
59f46b7b
SB
1429 if (ifname)
1430 out("%s" "%%" "%s%s", addr, ifname, delim);
1431 else
1432 out("%s%s", addr, delim);
1433
1434 field_next();
1435 out("%s", port);
1436 field_next();
b217df10
VK
1437}
1438
4cbf5224 1439static const char *print_ms_timer(unsigned int timeout)
aba5acdf
SH
1440{
1441 static char buf[64];
1442 int secs, msecs, minutes;
acd1e437 1443
aba5acdf
SH
1444 secs = timeout/1000;
1445 minutes = secs/60;
1446 secs = secs%60;
1447 msecs = timeout%1000;
1448 buf[0] = 0;
1449 if (minutes) {
1450 msecs = 0;
1451 snprintf(buf, sizeof(buf)-16, "%dmin", minutes);
1452 if (minutes > 9)
1453 secs = 0;
1454 }
1455 if (secs) {
1456 if (secs > 9)
1457 msecs = 0;
1458 sprintf(buf+strlen(buf), "%d%s", secs, msecs ? "." : "sec");
1459 }
1460 if (msecs)
1461 sprintf(buf+strlen(buf), "%03dms", msecs);
1462 return buf;
e7113c61 1463}
aba5acdf 1464
22588a0e 1465struct scache {
aba5acdf
SH
1466 struct scache *next;
1467 int port;
1468 char *name;
1469 const char *proto;
1470};
1471
3f7bd0fd 1472static struct scache *rlist;
aba5acdf 1473
d1f28cf1 1474static void init_service_resolver(void)
aba5acdf
SH
1475{
1476 char buf[128];
1477 FILE *fp = popen("/usr/sbin/rpcinfo -p 2>/dev/null", "r");
596307ea
PS
1478
1479 if (!fp)
1480 return;
1481
1482 if (!fgets(buf, sizeof(buf), fp)) {
2bcc3c16 1483 pclose(fp);
596307ea
PS
1484 return;
1485 }
1486 while (fgets(buf, sizeof(buf), fp) != NULL) {
1487 unsigned int progn, port;
1488 char proto[128], prog[128] = "rpc.";
1489 struct scache *c;
1490
1491 if (sscanf(buf, "%u %*d %s %u %s",
acd1e437 1492 &progn, proto, &port, prog+4) != 4)
596307ea
PS
1493 continue;
1494
1495 if (!(c = malloc(sizeof(*c))))
1496 continue;
1497
1498 c->port = port;
1499 c->name = strdup(prog);
1500 if (strcmp(proto, TCP_PROTO) == 0)
1501 c->proto = TCP_PROTO;
1502 else if (strcmp(proto, UDP_PROTO) == 0)
1503 c->proto = UDP_PROTO;
f89d46ad
PS
1504 else if (strcmp(proto, SCTP_PROTO) == 0)
1505 c->proto = SCTP_PROTO;
596307ea
PS
1506 else
1507 c->proto = NULL;
1508 c->next = rlist;
1509 rlist = c;
aba5acdf 1510 }
596307ea 1511 pclose(fp);
aba5acdf
SH
1512}
1513
ab61159a
SH
1514/* Even do not try default linux ephemeral port ranges:
1515 * default /etc/services contains so much of useless crap
1516 * wouldbe "allocated" to this area that resolution
1517 * is really harmful. I shrug each time when seeing
1518 * "socks" or "cfinger" in dumps.
1519 */
1520static int is_ephemeral(int port)
1521{
acd1e437 1522 static int min = 0, max;
c29d3792
PS
1523
1524 if (!min) {
ab01dbbb 1525 FILE *f = ephemeral_ports_open();
acd1e437 1526
c29d3792
PS
1527 if (!f || fscanf(f, "%d %d", &min, &max) < 2) {
1528 min = 1024;
1529 max = 4999;
ab61159a 1530 }
c29d3792
PS
1531 if (f)
1532 fclose(f);
ab61159a 1533 }
c29d3792 1534 return port >= min && port <= max;
ab61159a
SH
1535}
1536
1537
d1f28cf1 1538static const char *__resolve_service(int port)
aba5acdf
SH
1539{
1540 struct scache *c;
1541
1542 for (c = rlist; c; c = c->next) {
1543 if (c->port == port && c->proto == dg_proto)
1544 return c->name;
1545 }
1546
ab61159a 1547 if (!is_ephemeral(port)) {
aba5acdf
SH
1548 static int notfirst;
1549 struct servent *se;
acd1e437 1550
aba5acdf
SH
1551 if (!notfirst) {
1552 setservent(1);
1553 notfirst = 1;
ae665a52 1554 }
aba5acdf
SH
1555 se = getservbyport(htons(port), dg_proto);
1556 if (se)
1557 return se->s_name;
1558 }
1559
1560 return NULL;
1561}
1562
22588a0e
ED
1563#define SCACHE_BUCKETS 1024
1564static struct scache *cache_htab[SCACHE_BUCKETS];
aba5acdf 1565
d1f28cf1 1566static const char *resolve_service(int port)
aba5acdf
SH
1567{
1568 static char buf[128];
22588a0e
ED
1569 struct scache *c;
1570 const char *res;
1571 int hash;
aba5acdf
SH
1572
1573 if (port == 0) {
1574 buf[0] = '*';
1575 buf[1] = 0;
1576 return buf;
1577 }
1578
ca697cee 1579 if (numeric)
22588a0e 1580 goto do_numeric;
aba5acdf 1581
22588a0e
ED
1582 if (dg_proto == RAW_PROTO)
1583 return inet_proto_n2a(port, buf, sizeof(buf));
1584
1585
1586 hash = (port^(((unsigned long)dg_proto)>>2)) % SCACHE_BUCKETS;
1587
1588 for (c = cache_htab[hash]; c; c = c->next) {
1589 if (c->port == port && c->proto == dg_proto)
1590 goto do_cache;
aba5acdf
SH
1591 }
1592
22588a0e
ED
1593 c = malloc(sizeof(*c));
1594 if (!c)
1595 goto do_numeric;
1596 res = __resolve_service(port);
1597 c->port = port;
1598 c->name = res ? strdup(res) : NULL;
1599 c->proto = dg_proto;
1600 c->next = cache_htab[hash];
1601 cache_htab[hash] = c;
1602
1603do_cache:
1604 if (c->name)
1605 return c->name;
1606
1607do_numeric:
aba5acdf
SH
1608 sprintf(buf, "%u", port);
1609 return buf;
1610}
1611
1267c0b9
PS
1612static void inet_addr_print(const inet_prefix *a, int port,
1613 unsigned int ifindex, bool v6only)
aba5acdf
SH
1614{
1615 char buf[1024];
1616 const char *ap = buf;
b217df10 1617 const char *ifname = NULL;
aba5acdf
SH
1618
1619 if (a->family == AF_INET) {
1267c0b9 1620 ap = format_host(AF_INET, 4, a->data);
aba5acdf 1621 } else {
1267c0b9
PS
1622 if (!v6only &&
1623 !memcmp(a->data, &in6addr_any, sizeof(in6addr_any))) {
aba9c23a
SH
1624 buf[0] = '*';
1625 buf[1] = 0;
1626 } else {
1627 ap = format_host(a->family, 16, a->data);
1628
1629 /* Numeric IPv6 addresses should be bracketed */
1630 if (strchr(ap, ':')) {
1631 snprintf(buf, sizeof(buf),
1632 "[%s]", ap);
1633 ap = buf;
1634 }
aba9c23a 1635 }
aba5acdf 1636 }
b217df10 1637
59f46b7b
SB
1638 if (ifindex)
1639 ifname = ll_index_to_name(ifindex);
7c8a3cfb 1640
59f46b7b 1641 sock_addr_print(ap, ":", resolve_service(port), ifname);
aba5acdf
SH
1642}
1643
acd1e437 1644struct aafilter {
aba5acdf
SH
1645 inet_prefix addr;
1646 int port;
2d293212 1647 unsigned int iface;
ec75249b
LC
1648 __u32 mark;
1649 __u32 mask;
14f4bda5 1650 __u64 cgroup_id;
aba5acdf
SH
1651 struct aafilter *next;
1652};
1653
d1f28cf1
SH
1654static int inet2_addr_match(const inet_prefix *a, const inet_prefix *p,
1655 int plen)
aba5acdf
SH
1656{
1657 if (!inet_addr_match(a, p, plen))
1658 return 0;
7d105b56 1659
aba5acdf
SH
1660 /* Cursed "v4 mapped" addresses: v4 mapped socket matches
1661 * pure IPv4 rule, but v4-mapped rule selects only v4-mapped
1662 * sockets. Fair? */
1663 if (p->family == AF_INET && a->family == AF_INET6) {
1664 if (a->data[0] == 0 && a->data[1] == 0 &&
1665 a->data[2] == htonl(0xffff)) {
1666 inet_prefix tmp = *a;
acd1e437 1667
aba5acdf
SH
1668 tmp.data[0] = a->data[3];
1669 return inet_addr_match(&tmp, p, plen);
1670 }
1671 }
1672 return 1;
1673}
1674
d1f28cf1 1675static int unix_match(const inet_prefix *a, const inet_prefix *p)
aba5acdf 1676{
99bb68ff 1677 char *addr, *pattern;
acd1e437 1678
99bb68ff
VK
1679 memcpy(&addr, a->data, sizeof(addr));
1680 memcpy(&pattern, p->data, sizeof(pattern));
aba5acdf
SH
1681 if (pattern == NULL)
1682 return 1;
1683 if (addr == NULL)
1684 addr = "";
8f5a602f 1685 return !fnmatch(pattern, addr, FNM_CASEFOLD);
aba5acdf
SH
1686}
1687
055840f2 1688static int run_ssfilter(struct ssfilter *f, struct sockstat *s)
aba5acdf
SH
1689{
1690 switch (f->type) {
1691 case SSF_S_AUTO:
1692 {
aba5acdf 1693 if (s->local.family == AF_UNIX) {
99bb68ff 1694 char *p;
acd1e437 1695
99bb68ff 1696 memcpy(&p, s->local.data, sizeof(p));
aba5acdf 1697 return p == NULL || (p[0] == '@' && strlen(p) == 6 &&
ae665a52 1698 strspn(p+1, "0123456789abcdef") == 5);
aba5acdf
SH
1699 }
1700 if (s->local.family == AF_PACKET)
bbd303d1 1701 return s->lport == 0 && s->local.data[0] == 0;
aba5acdf
SH
1702 if (s->local.family == AF_NETLINK)
1703 return s->lport < 0;
c759116a
SH
1704 if (s->local.family == AF_VSOCK)
1705 return s->lport > 1023;
aba5acdf 1706
c29d3792 1707 return is_ephemeral(s->lport);
aba5acdf
SH
1708 }
1709 case SSF_DCOND:
1710 {
acd1e437
SH
1711 struct aafilter *a = (void *)f->pred;
1712
aba5acdf
SH
1713 if (a->addr.family == AF_UNIX)
1714 return unix_match(&s->remote, &a->addr);
1715 if (a->port != -1 && a->port != s->rport)
1716 return 0;
1717 if (a->addr.bitlen) {
1718 do {
1719 if (!inet2_addr_match(&s->remote, &a->addr, a->addr.bitlen))
1720 return 1;
1721 } while ((a = a->next) != NULL);
1722 return 0;
1723 }
1724 return 1;
1725 }
1726 case SSF_SCOND:
1727 {
acd1e437
SH
1728 struct aafilter *a = (void *)f->pred;
1729
aba5acdf
SH
1730 if (a->addr.family == AF_UNIX)
1731 return unix_match(&s->local, &a->addr);
1732 if (a->port != -1 && a->port != s->lport)
1733 return 0;
1734 if (a->addr.bitlen) {
1735 do {
1736 if (!inet2_addr_match(&s->local, &a->addr, a->addr.bitlen))
1737 return 1;
ae665a52 1738 } while ((a = a->next) != NULL);
aba5acdf
SH
1739 return 0;
1740 }
1741 return 1;
1742 }
1743 case SSF_D_GE:
1744 {
acd1e437
SH
1745 struct aafilter *a = (void *)f->pred;
1746
aba5acdf
SH
1747 return s->rport >= a->port;
1748 }
1749 case SSF_D_LE:
1750 {
acd1e437
SH
1751 struct aafilter *a = (void *)f->pred;
1752
aba5acdf
SH
1753 return s->rport <= a->port;
1754 }
1755 case SSF_S_GE:
1756 {
acd1e437
SH
1757 struct aafilter *a = (void *)f->pred;
1758
aba5acdf
SH
1759 return s->lport >= a->port;
1760 }
1761 case SSF_S_LE:
1762 {
acd1e437
SH
1763 struct aafilter *a = (void *)f->pred;
1764
aba5acdf
SH
1765 return s->lport <= a->port;
1766 }
2d293212
DA
1767 case SSF_DEVCOND:
1768 {
1769 struct aafilter *a = (void *)f->pred;
aba5acdf 1770
2d293212 1771 return s->iface == a->iface;
ec75249b
LC
1772 }
1773 case SSF_MARKMASK:
1774 {
1775 struct aafilter *a = (void *)f->pred;
1776
1777 return (s->mark & a->mask) == a->mark;
14f4bda5
DY
1778 }
1779 case SSF_CGROUPCOND:
1780 {
1781 struct aafilter *a = (void *)f->pred;
1782
1783 return s->cgroup_id == a->cgroup_id;
2d293212 1784 }
aba5acdf
SH
1785 /* Yup. It is recursion. Sorry. */
1786 case SSF_AND:
1787 return run_ssfilter(f->pred, s) && run_ssfilter(f->post, s);
1788 case SSF_OR:
1789 return run_ssfilter(f->pred, s) || run_ssfilter(f->post, s);
1790 case SSF_NOT:
1791 return !run_ssfilter(f->pred, s);
1792 default:
1793 abort();
1794 }
1795}
1796
ae665a52 1797/* Relocate external jumps by reloc. */
b4b0b7d5 1798static void ssfilter_patch(char *a, int len, int reloc)
aba5acdf
SH
1799{
1800 while (len > 0) {
acd1e437
SH
1801 struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)a;
1802
aba5acdf
SH
1803 if (op->no == len+4)
1804 op->no += reloc;
1805 len -= op->yes;
1806 a += op->yes;
1807 }
1808 if (len < 0)
1809 abort();
1810}
1811
b4b0b7d5 1812static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode)
aba5acdf
SH
1813{
1814 switch (f->type) {
1815 case SSF_S_AUTO:
1816 {
acd1e437
SH
1817 if (!(*bytecode = malloc(4))) abort();
1818 ((struct inet_diag_bc_op *)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_AUTO, 4, 8 };
df39de8d 1819 return 4;
aba5acdf
SH
1820 }
1821 case SSF_DCOND:
1822 case SSF_SCOND:
1823 {
acd1e437 1824 struct aafilter *a = (void *)f->pred;
aba5acdf
SH
1825 struct aafilter *b;
1826 char *ptr;
351efcde 1827 int code = (f->type == SSF_DCOND ? INET_DIAG_BC_D_COND : INET_DIAG_BC_S_COND);
aba5acdf
SH
1828 int len = 0;
1829
acd1e437 1830 for (b = a; b; b = b->next) {
351efcde 1831 len += 4 + sizeof(struct inet_diag_hostcond);
aba5acdf
SH
1832 if (a->addr.family == AF_INET6)
1833 len += 16;
1834 else
1835 len += 4;
1836 if (b->next)
1837 len += 4;
1838 }
1839 if (!(ptr = malloc(len))) abort();
1840 *bytecode = ptr;
acd1e437 1841 for (b = a; b; b = b->next) {
351efcde 1842 struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)ptr;
aba5acdf 1843 int alen = (a->addr.family == AF_INET6 ? 16 : 4);
351efcde 1844 int oplen = alen + 4 + sizeof(struct inet_diag_hostcond);
acd1e437 1845 struct inet_diag_hostcond *cond = (struct inet_diag_hostcond *)(ptr+4);
aba5acdf 1846
351efcde 1847 *op = (struct inet_diag_bc_op){ code, oplen, oplen+4 };
aba5acdf
SH
1848 cond->family = a->addr.family;
1849 cond->port = a->port;
1850 cond->prefix_len = a->addr.bitlen;
1851 memcpy(cond->addr, a->addr.data, alen);
1852 ptr += oplen;
1853 if (b->next) {
351efcde
SH
1854 op = (struct inet_diag_bc_op *)ptr;
1855 *op = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, len - (ptr-*bytecode)};
aba5acdf
SH
1856 ptr += 4;
1857 }
1858 }
1859 return ptr - *bytecode;
1860 }
1861 case SSF_D_GE:
1862 {
acd1e437
SH
1863 struct aafilter *x = (void *)f->pred;
1864
1865 if (!(*bytecode = malloc(8))) abort();
1866 ((struct inet_diag_bc_op *)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_D_GE, 8, 12 };
1867 ((struct inet_diag_bc_op *)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port };
aba5acdf
SH
1868 return 8;
1869 }
1870 case SSF_D_LE:
1871 {
acd1e437
SH
1872 struct aafilter *x = (void *)f->pred;
1873
1874 if (!(*bytecode = malloc(8))) abort();
1875 ((struct inet_diag_bc_op *)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_D_LE, 8, 12 };
1876 ((struct inet_diag_bc_op *)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port };
aba5acdf
SH
1877 return 8;
1878 }
1879 case SSF_S_GE:
1880 {
acd1e437
SH
1881 struct aafilter *x = (void *)f->pred;
1882
1883 if (!(*bytecode = malloc(8))) abort();
1884 ((struct inet_diag_bc_op *)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_S_GE, 8, 12 };
1885 ((struct inet_diag_bc_op *)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port };
aba5acdf
SH
1886 return 8;
1887 }
1888 case SSF_S_LE:
1889 {
acd1e437
SH
1890 struct aafilter *x = (void *)f->pred;
1891
1892 if (!(*bytecode = malloc(8))) abort();
1893 ((struct inet_diag_bc_op *)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_S_LE, 8, 12 };
1894 ((struct inet_diag_bc_op *)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port };
aba5acdf
SH
1895 return 8;
1896 }
1897
1898 case SSF_AND:
1899 {
376fb868 1900 char *a1 = NULL, *a2 = NULL, *a;
2a4fa1c3 1901 int l1, l2;
acd1e437 1902
aba5acdf
SH
1903 l1 = ssfilter_bytecompile(f->pred, &a1);
1904 l2 = ssfilter_bytecompile(f->post, &a2);
376fb868
DA
1905 if (!l1 || !l2) {
1906 free(a1);
1907 free(a2);
1908 return 0;
1909 }
aba5acdf
SH
1910 if (!(a = malloc(l1+l2))) abort();
1911 memcpy(a, a1, l1);
1912 memcpy(a+l1, a2, l2);
1913 free(a1); free(a2);
1914 ssfilter_patch(a, l1, l2);
1915 *bytecode = a;
1916 return l1+l2;
1917 }
1918 case SSF_OR:
1919 {
376fb868 1920 char *a1 = NULL, *a2 = NULL, *a;
2a4fa1c3 1921 int l1, l2;
acd1e437 1922
aba5acdf
SH
1923 l1 = ssfilter_bytecompile(f->pred, &a1);
1924 l2 = ssfilter_bytecompile(f->post, &a2);
376fb868
DA
1925 if (!l1 || !l2) {
1926 free(a1);
1927 free(a2);
1928 return 0;
1929 }
aba5acdf
SH
1930 if (!(a = malloc(l1+l2+4))) abort();
1931 memcpy(a, a1, l1);
1932 memcpy(a+l1+4, a2, l2);
1933 free(a1); free(a2);
acd1e437 1934 *(struct inet_diag_bc_op *)(a+l1) = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, l2+4 };
aba5acdf
SH
1935 *bytecode = a;
1936 return l1+l2+4;
1937 }
1938 case SSF_NOT:
1939 {
376fb868 1940 char *a1 = NULL, *a;
2a4fa1c3 1941 int l1;
acd1e437 1942
aba5acdf 1943 l1 = ssfilter_bytecompile(f->pred, &a1);
376fb868
DA
1944 if (!l1) {
1945 free(a1);
1946 return 0;
1947 }
aba5acdf
SH
1948 if (!(a = malloc(l1+4))) abort();
1949 memcpy(a, a1, l1);
1950 free(a1);
acd1e437 1951 *(struct inet_diag_bc_op *)(a+l1) = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, 8 };
aba5acdf
SH
1952 *bytecode = a;
1953 return l1+4;
2d293212
DA
1954 }
1955 case SSF_DEVCOND:
1956 {
1957 /* bytecompile for SSF_DEVCOND not supported yet */
1958 return 0;
ec75249b
LC
1959 }
1960 case SSF_MARKMASK:
1961 {
1962 struct aafilter *a = (void *)f->pred;
1963 struct instr {
1964 struct inet_diag_bc_op op;
1965 struct inet_diag_markcond cond;
1966 };
1967 int inslen = sizeof(struct instr);
1968
1969 if (!(*bytecode = malloc(inslen))) abort();
1970 ((struct instr *)*bytecode)[0] = (struct instr) {
1971 { INET_DIAG_BC_MARK_COND, inslen, inslen + 4 },
1972 { a->mark, a->mask},
1973 };
1974
14f4bda5
DY
1975 return inslen;
1976 }
1977 case SSF_CGROUPCOND:
1978 {
1979 struct aafilter *a = (void *)f->pred;
1980 struct instr {
1981 struct inet_diag_bc_op op;
1982 __u64 cgroup_id;
1983 } __attribute__((packed));
1984 int inslen = sizeof(struct instr);
1985
1986 if (!(*bytecode = malloc(inslen))) abort();
1987 ((struct instr *)*bytecode)[0] = (struct instr) {
1988 { INET_DIAG_BC_CGROUP_COND, inslen, inslen + 4 },
1989 a->cgroup_id,
1990 };
1991
ec75249b 1992 return inslen;
aba5acdf
SH
1993 }
1994 default:
1995 abort();
1996 }
1997}
1998
b4b0b7d5 1999static int remember_he(struct aafilter *a, struct hostent *he)
aba5acdf 2000{
ae665a52 2001 char **ptr = he->h_addr_list;
aba5acdf
SH
2002 int cnt = 0;
2003 int len;
2004
2005 if (he->h_addrtype == AF_INET)
2006 len = 4;
2007 else if (he->h_addrtype == AF_INET6)
2008 len = 16;
2009 else
2010 return 0;
2011
2012 while (*ptr) {
2013 struct aafilter *b = a;
acd1e437 2014
aba5acdf
SH
2015 if (a->addr.bitlen) {
2016 if ((b = malloc(sizeof(*b))) == NULL)
2017 return cnt;
2018 *b = *a;
aba5acdf
SH
2019 a->next = b;
2020 }
2021 memcpy(b->addr.data, *ptr, len);
2022 b->addr.bytelen = len;
2023 b->addr.bitlen = len*8;
2024 b->addr.family = he->h_addrtype;
2025 ptr++;
2026 cnt++;
2027 }
2028 return cnt;
2029}
2030
b4b0b7d5 2031static int get_dns_host(struct aafilter *a, const char *addr, int fam)
aba5acdf
SH
2032{
2033 static int notfirst;
2034 int cnt = 0;
2035 struct hostent *he;
2036
2037 a->addr.bitlen = 0;
2038 if (!notfirst) {
2039 sethostent(1);
2040 notfirst = 1;
2041 }
2042 he = gethostbyname2(addr, fam == AF_UNSPEC ? AF_INET : fam);
2043 if (he)
2044 cnt = remember_he(a, he);
2045 if (fam == AF_UNSPEC) {
2046 he = gethostbyname2(addr, AF_INET6);
2047 if (he)
2048 cnt += remember_he(a, he);
2049 }
2050 return !cnt;
2051}
2052
acd1e437 2053static int xll_initted;
aba5acdf 2054
b4b0b7d5 2055static void xll_init(void)
aba5acdf
SH
2056{
2057 struct rtnl_handle rth;
acd1e437 2058
d2468da0
SH
2059 if (rtnl_open(&rth, 0) < 0)
2060 exit(1);
2061
aba5acdf
SH
2062 ll_init_map(&rth);
2063 rtnl_close(&rth);
2064 xll_initted = 1;
2065}
2066
b4b0b7d5 2067static const char *xll_index_to_name(int index)
aba5acdf
SH
2068{
2069 if (!xll_initted)
2070 xll_init();
2071 return ll_index_to_name(index);
2072}
2073
b4b0b7d5 2074static int xll_name_to_index(const char *dev)
aba5acdf
SH
2075{
2076 if (!xll_initted)
2077 xll_init();
2078 return ll_name_to_index(dev);
2079}
2080
2d293212
DA
2081void *parse_devcond(char *name)
2082{
2083 struct aafilter a = { .iface = 0 };
2084 struct aafilter *res;
2085
2086 a.iface = xll_name_to_index(name);
2087 if (a.iface == 0) {
2088 char *end;
930d3f28 2089 unsigned long n;
2d293212 2090
930d3f28
DA
2091 n = strtoul(name, &end, 0);
2092 if (!end || end == name || *end || n > UINT_MAX)
2d293212 2093 return NULL;
930d3f28
DA
2094
2095 a.iface = n;
2d293212
DA
2096 }
2097
2098 res = malloc(sizeof(*res));
2099 *res = a;
2100
2101 return res;
2102}
2103
c759116a
SH
2104static void vsock_set_inet_prefix(inet_prefix *a, __u32 cid)
2105{
2106 *a = (inet_prefix){
2107 .bytelen = sizeof(cid),
2108 .family = AF_VSOCK,
2109 };
2110 memcpy(a->data, &cid, sizeof(cid));
2111}
2112
7871f7db 2113void *parse_hostcond(char *addr, bool is_port)
aba5acdf
SH
2114{
2115 char *port = NULL;
1527a17e 2116 struct aafilter a = { .port = -1 };
aba5acdf 2117 struct aafilter *res;
1527a17e 2118 int fam = preferred_family;
9db7bf15 2119 struct filter *f = &current_filter;
aba5acdf 2120
1527a17e 2121 if (fam == AF_UNIX || strncmp(addr, "unix:", 5) == 0) {
aba5acdf 2122 char *p;
acd1e437 2123
aba5acdf
SH
2124 a.addr.family = AF_UNIX;
2125 if (strncmp(addr, "unix:", 5) == 0)
acd1e437 2126 addr += 5;
aba5acdf
SH
2127 p = strdup(addr);
2128 a.addr.bitlen = 8*strlen(p);
99bb68ff 2129 memcpy(a.addr.data, &p, sizeof(p));
9db7bf15 2130 fam = AF_UNIX;
aba5acdf
SH
2131 goto out;
2132 }
2133
1527a17e 2134 if (fam == AF_PACKET || strncmp(addr, "link:", 5) == 0) {
aba5acdf
SH
2135 a.addr.family = AF_PACKET;
2136 a.addr.bitlen = 0;
2137 if (strncmp(addr, "link:", 5) == 0)
acd1e437 2138 addr += 5;
aba5acdf
SH
2139 port = strchr(addr, ':');
2140 if (port) {
2141 *port = 0;
2142 if (port[1] && strcmp(port+1, "*")) {
2143 if (get_integer(&a.port, port+1, 0)) {
2144 if ((a.port = xll_name_to_index(port+1)) <= 0)
2145 return NULL;
2146 }
2147 }
2148 }
2149 if (addr[0] && strcmp(addr, "*")) {
2150 unsigned short tmp;
acd1e437 2151
aba5acdf
SH
2152 a.addr.bitlen = 32;
2153 if (ll_proto_a2n(&tmp, addr))
2154 return NULL;
2155 a.addr.data[0] = ntohs(tmp);
2156 }
9db7bf15 2157 fam = AF_PACKET;
aba5acdf
SH
2158 goto out;
2159 }
2160
1527a17e 2161 if (fam == AF_NETLINK || strncmp(addr, "netlink:", 8) == 0) {
aba5acdf
SH
2162 a.addr.family = AF_NETLINK;
2163 a.addr.bitlen = 0;
2164 if (strncmp(addr, "netlink:", 8) == 0)
acd1e437 2165 addr += 8;
aba5acdf
SH
2166 port = strchr(addr, ':');
2167 if (port) {
2168 *port = 0;
2169 if (port[1] && strcmp(port+1, "*")) {
2170 if (get_integer(&a.port, port+1, 0)) {
2171 if (strcmp(port+1, "kernel") == 0)
2172 a.port = 0;
2173 else
2174 return NULL;
2175 }
2176 }
2177 }
2178 if (addr[0] && strcmp(addr, "*")) {
2179 a.addr.bitlen = 32;
b00daf6a 2180 if (nl_proto_a2n(&a.addr.data[0], addr) == -1)
2181 return NULL;
aba5acdf 2182 }
9db7bf15 2183 fam = AF_NETLINK;
aba5acdf
SH
2184 goto out;
2185 }
2186
c759116a
SH
2187 if (fam == AF_VSOCK || strncmp(addr, "vsock:", 6) == 0) {
2188 __u32 cid = ~(__u32)0;
2189
2190 a.addr.family = AF_VSOCK;
2191 if (strncmp(addr, "vsock:", 6) == 0)
2192 addr += 6;
2193
2194 if (is_port)
2195 port = addr;
2196 else {
2197 port = strchr(addr, ':');
2198 if (port) {
2199 *port = '\0';
2200 port++;
2201 }
2202 }
2203
2204 if (port && strcmp(port, "*") &&
2205 get_u32((__u32 *)&a.port, port, 0))
2206 return NULL;
2207
2208 if (addr[0] && strcmp(addr, "*")) {
2209 a.addr.bitlen = 32;
2210 if (get_u32(&cid, addr, 0))
2211 return NULL;
2212 }
2213 vsock_set_inet_prefix(&a.addr, cid);
2214 fam = AF_VSOCK;
2215 goto out;
2216 }
2217
1527a17e 2218 if (fam == AF_INET || !strncmp(addr, "inet:", 5)) {
aba5acdf 2219 fam = AF_INET;
1527a17e
VK
2220 if (!strncmp(addr, "inet:", 5))
2221 addr += 5;
2222 } else if (fam == AF_INET6 || !strncmp(addr, "inet6:", 6)) {
aba5acdf 2223 fam = AF_INET6;
1527a17e
VK
2224 if (!strncmp(addr, "inet6:", 6))
2225 addr += 6;
aba5acdf
SH
2226 }
2227
2228 /* URL-like literal [] */
2229 if (addr[0] == '[') {
2230 addr++;
2231 if ((port = strchr(addr, ']')) == NULL)
2232 return NULL;
2233 *port++ = 0;
2234 } else if (addr[0] == '*') {
2235 port = addr+1;
2236 } else {
2237 port = strrchr(strchr(addr, '/') ? : addr, ':');
2238 }
7871f7db
VK
2239
2240 if (is_port)
2241 port = addr;
2242
aba5acdf 2243 if (port && *port) {
7871f7db
VK
2244 if (*port == ':')
2245 *port++ = 0;
2246
aba5acdf
SH
2247 if (*port && *port != '*') {
2248 if (get_integer(&a.port, port, 0)) {
2249 struct servent *se1 = NULL;
2250 struct servent *se2 = NULL;
acd1e437 2251
aba5acdf
SH
2252 if (current_filter.dbs&(1<<UDP_DB))
2253 se1 = getservbyname(port, UDP_PROTO);
2254 if (current_filter.dbs&(1<<TCP_DB))
2255 se2 = getservbyname(port, TCP_PROTO);
2256 if (se1 && se2 && se1->s_port != se2->s_port) {
2257 fprintf(stderr, "Error: ambiguous port \"%s\".\n", port);
2258 return NULL;
2259 }
2260 if (!se1)
2261 se1 = se2;
2262 if (se1) {
2263 a.port = ntohs(se1->s_port);
2264 } else {
2265 struct scache *s;
acd1e437 2266
aba5acdf
SH
2267 for (s = rlist; s; s = s->next) {
2268 if ((s->proto == UDP_PROTO &&
2269 (current_filter.dbs&(1<<UDP_DB))) ||
2270 (s->proto == TCP_PROTO &&
2271 (current_filter.dbs&(1<<TCP_DB)))) {
2272 if (s->name && strcmp(s->name, port) == 0) {
2273 if (a.port > 0 && a.port != s->port) {
2274 fprintf(stderr, "Error: ambiguous port \"%s\".\n", port);
2275 return NULL;
2276 }
2277 a.port = s->port;
2278 }
2279 }
2280 }
2281 if (a.port <= 0) {
2282 fprintf(stderr, "Error: \"%s\" does not look like a port.\n", port);
2283 return NULL;
2284 }
2285 }
2286 }
2287 }
2288 }
44448a90 2289 if (!is_port && *addr && *addr != '*') {
aba5acdf
SH
2290 if (get_prefix_1(&a.addr, addr, fam)) {
2291 if (get_dns_host(&a, addr, fam)) {
2292 fprintf(stderr, "Error: an inet prefix is expected rather than \"%s\".\n", addr);
2293 return NULL;
2294 }
2295 }
2296 }
2297
9db7bf15 2298out:
1527a17e 2299 if (fam != AF_UNSPEC) {
e56a959e 2300 int states = f->states;
1527a17e 2301 f->families = 0;
9db7bf15 2302 filter_af_set(f, fam);
e56a959e 2303 filter_states_set(f, states);
1527a17e 2304 }
9db7bf15 2305
aba5acdf
SH
2306 res = malloc(sizeof(*res));
2307 if (res)
2308 memcpy(res, &a, sizeof(a));
2309 return res;
2310}
2311
ec75249b
LC
2312void *parse_markmask(const char *markmask)
2313{
2314 struct aafilter a, *res;
2315
2316 if (strchr(markmask, '/')) {
2317 if (sscanf(markmask, "%i/%i", &a.mark, &a.mask) != 2)
2318 return NULL;
2319 } else {
2320 a.mask = 0xffffffff;
2321 if (sscanf(markmask, "%i", &a.mark) != 1)
2322 return NULL;
2323 }
2324
2325 res = malloc(sizeof(*res));
2326 if (res)
2327 memcpy(res, &a, sizeof(a));
2328 return res;
2329}
2330
14f4bda5
DY
2331void *parse_cgroupcond(const char *path)
2332{
2333 struct aafilter *res;
2334 __u64 id;
2335
2336 id = get_cgroup2_id(path);
2337 if (!id)
2338 return NULL;
2339
2340 res = malloc(sizeof(*res));
2341 if (res)
2342 res->cgroup_id = id;
2343
2344 return res;
2345}
2346
5f27ac1d 2347static void proc_ctx_print(struct sockstat *s)
8250bc9f 2348{
5f27ac1d 2349 char *buf;
8250bc9f 2350
8250bc9f
VK
2351 if (show_proc_ctx || show_sock_ctx) {
2352 if (find_entry(s->ino, &buf,
2353 (show_proc_ctx & show_sock_ctx) ?
2354 PROC_SOCK_CTX : PROC_CTX) > 0) {
90351722 2355 out(" users:(%s)", buf);
8250bc9f
VK
2356 free(buf);
2357 }
2358 } else if (show_users) {
2359 if (find_entry(s->ino, &buf, USERS) > 0) {
90351722 2360 out(" users:(%s)", buf);
8250bc9f
VK
2361 free(buf);
2362 }
2363 }
2364}
2365
1267c0b9 2366static void inet_stats_print(struct sockstat *s, bool v6only)
5f27ac1d
PS
2367{
2368 sock_state_print(s);
2369
1267c0b9
PS
2370 inet_addr_print(&s->local, s->lport, s->iface, v6only);
2371 inet_addr_print(&s->remote, s->rport, 0, v6only);
5f27ac1d
PS
2372
2373 proc_ctx_print(s);
2374}
2375
055840f2 2376static int proc_parse_inet_addr(char *loc, char *rem, int family, struct
acd1e437 2377 sockstat * s)
8250bc9f
VK
2378{
2379 s->local.family = s->remote.family = family;
2380 if (family == AF_INET) {
acd1e437
SH
2381 sscanf(loc, "%x:%x", s->local.data, (unsigned *)&s->lport);
2382 sscanf(rem, "%x:%x", s->remote.data, (unsigned *)&s->rport);
8250bc9f
VK
2383 s->local.bytelen = s->remote.bytelen = 4;
2384 return 0;
2385 } else {
2386 sscanf(loc, "%08x%08x%08x%08x:%x",
2387 s->local.data,
2388 s->local.data + 1,
2389 s->local.data + 2,
2390 s->local.data + 3,
2391 &s->lport);
2392 sscanf(rem, "%08x%08x%08x%08x:%x",
2393 s->remote.data,
2394 s->remote.data + 1,
2395 s->remote.data + 2,
2396 s->remote.data + 3,
2397 &s->rport);
2398 s->local.bytelen = s->remote.bytelen = 16;
2399 return 0;
2400 }
2401 return -1;
2402}
2403
2404static int proc_inet_split_line(char *line, char **loc, char **rem, char **data)
aba5acdf 2405{
aba5acdf 2406 char *p;
ae665a52 2407
aba5acdf
SH
2408 if ((p = strchr(line, ':')) == NULL)
2409 return -1;
ae665a52 2410
8250bc9f
VK
2411 *loc = p+2;
2412 if ((p = strchr(*loc, ':')) == NULL)
aba5acdf 2413 return -1;
ae665a52 2414
8250bc9f
VK
2415 p[5] = 0;
2416 *rem = p+6;
2417 if ((p = strchr(*rem, ':')) == NULL)
aba5acdf 2418 return -1;
8250bc9f 2419
aba5acdf 2420 p[5] = 0;
8250bc9f
VK
2421 *data = p+6;
2422 return 0;
2423}
ae665a52 2424
8142c762
SH
2425/*
2426 * Display bandwidth in standard units
2427 * See: https://en.wikipedia.org/wiki/Data-rate_units
2428 * bw is in bits per second
2429 */
8250bc9f
VK
2430static char *sprint_bw(char *buf, double bw)
2431{
a257456f 2432 if (numeric)
d791e75d 2433 sprintf(buf, "%.0f", bw);
8142c762
SH
2434 else if (bw >= 1e12)
2435 sprintf(buf, "%.3gT", bw / 1e12);
e133fa9c
ED
2436 else if (bw >= 1e9)
2437 sprintf(buf, "%.3gG", bw / 1e9);
2438 else if (bw >= 1e6)
2439 sprintf(buf, "%.3gM", bw / 1e6);
2440 else if (bw >= 1e3)
8142c762 2441 sprintf(buf, "%.3gk", bw / 1e3);
8250bc9f
VK
2442 else
2443 sprintf(buf, "%g", bw);
aba5acdf 2444
8250bc9f
VK
2445 return buf;
2446}
ae665a52 2447
f89d46ad
PS
2448static void sctp_stats_print(struct sctp_info *s)
2449{
2450 if (s->sctpi_tag)
90351722 2451 out(" tag:%x", s->sctpi_tag);
f89d46ad 2452 if (s->sctpi_state)
90351722 2453 out(" state:%s", sctp_sstate_name[s->sctpi_state]);
f89d46ad 2454 if (s->sctpi_rwnd)
90351722 2455 out(" rwnd:%d", s->sctpi_rwnd);
f89d46ad 2456 if (s->sctpi_unackdata)
90351722 2457 out(" unackdata:%d", s->sctpi_unackdata);
f89d46ad 2458 if (s->sctpi_penddata)
90351722 2459 out(" penddata:%d", s->sctpi_penddata);
f89d46ad 2460 if (s->sctpi_instrms)
90351722 2461 out(" instrms:%d", s->sctpi_instrms);
f89d46ad 2462 if (s->sctpi_outstrms)
90351722 2463 out(" outstrms:%d", s->sctpi_outstrms);
f89d46ad 2464 if (s->sctpi_inqueue)
90351722 2465 out(" inqueue:%d", s->sctpi_inqueue);
f89d46ad 2466 if (s->sctpi_outqueue)
90351722 2467 out(" outqueue:%d", s->sctpi_outqueue);
f89d46ad 2468 if (s->sctpi_overall_error)
90351722 2469 out(" overerr:%d", s->sctpi_overall_error);
f89d46ad 2470 if (s->sctpi_max_burst)
90351722 2471 out(" maxburst:%d", s->sctpi_max_burst);
f89d46ad 2472 if (s->sctpi_maxseg)
90351722 2473 out(" maxseg:%d", s->sctpi_maxseg);
f89d46ad 2474 if (s->sctpi_peer_rwnd)
90351722 2475 out(" prwnd:%d", s->sctpi_peer_rwnd);
f89d46ad 2476 if (s->sctpi_peer_tag)
90351722 2477 out(" ptag:%x", s->sctpi_peer_tag);
f89d46ad 2478 if (s->sctpi_peer_capable)
90351722 2479 out(" pcapable:%d", s->sctpi_peer_capable);
f89d46ad 2480 if (s->sctpi_peer_sack)
90351722 2481 out(" psack:%d", s->sctpi_peer_sack);
f89d46ad 2482 if (s->sctpi_s_autoclose)
90351722 2483 out(" autoclose:%d", s->sctpi_s_autoclose);
f89d46ad 2484 if (s->sctpi_s_adaptation_ind)
90351722 2485 out(" adapind:%d", s->sctpi_s_adaptation_ind);
f89d46ad 2486 if (s->sctpi_s_pd_point)
90351722 2487 out(" pdpoint:%d", s->sctpi_s_pd_point);
f89d46ad 2488 if (s->sctpi_s_nodelay)
18db049f 2489 out(" nodelay:%d", s->sctpi_s_nodelay);
f89d46ad 2490 if (s->sctpi_s_disable_fragments)
90351722 2491 out(" nofrag:%d", s->sctpi_s_disable_fragments);
f89d46ad 2492 if (s->sctpi_s_v4mapped)
90351722 2493 out(" v4mapped:%d", s->sctpi_s_v4mapped);
f89d46ad 2494 if (s->sctpi_s_frag_interleave)
90351722 2495 out(" fraginl:%d", s->sctpi_s_frag_interleave);
f89d46ad
PS
2496}
2497
8250bc9f
VK
2498static void tcp_stats_print(struct tcpstat *s)
2499{
2500 char b1[64];
2501
2502 if (s->has_ts_opt)
90351722 2503 out(" ts");
8250bc9f 2504 if (s->has_sack_opt)
90351722 2505 out(" sack");
8250bc9f 2506 if (s->has_ecn_opt)
90351722 2507 out(" ecn");
8250bc9f 2508 if (s->has_ecnseen_opt)
90351722 2509 out(" ecnseen");
8250bc9f 2510 if (s->has_fastopen_opt)
90351722 2511 out(" fastopen");
d2055ea5 2512 if (s->cong_alg[0])
90351722 2513 out(" %s", s->cong_alg);
8250bc9f 2514 if (s->has_wscale_opt)
90351722 2515 out(" wscale:%d,%d", s->snd_wscale, s->rcv_wscale);
8250bc9f 2516 if (s->rto)
90351722 2517 out(" rto:%g", s->rto);
8250bc9f 2518 if (s->backoff)
90351722 2519 out(" backoff:%u", s->backoff);
8250bc9f 2520 if (s->rtt)
90351722 2521 out(" rtt:%g/%g", s->rtt, s->rttvar);
8250bc9f 2522 if (s->ato)
90351722 2523 out(" ato:%g", s->ato);
8250bc9f
VK
2524
2525 if (s->qack)
90351722 2526 out(" qack:%d", s->qack);
8250bc9f 2527 if (s->qack & 1)
90351722 2528 out(" bidir");
8250bc9f
VK
2529
2530 if (s->mss)
90351722 2531 out(" mss:%d", s->mss);
3d791a32
RM
2532 if (s->pmtu)
2533 out(" pmtu:%u", s->pmtu);
38e6dbc4 2534 if (s->rcv_mss)
90351722 2535 out(" rcvmss:%d", s->rcv_mss);
38e6dbc4 2536 if (s->advmss)
90351722 2537 out(" advmss:%d", s->advmss);
3bf5445c 2538 if (s->cwnd)
90351722 2539 out(" cwnd:%u", s->cwnd);
8250bc9f 2540 if (s->ssthresh)
90351722 2541 out(" ssthresh:%d", s->ssthresh);
8250bc9f 2542
5eead627
ED
2543 if (s->bytes_sent)
2544 out(" bytes_sent:%llu", s->bytes_sent);
2545 if (s->bytes_retrans)
2546 out(" bytes_retrans:%llu", s->bytes_retrans);
1a4dda71 2547 if (s->bytes_acked)
90351722 2548 out(" bytes_acked:%llu", s->bytes_acked);
1a4dda71 2549 if (s->bytes_received)
90351722 2550 out(" bytes_received:%llu", s->bytes_received);
ecb435ea 2551 if (s->segs_out)
90351722 2552 out(" segs_out:%u", s->segs_out);
ecb435ea 2553 if (s->segs_in)
90351722 2554 out(" segs_in:%u", s->segs_in);
414aeec9 2555 if (s->data_segs_out)
90351722 2556 out(" data_segs_out:%u", s->data_segs_out);
414aeec9 2557 if (s->data_segs_in)
90351722 2558 out(" data_segs_in:%u", s->data_segs_in);
1a4dda71 2559
8250bc9f
VK
2560 if (s->dctcp && s->dctcp->enabled) {
2561 struct dctcpstat *dctcp = s->dctcp;
2562
90351722
SB
2563 out(" dctcp:(ce_state:%u,alpha:%u,ab_ecn:%u,ab_tot:%u)",
2564 dctcp->ce_state, dctcp->alpha, dctcp->ab_ecn,
2565 dctcp->ab_tot);
8250bc9f 2566 } else if (s->dctcp) {
90351722 2567 out(" dctcp:fallback_mode");
8250bc9f
VK
2568 }
2569
2f0f9aef
NC
2570 if (s->bbr_info) {
2571 __u64 bw;
2572
2573 bw = s->bbr_info->bbr_bw_hi;
2574 bw <<= 32;
2575 bw |= s->bbr_info->bbr_bw_lo;
2576
90351722
SB
2577 out(" bbr:(bw:%sbps,mrtt:%g",
2578 sprint_bw(b1, bw * 8.0),
2579 (double)s->bbr_info->bbr_min_rtt / 1000.0);
2f0f9aef 2580 if (s->bbr_info->bbr_pacing_gain)
90351722
SB
2581 out(",pacing_gain:%g",
2582 (double)s->bbr_info->bbr_pacing_gain / 256.0);
2f0f9aef 2583 if (s->bbr_info->bbr_cwnd_gain)
90351722
SB
2584 out(",cwnd_gain:%g",
2585 (double)s->bbr_info->bbr_cwnd_gain / 256.0);
2586 out(")");
2f0f9aef
NC
2587 }
2588
8250bc9f 2589 if (s->send_bps)
90351722 2590 out(" send %sbps", sprint_bw(b1, s->send_bps));
8250bc9f 2591 if (s->lastsnd)
90351722 2592 out(" lastsnd:%u", s->lastsnd);
8250bc9f 2593 if (s->lastrcv)
90351722 2594 out(" lastrcv:%u", s->lastrcv);
8250bc9f 2595 if (s->lastack)
90351722 2596 out(" lastack:%u", s->lastack);
8250bc9f
VK
2597
2598 if (s->pacing_rate) {
90351722 2599 out(" pacing_rate %sbps", sprint_bw(b1, s->pacing_rate));
8250bc9f 2600 if (s->pacing_rate_max)
90351722 2601 out("/%sbps", sprint_bw(b1, s->pacing_rate_max));
8250bc9f
VK
2602 }
2603
2f579872 2604 if (s->delivery_rate)
90351722 2605 out(" delivery_rate %sbps", sprint_bw(b1, s->delivery_rate));
2f4d834b
ED
2606 if (s->delivered)
2607 out(" delivered:%u", s->delivered);
2608 if (s->delivered_ce)
2609 out(" delivered_ce:%u", s->delivered_ce);
2f579872 2610 if (s->app_limited)
90351722 2611 out(" app_limited");
2f579872 2612
b6c7fc61 2613 if (s->busy_time) {
90351722 2614 out(" busy:%llums", s->busy_time / 1000);
b6c7fc61 2615 if (s->rwnd_limited)
90351722
SB
2616 out(" rwnd_limited:%llums(%.1f%%)",
2617 s->rwnd_limited / 1000,
2618 100.0 * s->rwnd_limited / s->busy_time);
b6c7fc61 2619 if (s->sndbuf_limited)
90351722
SB
2620 out(" sndbuf_limited:%llums(%.1f%%)",
2621 s->sndbuf_limited / 1000,
2622 100.0 * s->sndbuf_limited / s->busy_time);
b6c7fc61
YC
2623 }
2624
8250bc9f 2625 if (s->unacked)
90351722 2626 out(" unacked:%u", s->unacked);
8250bc9f 2627 if (s->retrans || s->retrans_total)
90351722 2628 out(" retrans:%u/%u", s->retrans, s->retrans_total);
8250bc9f 2629 if (s->lost)
90351722 2630 out(" lost:%u", s->lost);
055840f2 2631 if (s->sacked && s->ss.state != SS_LISTEN)
90351722 2632 out(" sacked:%u", s->sacked);
5eead627
ED
2633 if (s->dsack_dups)
2634 out(" dsack_dups:%u", s->dsack_dups);
8250bc9f 2635 if (s->fackets)
90351722 2636 out(" fackets:%u", s->fackets);
8250bc9f 2637 if (s->reordering != 3)
90351722 2638 out(" reordering:%d", s->reordering);
5eead627
ED
2639 if (s->reord_seen)
2640 out(" reord_seen:%d", s->reord_seen);
8250bc9f 2641 if (s->rcv_rtt)
90351722 2642 out(" rcv_rtt:%g", s->rcv_rtt);
8250bc9f 2643 if (s->rcv_space)
90351722 2644 out(" rcv_space:%d", s->rcv_space);
00ac78d3 2645 if (s->rcv_ssthresh)
90351722 2646 out(" rcv_ssthresh:%u", s->rcv_ssthresh);
9e99e495 2647 if (s->not_sent)
90351722 2648 out(" notsent:%u", s->not_sent);
9e99e495 2649 if (s->min_rtt)
90351722 2650 out(" minrtt:%g", s->min_rtt);
8250bc9f
VK
2651}
2652
055840f2
VK
2653static void tcp_timer_print(struct tcpstat *s)
2654{
86dfa1be
PS
2655 static const char * const tmr_name[] = {
2656 "off",
2657 "on",
2658 "keepalive",
2659 "timewait",
2660 "persist",
2661 "unknown"
2662 };
2663
055840f2
VK
2664 if (s->timer) {
2665 if (s->timer > 4)
2666 s->timer = 5;
90351722
SB
2667 out(" timer:(%s,%s,%d)",
2668 tmr_name[s->timer],
2669 print_ms_timer(s->timeout),
2670 s->retrans);
055840f2
VK
2671 }
2672}
2673
f89d46ad
PS
2674static void sctp_timer_print(struct tcpstat *s)
2675{
2676 if (s->timer)
90351722
SB
2677 out(" timer:(T3_RTX,%s,%d)",
2678 print_ms_timer(s->timeout), s->retrans);
f89d46ad
PS
2679}
2680
8250bc9f
VK
2681static int tcp_show_line(char *line, const struct filter *f, int family)
2682{
2683 int rto = 0, ato = 0;
2684 struct tcpstat s = {};
2685 char *loc, *rem, *data;
2686 char opt[256];
2687 int n;
2688 int hz = get_user_hz();
2689
2690 if (proc_inet_split_line(line, &loc, &rem, &data))
2691 return -1;
2692
2693 int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0');
acd1e437 2694
8250bc9f
VK
2695 if (!(f->states & (1 << state)))
2696 return 0;
2697
055840f2 2698 proc_parse_inet_addr(loc, rem, family, &s.ss);
ae665a52 2699
055840f2 2700 if (f->f && run_ssfilter(f->f, &s.ss) == 0)
aba5acdf 2701 return 0;
ae665a52 2702
aba5acdf 2703 opt[0] = 0;
d1f338b3 2704 n = sscanf(data, "%x %x:%x %x:%x %x %d %d %u %d %llx %d %d %d %u %d %[^\n]\n",
055840f2
VK
2705 &s.ss.state, &s.ss.wq, &s.ss.rq,
2706 &s.timer, &s.timeout, &s.retrans, &s.ss.uid, &s.probes,
2707 &s.ss.ino, &s.ss.refcnt, &s.ss.sk, &rto, &ato, &s.qack, &s.cwnd,
2708 &s.ssthresh, opt);
ae665a52 2709
aba5acdf
SH
2710 if (n < 17)
2711 opt[0] = 0;
ae665a52 2712
aba5acdf 2713 if (n < 12) {
8250bc9f 2714 rto = 0;
aba5acdf
SH
2715 s.cwnd = 2;
2716 s.ssthresh = -1;
8250bc9f 2717 ato = s.qack = 0;
aba5acdf 2718 }
ae665a52 2719
8250bc9f
VK
2720 s.retrans = s.timer != 1 ? s.probes : s.retrans;
2721 s.timeout = (s.timeout * 1000 + hz - 1) / hz;
2722 s.ato = (double)ato / hz;
2723 s.qack /= 2;
2724 s.rto = (double)rto;
2725 s.ssthresh = s.ssthresh == -1 ? 0 : s.ssthresh;
2726 s.rto = s.rto != 3 * hz ? s.rto / hz : 0;
be7e4d20 2727 s.ss.type = IPPROTO_TCP;
ae665a52 2728
1267c0b9 2729 inet_stats_print(&s.ss, false);
055840f2
VK
2730
2731 if (show_options)
2732 tcp_timer_print(&s);
116ac927 2733
aba5acdf 2734 if (show_details) {
f1b39e1b 2735 sock_details_print(&s.ss);
aba5acdf 2736 if (opt[0])
90351722 2737 out(" opt:\"%s\"", opt);
aba5acdf 2738 }
aba5acdf 2739
8250bc9f
VK
2740 if (show_tcpinfo)
2741 tcp_stats_print(&s);
2742
aba5acdf
SH
2743 return 0;
2744}
2745
ab01dbbb
SH
2746static int generic_record_read(FILE *fp,
2747 int (*worker)(char*, const struct filter *, int),
2748 const struct filter *f, int fam)
aba5acdf 2749{
ab01dbbb 2750 char line[256];
aba5acdf 2751
ab01dbbb
SH
2752 /* skip header */
2753 if (fgets(line, sizeof(line), fp) == NULL)
aba5acdf 2754 goto outerr;
ab01dbbb
SH
2755
2756 while (fgets(line, sizeof(line), fp) != NULL) {
2757 int n = strlen(line);
acd1e437 2758
ab01dbbb
SH
2759 if (n == 0 || line[n-1] != '\n') {
2760 errno = -EINVAL;
2761 return -1;
aba5acdf 2762 }
ab01dbbb 2763 line[n-1] = 0;
aba5acdf 2764
ab01dbbb
SH
2765 if (worker(line, f, fam) < 0)
2766 return 0;
2767 }
aba5acdf 2768outerr:
ab01dbbb
SH
2769
2770 return ferror(fp) ? -1 : 0;
aba5acdf 2771}
ae665a52 2772
51ff9f24
HFS
2773static void print_skmeminfo(struct rtattr *tb[], int attrtype)
2774{
2775 const __u32 *skmeminfo;
db08bdb8
VK
2776
2777 if (!tb[attrtype]) {
2778 if (attrtype == INET_DIAG_SKMEMINFO) {
2779 if (!tb[INET_DIAG_MEMINFO])
2780 return;
2781
2782 const struct inet_diag_meminfo *minfo =
2783 RTA_DATA(tb[INET_DIAG_MEMINFO]);
2784
90351722
SB
2785 out(" mem:(r%u,w%u,f%u,t%u)",
2786 minfo->idiag_rmem,
2787 minfo->idiag_wmem,
2788 minfo->idiag_fmem,
2789 minfo->idiag_tmem);
db08bdb8 2790 }
51ff9f24 2791 return;
db08bdb8
VK
2792 }
2793
51ff9f24
HFS
2794 skmeminfo = RTA_DATA(tb[attrtype]);
2795
90351722
SB
2796 out(" skmem:(r%u,rb%u,t%u,tb%u,f%u,w%u,o%u",
2797 skmeminfo[SK_MEMINFO_RMEM_ALLOC],
2798 skmeminfo[SK_MEMINFO_RCVBUF],
2799 skmeminfo[SK_MEMINFO_WMEM_ALLOC],
2800 skmeminfo[SK_MEMINFO_SNDBUF],
2801 skmeminfo[SK_MEMINFO_FWD_ALLOC],
2802 skmeminfo[SK_MEMINFO_WMEM_QUEUED],
2803 skmeminfo[SK_MEMINFO_OPTMEM]);
51ff9f24
HFS
2804
2805 if (RTA_PAYLOAD(tb[attrtype]) >=
2806 (SK_MEMINFO_BACKLOG + 1) * sizeof(__u32))
90351722 2807 out(",bl%u", skmeminfo[SK_MEMINFO_BACKLOG]);
51ff9f24 2808
6df9c7a0
ED
2809 if (RTA_PAYLOAD(tb[attrtype]) >=
2810 (SK_MEMINFO_DROPS + 1) * sizeof(__u32))
90351722 2811 out(",d%u", skmeminfo[SK_MEMINFO_DROPS]);
6df9c7a0 2812
90351722 2813 out(")");
51ff9f24
HFS
2814}
2815
da9cc6ab
ID
2816static void print_md5sig(struct tcp_diag_md5sig *sig)
2817{
90351722
SB
2818 out("%s/%d=",
2819 format_host(sig->tcpm_family,
2820 sig->tcpm_family == AF_INET6 ? 16 : 4,
2821 &sig->tcpm_addr),
2822 sig->tcpm_prefixlen);
da9cc6ab
ID
2823 print_escape_buf(sig->tcpm_key, sig->tcpm_keylen, " ,");
2824}
2825
14cadc70
DC
2826static void tcp_tls_version(struct rtattr *attr)
2827{
2828 u_int16_t val;
2829
2830 if (!attr)
2831 return;
2832 val = rta_getattr_u16(attr);
2833
2834 switch (val) {
2835 case TLS_1_2_VERSION:
2836 out(" version: 1.2");
2837 break;
2838 case TLS_1_3_VERSION:
2839 out(" version: 1.3");
2840 break;
2841 default:
2842 out(" version: unknown(%hu)", val);
2843 break;
2844 }
2845}
2846
2847static void tcp_tls_cipher(struct rtattr *attr)
2848{
2849 u_int16_t val;
2850
2851 if (!attr)
2852 return;
2853 val = rta_getattr_u16(attr);
2854
2855 switch (val) {
2856 case TLS_CIPHER_AES_GCM_128:
2857 out(" cipher: aes-gcm-128");
2858 break;
2859 case TLS_CIPHER_AES_GCM_256:
2860 out(" cipher: aes-gcm-256");
2861 break;
2862 }
2863}
2864
2865static void tcp_tls_conf(const char *name, struct rtattr *attr)
2866{
2867 u_int16_t val;
2868
2869 if (!attr)
2870 return;
2871 val = rta_getattr_u16(attr);
2872
2873 switch (val) {
2874 case TLS_CONF_BASE:
2875 out(" %s: none", name);
2876 break;
2877 case TLS_CONF_SW:
2878 out(" %s: sw", name);
2879 break;
2880 case TLS_CONF_HW:
2881 out(" %s: hw", name);
2882 break;
2883 case TLS_CONF_HW_RECORD:
2884 out(" %s: hw-record", name);
2885 break;
2886 default:
2887 out(" %s: unknown(%hu)", name, val);
2888 break;
2889 }
2890}
2891
712fdd98
DC
2892static void mptcp_subflow_info(struct rtattr *tb[])
2893{
2894 u_int32_t flags = 0;
2895
2896 if (tb[MPTCP_SUBFLOW_ATTR_FLAGS]) {
2897 char caps[32 + 1] = { 0 }, *cap = &caps[0];
2898
2899 flags = rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_FLAGS]);
2900
2901 if (flags & MPTCP_SUBFLOW_FLAG_MCAP_REM)
2902 *cap++ = 'M';
2903 if (flags & MPTCP_SUBFLOW_FLAG_MCAP_LOC)
2904 *cap++ = 'm';
2905 if (flags & MPTCP_SUBFLOW_FLAG_JOIN_REM)
2906 *cap++ = 'J';
2907 if (flags & MPTCP_SUBFLOW_FLAG_JOIN_LOC)
2908 *cap++ = 'j';
2909 if (flags & MPTCP_SUBFLOW_FLAG_BKUP_REM)
2910 *cap++ = 'B';
2911 if (flags & MPTCP_SUBFLOW_FLAG_BKUP_LOC)
2912 *cap++ = 'b';
2913 if (flags & MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED)
2914 *cap++ = 'e';
2915 if (flags & MPTCP_SUBFLOW_FLAG_CONNECTED)
2916 *cap++ = 'c';
2917 if (flags & MPTCP_SUBFLOW_FLAG_MAPVALID)
2918 *cap++ = 'v';
2919 if (flags)
2920 out(" flags:%s", caps);
2921 }
2922 if (tb[MPTCP_SUBFLOW_ATTR_TOKEN_REM] &&
2923 tb[MPTCP_SUBFLOW_ATTR_TOKEN_LOC] &&
2924 tb[MPTCP_SUBFLOW_ATTR_ID_REM] &&
2925 tb[MPTCP_SUBFLOW_ATTR_ID_LOC])
2926 out(" token:%04x(id:%hhu)/%04x(id:%hhu)",
2927 rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_TOKEN_REM]),
2928 rta_getattr_u8(tb[MPTCP_SUBFLOW_ATTR_ID_REM]),
2929 rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_TOKEN_LOC]),
2930 rta_getattr_u8(tb[MPTCP_SUBFLOW_ATTR_ID_LOC]));
2931 if (tb[MPTCP_SUBFLOW_ATTR_MAP_SEQ])
2932 out(" seq:%llx",
2933 rta_getattr_u64(tb[MPTCP_SUBFLOW_ATTR_MAP_SEQ]));
2934 if (tb[MPTCP_SUBFLOW_ATTR_MAP_SFSEQ])
2935 out(" sfseq:%x",
2936 rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_MAP_SFSEQ]));
2937 if (tb[MPTCP_SUBFLOW_ATTR_SSN_OFFSET])
2938 out(" ssnoff:%x",
2939 rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_SSN_OFFSET]));
2940 if (tb[MPTCP_SUBFLOW_ATTR_MAP_DATALEN])
2941 out(" maplen:%x",
2942 rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_MAP_DATALEN]));
2943}
2944
8250bc9f
VK
2945#define TCPI_HAS_OPT(info, opt) !!(info->tcpi_options & (opt))
2946
5b816047
PE
2947static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
2948 struct rtattr *tb[])
7d105b56 2949{
b4b0b7d5 2950 double rtt = 0;
8250bc9f 2951 struct tcpstat s = {};
7d105b56 2952
055840f2
VK
2953 s.ss.state = r->idiag_state;
2954
db08bdb8 2955 print_skmeminfo(tb, INET_DIAG_SKMEMINFO);
7d105b56 2956
351efcde 2957 if (tb[INET_DIAG_INFO]) {
05e18118 2958 struct tcp_info *info;
351efcde 2959 int len = RTA_PAYLOAD(tb[INET_DIAG_INFO]);
05e18118
SH
2960
2961 /* workaround for older kernels with less fields */
2962 if (len < sizeof(*info)) {
2963 info = alloca(sizeof(*info));
351efcde 2964 memcpy(info, RTA_DATA(tb[INET_DIAG_INFO]), len);
656e8fdd 2965 memset((char *)info + len, 0, sizeof(*info) - len);
05e18118 2966 } else
351efcde 2967 info = RTA_DATA(tb[INET_DIAG_INFO]);
05e18118 2968
b4b0b7d5 2969 if (show_options) {
8250bc9f
VK
2970 s.has_ts_opt = TCPI_HAS_OPT(info, TCPI_OPT_TIMESTAMPS);
2971 s.has_sack_opt = TCPI_HAS_OPT(info, TCPI_OPT_SACK);
2972 s.has_ecn_opt = TCPI_HAS_OPT(info, TCPI_OPT_ECN);
2973 s.has_ecnseen_opt = TCPI_HAS_OPT(info, TCPI_OPT_ECN_SEEN);
2974 s.has_fastopen_opt = TCPI_HAS_OPT(info, TCPI_OPT_SYN_DATA);
b4b0b7d5 2975 }
52d5ac3f 2976
d2055ea5
ED
2977 if (tb[INET_DIAG_CONG])
2978 strncpy(s.cong_alg,
2979 rta_getattr_str(tb[INET_DIAG_CONG]),
2980 sizeof(s.cong_alg) - 1);
8250bc9f
VK
2981
2982 if (TCPI_HAS_OPT(info, TCPI_OPT_WSCALE)) {
2983 s.has_wscale_opt = true;
2984 s.snd_wscale = info->tcpi_snd_wscale;
2985 s.rcv_wscale = info->tcpi_rcv_wscale;
2986 }
ea8fc104 2987
7d105b56 2988 if (info->tcpi_rto && info->tcpi_rto != 3000000)
8250bc9f
VK
2989 s.rto = (double)info->tcpi_rto / 1000;
2990
2991 s.backoff = info->tcpi_backoff;
2992 s.rtt = (double)info->tcpi_rtt / 1000;
2993 s.rttvar = (double)info->tcpi_rttvar / 1000;
11ba90fc 2994 s.ato = (double)info->tcpi_ato / 1000;
8250bc9f 2995 s.mss = info->tcpi_snd_mss;
38e6dbc4
ED
2996 s.rcv_mss = info->tcpi_rcv_mss;
2997 s.advmss = info->tcpi_advmss;
8250bc9f
VK
2998 s.rcv_space = info->tcpi_rcv_space;
2999 s.rcv_rtt = (double)info->tcpi_rcv_rtt / 1000;
3000 s.lastsnd = info->tcpi_last_data_sent;
3001 s.lastrcv = info->tcpi_last_data_recv;
3002 s.lastack = info->tcpi_last_ack_recv;
3003 s.unacked = info->tcpi_unacked;
3004 s.retrans = info->tcpi_retrans;
3005 s.retrans_total = info->tcpi_total_retrans;
3006 s.lost = info->tcpi_lost;
3007 s.sacked = info->tcpi_sacked;
c4be5feb 3008 s.fackets = info->tcpi_fackets;
8250bc9f 3009 s.reordering = info->tcpi_reordering;
00ac78d3 3010 s.rcv_ssthresh = info->tcpi_rcv_ssthresh;
8250bc9f 3011 s.cwnd = info->tcpi_snd_cwnd;
3d791a32 3012 s.pmtu = info->tcpi_pmtu;
8250bc9f 3013
7d105b56 3014 if (info->tcpi_snd_ssthresh < 0xFFFF)
8250bc9f 3015 s.ssthresh = info->tcpi_snd_ssthresh;
52d5ac3f 3016
b4b0b7d5 3017 rtt = (double) info->tcpi_rtt;
351efcde 3018 if (tb[INET_DIAG_VEGASINFO]) {
05e18118 3019 const struct tcpvegas_info *vinfo
351efcde 3020 = RTA_DATA(tb[INET_DIAG_VEGASINFO]);
7d105b56 3021
ae665a52 3022 if (vinfo->tcpv_enabled &&
8250bc9f 3023 vinfo->tcpv_rtt && vinfo->tcpv_rtt != 0x7fffffff)
ea8fc104 3024 rtt = vinfo->tcpv_rtt;
b4b0b7d5
SH
3025 }
3026
907e1aca 3027 if (tb[INET_DIAG_DCTCPINFO]) {
8250bc9f
VK
3028 struct dctcpstat *dctcp = malloc(sizeof(struct
3029 dctcpstat));
3030
907e1aca
DB
3031 const struct tcp_dctcp_info *dinfo
3032 = RTA_DATA(tb[INET_DIAG_DCTCPINFO]);
3033
8250bc9f
VK
3034 dctcp->enabled = !!dinfo->dctcp_enabled;
3035 dctcp->ce_state = dinfo->dctcp_ce_state;
3036 dctcp->alpha = dinfo->dctcp_alpha;
3037 dctcp->ab_ecn = dinfo->dctcp_ab_ecn;
3038 dctcp->ab_tot = dinfo->dctcp_ab_tot;
3039 s.dctcp = dctcp;
907e1aca
DB
3040 }
3041
2f0f9aef
NC
3042 if (tb[INET_DIAG_BBRINFO]) {
3043 const void *bbr_info = RTA_DATA(tb[INET_DIAG_BBRINFO]);
3044 int len = min(RTA_PAYLOAD(tb[INET_DIAG_BBRINFO]),
3045 sizeof(*s.bbr_info));
3046
3047 s.bbr_info = calloc(1, sizeof(*s.bbr_info));
3048 if (s.bbr_info && bbr_info)
3049 memcpy(s.bbr_info, bbr_info, len);
3050 }
3051
b4b0b7d5 3052 if (rtt > 0 && info->tcpi_snd_mss && info->tcpi_snd_cwnd) {
8250bc9f
VK
3053 s.send_bps = (double) info->tcpi_snd_cwnd *
3054 (double)info->tcpi_snd_mss * 8000000. / rtt;
7d105b56 3055 }
b4b0b7d5 3056
eb6028b2 3057 if (info->tcpi_pacing_rate &&
8250bc9f
VK
3058 info->tcpi_pacing_rate != ~0ULL) {
3059 s.pacing_rate = info->tcpi_pacing_rate * 8.;
eb6028b2
ED
3060
3061 if (info->tcpi_max_pacing_rate &&
8250bc9f
VK
3062 info->tcpi_max_pacing_rate != ~0ULL)
3063 s.pacing_rate_max = info->tcpi_max_pacing_rate * 8.;
eb6028b2 3064 }
1a4dda71
ED
3065 s.bytes_acked = info->tcpi_bytes_acked;
3066 s.bytes_received = info->tcpi_bytes_received;
ecb435ea
CG
3067 s.segs_out = info->tcpi_segs_out;
3068 s.segs_in = info->tcpi_segs_in;
414aeec9
MKL
3069 s.data_segs_out = info->tcpi_data_segs_out;
3070 s.data_segs_in = info->tcpi_data_segs_in;
9e99e495 3071 s.not_sent = info->tcpi_notsent_bytes;
d9ba887e
ED
3072 if (info->tcpi_min_rtt && info->tcpi_min_rtt != ~0U)
3073 s.min_rtt = (double) info->tcpi_min_rtt / 1000;
2f579872
NC
3074 s.delivery_rate = info->tcpi_delivery_rate * 8.;
3075 s.app_limited = info->tcpi_delivery_rate_app_limited;
b6c7fc61
YC
3076 s.busy_time = info->tcpi_busy_time;
3077 s.rwnd_limited = info->tcpi_rwnd_limited;
3078 s.sndbuf_limited = info->tcpi_sndbuf_limited;
2f4d834b
ED
3079 s.delivered = info->tcpi_delivered;
3080 s.delivered_ce = info->tcpi_delivered_ce;
5eead627
ED
3081 s.dsack_dups = info->tcpi_dsack_dups;
3082 s.reord_seen = info->tcpi_reord_seen;
3083 s.bytes_sent = info->tcpi_bytes_sent;
3084 s.bytes_retrans = info->tcpi_bytes_retrans;
8250bc9f 3085 tcp_stats_print(&s);
92de1c2c 3086 free(s.dctcp);
2f0f9aef 3087 free(s.bbr_info);
77a8ca81 3088 }
da9cc6ab
ID
3089 if (tb[INET_DIAG_MD5SIG]) {
3090 struct tcp_diag_md5sig *sig = RTA_DATA(tb[INET_DIAG_MD5SIG]);
3091 int len = RTA_PAYLOAD(tb[INET_DIAG_MD5SIG]);
3092
90351722 3093 out(" md5keys:");
da9cc6ab
ID
3094 print_md5sig(sig++);
3095 for (len -= sizeof(*sig); len > 0; len -= sizeof(*sig)) {
90351722 3096 out(",");
da9cc6ab
ID
3097 print_md5sig(sig++);
3098 }
3099 }
14cadc70
DC
3100 if (tb[INET_DIAG_ULP_INFO]) {
3101 struct rtattr *ulpinfo[INET_ULP_INFO_MAX + 1] = { 0 };
3102
3103 parse_rtattr_nested(ulpinfo, INET_ULP_INFO_MAX,
3104 tb[INET_DIAG_ULP_INFO]);
3105
3106 if (ulpinfo[INET_ULP_INFO_NAME])
3107 out(" tcp-ulp-%s",
3108 rta_getattr_str(ulpinfo[INET_ULP_INFO_NAME]));
3109
3110 if (ulpinfo[INET_ULP_INFO_TLS]) {
3111 struct rtattr *tlsinfo[TLS_INFO_MAX + 1] = { 0 };
3112
3113 parse_rtattr_nested(tlsinfo, TLS_INFO_MAX,
3114 ulpinfo[INET_ULP_INFO_TLS]);
3115
3116 tcp_tls_version(tlsinfo[TLS_INFO_VERSION]);
3117 tcp_tls_cipher(tlsinfo[TLS_INFO_CIPHER]);
3118 tcp_tls_conf("rxconf", tlsinfo[TLS_INFO_RXCONF]);
3119 tcp_tls_conf("txconf", tlsinfo[TLS_INFO_TXCONF]);
3120 }
712fdd98
DC
3121 if (ulpinfo[INET_ULP_INFO_MPTCP]) {
3122 struct rtattr *sfinfo[MPTCP_SUBFLOW_ATTR_MAX + 1] =
3123 { 0 };
3124
3125 parse_rtattr_nested(sfinfo, MPTCP_SUBFLOW_ATTR_MAX,
3126 ulpinfo[INET_ULP_INFO_MPTCP]);
3127 mptcp_subflow_info(sfinfo);
3128 }
14cadc70 3129 }
77a8ca81
PE
3130}
3131
9c3be2c0
PA
3132static void mptcp_stats_print(struct mptcp_info *s)
3133{
3134 if (s->mptcpi_subflows)
3135 out(" subflows:%d", s->mptcpi_subflows);
3136 if (s->mptcpi_add_addr_signal)
3137 out(" add_addr_signal:%d", s->mptcpi_add_addr_signal);
3138 if (s->mptcpi_add_addr_signal)
3139 out(" add_addr_accepted:%d", s->mptcpi_add_addr_accepted);
3140 if (s->mptcpi_subflows_max)
3141 out(" subflows_max:%d", s->mptcpi_subflows_max);
3142 if (s->mptcpi_add_addr_signal_max)
3143 out(" add_addr_signal_max:%d", s->mptcpi_add_addr_signal_max);
3144 if (s->mptcpi_add_addr_accepted_max)
3145 out(" add_addr_accepted_max:%d", s->mptcpi_add_addr_accepted_max);
3146 if (s->mptcpi_flags & MPTCP_INFO_FLAG_FALLBACK)
3147 out(" fallback");
3148 if (s->mptcpi_flags & MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED)
3149 out(" remote_key");
3150 if (s->mptcpi_token)
3151 out(" token:%x", s->mptcpi_token);
3152 if (s->mptcpi_write_seq)
3153 out(" write_seq:%llx", s->mptcpi_write_seq);
3154 if (s->mptcpi_snd_una)
3155 out(" snd_una:%llx", s->mptcpi_snd_una);
3156 if (s->mptcpi_rcv_nxt)
3157 out(" rcv_nxt:%llx", s->mptcpi_rcv_nxt);
3158}
3159
3160static void mptcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
3161 struct rtattr *tb[])
3162{
3163 print_skmeminfo(tb, INET_DIAG_SKMEMINFO);
3164
3165 if (tb[INET_DIAG_INFO]) {
3166 struct mptcp_info *info;
3167 int len = RTA_PAYLOAD(tb[INET_DIAG_INFO]);
3168
3169 /* workaround for older kernels with less fields */
3170 if (len < sizeof(*info)) {
3171 info = alloca(sizeof(*info));
3172 memcpy(info, RTA_DATA(tb[INET_DIAG_INFO]), len);
3173 memset((char *)info + len, 0, sizeof(*info) - len);
3174 } else
3175 info = RTA_DATA(tb[INET_DIAG_INFO]);
3176
3177 mptcp_stats_print(info);
3178 }
3179}
3180
f89d46ad
PS
3181static const char *format_host_sa(struct sockaddr_storage *sa)
3182{
3183 union {
3184 struct sockaddr_in sin;
3185 struct sockaddr_in6 sin6;
3186 } *saddr = (void *)sa;
3187
3188 switch (sa->ss_family) {
3189 case AF_INET:
3190 return format_host(AF_INET, 4, &saddr->sin.sin_addr);
3191 case AF_INET6:
3192 return format_host(AF_INET6, 16, &saddr->sin6.sin6_addr);
3193 default:
3194 return "";
3195 }
3196}
3197
3198static void sctp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
3199 struct rtattr *tb[])
3200{
3201 struct sockaddr_storage *sa;
3202 int len;
3203
3204 print_skmeminfo(tb, INET_DIAG_SKMEMINFO);
3205
3206 if (tb[INET_DIAG_LOCALS]) {
3207 len = RTA_PAYLOAD(tb[INET_DIAG_LOCALS]);
3208 sa = RTA_DATA(tb[INET_DIAG_LOCALS]);
3209
2d7cb222 3210 out(" locals:%s", format_host_sa(sa));
f89d46ad 3211 for (sa++, len -= sizeof(*sa); len > 0; sa++, len -= sizeof(*sa))
90351722 3212 out(",%s", format_host_sa(sa));
f89d46ad
PS
3213
3214 }
3215 if (tb[INET_DIAG_PEERS]) {
3216 len = RTA_PAYLOAD(tb[INET_DIAG_PEERS]);
3217 sa = RTA_DATA(tb[INET_DIAG_PEERS]);
3218
90351722 3219 out(" peers:%s", format_host_sa(sa));
f89d46ad 3220 for (sa++, len -= sizeof(*sa); len > 0; sa++, len -= sizeof(*sa))
90351722 3221 out(",%s", format_host_sa(sa));
f89d46ad
PS
3222 }
3223 if (tb[INET_DIAG_INFO]) {
3224 struct sctp_info *info;
3225 len = RTA_PAYLOAD(tb[INET_DIAG_INFO]);
3226
3227 /* workaround for older kernels with less fields */
3228 if (len < sizeof(*info)) {
3229 info = alloca(sizeof(*info));
3230 memcpy(info, RTA_DATA(tb[INET_DIAG_INFO]), len);
3231 memset((char *)info + len, 0, sizeof(*info) - len);
3232 } else
3233 info = RTA_DATA(tb[INET_DIAG_INFO]);
3234
3235 sctp_stats_print(info);
3236 }
3237}
3238
82d73ea0 3239static void parse_diag_msg(struct nlmsghdr *nlh, struct sockstat *s)
aba5acdf 3240{
acd1e437 3241 struct rtattr *tb[INET_DIAG_MAX+1];
351efcde 3242 struct inet_diag_msg *r = NLMSG_DATA(nlh);
aba5acdf 3243
acd1e437 3244 parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr *)(r+1),
5b816047
PE
3245 nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
3246
82d73ea0
DA
3247 s->state = r->idiag_state;
3248 s->local.family = s->remote.family = r->idiag_family;
3249 s->lport = ntohs(r->id.idiag_sport);
3250 s->rport = ntohs(r->id.idiag_dport);
3251 s->wq = r->idiag_wqueue;
3252 s->rq = r->idiag_rqueue;
3253 s->ino = r->idiag_inode;
3254 s->uid = r->idiag_uid;
3255 s->iface = r->id.idiag_if;
3256 s->sk = cookie_sk_get(&r->id.idiag_cookie[0]);
3257
ec75249b
LC
3258 s->mark = 0;
3259 if (tb[INET_DIAG_MARK])
9f1370c0 3260 s->mark = rta_getattr_u32(tb[INET_DIAG_MARK]);
14f4bda5
DY
3261 s->cgroup_id = 0;
3262 if (tb[INET_DIAG_CGROUP_ID])
3263 s->cgroup_id = rta_getattr_u64(tb[INET_DIAG_CGROUP_ID]);
41fe6c34 3264 if (tb[INET_DIAG_PROTOCOL])
9f1370c0 3265 s->raw_prot = rta_getattr_u8(tb[INET_DIAG_PROTOCOL]);
41fe6c34
CG
3266 else
3267 s->raw_prot = 0;
ec75249b 3268
82d73ea0
DA
3269 if (s->local.family == AF_INET)
3270 s->local.bytelen = s->remote.bytelen = 4;
3271 else
3272 s->local.bytelen = s->remote.bytelen = 16;
8250bc9f 3273
82d73ea0
DA
3274 memcpy(s->local.data, r->id.idiag_src, s->local.bytelen);
3275 memcpy(s->remote.data, r->id.idiag_dst, s->local.bytelen);
3276}
aba5acdf 3277
82d73ea0 3278static int inet_show_sock(struct nlmsghdr *nlh,
be7e4d20 3279 struct sockstat *s)
82d73ea0
DA
3280{
3281 struct rtattr *tb[INET_DIAG_MAX+1];
3282 struct inet_diag_msg *r = NLMSG_DATA(nlh);
1267c0b9 3283 unsigned char v6only = 0;
82d73ea0
DA
3284
3285 parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr *)(r+1),
3286 nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
aba5acdf 3287
6885e3bf 3288 if (tb[INET_DIAG_PROTOCOL])
9f1370c0 3289 s->type = rta_getattr_u8(tb[INET_DIAG_PROTOCOL]);
6885e3bf 3290
1267c0b9
PS
3291 if (s->local.family == AF_INET6 && tb[INET_DIAG_SKV6ONLY])
3292 v6only = rta_getattr_u8(tb[INET_DIAG_SKV6ONLY]);
3293
3294 inet_stats_print(s, v6only);
116ac927 3295
055840f2
VK
3296 if (show_options) {
3297 struct tcpstat t = {};
3298
3299 t.timer = r->idiag_timer;
3300 t.timeout = r->idiag_expires;
3301 t.retrans = r->idiag_retrans;
be7e4d20 3302 if (s->type == IPPROTO_SCTP)
f89d46ad
PS
3303 sctp_timer_print(&t);
3304 else
3305 tcp_timer_print(&t);
055840f2
VK
3306 }
3307
aba5acdf 3308 if (show_details) {
82d73ea0 3309 sock_details_print(s);
1267c0b9 3310 if (s->local.family == AF_INET6 && tb[INET_DIAG_SKV6ONLY])
90351722 3311 out(" v6only:%u", v6only);
1267c0b9 3312
5b816047
PE
3313 if (tb[INET_DIAG_SHUTDOWN]) {
3314 unsigned char mask;
acd1e437 3315
9f1370c0 3316 mask = rta_getattr_u8(tb[INET_DIAG_SHUTDOWN]);
90351722
SB
3317 out(" %c-%c",
3318 mask & 1 ? '-' : '<', mask & 2 ? '-' : '>');
5b816047 3319 }
aba5acdf 3320 }
8250bc9f 3321
0f3f0ca3
KK
3322 if (show_tos) {
3323 if (tb[INET_DIAG_TOS])
3324 out(" tos:%#x", rta_getattr_u8(tb[INET_DIAG_TOS]));
3325 if (tb[INET_DIAG_TCLASS])
3326 out(" tclass:%#x", rta_getattr_u8(tb[INET_DIAG_TCLASS]));
3327 if (tb[INET_DIAG_CLASS_ID])
3328 out(" class_id:%#x", rta_getattr_u32(tb[INET_DIAG_CLASS_ID]));
3329 }
3330
14f4bda5
DY
3331 if (show_cgroup) {
3332 if (tb[INET_DIAG_CGROUP_ID])
3333 out(" cgroup:%s", cg_id_to_path(rta_getattr_u64(tb[INET_DIAG_CGROUP_ID])));
3334 }
3335
be7e4d20 3336 if (show_mem || (show_tcpinfo && s->type != IPPROTO_UDP)) {
296b5de7
JH
3337 if (!oneline)
3338 out("\n\t");
be7e4d20 3339 if (s->type == IPPROTO_SCTP)
f89d46ad 3340 sctp_show_info(nlh, r, tb);
9c3be2c0
PA
3341 else if (s->type == IPPROTO_MPTCP)
3342 mptcp_show_info(nlh, r, tb);
f89d46ad
PS
3343 else
3344 tcp_show_info(nlh, r, tb);
aba5acdf 3345 }
f89d46ad 3346 sctp_ino = s->ino;
7d105b56 3347
aba5acdf 3348 return 0;
aba5acdf
SH
3349}
3350
746a695f 3351static int tcpdiag_send(int fd, int protocol, struct filter *f)
aba5acdf 3352{
d17b136f 3353 struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
aba5acdf
SH
3354 struct {
3355 struct nlmsghdr nlh;
351efcde 3356 struct inet_diag_req r;
d17b136f
PS
3357 } req = {
3358 .nlh.nlmsg_len = sizeof(req),
3359 .nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST,
3360 .nlh.nlmsg_seq = MAGIC_SEQ,
3361 .r.idiag_family = AF_INET,
3362 .r.idiag_states = f->states,
3363 };
aba5acdf
SH
3364 char *bc = NULL;
3365 int bclen;
3366 struct msghdr msg;
3367 struct rtattr rta;
aba5acdf 3368 struct iovec iov[3];
376fb868 3369 int iovlen = 1;
aba5acdf 3370
346f8ca8
PE
3371 if (protocol == IPPROTO_UDP)
3372 return -1;
3373
3fe5b534
PE
3374 if (protocol == IPPROTO_TCP)
3375 req.nlh.nlmsg_type = TCPDIAG_GETSOCK;
3376 else
3377 req.nlh.nlmsg_type = DCCPDIAG_GETSOCK;
910b0397 3378 if (show_mem) {
ae665a52 3379 req.r.idiag_ext |= (1<<(INET_DIAG_MEMINFO-1));
910b0397
SW
3380 req.r.idiag_ext |= (1<<(INET_DIAG_SKMEMINFO-1));
3381 }
b4b0b7d5 3382
7d105b56 3383 if (show_tcpinfo) {
351efcde
SH
3384 req.r.idiag_ext |= (1<<(INET_DIAG_INFO-1));
3385 req.r.idiag_ext |= (1<<(INET_DIAG_VEGASINFO-1));
3386 req.r.idiag_ext |= (1<<(INET_DIAG_CONG-1));
7d105b56 3387 }
aba5acdf 3388
0f3f0ca3
KK
3389 if (show_tos) {
3390 req.r.idiag_ext |= (1<<(INET_DIAG_TOS-1));
3391 req.r.idiag_ext |= (1<<(INET_DIAG_TCLASS-1));
3392 }
3393
ae665a52
SH
3394 iov[0] = (struct iovec){
3395 .iov_base = &req,
3396 .iov_len = sizeof(req)
ea8fc104 3397 };
aba5acdf
SH
3398 if (f->f) {
3399 bclen = ssfilter_bytecompile(f->f, &bc);
376fb868
DA
3400 if (bclen) {
3401 rta.rta_type = INET_DIAG_REQ_BYTECODE;
3402 rta.rta_len = RTA_LENGTH(bclen);
3403 iov[1] = (struct iovec){ &rta, sizeof(rta) };
3404 iov[2] = (struct iovec){ bc, bclen };
3405 req.nlh.nlmsg_len += RTA_LENGTH(bclen);
3406 iovlen = 3;
3407 }
aba5acdf
SH
3408 }
3409
3410 msg = (struct msghdr) {
acd1e437 3411 .msg_name = (void *)&nladdr,
ea8fc104 3412 .msg_namelen = sizeof(nladdr),
ae665a52 3413 .msg_iov = iov,
376fb868 3414 .msg_iovlen = iovlen,
aba5acdf
SH
3415 };
3416
930a75f9
ED
3417 if (sendmsg(fd, &msg, 0) < 0) {
3418 close(fd);
aba5acdf 3419 return -1;
930a75f9 3420 }
aba5acdf 3421
746a695f
PE
3422 return 0;
3423}
3424
886d19d6
PE
3425static int sockdiag_send(int family, int fd, int protocol, struct filter *f)
3426{
d17b136f 3427 struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
5fb421d4 3428 DIAG_REQUEST(req, struct inet_diag_req_v2 r);
886d19d6
PE
3429 char *bc = NULL;
3430 int bclen;
9c3be2c0 3431 __u32 proto;
886d19d6 3432 struct msghdr msg;
9c3be2c0
PA
3433 struct rtattr rta_bc;
3434 struct rtattr rta_proto;
3435 struct iovec iov[5];
376fb868 3436 int iovlen = 1;
886d19d6
PE
3437
3438 if (family == PF_UNSPEC)
3439 return tcpdiag_send(fd, protocol, f);
3440
886d19d6
PE
3441 memset(&req.r, 0, sizeof(req.r));
3442 req.r.sdiag_family = family;
3443 req.r.sdiag_protocol = protocol;
3444 req.r.idiag_states = f->states;
3445 if (show_mem) {
3446 req.r.idiag_ext |= (1<<(INET_DIAG_MEMINFO-1));
3447 req.r.idiag_ext |= (1<<(INET_DIAG_SKMEMINFO-1));
3448 }
3449
3450 if (show_tcpinfo) {
3451 req.r.idiag_ext |= (1<<(INET_DIAG_INFO-1));
3452 req.r.idiag_ext |= (1<<(INET_DIAG_VEGASINFO-1));
3453 req.r.idiag_ext |= (1<<(INET_DIAG_CONG-1));
3454 }
3455
0f3f0ca3
KK
3456 if (show_tos) {
3457 req.r.idiag_ext |= (1<<(INET_DIAG_TOS-1));
3458 req.r.idiag_ext |= (1<<(INET_DIAG_TCLASS-1));
3459 }
3460
886d19d6
PE
3461 iov[0] = (struct iovec){
3462 .iov_base = &req,
3463 .iov_len = sizeof(req)
3464 };
3465 if (f->f) {
3466 bclen = ssfilter_bytecompile(f->f, &bc);
376fb868 3467 if (bclen) {
9c3be2c0
PA
3468 rta_bc.rta_type = INET_DIAG_REQ_BYTECODE;
3469 rta_bc.rta_len = RTA_LENGTH(bclen);
3470 iov[1] = (struct iovec){ &rta_bc, sizeof(rta_bc) };
376fb868
DA
3471 iov[2] = (struct iovec){ bc, bclen };
3472 req.nlh.nlmsg_len += RTA_LENGTH(bclen);
3473 iovlen = 3;
3474 }
886d19d6
PE
3475 }
3476
9c3be2c0
PA
3477 /* put extended protocol attribute, if required */
3478 if (protocol > 255) {
3479 rta_proto.rta_type = INET_DIAG_REQ_PROTOCOL;
3480 rta_proto.rta_len = RTA_LENGTH(sizeof(proto));
3481 proto = protocol;
3482 iov[iovlen] = (struct iovec){ &rta_proto, sizeof(rta_proto) };
3483 iov[iovlen + 1] = (struct iovec){ &proto, sizeof(proto) };
3484 req.nlh.nlmsg_len += RTA_LENGTH(sizeof(proto));
3485 iovlen += 2;
3486 }
3487
886d19d6 3488 msg = (struct msghdr) {
acd1e437 3489 .msg_name = (void *)&nladdr,
886d19d6
PE
3490 .msg_namelen = sizeof(nladdr),
3491 .msg_iov = iov,
376fb868 3492 .msg_iovlen = iovlen,
886d19d6
PE
3493 };
3494
3495 if (sendmsg(fd, &msg, 0) < 0) {
3496 close(fd);
3497 return -1;
3498 }
3499
3500 return 0;
3501}
3502
486ccd99
VK
3503struct inet_diag_arg {
3504 struct filter *f;
3505 int protocol;
fb2594c1 3506 struct rtnl_handle *rth;
486ccd99 3507};
aba5acdf 3508
41fe6c34 3509static int kill_inet_sock(struct nlmsghdr *h, void *arg, struct sockstat *s)
fb2594c1
LC
3510{
3511 struct inet_diag_msg *d = NLMSG_DATA(h);
3512 struct inet_diag_arg *diag_arg = arg;
3513 struct rtnl_handle *rth = diag_arg->rth;
acd1e437 3514
fb2594c1
LC
3515 DIAG_REQUEST(req, struct inet_diag_req_v2 r);
3516
3517 req.nlh.nlmsg_type = SOCK_DESTROY;
3518 req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
3519 req.nlh.nlmsg_seq = ++rth->seq;
3520 req.r.sdiag_family = d->idiag_family;
3521 req.r.sdiag_protocol = diag_arg->protocol;
3522 req.r.id = d->id;
3523
41fe6c34
CG
3524 if (diag_arg->protocol == IPPROTO_RAW) {
3525 struct inet_diag_req_raw *raw = (void *)&req.r;
3526
3527 BUILD_BUG_ON(sizeof(req.r) != sizeof(*raw));
3528 raw->sdiag_raw_protocol = s->raw_prot;
3529 }
3530
86bf43c7 3531 return rtnl_talk(rth, &req.nlh, NULL);
fb2594c1
LC
3532}
3533
cd554f2c 3534static int show_one_inet_sock(struct nlmsghdr *h, void *arg)
486ccd99
VK
3535{
3536 int err;
3537 struct inet_diag_arg *diag_arg = arg;
3538 struct inet_diag_msg *r = NLMSG_DATA(h);
82d73ea0 3539 struct sockstat s = {};
aba5acdf 3540
b338a3e7 3541 if (!(diag_arg->f->families & FAMILY_MASK(r->idiag_family)))
486ccd99 3542 return 0;
82d73ea0
DA
3543
3544 parse_diag_msg(h, &s);
be7e4d20 3545 s.type = diag_arg->protocol;
82d73ea0
DA
3546
3547 if (diag_arg->f->f && run_ssfilter(diag_arg->f->f, &s) == 0)
3548 return 0;
3549
41fe6c34 3550 if (diag_arg->f->kill && kill_inet_sock(h, arg, &s) != 0) {
fb2594c1
LC
3551 if (errno == EOPNOTSUPP || errno == ENOENT) {
3552 /* Socket can't be closed, or is already closed. */
3553 return 0;
3554 } else {
3555 perror("SOCK_DESTROY answers");
3556 return -1;
3557 }
3558 }
82d73ea0 3559
be7e4d20 3560 err = inet_show_sock(h, &s);
82d73ea0 3561 if (err < 0)
486ccd99 3562 return err;
aba5acdf 3563
486ccd99
VK
3564 return 0;
3565}
886d19d6 3566
486ccd99
VK
3567static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol)
3568{
3569 int err = 0;
fb2594c1 3570 struct rtnl_handle rth, rth2;
486ccd99
VK
3571 int family = PF_INET;
3572 struct inet_diag_arg arg = { .f = f, .protocol = protocol };
886d19d6 3573
486ccd99
VK
3574 if (rtnl_open_byproto(&rth, 0, NETLINK_SOCK_DIAG))
3575 return -1;
fb2594c1
LC
3576
3577 if (f->kill) {
3578 if (rtnl_open_byproto(&rth2, 0, NETLINK_SOCK_DIAG)) {
3579 rtnl_close(&rth);
3580 return -1;
3581 }
3582 arg.rth = &rth2;
3583 }
3584
486ccd99
VK
3585 rth.dump = MAGIC_SEQ;
3586 rth.dump_fp = dump_fp;
518af1e0
ED
3587 if (preferred_family == PF_INET6)
3588 family = PF_INET6;
886d19d6 3589
486ccd99
VK
3590again:
3591 if ((err = sockdiag_send(family, rth.fd, protocol, f)))
3592 goto Exit;
aba5acdf 3593
486ccd99
VK
3594 if ((err = rtnl_dump_filter(&rth, show_one_inet_sock, &arg))) {
3595 if (family != PF_UNSPEC) {
3596 family = PF_UNSPEC;
3597 goto again;
aba5acdf 3598 }
486ccd99 3599 goto Exit;
aba5acdf 3600 }
518af1e0 3601 if (family == PF_INET && preferred_family != PF_INET) {
886d19d6
PE
3602 family = PF_INET6;
3603 goto again;
3604 }
3605
486ccd99
VK
3606Exit:
3607 rtnl_close(&rth);
fb2594c1
LC
3608 if (arg.rth)
3609 rtnl_close(arg.rth);
486ccd99 3610 return err;
aba5acdf
SH
3611}
3612
ab01dbbb 3613static int tcp_show_netlink_file(struct filter *f)
aba5acdf
SH
3614{
3615 FILE *fp;
e557212e 3616 char buf[16384];
4b45ae22 3617 int err = -1;
aba5acdf
SH
3618
3619 if ((fp = fopen(getenv("TCPDIAG_FILE"), "r")) == NULL) {
3620 perror("fopen($TCPDIAG_FILE)");
4b45ae22 3621 return err;
aba5acdf
SH
3622 }
3623
3624 while (1) {
eca51239
3625 int err2;
3626 size_t status, nitems;
acd1e437 3627 struct nlmsghdr *h = (struct nlmsghdr *)buf;
82d73ea0 3628 struct sockstat s = {};
aba5acdf
SH
3629
3630 status = fread(buf, 1, sizeof(*h), fp);
aba5acdf 3631 if (status != sizeof(*h)) {
eca51239
3632 if (ferror(fp))
3633 perror("Reading header from $TCPDIAG_FILE");
3634 if (feof(fp))
3635 fprintf(stderr, "Unexpected EOF reading $TCPDIAG_FILE");
4b45ae22 3636 break;
aba5acdf
SH
3637 }
3638
eca51239
3639 nitems = NLMSG_ALIGN(h->nlmsg_len - sizeof(*h));
3640 status = fread(h+1, 1, nitems, fp);
aba5acdf 3641
eca51239
3642 if (status != nitems) {
3643 if (ferror(fp))
3644 perror("Reading $TCPDIAG_FILE");
3645 if (feof(fp))
3646 fprintf(stderr, "Unexpected EOF reading $TCPDIAG_FILE");
4b45ae22 3647 break;
aba5acdf
SH
3648 }
3649
3650 /* The only legal exit point */
4b45ae22
PS
3651 if (h->nlmsg_type == NLMSG_DONE) {
3652 err = 0;
3653 break;
3654 }
aba5acdf
SH
3655
3656 if (h->nlmsg_type == NLMSG_ERROR) {
acd1e437
SH
3657 struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(h);
3658
aba5acdf
SH
3659 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
3660 fprintf(stderr, "ERROR truncated\n");
3661 } else {
3662 errno = -err->error;
3663 perror("TCPDIAG answered");
3664 }
4b45ae22 3665 break;
aba5acdf
SH
3666 }
3667
82d73ea0 3668 parse_diag_msg(h, &s);
be7e4d20 3669 s.type = IPPROTO_TCP;
82d73ea0
DA
3670
3671 if (f && f->f && run_ssfilter(f->f, &s) == 0)
3672 continue;
3673
4b45ae22
PS
3674 err2 = inet_show_sock(h, &s);
3675 if (err2 < 0) {
3676 err = err2;
3677 break;
3678 }
aba5acdf 3679 }
4b45ae22
PS
3680
3681 fclose(fp);
3682 return err;
aba5acdf
SH
3683}
3684
6c6bbc30 3685static int tcp_show(struct filter *f)
aba5acdf 3686{
ab01dbbb 3687 FILE *fp = NULL;
aba5acdf 3688 char *buf = NULL;
10f68773 3689 int bufsize = 1024*1024;
aba5acdf 3690
1527a17e
VK
3691 if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
3692 return 0;
3693
aba5acdf
SH
3694 dg_proto = TCP_PROTO;
3695
3696 if (getenv("TCPDIAG_FILE"))
3697 return tcp_show_netlink_file(f);
3698
3699 if (!getenv("PROC_NET_TCP") && !getenv("PROC_ROOT")
6c6bbc30 3700 && inet_show_netlink(f, NULL, IPPROTO_TCP) == 0)
aba5acdf
SH
3701 return 0;
3702
3703 /* Sigh... We have to parse /proc/net/tcp... */
aba5acdf
SH
3704 while (bufsize >= 64*1024) {
3705 if ((buf = malloc(bufsize)) != NULL)
3706 break;
3707 bufsize /= 2;
3708 }
3709 if (buf == NULL) {
3710 errno = ENOMEM;
3711 return -1;
3712 }
3713
b338a3e7 3714 if (f->families & FAMILY_MASK(AF_INET)) {
69cae645 3715 if ((fp = net_tcp_open()) == NULL)
aba5acdf 3716 goto outerr;
ab01dbbb
SH
3717
3718 setbuffer(fp, buf, bufsize);
3719 if (generic_record_read(fp, tcp_show_line, f, AF_INET))
aba5acdf 3720 goto outerr;
ab01dbbb 3721 fclose(fp);
aba5acdf
SH
3722 }
3723
b338a3e7 3724 if ((f->families & FAMILY_MASK(AF_INET6)) &&
69cae645 3725 (fp = net_tcp6_open()) != NULL) {
ab01dbbb
SH
3726 setbuffer(fp, buf, bufsize);
3727 if (generic_record_read(fp, tcp_show_line, f, AF_INET6))
aba5acdf 3728 goto outerr;
ab01dbbb 3729 fclose(fp);
aba5acdf
SH
3730 }
3731
3732 free(buf);
3733 return 0;
3734
3735outerr:
3736 do {
3737 int saved_errno = errno;
acd1e437 3738
92de1c2c 3739 free(buf);
ab01dbbb
SH
3740 if (fp)
3741 fclose(fp);
aba5acdf
SH
3742 errno = saved_errno;
3743 return -1;
3744 } while (0);
3745}
3746
9c3be2c0
PA
3747static int mptcp_show(struct filter *f)
3748{
3749 if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
3750 return 0;
3751
3752 if (!getenv("PROC_NET_MPTCP") && !getenv("PROC_ROOT")
3753 && inet_show_netlink(f, NULL, IPPROTO_MPTCP) == 0)
3754 return 0;
3755
3756 return 0;
3757}
3758
6c6bbc30
PS
3759static int dccp_show(struct filter *f)
3760{
3761 if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
3762 return 0;
3763
3764 if (!getenv("PROC_NET_DCCP") && !getenv("PROC_ROOT")
3765 && inet_show_netlink(f, NULL, IPPROTO_DCCP) == 0)
3766 return 0;
3767
3768 return 0;
3769}
3770
f89d46ad
PS
3771static int sctp_show(struct filter *f)
3772{
3773 if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
3774 return 0;
3775
3776 if (!getenv("PROC_NET_SCTP") && !getenv("PROC_ROOT")
3777 && inet_show_netlink(f, NULL, IPPROTO_SCTP) == 0)
3778 return 0;
3779
3780 return 0;
3781}
aba5acdf 3782
d1f28cf1 3783static int dgram_show_line(char *line, const struct filter *f, int family)
aba5acdf 3784{
055840f2 3785 struct sockstat s = {};
aba5acdf
SH
3786 char *loc, *rem, *data;
3787 char opt[256];
3788 int n;
aba5acdf 3789
8250bc9f 3790 if (proc_inet_split_line(line, &loc, &rem, &data))
aba5acdf 3791 return -1;
aba5acdf 3792
8250bc9f 3793 int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0');
acd1e437 3794
8250bc9f
VK
3795 if (!(f->states & (1 << state)))
3796 return 0;
aba5acdf 3797
8250bc9f 3798 proc_parse_inet_addr(loc, rem, family, &s);
aba5acdf
SH
3799
3800 if (f->f && run_ssfilter(f->f, &s) == 0)
3801 return 0;
3802
3803 opt[0] = 0;
e7113c61 3804 n = sscanf(data, "%x %x:%x %*x:%*x %*x %d %*d %u %d %llx %[^\n]\n",
aba5acdf
SH
3805 &s.state, &s.wq, &s.rq,
3806 &s.uid, &s.ino,
3807 &s.refcnt, &s.sk, opt);
3808
3809 if (n < 9)
3810 opt[0] = 0;
3811
be7e4d20 3812 s.type = dg_proto == UDP_PROTO ? IPPROTO_UDP : 0;
1267c0b9 3813 inet_stats_print(&s, false);
aba5acdf 3814
f1b39e1b 3815 if (show_details && opt[0])
90351722 3816 out(" opt:\"%s\"", opt);
aba5acdf
SH
3817
3818 return 0;
3819}
3820
d1f28cf1 3821static int udp_show(struct filter *f)
aba5acdf 3822{
ab01dbbb 3823 FILE *fp = NULL;
aba5acdf 3824
1527a17e
VK
3825 if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
3826 return 0;
3827
ace5cb31
VK
3828 dg_proto = UDP_PROTO;
3829
346f8ca8
PE
3830 if (!getenv("PROC_NET_UDP") && !getenv("PROC_ROOT")
3831 && inet_show_netlink(f, NULL, IPPROTO_UDP) == 0)
3832 return 0;
3833
b338a3e7 3834 if (f->families&FAMILY_MASK(AF_INET)) {
69cae645 3835 if ((fp = net_udp_open()) == NULL)
aba5acdf 3836 goto outerr;
ab01dbbb 3837 if (generic_record_read(fp, dgram_show_line, f, AF_INET))
aba5acdf 3838 goto outerr;
ab01dbbb 3839 fclose(fp);
aba5acdf
SH
3840 }
3841
b338a3e7 3842 if ((f->families&FAMILY_MASK(AF_INET6)) &&
69cae645 3843 (fp = net_udp6_open()) != NULL) {
ab01dbbb 3844 if (generic_record_read(fp, dgram_show_line, f, AF_INET6))
aba5acdf 3845 goto outerr;
ab01dbbb 3846 fclose(fp);
aba5acdf
SH
3847 }
3848 return 0;
3849
3850outerr:
3851 do {
3852 int saved_errno = errno;
acd1e437 3853
ab01dbbb
SH
3854 if (fp)
3855 fclose(fp);
aba5acdf
SH
3856 errno = saved_errno;
3857 return -1;
3858 } while (0);
3859}
3860
d1f28cf1 3861static int raw_show(struct filter *f)
aba5acdf 3862{
ab01dbbb 3863 FILE *fp = NULL;
aba5acdf 3864
1527a17e
VK
3865 if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
3866 return 0;
3867
aba5acdf
SH
3868 dg_proto = RAW_PROTO;
3869
41fe6c34
CG
3870 if (!getenv("PROC_NET_RAW") && !getenv("PROC_ROOT") &&
3871 inet_show_netlink(f, NULL, IPPROTO_RAW) == 0)
3872 return 0;
3873
b338a3e7 3874 if (f->families&FAMILY_MASK(AF_INET)) {
69cae645 3875 if ((fp = net_raw_open()) == NULL)
aba5acdf 3876 goto outerr;
ab01dbbb 3877 if (generic_record_read(fp, dgram_show_line, f, AF_INET))
aba5acdf 3878 goto outerr;
ab01dbbb 3879 fclose(fp);
aba5acdf
SH
3880 }
3881
b338a3e7 3882 if ((f->families&FAMILY_MASK(AF_INET6)) &&
69cae645 3883 (fp = net_raw6_open()) != NULL) {
ab01dbbb 3884 if (generic_record_read(fp, dgram_show_line, f, AF_INET6))
aba5acdf 3885 goto outerr;
ab01dbbb 3886 fclose(fp);
aba5acdf
SH
3887 }
3888 return 0;
3889
3890outerr:
3891 do {
3892 int saved_errno = errno;
acd1e437 3893
ab01dbbb
SH
3894 if (fp)
3895 fclose(fp);
aba5acdf
SH
3896 errno = saved_errno;
3897 return -1;
3898 } while (0);
3899}
3900
ec4d0d8a 3901#define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct sockstat))
aba5acdf 3902
2d0e538f 3903static void unix_list_drop_first(struct sockstat **list)
aba5acdf 3904{
2d0e538f 3905 struct sockstat *s = *list;
ec4d0d8a 3906
2d0e538f
PS
3907 (*list) = (*list)->next;
3908 free(s->name);
3909 free(s);
aba5acdf
SH
3910}
3911
ec4d0d8a 3912static bool unix_type_skip(struct sockstat *s, struct filter *f)
bf4ceee6
VK
3913{
3914 if (s->type == SOCK_STREAM && !(f->dbs&(1<<UNIX_ST_DB)))
3915 return true;
3916 if (s->type == SOCK_DGRAM && !(f->dbs&(1<<UNIX_DG_DB)))
3917 return true;
3918 if (s->type == SOCK_SEQPACKET && !(f->dbs&(1<<UNIX_SQ_DB)))
3919 return true;
3920 return false;
3921}
3922
2d0e538f 3923static void unix_stats_print(struct sockstat *s, struct filter *f)
aba5acdf 3924{
b217df10 3925 char port_name[30] = {};
aba5acdf 3926
2d0e538f 3927 sock_state_print(s);
2d791bc8 3928
2d0e538f
PS
3929 sock_addr_print(s->name ?: "*", " ",
3930 int_to_str(s->lport, port_name), NULL);
3931 sock_addr_print(s->peer_name ?: "*", " ",
3932 int_to_str(s->rport, port_name), NULL);
116ac927 3933
2d0e538f 3934 proc_ctx_print(s);
aba5acdf
SH
3935}
3936
cd554f2c 3937static int unix_show_sock(struct nlmsghdr *nlh, void *arg)
dfbaa90d 3938{
8a4025f6 3939 struct filter *f = (struct filter *)arg;
dfbaa90d
PE
3940 struct unix_diag_msg *r = NLMSG_DATA(nlh);
3941 struct rtattr *tb[UNIX_DIAG_MAX+1];
99bb68ff
VK
3942 char name[128];
3943 struct sockstat stat = { .name = "*", .peer_name = "*" };
dfbaa90d 3944
acd1e437 3945 parse_rtattr(tb, UNIX_DIAG_MAX, (struct rtattr *)(r+1),
dfbaa90d
PE
3946 nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
3947
bf4ceee6
VK
3948 stat.type = r->udiag_type;
3949 stat.state = r->udiag_state;
ec4d0d8a
VK
3950 stat.ino = stat.lport = r->udiag_ino;
3951 stat.local.family = stat.remote.family = AF_UNIX;
0d2e01c5 3952
bf4ceee6
VK
3953 if (unix_type_skip(&stat, f))
3954 return 0;
dfbaa90d 3955
defd61ca
HFS
3956 if (tb[UNIX_DIAG_RQLEN]) {
3957 struct unix_diag_rqlen *rql = RTA_DATA(tb[UNIX_DIAG_RQLEN]);
acd1e437 3958
bf4ceee6
VK
3959 stat.rq = rql->udiag_rqueue;
3960 stat.wq = rql->udiag_wqueue;
defd61ca 3961 }
dfbaa90d
PE
3962 if (tb[UNIX_DIAG_NAME]) {
3963 int len = RTA_PAYLOAD(tb[UNIX_DIAG_NAME]);
3964
3965 memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len);
3966 name[len] = '\0';
1dd0cca7
SH
3967 if (name[0] == '\0') {
3968 int i;
3969 for (i = 0; i < len; i++)
878dadc7
IB
3970 if (name[i] == '\0')
3971 name[i] = '@';
1dd0cca7 3972 }
99bb68ff
VK
3973 stat.name = &name[0];
3974 memcpy(stat.local.data, &stat.name, sizeof(stat.name));
bf4ceee6 3975 }
dfbaa90d 3976 if (tb[UNIX_DIAG_PEER])
ec4d0d8a 3977 stat.rport = rta_getattr_u32(tb[UNIX_DIAG_PEER]);
dfbaa90d 3978
29999b0f
VK
3979 if (f->f && run_ssfilter(f->f, &stat) == 0)
3980 return 0;
3981
bf4ceee6 3982 unix_stats_print(&stat, f);
dfbaa90d 3983
45199997 3984 if (show_mem)
51ff9f24 3985 print_skmeminfo(tb, UNIX_DIAG_MEMINFO);
5b816047
PE
3986 if (show_details) {
3987 if (tb[UNIX_DIAG_SHUTDOWN]) {
3988 unsigned char mask;
acd1e437 3989
9f1370c0 3990 mask = rta_getattr_u8(tb[UNIX_DIAG_SHUTDOWN]);
90351722
SB
3991 out(" %c-%c",
3992 mask & 1 ? '-' : '<', mask & 2 ? '-' : '>');
5b816047 3993 }
0bab7630
CW
3994 if (tb[UNIX_DIAG_VFS]) {
3995 struct unix_diag_vfs *uv = RTA_DATA(tb[UNIX_DIAG_VFS]);
3996
3997 out(" ino:%u dev:%u/%u", uv->udiag_vfs_ino, major(uv->udiag_vfs_dev),
3998 minor(uv->udiag_vfs_dev));
3999 }
4000 if (tb[UNIX_DIAG_ICONS]) {
4001 int len = RTA_PAYLOAD(tb[UNIX_DIAG_ICONS]);
4002 __u32 *peers = RTA_DATA(tb[UNIX_DIAG_ICONS]);
4003 int i;
4004
4005 out(" peers:");
4006 for (i = 0; i < len / sizeof(__u32); i++)
4007 out(" %u", peers[i]);
4008 }
5b816047 4009 }
ec4d0d8a 4010
dfbaa90d
PE
4011 return 0;
4012}
4013
8a4025f6 4014static int handle_netlink_request(struct filter *f, struct nlmsghdr *req,
4015 size_t size, rtnl_filter_t show_one_sock)
dfbaa90d 4016{
8a4025f6 4017 int ret = -1;
4018 struct rtnl_handle rth;
dfbaa90d 4019
8a4025f6 4020 if (rtnl_open_byproto(&rth, 0, NETLINK_SOCK_DIAG))
dfbaa90d
PE
4021 return -1;
4022
8a4025f6 4023 rth.dump = MAGIC_SEQ;
dfbaa90d 4024
8a4025f6 4025 if (rtnl_send(&rth, req, size) < 0)
4026 goto Exit;
dfbaa90d 4027
8a4025f6 4028 if (rtnl_dump_filter(&rth, show_one_sock, f))
4029 goto Exit;
dfbaa90d 4030
8a4025f6 4031 ret = 0;
4032Exit:
4033 rtnl_close(&rth);
4034 return ret;
dfbaa90d
PE
4035}
4036
8a4025f6 4037static int unix_show_netlink(struct filter *f)
d8402b96 4038{
5fb421d4 4039 DIAG_REQUEST(req, struct unix_diag_req r);
d8402b96
AV
4040
4041 req.r.sdiag_family = AF_UNIX;
4042 req.r.udiag_states = f->states;
4043 req.r.udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER | UDIAG_SHOW_RQLEN;
4044 if (show_mem)
4045 req.r.udiag_show |= UDIAG_SHOW_MEMINFO;
0bab7630
CW
4046 if (show_details)
4047 req.r.udiag_show |= UDIAG_SHOW_VFS | UDIAG_SHOW_ICONS;
d8402b96 4048
8a4025f6 4049 return handle_netlink_request(f, &req.nlh, sizeof(req), unix_show_sock);
d8402b96
AV
4050}
4051
d1f28cf1 4052static int unix_show(struct filter *f)
aba5acdf
SH
4053{
4054 FILE *fp;
4055 char buf[256];
4056 char name[128];
4057 int newformat = 0;
4058 int cnt;
ec4d0d8a 4059 struct sockstat *list = NULL;
96d45daa
PS
4060 const int unix_state_map[] = { SS_CLOSE, SS_SYN_SENT,
4061 SS_ESTABLISHED, SS_CLOSING };
aba5acdf 4062
9db7bf15
VK
4063 if (!filter_af_get(f, AF_UNIX))
4064 return 0;
4065
f25062e9
PS
4066 if (!getenv("PROC_NET_UNIX") && !getenv("PROC_ROOT")
4067 && unix_show_netlink(f) == 0)
dfbaa90d
PE
4068 return 0;
4069
ab01dbbb 4070 if ((fp = net_unix_open()) == NULL)
aba5acdf 4071 return -1;
61170fd8 4072 if (!fgets(buf, sizeof(buf), fp)) {
d572ed4d
PS
4073 fclose(fp);
4074 return -1;
4075 }
aba5acdf 4076
ae665a52 4077 if (memcmp(buf, "Peer", 4) == 0)
aba5acdf
SH
4078 newformat = 1;
4079 cnt = 0;
4080
61170fd8 4081 while (fgets(buf, sizeof(buf), fp)) {
ec4d0d8a 4082 struct sockstat *u, **insp;
aba5acdf
SH
4083 int flags;
4084
0ee9052f 4085 if (!(u = calloc(1, sizeof(*u))))
aba5acdf 4086 break;
aba5acdf
SH
4087
4088 if (sscanf(buf, "%x: %x %x %x %x %x %d %s",
ec4d0d8a 4089 &u->rport, &u->rq, &u->wq, &flags, &u->type,
aba5acdf
SH
4090 &u->state, &u->ino, name) < 8)
4091 name[0] = 0;
4092
ec4d0d8a
VK
4093 u->lport = u->ino;
4094 u->local.family = u->remote.family = AF_UNIX;
4095
4096 if (flags & (1 << 16)) {
aba5acdf 4097 u->state = SS_LISTEN;
0aa03350
PS
4098 } else if (u->state > 0 &&
4099 u->state <= ARRAY_SIZE(unix_state_map)) {
aba5acdf 4100 u->state = unix_state_map[u->state-1];
ec4d0d8a 4101 if (u->type == SOCK_DGRAM && u->state == SS_CLOSE && u->rport)
aba5acdf
SH
4102 u->state = SS_ESTABLISHED;
4103 }
2d0e538f
PS
4104 if (unix_type_skip(u, f) ||
4105 !(f->states & (1 << u->state))) {
4106 free(u);
4107 continue;
4108 }
aba5acdf
SH
4109
4110 if (!newformat) {
ec4d0d8a 4111 u->rport = 0;
aba5acdf
SH
4112 u->rq = 0;
4113 u->wq = 0;
4114 }
4115
2d0e538f
PS
4116 if (name[0]) {
4117 u->name = strdup(name);
46131577
PS
4118 if (!u->name) {
4119 free(u);
2d0e538f 4120 break;
46131577 4121 }
2d0e538f
PS
4122 }
4123
4124 if (u->rport) {
4125 struct sockstat *p;
4126
4127 for (p = list; p; p = p->next) {
4128 if (u->rport == p->lport)
4129 break;
4130 }
4131 if (!p)
4132 u->peer_name = "?";
4133 else
4134 u->peer_name = p->name ? : "*";
4135 }
4136
4137 if (f->f) {
4138 struct sockstat st = {
4139 .local.family = AF_UNIX,
4140 .remote.family = AF_UNIX,
4141 };
4142
4143 memcpy(st.local.data, &u->name, sizeof(u->name));
ebbb219c
AQ
4144 /* when parsing the old format rport is set to 0 and
4145 * therefore peer_name remains NULL
4146 */
4147 if (u->peer_name && strcmp(u->peer_name, "*"))
2d0e538f
PS
4148 memcpy(st.remote.data, &u->peer_name,
4149 sizeof(u->peer_name));
4150 if (run_ssfilter(f->f, &st) == 0) {
4151 free(u->name);
4152 free(u);
4153 continue;
4154 }
4155 }
4156
aba5acdf
SH
4157 insp = &list;
4158 while (*insp) {
4159 if (u->type < (*insp)->type ||
4160 (u->type == (*insp)->type &&
4161 u->ino < (*insp)->ino))
4162 break;
4163 insp = &(*insp)->next;
4164 }
4165 u->next = *insp;
4166 *insp = u;
4167
aba5acdf 4168 if (++cnt > MAX_UNIX_REMEMBER) {
2d0e538f
PS
4169 while (list) {
4170 unix_stats_print(list, f);
2d0e538f
PS
4171 unix_list_drop_first(&list);
4172 }
aba5acdf
SH
4173 cnt = 0;
4174 }
4175 }
a3fd8e58 4176 fclose(fp);
2d0e538f 4177 while (list) {
bf4ceee6 4178 unix_stats_print(list, f);
2d0e538f 4179 unix_list_drop_first(&list);
aba5acdf
SH
4180 }
4181
4182 return 0;
4183}
4184
89f634f9 4185static int packet_stats_print(struct sockstat *s, const struct filter *f)
4a0053b6 4186{
b217df10
VK
4187 const char *addr, *port;
4188 char ll_name[16];
372c30d2 4189
be7e4d20
PS
4190 s->local.family = s->remote.family = AF_PACKET;
4191
4a0053b6 4192 if (f->f) {
89f634f9 4193 s->local.data[0] = s->prot;
89f634f9 4194 if (run_ssfilter(f->f, s) == 0)
4a0053b6
VK
4195 return 1;
4196 }
372c30d2 4197
be7e4d20 4198 sock_state_print(s);
372c30d2 4199
b217df10
VK
4200 if (s->prot == 3)
4201 addr = "*";
4202 else
4203 addr = ll_proto_n2a(htons(s->prot), ll_name, sizeof(ll_name));
4204
4205 if (s->iface == 0)
4206 port = "*";
4207 else
4208 port = xll_index_to_name(s->iface);
372c30d2 4209
b217df10
VK
4210 sock_addr_print(addr, ":", port, NULL);
4211 sock_addr_print("", "*", "", NULL);
116ac927 4212
5f27ac1d 4213 proc_ctx_print(s);
116ac927 4214
f1b39e1b
VK
4215 if (show_details)
4216 sock_details_print(s);
4217
4a0053b6
VK
4218 return 0;
4219}
4220
2631b856
VK
4221static void packet_show_ring(struct packet_diag_ring *ring)
4222{
90351722
SB
4223 out("blk_size:%d", ring->pdr_block_size);
4224 out(",blk_nr:%d", ring->pdr_block_nr);
4225 out(",frm_size:%d", ring->pdr_frame_size);
4226 out(",frm_nr:%d", ring->pdr_frame_nr);
4227 out(",tmo:%d", ring->pdr_retire_tmo);
4228 out(",features:0x%x", ring->pdr_features);
2631b856
VK
4229}
4230
cd554f2c 4231static int packet_show_sock(struct nlmsghdr *nlh, void *arg)
4a0053b6
VK
4232{
4233 const struct filter *f = arg;
4234 struct packet_diag_msg *r = NLMSG_DATA(nlh);
2631b856
VK
4235 struct packet_diag_info *pinfo = NULL;
4236 struct packet_diag_ring *ring_rx = NULL, *ring_tx = NULL;
4a0053b6 4237 struct rtattr *tb[PACKET_DIAG_MAX+1];
89f634f9 4238 struct sockstat stat = {};
2631b856
VK
4239 uint32_t fanout = 0;
4240 bool has_fanout = false;
4a0053b6 4241
acd1e437 4242 parse_rtattr(tb, PACKET_DIAG_MAX, (struct rtattr *)(r+1),
4a0053b6
VK
4243 nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
4244
4245 /* use /proc/net/packet if all info are not available */
4246 if (!tb[PACKET_DIAG_MEMINFO])
4247 return -1;
4248
2d791bc8
VK
4249 stat.type = r->pdiag_type;
4250 stat.prot = r->pdiag_num;
4251 stat.ino = r->pdiag_ino;
4252 stat.state = SS_CLOSE;
f1b39e1b 4253 stat.sk = cookie_sk_get(&r->pdiag_cookie[0]);
4a0053b6
VK
4254
4255 if (tb[PACKET_DIAG_MEMINFO]) {
4256 __u32 *skmeminfo = RTA_DATA(tb[PACKET_DIAG_MEMINFO]);
acd1e437 4257
4a0053b6
VK
4258 stat.rq = skmeminfo[SK_MEMINFO_RMEM_ALLOC];
4259 }
4260
4261 if (tb[PACKET_DIAG_INFO]) {
2631b856 4262 pinfo = RTA_DATA(tb[PACKET_DIAG_INFO]);
2d791bc8 4263 stat.lport = stat.iface = pinfo->pdi_index;
4a0053b6
VK
4264 }
4265
f1b39e1b 4266 if (tb[PACKET_DIAG_UID])
9f1370c0 4267 stat.uid = rta_getattr_u32(tb[PACKET_DIAG_UID]);
f1b39e1b 4268
2631b856
VK
4269 if (tb[PACKET_DIAG_RX_RING])
4270 ring_rx = RTA_DATA(tb[PACKET_DIAG_RX_RING]);
4271
4272 if (tb[PACKET_DIAG_TX_RING])
4273 ring_tx = RTA_DATA(tb[PACKET_DIAG_TX_RING]);
4274
4275 if (tb[PACKET_DIAG_FANOUT]) {
4276 has_fanout = true;
9f1370c0 4277 fanout = rta_getattr_u32(tb[PACKET_DIAG_FANOUT]);
2631b856
VK
4278 }
4279
4a0053b6
VK
4280 if (packet_stats_print(&stat, f))
4281 return 0;
4282
2631b856
VK
4283 if (show_details) {
4284 if (pinfo) {
296b5de7
JH
4285 if (oneline)
4286 out(" ver:%d", pinfo->pdi_version);
4287 else
4288 out("\n\tver:%d", pinfo->pdi_version);
90351722
SB
4289 out(" cpy_thresh:%d", pinfo->pdi_copy_thresh);
4290 out(" flags( ");
2631b856 4291 if (pinfo->pdi_flags & PDI_RUNNING)
90351722 4292 out("running");
2631b856 4293 if (pinfo->pdi_flags & PDI_AUXDATA)
90351722 4294 out(" auxdata");
2631b856 4295 if (pinfo->pdi_flags & PDI_ORIGDEV)
90351722 4296 out(" origdev");
2631b856 4297 if (pinfo->pdi_flags & PDI_VNETHDR)
90351722 4298 out(" vnethdr");
2631b856 4299 if (pinfo->pdi_flags & PDI_LOSS)
90351722 4300 out(" loss");
2631b856 4301 if (!pinfo->pdi_flags)
90351722
SB
4302 out("0");
4303 out(" )");
2631b856
VK
4304 }
4305 if (ring_rx) {
296b5de7
JH
4306 if (oneline)
4307 out(" ring_rx(");
4308 else
4309 out("\n\tring_rx(");
2631b856 4310 packet_show_ring(ring_rx);
90351722 4311 out(")");
2631b856
VK
4312 }
4313 if (ring_tx) {
296b5de7
JH
4314 if (oneline)
4315 out(" ring_tx(");
4316 else
4317 out("\n\tring_tx(");
2631b856 4318 packet_show_ring(ring_tx);
90351722 4319 out(")");
2631b856
VK
4320 }
4321 if (has_fanout) {
4322 uint16_t type = (fanout >> 16) & 0xffff;
4323
296b5de7
JH
4324 if (oneline)
4325 out(" fanout(");
4326 else
4327 out("\n\tfanout(");
90351722
SB
4328 out("id:%d,", fanout & 0xffff);
4329 out("type:");
2631b856
VK
4330
4331 if (type == 0)
90351722 4332 out("hash");
2631b856 4333 else if (type == 1)
90351722 4334 out("lb");
2631b856 4335 else if (type == 2)
90351722 4336 out("cpu");
2631b856 4337 else if (type == 3)
90351722 4338 out("roll");
2631b856 4339 else if (type == 4)
90351722 4340 out("random");
2631b856 4341 else if (type == 5)
90351722 4342 out("qm");
2631b856 4343 else
90351722 4344 out("0x%x", type);
2631b856 4345
90351722 4346 out(")");
2631b856
VK
4347 }
4348 }
4349
372c30d2
ND
4350 if (show_bpf && tb[PACKET_DIAG_FILTER]) {
4351 struct sock_filter *fil =
4352 RTA_DATA(tb[PACKET_DIAG_FILTER]);
4353 int num = RTA_PAYLOAD(tb[PACKET_DIAG_FILTER]) /
4354 sizeof(struct sock_filter);
4355
296b5de7
JH
4356 if (oneline)
4357 out(" bpf filter (%d): ", num);
4358 else
4359 out("\n\tbpf filter (%d): ", num);
372c30d2 4360 while (num) {
90351722
SB
4361 out(" 0x%02x %u %u %u,",
4362 fil->code, fil->jt, fil->jf, fil->k);
372c30d2
ND
4363 num--;
4364 fil++;
4365 }
4366 }
430e05d3
RP
4367
4368 if (show_mem)
4369 print_skmeminfo(tb, PACKET_DIAG_MEMINFO);
372c30d2
ND
4370 return 0;
4371}
4372
8a4025f6 4373static int packet_show_netlink(struct filter *f)
372c30d2 4374{
5fb421d4 4375 DIAG_REQUEST(req, struct packet_diag_req r);
372c30d2 4376
372c30d2 4377 req.r.sdiag_family = AF_PACKET;
2631b856
VK
4378 req.r.pdiag_show = PACKET_SHOW_INFO | PACKET_SHOW_MEMINFO |
4379 PACKET_SHOW_FILTER | PACKET_SHOW_RING_CFG | PACKET_SHOW_FANOUT;
372c30d2 4380
8a4025f6 4381 return handle_netlink_request(f, &req.nlh, sizeof(req), packet_show_sock);
372c30d2
ND
4382}
4383
4a0053b6
VK
4384static int packet_show_line(char *buf, const struct filter *f, int fam)
4385{
4386 unsigned long long sk;
89f634f9 4387 struct sockstat stat = {};
4a0053b6
VK
4388 int type, prot, iface, state, rq, uid, ino;
4389
4390 sscanf(buf, "%llx %*d %d %x %d %d %u %u %u",
4391 &sk,
4392 &type, &prot, &iface, &state,
4393 &rq, &uid, &ino);
4394
4395 if (stat.type == SOCK_RAW && !(f->dbs&(1<<PACKET_R_DB)))
4396 return 0;
4397 if (stat.type == SOCK_DGRAM && !(f->dbs&(1<<PACKET_DG_DB)))
4398 return 0;
4399
4400 stat.type = type;
4401 stat.prot = prot;
2d791bc8 4402 stat.lport = stat.iface = iface;
4a0053b6
VK
4403 stat.state = state;
4404 stat.rq = rq;
4405 stat.uid = uid;
4406 stat.ino = ino;
2d791bc8
VK
4407 stat.state = SS_CLOSE;
4408
4a0053b6
VK
4409 if (packet_stats_print(&stat, f))
4410 return 0;
4411
4a0053b6
VK
4412 return 0;
4413}
aba5acdf 4414
d1f28cf1 4415static int packet_show(struct filter *f)
aba5acdf
SH
4416{
4417 FILE *fp;
b95d28c3 4418 int rc = 0;
3d0b7439 4419
9db7bf15 4420 if (!filter_af_get(f, AF_PACKET) || !(f->states & (1 << SS_CLOSE)))
b9ea445d 4421 return 0;
aba5acdf 4422
4a0053b6
VK
4423 if (!getenv("PROC_NET_PACKET") && !getenv("PROC_ROOT") &&
4424 packet_show_netlink(f) == 0)
372c30d2
ND
4425 return 0;
4426
ab01dbbb 4427 if ((fp = net_packet_open()) == NULL)
aba5acdf 4428 return -1;
4a0053b6 4429 if (generic_record_read(fp, packet_show_line, f, AF_PACKET))
b95d28c3 4430 rc = -1;
aba5acdf 4431
b95d28c3
PS
4432 fclose(fp);
4433 return rc;
aba5acdf
SH
4434}
4435
2abc3d76
BT
4436static int xdp_stats_print(struct sockstat *s, const struct filter *f)
4437{
4438 const char *addr, *port;
4439 char q_str[16];
4440
4441 s->local.family = s->remote.family = AF_XDP;
4442
4443 if (f->f) {
4444 if (run_ssfilter(f->f, s) == 0)
4445 return 1;
4446 }
4447
4448 sock_state_print(s);
4449
4450 if (s->iface) {
4451 addr = xll_index_to_name(s->iface);
4452 snprintf(q_str, sizeof(q_str), "q%d", s->lport);
4453 port = q_str;
4454 sock_addr_print(addr, ":", port, NULL);
4455 } else {
4456 sock_addr_print("", "*", "", NULL);
4457 }
4458
4459 sock_addr_print("", "*", "", NULL);
4460
4461 proc_ctx_print(s);
4462
4463 if (show_details)
4464 sock_details_print(s);
4465
4466 return 0;
4467}
4468
4469static void xdp_show_ring(const char *name, struct xdp_diag_ring *ring)
4470{
296b5de7
JH
4471 if (oneline)
4472 out(" %s(", name);
4473 else
4474 out("\n\t%s(", name);
2abc3d76
BT
4475 out("entries:%u", ring->entries);
4476 out(")");
4477}
4478
4479static void xdp_show_umem(struct xdp_diag_umem *umem, struct xdp_diag_ring *fr,
4480 struct xdp_diag_ring *cr)
4481{
296b5de7
JH
4482 if (oneline)
4483 out(" tumem(");
4484 else
4485 out("\n\tumem(");
2abc3d76
BT
4486 out("id:%u", umem->id);
4487 out(",size:%llu", umem->size);
4488 out(",num_pages:%u", umem->num_pages);
4489 out(",chunk_size:%u", umem->chunk_size);
4490 out(",headroom:%u", umem->headroom);
4491 out(",ifindex:%u", umem->ifindex);
4492 out(",qid:%u", umem->queue_id);
4493 out(",zc:%u", umem->flags & XDP_DU_F_ZEROCOPY);
4494 out(",refs:%u", umem->refs);
4495 out(")");
4496
4497 if (fr)
4498 xdp_show_ring("fr", fr);
4499 if (cr)
4500 xdp_show_ring("cr", cr);
4501}
4502
4503static int xdp_show_sock(struct nlmsghdr *nlh, void *arg)
4504{
4505 struct xdp_diag_ring *rx = NULL, *tx = NULL, *fr = NULL, *cr = NULL;
4506 struct xdp_diag_msg *msg = NLMSG_DATA(nlh);
4507 struct rtattr *tb[XDP_DIAG_MAX + 1];
4508 struct xdp_diag_info *info = NULL;
4509 struct xdp_diag_umem *umem = NULL;
4510 const struct filter *f = arg;
4511 struct sockstat stat = {};
4512
4513 parse_rtattr(tb, XDP_DIAG_MAX, (struct rtattr *)(msg + 1),
4514 nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*msg)));
4515
4516 stat.type = msg->xdiag_type;
4517 stat.ino = msg->xdiag_ino;
4518 stat.state = SS_CLOSE;
4519 stat.sk = cookie_sk_get(&msg->xdiag_cookie[0]);
4520
4521 if (tb[XDP_DIAG_INFO]) {
4522 info = RTA_DATA(tb[XDP_DIAG_INFO]);
4523 stat.iface = info->ifindex;
4524 stat.lport = info->queue_id;
4525 }
4526
4527 if (tb[XDP_DIAG_UID])
4528 stat.uid = rta_getattr_u32(tb[XDP_DIAG_UID]);
4529 if (tb[XDP_DIAG_RX_RING])
4530 rx = RTA_DATA(tb[XDP_DIAG_RX_RING]);
4531 if (tb[XDP_DIAG_TX_RING])
4532 tx = RTA_DATA(tb[XDP_DIAG_TX_RING]);
4533 if (tb[XDP_DIAG_UMEM])
4534 umem = RTA_DATA(tb[XDP_DIAG_UMEM]);
4535 if (tb[XDP_DIAG_UMEM_FILL_RING])
4536 fr = RTA_DATA(tb[XDP_DIAG_UMEM_FILL_RING]);
4537 if (tb[XDP_DIAG_UMEM_COMPLETION_RING])
4538 cr = RTA_DATA(tb[XDP_DIAG_UMEM_COMPLETION_RING]);
4539 if (tb[XDP_DIAG_MEMINFO]) {
4540 __u32 *skmeminfo = RTA_DATA(tb[XDP_DIAG_MEMINFO]);
4541
4542 stat.rq = skmeminfo[SK_MEMINFO_RMEM_ALLOC];
4543 }
4544
4545 if (xdp_stats_print(&stat, f))
4546 return 0;
4547
4548 if (show_details) {
4549 if (rx)
4550 xdp_show_ring("rx", rx);
4551 if (tx)
4552 xdp_show_ring("tx", tx);
4553 if (umem)
4554 xdp_show_umem(umem, fr, cr);
4555 }
4556
4557 if (show_mem)
4558 print_skmeminfo(tb, XDP_DIAG_MEMINFO); // really?
4559
4560
4561 return 0;
4562}
4563
4564static int xdp_show(struct filter *f)
4565{
4566 DIAG_REQUEST(req, struct xdp_diag_req r);
4567
4568 if (!filter_af_get(f, AF_XDP) || !(f->states & (1 << SS_CLOSE)))
4569 return 0;
4570
4571 req.r.sdiag_family = AF_XDP;
4572 req.r.xdiag_show = XDP_SHOW_INFO | XDP_SHOW_RING_CFG | XDP_SHOW_UMEM |
4573 XDP_SHOW_MEMINFO;
4574
4575 return handle_netlink_request(f, &req.nlh, sizeof(req), xdp_show_sock);
4576}
4577
5f24ec0e 4578static int netlink_show_one(struct filter *f,
acd1e437
SH
4579 int prot, int pid, unsigned int groups,
4580 int state, int dst_pid, unsigned int dst_group,
129709ae
AV
4581 int rq, int wq,
4582 unsigned long long sk, unsigned long long cb)
4583{
301826be
PS
4584 struct sockstat st = {
4585 .state = SS_CLOSE,
4586 .rq = rq,
4587 .wq = wq,
4588 .local.family = AF_NETLINK,
4589 .remote.family = AF_NETLINK,
4590 };
acd1e437 4591
b217df10
VK
4592 SPRINT_BUF(prot_buf) = {};
4593 const char *prot_name;
4594 char procname[64] = {};
eef43b50 4595
129709ae 4596 if (f->f) {
055840f2
VK
4597 st.rport = -1;
4598 st.lport = pid;
4599 st.local.data[0] = prot;
055840f2 4600 if (run_ssfilter(f->f, &st) == 0)
5f24ec0e 4601 return 1;
129709ae
AV
4602 }
4603
be7e4d20 4604 sock_state_print(&st);
eef43b50 4605
ca697cee 4606 prot_name = nl_proto_n2a(prot, prot_buf, sizeof(prot_buf));
eef43b50 4607
129709ae 4608 if (pid == -1) {
b217df10 4609 procname[0] = '*';
ca697cee 4610 } else if (!numeric) {
129709ae 4611 int done = 0;
acd1e437 4612
129709ae
AV
4613 if (!pid) {
4614 done = 1;
da8034a0 4615 strncpy(procname, "kernel", 7);
129709ae 4616 } else if (pid > 0) {
129709ae 4617 FILE *fp;
acd1e437 4618
0ee9052f 4619 snprintf(procname, sizeof(procname), "%s/%d/stat",
129709ae
AV
4620 getenv("PROC_ROOT") ? : "/proc", pid);
4621 if ((fp = fopen(procname, "r")) != NULL) {
4622 if (fscanf(fp, "%*d (%[^)])", procname) == 1) {
0ee9052f 4623 snprintf(procname+strlen(procname),
4624 sizeof(procname)-strlen(procname),
4625 "/%d", pid);
129709ae
AV
4626 done = 1;
4627 }
4628 fclose(fp);
4629 }
4630 }
4631 if (!done)
b217df10 4632 int_to_str(pid, procname);
129709ae 4633 } else {
b217df10 4634 int_to_str(pid, procname);
129709ae 4635 }
f271fe01 4636
b217df10
VK
4637 sock_addr_print(prot_name, ":", procname, NULL);
4638
f271fe01 4639 if (state == NETLINK_CONNECTED) {
b217df10
VK
4640 char dst_group_buf[30];
4641 char dst_pid_buf[30];
acd1e437 4642
b217df10
VK
4643 sock_addr_print(int_to_str(dst_group, dst_group_buf), ":",
4644 int_to_str(dst_pid, dst_pid_buf), NULL);
f271fe01 4645 } else {
b217df10 4646 sock_addr_print("", "*", "", NULL);
f271fe01 4647 }
129709ae 4648
116ac927 4649 char *pid_context = NULL;
acd1e437 4650
116ac927
RH
4651 if (show_proc_ctx) {
4652 /* The pid value will either be:
4653 * 0 if destination kernel - show kernel initial context.
4654 * A valid process pid - use getpidcon.
4655 * A unique value allocated by the kernel or netlink user
4656 * to the process - show context as "not available".
4657 */
4658 if (!pid)
4659 security_get_initial_context("kernel", &pid_context);
4660 else if (pid > 0)
4661 getpidcon(pid, &pid_context);
4662
90351722 4663 out(" proc_ctx=%s", pid_context ? : "unavailable");
22658ff5 4664 free(pid_context);
116ac927
RH
4665 }
4666
129709ae 4667 if (show_details) {
90351722 4668 out(" sk=%llx cb=%llx groups=0x%08x", sk, cb, groups);
129709ae 4669 }
129709ae 4670
5f24ec0e 4671 return 0;
129709ae
AV
4672}
4673
cd554f2c 4674static int netlink_show_sock(struct nlmsghdr *nlh, void *arg)
ecb928c8 4675{
8a4025f6 4676 struct filter *f = (struct filter *)arg;
ecb928c8
AV
4677 struct netlink_diag_msg *r = NLMSG_DATA(nlh);
4678 struct rtattr *tb[NETLINK_DIAG_MAX+1];
4679 int rq = 0, wq = 0;
4680 unsigned long groups = 0;
4681
acd1e437 4682 parse_rtattr(tb, NETLINK_DIAG_MAX, (struct rtattr *)(r+1),
ecb928c8
AV
4683 nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
4684
4685 if (tb[NETLINK_DIAG_GROUPS] && RTA_PAYLOAD(tb[NETLINK_DIAG_GROUPS]))
4686 groups = *(unsigned long *) RTA_DATA(tb[NETLINK_DIAG_GROUPS]);
4687
4688 if (tb[NETLINK_DIAG_MEMINFO]) {
4689 const __u32 *skmeminfo;
acd1e437 4690
ecb928c8
AV
4691 skmeminfo = RTA_DATA(tb[NETLINK_DIAG_MEMINFO]);
4692
4693 rq = skmeminfo[SK_MEMINFO_RMEM_ALLOC];
4694 wq = skmeminfo[SK_MEMINFO_WMEM_ALLOC];
4695 }
4696
5f24ec0e 4697 if (netlink_show_one(f, r->ndiag_protocol, r->ndiag_portid, groups,
ecb928c8 4698 r->ndiag_state, r->ndiag_dst_portid, r->ndiag_dst_group,
5f24ec0e
VK
4699 rq, wq, 0, 0)) {
4700 return 0;
4701 }
ecb928c8
AV
4702
4703 if (show_mem) {
90351722 4704 out("\t");
ecb928c8 4705 print_skmeminfo(tb, NETLINK_DIAG_MEMINFO);
ecb928c8
AV
4706 }
4707
4708 return 0;
4709}
4710
8a4025f6 4711static int netlink_show_netlink(struct filter *f)
ecb928c8 4712{
5fb421d4 4713 DIAG_REQUEST(req, struct netlink_diag_req r);
ecb928c8
AV
4714
4715 req.r.sdiag_family = AF_NETLINK;
4716 req.r.sdiag_protocol = NDIAG_PROTO_ALL;
4717 req.r.ndiag_show = NDIAG_SHOW_GROUPS | NDIAG_SHOW_MEMINFO;
4718
8a4025f6 4719 return handle_netlink_request(f, &req.nlh, sizeof(req), netlink_show_sock);
ecb928c8
AV
4720}
4721
d1f28cf1 4722static int netlink_show(struct filter *f)
aba5acdf
SH
4723{
4724 FILE *fp;
4725 char buf[256];
4726 int prot, pid;
acd1e437 4727 unsigned int groups;
aba5acdf
SH
4728 int rq, wq, rc;
4729 unsigned long long sk, cb;
4730
9db7bf15 4731 if (!filter_af_get(f, AF_NETLINK) || !(f->states & (1 << SS_CLOSE)))
b9ea445d
VK
4732 return 0;
4733
129709ae 4734 if (!getenv("PROC_NET_NETLINK") && !getenv("PROC_ROOT") &&
8a4025f6 4735 netlink_show_netlink(f) == 0)
129709ae
AV
4736 return 0;
4737
ab01dbbb 4738 if ((fp = net_netlink_open()) == NULL)
aba5acdf 4739 return -1;
61170fd8 4740 if (!fgets(buf, sizeof(buf), fp)) {
d572ed4d
PS
4741 fclose(fp);
4742 return -1;
4743 }
aba5acdf 4744
61170fd8 4745 while (fgets(buf, sizeof(buf), fp)) {
aba5acdf
SH
4746 sscanf(buf, "%llx %d %d %x %d %d %llx %d",
4747 &sk,
4748 &prot, &pid, &groups, &rq, &wq, &cb, &rc);
4749
f271fe01 4750 netlink_show_one(f, prot, pid, groups, 0, 0, 0, rq, wq, sk, cb);
aba5acdf
SH
4751 }
4752
b95d28c3 4753 fclose(fp);
aba5acdf
SH
4754 return 0;
4755}
4756
c759116a
SH
4757static bool vsock_type_skip(struct sockstat *s, struct filter *f)
4758{
4759 if (s->type == SOCK_STREAM && !(f->dbs & (1 << VSOCK_ST_DB)))
4760 return true;
4761 if (s->type == SOCK_DGRAM && !(f->dbs & (1 << VSOCK_DG_DB)))
4762 return true;
4763 return false;
4764}
4765
4766static void vsock_addr_print(inet_prefix *a, __u32 port)
4767{
4768 char cid_str[sizeof("4294967295")];
4769 char port_str[sizeof("4294967295")];
4770 __u32 cid;
4771
4772 memcpy(&cid, a->data, sizeof(cid));
4773
4774 if (cid == ~(__u32)0)
4775 snprintf(cid_str, sizeof(cid_str), "*");
4776 else
4777 snprintf(cid_str, sizeof(cid_str), "%u", cid);
4778
4779 if (port == ~(__u32)0)
4780 snprintf(port_str, sizeof(port_str), "*");
4781 else
4782 snprintf(port_str, sizeof(port_str), "%u", port);
4783
4784 sock_addr_print(cid_str, ":", port_str, NULL);
4785}
4786
4787static void vsock_stats_print(struct sockstat *s, struct filter *f)
4788{
4789 sock_state_print(s);
4790
4791 vsock_addr_print(&s->local, s->lport);
4792 vsock_addr_print(&s->remote, s->rport);
4793
4794 proc_ctx_print(s);
c759116a
SH
4795}
4796
cd554f2c 4797static int vsock_show_sock(struct nlmsghdr *nlh, void *arg)
c759116a
SH
4798{
4799 struct filter *f = (struct filter *)arg;
4800 struct vsock_diag_msg *r = NLMSG_DATA(nlh);
4801 struct sockstat stat = {
4802 .type = r->vdiag_type,
4803 .lport = r->vdiag_src_port,
4804 .rport = r->vdiag_dst_port,
4805 .state = r->vdiag_state,
4806 .ino = r->vdiag_ino,
4807 };
4808
4809 vsock_set_inet_prefix(&stat.local, r->vdiag_src_cid);
4810 vsock_set_inet_prefix(&stat.remote, r->vdiag_dst_cid);
4811
4812 if (vsock_type_skip(&stat, f))
4813 return 0;
4814
4815 if (f->f && run_ssfilter(f->f, &stat) == 0)
4816 return 0;
4817
4818 vsock_stats_print(&stat, f);
4819
4820 return 0;
4821}
4822
4823static int vsock_show(struct filter *f)
4824{
4825 DIAG_REQUEST(req, struct vsock_diag_req r);
4826
4827 if (!filter_af_get(f, AF_VSOCK))
4828 return 0;
4829
4830 req.r.sdiag_family = AF_VSOCK;
4831 req.r.vdiag_states = f->states;
4832
4833 return handle_netlink_request(f, &req.nlh, sizeof(req), vsock_show_sock);
4834}
4835
5caf79a0
GM
4836static void tipc_sock_addr_print(struct rtattr *net_addr, struct rtattr *id)
4837{
4838 uint32_t node = rta_getattr_u32(net_addr);
4839 uint32_t identity = rta_getattr_u32(id);
4840
4841 SPRINT_BUF(addr) = {};
4842 SPRINT_BUF(port) = {};
4843
4844 sprintf(addr, "%u", node);
4845 sprintf(port, "%u", identity);
4846 sock_addr_print(addr, ":", port, NULL);
4847
4848}
4849
cd554f2c 4850static int tipc_show_sock(struct nlmsghdr *nlh, void *arg)
5caf79a0
GM
4851{
4852 struct rtattr *stat[TIPC_NLA_SOCK_STAT_MAX + 1] = {};
4853 struct rtattr *attrs[TIPC_NLA_SOCK_MAX + 1] = {};
4854 struct rtattr *con[TIPC_NLA_CON_MAX + 1] = {};
4855 struct rtattr *info[TIPC_NLA_MAX + 1] = {};
4856 struct rtattr *msg_ref;
4857 struct sockstat ss = {};
4858
4859 parse_rtattr(info, TIPC_NLA_MAX, NLMSG_DATA(nlh),
4860 NLMSG_PAYLOAD(nlh, 0));
4861
4862 if (!info[TIPC_NLA_SOCK])
4863 return 0;
4864
4865 msg_ref = info[TIPC_NLA_SOCK];
4866 parse_rtattr(attrs, TIPC_NLA_SOCK_MAX, RTA_DATA(msg_ref),
4867 RTA_PAYLOAD(msg_ref));
4868
4869 msg_ref = attrs[TIPC_NLA_SOCK_STAT];
4870 parse_rtattr(stat, TIPC_NLA_SOCK_STAT_MAX,
4871 RTA_DATA(msg_ref), RTA_PAYLOAD(msg_ref));
4872
4873
4874 ss.local.family = AF_TIPC;
4875 ss.type = rta_getattr_u32(attrs[TIPC_NLA_SOCK_TYPE]);
4876 ss.state = rta_getattr_u32(attrs[TIPC_NLA_SOCK_TIPC_STATE]);
4877 ss.uid = rta_getattr_u32(attrs[TIPC_NLA_SOCK_UID]);
4878 ss.ino = rta_getattr_u32(attrs[TIPC_NLA_SOCK_INO]);
4879 ss.rq = rta_getattr_u32(stat[TIPC_NLA_SOCK_STAT_RCVQ]);
4880 ss.wq = rta_getattr_u32(stat[TIPC_NLA_SOCK_STAT_SENDQ]);
4881 ss.sk = rta_getattr_u64(attrs[TIPC_NLA_SOCK_COOKIE]);
4882
4883 sock_state_print (&ss);
4884
4885 tipc_sock_addr_print(attrs[TIPC_NLA_SOCK_ADDR],
4886 attrs[TIPC_NLA_SOCK_REF]);
4887
4888 msg_ref = attrs[TIPC_NLA_SOCK_CON];
4889 if (msg_ref) {
4890 parse_rtattr(con, TIPC_NLA_CON_MAX,
4891 RTA_DATA(msg_ref), RTA_PAYLOAD(msg_ref));
4892
4893 tipc_sock_addr_print(con[TIPC_NLA_CON_NODE],
4894 con[TIPC_NLA_CON_SOCK]);
4895 } else
4896 sock_addr_print("", "-", "", NULL);
4897
4898 if (show_details)
4899 sock_details_print(&ss);
4900
4901 proc_ctx_print(&ss);
4902
4903 if (show_tipcinfo) {
296b5de7
JH
4904 if (oneline)
4905 out(" type:%s", stype_nameg[ss.type]);
4906 else
4907 out("\n type:%s", stype_nameg[ss.type]);
5caf79a0
GM
4908 out(" cong:%s ",
4909 stat[TIPC_NLA_SOCK_STAT_LINK_CONG] ? "link" :
4910 stat[TIPC_NLA_SOCK_STAT_CONN_CONG] ? "conn" : "none");
4911 out(" drop:%d ",
4912 rta_getattr_u32(stat[TIPC_NLA_SOCK_STAT_DROP]));
4913
4914 if (attrs[TIPC_NLA_SOCK_HAS_PUBL])
4915 out(" publ");
4916
4917 if (con[TIPC_NLA_CON_FLAG])
4918 out(" via {%u,%u} ",
4919 rta_getattr_u32(con[TIPC_NLA_CON_TYPE]),
4920 rta_getattr_u32(con[TIPC_NLA_CON_INST]));
4921 }
4922
4923 return 0;
4924}
4925
4926static int tipc_show(struct filter *f)
4927{
4928 DIAG_REQUEST(req, struct tipc_sock_diag_req r);
4929
4930 memset(&req.r, 0, sizeof(req.r));
4931 req.r.sdiag_family = AF_TIPC;
4932 req.r.tidiag_states = f->states;
4933
4934 return handle_netlink_request(f, &req.nlh, sizeof(req), tipc_show_sock);
4935}
4936
6885e3bf
CG
4937struct sock_diag_msg {
4938 __u8 sdiag_family;
4939};
4940
cd554f2c 4941static int generic_show_sock(struct nlmsghdr *nlh, void *arg)
6885e3bf
CG
4942{
4943 struct sock_diag_msg *r = NLMSG_DATA(nlh);
4944 struct inet_diag_arg inet_arg = { .f = arg, .protocol = IPPROTO_MAX };
32ea3d54 4945 int ret;
6885e3bf
CG
4946
4947 switch (r->sdiag_family) {
4948 case AF_INET:
4949 case AF_INET6:
97352f1b 4950 inet_arg.rth = inet_arg.f->rth_for_killing;
cd554f2c 4951 ret = show_one_inet_sock(nlh, &inet_arg);
32ea3d54 4952 break;
6885e3bf 4953 case AF_UNIX:
cd554f2c 4954 ret = unix_show_sock(nlh, arg);
32ea3d54 4955 break;
6885e3bf 4956 case AF_PACKET:
cd554f2c 4957 ret = packet_show_sock(nlh, arg);
32ea3d54 4958 break;
6885e3bf 4959 case AF_NETLINK:
cd554f2c 4960 ret = netlink_show_sock(nlh, arg);
32ea3d54 4961 break;
c759116a 4962 case AF_VSOCK:
cd554f2c 4963 ret = vsock_show_sock(nlh, arg);
32ea3d54 4964 break;
2abc3d76
BT
4965 case AF_XDP:
4966 ret = xdp_show_sock(nlh, arg);
4967 break;
6885e3bf 4968 default:
32ea3d54 4969 ret = -1;
6885e3bf 4970 }
32ea3d54
SB
4971
4972 render();
4973
4974 return ret;
6885e3bf
CG
4975}
4976
4977static int handle_follow_request(struct filter *f)
4978{
6b224dad 4979 int ret = 0;
6885e3bf 4980 int groups = 0;
97352f1b 4981 struct rtnl_handle rth, rth2;
6885e3bf 4982
b338a3e7 4983 if (f->families & FAMILY_MASK(AF_INET) && f->dbs & (1 << TCP_DB))
6885e3bf 4984 groups |= 1 << (SKNLGRP_INET_TCP_DESTROY - 1);
b338a3e7 4985 if (f->families & FAMILY_MASK(AF_INET) && f->dbs & (1 << UDP_DB))
6885e3bf 4986 groups |= 1 << (SKNLGRP_INET_UDP_DESTROY - 1);
b338a3e7 4987 if (f->families & FAMILY_MASK(AF_INET6) && f->dbs & (1 << TCP_DB))
6885e3bf 4988 groups |= 1 << (SKNLGRP_INET6_TCP_DESTROY - 1);
b338a3e7 4989 if (f->families & FAMILY_MASK(AF_INET6) && f->dbs & (1 << UDP_DB))
6885e3bf
CG
4990 groups |= 1 << (SKNLGRP_INET6_UDP_DESTROY - 1);
4991
4992 if (groups == 0)
4993 return -1;
4994
4995 if (rtnl_open_byproto(&rth, groups, NETLINK_SOCK_DIAG))
4996 return -1;
4997
4998 rth.dump = 0;
4999 rth.local.nl_pid = 0;
5000
97352f1b
MY
5001 if (f->kill) {
5002 if (rtnl_open_byproto(&rth2, groups, NETLINK_SOCK_DIAG)) {
5003 rtnl_close(&rth);
5004 return -1;
5005 }
5006 f->rth_for_killing = &rth2;
5007 }
5008
6885e3bf 5009 if (rtnl_dump_filter(&rth, generic_show_sock, f))
6b224dad 5010 ret = -1;
6885e3bf 5011
6885e3bf 5012 rtnl_close(&rth);
97352f1b
MY
5013 if (f->rth_for_killing)
5014 rtnl_close(f->rth_for_killing);
6885e3bf
CG
5015 return ret;
5016}
5017
d1f28cf1 5018static int get_snmp_int(char *proto, char *key, int *result)
aba5acdf
SH
5019{
5020 char buf[1024];
5021 FILE *fp;
5022 int protolen = strlen(proto);
5023 int keylen = strlen(key);
5024
5025 *result = 0;
5026
ab01dbbb 5027 if ((fp = net_snmp_open()) == NULL)
aba5acdf
SH
5028 return -1;
5029
5030 while (fgets(buf, sizeof(buf), fp) != NULL) {
5031 char *p = buf;
5032 int pos = 0;
acd1e437 5033
aba5acdf
SH
5034 if (memcmp(buf, proto, protolen))
5035 continue;
5036 while ((p = strchr(p, ' ')) != NULL) {
5037 pos++;
5038 p++;
5039 if (memcmp(p, key, keylen) == 0 &&
5040 (p[keylen] == ' ' || p[keylen] == '\n'))
5041 break;
5042 }
5043 if (fgets(buf, sizeof(buf), fp) == NULL)
5044 break;
5045 if (memcmp(buf, proto, protolen))
5046 break;
5047 p = buf;
5048 while ((p = strchr(p, ' ')) != NULL) {
5049 p++;
5050 if (--pos == 0) {
5051 sscanf(p, "%d", result);
5052 fclose(fp);
5053 return 0;
5054 }
5055 }
5056 }
5057
5058 fclose(fp);
5059 errno = ESRCH;
5060 return -1;
5061}
5062
5063
5064/* Get stats from sockstat */
5065
acd1e437 5066struct ssummary {
aba5acdf
SH
5067 int socks;
5068 int tcp_mem;
5069 int tcp_total;
5070 int tcp_orphans;
5071 int tcp_tws;
5072 int tcp4_hashed;
5073 int udp4;
5074 int raw4;
5075 int frag4;
5076 int frag4_mem;
5077 int tcp6_hashed;
5078 int udp6;
5079 int raw6;
5080 int frag6;
5081 int frag6_mem;
5082};
5083
055840f2 5084static void get_sockstat_line(char *line, struct ssummary *s)
aba5acdf
SH
5085{
5086 char id[256], rem[256];
5087
5088 if (sscanf(line, "%[^ ] %[^\n]\n", id, rem) != 2)
5089 return;
5090
5091 if (strcmp(id, "sockets:") == 0)
5092 sscanf(rem, "%*s%d", &s->socks);
5093 else if (strcmp(id, "UDP:") == 0)
5094 sscanf(rem, "%*s%d", &s->udp4);
5095 else if (strcmp(id, "UDP6:") == 0)
5096 sscanf(rem, "%*s%d", &s->udp6);
5097 else if (strcmp(id, "RAW:") == 0)
5098 sscanf(rem, "%*s%d", &s->raw4);
5099 else if (strcmp(id, "RAW6:") == 0)
5100 sscanf(rem, "%*s%d", &s->raw6);
5101 else if (strcmp(id, "TCP6:") == 0)
5102 sscanf(rem, "%*s%d", &s->tcp6_hashed);
5103 else if (strcmp(id, "FRAG:") == 0)
5104 sscanf(rem, "%*s%d%*s%d", &s->frag4, &s->frag4_mem);
5105 else if (strcmp(id, "FRAG6:") == 0)
5106 sscanf(rem, "%*s%d%*s%d", &s->frag6, &s->frag6_mem);
5107 else if (strcmp(id, "TCP:") == 0)
5108 sscanf(rem, "%*s%d%*s%d%*s%d%*s%d%*s%d",
5109 &s->tcp4_hashed,
5110 &s->tcp_orphans, &s->tcp_tws, &s->tcp_total, &s->tcp_mem);
5111}
5112
055840f2 5113static int get_sockstat(struct ssummary *s)
aba5acdf
SH
5114{
5115 char buf[256];
5116 FILE *fp;
5117
5118 memset(s, 0, sizeof(*s));
5119
ab01dbbb 5120 if ((fp = net_sockstat_open()) == NULL)
aba5acdf 5121 return -1;
acd1e437 5122 while (fgets(buf, sizeof(buf), fp) != NULL)
aba5acdf
SH
5123 get_sockstat_line(buf, s);
5124 fclose(fp);
5125
ab01dbbb 5126 if ((fp = net_sockstat6_open()) == NULL)
aba5acdf 5127 return 0;
acd1e437 5128 while (fgets(buf, sizeof(buf), fp) != NULL)
aba5acdf
SH
5129 get_sockstat_line(buf, s);
5130 fclose(fp);
5131
5132 return 0;
5133}
5134
d1f28cf1 5135static int print_summary(void)
aba5acdf 5136{
055840f2 5137 struct ssummary s;
2f938ce1 5138 int tcp_estab;
aba5acdf
SH
5139
5140 if (get_sockstat(&s) < 0)
5141 perror("ss: get_sockstat");
2f938ce1 5142 if (get_snmp_int("Tcp:", "CurrEstab", &tcp_estab) < 0)
aba5acdf
SH
5143 perror("ss: get_snmpstat");
5144
10f68773 5145 printf("Total: %d\n", s.socks);
aba5acdf 5146
10f68773
SH
5147 printf("TCP: %d (estab %d, closed %d, orphaned %d, timewait %d)\n",
5148 s.tcp_total + s.tcp_tws, tcp_estab,
5149 s.tcp_total - (s.tcp4_hashed + s.tcp6_hashed - s.tcp_tws),
5150 s.tcp_orphans, s.tcp_tws);
aba5acdf
SH
5151
5152 printf("\n");
5153 printf("Transport Total IP IPv6\n");
aba5acdf
SH
5154 printf("RAW %-9d %-9d %-9d\n", s.raw4+s.raw6, s.raw4, s.raw6);
5155 printf("UDP %-9d %-9d %-9d\n", s.udp4+s.udp6, s.udp4, s.udp6);
5156 printf("TCP %-9d %-9d %-9d\n", s.tcp4_hashed+s.tcp6_hashed, s.tcp4_hashed, s.tcp6_hashed);
ae665a52 5157 printf("INET %-9d %-9d %-9d\n",
aba5acdf
SH
5158 s.raw4+s.udp4+s.tcp4_hashed+
5159 s.raw6+s.udp6+s.tcp6_hashed,
5160 s.raw4+s.udp4+s.tcp4_hashed,
5161 s.raw6+s.udp6+s.tcp6_hashed);
5162 printf("FRAG %-9d %-9d %-9d\n", s.frag4+s.frag6, s.frag4, s.frag6);
5163
5164 printf("\n");
5165
5166 return 0;
5167}
5168
7a96e199 5169static void _usage(FILE *dest)
aba5acdf 5170{
7a96e199 5171 fprintf(dest,
aba5acdf
SH
5172"Usage: ss [ OPTIONS ]\n"
5173" ss [ OPTIONS ] [ FILTER ]\n"
ff041f16
VK
5174" -h, --help this message\n"
5175" -V, --version output version information\n"
5176" -n, --numeric don't resolve service names\n"
ab61159a 5177" -r, --resolve resolve host names\n"
ff041f16
VK
5178" -a, --all display all sockets\n"
5179" -l, --listening display listening sockets\n"
ab61159a
SH
5180" -o, --options show timer information\n"
5181" -e, --extended show detailed socket information\n"
5182" -m, --memory show socket memory usage\n"
ff041f16
VK
5183" -p, --processes show process using socket\n"
5184" -i, --info show internal TCP information\n"
5caf79a0 5185" --tipcinfo show internal tipc socket information\n"
ff041f16 5186" -s, --summary show socket usage summary\n"
0f3f0ca3 5187" --tos show tos and priority information\n"
14f4bda5 5188" --cgroup show cgroup information\n"
b0f01cf6 5189" -b, --bpf show bpf filter socket information\n"
6885e3bf 5190" -E, --events continually display sockets as they are destroyed\n"
ff041f16
VK
5191" -Z, --context display process SELinux security contexts\n"
5192" -z, --contexts display process and socket SELinux security contexts\n"
95ce04bc 5193" -N, --net switch to the specified network namespace name\n"
ab61159a
SH
5194"\n"
5195" -4, --ipv4 display only IP version 4 sockets\n"
5196" -6, --ipv6 display only IP version 6 sockets\n"
ff041f16
VK
5197" -0, --packet display PACKET sockets\n"
5198" -t, --tcp display only TCP sockets\n"
9c3be2c0 5199" -M, --mptcp display only MPTCP sockets\n"
f89d46ad 5200" -S, --sctp display only SCTP sockets\n"
ff041f16
VK
5201" -u, --udp display only UDP sockets\n"
5202" -d, --dccp display only DCCP sockets\n"
5203" -w, --raw display only RAW sockets\n"
5204" -x, --unix display only Unix domain sockets\n"
5caf79a0 5205" --tipc display only TIPC sockets\n"
c759116a 5206" --vsock display only vsock sockets\n"
ab61159a 5207" -f, --family=FAMILY display sockets of type FAMILY\n"
2abc3d76 5208" FAMILY := {inet|inet6|link|unix|netlink|vsock|tipc|xdp|help}\n"
ab61159a 5209"\n"
fb2594c1 5210" -K, --kill forcibly close sockets, display what was closed\n"
7a4559f6 5211" -H, --no-header Suppress header line\n"
296b5de7 5212" -O, --oneline socket's data printed on a single line\n"
fb2594c1 5213"\n"
583de149 5214" -A, --query=QUERY, --socket=QUERY\n"
9c3be2c0 5215" QUERY := {all|inet|tcp|mptcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink|vsock_stream|vsock_dgram|tipc}[,QUERY]\n"
ab61159a 5216"\n"
583de149 5217" -D, --diag=FILE Dump raw information about TCP sockets to FILE\n"
ab61159a 5218" -F, --filter=FILE read filter information from FILE\n"
ff041f16
VK
5219" FILTER := [ state STATE-FILTER ] [ EXPRESSION ]\n"
5220" STATE-FILTER := {all|connected|synchronized|bucket|big|TCP-STATES}\n"
ae4e21c9 5221" TCP-STATES := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|closed|close-wait|last-ack|listening|closing}\n"
ff041f16
VK
5222" connected := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}\n"
5223" synchronized := {established|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}\n"
5224" bucket := {syn-recv|time-wait}\n"
ae4e21c9 5225" big := {established|syn-sent|fin-wait-{1,2}|closed|close-wait|last-ack|listening|closing}\n"
ab61159a 5226 );
7a96e199
AH
5227}
5228
5229static void help(void) __attribute__((noreturn));
5230static void help(void)
5231{
5232 _usage(stdout);
5233 exit(0);
5234}
5235
5236static void usage(void) __attribute__((noreturn));
5237static void usage(void)
5238{
5239 _usage(stderr);
aba5acdf
SH
5240 exit(-1);
5241}
5242
5243
d1f28cf1 5244static int scan_state(const char *state)
aba5acdf 5245{
b710a722
PS
5246 static const char * const sstate_namel[] = {
5247 "UNKNOWN",
5248 [SS_ESTABLISHED] = "established",
5249 [SS_SYN_SENT] = "syn-sent",
5250 [SS_SYN_RECV] = "syn-recv",
5251 [SS_FIN_WAIT1] = "fin-wait-1",
5252 [SS_FIN_WAIT2] = "fin-wait-2",
5253 [SS_TIME_WAIT] = "time-wait",
5254 [SS_CLOSE] = "unconnected",
5255 [SS_CLOSE_WAIT] = "close-wait",
5256 [SS_LAST_ACK] = "last-ack",
5257 [SS_LISTEN] = "listening",
5258 [SS_CLOSING] = "closing",
5259 };
aba5acdf 5260 int i;
acd1e437 5261
aba5acdf
SH
5262 if (strcasecmp(state, "close") == 0 ||
5263 strcasecmp(state, "closed") == 0)
5264 return (1<<SS_CLOSE);
5265 if (strcasecmp(state, "syn-rcv") == 0)
5266 return (1<<SS_SYN_RECV);
1a5bad5a 5267 if (strcasecmp(state, "established") == 0)
aba5acdf
SH
5268 return (1<<SS_ESTABLISHED);
5269 if (strcasecmp(state, "all") == 0)
5270 return SS_ALL;
5271 if (strcasecmp(state, "connected") == 0)
5272 return SS_ALL & ~((1<<SS_CLOSE)|(1<<SS_LISTEN));
1a5bad5a 5273 if (strcasecmp(state, "synchronized") == 0)
aba5acdf
SH
5274 return SS_ALL & ~((1<<SS_CLOSE)|(1<<SS_LISTEN)|(1<<SS_SYN_SENT));
5275 if (strcasecmp(state, "bucket") == 0)
5276 return (1<<SS_SYN_RECV)|(1<<SS_TIME_WAIT);
5277 if (strcasecmp(state, "big") == 0)
5278 return SS_ALL & ~((1<<SS_SYN_RECV)|(1<<SS_TIME_WAIT));
acd1e437 5279 for (i = 0; i < SS_MAX; i++) {
1a5bad5a 5280 if (strcasecmp(state, sstate_namel[i]) == 0)
aba5acdf
SH
5281 return (1<<i);
5282 }
9db7bf15
VK
5283
5284 fprintf(stderr, "ss: wrong state name: %s\n", state);
5285 exit(-1);
aba5acdf
SH
5286}
5287
c759116a
SH
5288/* Values 'v' and 'V' are already used so a non-character is used */
5289#define OPT_VSOCK 256
5290
5caf79a0
GM
5291/* Values of 't' are already used so a non-character is used */
5292#define OPT_TIPCSOCK 257
5293#define OPT_TIPCINFO 258
5294
0f3f0ca3
KK
5295#define OPT_TOS 259
5296
2abc3d76 5297/* Values of 'x' are already used so a non-character is used */
9f78e995 5298#define OPT_XDPSOCK 260
2abc3d76 5299
14f4bda5
DY
5300#define OPT_CGROUP 261
5301
ab61159a
SH
5302static const struct option long_opts[] = {
5303 { "numeric", 0, 0, 'n' },
5304 { "resolve", 0, 0, 'r' },
5305 { "options", 0, 0, 'o' },
5306 { "extended", 0, 0, 'e' },
5307 { "memory", 0, 0, 'm' },
5308 { "info", 0, 0, 'i' },
5309 { "processes", 0, 0, 'p' },
372c30d2 5310 { "bpf", 0, 0, 'b' },
6885e3bf 5311 { "events", 0, 0, 'E' },
351efcde 5312 { "dccp", 0, 0, 'd' },
ab61159a 5313 { "tcp", 0, 0, 't' },
f89d46ad 5314 { "sctp", 0, 0, 'S' },
ab61159a
SH
5315 { "udp", 0, 0, 'u' },
5316 { "raw", 0, 0, 'w' },
5317 { "unix", 0, 0, 'x' },
5caf79a0 5318 { "tipc", 0, 0, OPT_TIPCSOCK},
c759116a 5319 { "vsock", 0, 0, OPT_VSOCK },
ab61159a
SH
5320 { "all", 0, 0, 'a' },
5321 { "listening", 0, 0, 'l' },
5322 { "ipv4", 0, 0, '4' },
5323 { "ipv6", 0, 0, '6' },
5324 { "packet", 0, 0, '0' },
5325 { "family", 1, 0, 'f' },
5326 { "socket", 1, 0, 'A' },
583de149 5327 { "query", 1, 0, 'A' },
c3f346b0 5328 { "summary", 0, 0, 's' },
583de149 5329 { "diag", 1, 0, 'D' },
ab61159a
SH
5330 { "filter", 1, 0, 'F' },
5331 { "version", 0, 0, 'V' },
5332 { "help", 0, 0, 'h' },
116ac927
RH
5333 { "context", 0, 0, 'Z' },
5334 { "contexts", 0, 0, 'z' },
95ce04bc 5335 { "net", 1, 0, 'N' },
5caf79a0 5336 { "tipcinfo", 0, 0, OPT_TIPCINFO},
0f3f0ca3 5337 { "tos", 0, 0, OPT_TOS },
14f4bda5 5338 { "cgroup", 0, 0, OPT_CGROUP },
fb2594c1 5339 { "kill", 0, 0, 'K' },
7a4559f6 5340 { "no-header", 0, 0, 'H' },
2abc3d76 5341 { "xdp", 0, 0, OPT_XDPSOCK},
9c3be2c0 5342 { "mptcp", 0, 0, 'M' },
296b5de7 5343 { "oneline", 0, 0, 'O' },
ab61159a 5344 { 0 }
ae665a52 5345
ab61159a
SH
5346};
5347
aba5acdf
SH
5348int main(int argc, char *argv[])
5349{
aba5acdf
SH
5350 int saw_states = 0;
5351 int saw_query = 0;
5352 int do_summary = 0;
7d105b56 5353 const char *dump_tcpdiag = NULL;
aba5acdf
SH
5354 FILE *filter_fp = NULL;
5355 int ch;
9db7bf15 5356 int state_filter = 0;
aba5acdf 5357
168d97f9 5358 while ((ch = getopt_long(argc, argv,
9c3be2c0 5359 "dhaletuwxnro460spbEf:mMiA:D:F:vVzZN:KHSO",
ab61159a 5360 long_opts, NULL)) != EOF) {
acd1e437 5361 switch (ch) {
aba5acdf 5362 case 'n':
ca697cee 5363 numeric = 1;
aba5acdf
SH
5364 break;
5365 case 'r':
5366 resolve_hosts = 1;
5367 break;
5368 case 'o':
5369 show_options = 1;
5370 break;
5371 case 'e':
5372 show_options = 1;
5373 show_details++;
5374 break;
5375 case 'm':
5376 show_mem = 1;
5377 break;
5378 case 'i':
5379 show_tcpinfo = 1;
5380 break;
5381 case 'p':
5382 show_users++;
fbc0f876 5383 user_ent_hash_build();
aba5acdf 5384 break;
372c30d2
ND
5385 case 'b':
5386 show_options = 1;
5387 show_bpf++;
5388 break;
6885e3bf
CG
5389 case 'E':
5390 follow_events = 1;
5391 break;
351efcde 5392 case 'd':
c121111e 5393 filter_db_set(&current_filter, DCCP_DB, true);
351efcde 5394 break;
aba5acdf 5395 case 't':
c121111e 5396 filter_db_set(&current_filter, TCP_DB, true);
aba5acdf 5397 break;
f89d46ad 5398 case 'S':
c121111e 5399 filter_db_set(&current_filter, SCTP_DB, true);
f89d46ad 5400 break;
aba5acdf 5401 case 'u':
c121111e 5402 filter_db_set(&current_filter, UDP_DB, true);
aba5acdf
SH
5403 break;
5404 case 'w':
c121111e 5405 filter_db_set(&current_filter, RAW_DB, true);
aba5acdf
SH
5406 break;
5407 case 'x':
9db7bf15 5408 filter_af_set(&current_filter, AF_UNIX);
aba5acdf 5409 break;
c759116a
SH
5410 case OPT_VSOCK:
5411 filter_af_set(&current_filter, AF_VSOCK);
5412 break;
5caf79a0
GM
5413 case OPT_TIPCSOCK:
5414 filter_af_set(&current_filter, AF_TIPC);
5415 break;
aba5acdf 5416 case 'a':
9db7bf15 5417 state_filter = SS_ALL;
aba5acdf
SH
5418 break;
5419 case 'l':
9db7bf15 5420 state_filter = (1 << SS_LISTEN) | (1 << SS_CLOSE);
aba5acdf
SH
5421 break;
5422 case '4':
9db7bf15 5423 filter_af_set(&current_filter, AF_INET);
aba5acdf
SH
5424 break;
5425 case '6':
9db7bf15 5426 filter_af_set(&current_filter, AF_INET6);
aba5acdf
SH
5427 break;
5428 case '0':
9db7bf15 5429 filter_af_set(&current_filter, AF_PACKET);
aba5acdf 5430 break;
2abc3d76
BT
5431 case OPT_XDPSOCK:
5432 filter_af_set(&current_filter, AF_XDP);
5433 break;
9c3be2c0
PA
5434 case 'M':
5435 filter_db_set(&current_filter, MPTCP_DB, true);
5436 break;
aba5acdf
SH
5437 case 'f':
5438 if (strcmp(optarg, "inet") == 0)
9db7bf15 5439 filter_af_set(&current_filter, AF_INET);
aba5acdf 5440 else if (strcmp(optarg, "inet6") == 0)
9db7bf15 5441 filter_af_set(&current_filter, AF_INET6);
aba5acdf 5442 else if (strcmp(optarg, "link") == 0)
9db7bf15 5443 filter_af_set(&current_filter, AF_PACKET);
aba5acdf 5444 else if (strcmp(optarg, "unix") == 0)
9db7bf15 5445 filter_af_set(&current_filter, AF_UNIX);
aba5acdf 5446 else if (strcmp(optarg, "netlink") == 0)
9db7bf15 5447 filter_af_set(&current_filter, AF_NETLINK);
5caf79a0
GM
5448 else if (strcmp(optarg, "tipc") == 0)
5449 filter_af_set(&current_filter, AF_TIPC);
c759116a
SH
5450 else if (strcmp(optarg, "vsock") == 0)
5451 filter_af_set(&current_filter, AF_VSOCK);
2abc3d76
BT
5452 else if (strcmp(optarg, "xdp") == 0)
5453 filter_af_set(&current_filter, AF_XDP);
aba5acdf 5454 else if (strcmp(optarg, "help") == 0)
7a96e199 5455 help();
aba5acdf 5456 else {
9db7bf15
VK
5457 fprintf(stderr, "ss: \"%s\" is invalid family\n",
5458 optarg);
aba5acdf
SH
5459 usage();
5460 }
5461 break;
5462 case 'A':
5463 {
5464 char *p, *p1;
acd1e437 5465
aba5acdf
SH
5466 if (!saw_query) {
5467 current_filter.dbs = 0;
7f9dddbe 5468 state_filter = state_filter ?
acd1e437 5469 state_filter : SS_CONN;
aba5acdf
SH
5470 saw_query = 1;
5471 do_default = 0;
5472 }
5473 p = p1 = optarg;
5474 do {
5475 if ((p1 = strchr(p, ',')) != NULL)
ae665a52 5476 *p1 = 0;
67d5fd55 5477 if (filter_db_parse(&current_filter, p)) {
aba5acdf
SH
5478 fprintf(stderr, "ss: \"%s\" is illegal socket table id\n", p);
5479 usage();
5480 }
5481 p = p1 + 1;
5482 } while (p1);
5483 break;
5484 }
5485 case 's':
5486 do_summary = 1;
5487 break;
5488 case 'D':
5489 dump_tcpdiag = optarg;
5490 break;
5491 case 'F':
5492 if (filter_fp) {
5493 fprintf(stderr, "More than one filter file\n");
5494 exit(-1);
5495 }
5496 if (optarg[0] == '-')
5497 filter_fp = stdin;
5498 else
5499 filter_fp = fopen(optarg, "r");
5500 if (!filter_fp) {
5501 perror("fopen filter file");
5502 exit(-1);
5503 }
5504 break;
5505 case 'v':
5506 case 'V':
fbef6555 5507 printf("ss utility, iproute2-%s\n", version);
aba5acdf 5508 exit(0);
116ac927
RH
5509 case 'z':
5510 show_sock_ctx++;
36df1a6e 5511 /* fall through */
116ac927
RH
5512 case 'Z':
5513 if (is_selinux_enabled() <= 0) {
5514 fprintf(stderr, "ss: SELinux is not enabled.\n");
5515 exit(1);
5516 }
5517 show_proc_ctx++;
5518 user_ent_hash_build();
5519 break;
95ce04bc
VK
5520 case 'N':
5521 if (netns_switch(optarg))
5522 exit(1);
5523 break;
5caf79a0
GM
5524 case OPT_TIPCINFO:
5525 show_tipcinfo = 1;
5526 break;
0f3f0ca3
KK
5527 case OPT_TOS:
5528 show_tos = 1;
5529 break;
14f4bda5
DY
5530 case OPT_CGROUP:
5531 show_cgroup = 1;
5532 break;
fb2594c1
LC
5533 case 'K':
5534 current_filter.kill = 1;
5535 break;
7a4559f6
DA
5536 case 'H':
5537 show_header = 0;
5538 break;
296b5de7
JH
5539 case 'O':
5540 oneline = 1;
5541 break;
aba5acdf 5542 case 'h':
7a96e199 5543 help();
f73105ab 5544 case '?':
aba5acdf
SH
5545 default:
5546 usage();
5547 }
5548 }
5549
5550 argc -= optind;
5551 argv += optind;
5552
aba5acdf
SH
5553 if (do_summary) {
5554 print_summary();
5555 if (do_default && argc == 0)
5556 exit(0);
5557 }
5558
aba5acdf
SH
5559 while (argc > 0) {
5560 if (strcmp(*argv, "state") == 0) {
5561 NEXT_ARG();
5562 if (!saw_states)
9db7bf15
VK
5563 state_filter = 0;
5564 state_filter |= scan_state(*argv);
aba5acdf
SH
5565 saw_states = 1;
5566 } else if (strcmp(*argv, "exclude") == 0 ||
5567 strcmp(*argv, "excl") == 0) {
5568 NEXT_ARG();
5569 if (!saw_states)
9db7bf15
VK
5570 state_filter = SS_ALL;
5571 state_filter &= ~scan_state(*argv);
aba5acdf
SH
5572 saw_states = 1;
5573 } else {
aba5acdf
SH
5574 break;
5575 }
5576 argc--; argv++;
5577 }
5578
9db7bf15
VK
5579 if (do_default) {
5580 state_filter = state_filter ? state_filter : SS_CONN;
3e1652c9 5581 filter_db_parse(&current_filter, "all");
9db7bf15
VK
5582 }
5583
57ff5a10
VK
5584 filter_states_set(&current_filter, state_filter);
5585 filter_merge_defaults(&current_filter);
5586
ca697cee 5587 if (!numeric && resolve_hosts &&
168d97f9 5588 (current_filter.dbs & (UNIX_DBM|INET_L4_DBM)))
9db7bf15
VK
5589 init_service_resolver();
5590
9db7bf15
VK
5591 if (current_filter.dbs == 0) {
5592 fprintf(stderr, "ss: no socket tables to show with such filter.\n");
5593 exit(0);
5594 }
5595 if (current_filter.families == 0) {
5596 fprintf(stderr, "ss: no families to show with such filter.\n");
5597 exit(0);
5598 }
aba5acdf
SH
5599 if (current_filter.states == 0) {
5600 fprintf(stderr, "ss: no socket states to show with such filter.\n");
5601 exit(0);
5602 }
5603
5604 if (dump_tcpdiag) {
5605 FILE *dump_fp = stdout;
acd1e437 5606
aba5acdf
SH
5607 if (!(current_filter.dbs & (1<<TCP_DB))) {
5608 fprintf(stderr, "ss: tcpdiag dump requested and no tcp in filter.\n");
5609 exit(0);
5610 }
5611 if (dump_tcpdiag[0] != '-') {
5612 dump_fp = fopen(dump_tcpdiag, "w");
5613 if (!dump_tcpdiag) {
5614 perror("fopen dump file");
5615 exit(-1);
5616 }
5617 }
3fe5b534 5618 inet_show_netlink(&current_filter, dump_fp, IPPROTO_TCP);
aba5acdf
SH
5619 fflush(dump_fp);
5620 exit(0);
5621 }
5622
1527a17e
VK
5623 if (ssfilter_parse(&current_filter.f, argc, argv, filter_fp))
5624 usage();
5625
87b1a7ae
SB
5626 if (!(current_filter.dbs & (current_filter.dbs - 1)))
5627 columns[COL_NETID].disabled = 1;
59f46b7b 5628
87b1a7ae
SB
5629 if (!(current_filter.states & (current_filter.states - 1)))
5630 columns[COL_STATE].disabled = 1;
aba5acdf 5631
59f46b7b
SB
5632 if (show_header)
5633 print_header();
aba5acdf 5634
aba5acdf
SH
5635 fflush(stdout);
5636
6885e3bf
CG
5637 if (follow_events)
5638 exit(handle_follow_request(&current_filter));
5639
aba5acdf
SH
5640 if (current_filter.dbs & (1<<NETLINK_DB))
5641 netlink_show(&current_filter);
5642 if (current_filter.dbs & PACKET_DBM)
5643 packet_show(&current_filter);
5644 if (current_filter.dbs & UNIX_DBM)
5645 unix_show(&current_filter);
5646 if (current_filter.dbs & (1<<RAW_DB))
5647 raw_show(&current_filter);
5648 if (current_filter.dbs & (1<<UDP_DB))
5649 udp_show(&current_filter);
5650 if (current_filter.dbs & (1<<TCP_DB))
6c6bbc30 5651 tcp_show(&current_filter);
351efcde 5652 if (current_filter.dbs & (1<<DCCP_DB))
6c6bbc30 5653 dccp_show(&current_filter);
f89d46ad
PS
5654 if (current_filter.dbs & (1<<SCTP_DB))
5655 sctp_show(&current_filter);
c759116a
SH
5656 if (current_filter.dbs & VSOCK_DBM)
5657 vsock_show(&current_filter);
5caf79a0
GM
5658 if (current_filter.dbs & (1<<TIPC_DB))
5659 tipc_show(&current_filter);
2abc3d76
BT
5660 if (current_filter.dbs & (1<<XDP_DB))
5661 xdp_show(&current_filter);
9c3be2c0
PA
5662 if (current_filter.dbs & (1<<MPTCP_DB))
5663 mptcp_show(&current_filter);
116ac927
RH
5664
5665 if (show_users || show_proc_ctx || show_sock_ctx)
5666 user_ent_destroy();
5667
32ea3d54 5668 render();
59f46b7b 5669
aba5acdf
SH
5670 return 0;
5671}