2 * ss.c "sockstat", socket statistics
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.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
17 #include <sys/ioctl.h>
18 #include <sys/socket.h>
20 #include <netinet/in.h>
24 #include <arpa/inet.h>
34 #include "libnetlink.h"
35 #include "namespace.h"
38 #include <linux/tcp.h>
39 #include <linux/sock_diag.h>
40 #include <linux/inet_diag.h>
41 #include <linux/unix_diag.h>
42 #include <linux/netdevice.h> /* for MAX_ADDR_LEN */
43 #include <linux/filter.h>
44 #include <linux/packet_diag.h>
45 #include <linux/netlink_diag.h>
46 #include <linux/sctp.h>
48 #define MAGIC_SEQ 123456
50 #define DIAG_REQUEST(_req, _r) \
52 struct nlmsghdr nlh; \
56 .nlmsg_type = SOCK_DIAG_BY_FAMILY, \
57 .nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST,\
58 .nlmsg_seq = MAGIC_SEQ, \
59 .nlmsg_len = sizeof(_req), \
64 #include <selinux/selinux.h>
66 /* Stubs for SELinux functions */
67 static int is_selinux_enabled(void)
72 static int getpidcon(pid_t pid
, char **context
)
78 static int getfilecon(char *path
, char **context
)
84 static int security_get_initial_context(char *name
, char **context
)
92 int resolve_services
= 1;
93 int preferred_family
= AF_UNSPEC
;
110 char *odd_width_pad
= "";
112 static const char *TCP_PROTO
= "tcp";
113 static const char *SCTP_PROTO
= "sctp";
114 static const char *UDP_PROTO
= "udp";
115 static const char *RAW_PROTO
= "raw";
116 static const char *dg_proto
;
133 #define PACKET_DBM ((1<<PACKET_DG_DB)|(1<<PACKET_R_DB))
134 #define UNIX_DBM ((1<<UNIX_DG_DB)|(1<<UNIX_ST_DB)|(1<<UNIX_SQ_DB))
135 #define ALL_DB ((1<<MAX_DB)-1)
136 #define INET_L4_DBM ((1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB)|(1<<SCTP_DB))
137 #define INET_DBM (INET_L4_DBM | (1<<RAW_DB))
156 SCTP_STATE_CLOSED
= 0,
157 SCTP_STATE_COOKIE_WAIT
= 1,
158 SCTP_STATE_COOKIE_ECHOED
= 2,
159 SCTP_STATE_ESTABLISHED
= 3,
160 SCTP_STATE_SHUTDOWN_PENDING
= 4,
161 SCTP_STATE_SHUTDOWN_SENT
= 5,
162 SCTP_STATE_SHUTDOWN_RECEIVED
= 6,
163 SCTP_STATE_SHUTDOWN_ACK_SENT
= 7,
166 #define SS_ALL ((1 << SS_MAX) - 1)
167 #define SS_CONN (SS_ALL & ~((1<<SS_LISTEN)|(1<<SS_CLOSE)|(1<<SS_TIME_WAIT)|(1<<SS_SYN_RECV)))
169 #include "ssfilter.h"
179 static const struct filter default_dbs
[MAX_DB
] = {
182 .families
= (1 << AF_INET
) | (1 << AF_INET6
),
186 .families
= (1 << AF_INET
) | (1 << AF_INET6
),
189 .states
= (1 << SS_ESTABLISHED
),
190 .families
= (1 << AF_INET
) | (1 << AF_INET6
),
193 .states
= (1 << SS_ESTABLISHED
),
194 .families
= (1 << AF_INET
) | (1 << AF_INET6
),
197 .states
= (1 << SS_CLOSE
),
198 .families
= (1 << AF_UNIX
),
202 .families
= (1 << AF_UNIX
),
206 .families
= (1 << AF_UNIX
),
209 .states
= (1 << SS_CLOSE
),
210 .families
= (1 << AF_PACKET
),
213 .states
= (1 << SS_CLOSE
),
214 .families
= (1 << AF_PACKET
),
217 .states
= (1 << SS_CLOSE
),
218 .families
= (1 << AF_NETLINK
),
222 .families
= (1 << AF_INET
) | (1 << AF_INET6
),
226 static const struct filter default_afs
[AF_MAX
] = {
241 .states
= (1 << SS_CLOSE
),
244 .dbs
= (1 << NETLINK_DB
),
245 .states
= (1 << SS_CLOSE
),
249 static int do_default
= 1;
250 static struct filter current_filter
;
252 static void filter_db_set(struct filter
*f
, int db
)
254 f
->states
|= default_dbs
[db
].states
;
259 static void filter_af_set(struct filter
*f
, int af
)
261 f
->states
|= default_afs
[af
].states
;
262 f
->families
|= 1 << af
;
264 preferred_family
= af
;
267 static int filter_af_get(struct filter
*f
, int af
)
269 return f
->families
& (1 << af
);
272 static void filter_default_dbs(struct filter
*f
)
274 filter_db_set(f
, UDP_DB
);
275 filter_db_set(f
, DCCP_DB
);
276 filter_db_set(f
, TCP_DB
);
277 filter_db_set(f
, RAW_DB
);
278 filter_db_set(f
, UNIX_ST_DB
);
279 filter_db_set(f
, UNIX_DG_DB
);
280 filter_db_set(f
, UNIX_SQ_DB
);
281 filter_db_set(f
, PACKET_R_DB
);
282 filter_db_set(f
, PACKET_DG_DB
);
283 filter_db_set(f
, NETLINK_DB
);
284 filter_db_set(f
, SCTP_DB
);
287 static void filter_states_set(struct filter
*f
, int states
)
293 static void filter_merge_defaults(struct filter
*f
)
298 for (db
= 0; db
< MAX_DB
; db
++) {
299 if (!(f
->dbs
& (1 << db
)))
302 if (!(default_dbs
[db
].families
& f
->families
))
303 f
->families
|= default_dbs
[db
].families
;
305 for (af
= 0; af
< AF_MAX
; af
++) {
306 if (!(f
->families
& (1 << af
)))
309 if (!(default_afs
[af
].dbs
& f
->dbs
))
310 f
->dbs
|= default_afs
[af
].dbs
;
314 static FILE *generic_proc_open(const char *env
, const char *name
)
316 const char *p
= getenv(env
);
320 p
= getenv("PROC_ROOT") ? : "/proc";
321 snprintf(store
, sizeof(store
)-1, "%s/%s", p
, name
);
325 return fopen(p
, "r");
327 #define net_tcp_open() generic_proc_open("PROC_NET_TCP", "net/tcp")
328 #define net_tcp6_open() generic_proc_open("PROC_NET_TCP6", "net/tcp6")
329 #define net_udp_open() generic_proc_open("PROC_NET_UDP", "net/udp")
330 #define net_udp6_open() generic_proc_open("PROC_NET_UDP6", "net/udp6")
331 #define net_raw_open() generic_proc_open("PROC_NET_RAW", "net/raw")
332 #define net_raw6_open() generic_proc_open("PROC_NET_RAW6", "net/raw6")
333 #define net_unix_open() generic_proc_open("PROC_NET_UNIX", "net/unix")
334 #define net_packet_open() generic_proc_open("PROC_NET_PACKET", \
336 #define net_netlink_open() generic_proc_open("PROC_NET_NETLINK", \
338 #define slabinfo_open() generic_proc_open("PROC_SLABINFO", "slabinfo")
339 #define net_sockstat_open() generic_proc_open("PROC_NET_SOCKSTAT", \
341 #define net_sockstat6_open() generic_proc_open("PROC_NET_SOCKSTAT6", \
343 #define net_snmp_open() generic_proc_open("PROC_NET_SNMP", "net/snmp")
344 #define ephemeral_ports_open() generic_proc_open("PROC_IP_LOCAL_PORT_RANGE", \
345 "sys/net/ipv4/ip_local_port_range")
348 struct user_ent
*next
;
357 #define USER_ENT_HASH_SIZE 256
358 struct user_ent
*user_ent_hash
[USER_ENT_HASH_SIZE
];
360 static int user_ent_hashfn(unsigned int ino
)
362 int val
= (ino
>> 24) ^ (ino
>> 16) ^ (ino
>> 8) ^ ino
;
364 return val
& (USER_ENT_HASH_SIZE
- 1);
367 static void user_ent_add(unsigned int ino
, char *process
,
372 struct user_ent
*p
, **pp
;
374 p
= malloc(sizeof(struct user_ent
));
376 fprintf(stderr
, "ss: failed to malloc buffer\n");
383 p
->process
= strdup(process
);
384 p
->process_ctx
= strdup(proc_ctx
);
385 p
->socket_ctx
= strdup(sock_ctx
);
387 pp
= &user_ent_hash
[user_ent_hashfn(ino
)];
392 static void user_ent_destroy(void)
394 struct user_ent
*p
, *p_next
;
397 while (cnt
!= USER_ENT_HASH_SIZE
) {
398 p
= user_ent_hash
[cnt
];
401 free(p
->process_ctx
);
411 static void user_ent_hash_build(void)
413 const char *root
= getenv("PROC_ROOT") ? : "/proc/";
420 const char *no_ctx
= "unavailable";
421 static int user_ent_hash_build_init
;
423 /* If show_users & show_proc_ctx set only do this once */
424 if (user_ent_hash_build_init
!= 0)
427 user_ent_hash_build_init
= 1;
429 strlcpy(name
, root
, sizeof(name
));
431 if (strlen(name
) == 0 || name
[strlen(name
)-1] != '/')
434 nameoff
= strlen(name
);
440 while ((d
= readdir(dir
)) != NULL
) {
448 if (sscanf(d
->d_name
, "%d%c", &pid
, &crap
) != 1)
451 if (getpidcon(pid
, &pid_context
) != 0)
452 pid_context
= strdup(no_ctx
);
454 snprintf(name
+ nameoff
, sizeof(name
) - nameoff
, "%d/fd/", pid
);
456 if ((dir1
= opendir(name
)) == NULL
) {
464 while ((d1
= readdir(dir1
)) != NULL
) {
465 const char *pattern
= "socket:[";
472 if (sscanf(d1
->d_name
, "%d%c", &fd
, &crap
) != 1)
475 snprintf(name
+pos
, sizeof(name
) - pos
, "%d", fd
);
477 link_len
= readlink(name
, lnk
, sizeof(lnk
)-1);
480 lnk
[link_len
] = '\0';
482 if (strncmp(lnk
, pattern
, strlen(pattern
)))
485 sscanf(lnk
, "socket:[%u]", &ino
);
487 snprintf(tmp
, sizeof(tmp
), "%s/%d/fd/%s",
488 root
, pid
, d1
->d_name
);
490 if (getfilecon(tmp
, &sock_context
) <= 0)
491 sock_context
= strdup(no_ctx
);
496 snprintf(tmp
, sizeof(tmp
), "%s/%d/stat",
498 if ((fp
= fopen(tmp
, "r")) != NULL
) {
499 if (fscanf(fp
, "%*d (%[^)])", p
) < 1)
504 user_ent_add(ino
, p
, pid
, fd
,
505 pid_context
, sock_context
);
520 #define ENTRY_BUF_SIZE 512
521 static int find_entry(unsigned int ino
, char **buf
, int type
)
527 int len
, new_buf_len
;
534 p
= user_ent_hash
[user_ent_hashfn(ino
)];
541 ptr
= *buf
+ buf_used
;
544 len
= snprintf(ptr
, buf_len
- buf_used
,
545 "(\"%s\",pid=%d,fd=%d),",
546 p
->process
, p
->pid
, p
->fd
);
549 len
= snprintf(ptr
, buf_len
- buf_used
,
550 "(\"%s\",pid=%d,proc_ctx=%s,fd=%d),",
552 p
->process_ctx
, p
->fd
);
555 len
= snprintf(ptr
, buf_len
- buf_used
,
556 "(\"%s\",pid=%d,proc_ctx=%s,fd=%d,sock_ctx=%s),",
558 p
->process_ctx
, p
->fd
,
562 fprintf(stderr
, "ss: invalid type: %d\n", type
);
566 if (len
< 0 || len
>= buf_len
- buf_used
) {
567 new_buf_len
= buf_len
+ ENTRY_BUF_SIZE
;
568 new_buf
= realloc(*buf
, new_buf_len
);
570 fprintf(stderr
, "ss: failed to malloc buffer\n");
574 buf_len
= new_buf_len
;
586 ptr
= *buf
+ buf_used
;
592 /* Get stats from slab */
602 static struct slabstat slabstat
;
604 static int get_slabstat(struct slabstat
*s
)
609 static int slabstat_valid
;
610 static const char * const slabstat_ids
[] = {
621 memset(s
, 0, sizeof(*s
));
623 fp
= slabinfo_open();
627 cnt
= sizeof(*s
)/sizeof(int);
629 if (!fgets(buf
, sizeof(buf
), fp
)) {
633 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
636 for (i
= 0; i
< ARRAY_SIZE(slabstat_ids
); i
++) {
637 if (memcmp(buf
, slabstat_ids
[i
], strlen(slabstat_ids
[i
])) == 0) {
638 sscanf(buf
, "%*s%d", ((int *)s
) + i
);
653 static unsigned long long cookie_sk_get(const uint32_t *cookie
)
655 return (((unsigned long long)cookie
[1] << 31) << 1) | cookie
[0];
658 static const char *sctp_sstate_name
[] = {
659 [SCTP_STATE_CLOSED
] = "CLOSED",
660 [SCTP_STATE_COOKIE_WAIT
] = "COOKIE_WAIT",
661 [SCTP_STATE_COOKIE_ECHOED
] = "COOKIE_ECHOED",
662 [SCTP_STATE_ESTABLISHED
] = "ESTAB",
663 [SCTP_STATE_SHUTDOWN_PENDING
] = "SHUTDOWN_PENDING",
664 [SCTP_STATE_SHUTDOWN_SENT
] = "SHUTDOWN_SENT",
665 [SCTP_STATE_SHUTDOWN_RECEIVED
] = "SHUTDOWN_RECEIVED",
666 [SCTP_STATE_SHUTDOWN_ACK_SENT
] = "ACK_SENT",
670 struct sockstat
*next
;
684 unsigned long long sk
;
691 unsigned int ce_state
;
701 unsigned int timeout
;
704 double rto
, ato
, rtt
, rttvar
;
705 int qack
, ssthresh
, backoff
;
713 unsigned int lastsnd
;
714 unsigned int lastrcv
;
715 unsigned int lastack
;
717 double pacing_rate_max
;
718 double delivery_rate
;
719 unsigned long long bytes_acked
;
720 unsigned long long bytes_received
;
721 unsigned int segs_out
;
722 unsigned int segs_in
;
723 unsigned int data_segs_out
;
724 unsigned int data_segs_in
;
725 unsigned int unacked
;
726 unsigned int retrans
;
727 unsigned int retrans_total
;
730 unsigned int fackets
;
731 unsigned int reordering
;
732 unsigned int not_sent
;
736 unsigned long long busy_time
;
737 unsigned long long rwnd_limited
;
738 unsigned long long sndbuf_limited
;
742 bool has_ecnseen_opt
;
743 bool has_fastopen_opt
;
746 struct dctcpstat
*dctcp
;
747 struct tcp_bbr_info
*bbr_info
;
750 /* SCTP assocs share the same inode number with their parent endpoint. So if we
751 * have seen the inode number before, it must be an assoc instead of the next
753 static bool is_sctp_assoc(struct sockstat
*s
, const char *sock_name
)
755 if (strcmp(sock_name
, "sctp"))
757 if (!sctp_ino
|| sctp_ino
!= s
->ino
)
762 static const char *unix_netid_name(int type
)
775 static const char *proto_name(int protocol
)
795 static void sock_state_print(struct sockstat
*s
)
797 const char *sock_name
;
798 static const char * const sstate_name
[] = {
800 [SS_ESTABLISHED
] = "ESTAB",
801 [SS_SYN_SENT
] = "SYN-SENT",
802 [SS_SYN_RECV
] = "SYN-RECV",
803 [SS_FIN_WAIT1
] = "FIN-WAIT-1",
804 [SS_FIN_WAIT2
] = "FIN-WAIT-2",
805 [SS_TIME_WAIT
] = "TIME-WAIT",
806 [SS_CLOSE
] = "UNCONN",
807 [SS_CLOSE_WAIT
] = "CLOSE-WAIT",
808 [SS_LAST_ACK
] = "LAST-ACK",
809 [SS_LISTEN
] = "LISTEN",
810 [SS_CLOSING
] = "CLOSING",
813 switch (s
->local
.family
) {
815 sock_name
= unix_netid_name(s
->type
);
819 sock_name
= proto_name(s
->type
);
822 sock_name
= s
->type
== SOCK_RAW
? "p_raw" : "p_dgr";
828 sock_name
= "unknown";
832 printf("%-*s ", netid_width
,
833 is_sctp_assoc(s
, sock_name
) ? "" : sock_name
);
835 if (is_sctp_assoc(s
, sock_name
))
836 printf("`- %-*s ", state_width
- 3,
837 sctp_sstate_name
[s
->state
]);
839 printf("%-*s ", state_width
, sstate_name
[s
->state
]);
842 printf("%-6d %-6d %s", s
->rq
, s
->wq
, odd_width_pad
);
845 static void sock_details_print(struct sockstat
*s
)
848 printf(" uid:%u", s
->uid
);
850 printf(" ino:%u", s
->ino
);
851 printf(" sk:%llx", s
->sk
);
854 printf(" fwmark:0x%x", s
->mark
);
857 static void sock_addr_print_width(int addr_len
, const char *addr
, char *delim
,
858 int port_len
, const char *port
, const char *ifname
)
861 printf("%*s%%%s%s%-*s ", addr_len
, addr
, ifname
, delim
,
864 printf("%*s%s%-*s ", addr_len
, addr
, delim
, port_len
, port
);
868 static void sock_addr_print(const char *addr
, char *delim
, const char *port
,
871 sock_addr_print_width(addr_width
, addr
, delim
, serv_width
, port
, ifname
);
874 static const char *print_ms_timer(unsigned int timeout
)
877 int secs
, msecs
, minutes
;
882 msecs
= timeout
%1000;
886 snprintf(buf
, sizeof(buf
)-16, "%dmin", minutes
);
893 sprintf(buf
+strlen(buf
), "%d%s", secs
, msecs
? "." : "sec");
896 sprintf(buf
+strlen(buf
), "%03dms", msecs
);
907 struct scache
*rlist
;
909 static void init_service_resolver(void)
912 FILE *fp
= popen("/usr/sbin/rpcinfo -p 2>/dev/null", "r");
917 if (!fgets(buf
, sizeof(buf
), fp
)) {
921 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
922 unsigned int progn
, port
;
923 char proto
[128], prog
[128] = "rpc.";
926 if (sscanf(buf
, "%u %*d %s %u %s",
927 &progn
, proto
, &port
, prog
+4) != 4)
930 if (!(c
= malloc(sizeof(*c
))))
934 c
->name
= strdup(prog
);
935 if (strcmp(proto
, TCP_PROTO
) == 0)
936 c
->proto
= TCP_PROTO
;
937 else if (strcmp(proto
, UDP_PROTO
) == 0)
938 c
->proto
= UDP_PROTO
;
939 else if (strcmp(proto
, SCTP_PROTO
) == 0)
940 c
->proto
= SCTP_PROTO
;
949 /* Even do not try default linux ephemeral port ranges:
950 * default /etc/services contains so much of useless crap
951 * wouldbe "allocated" to this area that resolution
952 * is really harmful. I shrug each time when seeing
953 * "socks" or "cfinger" in dumps.
955 static int is_ephemeral(int port
)
957 static int min
= 0, max
;
960 FILE *f
= ephemeral_ports_open();
962 if (!f
|| fscanf(f
, "%d %d", &min
, &max
) < 2) {
969 return port
>= min
&& port
<= max
;
973 static const char *__resolve_service(int port
)
977 for (c
= rlist
; c
; c
= c
->next
) {
978 if (c
->port
== port
&& c
->proto
== dg_proto
)
982 if (!is_ephemeral(port
)) {
990 se
= getservbyport(htons(port
), dg_proto
);
998 #define SCACHE_BUCKETS 1024
999 static struct scache
*cache_htab
[SCACHE_BUCKETS
];
1001 static const char *resolve_service(int port
)
1003 static char buf
[128];
1014 if (!resolve_services
)
1017 if (dg_proto
== RAW_PROTO
)
1018 return inet_proto_n2a(port
, buf
, sizeof(buf
));
1021 hash
= (port
^(((unsigned long)dg_proto
)>>2)) % SCACHE_BUCKETS
;
1023 for (c
= cache_htab
[hash
]; c
; c
= c
->next
) {
1024 if (c
->port
== port
&& c
->proto
== dg_proto
)
1028 c
= malloc(sizeof(*c
));
1031 res
= __resolve_service(port
);
1033 c
->name
= res
? strdup(res
) : NULL
;
1034 c
->proto
= dg_proto
;
1035 c
->next
= cache_htab
[hash
];
1036 cache_htab
[hash
] = c
;
1043 sprintf(buf
, "%u", port
);
1047 static void inet_addr_print(const inet_prefix
*a
, int port
,
1048 unsigned int ifindex
, bool v6only
)
1051 const char *ap
= buf
;
1052 int est_len
= addr_width
;
1053 const char *ifname
= NULL
;
1055 if (a
->family
== AF_INET
) {
1056 ap
= format_host(AF_INET
, 4, a
->data
);
1059 !memcmp(a
->data
, &in6addr_any
, sizeof(in6addr_any
))) {
1063 ap
= format_host(a
->family
, 16, a
->data
);
1065 /* Numeric IPv6 addresses should be bracketed */
1066 if (strchr(ap
, ':')) {
1067 snprintf(buf
, sizeof(buf
),
1072 est_len
= strlen(ap
);
1073 if (est_len
<= addr_width
)
1074 est_len
= addr_width
;
1076 est_len
= addr_width
+ ((est_len
-addr_width
+3)/4)*4;
1081 ifname
= ll_index_to_name(ifindex
);
1082 est_len
-= strlen(ifname
) + 1; /* +1 for percent char */
1087 sock_addr_print_width(est_len
, ap
, ":", serv_width
, resolve_service(port
),
1097 struct aafilter
*next
;
1100 static int inet2_addr_match(const inet_prefix
*a
, const inet_prefix
*p
,
1103 if (!inet_addr_match(a
, p
, plen
))
1106 /* Cursed "v4 mapped" addresses: v4 mapped socket matches
1107 * pure IPv4 rule, but v4-mapped rule selects only v4-mapped
1109 if (p
->family
== AF_INET
&& a
->family
== AF_INET6
) {
1110 if (a
->data
[0] == 0 && a
->data
[1] == 0 &&
1111 a
->data
[2] == htonl(0xffff)) {
1112 inet_prefix tmp
= *a
;
1114 tmp
.data
[0] = a
->data
[3];
1115 return inet_addr_match(&tmp
, p
, plen
);
1121 static int unix_match(const inet_prefix
*a
, const inet_prefix
*p
)
1123 char *addr
, *pattern
;
1125 memcpy(&addr
, a
->data
, sizeof(addr
));
1126 memcpy(&pattern
, p
->data
, sizeof(pattern
));
1127 if (pattern
== NULL
)
1131 return !fnmatch(pattern
, addr
, 0);
1134 static int run_ssfilter(struct ssfilter
*f
, struct sockstat
*s
)
1139 if (s
->local
.family
== AF_UNIX
) {
1142 memcpy(&p
, s
->local
.data
, sizeof(p
));
1143 return p
== NULL
|| (p
[0] == '@' && strlen(p
) == 6 &&
1144 strspn(p
+1, "0123456789abcdef") == 5);
1146 if (s
->local
.family
== AF_PACKET
)
1147 return s
->lport
== 0 && s
->local
.data
[0] == 0;
1148 if (s
->local
.family
== AF_NETLINK
)
1149 return s
->lport
< 0;
1151 return is_ephemeral(s
->lport
);
1155 struct aafilter
*a
= (void *)f
->pred
;
1157 if (a
->addr
.family
== AF_UNIX
)
1158 return unix_match(&s
->remote
, &a
->addr
);
1159 if (a
->port
!= -1 && a
->port
!= s
->rport
)
1161 if (a
->addr
.bitlen
) {
1163 if (!inet2_addr_match(&s
->remote
, &a
->addr
, a
->addr
.bitlen
))
1165 } while ((a
= a
->next
) != NULL
);
1172 struct aafilter
*a
= (void *)f
->pred
;
1174 if (a
->addr
.family
== AF_UNIX
)
1175 return unix_match(&s
->local
, &a
->addr
);
1176 if (a
->port
!= -1 && a
->port
!= s
->lport
)
1178 if (a
->addr
.bitlen
) {
1180 if (!inet2_addr_match(&s
->local
, &a
->addr
, a
->addr
.bitlen
))
1182 } while ((a
= a
->next
) != NULL
);
1189 struct aafilter
*a
= (void *)f
->pred
;
1191 return s
->rport
>= a
->port
;
1195 struct aafilter
*a
= (void *)f
->pred
;
1197 return s
->rport
<= a
->port
;
1201 struct aafilter
*a
= (void *)f
->pred
;
1203 return s
->lport
>= a
->port
;
1207 struct aafilter
*a
= (void *)f
->pred
;
1209 return s
->lport
<= a
->port
;
1213 struct aafilter
*a
= (void *)f
->pred
;
1215 return s
->iface
== a
->iface
;
1219 struct aafilter
*a
= (void *)f
->pred
;
1221 return (s
->mark
& a
->mask
) == a
->mark
;
1223 /* Yup. It is recursion. Sorry. */
1225 return run_ssfilter(f
->pred
, s
) && run_ssfilter(f
->post
, s
);
1227 return run_ssfilter(f
->pred
, s
) || run_ssfilter(f
->post
, s
);
1229 return !run_ssfilter(f
->pred
, s
);
1235 /* Relocate external jumps by reloc. */
1236 static void ssfilter_patch(char *a
, int len
, int reloc
)
1239 struct inet_diag_bc_op
*op
= (struct inet_diag_bc_op
*)a
;
1241 if (op
->no
== len
+4)
1250 static int ssfilter_bytecompile(struct ssfilter
*f
, char **bytecode
)
1255 if (!(*bytecode
= malloc(4))) abort();
1256 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_AUTO
, 4, 8 };
1262 struct aafilter
*a
= (void *)f
->pred
;
1265 int code
= (f
->type
== SSF_DCOND
? INET_DIAG_BC_D_COND
: INET_DIAG_BC_S_COND
);
1268 for (b
= a
; b
; b
= b
->next
) {
1269 len
+= 4 + sizeof(struct inet_diag_hostcond
);
1270 if (a
->addr
.family
== AF_INET6
)
1277 if (!(ptr
= malloc(len
))) abort();
1279 for (b
= a
; b
; b
= b
->next
) {
1280 struct inet_diag_bc_op
*op
= (struct inet_diag_bc_op
*)ptr
;
1281 int alen
= (a
->addr
.family
== AF_INET6
? 16 : 4);
1282 int oplen
= alen
+ 4 + sizeof(struct inet_diag_hostcond
);
1283 struct inet_diag_hostcond
*cond
= (struct inet_diag_hostcond
*)(ptr
+4);
1285 *op
= (struct inet_diag_bc_op
){ code
, oplen
, oplen
+4 };
1286 cond
->family
= a
->addr
.family
;
1287 cond
->port
= a
->port
;
1288 cond
->prefix_len
= a
->addr
.bitlen
;
1289 memcpy(cond
->addr
, a
->addr
.data
, alen
);
1292 op
= (struct inet_diag_bc_op
*)ptr
;
1293 *op
= (struct inet_diag_bc_op
){ INET_DIAG_BC_JMP
, 4, len
- (ptr
-*bytecode
)};
1297 return ptr
- *bytecode
;
1301 struct aafilter
*x
= (void *)f
->pred
;
1303 if (!(*bytecode
= malloc(8))) abort();
1304 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_D_GE
, 8, 12 };
1305 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
1310 struct aafilter
*x
= (void *)f
->pred
;
1312 if (!(*bytecode
= malloc(8))) abort();
1313 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_D_LE
, 8, 12 };
1314 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
1319 struct aafilter
*x
= (void *)f
->pred
;
1321 if (!(*bytecode
= malloc(8))) abort();
1322 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_S_GE
, 8, 12 };
1323 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
1328 struct aafilter
*x
= (void *)f
->pred
;
1330 if (!(*bytecode
= malloc(8))) abort();
1331 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_S_LE
, 8, 12 };
1332 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
1338 char *a1
= NULL
, *a2
= NULL
, *a
;
1341 l1
= ssfilter_bytecompile(f
->pred
, &a1
);
1342 l2
= ssfilter_bytecompile(f
->post
, &a2
);
1348 if (!(a
= malloc(l1
+l2
))) abort();
1350 memcpy(a
+l1
, a2
, l2
);
1352 ssfilter_patch(a
, l1
, l2
);
1358 char *a1
= NULL
, *a2
= NULL
, *a
;
1361 l1
= ssfilter_bytecompile(f
->pred
, &a1
);
1362 l2
= ssfilter_bytecompile(f
->post
, &a2
);
1368 if (!(a
= malloc(l1
+l2
+4))) abort();
1370 memcpy(a
+l1
+4, a2
, l2
);
1372 *(struct inet_diag_bc_op
*)(a
+l1
) = (struct inet_diag_bc_op
){ INET_DIAG_BC_JMP
, 4, l2
+4 };
1378 char *a1
= NULL
, *a
;
1381 l1
= ssfilter_bytecompile(f
->pred
, &a1
);
1386 if (!(a
= malloc(l1
+4))) abort();
1389 *(struct inet_diag_bc_op
*)(a
+l1
) = (struct inet_diag_bc_op
){ INET_DIAG_BC_JMP
, 4, 8 };
1395 /* bytecompile for SSF_DEVCOND not supported yet */
1400 struct aafilter
*a
= (void *)f
->pred
;
1402 struct inet_diag_bc_op op
;
1403 struct inet_diag_markcond cond
;
1405 int inslen
= sizeof(struct instr
);
1407 if (!(*bytecode
= malloc(inslen
))) abort();
1408 ((struct instr
*)*bytecode
)[0] = (struct instr
) {
1409 { INET_DIAG_BC_MARK_COND
, inslen
, inslen
+ 4 },
1410 { a
->mark
, a
->mask
},
1420 static int remember_he(struct aafilter
*a
, struct hostent
*he
)
1422 char **ptr
= he
->h_addr_list
;
1426 if (he
->h_addrtype
== AF_INET
)
1428 else if (he
->h_addrtype
== AF_INET6
)
1434 struct aafilter
*b
= a
;
1436 if (a
->addr
.bitlen
) {
1437 if ((b
= malloc(sizeof(*b
))) == NULL
)
1442 memcpy(b
->addr
.data
, *ptr
, len
);
1443 b
->addr
.bytelen
= len
;
1444 b
->addr
.bitlen
= len
*8;
1445 b
->addr
.family
= he
->h_addrtype
;
1452 static int get_dns_host(struct aafilter
*a
, const char *addr
, int fam
)
1454 static int notfirst
;
1463 he
= gethostbyname2(addr
, fam
== AF_UNSPEC
? AF_INET
: fam
);
1465 cnt
= remember_he(a
, he
);
1466 if (fam
== AF_UNSPEC
) {
1467 he
= gethostbyname2(addr
, AF_INET6
);
1469 cnt
+= remember_he(a
, he
);
1474 static int xll_initted
;
1476 static void xll_init(void)
1478 struct rtnl_handle rth
;
1480 if (rtnl_open(&rth
, 0) < 0)
1488 static const char *xll_index_to_name(int index
)
1492 return ll_index_to_name(index
);
1495 static int xll_name_to_index(const char *dev
)
1499 return ll_name_to_index(dev
);
1502 void *parse_devcond(char *name
)
1504 struct aafilter a
= { .iface
= 0 };
1505 struct aafilter
*res
;
1507 a
.iface
= xll_name_to_index(name
);
1512 n
= strtoul(name
, &end
, 0);
1513 if (!end
|| end
== name
|| *end
|| n
> UINT_MAX
)
1519 res
= malloc(sizeof(*res
));
1525 void *parse_hostcond(char *addr
, bool is_port
)
1528 struct aafilter a
= { .port
= -1 };
1529 struct aafilter
*res
;
1530 int fam
= preferred_family
;
1531 struct filter
*f
= ¤t_filter
;
1533 if (fam
== AF_UNIX
|| strncmp(addr
, "unix:", 5) == 0) {
1536 a
.addr
.family
= AF_UNIX
;
1537 if (strncmp(addr
, "unix:", 5) == 0)
1540 a
.addr
.bitlen
= 8*strlen(p
);
1541 memcpy(a
.addr
.data
, &p
, sizeof(p
));
1546 if (fam
== AF_PACKET
|| strncmp(addr
, "link:", 5) == 0) {
1547 a
.addr
.family
= AF_PACKET
;
1549 if (strncmp(addr
, "link:", 5) == 0)
1551 port
= strchr(addr
, ':');
1554 if (port
[1] && strcmp(port
+1, "*")) {
1555 if (get_integer(&a
.port
, port
+1, 0)) {
1556 if ((a
.port
= xll_name_to_index(port
+1)) <= 0)
1561 if (addr
[0] && strcmp(addr
, "*")) {
1565 if (ll_proto_a2n(&tmp
, addr
))
1567 a
.addr
.data
[0] = ntohs(tmp
);
1573 if (fam
== AF_NETLINK
|| strncmp(addr
, "netlink:", 8) == 0) {
1574 a
.addr
.family
= AF_NETLINK
;
1576 if (strncmp(addr
, "netlink:", 8) == 0)
1578 port
= strchr(addr
, ':');
1581 if (port
[1] && strcmp(port
+1, "*")) {
1582 if (get_integer(&a
.port
, port
+1, 0)) {
1583 if (strcmp(port
+1, "kernel") == 0)
1590 if (addr
[0] && strcmp(addr
, "*")) {
1592 if (nl_proto_a2n(&a
.addr
.data
[0], addr
) == -1)
1599 if (fam
== AF_INET
|| !strncmp(addr
, "inet:", 5)) {
1601 if (!strncmp(addr
, "inet:", 5))
1603 } else if (fam
== AF_INET6
|| !strncmp(addr
, "inet6:", 6)) {
1605 if (!strncmp(addr
, "inet6:", 6))
1609 /* URL-like literal [] */
1610 if (addr
[0] == '[') {
1612 if ((port
= strchr(addr
, ']')) == NULL
)
1615 } else if (addr
[0] == '*') {
1618 port
= strrchr(strchr(addr
, '/') ? : addr
, ':');
1624 if (port
&& *port
) {
1628 if (*port
&& *port
!= '*') {
1629 if (get_integer(&a
.port
, port
, 0)) {
1630 struct servent
*se1
= NULL
;
1631 struct servent
*se2
= NULL
;
1633 if (current_filter
.dbs
&(1<<UDP_DB
))
1634 se1
= getservbyname(port
, UDP_PROTO
);
1635 if (current_filter
.dbs
&(1<<TCP_DB
))
1636 se2
= getservbyname(port
, TCP_PROTO
);
1637 if (se1
&& se2
&& se1
->s_port
!= se2
->s_port
) {
1638 fprintf(stderr
, "Error: ambiguous port \"%s\".\n", port
);
1644 a
.port
= ntohs(se1
->s_port
);
1648 for (s
= rlist
; s
; s
= s
->next
) {
1649 if ((s
->proto
== UDP_PROTO
&&
1650 (current_filter
.dbs
&(1<<UDP_DB
))) ||
1651 (s
->proto
== TCP_PROTO
&&
1652 (current_filter
.dbs
&(1<<TCP_DB
)))) {
1653 if (s
->name
&& strcmp(s
->name
, port
) == 0) {
1654 if (a
.port
> 0 && a
.port
!= s
->port
) {
1655 fprintf(stderr
, "Error: ambiguous port \"%s\".\n", port
);
1663 fprintf(stderr
, "Error: \"%s\" does not look like a port.\n", port
);
1670 if (!is_port
&& *addr
&& *addr
!= '*') {
1671 if (get_prefix_1(&a
.addr
, addr
, fam
)) {
1672 if (get_dns_host(&a
, addr
, fam
)) {
1673 fprintf(stderr
, "Error: an inet prefix is expected rather than \"%s\".\n", addr
);
1680 if (fam
!= AF_UNSPEC
) {
1681 int states
= f
->states
;
1683 filter_af_set(f
, fam
);
1684 filter_states_set(f
, states
);
1687 res
= malloc(sizeof(*res
));
1689 memcpy(res
, &a
, sizeof(a
));
1693 void *parse_markmask(const char *markmask
)
1695 struct aafilter a
, *res
;
1697 if (strchr(markmask
, '/')) {
1698 if (sscanf(markmask
, "%i/%i", &a
.mark
, &a
.mask
) != 2)
1701 a
.mask
= 0xffffffff;
1702 if (sscanf(markmask
, "%i", &a
.mark
) != 1)
1706 res
= malloc(sizeof(*res
));
1708 memcpy(res
, &a
, sizeof(a
));
1712 static void proc_ctx_print(struct sockstat
*s
)
1716 if (show_proc_ctx
|| show_sock_ctx
) {
1717 if (find_entry(s
->ino
, &buf
,
1718 (show_proc_ctx
& show_sock_ctx
) ?
1719 PROC_SOCK_CTX
: PROC_CTX
) > 0) {
1720 printf(" users:(%s)", buf
);
1723 } else if (show_users
) {
1724 if (find_entry(s
->ino
, &buf
, USERS
) > 0) {
1725 printf(" users:(%s)", buf
);
1731 static void inet_stats_print(struct sockstat
*s
, bool v6only
)
1733 sock_state_print(s
);
1735 inet_addr_print(&s
->local
, s
->lport
, s
->iface
, v6only
);
1736 inet_addr_print(&s
->remote
, s
->rport
, 0, v6only
);
1741 static int proc_parse_inet_addr(char *loc
, char *rem
, int family
, struct
1744 s
->local
.family
= s
->remote
.family
= family
;
1745 if (family
== AF_INET
) {
1746 sscanf(loc
, "%x:%x", s
->local
.data
, (unsigned *)&s
->lport
);
1747 sscanf(rem
, "%x:%x", s
->remote
.data
, (unsigned *)&s
->rport
);
1748 s
->local
.bytelen
= s
->remote
.bytelen
= 4;
1751 sscanf(loc
, "%08x%08x%08x%08x:%x",
1757 sscanf(rem
, "%08x%08x%08x%08x:%x",
1763 s
->local
.bytelen
= s
->remote
.bytelen
= 16;
1769 static int proc_inet_split_line(char *line
, char **loc
, char **rem
, char **data
)
1773 if ((p
= strchr(line
, ':')) == NULL
)
1777 if ((p
= strchr(*loc
, ':')) == NULL
)
1782 if ((p
= strchr(*rem
, ':')) == NULL
)
1790 static char *sprint_bw(char *buf
, double bw
)
1793 sprintf(buf
, "%.1fM", bw
/ 1000000.);
1794 else if (bw
> 1000.)
1795 sprintf(buf
, "%.1fK", bw
/ 1000.);
1797 sprintf(buf
, "%g", bw
);
1802 static void sctp_stats_print(struct sctp_info
*s
)
1805 printf(" tag:%x", s
->sctpi_tag
);
1807 printf(" state:%s", sctp_sstate_name
[s
->sctpi_state
]);
1809 printf(" rwnd:%d", s
->sctpi_rwnd
);
1810 if (s
->sctpi_unackdata
)
1811 printf(" unackdata:%d", s
->sctpi_unackdata
);
1812 if (s
->sctpi_penddata
)
1813 printf(" penddata:%d", s
->sctpi_penddata
);
1814 if (s
->sctpi_instrms
)
1815 printf(" instrms:%d", s
->sctpi_instrms
);
1816 if (s
->sctpi_outstrms
)
1817 printf(" outstrms:%d", s
->sctpi_outstrms
);
1818 if (s
->sctpi_inqueue
)
1819 printf(" inqueue:%d", s
->sctpi_inqueue
);
1820 if (s
->sctpi_outqueue
)
1821 printf(" outqueue:%d", s
->sctpi_outqueue
);
1822 if (s
->sctpi_overall_error
)
1823 printf(" overerr:%d", s
->sctpi_overall_error
);
1824 if (s
->sctpi_max_burst
)
1825 printf(" maxburst:%d", s
->sctpi_max_burst
);
1826 if (s
->sctpi_maxseg
)
1827 printf(" maxseg:%d", s
->sctpi_maxseg
);
1828 if (s
->sctpi_peer_rwnd
)
1829 printf(" prwnd:%d", s
->sctpi_peer_rwnd
);
1830 if (s
->sctpi_peer_tag
)
1831 printf(" ptag:%x", s
->sctpi_peer_tag
);
1832 if (s
->sctpi_peer_capable
)
1833 printf(" pcapable:%d", s
->sctpi_peer_capable
);
1834 if (s
->sctpi_peer_sack
)
1835 printf(" psack:%d", s
->sctpi_peer_sack
);
1836 if (s
->sctpi_s_autoclose
)
1837 printf(" autoclose:%d", s
->sctpi_s_autoclose
);
1838 if (s
->sctpi_s_adaptation_ind
)
1839 printf(" adapind:%d", s
->sctpi_s_adaptation_ind
);
1840 if (s
->sctpi_s_pd_point
)
1841 printf(" pdpoint:%d", s
->sctpi_s_pd_point
);
1842 if (s
->sctpi_s_nodelay
)
1843 printf(" nodealy:%d", s
->sctpi_s_nodelay
);
1844 if (s
->sctpi_s_disable_fragments
)
1845 printf(" nofrag:%d", s
->sctpi_s_disable_fragments
);
1846 if (s
->sctpi_s_v4mapped
)
1847 printf(" v4mapped:%d", s
->sctpi_s_v4mapped
);
1848 if (s
->sctpi_s_frag_interleave
)
1849 printf(" fraginl:%d", s
->sctpi_s_frag_interleave
);
1852 static void tcp_stats_print(struct tcpstat
*s
)
1858 if (s
->has_sack_opt
)
1862 if (s
->has_ecnseen_opt
)
1864 if (s
->has_fastopen_opt
)
1865 printf(" fastopen");
1867 printf(" %s", s
->cong_alg
);
1868 if (s
->has_wscale_opt
)
1869 printf(" wscale:%d,%d", s
->snd_wscale
, s
->rcv_wscale
);
1871 printf(" rto:%g", s
->rto
);
1873 printf(" backoff:%u", s
->backoff
);
1875 printf(" rtt:%g/%g", s
->rtt
, s
->rttvar
);
1877 printf(" ato:%g", s
->ato
);
1880 printf(" qack:%d", s
->qack
);
1885 printf(" mss:%d", s
->mss
);
1887 printf(" rcvmss:%d", s
->rcv_mss
);
1889 printf(" advmss:%d", s
->advmss
);
1891 printf(" cwnd:%u", s
->cwnd
);
1893 printf(" ssthresh:%d", s
->ssthresh
);
1896 printf(" bytes_acked:%llu", s
->bytes_acked
);
1897 if (s
->bytes_received
)
1898 printf(" bytes_received:%llu", s
->bytes_received
);
1900 printf(" segs_out:%u", s
->segs_out
);
1902 printf(" segs_in:%u", s
->segs_in
);
1903 if (s
->data_segs_out
)
1904 printf(" data_segs_out:%u", s
->data_segs_out
);
1905 if (s
->data_segs_in
)
1906 printf(" data_segs_in:%u", s
->data_segs_in
);
1908 if (s
->dctcp
&& s
->dctcp
->enabled
) {
1909 struct dctcpstat
*dctcp
= s
->dctcp
;
1911 printf(" dctcp:(ce_state:%u,alpha:%u,ab_ecn:%u,ab_tot:%u)",
1912 dctcp
->ce_state
, dctcp
->alpha
, dctcp
->ab_ecn
,
1914 } else if (s
->dctcp
) {
1915 printf(" dctcp:fallback_mode");
1921 bw
= s
->bbr_info
->bbr_bw_hi
;
1923 bw
|= s
->bbr_info
->bbr_bw_lo
;
1925 printf(" bbr:(bw:%sbps,mrtt:%g",
1926 sprint_bw(b1
, bw
* 8.0),
1927 (double)s
->bbr_info
->bbr_min_rtt
/ 1000.0);
1928 if (s
->bbr_info
->bbr_pacing_gain
)
1929 printf(",pacing_gain:%g",
1930 (double)s
->bbr_info
->bbr_pacing_gain
/ 256.0);
1931 if (s
->bbr_info
->bbr_cwnd_gain
)
1932 printf(",cwnd_gain:%g",
1933 (double)s
->bbr_info
->bbr_cwnd_gain
/ 256.0);
1938 printf(" send %sbps", sprint_bw(b1
, s
->send_bps
));
1940 printf(" lastsnd:%u", s
->lastsnd
);
1942 printf(" lastrcv:%u", s
->lastrcv
);
1944 printf(" lastack:%u", s
->lastack
);
1946 if (s
->pacing_rate
) {
1947 printf(" pacing_rate %sbps", sprint_bw(b1
, s
->pacing_rate
));
1948 if (s
->pacing_rate_max
)
1949 printf("/%sbps", sprint_bw(b1
,
1950 s
->pacing_rate_max
));
1953 if (s
->delivery_rate
)
1954 printf(" delivery_rate %sbps", sprint_bw(b1
, s
->delivery_rate
));
1956 printf(" app_limited");
1959 printf(" busy:%llums", s
->busy_time
/ 1000);
1960 if (s
->rwnd_limited
)
1961 printf(" rwnd_limited:%llums(%.1f%%)",
1962 s
->rwnd_limited
/ 1000,
1963 100.0 * s
->rwnd_limited
/ s
->busy_time
);
1964 if (s
->sndbuf_limited
)
1965 printf(" sndbuf_limited:%llums(%.1f%%)",
1966 s
->sndbuf_limited
/ 1000,
1967 100.0 * s
->sndbuf_limited
/ s
->busy_time
);
1971 printf(" unacked:%u", s
->unacked
);
1972 if (s
->retrans
|| s
->retrans_total
)
1973 printf(" retrans:%u/%u", s
->retrans
, s
->retrans_total
);
1975 printf(" lost:%u", s
->lost
);
1976 if (s
->sacked
&& s
->ss
.state
!= SS_LISTEN
)
1977 printf(" sacked:%u", s
->sacked
);
1979 printf(" fackets:%u", s
->fackets
);
1980 if (s
->reordering
!= 3)
1981 printf(" reordering:%d", s
->reordering
);
1983 printf(" rcv_rtt:%g", s
->rcv_rtt
);
1985 printf(" rcv_space:%d", s
->rcv_space
);
1987 printf(" notsent:%u", s
->not_sent
);
1989 printf(" minrtt:%g", s
->min_rtt
);
1992 static void tcp_timer_print(struct tcpstat
*s
)
1994 static const char * const tmr_name
[] = {
2006 printf(" timer:(%s,%s,%d)",
2008 print_ms_timer(s
->timeout
),
2013 static void sctp_timer_print(struct tcpstat
*s
)
2016 printf(" timer:(T3_RTX,%s,%d)",
2017 print_ms_timer(s
->timeout
), s
->retrans
);
2020 static int tcp_show_line(char *line
, const struct filter
*f
, int family
)
2022 int rto
= 0, ato
= 0;
2023 struct tcpstat s
= {};
2024 char *loc
, *rem
, *data
;
2027 int hz
= get_user_hz();
2029 if (proc_inet_split_line(line
, &loc
, &rem
, &data
))
2032 int state
= (data
[1] >= 'A') ? (data
[1] - 'A' + 10) : (data
[1] - '0');
2034 if (!(f
->states
& (1 << state
)))
2037 proc_parse_inet_addr(loc
, rem
, family
, &s
.ss
);
2039 if (f
->f
&& run_ssfilter(f
->f
, &s
.ss
) == 0)
2043 n
= sscanf(data
, "%x %x:%x %x:%x %x %d %d %u %d %llx %d %d %d %u %d %[^\n]\n",
2044 &s
.ss
.state
, &s
.ss
.wq
, &s
.ss
.rq
,
2045 &s
.timer
, &s
.timeout
, &s
.retrans
, &s
.ss
.uid
, &s
.probes
,
2046 &s
.ss
.ino
, &s
.ss
.refcnt
, &s
.ss
.sk
, &rto
, &ato
, &s
.qack
, &s
.cwnd
,
2059 s
.retrans
= s
.timer
!= 1 ? s
.probes
: s
.retrans
;
2060 s
.timeout
= (s
.timeout
* 1000 + hz
- 1) / hz
;
2061 s
.ato
= (double)ato
/ hz
;
2063 s
.rto
= (double)rto
;
2064 s
.ssthresh
= s
.ssthresh
== -1 ? 0 : s
.ssthresh
;
2065 s
.rto
= s
.rto
!= 3 * hz
? s
.rto
/ hz
: 0;
2066 s
.ss
.type
= IPPROTO_TCP
;
2068 inet_stats_print(&s
.ss
, false);
2071 tcp_timer_print(&s
);
2074 sock_details_print(&s
.ss
);
2076 printf(" opt:\"%s\"", opt
);
2080 tcp_stats_print(&s
);
2086 static int generic_record_read(FILE *fp
,
2087 int (*worker
)(char*, const struct filter
*, int),
2088 const struct filter
*f
, int fam
)
2093 if (fgets(line
, sizeof(line
), fp
) == NULL
)
2096 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
2097 int n
= strlen(line
);
2099 if (n
== 0 || line
[n
-1] != '\n') {
2105 if (worker(line
, f
, fam
) < 0)
2110 return ferror(fp
) ? -1 : 0;
2113 static void print_skmeminfo(struct rtattr
*tb
[], int attrtype
)
2115 const __u32
*skmeminfo
;
2117 if (!tb
[attrtype
]) {
2118 if (attrtype
== INET_DIAG_SKMEMINFO
) {
2119 if (!tb
[INET_DIAG_MEMINFO
])
2122 const struct inet_diag_meminfo
*minfo
=
2123 RTA_DATA(tb
[INET_DIAG_MEMINFO
]);
2125 printf(" mem:(r%u,w%u,f%u,t%u)",
2134 skmeminfo
= RTA_DATA(tb
[attrtype
]);
2136 printf(" skmem:(r%u,rb%u,t%u,tb%u,f%u,w%u,o%u",
2137 skmeminfo
[SK_MEMINFO_RMEM_ALLOC
],
2138 skmeminfo
[SK_MEMINFO_RCVBUF
],
2139 skmeminfo
[SK_MEMINFO_WMEM_ALLOC
],
2140 skmeminfo
[SK_MEMINFO_SNDBUF
],
2141 skmeminfo
[SK_MEMINFO_FWD_ALLOC
],
2142 skmeminfo
[SK_MEMINFO_WMEM_QUEUED
],
2143 skmeminfo
[SK_MEMINFO_OPTMEM
]);
2145 if (RTA_PAYLOAD(tb
[attrtype
]) >=
2146 (SK_MEMINFO_BACKLOG
+ 1) * sizeof(__u32
))
2147 printf(",bl%u", skmeminfo
[SK_MEMINFO_BACKLOG
]);
2149 if (RTA_PAYLOAD(tb
[attrtype
]) >=
2150 (SK_MEMINFO_DROPS
+ 1) * sizeof(__u32
))
2151 printf(",d%u", skmeminfo
[SK_MEMINFO_DROPS
]);
2156 static void print_md5sig(struct tcp_diag_md5sig
*sig
)
2159 format_host(sig
->tcpm_family
,
2160 sig
->tcpm_family
== AF_INET6
? 16 : 4,
2162 sig
->tcpm_prefixlen
);
2163 print_escape_buf(sig
->tcpm_key
, sig
->tcpm_keylen
, " ,");
2166 #define TCPI_HAS_OPT(info, opt) !!(info->tcpi_options & (opt))
2168 static void tcp_show_info(const struct nlmsghdr
*nlh
, struct inet_diag_msg
*r
,
2169 struct rtattr
*tb
[])
2172 struct tcpstat s
= {};
2174 s
.ss
.state
= r
->idiag_state
;
2176 print_skmeminfo(tb
, INET_DIAG_SKMEMINFO
);
2178 if (tb
[INET_DIAG_INFO
]) {
2179 struct tcp_info
*info
;
2180 int len
= RTA_PAYLOAD(tb
[INET_DIAG_INFO
]);
2182 /* workaround for older kernels with less fields */
2183 if (len
< sizeof(*info
)) {
2184 info
= alloca(sizeof(*info
));
2185 memcpy(info
, RTA_DATA(tb
[INET_DIAG_INFO
]), len
);
2186 memset((char *)info
+ len
, 0, sizeof(*info
) - len
);
2188 info
= RTA_DATA(tb
[INET_DIAG_INFO
]);
2191 s
.has_ts_opt
= TCPI_HAS_OPT(info
, TCPI_OPT_TIMESTAMPS
);
2192 s
.has_sack_opt
= TCPI_HAS_OPT(info
, TCPI_OPT_SACK
);
2193 s
.has_ecn_opt
= TCPI_HAS_OPT(info
, TCPI_OPT_ECN
);
2194 s
.has_ecnseen_opt
= TCPI_HAS_OPT(info
, TCPI_OPT_ECN_SEEN
);
2195 s
.has_fastopen_opt
= TCPI_HAS_OPT(info
, TCPI_OPT_SYN_DATA
);
2198 if (tb
[INET_DIAG_CONG
])
2200 rta_getattr_str(tb
[INET_DIAG_CONG
]),
2201 sizeof(s
.cong_alg
) - 1);
2203 if (TCPI_HAS_OPT(info
, TCPI_OPT_WSCALE
)) {
2204 s
.has_wscale_opt
= true;
2205 s
.snd_wscale
= info
->tcpi_snd_wscale
;
2206 s
.rcv_wscale
= info
->tcpi_rcv_wscale
;
2209 if (info
->tcpi_rto
&& info
->tcpi_rto
!= 3000000)
2210 s
.rto
= (double)info
->tcpi_rto
/ 1000;
2212 s
.backoff
= info
->tcpi_backoff
;
2213 s
.rtt
= (double)info
->tcpi_rtt
/ 1000;
2214 s
.rttvar
= (double)info
->tcpi_rttvar
/ 1000;
2215 s
.ato
= (double)info
->tcpi_ato
/ 1000;
2216 s
.mss
= info
->tcpi_snd_mss
;
2217 s
.rcv_mss
= info
->tcpi_rcv_mss
;
2218 s
.advmss
= info
->tcpi_advmss
;
2219 s
.rcv_space
= info
->tcpi_rcv_space
;
2220 s
.rcv_rtt
= (double)info
->tcpi_rcv_rtt
/ 1000;
2221 s
.lastsnd
= info
->tcpi_last_data_sent
;
2222 s
.lastrcv
= info
->tcpi_last_data_recv
;
2223 s
.lastack
= info
->tcpi_last_ack_recv
;
2224 s
.unacked
= info
->tcpi_unacked
;
2225 s
.retrans
= info
->tcpi_retrans
;
2226 s
.retrans_total
= info
->tcpi_total_retrans
;
2227 s
.lost
= info
->tcpi_lost
;
2228 s
.sacked
= info
->tcpi_sacked
;
2229 s
.fackets
= info
->tcpi_fackets
;
2230 s
.reordering
= info
->tcpi_reordering
;
2231 s
.rcv_space
= info
->tcpi_rcv_space
;
2232 s
.cwnd
= info
->tcpi_snd_cwnd
;
2234 if (info
->tcpi_snd_ssthresh
< 0xFFFF)
2235 s
.ssthresh
= info
->tcpi_snd_ssthresh
;
2237 rtt
= (double) info
->tcpi_rtt
;
2238 if (tb
[INET_DIAG_VEGASINFO
]) {
2239 const struct tcpvegas_info
*vinfo
2240 = RTA_DATA(tb
[INET_DIAG_VEGASINFO
]);
2242 if (vinfo
->tcpv_enabled
&&
2243 vinfo
->tcpv_rtt
&& vinfo
->tcpv_rtt
!= 0x7fffffff)
2244 rtt
= vinfo
->tcpv_rtt
;
2247 if (tb
[INET_DIAG_DCTCPINFO
]) {
2248 struct dctcpstat
*dctcp
= malloc(sizeof(struct
2251 const struct tcp_dctcp_info
*dinfo
2252 = RTA_DATA(tb
[INET_DIAG_DCTCPINFO
]);
2254 dctcp
->enabled
= !!dinfo
->dctcp_enabled
;
2255 dctcp
->ce_state
= dinfo
->dctcp_ce_state
;
2256 dctcp
->alpha
= dinfo
->dctcp_alpha
;
2257 dctcp
->ab_ecn
= dinfo
->dctcp_ab_ecn
;
2258 dctcp
->ab_tot
= dinfo
->dctcp_ab_tot
;
2262 if (tb
[INET_DIAG_BBRINFO
]) {
2263 const void *bbr_info
= RTA_DATA(tb
[INET_DIAG_BBRINFO
]);
2264 int len
= min(RTA_PAYLOAD(tb
[INET_DIAG_BBRINFO
]),
2265 sizeof(*s
.bbr_info
));
2267 s
.bbr_info
= calloc(1, sizeof(*s
.bbr_info
));
2268 if (s
.bbr_info
&& bbr_info
)
2269 memcpy(s
.bbr_info
, bbr_info
, len
);
2272 if (rtt
> 0 && info
->tcpi_snd_mss
&& info
->tcpi_snd_cwnd
) {
2273 s
.send_bps
= (double) info
->tcpi_snd_cwnd
*
2274 (double)info
->tcpi_snd_mss
* 8000000. / rtt
;
2277 if (info
->tcpi_pacing_rate
&&
2278 info
->tcpi_pacing_rate
!= ~0ULL) {
2279 s
.pacing_rate
= info
->tcpi_pacing_rate
* 8.;
2281 if (info
->tcpi_max_pacing_rate
&&
2282 info
->tcpi_max_pacing_rate
!= ~0ULL)
2283 s
.pacing_rate_max
= info
->tcpi_max_pacing_rate
* 8.;
2285 s
.bytes_acked
= info
->tcpi_bytes_acked
;
2286 s
.bytes_received
= info
->tcpi_bytes_received
;
2287 s
.segs_out
= info
->tcpi_segs_out
;
2288 s
.segs_in
= info
->tcpi_segs_in
;
2289 s
.data_segs_out
= info
->tcpi_data_segs_out
;
2290 s
.data_segs_in
= info
->tcpi_data_segs_in
;
2291 s
.not_sent
= info
->tcpi_notsent_bytes
;
2292 if (info
->tcpi_min_rtt
&& info
->tcpi_min_rtt
!= ~0U)
2293 s
.min_rtt
= (double) info
->tcpi_min_rtt
/ 1000;
2294 s
.delivery_rate
= info
->tcpi_delivery_rate
* 8.;
2295 s
.app_limited
= info
->tcpi_delivery_rate_app_limited
;
2296 s
.busy_time
= info
->tcpi_busy_time
;
2297 s
.rwnd_limited
= info
->tcpi_rwnd_limited
;
2298 s
.sndbuf_limited
= info
->tcpi_sndbuf_limited
;
2299 tcp_stats_print(&s
);
2303 if (tb
[INET_DIAG_MD5SIG
]) {
2304 struct tcp_diag_md5sig
*sig
= RTA_DATA(tb
[INET_DIAG_MD5SIG
]);
2305 int len
= RTA_PAYLOAD(tb
[INET_DIAG_MD5SIG
]);
2307 printf(" md5keys:");
2308 print_md5sig(sig
++);
2309 for (len
-= sizeof(*sig
); len
> 0; len
-= sizeof(*sig
)) {
2311 print_md5sig(sig
++);
2316 static const char *format_host_sa(struct sockaddr_storage
*sa
)
2319 struct sockaddr_in sin
;
2320 struct sockaddr_in6 sin6
;
2321 } *saddr
= (void *)sa
;
2323 switch (sa
->ss_family
) {
2325 return format_host(AF_INET
, 4, &saddr
->sin
.sin_addr
);
2327 return format_host(AF_INET6
, 16, &saddr
->sin6
.sin6_addr
);
2333 static void sctp_show_info(const struct nlmsghdr
*nlh
, struct inet_diag_msg
*r
,
2334 struct rtattr
*tb
[])
2336 struct sockaddr_storage
*sa
;
2339 print_skmeminfo(tb
, INET_DIAG_SKMEMINFO
);
2341 if (tb
[INET_DIAG_LOCALS
]) {
2342 len
= RTA_PAYLOAD(tb
[INET_DIAG_LOCALS
]);
2343 sa
= RTA_DATA(tb
[INET_DIAG_LOCALS
]);
2345 printf("locals:%s", format_host_sa(sa
));
2346 for (sa
++, len
-= sizeof(*sa
); len
> 0; sa
++, len
-= sizeof(*sa
))
2347 printf(",%s", format_host_sa(sa
));
2350 if (tb
[INET_DIAG_PEERS
]) {
2351 len
= RTA_PAYLOAD(tb
[INET_DIAG_PEERS
]);
2352 sa
= RTA_DATA(tb
[INET_DIAG_PEERS
]);
2354 printf(" peers:%s", format_host_sa(sa
));
2355 for (sa
++, len
-= sizeof(*sa
); len
> 0; sa
++, len
-= sizeof(*sa
))
2356 printf(",%s", format_host_sa(sa
));
2358 if (tb
[INET_DIAG_INFO
]) {
2359 struct sctp_info
*info
;
2360 len
= RTA_PAYLOAD(tb
[INET_DIAG_INFO
]);
2362 /* workaround for older kernels with less fields */
2363 if (len
< sizeof(*info
)) {
2364 info
= alloca(sizeof(*info
));
2365 memcpy(info
, RTA_DATA(tb
[INET_DIAG_INFO
]), len
);
2366 memset((char *)info
+ len
, 0, sizeof(*info
) - len
);
2368 info
= RTA_DATA(tb
[INET_DIAG_INFO
]);
2370 sctp_stats_print(info
);
2374 static void parse_diag_msg(struct nlmsghdr
*nlh
, struct sockstat
*s
)
2376 struct rtattr
*tb
[INET_DIAG_MAX
+1];
2377 struct inet_diag_msg
*r
= NLMSG_DATA(nlh
);
2379 parse_rtattr(tb
, INET_DIAG_MAX
, (struct rtattr
*)(r
+1),
2380 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
2382 s
->state
= r
->idiag_state
;
2383 s
->local
.family
= s
->remote
.family
= r
->idiag_family
;
2384 s
->lport
= ntohs(r
->id
.idiag_sport
);
2385 s
->rport
= ntohs(r
->id
.idiag_dport
);
2386 s
->wq
= r
->idiag_wqueue
;
2387 s
->rq
= r
->idiag_rqueue
;
2388 s
->ino
= r
->idiag_inode
;
2389 s
->uid
= r
->idiag_uid
;
2390 s
->iface
= r
->id
.idiag_if
;
2391 s
->sk
= cookie_sk_get(&r
->id
.idiag_cookie
[0]);
2394 if (tb
[INET_DIAG_MARK
])
2395 s
->mark
= rta_getattr_u32(tb
[INET_DIAG_MARK
]);
2396 if (tb
[INET_DIAG_PROTOCOL
])
2397 s
->raw_prot
= rta_getattr_u8(tb
[INET_DIAG_PROTOCOL
]);
2401 if (s
->local
.family
== AF_INET
)
2402 s
->local
.bytelen
= s
->remote
.bytelen
= 4;
2404 s
->local
.bytelen
= s
->remote
.bytelen
= 16;
2406 memcpy(s
->local
.data
, r
->id
.idiag_src
, s
->local
.bytelen
);
2407 memcpy(s
->remote
.data
, r
->id
.idiag_dst
, s
->local
.bytelen
);
2410 static int inet_show_sock(struct nlmsghdr
*nlh
,
2413 struct rtattr
*tb
[INET_DIAG_MAX
+1];
2414 struct inet_diag_msg
*r
= NLMSG_DATA(nlh
);
2415 unsigned char v6only
= 0;
2417 parse_rtattr(tb
, INET_DIAG_MAX
, (struct rtattr
*)(r
+1),
2418 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
2420 if (tb
[INET_DIAG_PROTOCOL
])
2421 s
->type
= rta_getattr_u8(tb
[INET_DIAG_PROTOCOL
]);
2423 if (s
->local
.family
== AF_INET6
&& tb
[INET_DIAG_SKV6ONLY
])
2424 v6only
= rta_getattr_u8(tb
[INET_DIAG_SKV6ONLY
]);
2426 inet_stats_print(s
, v6only
);
2429 struct tcpstat t
= {};
2431 t
.timer
= r
->idiag_timer
;
2432 t
.timeout
= r
->idiag_expires
;
2433 t
.retrans
= r
->idiag_retrans
;
2434 if (s
->type
== IPPROTO_SCTP
)
2435 sctp_timer_print(&t
);
2437 tcp_timer_print(&t
);
2441 sock_details_print(s
);
2442 if (s
->local
.family
== AF_INET6
&& tb
[INET_DIAG_SKV6ONLY
])
2443 printf(" v6only:%u", v6only
);
2445 if (tb
[INET_DIAG_SHUTDOWN
]) {
2448 mask
= rta_getattr_u8(tb
[INET_DIAG_SHUTDOWN
]);
2449 printf(" %c-%c", mask
& 1 ? '-' : '<', mask
& 2 ? '-' : '>');
2453 if (show_mem
|| (show_tcpinfo
&& s
->type
!= IPPROTO_UDP
)) {
2455 if (s
->type
== IPPROTO_SCTP
)
2456 sctp_show_info(nlh
, r
, tb
);
2458 tcp_show_info(nlh
, r
, tb
);
2466 static int tcpdiag_send(int fd
, int protocol
, struct filter
*f
)
2468 struct sockaddr_nl nladdr
= { .nl_family
= AF_NETLINK
};
2470 struct nlmsghdr nlh
;
2471 struct inet_diag_req r
;
2473 .nlh
.nlmsg_len
= sizeof(req
),
2474 .nlh
.nlmsg_flags
= NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
,
2475 .nlh
.nlmsg_seq
= MAGIC_SEQ
,
2476 .r
.idiag_family
= AF_INET
,
2477 .r
.idiag_states
= f
->states
,
2483 struct iovec iov
[3];
2486 if (protocol
== IPPROTO_UDP
)
2489 if (protocol
== IPPROTO_TCP
)
2490 req
.nlh
.nlmsg_type
= TCPDIAG_GETSOCK
;
2492 req
.nlh
.nlmsg_type
= DCCPDIAG_GETSOCK
;
2494 req
.r
.idiag_ext
|= (1<<(INET_DIAG_MEMINFO
-1));
2495 req
.r
.idiag_ext
|= (1<<(INET_DIAG_SKMEMINFO
-1));
2499 req
.r
.idiag_ext
|= (1<<(INET_DIAG_INFO
-1));
2500 req
.r
.idiag_ext
|= (1<<(INET_DIAG_VEGASINFO
-1));
2501 req
.r
.idiag_ext
|= (1<<(INET_DIAG_CONG
-1));
2504 iov
[0] = (struct iovec
){
2506 .iov_len
= sizeof(req
)
2509 bclen
= ssfilter_bytecompile(f
->f
, &bc
);
2511 rta
.rta_type
= INET_DIAG_REQ_BYTECODE
;
2512 rta
.rta_len
= RTA_LENGTH(bclen
);
2513 iov
[1] = (struct iovec
){ &rta
, sizeof(rta
) };
2514 iov
[2] = (struct iovec
){ bc
, bclen
};
2515 req
.nlh
.nlmsg_len
+= RTA_LENGTH(bclen
);
2520 msg
= (struct msghdr
) {
2521 .msg_name
= (void *)&nladdr
,
2522 .msg_namelen
= sizeof(nladdr
),
2524 .msg_iovlen
= iovlen
,
2527 if (sendmsg(fd
, &msg
, 0) < 0) {
2535 static int sockdiag_send(int family
, int fd
, int protocol
, struct filter
*f
)
2537 struct sockaddr_nl nladdr
= { .nl_family
= AF_NETLINK
};
2538 DIAG_REQUEST(req
, struct inet_diag_req_v2 r
);
2543 struct iovec iov
[3];
2546 if (family
== PF_UNSPEC
)
2547 return tcpdiag_send(fd
, protocol
, f
);
2549 memset(&req
.r
, 0, sizeof(req
.r
));
2550 req
.r
.sdiag_family
= family
;
2551 req
.r
.sdiag_protocol
= protocol
;
2552 req
.r
.idiag_states
= f
->states
;
2554 req
.r
.idiag_ext
|= (1<<(INET_DIAG_MEMINFO
-1));
2555 req
.r
.idiag_ext
|= (1<<(INET_DIAG_SKMEMINFO
-1));
2559 req
.r
.idiag_ext
|= (1<<(INET_DIAG_INFO
-1));
2560 req
.r
.idiag_ext
|= (1<<(INET_DIAG_VEGASINFO
-1));
2561 req
.r
.idiag_ext
|= (1<<(INET_DIAG_CONG
-1));
2564 iov
[0] = (struct iovec
){
2566 .iov_len
= sizeof(req
)
2569 bclen
= ssfilter_bytecompile(f
->f
, &bc
);
2571 rta
.rta_type
= INET_DIAG_REQ_BYTECODE
;
2572 rta
.rta_len
= RTA_LENGTH(bclen
);
2573 iov
[1] = (struct iovec
){ &rta
, sizeof(rta
) };
2574 iov
[2] = (struct iovec
){ bc
, bclen
};
2575 req
.nlh
.nlmsg_len
+= RTA_LENGTH(bclen
);
2580 msg
= (struct msghdr
) {
2581 .msg_name
= (void *)&nladdr
,
2582 .msg_namelen
= sizeof(nladdr
),
2584 .msg_iovlen
= iovlen
,
2587 if (sendmsg(fd
, &msg
, 0) < 0) {
2595 struct inet_diag_arg
{
2598 struct rtnl_handle
*rth
;
2601 static int kill_inet_sock(struct nlmsghdr
*h
, void *arg
, struct sockstat
*s
)
2603 struct inet_diag_msg
*d
= NLMSG_DATA(h
);
2604 struct inet_diag_arg
*diag_arg
= arg
;
2605 struct rtnl_handle
*rth
= diag_arg
->rth
;
2607 DIAG_REQUEST(req
, struct inet_diag_req_v2 r
);
2609 req
.nlh
.nlmsg_type
= SOCK_DESTROY
;
2610 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
2611 req
.nlh
.nlmsg_seq
= ++rth
->seq
;
2612 req
.r
.sdiag_family
= d
->idiag_family
;
2613 req
.r
.sdiag_protocol
= diag_arg
->protocol
;
2616 if (diag_arg
->protocol
== IPPROTO_RAW
) {
2617 struct inet_diag_req_raw
*raw
= (void *)&req
.r
;
2619 BUILD_BUG_ON(sizeof(req
.r
) != sizeof(*raw
));
2620 raw
->sdiag_raw_protocol
= s
->raw_prot
;
2623 return rtnl_talk(rth
, &req
.nlh
, NULL
, 0);
2626 static int show_one_inet_sock(const struct sockaddr_nl
*addr
,
2627 struct nlmsghdr
*h
, void *arg
)
2630 struct inet_diag_arg
*diag_arg
= arg
;
2631 struct inet_diag_msg
*r
= NLMSG_DATA(h
);
2632 struct sockstat s
= {};
2634 if (!(diag_arg
->f
->families
& (1 << r
->idiag_family
)))
2637 parse_diag_msg(h
, &s
);
2638 s
.type
= diag_arg
->protocol
;
2640 if (diag_arg
->f
->f
&& run_ssfilter(diag_arg
->f
->f
, &s
) == 0)
2643 if (diag_arg
->f
->kill
&& kill_inet_sock(h
, arg
, &s
) != 0) {
2644 if (errno
== EOPNOTSUPP
|| errno
== ENOENT
) {
2645 /* Socket can't be closed, or is already closed. */
2648 perror("SOCK_DESTROY answers");
2653 err
= inet_show_sock(h
, &s
);
2660 static int inet_show_netlink(struct filter
*f
, FILE *dump_fp
, int protocol
)
2663 struct rtnl_handle rth
, rth2
;
2664 int family
= PF_INET
;
2665 struct inet_diag_arg arg
= { .f
= f
, .protocol
= protocol
};
2667 if (rtnl_open_byproto(&rth
, 0, NETLINK_SOCK_DIAG
))
2671 if (rtnl_open_byproto(&rth2
, 0, NETLINK_SOCK_DIAG
)) {
2678 rth
.dump
= MAGIC_SEQ
;
2679 rth
.dump_fp
= dump_fp
;
2680 if (preferred_family
== PF_INET6
)
2684 if ((err
= sockdiag_send(family
, rth
.fd
, protocol
, f
)))
2687 if ((err
= rtnl_dump_filter(&rth
, show_one_inet_sock
, &arg
))) {
2688 if (family
!= PF_UNSPEC
) {
2694 if (family
== PF_INET
&& preferred_family
!= PF_INET
) {
2702 rtnl_close(arg
.rth
);
2706 static int tcp_show_netlink_file(struct filter
*f
)
2712 if ((fp
= fopen(getenv("TCPDIAG_FILE"), "r")) == NULL
) {
2713 perror("fopen($TCPDIAG_FILE)");
2719 struct nlmsghdr
*h
= (struct nlmsghdr
*)buf
;
2720 struct sockstat s
= {};
2722 status
= fread(buf
, 1, sizeof(*h
), fp
);
2724 perror("Reading header from $TCPDIAG_FILE");
2727 if (status
!= sizeof(*h
)) {
2728 perror("Unexpected EOF reading $TCPDIAG_FILE");
2732 status
= fread(h
+1, 1, NLMSG_ALIGN(h
->nlmsg_len
-sizeof(*h
)), fp
);
2735 perror("Reading $TCPDIAG_FILE");
2738 if (status
+ sizeof(*h
) < h
->nlmsg_len
) {
2739 perror("Unexpected EOF reading $TCPDIAG_FILE");
2743 /* The only legal exit point */
2744 if (h
->nlmsg_type
== NLMSG_DONE
) {
2749 if (h
->nlmsg_type
== NLMSG_ERROR
) {
2750 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(h
);
2752 if (h
->nlmsg_len
< NLMSG_LENGTH(sizeof(struct nlmsgerr
))) {
2753 fprintf(stderr
, "ERROR truncated\n");
2755 errno
= -err
->error
;
2756 perror("TCPDIAG answered");
2761 parse_diag_msg(h
, &s
);
2762 s
.type
= IPPROTO_TCP
;
2764 if (f
&& f
->f
&& run_ssfilter(f
->f
, &s
) == 0)
2767 err2
= inet_show_sock(h
, &s
);
2778 static int tcp_show(struct filter
*f
)
2782 int bufsize
= 64*1024;
2784 if (!filter_af_get(f
, AF_INET
) && !filter_af_get(f
, AF_INET6
))
2787 dg_proto
= TCP_PROTO
;
2789 if (getenv("TCPDIAG_FILE"))
2790 return tcp_show_netlink_file(f
);
2792 if (!getenv("PROC_NET_TCP") && !getenv("PROC_ROOT")
2793 && inet_show_netlink(f
, NULL
, IPPROTO_TCP
) == 0)
2796 /* Sigh... We have to parse /proc/net/tcp... */
2799 /* Estimate amount of sockets and try to allocate
2800 * huge buffer to read all the table at one read.
2801 * Limit it by 16MB though. The assumption is: as soon as
2802 * kernel was able to hold information about N connections,
2803 * it is able to give us some memory for snapshot.
2806 get_slabstat(&slabstat
);
2808 int guess
= slabstat
.socks
+slabstat
.tcp_syns
;
2810 if (f
->states
&(1<<SS_TIME_WAIT
))
2811 guess
+= slabstat
.tcp_tws
;
2812 if (guess
> (16*1024*1024)/128)
2813 guess
= (16*1024*1024)/128;
2815 if (guess
> bufsize
)
2818 while (bufsize
>= 64*1024) {
2819 if ((buf
= malloc(bufsize
)) != NULL
)
2828 if (f
->families
& (1<<AF_INET
)) {
2829 if ((fp
= net_tcp_open()) == NULL
)
2832 setbuffer(fp
, buf
, bufsize
);
2833 if (generic_record_read(fp
, tcp_show_line
, f
, AF_INET
))
2838 if ((f
->families
& (1<<AF_INET6
)) &&
2839 (fp
= net_tcp6_open()) != NULL
) {
2840 setbuffer(fp
, buf
, bufsize
);
2841 if (generic_record_read(fp
, tcp_show_line
, f
, AF_INET6
))
2851 int saved_errno
= errno
;
2856 errno
= saved_errno
;
2861 static int dccp_show(struct filter
*f
)
2863 if (!filter_af_get(f
, AF_INET
) && !filter_af_get(f
, AF_INET6
))
2866 if (!getenv("PROC_NET_DCCP") && !getenv("PROC_ROOT")
2867 && inet_show_netlink(f
, NULL
, IPPROTO_DCCP
) == 0)
2873 static int sctp_show(struct filter
*f
)
2875 if (!filter_af_get(f
, AF_INET
) && !filter_af_get(f
, AF_INET6
))
2878 if (!getenv("PROC_NET_SCTP") && !getenv("PROC_ROOT")
2879 && inet_show_netlink(f
, NULL
, IPPROTO_SCTP
) == 0)
2885 static int dgram_show_line(char *line
, const struct filter
*f
, int family
)
2887 struct sockstat s
= {};
2888 char *loc
, *rem
, *data
;
2892 if (proc_inet_split_line(line
, &loc
, &rem
, &data
))
2895 int state
= (data
[1] >= 'A') ? (data
[1] - 'A' + 10) : (data
[1] - '0');
2897 if (!(f
->states
& (1 << state
)))
2900 proc_parse_inet_addr(loc
, rem
, family
, &s
);
2902 if (f
->f
&& run_ssfilter(f
->f
, &s
) == 0)
2906 n
= sscanf(data
, "%x %x:%x %*x:%*x %*x %d %*d %u %d %llx %[^\n]\n",
2907 &s
.state
, &s
.wq
, &s
.rq
,
2909 &s
.refcnt
, &s
.sk
, opt
);
2914 s
.type
= dg_proto
== UDP_PROTO
? IPPROTO_UDP
: 0;
2915 inet_stats_print(&s
, false);
2917 if (show_details
&& opt
[0])
2918 printf(" opt:\"%s\"", opt
);
2924 static int udp_show(struct filter
*f
)
2928 if (!filter_af_get(f
, AF_INET
) && !filter_af_get(f
, AF_INET6
))
2931 dg_proto
= UDP_PROTO
;
2933 if (!getenv("PROC_NET_UDP") && !getenv("PROC_ROOT")
2934 && inet_show_netlink(f
, NULL
, IPPROTO_UDP
) == 0)
2937 if (f
->families
&(1<<AF_INET
)) {
2938 if ((fp
= net_udp_open()) == NULL
)
2940 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET
))
2945 if ((f
->families
&(1<<AF_INET6
)) &&
2946 (fp
= net_udp6_open()) != NULL
) {
2947 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET6
))
2955 int saved_errno
= errno
;
2959 errno
= saved_errno
;
2964 static int raw_show(struct filter
*f
)
2968 if (!filter_af_get(f
, AF_INET
) && !filter_af_get(f
, AF_INET6
))
2971 dg_proto
= RAW_PROTO
;
2973 if (!getenv("PROC_NET_RAW") && !getenv("PROC_ROOT") &&
2974 inet_show_netlink(f
, NULL
, IPPROTO_RAW
) == 0)
2977 if (f
->families
&(1<<AF_INET
)) {
2978 if ((fp
= net_raw_open()) == NULL
)
2980 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET
))
2985 if ((f
->families
&(1<<AF_INET6
)) &&
2986 (fp
= net_raw6_open()) != NULL
) {
2987 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET6
))
2995 int saved_errno
= errno
;
2999 errno
= saved_errno
;
3004 #define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct sockstat))
3006 static void unix_list_drop_first(struct sockstat
**list
)
3008 struct sockstat
*s
= *list
;
3010 (*list
) = (*list
)->next
;
3015 static bool unix_type_skip(struct sockstat
*s
, struct filter
*f
)
3017 if (s
->type
== SOCK_STREAM
&& !(f
->dbs
&(1<<UNIX_ST_DB
)))
3019 if (s
->type
== SOCK_DGRAM
&& !(f
->dbs
&(1<<UNIX_DG_DB
)))
3021 if (s
->type
== SOCK_SEQPACKET
&& !(f
->dbs
&(1<<UNIX_SQ_DB
)))
3026 static void unix_stats_print(struct sockstat
*s
, struct filter
*f
)
3028 char port_name
[30] = {};
3030 sock_state_print(s
);
3032 sock_addr_print(s
->name
?: "*", " ",
3033 int_to_str(s
->lport
, port_name
), NULL
);
3034 sock_addr_print(s
->peer_name
?: "*", " ",
3035 int_to_str(s
->rport
, port_name
), NULL
);
3040 static int unix_show_sock(const struct sockaddr_nl
*addr
, struct nlmsghdr
*nlh
,
3043 struct filter
*f
= (struct filter
*)arg
;
3044 struct unix_diag_msg
*r
= NLMSG_DATA(nlh
);
3045 struct rtattr
*tb
[UNIX_DIAG_MAX
+1];
3047 struct sockstat stat
= { .name
= "*", .peer_name
= "*" };
3049 parse_rtattr(tb
, UNIX_DIAG_MAX
, (struct rtattr
*)(r
+1),
3050 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
3052 stat
.type
= r
->udiag_type
;
3053 stat
.state
= r
->udiag_state
;
3054 stat
.ino
= stat
.lport
= r
->udiag_ino
;
3055 stat
.local
.family
= stat
.remote
.family
= AF_UNIX
;
3057 if (unix_type_skip(&stat
, f
))
3060 if (tb
[UNIX_DIAG_RQLEN
]) {
3061 struct unix_diag_rqlen
*rql
= RTA_DATA(tb
[UNIX_DIAG_RQLEN
]);
3063 stat
.rq
= rql
->udiag_rqueue
;
3064 stat
.wq
= rql
->udiag_wqueue
;
3066 if (tb
[UNIX_DIAG_NAME
]) {
3067 int len
= RTA_PAYLOAD(tb
[UNIX_DIAG_NAME
]);
3069 memcpy(name
, RTA_DATA(tb
[UNIX_DIAG_NAME
]), len
);
3071 if (name
[0] == '\0') {
3073 for (i
= 0; i
< len
; i
++)
3074 if (name
[i
] == '\0')
3077 stat
.name
= &name
[0];
3078 memcpy(stat
.local
.data
, &stat
.name
, sizeof(stat
.name
));
3080 if (tb
[UNIX_DIAG_PEER
])
3081 stat
.rport
= rta_getattr_u32(tb
[UNIX_DIAG_PEER
]);
3083 if (f
->f
&& run_ssfilter(f
->f
, &stat
) == 0)
3086 unix_stats_print(&stat
, f
);
3089 print_skmeminfo(tb
, UNIX_DIAG_MEMINFO
);
3091 if (tb
[UNIX_DIAG_SHUTDOWN
]) {
3094 mask
= rta_getattr_u8(tb
[UNIX_DIAG_SHUTDOWN
]);
3095 printf(" %c-%c", mask
& 1 ? '-' : '<', mask
& 2 ? '-' : '>');
3103 static int handle_netlink_request(struct filter
*f
, struct nlmsghdr
*req
,
3104 size_t size
, rtnl_filter_t show_one_sock
)
3107 struct rtnl_handle rth
;
3109 if (rtnl_open_byproto(&rth
, 0, NETLINK_SOCK_DIAG
))
3112 rth
.dump
= MAGIC_SEQ
;
3114 if (rtnl_send(&rth
, req
, size
) < 0)
3117 if (rtnl_dump_filter(&rth
, show_one_sock
, f
))
3126 static int unix_show_netlink(struct filter
*f
)
3128 DIAG_REQUEST(req
, struct unix_diag_req r
);
3130 req
.r
.sdiag_family
= AF_UNIX
;
3131 req
.r
.udiag_states
= f
->states
;
3132 req
.r
.udiag_show
= UDIAG_SHOW_NAME
| UDIAG_SHOW_PEER
| UDIAG_SHOW_RQLEN
;
3134 req
.r
.udiag_show
|= UDIAG_SHOW_MEMINFO
;
3136 return handle_netlink_request(f
, &req
.nlh
, sizeof(req
), unix_show_sock
);
3139 static int unix_show(struct filter
*f
)
3146 struct sockstat
*list
= NULL
;
3147 const int unix_state_map
[] = { SS_CLOSE
, SS_SYN_SENT
,
3148 SS_ESTABLISHED
, SS_CLOSING
};
3150 if (!filter_af_get(f
, AF_UNIX
))
3153 if (!getenv("PROC_NET_UNIX") && !getenv("PROC_ROOT")
3154 && unix_show_netlink(f
) == 0)
3157 if ((fp
= net_unix_open()) == NULL
)
3159 if (!fgets(buf
, sizeof(buf
), fp
)) {
3164 if (memcmp(buf
, "Peer", 4) == 0)
3168 while (fgets(buf
, sizeof(buf
), fp
)) {
3169 struct sockstat
*u
, **insp
;
3172 if (!(u
= calloc(1, sizeof(*u
))))
3175 if (sscanf(buf
, "%x: %x %x %x %x %x %d %s",
3176 &u
->rport
, &u
->rq
, &u
->wq
, &flags
, &u
->type
,
3177 &u
->state
, &u
->ino
, name
) < 8)
3181 u
->local
.family
= u
->remote
.family
= AF_UNIX
;
3183 if (flags
& (1 << 16)) {
3184 u
->state
= SS_LISTEN
;
3185 } else if (u
->state
> 0 &&
3186 u
->state
<= ARRAY_SIZE(unix_state_map
)) {
3187 u
->state
= unix_state_map
[u
->state
-1];
3188 if (u
->type
== SOCK_DGRAM
&& u
->state
== SS_CLOSE
&& u
->rport
)
3189 u
->state
= SS_ESTABLISHED
;
3191 if (unix_type_skip(u
, f
) ||
3192 !(f
->states
& (1 << u
->state
))) {
3204 u
->name
= strdup(name
);
3214 for (p
= list
; p
; p
= p
->next
) {
3215 if (u
->rport
== p
->lport
)
3221 u
->peer_name
= p
->name
? : "*";
3225 struct sockstat st
= {
3226 .local
.family
= AF_UNIX
,
3227 .remote
.family
= AF_UNIX
,
3230 memcpy(st
.local
.data
, &u
->name
, sizeof(u
->name
));
3231 if (strcmp(u
->peer_name
, "*"))
3232 memcpy(st
.remote
.data
, &u
->peer_name
,
3233 sizeof(u
->peer_name
));
3234 if (run_ssfilter(f
->f
, &st
) == 0) {
3243 if (u
->type
< (*insp
)->type
||
3244 (u
->type
== (*insp
)->type
&&
3245 u
->ino
< (*insp
)->ino
))
3247 insp
= &(*insp
)->next
;
3252 if (++cnt
> MAX_UNIX_REMEMBER
) {
3254 unix_stats_print(list
, f
);
3257 unix_list_drop_first(&list
);
3264 unix_stats_print(list
, f
);
3267 unix_list_drop_first(&list
);
3273 static int packet_stats_print(struct sockstat
*s
, const struct filter
*f
)
3275 const char *addr
, *port
;
3278 s
->local
.family
= s
->remote
.family
= AF_PACKET
;
3281 s
->local
.data
[0] = s
->prot
;
3282 if (run_ssfilter(f
->f
, s
) == 0)
3286 sock_state_print(s
);
3291 addr
= ll_proto_n2a(htons(s
->prot
), ll_name
, sizeof(ll_name
));
3296 port
= xll_index_to_name(s
->iface
);
3298 sock_addr_print(addr
, ":", port
, NULL
);
3299 sock_addr_print("", "*", "", NULL
);
3304 sock_details_print(s
);
3309 static void packet_show_ring(struct packet_diag_ring
*ring
)
3311 printf("blk_size:%d", ring
->pdr_block_size
);
3312 printf(",blk_nr:%d", ring
->pdr_block_nr
);
3313 printf(",frm_size:%d", ring
->pdr_frame_size
);
3314 printf(",frm_nr:%d", ring
->pdr_frame_nr
);
3315 printf(",tmo:%d", ring
->pdr_retire_tmo
);
3316 printf(",features:0x%x", ring
->pdr_features
);
3319 static int packet_show_sock(const struct sockaddr_nl
*addr
,
3320 struct nlmsghdr
*nlh
, void *arg
)
3322 const struct filter
*f
= arg
;
3323 struct packet_diag_msg
*r
= NLMSG_DATA(nlh
);
3324 struct packet_diag_info
*pinfo
= NULL
;
3325 struct packet_diag_ring
*ring_rx
= NULL
, *ring_tx
= NULL
;
3326 struct rtattr
*tb
[PACKET_DIAG_MAX
+1];
3327 struct sockstat stat
= {};
3328 uint32_t fanout
= 0;
3329 bool has_fanout
= false;
3331 parse_rtattr(tb
, PACKET_DIAG_MAX
, (struct rtattr
*)(r
+1),
3332 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
3334 /* use /proc/net/packet if all info are not available */
3335 if (!tb
[PACKET_DIAG_MEMINFO
])
3338 stat
.type
= r
->pdiag_type
;
3339 stat
.prot
= r
->pdiag_num
;
3340 stat
.ino
= r
->pdiag_ino
;
3341 stat
.state
= SS_CLOSE
;
3342 stat
.sk
= cookie_sk_get(&r
->pdiag_cookie
[0]);
3344 if (tb
[PACKET_DIAG_MEMINFO
]) {
3345 __u32
*skmeminfo
= RTA_DATA(tb
[PACKET_DIAG_MEMINFO
]);
3347 stat
.rq
= skmeminfo
[SK_MEMINFO_RMEM_ALLOC
];
3350 if (tb
[PACKET_DIAG_INFO
]) {
3351 pinfo
= RTA_DATA(tb
[PACKET_DIAG_INFO
]);
3352 stat
.lport
= stat
.iface
= pinfo
->pdi_index
;
3355 if (tb
[PACKET_DIAG_UID
])
3356 stat
.uid
= rta_getattr_u32(tb
[PACKET_DIAG_UID
]);
3358 if (tb
[PACKET_DIAG_RX_RING
])
3359 ring_rx
= RTA_DATA(tb
[PACKET_DIAG_RX_RING
]);
3361 if (tb
[PACKET_DIAG_TX_RING
])
3362 ring_tx
= RTA_DATA(tb
[PACKET_DIAG_TX_RING
]);
3364 if (tb
[PACKET_DIAG_FANOUT
]) {
3366 fanout
= rta_getattr_u32(tb
[PACKET_DIAG_FANOUT
]);
3369 if (packet_stats_print(&stat
, f
))
3374 printf("\n\tver:%d", pinfo
->pdi_version
);
3375 printf(" cpy_thresh:%d", pinfo
->pdi_copy_thresh
);
3377 if (pinfo
->pdi_flags
& PDI_RUNNING
)
3379 if (pinfo
->pdi_flags
& PDI_AUXDATA
)
3381 if (pinfo
->pdi_flags
& PDI_ORIGDEV
)
3383 if (pinfo
->pdi_flags
& PDI_VNETHDR
)
3385 if (pinfo
->pdi_flags
& PDI_LOSS
)
3387 if (!pinfo
->pdi_flags
)
3392 printf("\n\tring_rx(");
3393 packet_show_ring(ring_rx
);
3397 printf("\n\tring_tx(");
3398 packet_show_ring(ring_tx
);
3402 uint16_t type
= (fanout
>> 16) & 0xffff;
3404 printf("\n\tfanout(");
3405 printf("id:%d,", fanout
& 0xffff);
3421 printf("0x%x", type
);
3427 if (show_bpf
&& tb
[PACKET_DIAG_FILTER
]) {
3428 struct sock_filter
*fil
=
3429 RTA_DATA(tb
[PACKET_DIAG_FILTER
]);
3430 int num
= RTA_PAYLOAD(tb
[PACKET_DIAG_FILTER
]) /
3431 sizeof(struct sock_filter
);
3433 printf("\n\tbpf filter (%d): ", num
);
3435 printf(" 0x%02x %u %u %u,",
3436 fil
->code
, fil
->jt
, fil
->jf
, fil
->k
);
3445 static int packet_show_netlink(struct filter
*f
)
3447 DIAG_REQUEST(req
, struct packet_diag_req r
);
3449 req
.r
.sdiag_family
= AF_PACKET
;
3450 req
.r
.pdiag_show
= PACKET_SHOW_INFO
| PACKET_SHOW_MEMINFO
|
3451 PACKET_SHOW_FILTER
| PACKET_SHOW_RING_CFG
| PACKET_SHOW_FANOUT
;
3453 return handle_netlink_request(f
, &req
.nlh
, sizeof(req
), packet_show_sock
);
3456 static int packet_show_line(char *buf
, const struct filter
*f
, int fam
)
3458 unsigned long long sk
;
3459 struct sockstat stat
= {};
3460 int type
, prot
, iface
, state
, rq
, uid
, ino
;
3462 sscanf(buf
, "%llx %*d %d %x %d %d %u %u %u",
3464 &type
, &prot
, &iface
, &state
,
3467 if (stat
.type
== SOCK_RAW
&& !(f
->dbs
&(1<<PACKET_R_DB
)))
3469 if (stat
.type
== SOCK_DGRAM
&& !(f
->dbs
&(1<<PACKET_DG_DB
)))
3474 stat
.lport
= stat
.iface
= iface
;
3479 stat
.state
= SS_CLOSE
;
3481 if (packet_stats_print(&stat
, f
))
3488 static int packet_show(struct filter
*f
)
3493 if (!filter_af_get(f
, AF_PACKET
) || !(f
->states
& (1 << SS_CLOSE
)))
3496 if (!getenv("PROC_NET_PACKET") && !getenv("PROC_ROOT") &&
3497 packet_show_netlink(f
) == 0)
3500 if ((fp
= net_packet_open()) == NULL
)
3502 if (generic_record_read(fp
, packet_show_line
, f
, AF_PACKET
))
3509 static int netlink_show_one(struct filter
*f
,
3510 int prot
, int pid
, unsigned int groups
,
3511 int state
, int dst_pid
, unsigned int dst_group
,
3513 unsigned long long sk
, unsigned long long cb
)
3515 struct sockstat st
= {
3519 .local
.family
= AF_NETLINK
,
3520 .remote
.family
= AF_NETLINK
,
3523 SPRINT_BUF(prot_buf
) = {};
3524 const char *prot_name
;
3525 char procname
[64] = {};
3530 st
.local
.data
[0] = prot
;
3531 if (run_ssfilter(f
->f
, &st
) == 0)
3535 sock_state_print(&st
);
3537 if (resolve_services
)
3538 prot_name
= nl_proto_n2a(prot
, prot_buf
, sizeof(prot_buf
));
3540 prot_name
= int_to_str(prot
, prot_buf
);
3544 } else if (resolve_services
) {
3549 strncpy(procname
, "kernel", 6);
3550 } else if (pid
> 0) {
3553 snprintf(procname
, sizeof(procname
), "%s/%d/stat",
3554 getenv("PROC_ROOT") ? : "/proc", pid
);
3555 if ((fp
= fopen(procname
, "r")) != NULL
) {
3556 if (fscanf(fp
, "%*d (%[^)])", procname
) == 1) {
3557 snprintf(procname
+strlen(procname
),
3558 sizeof(procname
)-strlen(procname
),
3566 int_to_str(pid
, procname
);
3568 int_to_str(pid
, procname
);
3571 sock_addr_print(prot_name
, ":", procname
, NULL
);
3573 if (state
== NETLINK_CONNECTED
) {
3574 char dst_group_buf
[30];
3575 char dst_pid_buf
[30];
3577 sock_addr_print(int_to_str(dst_group
, dst_group_buf
), ":",
3578 int_to_str(dst_pid
, dst_pid_buf
), NULL
);
3580 sock_addr_print("", "*", "", NULL
);
3583 char *pid_context
= NULL
;
3585 if (show_proc_ctx
) {
3586 /* The pid value will either be:
3587 * 0 if destination kernel - show kernel initial context.
3588 * A valid process pid - use getpidcon.
3589 * A unique value allocated by the kernel or netlink user
3590 * to the process - show context as "not available".
3593 security_get_initial_context("kernel", &pid_context
);
3595 getpidcon(pid
, &pid_context
);
3597 printf(" proc_ctx=%s", pid_context
? : "unavailable");
3602 printf(" sk=%llx cb=%llx groups=0x%08x", sk
, cb
, groups
);
3609 static int netlink_show_sock(const struct sockaddr_nl
*addr
,
3610 struct nlmsghdr
*nlh
, void *arg
)
3612 struct filter
*f
= (struct filter
*)arg
;
3613 struct netlink_diag_msg
*r
= NLMSG_DATA(nlh
);
3614 struct rtattr
*tb
[NETLINK_DIAG_MAX
+1];
3616 unsigned long groups
= 0;
3618 parse_rtattr(tb
, NETLINK_DIAG_MAX
, (struct rtattr
*)(r
+1),
3619 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
3621 if (tb
[NETLINK_DIAG_GROUPS
] && RTA_PAYLOAD(tb
[NETLINK_DIAG_GROUPS
]))
3622 groups
= *(unsigned long *) RTA_DATA(tb
[NETLINK_DIAG_GROUPS
]);
3624 if (tb
[NETLINK_DIAG_MEMINFO
]) {
3625 const __u32
*skmeminfo
;
3627 skmeminfo
= RTA_DATA(tb
[NETLINK_DIAG_MEMINFO
]);
3629 rq
= skmeminfo
[SK_MEMINFO_RMEM_ALLOC
];
3630 wq
= skmeminfo
[SK_MEMINFO_WMEM_ALLOC
];
3633 if (netlink_show_one(f
, r
->ndiag_protocol
, r
->ndiag_portid
, groups
,
3634 r
->ndiag_state
, r
->ndiag_dst_portid
, r
->ndiag_dst_group
,
3641 print_skmeminfo(tb
, NETLINK_DIAG_MEMINFO
);
3648 static int netlink_show_netlink(struct filter
*f
)
3650 DIAG_REQUEST(req
, struct netlink_diag_req r
);
3652 req
.r
.sdiag_family
= AF_NETLINK
;
3653 req
.r
.sdiag_protocol
= NDIAG_PROTO_ALL
;
3654 req
.r
.ndiag_show
= NDIAG_SHOW_GROUPS
| NDIAG_SHOW_MEMINFO
;
3656 return handle_netlink_request(f
, &req
.nlh
, sizeof(req
), netlink_show_sock
);
3659 static int netlink_show(struct filter
*f
)
3664 unsigned int groups
;
3666 unsigned long long sk
, cb
;
3668 if (!filter_af_get(f
, AF_NETLINK
) || !(f
->states
& (1 << SS_CLOSE
)))
3671 if (!getenv("PROC_NET_NETLINK") && !getenv("PROC_ROOT") &&
3672 netlink_show_netlink(f
) == 0)
3675 if ((fp
= net_netlink_open()) == NULL
)
3677 if (!fgets(buf
, sizeof(buf
), fp
)) {
3682 while (fgets(buf
, sizeof(buf
), fp
)) {
3683 sscanf(buf
, "%llx %d %d %x %d %d %llx %d",
3685 &prot
, &pid
, &groups
, &rq
, &wq
, &cb
, &rc
);
3687 netlink_show_one(f
, prot
, pid
, groups
, 0, 0, 0, rq
, wq
, sk
, cb
);
3694 struct sock_diag_msg
{
3698 static int generic_show_sock(const struct sockaddr_nl
*addr
,
3699 struct nlmsghdr
*nlh
, void *arg
)
3701 struct sock_diag_msg
*r
= NLMSG_DATA(nlh
);
3702 struct inet_diag_arg inet_arg
= { .f
= arg
, .protocol
= IPPROTO_MAX
};
3704 switch (r
->sdiag_family
) {
3707 return show_one_inet_sock(addr
, nlh
, &inet_arg
);
3709 return unix_show_sock(addr
, nlh
, arg
);
3711 return packet_show_sock(addr
, nlh
, arg
);
3713 return netlink_show_sock(addr
, nlh
, arg
);
3719 static int handle_follow_request(struct filter
*f
)
3723 struct rtnl_handle rth
;
3725 if (f
->families
& (1 << AF_INET
) && f
->dbs
& (1 << TCP_DB
))
3726 groups
|= 1 << (SKNLGRP_INET_TCP_DESTROY
- 1);
3727 if (f
->families
& (1 << AF_INET
) && f
->dbs
& (1 << UDP_DB
))
3728 groups
|= 1 << (SKNLGRP_INET_UDP_DESTROY
- 1);
3729 if (f
->families
& (1 << AF_INET6
) && f
->dbs
& (1 << TCP_DB
))
3730 groups
|= 1 << (SKNLGRP_INET6_TCP_DESTROY
- 1);
3731 if (f
->families
& (1 << AF_INET6
) && f
->dbs
& (1 << UDP_DB
))
3732 groups
|= 1 << (SKNLGRP_INET6_UDP_DESTROY
- 1);
3737 if (rtnl_open_byproto(&rth
, groups
, NETLINK_SOCK_DIAG
))
3741 rth
.local
.nl_pid
= 0;
3743 if (rtnl_dump_filter(&rth
, generic_show_sock
, f
))
3750 static int get_snmp_int(char *proto
, char *key
, int *result
)
3754 int protolen
= strlen(proto
);
3755 int keylen
= strlen(key
);
3759 if ((fp
= net_snmp_open()) == NULL
)
3762 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
3766 if (memcmp(buf
, proto
, protolen
))
3768 while ((p
= strchr(p
, ' ')) != NULL
) {
3771 if (memcmp(p
, key
, keylen
) == 0 &&
3772 (p
[keylen
] == ' ' || p
[keylen
] == '\n'))
3775 if (fgets(buf
, sizeof(buf
), fp
) == NULL
)
3777 if (memcmp(buf
, proto
, protolen
))
3780 while ((p
= strchr(p
, ' ')) != NULL
) {
3783 sscanf(p
, "%d", result
);
3796 /* Get stats from sockstat */
3816 static void get_sockstat_line(char *line
, struct ssummary
*s
)
3818 char id
[256], rem
[256];
3820 if (sscanf(line
, "%[^ ] %[^\n]\n", id
, rem
) != 2)
3823 if (strcmp(id
, "sockets:") == 0)
3824 sscanf(rem
, "%*s%d", &s
->socks
);
3825 else if (strcmp(id
, "UDP:") == 0)
3826 sscanf(rem
, "%*s%d", &s
->udp4
);
3827 else if (strcmp(id
, "UDP6:") == 0)
3828 sscanf(rem
, "%*s%d", &s
->udp6
);
3829 else if (strcmp(id
, "RAW:") == 0)
3830 sscanf(rem
, "%*s%d", &s
->raw4
);
3831 else if (strcmp(id
, "RAW6:") == 0)
3832 sscanf(rem
, "%*s%d", &s
->raw6
);
3833 else if (strcmp(id
, "TCP6:") == 0)
3834 sscanf(rem
, "%*s%d", &s
->tcp6_hashed
);
3835 else if (strcmp(id
, "FRAG:") == 0)
3836 sscanf(rem
, "%*s%d%*s%d", &s
->frag4
, &s
->frag4_mem
);
3837 else if (strcmp(id
, "FRAG6:") == 0)
3838 sscanf(rem
, "%*s%d%*s%d", &s
->frag6
, &s
->frag6_mem
);
3839 else if (strcmp(id
, "TCP:") == 0)
3840 sscanf(rem
, "%*s%d%*s%d%*s%d%*s%d%*s%d",
3842 &s
->tcp_orphans
, &s
->tcp_tws
, &s
->tcp_total
, &s
->tcp_mem
);
3845 static int get_sockstat(struct ssummary
*s
)
3850 memset(s
, 0, sizeof(*s
));
3852 if ((fp
= net_sockstat_open()) == NULL
)
3854 while (fgets(buf
, sizeof(buf
), fp
) != NULL
)
3855 get_sockstat_line(buf
, s
);
3858 if ((fp
= net_sockstat6_open()) == NULL
)
3860 while (fgets(buf
, sizeof(buf
), fp
) != NULL
)
3861 get_sockstat_line(buf
, s
);
3867 static int print_summary(void)
3872 if (get_sockstat(&s
) < 0)
3873 perror("ss: get_sockstat");
3874 if (get_snmp_int("Tcp:", "CurrEstab", &tcp_estab
) < 0)
3875 perror("ss: get_snmpstat");
3877 get_slabstat(&slabstat
);
3879 printf("Total: %d (kernel %d)\n", s
.socks
, slabstat
.socks
);
3881 printf("TCP: %d (estab %d, closed %d, orphaned %d, synrecv %d, timewait %d/%d), ports %d\n",
3882 s
.tcp_total
+ slabstat
.tcp_syns
+ s
.tcp_tws
,
3884 s
.tcp_total
- (s
.tcp4_hashed
+s
.tcp6_hashed
-s
.tcp_tws
),
3887 s
.tcp_tws
, slabstat
.tcp_tws
,
3892 printf("Transport Total IP IPv6\n");
3893 printf("* %-9d %-9s %-9s\n", slabstat
.socks
, "-", "-");
3894 printf("RAW %-9d %-9d %-9d\n", s
.raw4
+s
.raw6
, s
.raw4
, s
.raw6
);
3895 printf("UDP %-9d %-9d %-9d\n", s
.udp4
+s
.udp6
, s
.udp4
, s
.udp6
);
3896 printf("TCP %-9d %-9d %-9d\n", s
.tcp4_hashed
+s
.tcp6_hashed
, s
.tcp4_hashed
, s
.tcp6_hashed
);
3897 printf("INET %-9d %-9d %-9d\n",
3898 s
.raw4
+s
.udp4
+s
.tcp4_hashed
+
3899 s
.raw6
+s
.udp6
+s
.tcp6_hashed
,
3900 s
.raw4
+s
.udp4
+s
.tcp4_hashed
,
3901 s
.raw6
+s
.udp6
+s
.tcp6_hashed
);
3902 printf("FRAG %-9d %-9d %-9d\n", s
.frag4
+s
.frag6
, s
.frag4
, s
.frag6
);
3909 static void _usage(FILE *dest
)
3912 "Usage: ss [ OPTIONS ]\n"
3913 " ss [ OPTIONS ] [ FILTER ]\n"
3914 " -h, --help this message\n"
3915 " -V, --version output version information\n"
3916 " -n, --numeric don't resolve service names\n"
3917 " -r, --resolve resolve host names\n"
3918 " -a, --all display all sockets\n"
3919 " -l, --listening display listening sockets\n"
3920 " -o, --options show timer information\n"
3921 " -e, --extended show detailed socket information\n"
3922 " -m, --memory show socket memory usage\n"
3923 " -p, --processes show process using socket\n"
3924 " -i, --info show internal TCP information\n"
3925 " -s, --summary show socket usage summary\n"
3926 " -b, --bpf show bpf filter socket information\n"
3927 " -E, --events continually display sockets as they are destroyed\n"
3928 " -Z, --context display process SELinux security contexts\n"
3929 " -z, --contexts display process and socket SELinux security contexts\n"
3930 " -N, --net switch to the specified network namespace name\n"
3932 " -4, --ipv4 display only IP version 4 sockets\n"
3933 " -6, --ipv6 display only IP version 6 sockets\n"
3934 " -0, --packet display PACKET sockets\n"
3935 " -t, --tcp display only TCP sockets\n"
3936 " -S, --sctp display only SCTP sockets\n"
3937 " -u, --udp display only UDP sockets\n"
3938 " -d, --dccp display only DCCP sockets\n"
3939 " -w, --raw display only RAW sockets\n"
3940 " -x, --unix display only Unix domain sockets\n"
3941 " -f, --family=FAMILY display sockets of type FAMILY\n"
3942 " FAMILY := {inet|inet6|link|unix|netlink|help}\n"
3944 " -K, --kill forcibly close sockets, display what was closed\n"
3945 " -H, --no-header Suppress header line\n"
3947 " -A, --query=QUERY, --socket=QUERY\n"
3948 " QUERY := {all|inet|tcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink}[,QUERY]\n"
3950 " -D, --diag=FILE Dump raw information about TCP sockets to FILE\n"
3951 " -F, --filter=FILE read filter information from FILE\n"
3952 " FILTER := [ state STATE-FILTER ] [ EXPRESSION ]\n"
3953 " STATE-FILTER := {all|connected|synchronized|bucket|big|TCP-STATES}\n"
3954 " TCP-STATES := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|closed|close-wait|last-ack|listening|closing}\n"
3955 " connected := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}\n"
3956 " synchronized := {established|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}\n"
3957 " bucket := {syn-recv|time-wait}\n"
3958 " big := {established|syn-sent|fin-wait-{1,2}|closed|close-wait|last-ack|listening|closing}\n"
3962 static void help(void) __attribute__((noreturn
));
3963 static void help(void)
3969 static void usage(void) __attribute__((noreturn
));
3970 static void usage(void)
3977 static int scan_state(const char *state
)
3979 static const char * const sstate_namel
[] = {
3981 [SS_ESTABLISHED
] = "established",
3982 [SS_SYN_SENT
] = "syn-sent",
3983 [SS_SYN_RECV
] = "syn-recv",
3984 [SS_FIN_WAIT1
] = "fin-wait-1",
3985 [SS_FIN_WAIT2
] = "fin-wait-2",
3986 [SS_TIME_WAIT
] = "time-wait",
3987 [SS_CLOSE
] = "unconnected",
3988 [SS_CLOSE_WAIT
] = "close-wait",
3989 [SS_LAST_ACK
] = "last-ack",
3990 [SS_LISTEN
] = "listening",
3991 [SS_CLOSING
] = "closing",
3995 if (strcasecmp(state
, "close") == 0 ||
3996 strcasecmp(state
, "closed") == 0)
3997 return (1<<SS_CLOSE
);
3998 if (strcasecmp(state
, "syn-rcv") == 0)
3999 return (1<<SS_SYN_RECV
);
4000 if (strcasecmp(state
, "established") == 0)
4001 return (1<<SS_ESTABLISHED
);
4002 if (strcasecmp(state
, "all") == 0)
4004 if (strcasecmp(state
, "connected") == 0)
4005 return SS_ALL
& ~((1<<SS_CLOSE
)|(1<<SS_LISTEN
));
4006 if (strcasecmp(state
, "synchronized") == 0)
4007 return SS_ALL
& ~((1<<SS_CLOSE
)|(1<<SS_LISTEN
)|(1<<SS_SYN_SENT
));
4008 if (strcasecmp(state
, "bucket") == 0)
4009 return (1<<SS_SYN_RECV
)|(1<<SS_TIME_WAIT
);
4010 if (strcasecmp(state
, "big") == 0)
4011 return SS_ALL
& ~((1<<SS_SYN_RECV
)|(1<<SS_TIME_WAIT
));
4012 for (i
= 0; i
< SS_MAX
; i
++) {
4013 if (strcasecmp(state
, sstate_namel
[i
]) == 0)
4017 fprintf(stderr
, "ss: wrong state name: %s\n", state
);
4021 static const struct option long_opts
[] = {
4022 { "numeric", 0, 0, 'n' },
4023 { "resolve", 0, 0, 'r' },
4024 { "options", 0, 0, 'o' },
4025 { "extended", 0, 0, 'e' },
4026 { "memory", 0, 0, 'm' },
4027 { "info", 0, 0, 'i' },
4028 { "processes", 0, 0, 'p' },
4029 { "bpf", 0, 0, 'b' },
4030 { "events", 0, 0, 'E' },
4031 { "dccp", 0, 0, 'd' },
4032 { "tcp", 0, 0, 't' },
4033 { "sctp", 0, 0, 'S' },
4034 { "udp", 0, 0, 'u' },
4035 { "raw", 0, 0, 'w' },
4036 { "unix", 0, 0, 'x' },
4037 { "all", 0, 0, 'a' },
4038 { "listening", 0, 0, 'l' },
4039 { "ipv4", 0, 0, '4' },
4040 { "ipv6", 0, 0, '6' },
4041 { "packet", 0, 0, '0' },
4042 { "family", 1, 0, 'f' },
4043 { "socket", 1, 0, 'A' },
4044 { "query", 1, 0, 'A' },
4045 { "summary", 0, 0, 's' },
4046 { "diag", 1, 0, 'D' },
4047 { "filter", 1, 0, 'F' },
4048 { "version", 0, 0, 'V' },
4049 { "help", 0, 0, 'h' },
4050 { "context", 0, 0, 'Z' },
4051 { "contexts", 0, 0, 'z' },
4052 { "net", 1, 0, 'N' },
4053 { "kill", 0, 0, 'K' },
4054 { "no-header", 0, 0, 'H' },
4059 int main(int argc
, char *argv
[])
4064 const char *dump_tcpdiag
= NULL
;
4065 FILE *filter_fp
= NULL
;
4067 int state_filter
= 0;
4068 int addrp_width
, screen_width
= 80;
4070 while ((ch
= getopt_long(argc
, argv
,
4071 "dhaletuwxnro460spbEf:miA:D:F:vVzZN:KHS",
4072 long_opts
, NULL
)) != EOF
) {
4075 resolve_services
= 0;
4095 user_ent_hash_build();
4105 filter_db_set(¤t_filter
, DCCP_DB
);
4108 filter_db_set(¤t_filter
, TCP_DB
);
4111 filter_db_set(¤t_filter
, SCTP_DB
);
4114 filter_db_set(¤t_filter
, UDP_DB
);
4117 filter_db_set(¤t_filter
, RAW_DB
);
4120 filter_af_set(¤t_filter
, AF_UNIX
);
4123 state_filter
= SS_ALL
;
4126 state_filter
= (1 << SS_LISTEN
) | (1 << SS_CLOSE
);
4129 filter_af_set(¤t_filter
, AF_INET
);
4132 filter_af_set(¤t_filter
, AF_INET6
);
4135 filter_af_set(¤t_filter
, AF_PACKET
);
4138 if (strcmp(optarg
, "inet") == 0)
4139 filter_af_set(¤t_filter
, AF_INET
);
4140 else if (strcmp(optarg
, "inet6") == 0)
4141 filter_af_set(¤t_filter
, AF_INET6
);
4142 else if (strcmp(optarg
, "link") == 0)
4143 filter_af_set(¤t_filter
, AF_PACKET
);
4144 else if (strcmp(optarg
, "unix") == 0)
4145 filter_af_set(¤t_filter
, AF_UNIX
);
4146 else if (strcmp(optarg
, "netlink") == 0)
4147 filter_af_set(¤t_filter
, AF_NETLINK
);
4148 else if (strcmp(optarg
, "help") == 0)
4151 fprintf(stderr
, "ss: \"%s\" is invalid family\n",
4161 current_filter
.dbs
= 0;
4162 state_filter
= state_filter
?
4163 state_filter
: SS_CONN
;
4169 if ((p1
= strchr(p
, ',')) != NULL
)
4171 if (strcmp(p
, "all") == 0) {
4172 filter_default_dbs(¤t_filter
);
4173 } else if (strcmp(p
, "inet") == 0) {
4174 filter_db_set(¤t_filter
, UDP_DB
);
4175 filter_db_set(¤t_filter
, DCCP_DB
);
4176 filter_db_set(¤t_filter
, TCP_DB
);
4177 filter_db_set(¤t_filter
, SCTP_DB
);
4178 filter_db_set(¤t_filter
, RAW_DB
);
4179 } else if (strcmp(p
, "udp") == 0) {
4180 filter_db_set(¤t_filter
, UDP_DB
);
4181 } else if (strcmp(p
, "dccp") == 0) {
4182 filter_db_set(¤t_filter
, DCCP_DB
);
4183 } else if (strcmp(p
, "tcp") == 0) {
4184 filter_db_set(¤t_filter
, TCP_DB
);
4185 } else if (strcmp(p
, "sctp") == 0) {
4186 filter_db_set(¤t_filter
, SCTP_DB
);
4187 } else if (strcmp(p
, "raw") == 0) {
4188 filter_db_set(¤t_filter
, RAW_DB
);
4189 } else if (strcmp(p
, "unix") == 0) {
4190 filter_db_set(¤t_filter
, UNIX_ST_DB
);
4191 filter_db_set(¤t_filter
, UNIX_DG_DB
);
4192 filter_db_set(¤t_filter
, UNIX_SQ_DB
);
4193 } else if (strcasecmp(p
, "unix_stream") == 0 ||
4194 strcmp(p
, "u_str") == 0) {
4195 filter_db_set(¤t_filter
, UNIX_ST_DB
);
4196 } else if (strcasecmp(p
, "unix_dgram") == 0 ||
4197 strcmp(p
, "u_dgr") == 0) {
4198 filter_db_set(¤t_filter
, UNIX_DG_DB
);
4199 } else if (strcasecmp(p
, "unix_seqpacket") == 0 ||
4200 strcmp(p
, "u_seq") == 0) {
4201 filter_db_set(¤t_filter
, UNIX_SQ_DB
);
4202 } else if (strcmp(p
, "packet") == 0) {
4203 filter_db_set(¤t_filter
, PACKET_R_DB
);
4204 filter_db_set(¤t_filter
, PACKET_DG_DB
);
4205 } else if (strcmp(p
, "packet_raw") == 0 ||
4206 strcmp(p
, "p_raw") == 0) {
4207 filter_db_set(¤t_filter
, PACKET_R_DB
);
4208 } else if (strcmp(p
, "packet_dgram") == 0 ||
4209 strcmp(p
, "p_dgr") == 0) {
4210 filter_db_set(¤t_filter
, PACKET_DG_DB
);
4211 } else if (strcmp(p
, "netlink") == 0) {
4212 filter_db_set(¤t_filter
, NETLINK_DB
);
4214 fprintf(stderr
, "ss: \"%s\" is illegal socket table id\n", p
);
4225 dump_tcpdiag
= optarg
;
4229 fprintf(stderr
, "More than one filter file\n");
4232 if (optarg
[0] == '-')
4235 filter_fp
= fopen(optarg
, "r");
4237 perror("fopen filter file");
4243 printf("ss utility, iproute2-ss%s\n", SNAPSHOT
);
4249 if (is_selinux_enabled() <= 0) {
4250 fprintf(stderr
, "ss: SELinux is not enabled.\n");
4254 user_ent_hash_build();
4257 if (netns_switch(optarg
))
4261 current_filter
.kill
= 1;
4279 if (do_default
&& argc
== 0)
4284 if (strcmp(*argv
, "state") == 0) {
4288 state_filter
|= scan_state(*argv
);
4290 } else if (strcmp(*argv
, "exclude") == 0 ||
4291 strcmp(*argv
, "excl") == 0) {
4294 state_filter
= SS_ALL
;
4295 state_filter
&= ~scan_state(*argv
);
4304 state_filter
= state_filter
? state_filter
: SS_CONN
;
4305 filter_default_dbs(¤t_filter
);
4308 filter_states_set(¤t_filter
, state_filter
);
4309 filter_merge_defaults(¤t_filter
);
4311 if (resolve_services
&& resolve_hosts
&&
4312 (current_filter
.dbs
& (UNIX_DBM
|INET_L4_DBM
)))
4313 init_service_resolver();
4315 if (current_filter
.dbs
== 0) {
4316 fprintf(stderr
, "ss: no socket tables to show with such filter.\n");
4319 if (current_filter
.families
== 0) {
4320 fprintf(stderr
, "ss: no families to show with such filter.\n");
4323 if (current_filter
.states
== 0) {
4324 fprintf(stderr
, "ss: no socket states to show with such filter.\n");
4329 FILE *dump_fp
= stdout
;
4331 if (!(current_filter
.dbs
& (1<<TCP_DB
))) {
4332 fprintf(stderr
, "ss: tcpdiag dump requested and no tcp in filter.\n");
4335 if (dump_tcpdiag
[0] != '-') {
4336 dump_fp
= fopen(dump_tcpdiag
, "w");
4337 if (!dump_tcpdiag
) {
4338 perror("fopen dump file");
4342 inet_show_netlink(¤t_filter
, dump_fp
, IPPROTO_TCP
);
4347 if (ssfilter_parse(¤t_filter
.f
, argc
, argv
, filter_fp
))
4351 if (current_filter
.dbs
&(current_filter
.dbs
-1))
4355 if (current_filter
.states
&(current_filter
.states
-1))
4358 if (isatty(STDOUT_FILENO
)) {
4361 if (ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &w
) != -1) {
4363 screen_width
= w
.ws_col
;
4367 addrp_width
= screen_width
;
4369 addrp_width
-= netid_width
+ 1;
4371 addrp_width
-= state_width
+ 1;
4374 if (addrp_width
&1) {
4377 else if (state_width
)
4380 odd_width_pad
= " ";
4386 serv_width
= resolve_services
? 7 : 5;
4388 if (addrp_width
< 15+serv_width
+1)
4389 addrp_width
= 15+serv_width
+1;
4391 addr_width
= addrp_width
- serv_width
- 1;
4395 printf("%-*s ", netid_width
, "Netid");
4397 printf("%-*s ", state_width
, "State");
4398 printf("%-6s %-6s %s", "Recv-Q", "Send-Q", odd_width_pad
);
4401 /* Make enough space for the local/remote port field */
4406 printf("%*s:%-*s %*s:%-*s\n",
4407 addr_width
, "Local Address", serv_width
, "Port",
4408 addr_width
, "Peer Address", serv_width
, "Port");
4414 exit(handle_follow_request(¤t_filter
));
4416 if (current_filter
.dbs
& (1<<NETLINK_DB
))
4417 netlink_show(¤t_filter
);
4418 if (current_filter
.dbs
& PACKET_DBM
)
4419 packet_show(¤t_filter
);
4420 if (current_filter
.dbs
& UNIX_DBM
)
4421 unix_show(¤t_filter
);
4422 if (current_filter
.dbs
& (1<<RAW_DB
))
4423 raw_show(¤t_filter
);
4424 if (current_filter
.dbs
& (1<<UDP_DB
))
4425 udp_show(¤t_filter
);
4426 if (current_filter
.dbs
& (1<<TCP_DB
))
4427 tcp_show(¤t_filter
);
4428 if (current_filter
.dbs
& (1<<DCCP_DB
))
4429 dccp_show(¤t_filter
);
4430 if (current_filter
.dbs
& (1<<SCTP_DB
))
4431 sctp_show(¤t_filter
);
4433 if (show_users
|| show_proc_ctx
|| show_sock_ctx
)