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>
33 #include "libnetlink.h"
34 #include "namespace.h"
37 #include <linux/tcp.h>
38 #include <linux/sock_diag.h>
39 #include <linux/inet_diag.h>
40 #include <linux/unix_diag.h>
41 #include <linux/netdevice.h> /* for MAX_ADDR_LEN */
42 #include <linux/filter.h>
43 #include <linux/packet_diag.h>
44 #include <linux/netlink_diag.h>
46 #define MAGIC_SEQ 123456
48 #define DIAG_REQUEST(_req, _r) \
50 struct nlmsghdr nlh; \
54 .nlmsg_type = SOCK_DIAG_BY_FAMILY, \
55 .nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST,\
56 .nlmsg_seq = MAGIC_SEQ, \
57 .nlmsg_len = sizeof(_req), \
62 #include <selinux/selinux.h>
64 /* Stubs for SELinux functions */
65 static int is_selinux_enabled(void)
70 static int getpidcon(pid_t pid
, char **context
)
76 static int getfilecon(char *path
, char **context
)
82 static int security_get_initial_context(char *name
, char **context
)
89 int resolve_hosts
= 0;
90 int resolve_services
= 1;
91 int preferred_family
= AF_UNSPEC
;
98 int show_proc_ctx
= 0;
99 int show_sock_ctx
= 0;
100 /* If show_users & show_proc_ctx only do user_ent_hash_build() once */
101 int user_ent_hash_build_init
= 0;
110 static const char *TCP_PROTO
= "tcp";
111 static const char *UDP_PROTO
= "udp";
112 static const char *RAW_PROTO
= "raw";
113 static const char *dg_proto
= NULL
;
130 #define PACKET_DBM ((1<<PACKET_DG_DB)|(1<<PACKET_R_DB))
131 #define UNIX_DBM ((1<<UNIX_DG_DB)|(1<<UNIX_ST_DB)|(1<<UNIX_SQ_DB))
132 #define ALL_DB ((1<<MAX_DB)-1)
133 #define INET_DBM ((1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB)|(1<<RAW_DB))
151 #define SS_ALL ((1 << SS_MAX) - 1)
152 #define SS_CONN (SS_ALL & ~((1<<SS_LISTEN)|(1<<SS_CLOSE)|(1<<SS_TIME_WAIT)|(1<<SS_SYN_RECV)))
154 #include "ssfilter.h"
164 static const struct filter default_dbs
[MAX_DB
] = {
167 .families
= (1 << AF_INET
) | (1 << AF_INET6
),
171 .families
= (1 << AF_INET
) | (1 << AF_INET6
),
174 .states
= (1 << SS_ESTABLISHED
),
175 .families
= (1 << AF_INET
) | (1 << AF_INET6
),
178 .states
= (1 << SS_ESTABLISHED
),
179 .families
= (1 << AF_INET
) | (1 << AF_INET6
),
182 .states
= (1 << SS_CLOSE
),
183 .families
= (1 << AF_UNIX
),
187 .families
= (1 << AF_UNIX
),
191 .families
= (1 << AF_UNIX
),
194 .states
= (1 << SS_CLOSE
),
195 .families
= (1 << AF_PACKET
),
198 .states
= (1 << SS_CLOSE
),
199 .families
= (1 << AF_PACKET
),
202 .states
= (1 << SS_CLOSE
),
203 .families
= (1 << AF_NETLINK
),
207 static const struct filter default_afs
[AF_MAX
] = {
222 .states
= (1 << SS_CLOSE
),
225 .dbs
= (1 << NETLINK_DB
),
226 .states
= (1 << SS_CLOSE
),
230 static int do_default
= 1;
231 static struct filter current_filter
;
233 static void filter_db_set(struct filter
*f
, int db
)
235 f
->states
|= default_dbs
[db
].states
;
236 f
->families
|= default_dbs
[db
].families
;
241 static void filter_af_set(struct filter
*f
, int af
)
243 f
->dbs
|= default_afs
[af
].dbs
;
244 f
->states
|= default_afs
[af
].states
;
245 f
->families
|= 1 << af
;
247 preferred_family
= af
;
250 static int filter_af_get(struct filter
*f
, int af
)
252 return f
->families
& (1 << af
);
255 static void filter_default_dbs(struct filter
*f
)
257 filter_db_set(f
, UDP_DB
);
258 filter_db_set(f
, DCCP_DB
);
259 filter_db_set(f
, TCP_DB
);
260 filter_db_set(f
, RAW_DB
);
261 filter_db_set(f
, UNIX_ST_DB
);
262 filter_db_set(f
, UNIX_DG_DB
);
263 filter_db_set(f
, UNIX_SQ_DB
);
264 filter_db_set(f
, PACKET_R_DB
);
265 filter_db_set(f
, PACKET_DG_DB
);
266 filter_db_set(f
, NETLINK_DB
);
269 static void filter_merge(struct filter
*af
, struct filter
*dbf
, int states
)
272 af
->families
= (af
->families
| dbf
->families
) & af
->families
;
274 af
->families
= dbf
->families
;
277 af
->dbs
= (af
->dbs
| dbf
->dbs
) & dbf
->dbs
;
280 af
->states
= (af
->states
| dbf
->states
) & dbf
->states
;
283 af
->states
= (af
->states
| states
) & states
;
286 static FILE *generic_proc_open(const char *env
, const char *name
)
288 const char *p
= getenv(env
);
292 p
= getenv("PROC_ROOT") ? : "/proc";
293 snprintf(store
, sizeof(store
)-1, "%s/%s", p
, name
);
297 return fopen(p
, "r");
300 static FILE *net_tcp_open(void)
302 return generic_proc_open("PROC_NET_TCP", "net/tcp");
305 static FILE *net_tcp6_open(void)
307 return generic_proc_open("PROC_NET_TCP6", "net/tcp6");
310 static FILE *net_udp_open(void)
312 return generic_proc_open("PROC_NET_UDP", "net/udp");
315 static FILE *net_udp6_open(void)
317 return generic_proc_open("PROC_NET_UDP6", "net/udp6");
320 static FILE *net_raw_open(void)
322 return generic_proc_open("PROC_NET_RAW", "net/raw");
325 static FILE *net_raw6_open(void)
327 return generic_proc_open("PROC_NET_RAW6", "net/raw6");
330 static FILE *net_unix_open(void)
332 return generic_proc_open("PROC_NET_UNIX", "net/unix");
335 static FILE *net_packet_open(void)
337 return generic_proc_open("PROC_NET_PACKET", "net/packet");
340 static FILE *net_netlink_open(void)
342 return generic_proc_open("PROC_NET_NETLINK", "net/netlink");
345 static FILE *slabinfo_open(void)
347 return generic_proc_open("PROC_SLABINFO", "slabinfo");
350 static FILE *net_sockstat_open(void)
352 return generic_proc_open("PROC_NET_SOCKSTAT", "net/sockstat");
355 static FILE *net_sockstat6_open(void)
357 return generic_proc_open("PROC_NET_SOCKSTAT6", "net/sockstat6");
360 static FILE *net_snmp_open(void)
362 return generic_proc_open("PROC_NET_SNMP", "net/snmp");
365 static FILE *ephemeral_ports_open(void)
367 return generic_proc_open("PROC_IP_LOCAL_PORT_RANGE", "sys/net/ipv4/ip_local_port_range");
371 struct user_ent
*next
;
380 #define USER_ENT_HASH_SIZE 256
381 struct user_ent
*user_ent_hash
[USER_ENT_HASH_SIZE
];
383 static int user_ent_hashfn(unsigned int ino
)
385 int val
= (ino
>> 24) ^ (ino
>> 16) ^ (ino
>> 8) ^ ino
;
387 return val
& (USER_ENT_HASH_SIZE
- 1);
390 static void user_ent_add(unsigned int ino
, char *process
,
395 struct user_ent
*p
, **pp
;
397 p
= malloc(sizeof(struct user_ent
));
399 fprintf(stderr
, "ss: failed to malloc buffer\n");
406 p
->process
= strdup(process
);
407 p
->process_ctx
= strdup(proc_ctx
);
408 p
->socket_ctx
= strdup(sock_ctx
);
410 pp
= &user_ent_hash
[user_ent_hashfn(ino
)];
415 static void user_ent_destroy(void)
417 struct user_ent
*p
, *p_next
;
420 while (cnt
!= USER_ENT_HASH_SIZE
) {
421 p
= user_ent_hash
[cnt
];
424 free(p
->process_ctx
);
434 static void user_ent_hash_build(void)
436 const char *root
= getenv("PROC_ROOT") ? : "/proc/";
443 const char *no_ctx
= "unavailable";
445 /* If show_users & show_proc_ctx set only do this once */
446 if (user_ent_hash_build_init
!= 0)
449 user_ent_hash_build_init
= 1;
452 if (strlen(name
) == 0 || name
[strlen(name
)-1] != '/')
455 nameoff
= strlen(name
);
461 while ((d
= readdir(dir
)) != NULL
) {
469 if (sscanf(d
->d_name
, "%d%c", &pid
, &crap
) != 1)
472 if (getpidcon(pid
, &pid_context
) != 0)
473 pid_context
= strdup(no_ctx
);
475 sprintf(name
+ nameoff
, "%d/fd/", pid
);
477 if ((dir1
= opendir(name
)) == NULL
)
483 while ((d1
= readdir(dir1
)) != NULL
) {
484 const char *pattern
= "socket:[";
491 if (sscanf(d1
->d_name
, "%d%c", &fd
, &crap
) != 1)
494 sprintf(name
+pos
, "%d", fd
);
496 link_len
= readlink(name
, lnk
, sizeof(lnk
)-1);
499 lnk
[link_len
] = '\0';
501 if (strncmp(lnk
, pattern
, strlen(pattern
)))
504 sscanf(lnk
, "socket:[%u]", &ino
);
506 snprintf(tmp
, sizeof(tmp
), "%s/%d/fd/%s",
507 root
, pid
, d1
->d_name
);
509 if (getfilecon(tmp
, &sock_context
) <= 0)
510 sock_context
= strdup(no_ctx
);
515 snprintf(tmp
, sizeof(tmp
), "%s/%d/stat",
517 if ((fp
= fopen(tmp
, "r")) != NULL
) {
518 fscanf(fp
, "%*d (%[^)])", p
);
522 user_ent_add(ino
, p
, pid
, fd
,
523 pid_context
, sock_context
);
538 #define ENTRY_BUF_SIZE 512
539 static int find_entry(unsigned ino
, char **buf
, int type
)
544 char **new_buf
= buf
;
545 int len
, new_buf_len
;
552 p
= user_ent_hash
[user_ent_hashfn(ino
)];
559 ptr
= *buf
+ buf_used
;
562 len
= snprintf(ptr
, buf_len
- buf_used
,
563 "(\"%s\",pid=%d,fd=%d),",
564 p
->process
, p
->pid
, p
->fd
);
567 len
= snprintf(ptr
, buf_len
- buf_used
,
568 "(\"%s\",pid=%d,proc_ctx=%s,fd=%d),",
570 p
->process_ctx
, p
->fd
);
573 len
= snprintf(ptr
, buf_len
- buf_used
,
574 "(\"%s\",pid=%d,proc_ctx=%s,fd=%d,sock_ctx=%s),",
576 p
->process_ctx
, p
->fd
,
580 fprintf(stderr
, "ss: invalid type: %d\n", type
);
584 if (len
< 0 || len
>= buf_len
- buf_used
) {
585 new_buf_len
= buf_len
+ ENTRY_BUF_SIZE
;
586 *new_buf
= realloc(*buf
, new_buf_len
);
588 fprintf(stderr
, "ss: failed to malloc buffer\n");
592 buf_len
= new_buf_len
;
604 ptr
= *buf
+ buf_used
;
610 /* Get stats from slab */
621 struct slabstat slabstat
;
623 static const char *slabstat_ids
[] =
632 static int get_slabstat(struct slabstat
*s
)
638 memset(s
, 0, sizeof(*s
));
640 fp
= slabinfo_open();
644 cnt
= sizeof(*s
)/sizeof(int);
646 fgets(buf
, sizeof(buf
), fp
);
647 while(fgets(buf
, sizeof(buf
), fp
) != NULL
) {
649 for (i
=0; i
<sizeof(slabstat_ids
)/sizeof(slabstat_ids
[0]); i
++) {
650 if (memcmp(buf
, slabstat_ids
[i
], strlen(slabstat_ids
[i
])) == 0) {
651 sscanf(buf
, "%*s%d", ((int *)s
) + i
);
664 static const char *sstate_name
[] = {
666 [SS_ESTABLISHED
] = "ESTAB",
667 [SS_SYN_SENT
] = "SYN-SENT",
668 [SS_SYN_RECV
] = "SYN-RECV",
669 [SS_FIN_WAIT1
] = "FIN-WAIT-1",
670 [SS_FIN_WAIT2
] = "FIN-WAIT-2",
671 [SS_TIME_WAIT
] = "TIME-WAIT",
672 [SS_CLOSE
] = "UNCONN",
673 [SS_CLOSE_WAIT
] = "CLOSE-WAIT",
674 [SS_LAST_ACK
] = "LAST-ACK",
675 [SS_LISTEN
] = "LISTEN",
676 [SS_CLOSING
] = "CLOSING",
679 static const char *sstate_namel
[] = {
681 [SS_ESTABLISHED
] = "established",
682 [SS_SYN_SENT
] = "syn-sent",
683 [SS_SYN_RECV
] = "syn-recv",
684 [SS_FIN_WAIT1
] = "fin-wait-1",
685 [SS_FIN_WAIT2
] = "fin-wait-2",
686 [SS_TIME_WAIT
] = "time-wait",
687 [SS_CLOSE
] = "unconnected",
688 [SS_CLOSE_WAIT
] = "close-wait",
689 [SS_LAST_ACK
] = "last-ack",
690 [SS_LISTEN
] = "listening",
691 [SS_CLOSING
] = "closing",
696 unsigned int ce_state
;
715 unsigned long long sk
;
720 double rto
, ato
, rtt
, rttvar
;
721 int qack
, cwnd
, ssthresh
, backoff
;
726 unsigned int lastsnd
;
727 unsigned int lastrcv
;
728 unsigned int lastack
;
730 double pacing_rate_max
;
731 unsigned int unacked
;
732 unsigned int retrans
;
733 unsigned int retrans_total
;
736 unsigned int fackets
;
737 unsigned int reordering
;
743 bool has_ecnseen_opt
;
744 bool has_fastopen_opt
;
746 struct dctcpstat
*dctcp
;
749 static const char *tmr_name
[] = {
758 static const char *print_ms_timer(int timeout
)
761 int secs
, msecs
, minutes
;
767 msecs
= timeout
%1000;
771 snprintf(buf
, sizeof(buf
)-16, "%dmin", minutes
);
778 sprintf(buf
+strlen(buf
), "%d%s", secs
, msecs
? "." : "sec");
781 sprintf(buf
+strlen(buf
), "%03dms", msecs
);
793 struct scache
*rlist
;
795 static void init_service_resolver(void)
798 FILE *fp
= popen("/usr/sbin/rpcinfo -p 2>/dev/null", "r");
800 fgets(buf
, sizeof(buf
), fp
);
801 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
802 unsigned int progn
, port
;
803 char proto
[128], prog
[128];
804 if (sscanf(buf
, "%u %*d %s %u %s", &progn
, proto
,
805 &port
, prog
+4) == 4) {
806 struct scache
*c
= malloc(sizeof(*c
));
809 memcpy(prog
, "rpc.", 4);
810 c
->name
= strdup(prog
);
811 if (strcmp(proto
, TCP_PROTO
) == 0)
812 c
->proto
= TCP_PROTO
;
813 else if (strcmp(proto
, UDP_PROTO
) == 0)
814 c
->proto
= UDP_PROTO
;
826 static int ip_local_port_min
, ip_local_port_max
;
828 /* Even do not try default linux ephemeral port ranges:
829 * default /etc/services contains so much of useless crap
830 * wouldbe "allocated" to this area that resolution
831 * is really harmful. I shrug each time when seeing
832 * "socks" or "cfinger" in dumps.
834 static int is_ephemeral(int port
)
836 if (!ip_local_port_min
) {
837 FILE *f
= ephemeral_ports_open();
840 &ip_local_port_min
, &ip_local_port_max
);
843 ip_local_port_min
= 1024;
844 ip_local_port_max
= 4999;
848 return (port
>= ip_local_port_min
&& port
<= ip_local_port_max
);
852 static const char *__resolve_service(int port
)
856 for (c
= rlist
; c
; c
= c
->next
) {
857 if (c
->port
== port
&& c
->proto
== dg_proto
)
861 if (!is_ephemeral(port
)) {
868 se
= getservbyport(htons(port
), dg_proto
);
877 static const char *resolve_service(int port
)
879 static char buf
[128];
880 static struct scache cache
[256];
888 if (resolve_services
) {
889 if (dg_proto
== RAW_PROTO
) {
890 return inet_proto_n2a(port
, buf
, sizeof(buf
));
894 int hash
= (port
^(((unsigned long)dg_proto
)>>2))&255;
896 for (c
= &cache
[hash
]; c
; c
= c
->next
) {
897 if (c
->port
== port
&&
898 c
->proto
== dg_proto
) {
905 if ((res
= __resolve_service(port
)) != NULL
) {
906 if ((c
= malloc(sizeof(*c
))) == NULL
)
917 c
->name
= strdup(res
);
918 c
->next
= cache
[hash
].next
;
919 cache
[hash
].next
= c
;
927 sprintf(buf
, "%u", port
);
931 static void formatted_print(const inet_prefix
*a
, int port
, unsigned int ifindex
)
934 const char *ap
= buf
;
937 est_len
= addr_width
;
939 if (a
->family
== AF_INET
) {
940 if (a
->data
[0] == 0) {
944 ap
= format_host(AF_INET
, 4, a
->data
, buf
, sizeof(buf
));
947 ap
= format_host(a
->family
, 16, a
->data
, buf
, sizeof(buf
));
948 est_len
= strlen(ap
);
949 if (est_len
<= addr_width
)
950 est_len
= addr_width
;
952 est_len
= addr_width
+ ((est_len
-addr_width
+3)/4)*4;
955 const char *ifname
= ll_index_to_name(ifindex
);
956 const int len
= strlen(ifname
) + 1; /* +1 for percent char */
958 printf("%*s%%%s:%-*s ", est_len
- len
, ap
, ifname
, serv_width
,
959 resolve_service(port
));
961 printf("%*s:%-*s ", est_len
, ap
, serv_width
, resolve_service(port
));
968 struct aafilter
*next
;
971 static int inet2_addr_match(const inet_prefix
*a
, const inet_prefix
*p
,
974 if (!inet_addr_match(a
, p
, plen
))
977 /* Cursed "v4 mapped" addresses: v4 mapped socket matches
978 * pure IPv4 rule, but v4-mapped rule selects only v4-mapped
980 if (p
->family
== AF_INET
&& a
->family
== AF_INET6
) {
981 if (a
->data
[0] == 0 && a
->data
[1] == 0 &&
982 a
->data
[2] == htonl(0xffff)) {
983 inet_prefix tmp
= *a
;
984 tmp
.data
[0] = a
->data
[3];
985 return inet_addr_match(&tmp
, p
, plen
);
991 static int unix_match(const inet_prefix
*a
, const inet_prefix
*p
)
993 char *addr
, *pattern
;
994 memcpy(&addr
, a
->data
, sizeof(addr
));
995 memcpy(&pattern
, p
->data
, sizeof(pattern
));
1000 return !fnmatch(pattern
, addr
, 0);
1003 static int run_ssfilter(struct ssfilter
*f
, struct tcpstat
*s
)
1008 static int low
, high
=65535;
1010 if (s
->local
.family
== AF_UNIX
) {
1012 memcpy(&p
, s
->local
.data
, sizeof(p
));
1013 return p
== NULL
|| (p
[0] == '@' && strlen(p
) == 6 &&
1014 strspn(p
+1, "0123456789abcdef") == 5);
1016 if (s
->local
.family
== AF_PACKET
)
1017 return s
->lport
== 0 && s
->local
.data
== 0;
1018 if (s
->local
.family
== AF_NETLINK
)
1019 return s
->lport
< 0;
1022 FILE *fp
= ephemeral_ports_open();
1024 fscanf(fp
, "%d%d", &low
, &high
);
1028 return s
->lport
>= low
&& s
->lport
<= high
;
1032 struct aafilter
*a
= (void*)f
->pred
;
1033 if (a
->addr
.family
== AF_UNIX
)
1034 return unix_match(&s
->remote
, &a
->addr
);
1035 if (a
->port
!= -1 && a
->port
!= s
->rport
)
1037 if (a
->addr
.bitlen
) {
1039 if (!inet2_addr_match(&s
->remote
, &a
->addr
, a
->addr
.bitlen
))
1041 } while ((a
= a
->next
) != NULL
);
1048 struct aafilter
*a
= (void*)f
->pred
;
1049 if (a
->addr
.family
== AF_UNIX
)
1050 return unix_match(&s
->local
, &a
->addr
);
1051 if (a
->port
!= -1 && a
->port
!= s
->lport
)
1053 if (a
->addr
.bitlen
) {
1055 if (!inet2_addr_match(&s
->local
, &a
->addr
, a
->addr
.bitlen
))
1057 } while ((a
= a
->next
) != NULL
);
1064 struct aafilter
*a
= (void*)f
->pred
;
1065 return s
->rport
>= a
->port
;
1069 struct aafilter
*a
= (void*)f
->pred
;
1070 return s
->rport
<= a
->port
;
1074 struct aafilter
*a
= (void*)f
->pred
;
1075 return s
->lport
>= a
->port
;
1079 struct aafilter
*a
= (void*)f
->pred
;
1080 return s
->lport
<= a
->port
;
1083 /* Yup. It is recursion. Sorry. */
1085 return run_ssfilter(f
->pred
, s
) && run_ssfilter(f
->post
, s
);
1087 return run_ssfilter(f
->pred
, s
) || run_ssfilter(f
->post
, s
);
1089 return !run_ssfilter(f
->pred
, s
);
1095 /* Relocate external jumps by reloc. */
1096 static void ssfilter_patch(char *a
, int len
, int reloc
)
1099 struct inet_diag_bc_op
*op
= (struct inet_diag_bc_op
*)a
;
1100 if (op
->no
== len
+4)
1109 static int ssfilter_bytecompile(struct ssfilter
*f
, char **bytecode
)
1114 if (!(*bytecode
=malloc(4))) abort();
1115 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_AUTO
, 4, 8 };
1121 struct aafilter
*a
= (void*)f
->pred
;
1124 int code
= (f
->type
== SSF_DCOND
? INET_DIAG_BC_D_COND
: INET_DIAG_BC_S_COND
);
1127 for (b
=a
; b
; b
=b
->next
) {
1128 len
+= 4 + sizeof(struct inet_diag_hostcond
);
1129 if (a
->addr
.family
== AF_INET6
)
1136 if (!(ptr
= malloc(len
))) abort();
1138 for (b
=a
; b
; b
=b
->next
) {
1139 struct inet_diag_bc_op
*op
= (struct inet_diag_bc_op
*)ptr
;
1140 int alen
= (a
->addr
.family
== AF_INET6
? 16 : 4);
1141 int oplen
= alen
+ 4 + sizeof(struct inet_diag_hostcond
);
1142 struct inet_diag_hostcond
*cond
= (struct inet_diag_hostcond
*)(ptr
+4);
1144 *op
= (struct inet_diag_bc_op
){ code
, oplen
, oplen
+4 };
1145 cond
->family
= a
->addr
.family
;
1146 cond
->port
= a
->port
;
1147 cond
->prefix_len
= a
->addr
.bitlen
;
1148 memcpy(cond
->addr
, a
->addr
.data
, alen
);
1151 op
= (struct inet_diag_bc_op
*)ptr
;
1152 *op
= (struct inet_diag_bc_op
){ INET_DIAG_BC_JMP
, 4, len
- (ptr
-*bytecode
)};
1156 return ptr
- *bytecode
;
1160 struct aafilter
*x
= (void*)f
->pred
;
1161 if (!(*bytecode
=malloc(8))) abort();
1162 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_D_GE
, 8, 12 };
1163 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
1168 struct aafilter
*x
= (void*)f
->pred
;
1169 if (!(*bytecode
=malloc(8))) abort();
1170 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_D_LE
, 8, 12 };
1171 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
1176 struct aafilter
*x
= (void*)f
->pred
;
1177 if (!(*bytecode
=malloc(8))) abort();
1178 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_S_GE
, 8, 12 };
1179 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
1184 struct aafilter
*x
= (void*)f
->pred
;
1185 if (!(*bytecode
=malloc(8))) abort();
1186 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_S_LE
, 8, 12 };
1187 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
1195 l1
= ssfilter_bytecompile(f
->pred
, &a1
);
1196 l2
= ssfilter_bytecompile(f
->post
, &a2
);
1197 if (!(a
= malloc(l1
+l2
))) abort();
1199 memcpy(a
+l1
, a2
, l2
);
1201 ssfilter_patch(a
, l1
, l2
);
1209 l1
= ssfilter_bytecompile(f
->pred
, &a1
);
1210 l2
= ssfilter_bytecompile(f
->post
, &a2
);
1211 if (!(a
= malloc(l1
+l2
+4))) abort();
1213 memcpy(a
+l1
+4, a2
, l2
);
1215 *(struct inet_diag_bc_op
*)(a
+l1
) = (struct inet_diag_bc_op
){ INET_DIAG_BC_JMP
, 4, l2
+4 };
1223 l1
= ssfilter_bytecompile(f
->pred
, &a1
);
1224 if (!(a
= malloc(l1
+4))) abort();
1227 *(struct inet_diag_bc_op
*)(a
+l1
) = (struct inet_diag_bc_op
){ INET_DIAG_BC_JMP
, 4, 8 };
1236 static int remember_he(struct aafilter
*a
, struct hostent
*he
)
1238 char **ptr
= he
->h_addr_list
;
1242 if (he
->h_addrtype
== AF_INET
)
1244 else if (he
->h_addrtype
== AF_INET6
)
1250 struct aafilter
*b
= a
;
1251 if (a
->addr
.bitlen
) {
1252 if ((b
= malloc(sizeof(*b
))) == NULL
)
1258 memcpy(b
->addr
.data
, *ptr
, len
);
1259 b
->addr
.bytelen
= len
;
1260 b
->addr
.bitlen
= len
*8;
1261 b
->addr
.family
= he
->h_addrtype
;
1268 static int get_dns_host(struct aafilter
*a
, const char *addr
, int fam
)
1270 static int notfirst
;
1279 he
= gethostbyname2(addr
, fam
== AF_UNSPEC
? AF_INET
: fam
);
1281 cnt
= remember_he(a
, he
);
1282 if (fam
== AF_UNSPEC
) {
1283 he
= gethostbyname2(addr
, AF_INET6
);
1285 cnt
+= remember_he(a
, he
);
1290 static int xll_initted
= 0;
1292 static void xll_init(void)
1294 struct rtnl_handle rth
;
1295 if (rtnl_open(&rth
, 0) < 0)
1303 static const char *xll_index_to_name(int index
)
1307 return ll_index_to_name(index
);
1310 static int xll_name_to_index(const char *dev
)
1314 return ll_name_to_index(dev
);
1317 void *parse_hostcond(char *addr
)
1320 struct aafilter a
= { .port
= -1 };
1321 struct aafilter
*res
;
1322 int fam
= preferred_family
;
1323 struct filter
*f
= ¤t_filter
;
1325 if (fam
== AF_UNIX
|| strncmp(addr
, "unix:", 5) == 0) {
1327 a
.addr
.family
= AF_UNIX
;
1328 if (strncmp(addr
, "unix:", 5) == 0)
1331 a
.addr
.bitlen
= 8*strlen(p
);
1332 memcpy(a
.addr
.data
, &p
, sizeof(p
));
1337 if (fam
== AF_PACKET
|| strncmp(addr
, "link:", 5) == 0) {
1338 a
.addr
.family
= AF_PACKET
;
1340 if (strncmp(addr
, "link:", 5) == 0)
1342 port
= strchr(addr
, ':');
1345 if (port
[1] && strcmp(port
+1, "*")) {
1346 if (get_integer(&a
.port
, port
+1, 0)) {
1347 if ((a
.port
= xll_name_to_index(port
+1)) <= 0)
1352 if (addr
[0] && strcmp(addr
, "*")) {
1355 if (ll_proto_a2n(&tmp
, addr
))
1357 a
.addr
.data
[0] = ntohs(tmp
);
1363 if (fam
== AF_NETLINK
|| strncmp(addr
, "netlink:", 8) == 0) {
1364 a
.addr
.family
= AF_NETLINK
;
1366 if (strncmp(addr
, "netlink:", 8) == 0)
1368 port
= strchr(addr
, ':');
1371 if (port
[1] && strcmp(port
+1, "*")) {
1372 if (get_integer(&a
.port
, port
+1, 0)) {
1373 if (strcmp(port
+1, "kernel") == 0)
1380 if (addr
[0] && strcmp(addr
, "*")) {
1382 if (nl_proto_a2n(&a
.addr
.data
[0], addr
) == -1)
1389 if (fam
== AF_INET
|| !strncmp(addr
, "inet:", 5)) {
1391 if (!strncmp(addr
, "inet:", 5))
1393 } else if (fam
== AF_INET6
|| !strncmp(addr
, "inet6:", 6)) {
1395 if (!strncmp(addr
, "inet6:", 6))
1399 /* URL-like literal [] */
1400 if (addr
[0] == '[') {
1402 if ((port
= strchr(addr
, ']')) == NULL
)
1405 } else if (addr
[0] == '*') {
1408 port
= strrchr(strchr(addr
, '/') ? : addr
, ':');
1410 if (port
&& *port
) {
1414 if (*port
&& *port
!= '*') {
1415 if (get_integer(&a
.port
, port
, 0)) {
1416 struct servent
*se1
= NULL
;
1417 struct servent
*se2
= NULL
;
1418 if (current_filter
.dbs
&(1<<UDP_DB
))
1419 se1
= getservbyname(port
, UDP_PROTO
);
1420 if (current_filter
.dbs
&(1<<TCP_DB
))
1421 se2
= getservbyname(port
, TCP_PROTO
);
1422 if (se1
&& se2
&& se1
->s_port
!= se2
->s_port
) {
1423 fprintf(stderr
, "Error: ambiguous port \"%s\".\n", port
);
1429 a
.port
= ntohs(se1
->s_port
);
1432 for (s
= rlist
; s
; s
= s
->next
) {
1433 if ((s
->proto
== UDP_PROTO
&&
1434 (current_filter
.dbs
&(1<<UDP_DB
))) ||
1435 (s
->proto
== TCP_PROTO
&&
1436 (current_filter
.dbs
&(1<<TCP_DB
)))) {
1437 if (s
->name
&& strcmp(s
->name
, port
) == 0) {
1438 if (a
.port
> 0 && a
.port
!= s
->port
) {
1439 fprintf(stderr
, "Error: ambiguous port \"%s\".\n", port
);
1447 fprintf(stderr
, "Error: \"%s\" does not look like a port.\n", port
);
1454 if (addr
&& *addr
&& *addr
!= '*') {
1455 if (get_prefix_1(&a
.addr
, addr
, fam
)) {
1456 if (get_dns_host(&a
, addr
, fam
)) {
1457 fprintf(stderr
, "Error: an inet prefix is expected rather than \"%s\".\n", addr
);
1464 if (fam
!= AF_UNSPEC
) {
1466 filter_af_set(f
, fam
);
1467 filter_merge(f
, f
, 0);
1470 res
= malloc(sizeof(*res
));
1472 memcpy(res
, &a
, sizeof(a
));
1476 static char *proto_name(int protocol
)
1490 static void inet_stats_print(struct tcpstat
*s
, int protocol
)
1495 printf("%-*s ", netid_width
, proto_name(protocol
));
1497 printf("%-*s ", state_width
, sstate_name
[s
->state
]);
1499 printf("%-6d %-6d ", s
->rq
, s
->wq
);
1501 formatted_print(&s
->local
, s
->lport
, s
->iface
);
1502 formatted_print(&s
->remote
, s
->rport
, 0);
1508 printf(" timer:(%s,%s,%d)",
1510 print_ms_timer(s
->timeout
),
1515 if (show_proc_ctx
|| show_sock_ctx
) {
1516 if (find_entry(s
->ino
, &buf
,
1517 (show_proc_ctx
& show_sock_ctx
) ?
1518 PROC_SOCK_CTX
: PROC_CTX
) > 0) {
1519 printf(" users:(%s)", buf
);
1522 } else if (show_users
) {
1523 if (find_entry(s
->ino
, &buf
, USERS
) > 0) {
1524 printf(" users:(%s)", buf
);
1530 static int proc_parse_inet_addr(char *loc
, char *rem
, int family
, struct tcpstat
*s
)
1532 s
->local
.family
= s
->remote
.family
= family
;
1533 if (family
== AF_INET
) {
1534 sscanf(loc
, "%x:%x", s
->local
.data
, (unsigned*)&s
->lport
);
1535 sscanf(rem
, "%x:%x", s
->remote
.data
, (unsigned*)&s
->rport
);
1536 s
->local
.bytelen
= s
->remote
.bytelen
= 4;
1539 sscanf(loc
, "%08x%08x%08x%08x:%x",
1545 sscanf(rem
, "%08x%08x%08x%08x:%x",
1551 s
->local
.bytelen
= s
->remote
.bytelen
= 16;
1557 static int proc_inet_split_line(char *line
, char **loc
, char **rem
, char **data
)
1561 if ((p
= strchr(line
, ':')) == NULL
)
1565 if ((p
= strchr(*loc
, ':')) == NULL
)
1570 if ((p
= strchr(*rem
, ':')) == NULL
)
1578 static char *sprint_bw(char *buf
, double bw
)
1581 sprintf(buf
,"%.1fM", bw
/ 1000000.);
1582 else if (bw
> 1000.)
1583 sprintf(buf
,"%.1fK", bw
/ 1000.);
1585 sprintf(buf
, "%g", bw
);
1590 static void tcp_stats_print(struct tcpstat
*s
)
1596 if (s
->has_sack_opt
)
1600 if (s
->has_ecnseen_opt
)
1602 if (s
->has_fastopen_opt
)
1603 printf(" fastopen");
1605 printf(" %s", s
->cong_alg
);
1606 if (s
->has_wscale_opt
)
1607 printf(" wscale:%d,%d", s
->snd_wscale
, s
->rcv_wscale
);
1609 printf(" rto:%g", s
->rto
);
1611 printf(" backoff:%u", s
->backoff
);
1613 printf(" rtt:%g/%g", s
->rtt
, s
->rttvar
);
1615 printf(" ato:%g", s
->ato
);
1618 printf(" qack:%d", s
->qack
);
1623 printf(" mss:%d", s
->mss
);
1624 if (s
->cwnd
&& s
->cwnd
!= 2)
1625 printf(" cwnd:%d", s
->cwnd
);
1627 printf(" ssthresh:%d", s
->ssthresh
);
1629 if (s
->dctcp
&& s
->dctcp
->enabled
) {
1630 struct dctcpstat
*dctcp
= s
->dctcp
;
1632 printf(" ce_state %u alpha %u ab_ecn %u ab_tot %u",
1633 dctcp
->ce_state
, dctcp
->alpha
, dctcp
->ab_ecn
,
1635 } else if (s
->dctcp
) {
1636 printf(" fallback_mode");
1640 printf(" send %sbps", sprint_bw(b1
, s
->send_bps
));
1642 printf(" lastsnd:%u", s
->lastsnd
);
1644 printf(" lastrcv:%u", s
->lastrcv
);
1646 printf(" lastack:%u", s
->lastack
);
1648 if (s
->pacing_rate
) {
1649 printf(" pacing_rate %sbps", sprint_bw(b1
, s
->pacing_rate
));
1650 if (s
->pacing_rate_max
)
1651 printf("/%sbps", sprint_bw(b1
,
1652 s
->pacing_rate_max
));
1656 printf(" unacked:%u", s
->unacked
);
1657 if (s
->retrans
|| s
->retrans_total
)
1658 printf(" retrans:%u/%u", s
->retrans
, s
->retrans_total
);
1660 printf(" lost:%u", s
->lost
);
1661 if (s
->sacked
&& s
->state
!= SS_LISTEN
)
1662 printf(" sacked:%u", s
->sacked
);
1664 printf(" fackets:%u", s
->fackets
);
1665 if (s
->reordering
!= 3)
1666 printf(" reordering:%d", s
->reordering
);
1668 printf(" rcv_rtt:%g", s
->rcv_rtt
);
1670 printf(" rcv_space:%d", s
->rcv_space
);
1673 static int tcp_show_line(char *line
, const struct filter
*f
, int family
)
1675 int rto
= 0, ato
= 0;
1676 struct tcpstat s
= {};
1677 char *loc
, *rem
, *data
;
1680 int hz
= get_user_hz();
1682 if (proc_inet_split_line(line
, &loc
, &rem
, &data
))
1685 int state
= (data
[1] >= 'A') ? (data
[1] - 'A' + 10) : (data
[1] - '0');
1686 if (!(f
->states
& (1 << state
)))
1689 proc_parse_inet_addr(loc
, rem
, family
, &s
);
1691 if (f
->f
&& run_ssfilter(f
->f
, &s
) == 0)
1695 n
= sscanf(data
, "%x %x:%x %x:%x %x %d %d %u %d %llx %d %d %d %d %d %[^\n]\n",
1696 &s
.state
, &s
.wq
, &s
.rq
,
1697 &s
.timer
, &s
.timeout
, &s
.retrans
, &s
.uid
, &s
.probes
, &s
.ino
,
1698 &s
.refcnt
, &s
.sk
, &rto
, &ato
, &s
.qack
,
1699 &s
.cwnd
, &s
.ssthresh
, opt
);
1711 s
.retrans
= s
.timer
!= 1 ? s
.probes
: s
.retrans
;
1712 s
.timeout
= (s
.timeout
* 1000 + hz
- 1) / hz
;
1713 s
.ato
= (double)ato
/ hz
;
1715 s
.rto
= (double)rto
;
1716 s
.ssthresh
= s
.ssthresh
== -1 ? 0 : s
.ssthresh
;
1717 s
.rto
= s
.rto
!= 3 * hz
? s
.rto
/ hz
: 0;
1719 inet_stats_print(&s
, IPPROTO_TCP
);
1723 printf(" uid:%u", (unsigned)s
.uid
);
1724 printf(" ino:%u", s
.ino
);
1725 printf(" sk:%llx", s
.sk
);
1727 printf(" opt:\"%s\"", opt
);
1731 tcp_stats_print(&s
);
1737 static int generic_record_read(FILE *fp
,
1738 int (*worker
)(char*, const struct filter
*, int),
1739 const struct filter
*f
, int fam
)
1744 if (fgets(line
, sizeof(line
), fp
) == NULL
)
1747 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
1748 int n
= strlen(line
);
1749 if (n
== 0 || line
[n
-1] != '\n') {
1755 if (worker(line
, f
, fam
) < 0)
1760 return ferror(fp
) ? -1 : 0;
1763 static void print_skmeminfo(struct rtattr
*tb
[], int attrtype
)
1765 const __u32
*skmeminfo
;
1767 if (!tb
[attrtype
]) {
1768 if (attrtype
== INET_DIAG_SKMEMINFO
) {
1769 if (!tb
[INET_DIAG_MEMINFO
])
1772 const struct inet_diag_meminfo
*minfo
=
1773 RTA_DATA(tb
[INET_DIAG_MEMINFO
]);
1775 printf(" mem:(r%u,w%u,f%u,t%u)",
1784 skmeminfo
= RTA_DATA(tb
[attrtype
]);
1786 printf(" skmem:(r%u,rb%u,t%u,tb%u,f%u,w%u,o%u",
1787 skmeminfo
[SK_MEMINFO_RMEM_ALLOC
],
1788 skmeminfo
[SK_MEMINFO_RCVBUF
],
1789 skmeminfo
[SK_MEMINFO_WMEM_ALLOC
],
1790 skmeminfo
[SK_MEMINFO_SNDBUF
],
1791 skmeminfo
[SK_MEMINFO_FWD_ALLOC
],
1792 skmeminfo
[SK_MEMINFO_WMEM_QUEUED
],
1793 skmeminfo
[SK_MEMINFO_OPTMEM
]);
1795 if (RTA_PAYLOAD(tb
[attrtype
]) >=
1796 (SK_MEMINFO_BACKLOG
+ 1) * sizeof(__u32
))
1797 printf(",bl%u", skmeminfo
[SK_MEMINFO_BACKLOG
]);
1802 #define TCPI_HAS_OPT(info, opt) !!(info->tcpi_options & (opt))
1804 static void tcp_show_info(const struct nlmsghdr
*nlh
, struct inet_diag_msg
*r
,
1805 struct rtattr
*tb
[])
1808 struct tcpstat s
= {};
1810 print_skmeminfo(tb
, INET_DIAG_SKMEMINFO
);
1812 if (tb
[INET_DIAG_INFO
]) {
1813 struct tcp_info
*info
;
1814 int len
= RTA_PAYLOAD(tb
[INET_DIAG_INFO
]);
1816 /* workaround for older kernels with less fields */
1817 if (len
< sizeof(*info
)) {
1818 info
= alloca(sizeof(*info
));
1819 memset(info
, 0, sizeof(*info
));
1820 memcpy(info
, RTA_DATA(tb
[INET_DIAG_INFO
]), len
);
1822 info
= RTA_DATA(tb
[INET_DIAG_INFO
]);
1825 s
.has_ts_opt
= TCPI_HAS_OPT(info
, TCPI_OPT_TIMESTAMPS
);
1826 s
.has_sack_opt
= TCPI_HAS_OPT(info
, TCPI_OPT_SACK
);
1827 s
.has_ecn_opt
= TCPI_HAS_OPT(info
, TCPI_OPT_ECN
);
1828 s
.has_ecnseen_opt
= TCPI_HAS_OPT(info
, TCPI_OPT_ECN_SEEN
);
1829 s
.has_fastopen_opt
= TCPI_HAS_OPT(info
, TCPI_OPT_SYN_DATA
);
1832 if (tb
[INET_DIAG_CONG
]) {
1833 const char *cong_attr
= rta_getattr_str(tb
[INET_DIAG_CONG
]);
1834 s
.cong_alg
= malloc(strlen(cong_attr
+ 1));
1835 strcpy(s
.cong_alg
, cong_attr
);
1838 if (TCPI_HAS_OPT(info
, TCPI_OPT_WSCALE
)) {
1839 s
.has_wscale_opt
= true;
1840 s
.snd_wscale
= info
->tcpi_snd_wscale
;
1841 s
.rcv_wscale
= info
->tcpi_rcv_wscale
;
1844 if (info
->tcpi_rto
&& info
->tcpi_rto
!= 3000000)
1845 s
.rto
= (double)info
->tcpi_rto
/ 1000;
1847 s
.backoff
= info
->tcpi_backoff
;
1848 s
.rtt
= (double)info
->tcpi_rtt
/ 1000;
1849 s
.rttvar
= (double)info
->tcpi_rttvar
/ 1000;
1850 s
.ato
= (double)info
->tcpi_rttvar
/ 1000;
1851 s
.mss
= info
->tcpi_snd_mss
;
1852 s
.rcv_space
= info
->tcpi_rcv_space
;
1853 s
.rcv_rtt
= (double)info
->tcpi_rcv_rtt
/ 1000;
1854 s
.lastsnd
= info
->tcpi_last_data_sent
;
1855 s
.lastrcv
= info
->tcpi_last_data_recv
;
1856 s
.lastack
= info
->tcpi_last_ack_recv
;
1857 s
.unacked
= info
->tcpi_unacked
;
1858 s
.retrans
= info
->tcpi_retrans
;
1859 s
.retrans_total
= info
->tcpi_total_retrans
;
1860 s
.lost
= info
->tcpi_lost
;
1861 s
.sacked
= info
->tcpi_sacked
;
1862 s
.reordering
= info
->tcpi_reordering
;
1863 s
.rcv_space
= info
->tcpi_rcv_space
;
1864 s
.cwnd
= info
->tcpi_snd_cwnd
;
1866 if (info
->tcpi_snd_ssthresh
< 0xFFFF)
1867 s
.ssthresh
= info
->tcpi_snd_ssthresh
;
1869 rtt
= (double) info
->tcpi_rtt
;
1870 if (tb
[INET_DIAG_VEGASINFO
]) {
1871 const struct tcpvegas_info
*vinfo
1872 = RTA_DATA(tb
[INET_DIAG_VEGASINFO
]);
1874 if (vinfo
->tcpv_enabled
&&
1875 vinfo
->tcpv_rtt
&& vinfo
->tcpv_rtt
!= 0x7fffffff)
1876 rtt
= vinfo
->tcpv_rtt
;
1879 if (tb
[INET_DIAG_DCTCPINFO
]) {
1880 struct dctcpstat
*dctcp
= malloc(sizeof(struct
1883 const struct tcp_dctcp_info
*dinfo
1884 = RTA_DATA(tb
[INET_DIAG_DCTCPINFO
]);
1886 dctcp
->enabled
= !!dinfo
->dctcp_enabled
;
1887 dctcp
->ce_state
= dinfo
->dctcp_ce_state
;
1888 dctcp
->alpha
= dinfo
->dctcp_alpha
;
1889 dctcp
->ab_ecn
= dinfo
->dctcp_ab_ecn
;
1890 dctcp
->ab_tot
= dinfo
->dctcp_ab_tot
;
1894 if (rtt
> 0 && info
->tcpi_snd_mss
&& info
->tcpi_snd_cwnd
) {
1895 s
.send_bps
= (double) info
->tcpi_snd_cwnd
*
1896 (double)info
->tcpi_snd_mss
* 8000000. / rtt
;
1899 if (info
->tcpi_pacing_rate
&&
1900 info
->tcpi_pacing_rate
!= ~0ULL) {
1901 s
.pacing_rate
= info
->tcpi_pacing_rate
* 8.;
1903 if (info
->tcpi_max_pacing_rate
&&
1904 info
->tcpi_max_pacing_rate
!= ~0ULL)
1905 s
.pacing_rate_max
= info
->tcpi_max_pacing_rate
* 8.;
1907 tcp_stats_print(&s
);
1915 static int inet_show_sock(struct nlmsghdr
*nlh
, struct filter
*f
, int protocol
)
1917 struct rtattr
* tb
[INET_DIAG_MAX
+1];
1918 struct inet_diag_msg
*r
= NLMSG_DATA(nlh
);
1919 struct tcpstat s
= {};
1921 parse_rtattr(tb
, INET_DIAG_MAX
, (struct rtattr
*)(r
+1),
1922 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
1924 s
.state
= r
->idiag_state
;
1925 s
.local
.family
= s
.remote
.family
= r
->idiag_family
;
1926 s
.lport
= ntohs(r
->id
.idiag_sport
);
1927 s
.rport
= ntohs(r
->id
.idiag_dport
);
1928 s
.wq
= r
->idiag_wqueue
;
1929 s
.rq
= r
->idiag_rqueue
;
1930 s
.timer
= r
->idiag_timer
;
1931 s
.timeout
= r
->idiag_expires
;
1932 s
.retrans
= r
->idiag_retrans
;
1933 s
.ino
= r
->idiag_inode
;
1934 s
.uid
= r
->idiag_uid
;
1935 s
.iface
= r
->id
.idiag_if
;
1937 if (s
.local
.family
== AF_INET
) {
1938 s
.local
.bytelen
= s
.remote
.bytelen
= 4;
1940 s
.local
.bytelen
= s
.remote
.bytelen
= 16;
1943 memcpy(s
.local
.data
, r
->id
.idiag_src
, s
.local
.bytelen
);
1944 memcpy(s
.remote
.data
, r
->id
.idiag_dst
, s
.local
.bytelen
);
1946 if (f
&& f
->f
&& run_ssfilter(f
->f
, &s
) == 0)
1949 inet_stats_print(&s
, protocol
);
1953 printf(" uid:%u", (unsigned)r
->idiag_uid
);
1954 printf(" ino:%u", r
->idiag_inode
);
1956 if (r
->id
.idiag_cookie
[1] != 0)
1957 printf("%08x", r
->id
.idiag_cookie
[1]);
1958 printf("%08x", r
->id
.idiag_cookie
[0]);
1959 if (tb
[INET_DIAG_SHUTDOWN
]) {
1961 mask
= *(__u8
*)RTA_DATA(tb
[INET_DIAG_SHUTDOWN
]);
1962 printf(" %c-%c", mask
& 1 ? '-' : '<', mask
& 2 ? '-' : '>');
1966 if (show_mem
|| show_tcpinfo
) {
1968 tcp_show_info(nlh
, r
, tb
);
1975 static int tcpdiag_send(int fd
, int protocol
, struct filter
*f
)
1977 struct sockaddr_nl nladdr
;
1979 struct nlmsghdr nlh
;
1980 struct inet_diag_req r
;
1986 struct iovec iov
[3];
1988 if (protocol
== IPPROTO_UDP
)
1991 memset(&nladdr
, 0, sizeof(nladdr
));
1992 nladdr
.nl_family
= AF_NETLINK
;
1994 req
.nlh
.nlmsg_len
= sizeof(req
);
1995 if (protocol
== IPPROTO_TCP
)
1996 req
.nlh
.nlmsg_type
= TCPDIAG_GETSOCK
;
1998 req
.nlh
.nlmsg_type
= DCCPDIAG_GETSOCK
;
1999 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
2000 req
.nlh
.nlmsg_pid
= 0;
2001 req
.nlh
.nlmsg_seq
= MAGIC_SEQ
;
2002 memset(&req
.r
, 0, sizeof(req
.r
));
2003 req
.r
.idiag_family
= AF_INET
;
2004 req
.r
.idiag_states
= f
->states
;
2006 req
.r
.idiag_ext
|= (1<<(INET_DIAG_MEMINFO
-1));
2007 req
.r
.idiag_ext
|= (1<<(INET_DIAG_SKMEMINFO
-1));
2011 req
.r
.idiag_ext
|= (1<<(INET_DIAG_INFO
-1));
2012 req
.r
.idiag_ext
|= (1<<(INET_DIAG_VEGASINFO
-1));
2013 req
.r
.idiag_ext
|= (1<<(INET_DIAG_CONG
-1));
2016 iov
[0] = (struct iovec
){
2018 .iov_len
= sizeof(req
)
2021 bclen
= ssfilter_bytecompile(f
->f
, &bc
);
2022 rta
.rta_type
= INET_DIAG_REQ_BYTECODE
;
2023 rta
.rta_len
= RTA_LENGTH(bclen
);
2024 iov
[1] = (struct iovec
){ &rta
, sizeof(rta
) };
2025 iov
[2] = (struct iovec
){ bc
, bclen
};
2026 req
.nlh
.nlmsg_len
+= RTA_LENGTH(bclen
);
2029 msg
= (struct msghdr
) {
2030 .msg_name
= (void*)&nladdr
,
2031 .msg_namelen
= sizeof(nladdr
),
2033 .msg_iovlen
= f
->f
? 3 : 1,
2036 if (sendmsg(fd
, &msg
, 0) < 0) {
2044 static int sockdiag_send(int family
, int fd
, int protocol
, struct filter
*f
)
2046 struct sockaddr_nl nladdr
;
2047 DIAG_REQUEST(req
, struct inet_diag_req_v2 r
);
2052 struct iovec iov
[3];
2054 if (family
== PF_UNSPEC
)
2055 return tcpdiag_send(fd
, protocol
, f
);
2057 memset(&nladdr
, 0, sizeof(nladdr
));
2058 nladdr
.nl_family
= AF_NETLINK
;
2060 memset(&req
.r
, 0, sizeof(req
.r
));
2061 req
.r
.sdiag_family
= family
;
2062 req
.r
.sdiag_protocol
= protocol
;
2063 req
.r
.idiag_states
= f
->states
;
2065 req
.r
.idiag_ext
|= (1<<(INET_DIAG_MEMINFO
-1));
2066 req
.r
.idiag_ext
|= (1<<(INET_DIAG_SKMEMINFO
-1));
2070 req
.r
.idiag_ext
|= (1<<(INET_DIAG_INFO
-1));
2071 req
.r
.idiag_ext
|= (1<<(INET_DIAG_VEGASINFO
-1));
2072 req
.r
.idiag_ext
|= (1<<(INET_DIAG_CONG
-1));
2075 iov
[0] = (struct iovec
){
2077 .iov_len
= sizeof(req
)
2080 bclen
= ssfilter_bytecompile(f
->f
, &bc
);
2081 rta
.rta_type
= INET_DIAG_REQ_BYTECODE
;
2082 rta
.rta_len
= RTA_LENGTH(bclen
);
2083 iov
[1] = (struct iovec
){ &rta
, sizeof(rta
) };
2084 iov
[2] = (struct iovec
){ bc
, bclen
};
2085 req
.nlh
.nlmsg_len
+= RTA_LENGTH(bclen
);
2088 msg
= (struct msghdr
) {
2089 .msg_name
= (void*)&nladdr
,
2090 .msg_namelen
= sizeof(nladdr
),
2092 .msg_iovlen
= f
->f
? 3 : 1,
2095 if (sendmsg(fd
, &msg
, 0) < 0) {
2103 struct inet_diag_arg
{
2108 static int show_one_inet_sock(const struct sockaddr_nl
*addr
,
2109 struct nlmsghdr
*h
, void *arg
)
2112 struct inet_diag_arg
*diag_arg
= arg
;
2113 struct inet_diag_msg
*r
= NLMSG_DATA(h
);
2115 if (!(diag_arg
->f
->families
& (1 << r
->idiag_family
)))
2117 if ((err
= inet_show_sock(h
, NULL
, diag_arg
->protocol
)) < 0)
2123 static int inet_show_netlink(struct filter
*f
, FILE *dump_fp
, int protocol
)
2126 struct rtnl_handle rth
;
2127 int family
= PF_INET
;
2128 struct inet_diag_arg arg
= { .f
= f
, .protocol
= protocol
};
2130 if (rtnl_open_byproto(&rth
, 0, NETLINK_SOCK_DIAG
))
2132 rth
.dump
= MAGIC_SEQ
;
2133 rth
.dump_fp
= dump_fp
;
2136 if ((err
= sockdiag_send(family
, rth
.fd
, protocol
, f
)))
2139 if ((err
= rtnl_dump_filter(&rth
, show_one_inet_sock
, &arg
))) {
2140 if (family
!= PF_UNSPEC
) {
2146 if (family
== PF_INET
) {
2156 static int tcp_show_netlink_file(struct filter
*f
)
2161 if ((fp
= fopen(getenv("TCPDIAG_FILE"), "r")) == NULL
) {
2162 perror("fopen($TCPDIAG_FILE)");
2168 struct nlmsghdr
*h
= (struct nlmsghdr
*)buf
;
2170 status
= fread(buf
, 1, sizeof(*h
), fp
);
2172 perror("Reading header from $TCPDIAG_FILE");
2175 if (status
!= sizeof(*h
)) {
2176 perror("Unexpected EOF reading $TCPDIAG_FILE");
2180 status
= fread(h
+1, 1, NLMSG_ALIGN(h
->nlmsg_len
-sizeof(*h
)), fp
);
2183 perror("Reading $TCPDIAG_FILE");
2186 if (status
+ sizeof(*h
) < h
->nlmsg_len
) {
2187 perror("Unexpected EOF reading $TCPDIAG_FILE");
2191 /* The only legal exit point */
2192 if (h
->nlmsg_type
== NLMSG_DONE
)
2195 if (h
->nlmsg_type
== NLMSG_ERROR
) {
2196 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(h
);
2197 if (h
->nlmsg_len
< NLMSG_LENGTH(sizeof(struct nlmsgerr
))) {
2198 fprintf(stderr
, "ERROR truncated\n");
2200 errno
= -err
->error
;
2201 perror("TCPDIAG answered");
2206 err
= inet_show_sock(h
, f
, IPPROTO_TCP
);
2212 static int tcp_show(struct filter
*f
, int socktype
)
2216 int bufsize
= 64*1024;
2218 if (!filter_af_get(f
, AF_INET
) && !filter_af_get(f
, AF_INET6
))
2221 dg_proto
= TCP_PROTO
;
2223 if (getenv("TCPDIAG_FILE"))
2224 return tcp_show_netlink_file(f
);
2226 if (!getenv("PROC_NET_TCP") && !getenv("PROC_ROOT")
2227 && inet_show_netlink(f
, NULL
, socktype
) == 0)
2230 /* Sigh... We have to parse /proc/net/tcp... */
2233 /* Estimate amount of sockets and try to allocate
2234 * huge buffer to read all the table at one read.
2235 * Limit it by 16MB though. The assumption is: as soon as
2236 * kernel was able to hold information about N connections,
2237 * it is able to give us some memory for snapshot.
2240 int guess
= slabstat
.socks
+slabstat
.tcp_syns
;
2241 if (f
->states
&(1<<SS_TIME_WAIT
))
2242 guess
+= slabstat
.tcp_tws
;
2243 if (guess
> (16*1024*1024)/128)
2244 guess
= (16*1024*1024)/128;
2246 if (guess
> bufsize
)
2249 while (bufsize
>= 64*1024) {
2250 if ((buf
= malloc(bufsize
)) != NULL
)
2259 if (f
->families
& (1<<AF_INET
)) {
2260 if ((fp
= net_tcp_open()) == NULL
)
2263 setbuffer(fp
, buf
, bufsize
);
2264 if (generic_record_read(fp
, tcp_show_line
, f
, AF_INET
))
2269 if ((f
->families
& (1<<AF_INET6
)) &&
2270 (fp
= net_tcp6_open()) != NULL
) {
2271 setbuffer(fp
, buf
, bufsize
);
2272 if (generic_record_read(fp
, tcp_show_line
, f
, AF_INET6
))
2282 int saved_errno
= errno
;
2287 errno
= saved_errno
;
2293 static int dgram_show_line(char *line
, const struct filter
*f
, int family
)
2295 struct tcpstat s
= {};
2296 char *loc
, *rem
, *data
;
2300 if (proc_inet_split_line(line
, &loc
, &rem
, &data
))
2303 int state
= (data
[1] >= 'A') ? (data
[1] - 'A' + 10) : (data
[1] - '0');
2304 if (!(f
->states
& (1 << state
)))
2307 proc_parse_inet_addr(loc
, rem
, family
, &s
);
2309 if (f
->f
&& run_ssfilter(f
->f
, &s
) == 0)
2313 n
= sscanf(data
, "%x %x:%x %*x:%*x %*x %d %*d %u %d %llx %[^\n]\n",
2314 &s
.state
, &s
.wq
, &s
.rq
,
2316 &s
.refcnt
, &s
.sk
, opt
);
2321 inet_stats_print(&s
, IPPROTO_UDP
);
2325 printf(" uid=%u", (unsigned)s
.uid
);
2326 printf(" ino=%u", s
.ino
);
2327 printf(" sk=%llx", s
.sk
);
2329 printf(" opt:\"%s\"", opt
);
2336 static int udp_show(struct filter
*f
)
2340 if (!filter_af_get(f
, AF_INET
) && !filter_af_get(f
, AF_INET6
))
2343 dg_proto
= UDP_PROTO
;
2345 if (!getenv("PROC_NET_UDP") && !getenv("PROC_ROOT")
2346 && inet_show_netlink(f
, NULL
, IPPROTO_UDP
) == 0)
2349 if (f
->families
&(1<<AF_INET
)) {
2350 if ((fp
= net_udp_open()) == NULL
)
2352 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET
))
2357 if ((f
->families
&(1<<AF_INET6
)) &&
2358 (fp
= net_udp6_open()) != NULL
) {
2359 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET6
))
2367 int saved_errno
= errno
;
2370 errno
= saved_errno
;
2375 static int raw_show(struct filter
*f
)
2379 if (!filter_af_get(f
, AF_INET
) && !filter_af_get(f
, AF_INET6
))
2382 dg_proto
= RAW_PROTO
;
2384 if (f
->families
&(1<<AF_INET
)) {
2385 if ((fp
= net_raw_open()) == NULL
)
2387 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET
))
2392 if ((f
->families
&(1<<AF_INET6
)) &&
2393 (fp
= net_raw6_open()) != NULL
) {
2394 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET6
))
2402 int saved_errno
= errno
;
2405 errno
= saved_errno
;
2412 struct unixstat
*next
;
2423 int unix_state_map
[] = { SS_CLOSE
, SS_SYN_SENT
,
2424 SS_ESTABLISHED
, SS_CLOSING
};
2426 #define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct unixstat))
2428 static void unix_list_free(struct unixstat
*list
)
2431 struct unixstat
*s
= list
;
2439 static const char *unix_netid_name(int type
)
2447 case SOCK_SEQPACKET
:
2458 static bool unix_type_skip(struct unixstat
*s
, struct filter
*f
)
2460 if (s
->type
== SOCK_STREAM
&& !(f
->dbs
&(1<<UNIX_ST_DB
)))
2462 if (s
->type
== SOCK_DGRAM
&& !(f
->dbs
&(1<<UNIX_DG_DB
)))
2464 if (s
->type
== SOCK_SEQPACKET
&& !(f
->dbs
&(1<<UNIX_SQ_DB
)))
2469 static void unix_stats_print(struct unixstat
*list
, struct filter
*f
)
2474 for (s
= list
; s
; s
= s
->next
) {
2475 if (!(f
->states
& (1<<s
->state
)))
2477 if (unix_type_skip(s
, f
))
2482 peer
= s
->peer_name
;
2484 if (s
->peer
&& !s
->peer_name
) {
2486 for (p
= list
; p
; p
= p
->next
) {
2487 if (s
->peer
== p
->ino
)
2493 peer
= p
->name
? : "*";
2499 tst
.local
.family
= AF_UNIX
;
2500 tst
.remote
.family
= AF_UNIX
;
2501 memcpy(tst
.local
.data
, &s
->name
, sizeof(s
->name
));
2502 if (strcmp(peer
, "*") == 0)
2503 memset(tst
.remote
.data
, 0, sizeof(peer
));
2505 memcpy(tst
.remote
.data
, &peer
, sizeof(peer
));
2506 if (run_ssfilter(f
->f
, &tst
) == 0)
2511 printf("%-*s ", netid_width
,
2512 unix_netid_name(s
->type
));
2514 printf("%-*s ", state_width
, sstate_name
[s
->state
]);
2515 printf("%-6d %-6d ", s
->rq
, s
->wq
);
2516 printf("%*s %-*d %*s %-*d",
2517 addr_width
, s
->name
? : "*", serv_width
, s
->ino
,
2518 addr_width
, peer
, serv_width
, s
->peer
);
2521 if (show_proc_ctx
|| show_sock_ctx
) {
2522 if (find_entry(s
->ino
, &buf
,
2523 (show_proc_ctx
& show_sock_ctx
) ?
2524 PROC_SOCK_CTX
: PROC_CTX
) > 0) {
2525 printf(" users:(%s)", buf
);
2528 } else if (show_users
) {
2529 if (find_entry(s
->ino
, &buf
, USERS
) > 0) {
2530 printf(" users:(%s)", buf
);
2538 static int unix_show_sock(const struct sockaddr_nl
*addr
, struct nlmsghdr
*nlh
,
2541 struct filter
*f
= (struct filter
*)arg
;
2542 struct unix_diag_msg
*r
= NLMSG_DATA(nlh
);
2543 struct rtattr
*tb
[UNIX_DIAG_MAX
+1];
2545 struct unixstat stat
= { .name
= "*" , .peer_name
= "*" };
2547 parse_rtattr(tb
, UNIX_DIAG_MAX
, (struct rtattr
*)(r
+1),
2548 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
2550 stat
.type
= r
->udiag_type
;
2551 stat
.state
= r
->udiag_state
;
2552 stat
.ino
= r
->udiag_ino
;
2554 if (unix_type_skip(&stat
, f
))
2557 if (tb
[UNIX_DIAG_RQLEN
]) {
2558 struct unix_diag_rqlen
*rql
= RTA_DATA(tb
[UNIX_DIAG_RQLEN
]);
2559 stat
.rq
= rql
->udiag_rqueue
;
2560 stat
.wq
= rql
->udiag_wqueue
;
2562 if (tb
[UNIX_DIAG_NAME
]) {
2563 int len
= RTA_PAYLOAD(tb
[UNIX_DIAG_NAME
]);
2565 memcpy(name
, RTA_DATA(tb
[UNIX_DIAG_NAME
]), len
);
2567 if (name
[0] == '\0')
2569 stat
.name
= &name
[0];
2571 if (tb
[UNIX_DIAG_PEER
])
2572 stat
.peer
= rta_getattr_u32(tb
[UNIX_DIAG_PEER
]);
2574 unix_stats_print(&stat
, f
);
2578 print_skmeminfo(tb
, UNIX_DIAG_MEMINFO
);
2581 if (tb
[UNIX_DIAG_SHUTDOWN
]) {
2583 mask
= *(__u8
*)RTA_DATA(tb
[UNIX_DIAG_SHUTDOWN
]);
2584 printf(" %c-%c", mask
& 1 ? '-' : '<', mask
& 2 ? '-' : '>');
2587 if (show_mem
|| show_details
)
2592 static int handle_netlink_request(struct filter
*f
, struct nlmsghdr
*req
,
2593 size_t size
, rtnl_filter_t show_one_sock
)
2596 struct rtnl_handle rth
;
2598 if (rtnl_open_byproto(&rth
, 0, NETLINK_SOCK_DIAG
))
2601 rth
.dump
= MAGIC_SEQ
;
2603 if (rtnl_send(&rth
, req
, size
) < 0)
2606 if (rtnl_dump_filter(&rth
, show_one_sock
, f
))
2615 static int unix_show_netlink(struct filter
*f
)
2617 DIAG_REQUEST(req
, struct unix_diag_req r
);
2619 req
.r
.sdiag_family
= AF_UNIX
;
2620 req
.r
.udiag_states
= f
->states
;
2621 req
.r
.udiag_show
= UDIAG_SHOW_NAME
| UDIAG_SHOW_PEER
| UDIAG_SHOW_RQLEN
;
2623 req
.r
.udiag_show
|= UDIAG_SHOW_MEMINFO
;
2625 return handle_netlink_request(f
, &req
.nlh
, sizeof(req
), unix_show_sock
);
2628 static int unix_show(struct filter
*f
)
2635 struct unixstat
*list
= NULL
;
2637 if (!filter_af_get(f
, AF_UNIX
))
2640 if (!getenv("PROC_NET_UNIX") && !getenv("PROC_ROOT")
2641 && unix_show_netlink(f
) == 0)
2644 if ((fp
= net_unix_open()) == NULL
)
2646 fgets(buf
, sizeof(buf
)-1, fp
);
2648 if (memcmp(buf
, "Peer", 4) == 0)
2652 while (fgets(buf
, sizeof(buf
)-1, fp
)) {
2653 struct unixstat
*u
, **insp
;
2656 if (!(u
= malloc(sizeof(*u
))))
2659 u
->peer_name
= NULL
;
2661 if (sscanf(buf
, "%x: %x %x %x %x %x %d %s",
2662 &u
->peer
, &u
->rq
, &u
->wq
, &flags
, &u
->type
,
2663 &u
->state
, &u
->ino
, name
) < 8)
2666 if (flags
&(1<<16)) {
2667 u
->state
= SS_LISTEN
;
2669 u
->state
= unix_state_map
[u
->state
-1];
2670 if (u
->type
== SOCK_DGRAM
&&
2671 u
->state
== SS_CLOSE
&&
2673 u
->state
= SS_ESTABLISHED
;
2684 if (u
->type
< (*insp
)->type
||
2685 (u
->type
== (*insp
)->type
&&
2686 u
->ino
< (*insp
)->ino
))
2688 insp
= &(*insp
)->next
;
2694 if ((u
->name
= malloc(strlen(name
)+1)) == NULL
)
2696 strcpy(u
->name
, name
);
2698 if (++cnt
> MAX_UNIX_REMEMBER
) {
2699 unix_stats_print(list
, f
);
2700 unix_list_free(list
);
2707 unix_stats_print(list
, f
);
2708 unix_list_free(list
);
2726 static int packet_stats_print(struct pktstat
*s
, const struct filter
*f
)
2732 tst
.local
.family
= AF_PACKET
;
2733 tst
.remote
.family
= AF_PACKET
;
2735 tst
.lport
= s
->iface
;
2736 tst
.local
.data
[0] = s
->prot
;
2737 tst
.remote
.data
[0] = 0;
2738 if (run_ssfilter(f
->f
, &tst
) == 0)
2743 printf("%-*s ", netid_width
,
2744 s
->type
== SOCK_RAW
? "p_raw" : "p_dgr");
2746 printf("%-*s ", state_width
, "UNCONN");
2748 printf("%-6d %-6d ", s
->rq
, 0);
2750 printf("%*s:", addr_width
, "*");
2753 printf("%*s:", addr_width
,
2754 ll_proto_n2a(htons(s
->prot
), tb
, sizeof(tb
)));
2756 if (s
->iface
== 0) {
2757 printf("%-*s ", serv_width
, "*");
2759 printf("%-*s ", serv_width
, xll_index_to_name(s
->iface
));
2762 printf("%*s*%-*s", addr_width
, "", serv_width
, "");
2764 if (show_proc_ctx
|| show_sock_ctx
) {
2765 if (find_entry(s
->ino
, &buf
,
2766 (show_proc_ctx
& show_sock_ctx
) ?
2767 PROC_SOCK_CTX
: PROC_CTX
) > 0) {
2768 printf(" users:(%s)", buf
);
2771 } else if (show_users
) {
2772 if (find_entry(s
->ino
, &buf
, USERS
) > 0) {
2773 printf(" users:(%s)", buf
);
2781 static int packet_show_sock(const struct sockaddr_nl
*addr
,
2782 struct nlmsghdr
*nlh
, void *arg
)
2784 const struct filter
*f
= arg
;
2785 struct packet_diag_msg
*r
= NLMSG_DATA(nlh
);
2786 struct rtattr
*tb
[PACKET_DIAG_MAX
+1];
2787 struct pktstat stat
= {};
2789 parse_rtattr(tb
, PACKET_DIAG_MAX
, (struct rtattr
*)(r
+1),
2790 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
2792 /* use /proc/net/packet if all info are not available */
2793 if (!tb
[PACKET_DIAG_MEMINFO
])
2796 stat
.type
= r
->pdiag_type
;
2797 stat
.prot
= r
->pdiag_num
;
2798 stat
.ino
= r
->pdiag_ino
;
2800 if (tb
[PACKET_DIAG_MEMINFO
]) {
2801 __u32
*skmeminfo
= RTA_DATA(tb
[PACKET_DIAG_MEMINFO
]);
2802 stat
.rq
= skmeminfo
[SK_MEMINFO_RMEM_ALLOC
];
2805 if (tb
[PACKET_DIAG_INFO
]) {
2806 struct packet_diag_info
*pinfo
= RTA_DATA(tb
[PACKET_DIAG_INFO
]);
2807 stat
.iface
= pinfo
->pdi_index
;
2810 if (packet_stats_print(&stat
, f
))
2816 if (tb
[PACKET_DIAG_UID
])
2817 uid
= *(__u32
*)RTA_DATA(tb
[PACKET_DIAG_UID
]);
2819 printf(" ino=%u uid=%u sk=", r
->pdiag_ino
, uid
);
2820 if (r
->pdiag_cookie
[1] != 0)
2821 printf("%08x", r
->pdiag_cookie
[1]);
2822 printf("%08x", r
->pdiag_cookie
[0]);
2825 if (show_bpf
&& tb
[PACKET_DIAG_FILTER
]) {
2826 struct sock_filter
*fil
=
2827 RTA_DATA(tb
[PACKET_DIAG_FILTER
]);
2828 int num
= RTA_PAYLOAD(tb
[PACKET_DIAG_FILTER
]) /
2829 sizeof(struct sock_filter
);
2831 printf("\n\tbpf filter (%d): ", num
);
2833 printf(" 0x%02x %u %u %u,",
2834 fil
->code
, fil
->jt
, fil
->jf
, fil
->k
);
2843 static int packet_show_netlink(struct filter
*f
)
2845 DIAG_REQUEST(req
, struct packet_diag_req r
);
2847 req
.r
.sdiag_family
= AF_PACKET
;
2848 req
.r
.pdiag_show
= PACKET_SHOW_INFO
| PACKET_SHOW_MEMINFO
| PACKET_SHOW_FILTER
;
2850 return handle_netlink_request(f
, &req
.nlh
, sizeof(req
), packet_show_sock
);
2853 static int packet_show_line(char *buf
, const struct filter
*f
, int fam
)
2855 unsigned long long sk
;
2856 struct pktstat stat
= {};
2857 int type
, prot
, iface
, state
, rq
, uid
, ino
;
2859 sscanf(buf
, "%llx %*d %d %x %d %d %u %u %u",
2861 &type
, &prot
, &iface
, &state
,
2864 if (stat
.type
== SOCK_RAW
&& !(f
->dbs
&(1<<PACKET_R_DB
)))
2866 if (stat
.type
== SOCK_DGRAM
&& !(f
->dbs
&(1<<PACKET_DG_DB
)))
2876 if (packet_stats_print(&stat
, f
))
2880 printf(" ino=%u uid=%u sk=%llx", ino
, uid
, sk
);
2886 static int packet_show(struct filter
*f
)
2890 if (!filter_af_get(f
, AF_PACKET
) || !(f
->states
& (1 << SS_CLOSE
)))
2893 if (!getenv("PROC_NET_PACKET") && !getenv("PROC_ROOT") &&
2894 packet_show_netlink(f
) == 0)
2897 if ((fp
= net_packet_open()) == NULL
)
2899 if (generic_record_read(fp
, packet_show_line
, f
, AF_PACKET
))
2905 static void netlink_show_one(struct filter
*f
,
2906 int prot
, int pid
, unsigned groups
,
2907 int state
, int dst_pid
, unsigned dst_group
,
2909 unsigned long long sk
, unsigned long long cb
)
2911 SPRINT_BUF(prot_name
);
2915 tst
.local
.family
= AF_NETLINK
;
2916 tst
.remote
.family
= AF_NETLINK
;
2919 tst
.local
.data
[0] = prot
;
2920 tst
.remote
.data
[0] = 0;
2921 if (run_ssfilter(f
->f
, &tst
) == 0)
2926 printf("%-*s ", netid_width
, "nl");
2928 printf("%-*s ", state_width
, "UNCONN");
2929 printf("%-6d %-6d ", rq
, wq
);
2931 if (resolve_services
) {
2932 printf("%*s:", addr_width
, nl_proto_n2a(prot
, prot_name
,
2933 sizeof(prot_name
)));
2935 printf("%*d:", addr_width
, prot
);
2939 printf("%-*s ", serv_width
, "*");
2940 } else if (resolve_services
) {
2944 printf("%-*s ", serv_width
, "kernel");
2945 } else if (pid
> 0) {
2948 sprintf(procname
, "%s/%d/stat",
2949 getenv("PROC_ROOT") ? : "/proc", pid
);
2950 if ((fp
= fopen(procname
, "r")) != NULL
) {
2951 if (fscanf(fp
, "%*d (%[^)])", procname
) == 1) {
2952 sprintf(procname
+strlen(procname
), "/%d", pid
);
2953 printf("%-*s ", serv_width
, procname
);
2960 printf("%-*d ", serv_width
, pid
);
2962 printf("%-*d ", serv_width
, pid
);
2965 if (state
== NETLINK_CONNECTED
) {
2967 addr_width
, dst_group
, serv_width
, dst_pid
);
2970 addr_width
, "", serv_width
, "");
2973 char *pid_context
= NULL
;
2974 if (show_proc_ctx
) {
2975 /* The pid value will either be:
2976 * 0 if destination kernel - show kernel initial context.
2977 * A valid process pid - use getpidcon.
2978 * A unique value allocated by the kernel or netlink user
2979 * to the process - show context as "not available".
2982 security_get_initial_context("kernel", &pid_context
);
2984 getpidcon(pid
, &pid_context
);
2986 if (pid_context
!= NULL
) {
2987 printf("proc_ctx=%-*s ", serv_width
, pid_context
);
2990 printf("proc_ctx=%-*s ", serv_width
, "unavailable");
2995 printf(" sk=%llx cb=%llx groups=0x%08x", sk
, cb
, groups
);
3002 static int netlink_show_sock(const struct sockaddr_nl
*addr
,
3003 struct nlmsghdr
*nlh
, void *arg
)
3005 struct filter
*f
= (struct filter
*)arg
;
3006 struct netlink_diag_msg
*r
= NLMSG_DATA(nlh
);
3007 struct rtattr
*tb
[NETLINK_DIAG_MAX
+1];
3009 unsigned long groups
= 0;
3011 parse_rtattr(tb
, NETLINK_DIAG_MAX
, (struct rtattr
*)(r
+1),
3012 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
3014 if (tb
[NETLINK_DIAG_GROUPS
] && RTA_PAYLOAD(tb
[NETLINK_DIAG_GROUPS
]))
3015 groups
= *(unsigned long *) RTA_DATA(tb
[NETLINK_DIAG_GROUPS
]);
3017 if (tb
[NETLINK_DIAG_MEMINFO
]) {
3018 const __u32
*skmeminfo
;
3019 skmeminfo
= RTA_DATA(tb
[NETLINK_DIAG_MEMINFO
]);
3021 rq
= skmeminfo
[SK_MEMINFO_RMEM_ALLOC
];
3022 wq
= skmeminfo
[SK_MEMINFO_WMEM_ALLOC
];
3025 netlink_show_one(f
, r
->ndiag_protocol
, r
->ndiag_portid
, groups
,
3026 r
->ndiag_state
, r
->ndiag_dst_portid
, r
->ndiag_dst_group
,
3031 print_skmeminfo(tb
, NETLINK_DIAG_MEMINFO
);
3038 static int netlink_show_netlink(struct filter
*f
)
3040 DIAG_REQUEST(req
, struct netlink_diag_req r
);
3042 req
.r
.sdiag_family
= AF_NETLINK
;
3043 req
.r
.sdiag_protocol
= NDIAG_PROTO_ALL
;
3044 req
.r
.ndiag_show
= NDIAG_SHOW_GROUPS
| NDIAG_SHOW_MEMINFO
;
3046 return handle_netlink_request(f
, &req
.nlh
, sizeof(req
), netlink_show_sock
);
3049 static int netlink_show(struct filter
*f
)
3056 unsigned long long sk
, cb
;
3058 if (!filter_af_get(f
, AF_NETLINK
) || !(f
->states
& (1 << SS_CLOSE
)))
3061 if (!getenv("PROC_NET_NETLINK") && !getenv("PROC_ROOT") &&
3062 netlink_show_netlink(f
) == 0)
3065 if ((fp
= net_netlink_open()) == NULL
)
3067 fgets(buf
, sizeof(buf
)-1, fp
);
3069 while (fgets(buf
, sizeof(buf
)-1, fp
)) {
3070 sscanf(buf
, "%llx %d %d %x %d %d %llx %d",
3072 &prot
, &pid
, &groups
, &rq
, &wq
, &cb
, &rc
);
3074 netlink_show_one(f
, prot
, pid
, groups
, 0, 0, 0, rq
, wq
, sk
, cb
);
3085 static int get_snmp_int(char *proto
, char *key
, int *result
)
3089 int protolen
= strlen(proto
);
3090 int keylen
= strlen(key
);
3094 if ((fp
= net_snmp_open()) == NULL
)
3097 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
3100 if (memcmp(buf
, proto
, protolen
))
3102 while ((p
= strchr(p
, ' ')) != NULL
) {
3105 if (memcmp(p
, key
, keylen
) == 0 &&
3106 (p
[keylen
] == ' ' || p
[keylen
] == '\n'))
3109 if (fgets(buf
, sizeof(buf
), fp
) == NULL
)
3111 if (memcmp(buf
, proto
, protolen
))
3114 while ((p
= strchr(p
, ' ')) != NULL
) {
3117 sscanf(p
, "%d", result
);
3130 /* Get stats from sockstat */
3151 static void get_sockstat_line(char *line
, struct sockstat
*s
)
3153 char id
[256], rem
[256];
3155 if (sscanf(line
, "%[^ ] %[^\n]\n", id
, rem
) != 2)
3158 if (strcmp(id
, "sockets:") == 0)
3159 sscanf(rem
, "%*s%d", &s
->socks
);
3160 else if (strcmp(id
, "UDP:") == 0)
3161 sscanf(rem
, "%*s%d", &s
->udp4
);
3162 else if (strcmp(id
, "UDP6:") == 0)
3163 sscanf(rem
, "%*s%d", &s
->udp6
);
3164 else if (strcmp(id
, "RAW:") == 0)
3165 sscanf(rem
, "%*s%d", &s
->raw4
);
3166 else if (strcmp(id
, "RAW6:") == 0)
3167 sscanf(rem
, "%*s%d", &s
->raw6
);
3168 else if (strcmp(id
, "TCP6:") == 0)
3169 sscanf(rem
, "%*s%d", &s
->tcp6_hashed
);
3170 else if (strcmp(id
, "FRAG:") == 0)
3171 sscanf(rem
, "%*s%d%*s%d", &s
->frag4
, &s
->frag4_mem
);
3172 else if (strcmp(id
, "FRAG6:") == 0)
3173 sscanf(rem
, "%*s%d%*s%d", &s
->frag6
, &s
->frag6_mem
);
3174 else if (strcmp(id
, "TCP:") == 0)
3175 sscanf(rem
, "%*s%d%*s%d%*s%d%*s%d%*s%d",
3177 &s
->tcp_orphans
, &s
->tcp_tws
, &s
->tcp_total
, &s
->tcp_mem
);
3180 static int get_sockstat(struct sockstat
*s
)
3185 memset(s
, 0, sizeof(*s
));
3187 if ((fp
= net_sockstat_open()) == NULL
)
3189 while(fgets(buf
, sizeof(buf
), fp
) != NULL
)
3190 get_sockstat_line(buf
, s
);
3193 if ((fp
= net_sockstat6_open()) == NULL
)
3195 while(fgets(buf
, sizeof(buf
), fp
) != NULL
)
3196 get_sockstat_line(buf
, s
);
3202 static int print_summary(void)
3207 if (get_sockstat(&s
) < 0)
3208 perror("ss: get_sockstat");
3209 if (get_snmp_int("Tcp:", "CurrEstab", &sn
.tcp_estab
) < 0)
3210 perror("ss: get_snmpstat");
3212 printf("Total: %d (kernel %d)\n", s
.socks
, slabstat
.socks
);
3214 printf("TCP: %d (estab %d, closed %d, orphaned %d, synrecv %d, timewait %d/%d), ports %d\n",
3215 s
.tcp_total
+ slabstat
.tcp_syns
+ s
.tcp_tws
,
3217 s
.tcp_total
- (s
.tcp4_hashed
+s
.tcp6_hashed
-s
.tcp_tws
),
3220 s
.tcp_tws
, slabstat
.tcp_tws
,
3225 printf("Transport Total IP IPv6\n");
3226 printf("* %-9d %-9s %-9s\n", slabstat
.socks
, "-", "-");
3227 printf("RAW %-9d %-9d %-9d\n", s
.raw4
+s
.raw6
, s
.raw4
, s
.raw6
);
3228 printf("UDP %-9d %-9d %-9d\n", s
.udp4
+s
.udp6
, s
.udp4
, s
.udp6
);
3229 printf("TCP %-9d %-9d %-9d\n", s
.tcp4_hashed
+s
.tcp6_hashed
, s
.tcp4_hashed
, s
.tcp6_hashed
);
3230 printf("INET %-9d %-9d %-9d\n",
3231 s
.raw4
+s
.udp4
+s
.tcp4_hashed
+
3232 s
.raw6
+s
.udp6
+s
.tcp6_hashed
,
3233 s
.raw4
+s
.udp4
+s
.tcp4_hashed
,
3234 s
.raw6
+s
.udp6
+s
.tcp6_hashed
);
3235 printf("FRAG %-9d %-9d %-9d\n", s
.frag4
+s
.frag6
, s
.frag4
, s
.frag6
);
3242 static void _usage(FILE *dest
)
3245 "Usage: ss [ OPTIONS ]\n"
3246 " ss [ OPTIONS ] [ FILTER ]\n"
3247 " -h, --help this message\n"
3248 " -V, --version output version information\n"
3249 " -n, --numeric don't resolve service names\n"
3250 " -r, --resolve resolve host names\n"
3251 " -a, --all display all sockets\n"
3252 " -l, --listening display listening sockets\n"
3253 " -o, --options show timer information\n"
3254 " -e, --extended show detailed socket information\n"
3255 " -m, --memory show socket memory usage\n"
3256 " -p, --processes show process using socket\n"
3257 " -i, --info show internal TCP information\n"
3258 " -s, --summary show socket usage summary\n"
3259 " -b, --bpf show bpf filter socket information\n"
3260 " -Z, --context display process SELinux security contexts\n"
3261 " -z, --contexts display process and socket SELinux security contexts\n"
3262 " -N, --net switch to the specified network namespace name\n"
3264 " -4, --ipv4 display only IP version 4 sockets\n"
3265 " -6, --ipv6 display only IP version 6 sockets\n"
3266 " -0, --packet display PACKET sockets\n"
3267 " -t, --tcp display only TCP sockets\n"
3268 " -u, --udp display only UDP sockets\n"
3269 " -d, --dccp display only DCCP sockets\n"
3270 " -w, --raw display only RAW sockets\n"
3271 " -x, --unix display only Unix domain sockets\n"
3272 " -f, --family=FAMILY display sockets of type FAMILY\n"
3274 " -A, --query=QUERY, --socket=QUERY\n"
3275 " QUERY := {all|inet|tcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink}[,QUERY]\n"
3277 " -D, --diag=FILE Dump raw information about TCP sockets to FILE\n"
3278 " -F, --filter=FILE read filter information from FILE\n"
3279 " FILTER := [ state STATE-FILTER ] [ EXPRESSION ]\n"
3280 " STATE-FILTER := {all|connected|synchronized|bucket|big|TCP-STATES}\n"
3281 " TCP-STATES := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|closed|close-wait|last-ack|listen|closing}\n"
3282 " connected := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}\n"
3283 " synchronized := {established|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}\n"
3284 " bucket := {syn-recv|time-wait}\n"
3285 " big := {established|syn-sent|fin-wait-{1,2}|closed|close-wait|last-ack|listen|closing}\n"
3289 static void help(void) __attribute__((noreturn
));
3290 static void help(void)
3296 static void usage(void) __attribute__((noreturn
));
3297 static void usage(void)
3304 static int scan_state(const char *state
)
3307 if (strcasecmp(state
, "close") == 0 ||
3308 strcasecmp(state
, "closed") == 0)
3309 return (1<<SS_CLOSE
);
3310 if (strcasecmp(state
, "syn-rcv") == 0)
3311 return (1<<SS_SYN_RECV
);
3312 if (strcasecmp(state
, "established") == 0)
3313 return (1<<SS_ESTABLISHED
);
3314 if (strcasecmp(state
, "all") == 0)
3316 if (strcasecmp(state
, "connected") == 0)
3317 return SS_ALL
& ~((1<<SS_CLOSE
)|(1<<SS_LISTEN
));
3318 if (strcasecmp(state
, "synchronized") == 0)
3319 return SS_ALL
& ~((1<<SS_CLOSE
)|(1<<SS_LISTEN
)|(1<<SS_SYN_SENT
));
3320 if (strcasecmp(state
, "bucket") == 0)
3321 return (1<<SS_SYN_RECV
)|(1<<SS_TIME_WAIT
);
3322 if (strcasecmp(state
, "big") == 0)
3323 return SS_ALL
& ~((1<<SS_SYN_RECV
)|(1<<SS_TIME_WAIT
));
3324 for (i
=0; i
<SS_MAX
; i
++) {
3325 if (strcasecmp(state
, sstate_namel
[i
]) == 0)
3329 fprintf(stderr
, "ss: wrong state name: %s\n", state
);
3333 static const struct option long_opts
[] = {
3334 { "numeric", 0, 0, 'n' },
3335 { "resolve", 0, 0, 'r' },
3336 { "options", 0, 0, 'o' },
3337 { "extended", 0, 0, 'e' },
3338 { "memory", 0, 0, 'm' },
3339 { "info", 0, 0, 'i' },
3340 { "processes", 0, 0, 'p' },
3341 { "bpf", 0, 0, 'b' },
3342 { "dccp", 0, 0, 'd' },
3343 { "tcp", 0, 0, 't' },
3344 { "udp", 0, 0, 'u' },
3345 { "raw", 0, 0, 'w' },
3346 { "unix", 0, 0, 'x' },
3347 { "all", 0, 0, 'a' },
3348 { "listening", 0, 0, 'l' },
3349 { "ipv4", 0, 0, '4' },
3350 { "ipv6", 0, 0, '6' },
3351 { "packet", 0, 0, '0' },
3352 { "family", 1, 0, 'f' },
3353 { "socket", 1, 0, 'A' },
3354 { "query", 1, 0, 'A' },
3355 { "summary", 0, 0, 's' },
3356 { "diag", 1, 0, 'D' },
3357 { "filter", 1, 0, 'F' },
3358 { "version", 0, 0, 'V' },
3359 { "help", 0, 0, 'h' },
3360 { "context", 0, 0, 'Z' },
3361 { "contexts", 0, 0, 'z' },
3362 { "net", 1, 0, 'N' },
3367 int main(int argc
, char *argv
[])
3372 const char *dump_tcpdiag
= NULL
;
3373 FILE *filter_fp
= NULL
;
3375 struct filter dbs_filter
= {};
3376 int state_filter
= 0;
3378 while ((ch
= getopt_long(argc
, argv
, "dhaletuwxnro460spbf:miA:D:F:vVzZN:",
3379 long_opts
, NULL
)) != EOF
) {
3382 resolve_services
= 0;
3402 user_ent_hash_build();
3409 filter_db_set(&dbs_filter
, DCCP_DB
);
3412 filter_db_set(&dbs_filter
, TCP_DB
);
3415 filter_db_set(&dbs_filter
, UDP_DB
);
3418 filter_db_set(&dbs_filter
, RAW_DB
);
3421 filter_af_set(¤t_filter
, AF_UNIX
);
3424 state_filter
= SS_ALL
;
3427 state_filter
= (1 << SS_LISTEN
) | (1 << SS_CLOSE
);
3430 filter_af_set(¤t_filter
, AF_INET
);
3433 filter_af_set(¤t_filter
, AF_INET6
);
3436 filter_af_set(¤t_filter
, AF_PACKET
);
3439 if (strcmp(optarg
, "inet") == 0)
3440 filter_af_set(¤t_filter
, AF_INET
);
3441 else if (strcmp(optarg
, "inet6") == 0)
3442 filter_af_set(¤t_filter
, AF_INET6
);
3443 else if (strcmp(optarg
, "link") == 0)
3444 filter_af_set(¤t_filter
, AF_PACKET
);
3445 else if (strcmp(optarg
, "unix") == 0)
3446 filter_af_set(¤t_filter
, AF_UNIX
);
3447 else if (strcmp(optarg
, "netlink") == 0)
3448 filter_af_set(¤t_filter
, AF_NETLINK
);
3449 else if (strcmp(optarg
, "help") == 0)
3452 fprintf(stderr
, "ss: \"%s\" is invalid family\n",
3461 current_filter
.dbs
= 0;
3467 if ((p1
= strchr(p
, ',')) != NULL
)
3469 if (strcmp(p
, "all") == 0) {
3470 filter_default_dbs(&dbs_filter
);
3471 } else if (strcmp(p
, "inet") == 0) {
3472 filter_db_set(&dbs_filter
, UDP_DB
);
3473 filter_db_set(&dbs_filter
, DCCP_DB
);
3474 filter_db_set(&dbs_filter
, TCP_DB
);
3475 filter_db_set(&dbs_filter
, RAW_DB
);
3476 } else if (strcmp(p
, "udp") == 0) {
3477 filter_db_set(&dbs_filter
, UDP_DB
);
3478 } else if (strcmp(p
, "dccp") == 0) {
3479 filter_db_set(&dbs_filter
, DCCP_DB
);
3480 } else if (strcmp(p
, "tcp") == 0) {
3481 filter_db_set(&dbs_filter
, TCP_DB
);
3482 } else if (strcmp(p
, "raw") == 0) {
3483 filter_db_set(&dbs_filter
, RAW_DB
);
3484 } else if (strcmp(p
, "unix") == 0) {
3485 filter_db_set(&dbs_filter
, UNIX_ST_DB
);
3486 filter_db_set(&dbs_filter
, UNIX_DG_DB
);
3487 filter_db_set(&dbs_filter
, UNIX_SQ_DB
);
3488 } else if (strcasecmp(p
, "unix_stream") == 0 ||
3489 strcmp(p
, "u_str") == 0) {
3490 filter_db_set(&dbs_filter
, UNIX_ST_DB
);
3491 } else if (strcasecmp(p
, "unix_dgram") == 0 ||
3492 strcmp(p
, "u_dgr") == 0) {
3493 filter_db_set(&dbs_filter
, UNIX_DG_DB
);
3494 } else if (strcasecmp(p
, "unix_seqpacket") == 0 ||
3495 strcmp(p
, "u_seq") == 0) {
3496 filter_db_set(&dbs_filter
, UNIX_SQ_DB
);
3497 } else if (strcmp(p
, "packet") == 0) {
3498 filter_db_set(&dbs_filter
, PACKET_R_DB
);
3499 filter_db_set(&dbs_filter
, PACKET_DG_DB
);
3500 } else if (strcmp(p
, "packet_raw") == 0 ||
3501 strcmp(p
, "p_raw") == 0) {
3502 filter_db_set(&dbs_filter
, PACKET_R_DB
);
3503 } else if (strcmp(p
, "packet_dgram") == 0 ||
3504 strcmp(p
, "p_dgr") == 0) {
3505 filter_db_set(&dbs_filter
, PACKET_DG_DB
);
3506 } else if (strcmp(p
, "netlink") == 0) {
3507 filter_db_set(&dbs_filter
, NETLINK_DB
);
3509 fprintf(stderr
, "ss: \"%s\" is illegal socket table id\n", p
);
3520 dump_tcpdiag
= optarg
;
3524 fprintf(stderr
, "More than one filter file\n");
3527 if (optarg
[0] == '-')
3530 filter_fp
= fopen(optarg
, "r");
3532 perror("fopen filter file");
3538 printf("ss utility, iproute2-ss%s\n", SNAPSHOT
);
3543 if (is_selinux_enabled() <= 0) {
3544 fprintf(stderr
, "ss: SELinux is not enabled.\n");
3548 user_ent_hash_build();
3551 if (netns_switch(optarg
))
3565 get_slabstat(&slabstat
);
3569 if (do_default
&& argc
== 0)
3573 /* Now parse filter... */
3574 if (argc
== 0 && filter_fp
) {
3575 if (ssfilter_parse(¤t_filter
.f
, 0, NULL
, filter_fp
))
3580 if (strcmp(*argv
, "state") == 0) {
3584 state_filter
|= scan_state(*argv
);
3586 } else if (strcmp(*argv
, "exclude") == 0 ||
3587 strcmp(*argv
, "excl") == 0) {
3590 state_filter
= SS_ALL
;
3591 state_filter
&= ~scan_state(*argv
);
3600 state_filter
= state_filter
? state_filter
: SS_CONN
;
3601 filter_default_dbs(¤t_filter
);
3602 filter_merge(¤t_filter
, ¤t_filter
, state_filter
);
3604 filter_merge(¤t_filter
, &dbs_filter
, state_filter
);
3607 if (resolve_services
&& resolve_hosts
&&
3608 (current_filter
.dbs
&(UNIX_DBM
|(1<<TCP_DB
)|(1<<UDP_DB
)|(1<<DCCP_DB
))))
3609 init_service_resolver();
3612 if (current_filter
.dbs
== 0) {
3613 fprintf(stderr
, "ss: no socket tables to show with such filter.\n");
3616 if (current_filter
.families
== 0) {
3617 fprintf(stderr
, "ss: no families to show with such filter.\n");
3620 if (current_filter
.states
== 0) {
3621 fprintf(stderr
, "ss: no socket states to show with such filter.\n");
3626 FILE *dump_fp
= stdout
;
3627 if (!(current_filter
.dbs
& (1<<TCP_DB
))) {
3628 fprintf(stderr
, "ss: tcpdiag dump requested and no tcp in filter.\n");
3631 if (dump_tcpdiag
[0] != '-') {
3632 dump_fp
= fopen(dump_tcpdiag
, "w");
3633 if (!dump_tcpdiag
) {
3634 perror("fopen dump file");
3638 inet_show_netlink(¤t_filter
, dump_fp
, IPPROTO_TCP
);
3643 if (ssfilter_parse(¤t_filter
.f
, argc
, argv
, filter_fp
))
3647 if (current_filter
.dbs
&(current_filter
.dbs
-1))
3651 if (current_filter
.states
&(current_filter
.states
-1))
3655 if (isatty(STDOUT_FILENO
)) {
3658 if (ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &w
) != -1) {
3660 screen_width
= w
.ws_col
;
3664 addrp_width
= screen_width
;
3665 addrp_width
-= netid_width
+1;
3666 addrp_width
-= state_width
+1;
3669 if (addrp_width
&1) {
3672 else if (state_width
)
3679 serv_width
= resolve_services
? 7 : 5;
3681 if (addrp_width
< 15+serv_width
+1)
3682 addrp_width
= 15+serv_width
+1;
3684 addr_width
= addrp_width
- serv_width
- 1;
3687 printf("%-*s ", netid_width
, "Netid");
3689 printf("%-*s ", state_width
, "State");
3690 printf("%-6s %-6s ", "Recv-Q", "Send-Q");
3692 /* Make enough space for the local/remote port field */
3696 printf("%*s:%-*s %*s:%-*s\n",
3697 addr_width
, "Local Address", serv_width
, "Port",
3698 addr_width
, "Peer Address", serv_width
, "Port");
3702 if (current_filter
.dbs
& (1<<NETLINK_DB
))
3703 netlink_show(¤t_filter
);
3704 if (current_filter
.dbs
& PACKET_DBM
)
3705 packet_show(¤t_filter
);
3706 if (current_filter
.dbs
& UNIX_DBM
)
3707 unix_show(¤t_filter
);
3708 if (current_filter
.dbs
& (1<<RAW_DB
))
3709 raw_show(¤t_filter
);
3710 if (current_filter
.dbs
& (1<<UDP_DB
))
3711 udp_show(¤t_filter
);
3712 if (current_filter
.dbs
& (1<<TCP_DB
))
3713 tcp_show(¤t_filter
, IPPROTO_TCP
);
3714 if (current_filter
.dbs
& (1<<DCCP_DB
))
3715 tcp_show(¤t_filter
, IPPROTO_DCCP
);
3717 if (show_users
|| show_proc_ctx
|| show_sock_ctx
)