ss: Unify packet stats output from netlink and proc
Refactored to use one func for output packet stats info from both /proc and netlink. Added possibility to get packet stats info from /proc by setting environment variable PROC_ROOT or PROC_NET_PACKET. Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
This commit is contained in:
parent
bf4ceee6ae
commit
4a0053b606
231
misc/ss.c
231
misc/ss.c
|
|
@ -2536,12 +2536,78 @@ static int unix_show(struct filter *f)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct pktstat {
|
||||||
|
uint8_t type;
|
||||||
|
uint16_t prot;
|
||||||
|
uint32_t iface;
|
||||||
|
int state;
|
||||||
|
uint32_t rq;
|
||||||
|
uid_t uid;
|
||||||
|
ino_t ino;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int packet_stats_print(struct pktstat *s, const struct filter *f)
|
||||||
|
{
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (f->f) {
|
||||||
|
struct tcpstat tst;
|
||||||
|
tst.local.family = AF_PACKET;
|
||||||
|
tst.remote.family = AF_PACKET;
|
||||||
|
tst.rport = 0;
|
||||||
|
tst.lport = s->iface;
|
||||||
|
tst.local.data[0] = s->prot;
|
||||||
|
tst.remote.data[0] = 0;
|
||||||
|
if (run_ssfilter(f->f, &tst) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netid_width)
|
||||||
|
printf("%-*s ", netid_width,
|
||||||
|
s->type == SOCK_RAW ? "p_raw" : "p_dgr");
|
||||||
|
if (state_width)
|
||||||
|
printf("%-*s ", state_width, "UNCONN");
|
||||||
|
|
||||||
|
printf("%-6d %-6d ", s->rq, 0);
|
||||||
|
if (s->prot == 3) {
|
||||||
|
printf("%*s:", addr_width, "*");
|
||||||
|
} else {
|
||||||
|
char tb[16];
|
||||||
|
printf("%*s:", addr_width,
|
||||||
|
ll_proto_n2a(htons(s->prot), tb, sizeof(tb)));
|
||||||
|
}
|
||||||
|
if (s->iface == 0) {
|
||||||
|
printf("%-*s ", serv_width, "*");
|
||||||
|
} else {
|
||||||
|
printf("%-*s ", serv_width, xll_index_to_name(s->iface));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%*s*%-*s", addr_width, "", serv_width, "");
|
||||||
|
|
||||||
|
if (show_proc_ctx || show_sock_ctx) {
|
||||||
|
if (find_entry(s->ino, &buf,
|
||||||
|
(show_proc_ctx & show_sock_ctx) ?
|
||||||
|
PROC_SOCK_CTX : PROC_CTX) > 0) {
|
||||||
|
printf(" users:(%s)", buf);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
} else if (show_users) {
|
||||||
|
if (find_entry(s->ino, &buf, USERS) > 0) {
|
||||||
|
printf(" users:(%s)", buf);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int packet_show_sock(const struct sockaddr_nl *addr,
|
static int packet_show_sock(const struct sockaddr_nl *addr,
|
||||||
struct nlmsghdr *nlh, void *arg)
|
struct nlmsghdr *nlh, void *arg)
|
||||||
{
|
{
|
||||||
|
const struct filter *f = arg;
|
||||||
struct packet_diag_msg *r = NLMSG_DATA(nlh);
|
struct packet_diag_msg *r = NLMSG_DATA(nlh);
|
||||||
struct rtattr *tb[PACKET_DIAG_MAX+1];
|
struct rtattr *tb[PACKET_DIAG_MAX+1];
|
||||||
__u32 rq;
|
struct pktstat stat = {};
|
||||||
|
|
||||||
parse_rtattr(tb, PACKET_DIAG_MAX, (struct rtattr*)(r+1),
|
parse_rtattr(tb, PACKET_DIAG_MAX, (struct rtattr*)(r+1),
|
||||||
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
|
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
|
||||||
|
|
@ -2550,56 +2616,23 @@ static int packet_show_sock(const struct sockaddr_nl *addr,
|
||||||
if (!tb[PACKET_DIAG_MEMINFO])
|
if (!tb[PACKET_DIAG_MEMINFO])
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (netid_width)
|
stat.type = r->pdiag_type;
|
||||||
printf("%-*s ", netid_width,
|
stat.prot = r->pdiag_num;
|
||||||
r->pdiag_type == SOCK_RAW ? "p_raw" : "p_dgr");
|
stat.ino = r->pdiag_ino;
|
||||||
if (state_width)
|
|
||||||
printf("%-*s ", state_width, "UNCONN");
|
|
||||||
|
|
||||||
if (tb[PACKET_DIAG_MEMINFO]) {
|
if (tb[PACKET_DIAG_MEMINFO]) {
|
||||||
__u32 *skmeminfo = RTA_DATA(tb[PACKET_DIAG_MEMINFO]);
|
__u32 *skmeminfo = RTA_DATA(tb[PACKET_DIAG_MEMINFO]);
|
||||||
|
stat.rq = skmeminfo[SK_MEMINFO_RMEM_ALLOC];
|
||||||
rq = skmeminfo[SK_MEMINFO_RMEM_ALLOC];
|
|
||||||
} else
|
|
||||||
rq = 0;
|
|
||||||
printf("%-6d %-6d ", rq, 0);
|
|
||||||
|
|
||||||
if (r->pdiag_num == 3) {
|
|
||||||
printf("%*s:", addr_width, "*");
|
|
||||||
} else {
|
|
||||||
char tb2[16];
|
|
||||||
printf("%*s:", addr_width,
|
|
||||||
ll_proto_n2a(htons(r->pdiag_num), tb2, sizeof(tb2)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tb[PACKET_DIAG_INFO]) {
|
if (tb[PACKET_DIAG_INFO]) {
|
||||||
struct packet_diag_info *pinfo = RTA_DATA(tb[PACKET_DIAG_INFO]);
|
struct packet_diag_info *pinfo = RTA_DATA(tb[PACKET_DIAG_INFO]);
|
||||||
|
stat.iface = pinfo->pdi_index;
|
||||||
if (pinfo->pdi_index == 0)
|
|
||||||
printf("%-*s ", serv_width, "*");
|
|
||||||
else
|
|
||||||
printf("%-*s ", serv_width, xll_index_to_name(pinfo->pdi_index));
|
|
||||||
} else
|
|
||||||
printf("%-*s ", serv_width, "*");
|
|
||||||
|
|
||||||
printf("%*s*%-*s",
|
|
||||||
addr_width, "", serv_width, "");
|
|
||||||
|
|
||||||
char *buf = NULL;
|
|
||||||
|
|
||||||
if (show_proc_ctx || show_sock_ctx) {
|
|
||||||
if (find_entry(r->pdiag_ino, &buf,
|
|
||||||
(show_proc_ctx & show_sock_ctx) ?
|
|
||||||
PROC_SOCK_CTX : PROC_CTX) > 0) {
|
|
||||||
printf(" users:(%s)", buf);
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
} else if (show_users) {
|
|
||||||
if (find_entry(r->pdiag_ino, &buf, USERS) > 0) {
|
|
||||||
printf(" users:(%s)", buf);
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (packet_stats_print(&stat, f))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (show_details) {
|
if (show_details) {
|
||||||
__u32 uid = 0;
|
__u32 uid = 0;
|
||||||
|
|
||||||
|
|
@ -2640,94 +2673,54 @@ static int packet_show_netlink(struct filter *f)
|
||||||
return handle_netlink_request(f, &req.nlh, sizeof(req), packet_show_sock);
|
return handle_netlink_request(f, &req.nlh, sizeof(req), packet_show_sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int packet_show_line(char *buf, const struct filter *f, int fam)
|
||||||
|
{
|
||||||
|
unsigned long long sk;
|
||||||
|
struct pktstat stat = {};
|
||||||
|
int type, prot, iface, state, rq, uid, ino;
|
||||||
|
|
||||||
|
sscanf(buf, "%llx %*d %d %x %d %d %u %u %u",
|
||||||
|
&sk,
|
||||||
|
&type, &prot, &iface, &state,
|
||||||
|
&rq, &uid, &ino);
|
||||||
|
|
||||||
|
if (stat.type == SOCK_RAW && !(f->dbs&(1<<PACKET_R_DB)))
|
||||||
|
return 0;
|
||||||
|
if (stat.type == SOCK_DGRAM && !(f->dbs&(1<<PACKET_DG_DB)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
stat.type = type;
|
||||||
|
stat.prot = prot;
|
||||||
|
stat.iface = iface;
|
||||||
|
stat.state = state;
|
||||||
|
stat.rq = rq;
|
||||||
|
stat.uid = uid;
|
||||||
|
stat.ino = ino;
|
||||||
|
if (packet_stats_print(&stat, f))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (show_details) {
|
||||||
|
printf(" ino=%u uid=%u sk=%llx", ino, uid, sk);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int packet_show(struct filter *f)
|
static int packet_show(struct filter *f)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char buf[256];
|
|
||||||
int type;
|
|
||||||
int prot;
|
|
||||||
int iface;
|
|
||||||
int state;
|
|
||||||
int rq;
|
|
||||||
int uid;
|
|
||||||
int ino;
|
|
||||||
unsigned long long sk;
|
|
||||||
|
|
||||||
if (preferred_family != AF_PACKET && !(f->states & (1 << SS_CLOSE)))
|
if (preferred_family != AF_PACKET && !(f->states & (1 << SS_CLOSE)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (packet_show_netlink(f) == 0)
|
if (!getenv("PROC_NET_PACKET") && !getenv("PROC_ROOT") &&
|
||||||
|
packet_show_netlink(f) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((fp = net_packet_open()) == NULL)
|
if ((fp = net_packet_open()) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
fgets(buf, sizeof(buf)-1, fp);
|
if (generic_record_read(fp, packet_show_line, f, AF_PACKET))
|
||||||
|
return -1;
|
||||||
while (fgets(buf, sizeof(buf)-1, fp)) {
|
|
||||||
sscanf(buf, "%llx %*d %d %x %d %d %u %u %u",
|
|
||||||
&sk,
|
|
||||||
&type, &prot, &iface, &state,
|
|
||||||
&rq, &uid, &ino);
|
|
||||||
|
|
||||||
if (type == SOCK_RAW && !(f->dbs&(1<<PACKET_R_DB)))
|
|
||||||
continue;
|
|
||||||
if (type == SOCK_DGRAM && !(f->dbs&(1<<PACKET_DG_DB)))
|
|
||||||
continue;
|
|
||||||
if (f->f) {
|
|
||||||
struct tcpstat tst;
|
|
||||||
tst.local.family = AF_PACKET;
|
|
||||||
tst.remote.family = AF_PACKET;
|
|
||||||
tst.rport = 0;
|
|
||||||
tst.lport = iface;
|
|
||||||
tst.local.data[0] = prot;
|
|
||||||
tst.remote.data[0] = 0;
|
|
||||||
if (run_ssfilter(f->f, &tst) == 0)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (netid_width)
|
|
||||||
printf("%-*s ", netid_width,
|
|
||||||
type == SOCK_RAW ? "p_raw" : "p_dgr");
|
|
||||||
if (state_width)
|
|
||||||
printf("%-*s ", state_width, "UNCONN");
|
|
||||||
printf("%-6d %-6d ", rq, 0);
|
|
||||||
if (prot == 3) {
|
|
||||||
printf("%*s:", addr_width, "*");
|
|
||||||
} else {
|
|
||||||
char tb[16];
|
|
||||||
printf("%*s:", addr_width,
|
|
||||||
ll_proto_n2a(htons(prot), tb, sizeof(tb)));
|
|
||||||
}
|
|
||||||
if (iface == 0) {
|
|
||||||
printf("%-*s ", serv_width, "*");
|
|
||||||
} else {
|
|
||||||
printf("%-*s ", serv_width, xll_index_to_name(iface));
|
|
||||||
}
|
|
||||||
printf("%*s*%-*s",
|
|
||||||
addr_width, "", serv_width, "");
|
|
||||||
|
|
||||||
char *buf = NULL;
|
|
||||||
|
|
||||||
if (show_proc_ctx || show_sock_ctx) {
|
|
||||||
if (find_entry(ino, &buf,
|
|
||||||
(show_proc_ctx & show_sock_ctx) ?
|
|
||||||
PROC_SOCK_CTX : PROC_CTX) > 0) {
|
|
||||||
printf(" users:(%s)", buf);
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
} else if (show_users) {
|
|
||||||
if (find_entry(ino, &buf, USERS) > 0) {
|
|
||||||
printf(" users:(%s)", buf);
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (show_details) {
|
|
||||||
printf(" ino=%u uid=%u sk=%llx", ino, uid, sk);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue