mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2026-01-06 01:36:22 +00:00
ss: Include -E option for socket destroy events
Use the IPv4/IPv6/TCP/UDP multicast groups of NETLINK_SOCK_DIAG to filter and display socket statistics as they are destroyed. Kernel support patch series: 24029a3603cfa633e8bc2b3fb3e48e76c497831d Signed-off-by: Craig Gallek <kraig@google.com>
This commit is contained in:
parent
b0197a047e
commit
6885e3bf8e
74
misc/ss.c
74
misc/ss.c
@ -99,6 +99,7 @@ int show_proc_ctx = 0;
|
||||
int show_sock_ctx = 0;
|
||||
/* If show_users & show_proc_ctx only do user_ent_hash_build() once */
|
||||
int user_ent_hash_build_init = 0;
|
||||
int follow_events = 0;
|
||||
|
||||
int netid_width;
|
||||
int state_width;
|
||||
@ -2028,6 +2029,9 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol)
|
||||
if (f && f->f && run_ssfilter(f->f, &s) == 0)
|
||||
return 0;
|
||||
|
||||
if (tb[INET_DIAG_PROTOCOL])
|
||||
protocol = *(__u8 *)RTA_DATA(tb[INET_DIAG_PROTOCOL]);
|
||||
|
||||
inet_stats_print(&s, protocol);
|
||||
|
||||
if (show_options) {
|
||||
@ -2199,7 +2203,7 @@ static int show_one_inet_sock(const struct sockaddr_nl *addr,
|
||||
|
||||
if (!(diag_arg->f->families & (1 << r->idiag_family)))
|
||||
return 0;
|
||||
if ((err = inet_show_sock(h, NULL, diag_arg->protocol)) < 0)
|
||||
if ((err = inet_show_sock(h, diag_arg->f, diag_arg->protocol)) < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
@ -3217,6 +3221,64 @@ static int netlink_show(struct filter *f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sock_diag_msg {
|
||||
__u8 sdiag_family;
|
||||
};
|
||||
|
||||
static int generic_show_sock(const struct sockaddr_nl *addr,
|
||||
struct nlmsghdr *nlh, void *arg)
|
||||
{
|
||||
struct sock_diag_msg *r = NLMSG_DATA(nlh);
|
||||
struct inet_diag_arg inet_arg = { .f = arg, .protocol = IPPROTO_MAX };
|
||||
|
||||
switch (r->sdiag_family) {
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
return show_one_inet_sock(addr, nlh, &inet_arg);
|
||||
case AF_UNIX:
|
||||
return unix_show_sock(addr, nlh, arg);
|
||||
case AF_PACKET:
|
||||
return packet_show_sock(addr, nlh, arg);
|
||||
case AF_NETLINK:
|
||||
return netlink_show_sock(addr, nlh, arg);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_follow_request(struct filter *f)
|
||||
{
|
||||
int ret = -1;
|
||||
int groups = 0;
|
||||
struct rtnl_handle rth;
|
||||
|
||||
if (f->families & (1 << AF_INET) && f->dbs & (1 << TCP_DB))
|
||||
groups |= 1 << (SKNLGRP_INET_TCP_DESTROY - 1);
|
||||
if (f->families & (1 << AF_INET) && f->dbs & (1 << UDP_DB))
|
||||
groups |= 1 << (SKNLGRP_INET_UDP_DESTROY - 1);
|
||||
if (f->families & (1 << AF_INET6) && f->dbs & (1 << TCP_DB))
|
||||
groups |= 1 << (SKNLGRP_INET6_TCP_DESTROY - 1);
|
||||
if (f->families & (1 << AF_INET6) && f->dbs & (1 << UDP_DB))
|
||||
groups |= 1 << (SKNLGRP_INET6_UDP_DESTROY - 1);
|
||||
|
||||
if (groups == 0)
|
||||
return -1;
|
||||
|
||||
if (rtnl_open_byproto(&rth, groups, NETLINK_SOCK_DIAG))
|
||||
return -1;
|
||||
|
||||
rth.dump = 0;
|
||||
rth.local.nl_pid = 0;
|
||||
|
||||
if (rtnl_dump_filter(&rth, generic_show_sock, f))
|
||||
goto Exit;
|
||||
|
||||
ret = 0;
|
||||
Exit:
|
||||
rtnl_close(&rth);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct snmpstat
|
||||
{
|
||||
int tcp_estab;
|
||||
@ -3399,6 +3461,7 @@ static void _usage(FILE *dest)
|
||||
" -i, --info show internal TCP information\n"
|
||||
" -s, --summary show socket usage summary\n"
|
||||
" -b, --bpf show bpf filter socket information\n"
|
||||
" -E, --events continually display sockets as they are destroyed\n"
|
||||
" -Z, --context display process SELinux security contexts\n"
|
||||
" -z, --contexts display process and socket SELinux security contexts\n"
|
||||
" -N, --net switch to the specified network namespace name\n"
|
||||
@ -3481,6 +3544,7 @@ static const struct option long_opts[] = {
|
||||
{ "info", 0, 0, 'i' },
|
||||
{ "processes", 0, 0, 'p' },
|
||||
{ "bpf", 0, 0, 'b' },
|
||||
{ "events", 0, 0, 'E' },
|
||||
{ "dccp", 0, 0, 'd' },
|
||||
{ "tcp", 0, 0, 't' },
|
||||
{ "udp", 0, 0, 'u' },
|
||||
@ -3516,7 +3580,7 @@ int main(int argc, char *argv[])
|
||||
int ch;
|
||||
int state_filter = 0;
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbf:miA:D:F:vVzZN:",
|
||||
while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbEf:miA:D:F:vVzZN:",
|
||||
long_opts, NULL)) != EOF) {
|
||||
switch(ch) {
|
||||
case 'n':
|
||||
@ -3546,6 +3610,9 @@ int main(int argc, char *argv[])
|
||||
show_options = 1;
|
||||
show_bpf++;
|
||||
break;
|
||||
case 'E':
|
||||
follow_events = 1;
|
||||
break;
|
||||
case 'd':
|
||||
filter_db_set(¤t_filter, DCCP_DB);
|
||||
break;
|
||||
@ -3838,6 +3905,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
if (follow_events)
|
||||
exit(handle_follow_request(¤t_filter));
|
||||
|
||||
if (current_filter.dbs & (1<<NETLINK_DB))
|
||||
netlink_show(¤t_filter);
|
||||
if (current_filter.dbs & PACKET_DBM)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user