]>
git.proxmox.com Git - mirror_iproute2.git/blob - misc/ss.c
ce6a0a8d8fa17c0e5fbdbffb8a2aaa46c13e5412
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>
32 #include "libnetlink.h"
35 #include <linux/tcp.h>
36 #include <linux/sock_diag.h>
37 #include <linux/inet_diag.h>
38 #include <linux/unix_diag.h>
39 #include <linux/netdevice.h> /* for MAX_ADDR_LEN */
40 #include <linux/filter.h>
41 #include <linux/packet_diag.h>
42 #include <linux/netlink_diag.h>
44 int resolve_hosts
= 0;
45 int resolve_services
= 1;
46 int preferred_family
= AF_UNSPEC
;
61 static const char *TCP_PROTO
= "tcp";
62 static const char *UDP_PROTO
= "udp";
63 static const char *RAW_PROTO
= "raw";
64 static const char *dg_proto
= NULL
;
81 #define PACKET_DBM ((1<<PACKET_DG_DB)|(1<<PACKET_R_DB))
82 #define UNIX_DBM ((1<<UNIX_DG_DB)|(1<<UNIX_ST_DB)|(1<<UNIX_SQ_DB))
83 #define ALL_DB ((1<<MAX_DB)-1)
101 #define SS_ALL ((1<<SS_MAX)-1)
103 #include "ssfilter.h"
113 struct filter default_filter
= {
115 .states
= SS_ALL
& ~((1<<SS_LISTEN
)|(1<<SS_CLOSE
)|(1<<SS_TIME_WAIT
)|(1<<SS_SYN_RECV
)),
116 .families
= (1<<AF_INET
)|(1<<AF_INET6
),
119 struct filter current_filter
;
121 static FILE *generic_proc_open(const char *env
, const char *name
)
123 const char *p
= getenv(env
);
127 p
= getenv("PROC_ROOT") ? : "/proc";
128 snprintf(store
, sizeof(store
)-1, "%s/%s", p
, name
);
132 return fopen(p
, "r");
135 static FILE *net_tcp_open(void)
137 return generic_proc_open("PROC_NET_TCP", "net/tcp");
140 static FILE *net_tcp6_open(void)
142 return generic_proc_open("PROC_NET_TCP6", "net/tcp6");
145 static FILE *net_udp_open(void)
147 return generic_proc_open("PROC_NET_UDP", "net/udp");
150 static FILE *net_udp6_open(void)
152 return generic_proc_open("PROC_NET_UDP6", "net/udp6");
155 static FILE *net_raw_open(void)
157 return generic_proc_open("PROC_NET_RAW", "net/raw");
160 static FILE *net_raw6_open(void)
162 return generic_proc_open("PROC_NET_RAW6", "net/raw6");
165 static FILE *net_unix_open(void)
167 return generic_proc_open("PROC_NET_UNIX", "net/unix");
170 static FILE *net_packet_open(void)
172 return generic_proc_open("PROC_NET_PACKET", "net/packet");
175 static FILE *net_netlink_open(void)
177 return generic_proc_open("PROC_NET_NETLINK", "net/netlink");
180 static FILE *slabinfo_open(void)
182 return generic_proc_open("PROC_SLABINFO", "slabinfo");
185 static FILE *net_sockstat_open(void)
187 return generic_proc_open("PROC_NET_SOCKSTAT", "net/sockstat");
190 static FILE *net_sockstat6_open(void)
192 return generic_proc_open("PROC_NET_SOCKSTAT6", "net/sockstat6");
195 static FILE *net_snmp_open(void)
197 return generic_proc_open("PROC_NET_SNMP", "net/snmp");
200 static FILE *ephemeral_ports_open(void)
202 return generic_proc_open("PROC_IP_LOCAL_PORT_RANGE", "sys/net/ipv4/ip_local_port_range");
206 struct user_ent
*next
;
213 #define USER_ENT_HASH_SIZE 256
214 struct user_ent
*user_ent_hash
[USER_ENT_HASH_SIZE
];
216 static int user_ent_hashfn(unsigned int ino
)
218 int val
= (ino
>> 24) ^ (ino
>> 16) ^ (ino
>> 8) ^ ino
;
220 return val
& (USER_ENT_HASH_SIZE
- 1);
223 static void user_ent_add(unsigned int ino
, const char *process
, int pid
, int fd
)
225 struct user_ent
*p
, **pp
;
228 str_len
= strlen(process
) + 1;
229 p
= malloc(sizeof(struct user_ent
) + str_len
);
236 strcpy(p
->process
, process
);
238 pp
= &user_ent_hash
[user_ent_hashfn(ino
)];
243 static void user_ent_hash_build(void)
245 const char *root
= getenv("PROC_ROOT") ? : "/proc/";
252 if (strlen(name
) == 0 || name
[strlen(name
)-1] != '/')
255 nameoff
= strlen(name
);
261 while ((d
= readdir(dir
)) != NULL
) {
268 if (sscanf(d
->d_name
, "%d%c", &pid
, &crap
) != 1)
271 sprintf(name
+ nameoff
, "%d/fd/", pid
);
273 if ((dir1
= opendir(name
)) == NULL
)
278 while ((d1
= readdir(dir1
)) != NULL
) {
279 const char *pattern
= "socket:[";
285 if (sscanf(d1
->d_name
, "%d%c", &fd
, &crap
) != 1)
288 sprintf(name
+pos
, "%d", fd
);
290 link_len
= readlink(name
, lnk
, sizeof(lnk
)-1);
293 lnk
[link_len
] = '\0';
295 if (strncmp(lnk
, pattern
, strlen(pattern
)))
298 sscanf(lnk
, "socket:[%u]", &ino
);
300 if (process
[0] == '\0') {
304 snprintf(tmp
, sizeof(tmp
), "%s/%d/stat", root
, pid
);
305 if ((fp
= fopen(tmp
, "r")) != NULL
) {
306 fscanf(fp
, "%*d (%[^)])", process
);
311 user_ent_add(ino
, process
, pid
, fd
);
318 static int find_users(unsigned ino
, char *buf
, int buflen
)
327 p
= user_ent_hash
[user_ent_hashfn(ino
)];
333 if (ptr
- buf
>= buflen
- 1)
336 snprintf(ptr
, buflen
- (ptr
- buf
),
338 p
->process
, p
->pid
, p
->fd
);
352 /* Get stats from slab */
363 struct slabstat slabstat
;
365 static const char *slabstat_ids
[] =
374 static int get_slabstat(struct slabstat
*s
)
380 memset(s
, 0, sizeof(*s
));
382 fp
= slabinfo_open();
386 cnt
= sizeof(*s
)/sizeof(int);
388 fgets(buf
, sizeof(buf
), fp
);
389 while(fgets(buf
, sizeof(buf
), fp
) != NULL
) {
391 for (i
=0; i
<sizeof(slabstat_ids
)/sizeof(slabstat_ids
[0]); i
++) {
392 if (memcmp(buf
, slabstat_ids
[i
], strlen(slabstat_ids
[i
])) == 0) {
393 sscanf(buf
, "%*s%d", ((int *)s
) + i
);
406 static const char *sstate_name
[] = {
408 [SS_ESTABLISHED
] = "ESTAB",
409 [SS_SYN_SENT
] = "SYN-SENT",
410 [SS_SYN_RECV
] = "SYN-RECV",
411 [SS_FIN_WAIT1
] = "FIN-WAIT-1",
412 [SS_FIN_WAIT2
] = "FIN-WAIT-2",
413 [SS_TIME_WAIT
] = "TIME-WAIT",
414 [SS_CLOSE
] = "UNCONN",
415 [SS_CLOSE_WAIT
] = "CLOSE-WAIT",
416 [SS_LAST_ACK
] = "LAST-ACK",
417 [SS_LISTEN
] = "LISTEN",
418 [SS_CLOSING
] = "CLOSING",
421 static const char *sstate_namel
[] = {
423 [SS_ESTABLISHED
] = "established",
424 [SS_SYN_SENT
] = "syn-sent",
425 [SS_SYN_RECV
] = "syn-recv",
426 [SS_FIN_WAIT1
] = "fin-wait-1",
427 [SS_FIN_WAIT2
] = "fin-wait-2",
428 [SS_TIME_WAIT
] = "time-wait",
429 [SS_CLOSE
] = "unconnected",
430 [SS_CLOSE_WAIT
] = "close-wait",
431 [SS_LAST_ACK
] = "last-ack",
432 [SS_LISTEN
] = "listening",
433 [SS_CLOSING
] = "closing",
451 unsigned long long sk
;
452 int rto
, ato
, qack
, cwnd
, ssthresh
;
455 static const char *tmr_name
[] = {
464 static const char *print_ms_timer(int timeout
)
467 int secs
, msecs
, minutes
;
473 msecs
= timeout
%1000;
477 snprintf(buf
, sizeof(buf
)-16, "%dmin", minutes
);
484 sprintf(buf
+strlen(buf
), "%d%s", secs
, msecs
? "." : "sec");
487 sprintf(buf
+strlen(buf
), "%03dms", msecs
);
491 static const char *print_hz_timer(int timeout
)
493 int hz
= get_user_hz();
494 return print_ms_timer(((timeout
*1000) + hz
-1)/hz
);
505 struct scache
*rlist
;
507 static void init_service_resolver(void)
510 FILE *fp
= popen("/usr/sbin/rpcinfo -p 2>/dev/null", "r");
512 fgets(buf
, sizeof(buf
), fp
);
513 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
514 unsigned int progn
, port
;
515 char proto
[128], prog
[128];
516 if (sscanf(buf
, "%u %*d %s %u %s", &progn
, proto
,
517 &port
, prog
+4) == 4) {
518 struct scache
*c
= malloc(sizeof(*c
));
521 memcpy(prog
, "rpc.", 4);
522 c
->name
= strdup(prog
);
523 if (strcmp(proto
, TCP_PROTO
) == 0)
524 c
->proto
= TCP_PROTO
;
525 else if (strcmp(proto
, UDP_PROTO
) == 0)
526 c
->proto
= UDP_PROTO
;
538 static int ip_local_port_min
, ip_local_port_max
;
540 /* Even do not try default linux ephemeral port ranges:
541 * default /etc/services contains so much of useless crap
542 * wouldbe "allocated" to this area that resolution
543 * is really harmful. I shrug each time when seeing
544 * "socks" or "cfinger" in dumps.
546 static int is_ephemeral(int port
)
548 if (!ip_local_port_min
) {
549 FILE *f
= ephemeral_ports_open();
552 &ip_local_port_min
, &ip_local_port_max
);
555 ip_local_port_min
= 1024;
556 ip_local_port_max
= 4999;
560 return (port
>= ip_local_port_min
&& port
<= ip_local_port_max
);
564 static const char *__resolve_service(int port
)
568 for (c
= rlist
; c
; c
= c
->next
) {
569 if (c
->port
== port
&& c
->proto
== dg_proto
)
573 if (!is_ephemeral(port
)) {
580 se
= getservbyport(htons(port
), dg_proto
);
589 static const char *resolve_service(int port
)
591 static char buf
[128];
592 static struct scache cache
[256];
600 if (resolve_services
) {
601 if (dg_proto
== RAW_PROTO
) {
602 return inet_proto_n2a(port
, buf
, sizeof(buf
));
606 int hash
= (port
^(((unsigned long)dg_proto
)>>2))&255;
608 for (c
= &cache
[hash
]; c
; c
= c
->next
) {
609 if (c
->port
== port
&&
610 c
->proto
== dg_proto
) {
617 if ((res
= __resolve_service(port
)) != NULL
) {
618 if ((c
= malloc(sizeof(*c
))) == NULL
)
629 c
->name
= strdup(res
);
630 c
->next
= cache
[hash
].next
;
631 cache
[hash
].next
= c
;
639 sprintf(buf
, "%u", port
);
643 static void formatted_print(const inet_prefix
*a
, int port
, unsigned int ifindex
)
646 const char *ap
= buf
;
649 est_len
= addr_width
;
651 if (a
->family
== AF_INET
) {
652 if (a
->data
[0] == 0) {
656 ap
= format_host(AF_INET
, 4, a
->data
, buf
, sizeof(buf
));
659 ap
= format_host(a
->family
, 16, a
->data
, buf
, sizeof(buf
));
660 est_len
= strlen(ap
);
661 if (est_len
<= addr_width
)
662 est_len
= addr_width
;
664 est_len
= addr_width
+ ((est_len
-addr_width
+3)/4)*4;
667 const char *ifname
= ll_index_to_name(ifindex
);
668 const int len
= strlen(ifname
) + 1; /* +1 for percent char */
670 printf("%*s%%%s:%-*s ", est_len
- len
, ap
, ifname
, serv_width
,
671 resolve_service(port
));
673 printf("%*s:%-*s ", est_len
, ap
, serv_width
, resolve_service(port
));
680 struct aafilter
*next
;
683 static int inet2_addr_match(const inet_prefix
*a
, const inet_prefix
*p
,
686 if (!inet_addr_match(a
, p
, plen
))
689 /* Cursed "v4 mapped" addresses: v4 mapped socket matches
690 * pure IPv4 rule, but v4-mapped rule selects only v4-mapped
692 if (p
->family
== AF_INET
&& a
->family
== AF_INET6
) {
693 if (a
->data
[0] == 0 && a
->data
[1] == 0 &&
694 a
->data
[2] == htonl(0xffff)) {
695 inet_prefix tmp
= *a
;
696 tmp
.data
[0] = a
->data
[3];
697 return inet_addr_match(&tmp
, p
, plen
);
703 static int unix_match(const inet_prefix
*a
, const inet_prefix
*p
)
705 char *addr
, *pattern
;
706 memcpy(&addr
, a
->data
, sizeof(addr
));
707 memcpy(&pattern
, p
->data
, sizeof(pattern
));
712 return !fnmatch(pattern
, addr
, 0);
715 static int run_ssfilter(struct ssfilter
*f
, struct tcpstat
*s
)
720 static int low
, high
=65535;
722 if (s
->local
.family
== AF_UNIX
) {
724 memcpy(&p
, s
->local
.data
, sizeof(p
));
725 return p
== NULL
|| (p
[0] == '@' && strlen(p
) == 6 &&
726 strspn(p
+1, "0123456789abcdef") == 5);
728 if (s
->local
.family
== AF_PACKET
)
729 return s
->lport
== 0 && s
->local
.data
== 0;
730 if (s
->local
.family
== AF_NETLINK
)
734 FILE *fp
= ephemeral_ports_open();
736 fscanf(fp
, "%d%d", &low
, &high
);
740 return s
->lport
>= low
&& s
->lport
<= high
;
744 struct aafilter
*a
= (void*)f
->pred
;
745 if (a
->addr
.family
== AF_UNIX
)
746 return unix_match(&s
->remote
, &a
->addr
);
747 if (a
->port
!= -1 && a
->port
!= s
->rport
)
749 if (a
->addr
.bitlen
) {
751 if (!inet2_addr_match(&s
->remote
, &a
->addr
, a
->addr
.bitlen
))
753 } while ((a
= a
->next
) != NULL
);
760 struct aafilter
*a
= (void*)f
->pred
;
761 if (a
->addr
.family
== AF_UNIX
)
762 return unix_match(&s
->local
, &a
->addr
);
763 if (a
->port
!= -1 && a
->port
!= s
->lport
)
765 if (a
->addr
.bitlen
) {
767 if (!inet2_addr_match(&s
->local
, &a
->addr
, a
->addr
.bitlen
))
769 } while ((a
= a
->next
) != NULL
);
776 struct aafilter
*a
= (void*)f
->pred
;
777 return s
->rport
>= a
->port
;
781 struct aafilter
*a
= (void*)f
->pred
;
782 return s
->rport
<= a
->port
;
786 struct aafilter
*a
= (void*)f
->pred
;
787 return s
->lport
>= a
->port
;
791 struct aafilter
*a
= (void*)f
->pred
;
792 return s
->lport
<= a
->port
;
795 /* Yup. It is recursion. Sorry. */
797 return run_ssfilter(f
->pred
, s
) && run_ssfilter(f
->post
, s
);
799 return run_ssfilter(f
->pred
, s
) || run_ssfilter(f
->post
, s
);
801 return !run_ssfilter(f
->pred
, s
);
807 /* Relocate external jumps by reloc. */
808 static void ssfilter_patch(char *a
, int len
, int reloc
)
811 struct inet_diag_bc_op
*op
= (struct inet_diag_bc_op
*)a
;
821 static int ssfilter_bytecompile(struct ssfilter
*f
, char **bytecode
)
826 if (!(*bytecode
=malloc(4))) abort();
827 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_AUTO
, 4, 8 };
833 struct aafilter
*a
= (void*)f
->pred
;
836 int code
= (f
->type
== SSF_DCOND
? INET_DIAG_BC_D_COND
: INET_DIAG_BC_S_COND
);
839 for (b
=a
; b
; b
=b
->next
) {
840 len
+= 4 + sizeof(struct inet_diag_hostcond
);
841 if (a
->addr
.family
== AF_INET6
)
848 if (!(ptr
= malloc(len
))) abort();
850 for (b
=a
; b
; b
=b
->next
) {
851 struct inet_diag_bc_op
*op
= (struct inet_diag_bc_op
*)ptr
;
852 int alen
= (a
->addr
.family
== AF_INET6
? 16 : 4);
853 int oplen
= alen
+ 4 + sizeof(struct inet_diag_hostcond
);
854 struct inet_diag_hostcond
*cond
= (struct inet_diag_hostcond
*)(ptr
+4);
856 *op
= (struct inet_diag_bc_op
){ code
, oplen
, oplen
+4 };
857 cond
->family
= a
->addr
.family
;
858 cond
->port
= a
->port
;
859 cond
->prefix_len
= a
->addr
.bitlen
;
860 memcpy(cond
->addr
, a
->addr
.data
, alen
);
863 op
= (struct inet_diag_bc_op
*)ptr
;
864 *op
= (struct inet_diag_bc_op
){ INET_DIAG_BC_JMP
, 4, len
- (ptr
-*bytecode
)};
868 return ptr
- *bytecode
;
872 struct aafilter
*x
= (void*)f
->pred
;
873 if (!(*bytecode
=malloc(8))) abort();
874 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_D_GE
, 8, 12 };
875 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
880 struct aafilter
*x
= (void*)f
->pred
;
881 if (!(*bytecode
=malloc(8))) abort();
882 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_D_LE
, 8, 12 };
883 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
888 struct aafilter
*x
= (void*)f
->pred
;
889 if (!(*bytecode
=malloc(8))) abort();
890 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_S_GE
, 8, 12 };
891 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
896 struct aafilter
*x
= (void*)f
->pred
;
897 if (!(*bytecode
=malloc(8))) abort();
898 ((struct inet_diag_bc_op
*)*bytecode
)[0] = (struct inet_diag_bc_op
){ INET_DIAG_BC_S_LE
, 8, 12 };
899 ((struct inet_diag_bc_op
*)*bytecode
)[1] = (struct inet_diag_bc_op
){ 0, 0, x
->port
};
907 l1
= ssfilter_bytecompile(f
->pred
, &a1
);
908 l2
= ssfilter_bytecompile(f
->post
, &a2
);
909 if (!(a
= malloc(l1
+l2
))) abort();
911 memcpy(a
+l1
, a2
, l2
);
913 ssfilter_patch(a
, l1
, l2
);
921 l1
= ssfilter_bytecompile(f
->pred
, &a1
);
922 l2
= ssfilter_bytecompile(f
->post
, &a2
);
923 if (!(a
= malloc(l1
+l2
+4))) abort();
925 memcpy(a
+l1
+4, a2
, l2
);
927 *(struct inet_diag_bc_op
*)(a
+l1
) = (struct inet_diag_bc_op
){ INET_DIAG_BC_JMP
, 4, l2
+4 };
935 l1
= ssfilter_bytecompile(f
->pred
, &a1
);
936 if (!(a
= malloc(l1
+4))) abort();
939 *(struct inet_diag_bc_op
*)(a
+l1
) = (struct inet_diag_bc_op
){ INET_DIAG_BC_JMP
, 4, 8 };
948 static int remember_he(struct aafilter
*a
, struct hostent
*he
)
950 char **ptr
= he
->h_addr_list
;
954 if (he
->h_addrtype
== AF_INET
)
956 else if (he
->h_addrtype
== AF_INET6
)
962 struct aafilter
*b
= a
;
963 if (a
->addr
.bitlen
) {
964 if ((b
= malloc(sizeof(*b
))) == NULL
)
970 memcpy(b
->addr
.data
, *ptr
, len
);
971 b
->addr
.bytelen
= len
;
972 b
->addr
.bitlen
= len
*8;
973 b
->addr
.family
= he
->h_addrtype
;
980 static int get_dns_host(struct aafilter
*a
, const char *addr
, int fam
)
991 he
= gethostbyname2(addr
, fam
== AF_UNSPEC
? AF_INET
: fam
);
993 cnt
= remember_he(a
, he
);
994 if (fam
== AF_UNSPEC
) {
995 he
= gethostbyname2(addr
, AF_INET6
);
997 cnt
+= remember_he(a
, he
);
1002 static int xll_initted
= 0;
1004 static void xll_init(void)
1006 struct rtnl_handle rth
;
1007 if (rtnl_open(&rth
, 0) < 0)
1015 static const char *xll_index_to_name(int index
)
1019 return ll_index_to_name(index
);
1022 static int xll_name_to_index(const char *dev
)
1026 return ll_name_to_index(dev
);
1029 void *parse_hostcond(char *addr
)
1033 struct aafilter
*res
;
1034 int fam
= preferred_family
;
1036 memset(&a
, 0, sizeof(a
));
1039 if (fam
== AF_UNIX
|| strncmp(addr
, "unix:", 5) == 0) {
1041 a
.addr
.family
= AF_UNIX
;
1042 if (strncmp(addr
, "unix:", 5) == 0)
1045 a
.addr
.bitlen
= 8*strlen(p
);
1046 memcpy(a
.addr
.data
, &p
, sizeof(p
));
1050 if (fam
== AF_PACKET
|| strncmp(addr
, "link:", 5) == 0) {
1051 a
.addr
.family
= AF_PACKET
;
1053 if (strncmp(addr
, "link:", 5) == 0)
1055 port
= strchr(addr
, ':');
1058 if (port
[1] && strcmp(port
+1, "*")) {
1059 if (get_integer(&a
.port
, port
+1, 0)) {
1060 if ((a
.port
= xll_name_to_index(port
+1)) <= 0)
1065 if (addr
[0] && strcmp(addr
, "*")) {
1068 if (ll_proto_a2n(&tmp
, addr
))
1070 a
.addr
.data
[0] = ntohs(tmp
);
1075 if (fam
== AF_NETLINK
|| strncmp(addr
, "netlink:", 8) == 0) {
1076 a
.addr
.family
= AF_NETLINK
;
1078 if (strncmp(addr
, "netlink:", 8) == 0)
1080 port
= strchr(addr
, ':');
1083 if (port
[1] && strcmp(port
+1, "*")) {
1084 if (get_integer(&a
.port
, port
+1, 0)) {
1085 if (strcmp(port
+1, "kernel") == 0)
1092 if (addr
[0] && strcmp(addr
, "*")) {
1094 if (get_u32(a
.addr
.data
, addr
, 0)) {
1095 if (strcmp(addr
, "rtnl") == 0)
1097 else if (strcmp(addr
, "fw") == 0)
1099 else if (strcmp(addr
, "tcpdiag") == 0)
1108 if (strncmp(addr
, "inet:", 5) == 0) {
1111 } else if (strncmp(addr
, "inet6:", 6) == 0) {
1116 /* URL-like literal [] */
1117 if (addr
[0] == '[') {
1119 if ((port
= strchr(addr
, ']')) == NULL
)
1122 } else if (addr
[0] == '*') {
1125 port
= strrchr(strchr(addr
, '/') ? : addr
, ':');
1127 if (port
&& *port
) {
1131 if (*port
&& *port
!= '*') {
1132 if (get_integer(&a
.port
, port
, 0)) {
1133 struct servent
*se1
= NULL
;
1134 struct servent
*se2
= NULL
;
1135 if (current_filter
.dbs
&(1<<UDP_DB
))
1136 se1
= getservbyname(port
, UDP_PROTO
);
1137 if (current_filter
.dbs
&(1<<TCP_DB
))
1138 se2
= getservbyname(port
, TCP_PROTO
);
1139 if (se1
&& se2
&& se1
->s_port
!= se2
->s_port
) {
1140 fprintf(stderr
, "Error: ambiguous port \"%s\".\n", port
);
1146 a
.port
= ntohs(se1
->s_port
);
1149 for (s
= rlist
; s
; s
= s
->next
) {
1150 if ((s
->proto
== UDP_PROTO
&&
1151 (current_filter
.dbs
&(1<<UDP_DB
))) ||
1152 (s
->proto
== TCP_PROTO
&&
1153 (current_filter
.dbs
&(1<<TCP_DB
)))) {
1154 if (s
->name
&& strcmp(s
->name
, port
) == 0) {
1155 if (a
.port
> 0 && a
.port
!= s
->port
) {
1156 fprintf(stderr
, "Error: ambiguous port \"%s\".\n", port
);
1164 fprintf(stderr
, "Error: \"%s\" does not look like a port.\n", port
);
1171 if (addr
&& *addr
&& *addr
!= '*') {
1172 if (get_prefix_1(&a
.addr
, addr
, fam
)) {
1173 if (get_dns_host(&a
, addr
, fam
)) {
1174 fprintf(stderr
, "Error: an inet prefix is expected rather than \"%s\".\n", addr
);
1181 res
= malloc(sizeof(*res
));
1183 memcpy(res
, &a
, sizeof(a
));
1187 static int tcp_show_line(char *line
, const struct filter
*f
, int family
)
1190 char *loc
, *rem
, *data
;
1195 if ((p
= strchr(line
, ':')) == NULL
)
1199 if ((p
= strchr(loc
, ':')) == NULL
)
1204 if ((p
= strchr(rem
, ':')) == NULL
)
1210 int state
= (data
[1] >= 'A') ? (data
[1] - 'A' + 10) : (data
[1] - '0');
1212 if (!(f
->states
& (1<<state
)))
1216 s
.local
.family
= s
.remote
.family
= family
;
1217 if (family
== AF_INET
) {
1218 sscanf(loc
, "%x:%x", s
.local
.data
, (unsigned*)&s
.lport
);
1219 sscanf(rem
, "%x:%x", s
.remote
.data
, (unsigned*)&s
.rport
);
1220 s
.local
.bytelen
= s
.remote
.bytelen
= 4;
1222 sscanf(loc
, "%08x%08x%08x%08x:%x",
1228 sscanf(rem
, "%08x%08x%08x%08x:%x",
1234 s
.local
.bytelen
= s
.remote
.bytelen
= 16;
1237 if (f
->f
&& run_ssfilter(f
->f
, &s
) == 0)
1241 n
= sscanf(data
, "%x %x:%x %x:%x %x %d %d %u %d %llx %d %d %d %d %d %[^\n]\n",
1242 &s
.state
, &s
.wq
, &s
.rq
,
1243 &s
.timer
, &s
.timeout
, &s
.retrs
, &s
.uid
, &s
.probes
, &s
.ino
,
1244 &s
.refcnt
, &s
.sk
, &s
.rto
, &s
.ato
, &s
.qack
,
1245 &s
.cwnd
, &s
.ssthresh
, opt
);
1258 printf("%-*s ", netid_width
, "tcp");
1260 printf("%-*s ", state_width
, sstate_name
[s
.state
]);
1262 printf("%-6d %-6d ", s
.rq
, s
.wq
);
1264 formatted_print(&s
.local
, s
.lport
, 0);
1265 formatted_print(&s
.remote
, s
.rport
, 0);
1271 printf(" timer:(%s,%s,%d)",
1273 print_hz_timer(s
.timeout
),
1274 s
.timer
!= 1 ? s
.probes
: s
.retrs
);
1278 int hz
= get_user_hz();
1279 if (s
.rto
&& s
.rto
!= 3*hz
)
1280 printf(" rto:%g", (double)s
.rto
/hz
);
1282 printf(" ato:%g", (double)s
.ato
/hz
);
1284 printf(" cwnd:%d", s
.cwnd
);
1285 if (s
.ssthresh
!= -1)
1286 printf(" ssthresh:%d", s
.ssthresh
);
1288 printf(" qack:%d", s
.qack
/2);
1294 if (find_users(s
.ino
, ubuf
, sizeof(ubuf
)) > 0)
1295 printf(" users:(%s)", ubuf
);
1299 printf(" uid:%u", (unsigned)s
.uid
);
1300 printf(" ino:%u", s
.ino
);
1301 printf(" sk:%llx", s
.sk
);
1303 printf(" opt:\"%s\"", opt
);
1310 static int generic_record_read(FILE *fp
,
1311 int (*worker
)(char*, const struct filter
*, int),
1312 const struct filter
*f
, int fam
)
1317 if (fgets(line
, sizeof(line
), fp
) == NULL
)
1320 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
1321 int n
= strlen(line
);
1322 if (n
== 0 || line
[n
-1] != '\n') {
1328 if (worker(line
, f
, fam
) < 0)
1333 return ferror(fp
) ? -1 : 0;
1336 static char *sprint_bw(char *buf
, double bw
)
1339 sprintf(buf
,"%.1fM", bw
/ 1000000.);
1340 else if (bw
> 1000.)
1341 sprintf(buf
,"%.1fK", bw
/ 1000.);
1343 sprintf(buf
, "%g", bw
);
1348 static void print_skmeminfo(struct rtattr
*tb
[], int attrtype
)
1350 const __u32
*skmeminfo
;
1353 skmeminfo
= RTA_DATA(tb
[attrtype
]);
1355 printf(" skmem:(r%u,rb%u,t%u,tb%u,f%u,w%u,o%u",
1356 skmeminfo
[SK_MEMINFO_RMEM_ALLOC
],
1357 skmeminfo
[SK_MEMINFO_RCVBUF
],
1358 skmeminfo
[SK_MEMINFO_WMEM_ALLOC
],
1359 skmeminfo
[SK_MEMINFO_SNDBUF
],
1360 skmeminfo
[SK_MEMINFO_FWD_ALLOC
],
1361 skmeminfo
[SK_MEMINFO_WMEM_QUEUED
],
1362 skmeminfo
[SK_MEMINFO_OPTMEM
]);
1364 if (RTA_PAYLOAD(tb
[attrtype
]) >=
1365 (SK_MEMINFO_BACKLOG
+ 1) * sizeof(__u32
))
1366 printf(",bl%u", skmeminfo
[SK_MEMINFO_BACKLOG
]);
1371 static void tcp_show_info(const struct nlmsghdr
*nlh
, struct inet_diag_msg
*r
,
1372 struct rtattr
*tb
[])
1377 if (tb
[INET_DIAG_SKMEMINFO
]) {
1378 print_skmeminfo(tb
, INET_DIAG_SKMEMINFO
);
1379 } else if (tb
[INET_DIAG_MEMINFO
]) {
1380 const struct inet_diag_meminfo
*minfo
1381 = RTA_DATA(tb
[INET_DIAG_MEMINFO
]);
1382 printf(" mem:(r%u,w%u,f%u,t%u)",
1389 if (tb
[INET_DIAG_INFO
]) {
1390 struct tcp_info
*info
;
1391 int len
= RTA_PAYLOAD(tb
[INET_DIAG_INFO
]);
1393 /* workaround for older kernels with less fields */
1394 if (len
< sizeof(*info
)) {
1395 info
= alloca(sizeof(*info
));
1396 memset(info
, 0, sizeof(*info
));
1397 memcpy(info
, RTA_DATA(tb
[INET_DIAG_INFO
]), len
);
1399 info
= RTA_DATA(tb
[INET_DIAG_INFO
]);
1402 if (info
->tcpi_options
& TCPI_OPT_TIMESTAMPS
)
1404 if (info
->tcpi_options
& TCPI_OPT_SACK
)
1406 if (info
->tcpi_options
& TCPI_OPT_ECN
)
1408 if (info
->tcpi_options
& TCPI_OPT_ECN_SEEN
)
1410 if (info
->tcpi_options
& TCPI_OPT_SYN_DATA
)
1411 printf(" fastopen");
1414 if (tb
[INET_DIAG_CONG
])
1415 printf(" %s", rta_getattr_str(tb
[INET_DIAG_CONG
]));
1417 if (info
->tcpi_options
& TCPI_OPT_WSCALE
)
1418 printf(" wscale:%d,%d", info
->tcpi_snd_wscale
,
1419 info
->tcpi_rcv_wscale
);
1420 if (info
->tcpi_rto
&& info
->tcpi_rto
!= 3000000)
1421 printf(" rto:%g", (double)info
->tcpi_rto
/1000);
1423 printf(" rtt:%g/%g", (double)info
->tcpi_rtt
/1000,
1424 (double)info
->tcpi_rttvar
/1000);
1426 printf(" ato:%g", (double)info
->tcpi_ato
/1000);
1427 if (info
->tcpi_snd_mss
)
1428 printf(" mss:%d", info
->tcpi_snd_mss
);
1429 if (info
->tcpi_snd_cwnd
!= 2)
1430 printf(" cwnd:%d", info
->tcpi_snd_cwnd
);
1431 if (info
->tcpi_snd_ssthresh
< 0xFFFF)
1432 printf(" ssthresh:%d", info
->tcpi_snd_ssthresh
);
1434 rtt
= (double) info
->tcpi_rtt
;
1435 if (tb
[INET_DIAG_VEGASINFO
]) {
1436 const struct tcpvegas_info
*vinfo
1437 = RTA_DATA(tb
[INET_DIAG_VEGASINFO
]);
1439 if (vinfo
->tcpv_enabled
&&
1440 vinfo
->tcpv_rtt
&& vinfo
->tcpv_rtt
!= 0x7fffffff)
1441 rtt
= vinfo
->tcpv_rtt
;
1444 if (rtt
> 0 && info
->tcpi_snd_mss
&& info
->tcpi_snd_cwnd
) {
1445 printf(" send %sbps",
1446 sprint_bw(b1
, (double) info
->tcpi_snd_cwnd
*
1447 (double) info
->tcpi_snd_mss
* 8000000.
1451 if (info
->tcpi_unacked
)
1452 printf(" unacked:%u", info
->tcpi_unacked
);
1453 if (info
->tcpi_retrans
|| info
->tcpi_total_retrans
)
1454 printf(" retrans:%u/%u", info
->tcpi_retrans
,
1455 info
->tcpi_total_retrans
);
1456 if (info
->tcpi_lost
)
1457 printf(" lost:%u", info
->tcpi_lost
);
1458 if (info
->tcpi_sacked
&& r
->idiag_state
!= SS_LISTEN
)
1459 printf(" sacked:%u", info
->tcpi_sacked
);
1460 if (info
->tcpi_fackets
)
1461 printf(" fackets:%u", info
->tcpi_fackets
);
1462 if (info
->tcpi_reordering
!= 3)
1463 printf(" reordering:%d", info
->tcpi_reordering
);
1464 if (info
->tcpi_rcv_rtt
)
1465 printf(" rcv_rtt:%g", (double) info
->tcpi_rcv_rtt
/1000);
1466 if (info
->tcpi_rcv_space
)
1467 printf(" rcv_space:%d", info
->tcpi_rcv_space
);
1472 static char *proto_name(int protocol
)
1486 static int inet_show_sock(struct nlmsghdr
*nlh
, struct filter
*f
, int protocol
)
1488 struct rtattr
* tb
[INET_DIAG_MAX
+1];
1489 struct inet_diag_msg
*r
= NLMSG_DATA(nlh
);
1492 parse_rtattr(tb
, INET_DIAG_MAX
, (struct rtattr
*)(r
+1),
1493 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
1495 s
.state
= r
->idiag_state
;
1496 s
.local
.family
= s
.remote
.family
= r
->idiag_family
;
1497 s
.lport
= ntohs(r
->id
.idiag_sport
);
1498 s
.rport
= ntohs(r
->id
.idiag_dport
);
1499 if (s
.local
.family
== AF_INET
) {
1500 s
.local
.bytelen
= s
.remote
.bytelen
= 4;
1502 s
.local
.bytelen
= s
.remote
.bytelen
= 16;
1504 memcpy(s
.local
.data
, r
->id
.idiag_src
, s
.local
.bytelen
);
1505 memcpy(s
.remote
.data
, r
->id
.idiag_dst
, s
.local
.bytelen
);
1507 if (f
&& f
->f
&& run_ssfilter(f
->f
, &s
) == 0)
1511 printf("%-*s ", netid_width
, proto_name(protocol
));
1513 printf("%-*s ", state_width
, sstate_name
[s
.state
]);
1515 printf("%-6d %-6d ", r
->idiag_rqueue
, r
->idiag_wqueue
);
1517 formatted_print(&s
.local
, s
.lport
, r
->id
.idiag_if
);
1518 formatted_print(&s
.remote
, s
.rport
, 0);
1521 if (r
->idiag_timer
) {
1522 if (r
->idiag_timer
> 4)
1524 printf(" timer:(%s,%s,%d)",
1525 tmr_name
[r
->idiag_timer
],
1526 print_ms_timer(r
->idiag_expires
),
1532 if (find_users(r
->idiag_inode
, ubuf
, sizeof(ubuf
)) > 0)
1533 printf(" users:(%s)", ubuf
);
1537 printf(" uid:%u", (unsigned)r
->idiag_uid
);
1538 printf(" ino:%u", r
->idiag_inode
);
1540 if (r
->id
.idiag_cookie
[1] != 0)
1541 printf("%08x", r
->id
.idiag_cookie
[1]);
1542 printf("%08x", r
->id
.idiag_cookie
[0]);
1543 if (tb
[INET_DIAG_SHUTDOWN
]) {
1545 mask
= *(__u8
*)RTA_DATA(tb
[INET_DIAG_SHUTDOWN
]);
1546 printf(" %c-%c", mask
& 1 ? '-' : '<', mask
& 2 ? '-' : '>');
1549 if (show_mem
|| show_tcpinfo
) {
1551 tcp_show_info(nlh
, r
, tb
);
1559 static int tcpdiag_send(int fd
, int protocol
, struct filter
*f
)
1561 struct sockaddr_nl nladdr
;
1563 struct nlmsghdr nlh
;
1564 struct inet_diag_req r
;
1570 struct iovec iov
[3];
1572 if (protocol
== IPPROTO_UDP
)
1575 memset(&nladdr
, 0, sizeof(nladdr
));
1576 nladdr
.nl_family
= AF_NETLINK
;
1578 req
.nlh
.nlmsg_len
= sizeof(req
);
1579 if (protocol
== IPPROTO_TCP
)
1580 req
.nlh
.nlmsg_type
= TCPDIAG_GETSOCK
;
1582 req
.nlh
.nlmsg_type
= DCCPDIAG_GETSOCK
;
1583 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
1584 req
.nlh
.nlmsg_pid
= 0;
1585 req
.nlh
.nlmsg_seq
= 123456;
1586 memset(&req
.r
, 0, sizeof(req
.r
));
1587 req
.r
.idiag_family
= AF_INET
;
1588 req
.r
.idiag_states
= f
->states
;
1590 req
.r
.idiag_ext
|= (1<<(INET_DIAG_MEMINFO
-1));
1591 req
.r
.idiag_ext
|= (1<<(INET_DIAG_SKMEMINFO
-1));
1595 req
.r
.idiag_ext
|= (1<<(INET_DIAG_INFO
-1));
1596 req
.r
.idiag_ext
|= (1<<(INET_DIAG_VEGASINFO
-1));
1597 req
.r
.idiag_ext
|= (1<<(INET_DIAG_CONG
-1));
1600 iov
[0] = (struct iovec
){
1602 .iov_len
= sizeof(req
)
1605 bclen
= ssfilter_bytecompile(f
->f
, &bc
);
1606 rta
.rta_type
= INET_DIAG_REQ_BYTECODE
;
1607 rta
.rta_len
= RTA_LENGTH(bclen
);
1608 iov
[1] = (struct iovec
){ &rta
, sizeof(rta
) };
1609 iov
[2] = (struct iovec
){ bc
, bclen
};
1610 req
.nlh
.nlmsg_len
+= RTA_LENGTH(bclen
);
1613 msg
= (struct msghdr
) {
1614 .msg_name
= (void*)&nladdr
,
1615 .msg_namelen
= sizeof(nladdr
),
1617 .msg_iovlen
= f
->f
? 3 : 1,
1620 if (sendmsg(fd
, &msg
, 0) < 0) {
1628 static int sockdiag_send(int family
, int fd
, int protocol
, struct filter
*f
)
1630 struct sockaddr_nl nladdr
;
1632 struct nlmsghdr nlh
;
1633 struct inet_diag_req_v2 r
;
1639 struct iovec iov
[3];
1641 if (family
== PF_UNSPEC
)
1642 return tcpdiag_send(fd
, protocol
, f
);
1644 memset(&nladdr
, 0, sizeof(nladdr
));
1645 nladdr
.nl_family
= AF_NETLINK
;
1647 req
.nlh
.nlmsg_len
= sizeof(req
);
1648 req
.nlh
.nlmsg_type
= SOCK_DIAG_BY_FAMILY
;
1649 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
1650 req
.nlh
.nlmsg_pid
= 0;
1651 req
.nlh
.nlmsg_seq
= 123456;
1652 memset(&req
.r
, 0, sizeof(req
.r
));
1653 req
.r
.sdiag_family
= family
;
1654 req
.r
.sdiag_protocol
= protocol
;
1655 req
.r
.idiag_states
= f
->states
;
1657 req
.r
.idiag_ext
|= (1<<(INET_DIAG_MEMINFO
-1));
1658 req
.r
.idiag_ext
|= (1<<(INET_DIAG_SKMEMINFO
-1));
1662 req
.r
.idiag_ext
|= (1<<(INET_DIAG_INFO
-1));
1663 req
.r
.idiag_ext
|= (1<<(INET_DIAG_VEGASINFO
-1));
1664 req
.r
.idiag_ext
|= (1<<(INET_DIAG_CONG
-1));
1667 iov
[0] = (struct iovec
){
1669 .iov_len
= sizeof(req
)
1672 bclen
= ssfilter_bytecompile(f
->f
, &bc
);
1673 rta
.rta_type
= INET_DIAG_REQ_BYTECODE
;
1674 rta
.rta_len
= RTA_LENGTH(bclen
);
1675 iov
[1] = (struct iovec
){ &rta
, sizeof(rta
) };
1676 iov
[2] = (struct iovec
){ bc
, bclen
};
1677 req
.nlh
.nlmsg_len
+= RTA_LENGTH(bclen
);
1680 msg
= (struct msghdr
) {
1681 .msg_name
= (void*)&nladdr
,
1682 .msg_namelen
= sizeof(nladdr
),
1684 .msg_iovlen
= f
->f
? 3 : 1,
1687 if (sendmsg(fd
, &msg
, 0) < 0) {
1695 static int inet_show_netlink(struct filter
*f
, FILE *dump_fp
, int protocol
)
1698 struct sockaddr_nl nladdr
;
1701 struct iovec iov
[3];
1703 if ((fd
= socket(AF_NETLINK
, SOCK_RAW
, NETLINK_INET_DIAG
)) < 0)
1708 if (sockdiag_send(family
, fd
, protocol
, f
))
1711 memset(&nladdr
, 0, sizeof(nladdr
));
1712 nladdr
.nl_family
= AF_NETLINK
;
1714 iov
[0] = (struct iovec
){
1716 .iov_len
= sizeof(buf
)
1723 msg
= (struct msghdr
) {
1724 (void*)&nladdr
, sizeof(nladdr
),
1730 status
= recvmsg(fd
, &msg
, 0);
1739 fprintf(stderr
, "EOF on netlink\n");
1745 fwrite(buf
, 1, NLMSG_ALIGN(status
), dump_fp
);
1747 h
= (struct nlmsghdr
*)buf
;
1748 while (NLMSG_OK(h
, status
)) {
1750 struct inet_diag_msg
*r
= NLMSG_DATA(h
);
1752 if (/*h->nlmsg_pid != rth->local.nl_pid ||*/
1753 h
->nlmsg_seq
!= 123456)
1756 if (h
->nlmsg_type
== NLMSG_DONE
)
1759 if (h
->nlmsg_type
== NLMSG_ERROR
) {
1760 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(h
);
1761 if (h
->nlmsg_len
< NLMSG_LENGTH(sizeof(struct nlmsgerr
))) {
1762 fprintf(stderr
, "ERROR truncated\n");
1764 if (family
!= PF_UNSPEC
) {
1769 errno
= -err
->error
;
1770 if (errno
== EOPNOTSUPP
) {
1774 perror("TCPDIAG answers");
1780 if (!(f
->families
& (1<<r
->idiag_family
))) {
1781 h
= NLMSG_NEXT(h
, status
);
1784 err
= inet_show_sock(h
, NULL
, protocol
);
1792 h
= NLMSG_NEXT(h
, status
);
1794 if (msg
.msg_flags
& MSG_TRUNC
) {
1795 fprintf(stderr
, "Message truncated\n");
1799 fprintf(stderr
, "!!!Remnant of size %d\n", status
);
1804 if (family
== PF_INET
) {
1813 static int tcp_show_netlink_file(struct filter
*f
)
1818 if ((fp
= fopen(getenv("TCPDIAG_FILE"), "r")) == NULL
) {
1819 perror("fopen($TCPDIAG_FILE)");
1825 struct nlmsghdr
*h
= (struct nlmsghdr
*)buf
;
1827 status
= fread(buf
, 1, sizeof(*h
), fp
);
1829 perror("Reading header from $TCPDIAG_FILE");
1832 if (status
!= sizeof(*h
)) {
1833 perror("Unexpected EOF reading $TCPDIAG_FILE");
1837 status
= fread(h
+1, 1, NLMSG_ALIGN(h
->nlmsg_len
-sizeof(*h
)), fp
);
1840 perror("Reading $TCPDIAG_FILE");
1843 if (status
+ sizeof(*h
) < h
->nlmsg_len
) {
1844 perror("Unexpected EOF reading $TCPDIAG_FILE");
1848 /* The only legal exit point */
1849 if (h
->nlmsg_type
== NLMSG_DONE
)
1852 if (h
->nlmsg_type
== NLMSG_ERROR
) {
1853 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(h
);
1854 if (h
->nlmsg_len
< NLMSG_LENGTH(sizeof(struct nlmsgerr
))) {
1855 fprintf(stderr
, "ERROR truncated\n");
1857 errno
= -err
->error
;
1858 perror("TCPDIAG answered");
1863 err
= inet_show_sock(h
, f
, IPPROTO_TCP
);
1869 static int tcp_show(struct filter
*f
, int socktype
)
1873 int bufsize
= 64*1024;
1875 dg_proto
= TCP_PROTO
;
1877 if (getenv("TCPDIAG_FILE"))
1878 return tcp_show_netlink_file(f
);
1880 if (!getenv("PROC_NET_TCP") && !getenv("PROC_ROOT")
1881 && inet_show_netlink(f
, NULL
, socktype
) == 0)
1884 /* Sigh... We have to parse /proc/net/tcp... */
1887 /* Estimate amount of sockets and try to allocate
1888 * huge buffer to read all the table at one read.
1889 * Limit it by 16MB though. The assumption is: as soon as
1890 * kernel was able to hold information about N connections,
1891 * it is able to give us some memory for snapshot.
1894 int guess
= slabstat
.socks
+slabstat
.tcp_syns
;
1895 if (f
->states
&(1<<SS_TIME_WAIT
))
1896 guess
+= slabstat
.tcp_tws
;
1897 if (guess
> (16*1024*1024)/128)
1898 guess
= (16*1024*1024)/128;
1900 if (guess
> bufsize
)
1903 while (bufsize
>= 64*1024) {
1904 if ((buf
= malloc(bufsize
)) != NULL
)
1913 if (f
->families
& (1<<AF_INET
)) {
1914 if ((fp
= net_tcp_open()) == NULL
)
1917 setbuffer(fp
, buf
, bufsize
);
1918 if (generic_record_read(fp
, tcp_show_line
, f
, AF_INET
))
1923 if ((f
->families
& (1<<AF_INET6
)) &&
1924 (fp
= net_tcp6_open()) != NULL
) {
1925 setbuffer(fp
, buf
, bufsize
);
1926 if (generic_record_read(fp
, tcp_show_line
, f
, AF_INET6
))
1936 int saved_errno
= errno
;
1941 errno
= saved_errno
;
1947 static int dgram_show_line(char *line
, const struct filter
*f
, int family
)
1950 char *loc
, *rem
, *data
;
1955 if ((p
= strchr(line
, ':')) == NULL
)
1959 if ((p
= strchr(loc
, ':')) == NULL
)
1964 if ((p
= strchr(rem
, ':')) == NULL
)
1970 int state
= (data
[1] >= 'A') ? (data
[1] - 'A' + 10) : (data
[1] - '0');
1972 if (!(f
->states
& (1<<state
)))
1976 s
.local
.family
= s
.remote
.family
= family
;
1977 if (family
== AF_INET
) {
1978 sscanf(loc
, "%x:%x", s
.local
.data
, (unsigned*)&s
.lport
);
1979 sscanf(rem
, "%x:%x", s
.remote
.data
, (unsigned*)&s
.rport
);
1980 s
.local
.bytelen
= s
.remote
.bytelen
= 4;
1982 sscanf(loc
, "%08x%08x%08x%08x:%x",
1988 sscanf(rem
, "%08x%08x%08x%08x:%x",
1994 s
.local
.bytelen
= s
.remote
.bytelen
= 16;
1997 if (f
->f
&& run_ssfilter(f
->f
, &s
) == 0)
2001 n
= sscanf(data
, "%x %x:%x %*x:%*x %*x %d %*d %u %d %llx %[^\n]\n",
2002 &s
.state
, &s
.wq
, &s
.rq
,
2004 &s
.refcnt
, &s
.sk
, opt
);
2010 printf("%-*s ", netid_width
, dg_proto
);
2012 printf("%-*s ", state_width
, sstate_name
[s
.state
]);
2014 printf("%-6d %-6d ", s
.rq
, s
.wq
);
2016 formatted_print(&s
.local
, s
.lport
, 0);
2017 formatted_print(&s
.remote
, s
.rport
, 0);
2021 if (find_users(s
.ino
, ubuf
, sizeof(ubuf
)) > 0)
2022 printf(" users:(%s)", ubuf
);
2027 printf(" uid=%u", (unsigned)s
.uid
);
2028 printf(" ino=%u", s
.ino
);
2029 printf(" sk=%llx", s
.sk
);
2031 printf(" opt:\"%s\"", opt
);
2039 static int udp_show(struct filter
*f
)
2043 if (!getenv("PROC_NET_UDP") && !getenv("PROC_ROOT")
2044 && inet_show_netlink(f
, NULL
, IPPROTO_UDP
) == 0)
2047 dg_proto
= UDP_PROTO
;
2049 if (f
->families
&(1<<AF_INET
)) {
2050 if ((fp
= net_udp_open()) == NULL
)
2052 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET
))
2057 if ((f
->families
&(1<<AF_INET6
)) &&
2058 (fp
= net_udp6_open()) != NULL
) {
2059 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET6
))
2067 int saved_errno
= errno
;
2070 errno
= saved_errno
;
2075 static int raw_show(struct filter
*f
)
2079 dg_proto
= RAW_PROTO
;
2081 if (f
->families
&(1<<AF_INET
)) {
2082 if ((fp
= net_raw_open()) == NULL
)
2084 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET
))
2089 if ((f
->families
&(1<<AF_INET6
)) &&
2090 (fp
= net_raw6_open()) != NULL
) {
2091 if (generic_record_read(fp
, dgram_show_line
, f
, AF_INET6
))
2099 int saved_errno
= errno
;
2102 errno
= saved_errno
;
2110 struct unixstat
*next
;
2122 int unix_state_map
[] = { SS_CLOSE
, SS_SYN_SENT
,
2123 SS_ESTABLISHED
, SS_CLOSING
};
2126 #define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct unixstat))
2128 static void unix_list_free(struct unixstat
*list
)
2131 struct unixstat
*s
= list
;
2139 static const char *unix_netid_name(int type
)
2147 case SOCK_SEQPACKET
:
2158 static void unix_list_print(struct unixstat
*list
, struct filter
*f
)
2163 for (s
= list
; s
; s
= s
->next
) {
2164 if (!(f
->states
& (1<<s
->state
)))
2166 if (s
->type
== SOCK_STREAM
&& !(f
->dbs
&(1<<UNIX_ST_DB
)))
2168 if (s
->type
== SOCK_DGRAM
&& !(f
->dbs
&(1<<UNIX_DG_DB
)))
2170 if (s
->type
== SOCK_SEQPACKET
&& !(f
->dbs
&(1<<UNIX_SQ_DB
)))
2176 for (p
= list
; p
; p
= p
->next
) {
2177 if (s
->peer
== p
->ino
)
2183 peer
= p
->name
? : "*";
2189 tst
.local
.family
= AF_UNIX
;
2190 tst
.remote
.family
= AF_UNIX
;
2191 memcpy(tst
.local
.data
, &s
->name
, sizeof(s
->name
));
2192 if (strcmp(peer
, "*") == 0)
2193 memset(tst
.remote
.data
, 0, sizeof(peer
));
2195 memcpy(tst
.remote
.data
, &peer
, sizeof(peer
));
2196 if (run_ssfilter(f
->f
, &tst
) == 0)
2201 printf("%-*s ", netid_width
,
2202 unix_netid_name(s
->type
));
2204 printf("%-*s ", state_width
, sstate_name
[s
->state
]);
2205 printf("%-6d %-6d ", s
->rq
, s
->wq
);
2206 printf("%*s %-*d %*s %-*d",
2207 addr_width
, s
->name
? : "*", serv_width
, s
->ino
,
2208 addr_width
, peer
, serv_width
, s
->peer
);
2211 if (find_users(s
->ino
, ubuf
, sizeof(ubuf
)) > 0)
2212 printf(" users:(%s)", ubuf
);
2218 static int unix_show_sock(struct nlmsghdr
*nlh
, struct filter
*f
)
2220 struct unix_diag_msg
*r
= NLMSG_DATA(nlh
);
2221 struct rtattr
*tb
[UNIX_DIAG_MAX
+1];
2226 parse_rtattr(tb
, UNIX_DIAG_MAX
, (struct rtattr
*)(r
+1),
2227 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
2229 if (r
->udiag_type
== SOCK_STREAM
&& !(f
->dbs
&(1<<UNIX_ST_DB
)))
2231 if (r
->udiag_type
== SOCK_DGRAM
&& !(f
->dbs
&(1<<UNIX_DG_DB
)))
2233 if (r
->udiag_type
== SOCK_SEQPACKET
&& !(f
->dbs
&(1<<UNIX_SQ_DB
)))
2237 printf("%-*s ", netid_width
,
2238 unix_netid_name(r
->udiag_type
));
2240 printf("%-*s ", state_width
, sstate_name
[r
->udiag_state
]);
2242 if (tb
[UNIX_DIAG_RQLEN
]) {
2243 struct unix_diag_rqlen
*rql
= RTA_DATA(tb
[UNIX_DIAG_RQLEN
]);
2244 rqlen
= rql
->udiag_rqueue
;
2245 wqlen
= rql
->udiag_wqueue
;
2251 printf("%-6u %-6u ", rqlen
, wqlen
);
2253 if (tb
[UNIX_DIAG_NAME
]) {
2254 int len
= RTA_PAYLOAD(tb
[UNIX_DIAG_NAME
]);
2256 memcpy(name
, RTA_DATA(tb
[UNIX_DIAG_NAME
]), len
);
2258 if (name
[0] == '\0')
2263 if (tb
[UNIX_DIAG_PEER
])
2264 peer_ino
= rta_getattr_u32(tb
[UNIX_DIAG_PEER
]);
2268 printf("%*s %-*d %*s %-*d",
2270 serv_width
, r
->udiag_ino
,
2271 addr_width
, "*", /* FIXME */
2272 serv_width
, peer_ino
);
2276 if (find_users(r
->udiag_ino
, ubuf
, sizeof(ubuf
)) > 0)
2277 printf(" users:(%s)", ubuf
);
2282 print_skmeminfo(tb
, UNIX_DIAG_MEMINFO
);
2286 if (tb
[UNIX_DIAG_SHUTDOWN
]) {
2288 mask
= *(__u8
*)RTA_DATA(tb
[UNIX_DIAG_SHUTDOWN
]);
2289 printf(" %c-%c", mask
& 1 ? '-' : '<', mask
& 2 ? '-' : '>');
2298 static int handle_netlink_request(struct filter
*f
, FILE *dump_fp
,
2299 struct nlmsghdr
*req
, size_t size
,
2300 int (* show_one_sock
)(struct nlmsghdr
*nlh
, struct filter
*f
))
2305 if ((fd
= socket(AF_NETLINK
, SOCK_RAW
, NETLINK_INET_DIAG
)) < 0)
2308 if (send(fd
, req
, size
, 0) < 0) {
2316 struct sockaddr_nl nladdr
;
2317 socklen_t slen
= sizeof(nladdr
);
2319 status
= recvfrom(fd
, buf
, sizeof(buf
), 0,
2320 (struct sockaddr
*) &nladdr
, &slen
);
2328 fprintf(stderr
, "EOF on netlink\n");
2333 fwrite(buf
, 1, NLMSG_ALIGN(status
), dump_fp
);
2335 h
= (struct nlmsghdr
*)buf
;
2336 while (NLMSG_OK(h
, status
)) {
2339 if (/*h->nlmsg_pid != rth->local.nl_pid ||*/
2340 h
->nlmsg_seq
!= 123456)
2343 if (h
->nlmsg_type
== NLMSG_DONE
)
2346 if (h
->nlmsg_type
== NLMSG_ERROR
) {
2347 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(h
);
2348 if (h
->nlmsg_len
< NLMSG_LENGTH(sizeof(struct nlmsgerr
))) {
2349 fprintf(stderr
, "ERROR truncated\n");
2351 errno
= -err
->error
;
2352 if (errno
!= ENOENT
)
2353 fprintf(stderr
, "DIAG answers %d\n", errno
);
2359 err
= show_one_sock(h
, f
);
2367 h
= NLMSG_NEXT(h
, status
);
2371 fprintf(stderr
, "!!!Remnant of size %zd\n", status
);
2381 static int unix_show_netlink(struct filter
*f
, FILE *dump_fp
)
2384 struct nlmsghdr nlh
;
2385 struct unix_diag_req r
;
2388 memset(&req
, 0, sizeof(req
));
2389 req
.nlh
.nlmsg_len
= sizeof(req
);
2390 req
.nlh
.nlmsg_type
= SOCK_DIAG_BY_FAMILY
;
2391 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
2392 req
.nlh
.nlmsg_seq
= 123456;
2394 req
.r
.sdiag_family
= AF_UNIX
;
2395 req
.r
.udiag_states
= f
->states
;
2396 req
.r
.udiag_show
= UDIAG_SHOW_NAME
| UDIAG_SHOW_PEER
| UDIAG_SHOW_RQLEN
;
2398 req
.r
.udiag_show
|= UDIAG_SHOW_MEMINFO
;
2400 return handle_netlink_request(f
, dump_fp
, &req
.nlh
,
2401 sizeof(req
), unix_show_sock
);
2404 static int unix_show(struct filter
*f
)
2411 struct unixstat
*list
= NULL
;
2413 if (!getenv("PROC_NET_UNIX") && !getenv("PROC_ROOT")
2414 && unix_show_netlink(f
, NULL
) == 0)
2417 if ((fp
= net_unix_open()) == NULL
)
2419 fgets(buf
, sizeof(buf
)-1, fp
);
2421 if (memcmp(buf
, "Peer", 4) == 0)
2425 while (fgets(buf
, sizeof(buf
)-1, fp
)) {
2426 struct unixstat
*u
, **insp
;
2429 if (!(u
= malloc(sizeof(*u
))))
2433 if (sscanf(buf
, "%x: %x %x %x %x %x %d %s",
2434 &u
->peer
, &u
->rq
, &u
->wq
, &flags
, &u
->type
,
2435 &u
->state
, &u
->ino
, name
) < 8)
2438 if (flags
&(1<<16)) {
2439 u
->state
= SS_LISTEN
;
2441 u
->state
= unix_state_map
[u
->state
-1];
2442 if (u
->type
== SOCK_DGRAM
&&
2443 u
->state
== SS_CLOSE
&&
2445 u
->state
= SS_ESTABLISHED
;
2456 if (u
->type
< (*insp
)->type
||
2457 (u
->type
== (*insp
)->type
&&
2458 u
->ino
< (*insp
)->ino
))
2460 insp
= &(*insp
)->next
;
2466 if ((u
->name
= malloc(strlen(name
)+1)) == NULL
)
2468 strcpy(u
->name
, name
);
2470 if (++cnt
> MAX_UNIX_REMEMBER
) {
2471 unix_list_print(list
, f
);
2472 unix_list_free(list
);
2479 unix_list_print(list
, f
);
2480 unix_list_free(list
);
2488 static int packet_show_sock(struct nlmsghdr
*nlh
, struct filter
*f
)
2490 struct packet_diag_msg
*r
= NLMSG_DATA(nlh
);
2491 struct rtattr
*tb
[PACKET_DIAG_MAX
+1];
2494 parse_rtattr(tb
, PACKET_DIAG_MAX
, (struct rtattr
*)(r
+1),
2495 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
2497 /* use /proc/net/packet if all info are not available */
2498 if (!tb
[PACKET_DIAG_MEMINFO
])
2502 printf("%-*s ", netid_width
,
2503 r
->pdiag_type
== SOCK_RAW
? "p_raw" : "p_dgr");
2505 printf("%-*s ", state_width
, "UNCONN");
2507 if (tb
[PACKET_DIAG_MEMINFO
]) {
2508 __u32
*skmeminfo
= RTA_DATA(tb
[PACKET_DIAG_MEMINFO
]);
2510 rq
= skmeminfo
[SK_MEMINFO_RMEM_ALLOC
];
2513 printf("%-6d %-6d ", rq
, 0);
2515 if (r
->pdiag_num
== 3) {
2516 printf("%*s:", addr_width
, "*");
2519 printf("%*s:", addr_width
,
2520 ll_proto_n2a(htons(r
->pdiag_num
), tb2
, sizeof(tb2
)));
2522 if (tb
[PACKET_DIAG_INFO
]) {
2523 struct packet_diag_info
*pinfo
= RTA_DATA(tb
[PACKET_DIAG_INFO
]);
2525 if (pinfo
->pdi_index
== 0)
2526 printf("%-*s ", serv_width
, "*");
2528 printf("%-*s ", serv_width
, xll_index_to_name(pinfo
->pdi_index
));
2530 printf("%-*s ", serv_width
, "*");
2533 addr_width
, "", serv_width
, "");
2537 if (find_users(r
->pdiag_ino
, ubuf
, sizeof(ubuf
)) > 0)
2538 printf(" users:(%s)", ubuf
);
2543 if (tb
[PACKET_DIAG_UID
])
2544 uid
= *(__u32
*)RTA_DATA(tb
[PACKET_DIAG_UID
]);
2546 printf(" ino=%u uid=%u sk=", r
->pdiag_ino
, uid
);
2547 if (r
->pdiag_cookie
[1] != 0)
2548 printf("%08x", r
->pdiag_cookie
[1]);
2549 printf("%08x", r
->pdiag_cookie
[0]);
2552 if (show_bpf
&& tb
[PACKET_DIAG_FILTER
]) {
2553 struct sock_filter
*fil
=
2554 RTA_DATA(tb
[PACKET_DIAG_FILTER
]);
2555 int num
= RTA_PAYLOAD(tb
[PACKET_DIAG_FILTER
]) /
2556 sizeof(struct sock_filter
);
2558 printf("\n\tbpf filter (%d): ", num
);
2560 printf(" 0x%02x %u %u %u,",
2561 fil
->code
, fil
->jt
, fil
->jf
, fil
->k
);
2570 static int packet_show_netlink(struct filter
*f
, FILE *dump_fp
)
2574 struct nlmsghdr nlh
;
2575 struct packet_diag_req r
;
2579 if ((fd
= socket(AF_NETLINK
, SOCK_RAW
, NETLINK_INET_DIAG
)) < 0)
2582 memset(&req
, 0, sizeof(req
));
2583 req
.nlh
.nlmsg_len
= sizeof(req
);
2584 req
.nlh
.nlmsg_type
= SOCK_DIAG_BY_FAMILY
;
2585 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
2586 req
.nlh
.nlmsg_seq
= 123456;
2588 req
.r
.sdiag_family
= AF_PACKET
;
2589 req
.r
.pdiag_show
= PACKET_SHOW_INFO
| PACKET_SHOW_MEMINFO
| PACKET_SHOW_FILTER
;
2591 if (send(fd
, &req
, sizeof(req
), 0) < 0) {
2599 struct sockaddr_nl nladdr
;
2600 socklen_t slen
= sizeof(nladdr
);
2602 status
= recvfrom(fd
, buf
, sizeof(buf
), 0,
2603 (struct sockaddr
*) &nladdr
, &slen
);
2611 fprintf(stderr
, "EOF on netlink\n");
2616 fwrite(buf
, 1, NLMSG_ALIGN(status
), dump_fp
);
2618 h
= (struct nlmsghdr
*)buf
;
2619 while (NLMSG_OK(h
, status
)) {
2622 if (h
->nlmsg_seq
!= 123456)
2625 if (h
->nlmsg_type
== NLMSG_DONE
)
2628 if (h
->nlmsg_type
== NLMSG_ERROR
) {
2629 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(h
);
2630 if (h
->nlmsg_len
< NLMSG_LENGTH(sizeof(struct nlmsgerr
))) {
2631 fprintf(stderr
, "ERROR truncated\n");
2633 errno
= -err
->error
;
2634 if (errno
!= ENOENT
)
2635 fprintf(stderr
, "UDIAG answers %d\n", errno
);
2641 err
= packet_show_sock(h
, f
);
2649 h
= NLMSG_NEXT(h
, status
);
2653 fprintf(stderr
, "!!!Remnant of size %zd\n", status
);
2664 static int packet_show(struct filter
*f
)
2675 unsigned long long sk
;
2677 if (!(f
->states
& (1<<SS_CLOSE
)))
2680 if (packet_show_netlink(f
, NULL
) == 0)
2683 if ((fp
= net_packet_open()) == NULL
)
2685 fgets(buf
, sizeof(buf
)-1, fp
);
2687 while (fgets(buf
, sizeof(buf
)-1, fp
)) {
2688 sscanf(buf
, "%llx %*d %d %x %d %d %u %u %u",
2690 &type
, &prot
, &iface
, &state
,
2693 if (type
== SOCK_RAW
&& !(f
->dbs
&(1<<PACKET_R_DB
)))
2695 if (type
== SOCK_DGRAM
&& !(f
->dbs
&(1<<PACKET_DG_DB
)))
2699 tst
.local
.family
= AF_PACKET
;
2700 tst
.remote
.family
= AF_PACKET
;
2703 tst
.local
.data
[0] = prot
;
2704 tst
.remote
.data
[0] = 0;
2705 if (run_ssfilter(f
->f
, &tst
) == 0)
2710 printf("%-*s ", netid_width
,
2711 type
== SOCK_RAW
? "p_raw" : "p_dgr");
2713 printf("%-*s ", state_width
, "UNCONN");
2714 printf("%-6d %-6d ", rq
, 0);
2716 printf("%*s:", addr_width
, "*");
2719 printf("%*s:", addr_width
,
2720 ll_proto_n2a(htons(prot
), tb
, sizeof(tb
)));
2723 printf("%-*s ", serv_width
, "*");
2725 printf("%-*s ", serv_width
, xll_index_to_name(iface
));
2728 addr_width
, "", serv_width
, "");
2732 if (find_users(ino
, ubuf
, sizeof(ubuf
)) > 0)
2733 printf(" users:(%s)", ubuf
);
2736 printf(" ino=%u uid=%u sk=%llx", ino
, uid
, sk
);
2744 static void netlink_show_one(struct filter
*f
,
2745 int prot
, int pid
, unsigned groups
,
2746 int state
, int dst_pid
, unsigned dst_group
,
2748 unsigned long long sk
, unsigned long long cb
)
2752 tst
.local
.family
= AF_NETLINK
;
2753 tst
.remote
.family
= AF_NETLINK
;
2756 tst
.local
.data
[0] = prot
;
2757 tst
.remote
.data
[0] = 0;
2758 if (run_ssfilter(f
->f
, &tst
) == 0)
2763 printf("%-*s ", netid_width
, "nl");
2765 printf("%-*s ", state_width
, "UNCONN");
2766 printf("%-6d %-6d ", rq
, wq
);
2767 if (resolve_services
&& prot
== 0)
2768 printf("%*s:", addr_width
, "rtnl");
2769 else if (resolve_services
&& prot
== 3)
2770 printf("%*s:", addr_width
, "fw");
2771 else if (resolve_services
&& prot
== 4)
2772 printf("%*s:", addr_width
, "tcpdiag");
2774 printf("%*d:", addr_width
, prot
);
2776 printf("%-*s ", serv_width
, "*");
2777 } else if (resolve_services
) {
2781 printf("%-*s ", serv_width
, "kernel");
2782 } else if (pid
> 0) {
2785 sprintf(procname
, "%s/%d/stat",
2786 getenv("PROC_ROOT") ? : "/proc", pid
);
2787 if ((fp
= fopen(procname
, "r")) != NULL
) {
2788 if (fscanf(fp
, "%*d (%[^)])", procname
) == 1) {
2789 sprintf(procname
+strlen(procname
), "/%d", pid
);
2790 printf("%-*s ", serv_width
, procname
);
2797 printf("%-*d ", serv_width
, pid
);
2799 printf("%-*d ", serv_width
, pid
);
2802 if (state
== NETLINK_CONNECTED
) {
2804 addr_width
, dst_group
, serv_width
, dst_pid
);
2807 addr_width
, "", serv_width
, "");
2811 printf(" sk=%llx cb=%llx groups=0x%08x", sk
, cb
, groups
);
2818 static int netlink_show_sock(struct nlmsghdr
*nlh
, struct filter
*f
)
2820 struct netlink_diag_msg
*r
= NLMSG_DATA(nlh
);
2821 struct rtattr
*tb
[NETLINK_DIAG_MAX
+1];
2823 unsigned long groups
= 0;
2825 parse_rtattr(tb
, NETLINK_DIAG_MAX
, (struct rtattr
*)(r
+1),
2826 nlh
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
2828 if (tb
[NETLINK_DIAG_GROUPS
] && RTA_PAYLOAD(tb
[NETLINK_DIAG_GROUPS
]))
2829 groups
= *(unsigned long *) RTA_DATA(tb
[NETLINK_DIAG_GROUPS
]);
2831 if (tb
[NETLINK_DIAG_MEMINFO
]) {
2832 const __u32
*skmeminfo
;
2833 skmeminfo
= RTA_DATA(tb
[NETLINK_DIAG_MEMINFO
]);
2835 rq
= skmeminfo
[SK_MEMINFO_RMEM_ALLOC
];
2836 wq
= skmeminfo
[SK_MEMINFO_WMEM_ALLOC
];
2839 netlink_show_one(f
, r
->ndiag_protocol
, r
->ndiag_portid
, groups
,
2840 r
->ndiag_state
, r
->ndiag_dst_portid
, r
->ndiag_dst_group
,
2845 print_skmeminfo(tb
, NETLINK_DIAG_MEMINFO
);
2852 static int netlink_show_netlink(struct filter
*f
, FILE *dump_fp
)
2855 struct nlmsghdr nlh
;
2856 struct netlink_diag_req r
;
2859 memset(&req
, 0, sizeof(req
));
2860 req
.nlh
.nlmsg_len
= sizeof(req
);
2861 req
.nlh
.nlmsg_type
= SOCK_DIAG_BY_FAMILY
;
2862 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
2863 req
.nlh
.nlmsg_seq
= 123456;
2865 req
.r
.sdiag_family
= AF_NETLINK
;
2866 req
.r
.sdiag_protocol
= NDIAG_PROTO_ALL
;
2867 req
.r
.ndiag_show
= NDIAG_SHOW_GROUPS
| NDIAG_SHOW_MEMINFO
;
2869 return handle_netlink_request(f
, dump_fp
, &req
.nlh
,
2870 sizeof(req
), netlink_show_sock
);
2873 static int netlink_show(struct filter
*f
)
2880 unsigned long long sk
, cb
;
2882 if (!(f
->states
& (1<<SS_CLOSE
)))
2885 if (!getenv("PROC_NET_NETLINK") && !getenv("PROC_ROOT") &&
2886 netlink_show_netlink(f
, NULL
) == 0)
2889 if ((fp
= net_netlink_open()) == NULL
)
2891 fgets(buf
, sizeof(buf
)-1, fp
);
2893 while (fgets(buf
, sizeof(buf
)-1, fp
)) {
2894 sscanf(buf
, "%llx %d %d %x %d %d %llx %d",
2896 &prot
, &pid
, &groups
, &rq
, &wq
, &cb
, &rc
);
2898 netlink_show_one(f
, prot
, pid
, groups
, 0, 0, 0, rq
, wq
, sk
, cb
);
2909 static int get_snmp_int(char *proto
, char *key
, int *result
)
2913 int protolen
= strlen(proto
);
2914 int keylen
= strlen(key
);
2918 if ((fp
= net_snmp_open()) == NULL
)
2921 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
2924 if (memcmp(buf
, proto
, protolen
))
2926 while ((p
= strchr(p
, ' ')) != NULL
) {
2929 if (memcmp(p
, key
, keylen
) == 0 &&
2930 (p
[keylen
] == ' ' || p
[keylen
] == '\n'))
2933 if (fgets(buf
, sizeof(buf
), fp
) == NULL
)
2935 if (memcmp(buf
, proto
, protolen
))
2938 while ((p
= strchr(p
, ' ')) != NULL
) {
2941 sscanf(p
, "%d", result
);
2954 /* Get stats from sockstat */
2975 static void get_sockstat_line(char *line
, struct sockstat
*s
)
2977 char id
[256], rem
[256];
2979 if (sscanf(line
, "%[^ ] %[^\n]\n", id
, rem
) != 2)
2982 if (strcmp(id
, "sockets:") == 0)
2983 sscanf(rem
, "%*s%d", &s
->socks
);
2984 else if (strcmp(id
, "UDP:") == 0)
2985 sscanf(rem
, "%*s%d", &s
->udp4
);
2986 else if (strcmp(id
, "UDP6:") == 0)
2987 sscanf(rem
, "%*s%d", &s
->udp6
);
2988 else if (strcmp(id
, "RAW:") == 0)
2989 sscanf(rem
, "%*s%d", &s
->raw4
);
2990 else if (strcmp(id
, "RAW6:") == 0)
2991 sscanf(rem
, "%*s%d", &s
->raw6
);
2992 else if (strcmp(id
, "TCP6:") == 0)
2993 sscanf(rem
, "%*s%d", &s
->tcp6_hashed
);
2994 else if (strcmp(id
, "FRAG:") == 0)
2995 sscanf(rem
, "%*s%d%*s%d", &s
->frag4
, &s
->frag4_mem
);
2996 else if (strcmp(id
, "FRAG6:") == 0)
2997 sscanf(rem
, "%*s%d%*s%d", &s
->frag6
, &s
->frag6_mem
);
2998 else if (strcmp(id
, "TCP:") == 0)
2999 sscanf(rem
, "%*s%d%*s%d%*s%d%*s%d%*s%d",
3001 &s
->tcp_orphans
, &s
->tcp_tws
, &s
->tcp_total
, &s
->tcp_mem
);
3004 static int get_sockstat(struct sockstat
*s
)
3009 memset(s
, 0, sizeof(*s
));
3011 if ((fp
= net_sockstat_open()) == NULL
)
3013 while(fgets(buf
, sizeof(buf
), fp
) != NULL
)
3014 get_sockstat_line(buf
, s
);
3017 if ((fp
= net_sockstat6_open()) == NULL
)
3019 while(fgets(buf
, sizeof(buf
), fp
) != NULL
)
3020 get_sockstat_line(buf
, s
);
3026 static int print_summary(void)
3031 if (get_sockstat(&s
) < 0)
3032 perror("ss: get_sockstat");
3033 if (get_snmp_int("Tcp:", "CurrEstab", &sn
.tcp_estab
) < 0)
3034 perror("ss: get_snmpstat");
3036 printf("Total: %d (kernel %d)\n", s
.socks
, slabstat
.socks
);
3038 printf("TCP: %d (estab %d, closed %d, orphaned %d, synrecv %d, timewait %d/%d), ports %d\n",
3039 s
.tcp_total
+ slabstat
.tcp_syns
+ s
.tcp_tws
,
3041 s
.tcp_total
- (s
.tcp4_hashed
+s
.tcp6_hashed
-s
.tcp_tws
),
3044 s
.tcp_tws
, slabstat
.tcp_tws
,
3049 printf("Transport Total IP IPv6\n");
3050 printf("* %-9d %-9s %-9s\n", slabstat
.socks
, "-", "-");
3051 printf("RAW %-9d %-9d %-9d\n", s
.raw4
+s
.raw6
, s
.raw4
, s
.raw6
);
3052 printf("UDP %-9d %-9d %-9d\n", s
.udp4
+s
.udp6
, s
.udp4
, s
.udp6
);
3053 printf("TCP %-9d %-9d %-9d\n", s
.tcp4_hashed
+s
.tcp6_hashed
, s
.tcp4_hashed
, s
.tcp6_hashed
);
3054 printf("INET %-9d %-9d %-9d\n",
3055 s
.raw4
+s
.udp4
+s
.tcp4_hashed
+
3056 s
.raw6
+s
.udp6
+s
.tcp6_hashed
,
3057 s
.raw4
+s
.udp4
+s
.tcp4_hashed
,
3058 s
.raw6
+s
.udp6
+s
.tcp6_hashed
);
3059 printf("FRAG %-9d %-9d %-9d\n", s
.frag4
+s
.frag6
, s
.frag4
, s
.frag6
);
3066 static void _usage(FILE *dest
)
3069 "Usage: ss [ OPTIONS ]\n"
3070 " ss [ OPTIONS ] [ FILTER ]\n"
3071 " -h, --help this message\n"
3072 " -V, --version output version information\n"
3073 " -n, --numeric don't resolve service names\n"
3074 " -r, --resolve resolve host names\n"
3075 " -a, --all display all sockets\n"
3076 " -l, --listening display listening sockets\n"
3077 " -o, --options show timer information\n"
3078 " -e, --extended show detailed socket information\n"
3079 " -m, --memory show socket memory usage\n"
3080 " -p, --processes show process using socket\n"
3081 " -i, --info show internal TCP information\n"
3082 " -s, --summary show socket usage summary\n"
3083 " -b, --bpf show bpf filter socket information\n"
3085 " -4, --ipv4 display only IP version 4 sockets\n"
3086 " -6, --ipv6 display only IP version 6 sockets\n"
3087 " -0, --packet display PACKET sockets\n"
3088 " -t, --tcp display only TCP sockets\n"
3089 " -u, --udp display only UDP sockets\n"
3090 " -d, --dccp display only DCCP sockets\n"
3091 " -w, --raw display only RAW sockets\n"
3092 " -x, --unix display only Unix domain sockets\n"
3093 " -f, --family=FAMILY display sockets of type FAMILY\n"
3095 " -A, --query=QUERY, --socket=QUERY\n"
3096 " QUERY := {all|inet|tcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink}[,QUERY]\n"
3098 " -D, --diag=FILE Dump raw information about TCP sockets to FILE\n"
3099 " -F, --filter=FILE read filter information from FILE\n"
3100 " FILTER := [ state TCP-STATE ] [ EXPRESSION ]\n"
3104 static void help(void) __attribute__((noreturn
));
3105 static void help(void)
3111 static void usage(void) __attribute__((noreturn
));
3112 static void usage(void)
3119 static int scan_state(const char *state
)
3122 if (strcasecmp(state
, "close") == 0 ||
3123 strcasecmp(state
, "closed") == 0)
3124 return (1<<SS_CLOSE
);
3125 if (strcasecmp(state
, "syn-rcv") == 0)
3126 return (1<<SS_SYN_RECV
);
3127 if (strcasecmp(state
, "established") == 0)
3128 return (1<<SS_ESTABLISHED
);
3129 if (strcasecmp(state
, "all") == 0)
3131 if (strcasecmp(state
, "connected") == 0)
3132 return SS_ALL
& ~((1<<SS_CLOSE
)|(1<<SS_LISTEN
));
3133 if (strcasecmp(state
, "synchronized") == 0)
3134 return SS_ALL
& ~((1<<SS_CLOSE
)|(1<<SS_LISTEN
)|(1<<SS_SYN_SENT
));
3135 if (strcasecmp(state
, "bucket") == 0)
3136 return (1<<SS_SYN_RECV
)|(1<<SS_TIME_WAIT
);
3137 if (strcasecmp(state
, "big") == 0)
3138 return SS_ALL
& ~((1<<SS_SYN_RECV
)|(1<<SS_TIME_WAIT
));
3139 for (i
=0; i
<SS_MAX
; i
++) {
3140 if (strcasecmp(state
, sstate_namel
[i
]) == 0)
3146 static const struct option long_opts
[] = {
3147 { "numeric", 0, 0, 'n' },
3148 { "resolve", 0, 0, 'r' },
3149 { "options", 0, 0, 'o' },
3150 { "extended", 0, 0, 'e' },
3151 { "memory", 0, 0, 'm' },
3152 { "info", 0, 0, 'i' },
3153 { "processes", 0, 0, 'p' },
3154 { "bpf", 0, 0, 'b' },
3155 { "dccp", 0, 0, 'd' },
3156 { "tcp", 0, 0, 't' },
3157 { "udp", 0, 0, 'u' },
3158 { "raw", 0, 0, 'w' },
3159 { "unix", 0, 0, 'x' },
3160 { "all", 0, 0, 'a' },
3161 { "listening", 0, 0, 'l' },
3162 { "ipv4", 0, 0, '4' },
3163 { "ipv6", 0, 0, '6' },
3164 { "packet", 0, 0, '0' },
3165 { "family", 1, 0, 'f' },
3166 { "socket", 1, 0, 'A' },
3167 { "query", 1, 0, 'A' },
3168 { "summary", 0, 0, 's' },
3169 { "diag", 1, 0, 'D' },
3170 { "filter", 1, 0, 'F' },
3171 { "version", 0, 0, 'V' },
3172 { "help", 0, 0, 'h' },
3177 int main(int argc
, char *argv
[])
3183 const char *dump_tcpdiag
= NULL
;
3184 FILE *filter_fp
= NULL
;
3187 memset(¤t_filter
, 0, sizeof(current_filter
));
3189 current_filter
.states
= default_filter
.states
;
3191 while ((ch
= getopt_long(argc
, argv
, "dhaletuwxnro460spbf:miA:D:F:vV",
3192 long_opts
, NULL
)) != EOF
) {
3195 resolve_services
= 0;
3215 user_ent_hash_build();
3222 current_filter
.dbs
|= (1<<DCCP_DB
);
3226 current_filter
.dbs
|= (1<<TCP_DB
);
3230 current_filter
.dbs
|= (1<<UDP_DB
);
3234 current_filter
.dbs
|= (1<<RAW_DB
);
3238 current_filter
.dbs
|= UNIX_DBM
;
3242 current_filter
.states
= SS_ALL
;
3245 current_filter
.states
= (1<<SS_LISTEN
) | (1<<SS_CLOSE
);
3248 preferred_family
= AF_INET
;
3251 preferred_family
= AF_INET6
;
3254 preferred_family
= AF_PACKET
;
3257 if (strcmp(optarg
, "inet") == 0)
3258 preferred_family
= AF_INET
;
3259 else if (strcmp(optarg
, "inet6") == 0)
3260 preferred_family
= AF_INET6
;
3261 else if (strcmp(optarg
, "link") == 0)
3262 preferred_family
= AF_PACKET
;
3263 else if (strcmp(optarg
, "unix") == 0)
3264 preferred_family
= AF_UNIX
;
3265 else if (strcmp(optarg
, "netlink") == 0)
3266 preferred_family
= AF_NETLINK
;
3267 else if (strcmp(optarg
, "help") == 0)
3270 fprintf(stderr
, "ss: \"%s\" is invalid family\n", optarg
);
3278 current_filter
.dbs
= 0;
3284 if ((p1
= strchr(p
, ',')) != NULL
)
3286 if (strcmp(p
, "all") == 0) {
3287 current_filter
.dbs
= ALL_DB
;
3288 } else if (strcmp(p
, "inet") == 0) {
3289 current_filter
.dbs
|= (1<<TCP_DB
)|(1<<DCCP_DB
)|(1<<UDP_DB
)|(1<<RAW_DB
);
3290 } else if (strcmp(p
, "udp") == 0) {
3291 current_filter
.dbs
|= (1<<UDP_DB
);
3292 } else if (strcmp(p
, "dccp") == 0) {
3293 current_filter
.dbs
|= (1<<DCCP_DB
);
3294 } else if (strcmp(p
, "tcp") == 0) {
3295 current_filter
.dbs
|= (1<<TCP_DB
);
3296 } else if (strcmp(p
, "raw") == 0) {
3297 current_filter
.dbs
|= (1<<RAW_DB
);
3298 } else if (strcmp(p
, "unix") == 0) {
3299 current_filter
.dbs
|= UNIX_DBM
;
3300 } else if (strcasecmp(p
, "unix_stream") == 0 ||
3301 strcmp(p
, "u_str") == 0) {
3302 current_filter
.dbs
|= (1<<UNIX_ST_DB
);
3303 } else if (strcasecmp(p
, "unix_dgram") == 0 ||
3304 strcmp(p
, "u_dgr") == 0) {
3305 current_filter
.dbs
|= (1<<UNIX_DG_DB
);
3306 } else if (strcasecmp(p
, "unix_seqpacket") == 0 ||
3307 strcmp(p
, "u_seq") == 0) {
3308 current_filter
.dbs
|= (1<<UNIX_SQ_DB
);
3309 } else if (strcmp(p
, "packet") == 0) {
3310 current_filter
.dbs
|= PACKET_DBM
;
3311 } else if (strcmp(p
, "packet_raw") == 0 ||
3312 strcmp(p
, "p_raw") == 0) {
3313 current_filter
.dbs
|= (1<<PACKET_R_DB
);
3314 } else if (strcmp(p
, "packet_dgram") == 0 ||
3315 strcmp(p
, "p_dgr") == 0) {
3316 current_filter
.dbs
|= (1<<PACKET_DG_DB
);
3317 } else if (strcmp(p
, "netlink") == 0) {
3318 current_filter
.dbs
|= (1<<NETLINK_DB
);
3320 fprintf(stderr
, "ss: \"%s\" is illegal socket table id\n", p
);
3331 dump_tcpdiag
= optarg
;
3335 fprintf(stderr
, "More than one filter file\n");
3338 if (optarg
[0] == '-')
3341 filter_fp
= fopen(optarg
, "r");
3343 perror("fopen filter file");
3349 printf("ss utility, iproute2-ss%s\n", SNAPSHOT
);
3362 get_slabstat(&slabstat
);
3366 if (do_default
&& argc
== 0)
3371 current_filter
.dbs
= default_filter
.dbs
;
3373 if (preferred_family
== AF_UNSPEC
) {
3374 if (!(current_filter
.dbs
&~UNIX_DBM
))
3375 preferred_family
= AF_UNIX
;
3376 else if (!(current_filter
.dbs
&~PACKET_DBM
))
3377 preferred_family
= AF_PACKET
;
3378 else if (!(current_filter
.dbs
&~(1<<NETLINK_DB
)))
3379 preferred_family
= AF_NETLINK
;
3382 if (preferred_family
!= AF_UNSPEC
) {
3384 if (preferred_family
== AF_INET
||
3385 preferred_family
== AF_INET6
) {
3386 mask2
= current_filter
.dbs
;
3387 } else if (preferred_family
== AF_PACKET
) {
3389 } else if (preferred_family
== AF_UNIX
) {
3391 } else if (preferred_family
== AF_NETLINK
) {
3392 mask2
= (1<<NETLINK_DB
);
3398 current_filter
.dbs
= mask2
;
3400 current_filter
.dbs
&= mask2
;
3401 current_filter
.families
= (1<<preferred_family
);
3404 current_filter
.families
= ~0;
3406 current_filter
.families
= default_filter
.families
;
3408 if (current_filter
.dbs
== 0) {
3409 fprintf(stderr
, "ss: no socket tables to show with such filter.\n");
3412 if (current_filter
.families
== 0) {
3413 fprintf(stderr
, "ss: no families to show with such filter.\n");
3417 if (resolve_services
&& resolve_hosts
&&
3418 (current_filter
.dbs
&(UNIX_DBM
|(1<<TCP_DB
)|(1<<UDP_DB
)|(1<<DCCP_DB
))))
3419 init_service_resolver();
3421 /* Now parse filter... */
3422 if (argc
== 0 && filter_fp
) {
3423 if (ssfilter_parse(¤t_filter
.f
, 0, NULL
, filter_fp
))
3428 if (strcmp(*argv
, "state") == 0) {
3431 current_filter
.states
= 0;
3432 current_filter
.states
|= scan_state(*argv
);
3434 } else if (strcmp(*argv
, "exclude") == 0 ||
3435 strcmp(*argv
, "excl") == 0) {
3438 current_filter
.states
= SS_ALL
;
3439 current_filter
.states
&= ~scan_state(*argv
);
3442 if (ssfilter_parse(¤t_filter
.f
, argc
, argv
, filter_fp
))
3449 if (current_filter
.states
== 0) {
3450 fprintf(stderr
, "ss: no socket states to show with such filter.\n");
3455 FILE *dump_fp
= stdout
;
3456 if (!(current_filter
.dbs
& (1<<TCP_DB
))) {
3457 fprintf(stderr
, "ss: tcpdiag dump requested and no tcp in filter.\n");
3460 if (dump_tcpdiag
[0] != '-') {
3461 dump_fp
= fopen(dump_tcpdiag
, "w");
3462 if (!dump_tcpdiag
) {
3463 perror("fopen dump file");
3467 inet_show_netlink(¤t_filter
, dump_fp
, IPPROTO_TCP
);
3473 if (current_filter
.dbs
&(current_filter
.dbs
-1))
3477 if (current_filter
.states
&(current_filter
.states
-1))
3481 if (isatty(STDOUT_FILENO
)) {
3484 if (ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &w
) != -1) {
3486 screen_width
= w
.ws_col
;
3490 addrp_width
= screen_width
;
3491 addrp_width
-= netid_width
+1;
3492 addrp_width
-= state_width
+1;
3495 if (addrp_width
&1) {
3498 else if (state_width
)
3505 serv_width
= resolve_services
? 7 : 5;
3507 if (addrp_width
< 15+serv_width
+1)
3508 addrp_width
= 15+serv_width
+1;
3510 addr_width
= addrp_width
- serv_width
- 1;
3513 printf("%-*s ", netid_width
, "Netid");
3515 printf("%-*s ", state_width
, "State");
3516 printf("%-6s %-6s ", "Recv-Q", "Send-Q");
3518 printf("%*s:%-*s %*s:%-*s\n",
3519 addr_width
, "Local Address", serv_width
, "Port",
3520 addr_width
, "Peer Address", serv_width
, "Port");
3524 if (current_filter
.dbs
& (1<<NETLINK_DB
))
3525 netlink_show(¤t_filter
);
3526 if (current_filter
.dbs
& PACKET_DBM
)
3527 packet_show(¤t_filter
);
3528 if (current_filter
.dbs
& UNIX_DBM
)
3529 unix_show(¤t_filter
);
3530 if (current_filter
.dbs
& (1<<RAW_DB
))
3531 raw_show(¤t_filter
);
3532 if (current_filter
.dbs
& (1<<UDP_DB
))
3533 udp_show(¤t_filter
);
3534 if (current_filter
.dbs
& (1<<TCP_DB
))
3535 tcp_show(¤t_filter
, IPPROTO_TCP
);
3536 if (current_filter
.dbs
& (1<<DCCP_DB
))
3537 tcp_show(¤t_filter
, IPPROTO_DCCP
);