parent
d2b847ed13
commit
7d105b5648
182
misc/ss.c
182
misc/ss.c
|
|
@ -30,10 +30,11 @@
|
||||||
#include "rt_names.h"
|
#include "rt_names.h"
|
||||||
#include "ll_map.h"
|
#include "ll_map.h"
|
||||||
#include "libnetlink.h"
|
#include "libnetlink.h"
|
||||||
#include "tcp_diag.h"
|
|
||||||
#include "SNAPSHOT.h"
|
#include "SNAPSHOT.h"
|
||||||
|
|
||||||
|
#include <asm/byteorder.h>
|
||||||
#include <linux/tcp.h>
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/tcp_diag.h>
|
||||||
|
|
||||||
int resolve_hosts = 0;
|
int resolve_hosts = 0;
|
||||||
int resolve_services = 1;
|
int resolve_services = 1;
|
||||||
|
|
@ -333,37 +334,34 @@ int get_slabstat(struct slabstat *s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *sstate_name[] = {
|
||||||
|
|
||||||
|
|
||||||
char *sstate_name[] = {
|
|
||||||
"UNKNOWN",
|
"UNKNOWN",
|
||||||
"ESTAB",
|
[TCP_ESTABLISHED] = "ESTAB",
|
||||||
"SYN-SENT",
|
[TCP_SYN_SENT] = "SYN-SENT",
|
||||||
"SYN-RECV",
|
[TCP_SYN_RECV] = "SYN-RECV",
|
||||||
"FIN-WAIT-1",
|
[TCP_FIN_WAIT1] = "FIN-WAIT-1",
|
||||||
"FIN-WAIT-2",
|
[TCP_FIN_WAIT2] = "FIN-WAIT-2",
|
||||||
"TIME-WAIT",
|
[TCP_TIME_WAIT] = "TIME-WAIT",
|
||||||
"UNCONN",
|
[TCP_CLOSE] = "UNCONN",
|
||||||
"CLOSE-WAIT",
|
[TCP_CLOSE_WAIT] = "CLOSE-WAIT",
|
||||||
"LAST-ACK",
|
[TCP_LAST_ACK] = "LAST-ACK",
|
||||||
"LISTEN",
|
[TCP_LISTEN] = "LISTEN",
|
||||||
"CLOSING",
|
[TCP_CLOSING] = "CLOSING",
|
||||||
};
|
};
|
||||||
|
|
||||||
char *sstate_namel[] = {
|
static const char *sstate_namel[] = {
|
||||||
"UNKNOWN",
|
"UNKNOWN",
|
||||||
"established",
|
[TCP_ESTABLISHED] = "established",
|
||||||
"syn-sent",
|
[TCP_SYN_SENT] = "syn-sent",
|
||||||
"syn-recv",
|
[TCP_SYN_RECV] = "syn-recv",
|
||||||
"fin-wait-1",
|
[TCP_FIN_WAIT1] = "fin-wait-1",
|
||||||
"fin-wait-2",
|
[TCP_FIN_WAIT2] = "fin-wait-2",
|
||||||
"time-wait",
|
[TCP_TIME_WAIT] = "time-wait",
|
||||||
"unconnected",
|
[TCP_CLOSE] = "unconnected",
|
||||||
"close-wait",
|
[TCP_CLOSE_WAIT] = "close-wait",
|
||||||
"last-ack",
|
[TCP_LAST_ACK] = "last-ack",
|
||||||
"listening",
|
[TCP_LISTEN] = "listening",
|
||||||
"closing",
|
[TCP_CLOSING] = "closing",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tcpstat
|
struct tcpstat
|
||||||
|
|
@ -385,7 +383,7 @@ struct tcpstat
|
||||||
int rto, ato, qack, cwnd, ssthresh;
|
int rto, ato, qack, cwnd, ssthresh;
|
||||||
};
|
};
|
||||||
|
|
||||||
char *tmr_name[] = {
|
static const char *tmr_name[] = {
|
||||||
"off",
|
"off",
|
||||||
"on",
|
"on",
|
||||||
"keepalive",
|
"keepalive",
|
||||||
|
|
@ -552,7 +550,7 @@ const char *resolve_service(int port)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void formatted_print(inet_prefix *a, int port)
|
void formatted_print(const inet_prefix *a, int port)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
const char *ap = buf;
|
const char *ap = buf;
|
||||||
|
|
@ -585,10 +583,11 @@ struct aafilter
|
||||||
struct aafilter *next;
|
struct aafilter *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
int inet2_addr_match(inet_prefix *a, inet_prefix *p, int plen)
|
int inet2_addr_match(const inet_prefix *a, const inet_prefix *p, int plen)
|
||||||
{
|
{
|
||||||
if (!inet_addr_match(a, p, plen))
|
if (!inet_addr_match(a, p, plen))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Cursed "v4 mapped" addresses: v4 mapped socket matches
|
/* Cursed "v4 mapped" addresses: v4 mapped socket matches
|
||||||
* pure IPv4 rule, but v4-mapped rule selects only v4-mapped
|
* pure IPv4 rule, but v4-mapped rule selects only v4-mapped
|
||||||
* sockets. Fair? */
|
* sockets. Fair? */
|
||||||
|
|
@ -603,7 +602,7 @@ int inet2_addr_match(inet_prefix *a, inet_prefix *p, int plen)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int unix_match(inet_prefix *a, inet_prefix *p)
|
int unix_match(const inet_prefix *a, const inet_prefix *p)
|
||||||
{
|
{
|
||||||
char *addr, *pattern;
|
char *addr, *pattern;
|
||||||
memcpy(&addr, a->data, sizeof(addr));
|
memcpy(&addr, a->data, sizeof(addr));
|
||||||
|
|
@ -1268,6 +1267,71 @@ outerr:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tcp_show_info(struct nlmsghdr *nlh, struct tcpdiagmsg *r)
|
||||||
|
{
|
||||||
|
struct rtattr * tb[TCPDIAG_MAX+1];
|
||||||
|
const struct tcpdiag_meminfo *minfo = NULL;
|
||||||
|
const struct tcp_info *info = NULL;
|
||||||
|
const struct tcpvegas_info *vinfo = NULL;
|
||||||
|
|
||||||
|
memset(tb, 0, sizeof(tb));
|
||||||
|
parse_rtattr(tb, TCPDIAG_MAX, (struct rtattr*)(r+1),
|
||||||
|
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
|
||||||
|
|
||||||
|
if (tb[TCPDIAG_MEMINFO])
|
||||||
|
minfo = RTA_DATA(tb[TCPDIAG_MEMINFO]);
|
||||||
|
if (tb[TCPDIAG_INFO])
|
||||||
|
info = RTA_DATA(tb[TCPDIAG_INFO]);
|
||||||
|
|
||||||
|
#ifdef TCPDIAG_VEGASINFO
|
||||||
|
if (tb[TCPDIAG_VEGASINFO])
|
||||||
|
vinfo = RTA_DATA(tb[TCPDIAG_VEGASINFO]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (minfo) {
|
||||||
|
printf(" mem:(r%u,w%u,f%u,t%u)",
|
||||||
|
minfo->tcpdiag_rmem,
|
||||||
|
minfo->tcpdiag_wmem,
|
||||||
|
minfo->tcpdiag_fmem,
|
||||||
|
minfo->tcpdiag_tmem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info) {
|
||||||
|
#ifdef TCP_INFO
|
||||||
|
if (info->tcpi_rto && info->tcpi_rto != 3000000)
|
||||||
|
printf(" rto:%g", (double)info->tcpi_rto/1000);
|
||||||
|
if (info->tcpi_rtt)
|
||||||
|
printf(" rtt:%g/%g", (double)info->tcpi_rtt/1000,
|
||||||
|
(double)info->tcpi_rttvar/1000);
|
||||||
|
if (info->tcpi_ato)
|
||||||
|
printf(" ato:%g", (double)info->tcpi_ato/1000);
|
||||||
|
if (info->tcpi_snd_cwnd != 2)
|
||||||
|
printf(" cwnd:%d", info->tcpi_snd_cwnd);
|
||||||
|
if (info->tcpi_snd_ssthresh < 0xFFFF)
|
||||||
|
printf(" ssthresh:%d", info->tcpi_snd_ssthresh);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TCPDIAG_VEGASINFO
|
||||||
|
if (vinfo) {
|
||||||
|
if (vinfo->tcpv_enabled)
|
||||||
|
printf(" vegas");
|
||||||
|
if (vinfo->tcpv_rtt &&
|
||||||
|
vinfo->tcpv_rtt != 0x7fffffff &&
|
||||||
|
info->tcpi_snd_mss &&
|
||||||
|
info->tcpi_snd_cwnd) {
|
||||||
|
printf(" bw:%g",
|
||||||
|
(double) info->tcpi_snd_cwnd *
|
||||||
|
(double) info->tcpi_snd_mss *
|
||||||
|
8000000. / (double) vinfo->tcpv_rtt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#warning No TCP_INFO. Please, do not repeat this experiment, use right kernel.
|
||||||
|
printf(" MORE_INFO_PROVIDED_YOU_COMPILED_SS_RIGHT");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f)
|
int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f)
|
||||||
{
|
{
|
||||||
|
|
@ -1323,43 +1387,10 @@ int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f)
|
||||||
printf("%08x", r->id.tcpdiag_cookie[1]);
|
printf("%08x", r->id.tcpdiag_cookie[1]);
|
||||||
}
|
}
|
||||||
if (show_mem || show_tcpinfo) {
|
if (show_mem || show_tcpinfo) {
|
||||||
struct rtattr * tb[TCPDIAG_MAX+1];
|
printf("\n\t");
|
||||||
struct tcpdiag_meminfo *minfo = NULL;
|
tcp_show_info(nlh, r);
|
||||||
struct tcp_info *info = NULL;
|
}
|
||||||
|
|
||||||
memset(tb, 0, sizeof(tb));
|
|
||||||
parse_rtattr(tb, TCPDIAG_MAX, (struct rtattr*)(r+1),
|
|
||||||
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
|
|
||||||
if (tb[TCPDIAG_MEMINFO])
|
|
||||||
minfo = RTA_DATA(tb[TCPDIAG_MEMINFO]);
|
|
||||||
if (tb[TCPDIAG_INFO])
|
|
||||||
info = RTA_DATA(tb[TCPDIAG_INFO]);
|
|
||||||
if (minfo) {
|
|
||||||
printf(" mem:(r%u,w%u,f%u,t%u)",
|
|
||||||
minfo->tcpdiag_rmem,
|
|
||||||
minfo->tcpdiag_wmem,
|
|
||||||
minfo->tcpdiag_fmem,
|
|
||||||
minfo->tcpdiag_tmem);
|
|
||||||
}
|
|
||||||
if (info) {
|
|
||||||
#ifdef TCP_INFO
|
|
||||||
if (info->tcpi_rto && info->tcpi_rto != 3000000)
|
|
||||||
printf(" rto:%g", (double)info->tcpi_rto/1000);
|
|
||||||
if (info->tcpi_rtt)
|
|
||||||
printf(" rtt:%g/%g", (double)info->tcpi_rtt/1000,
|
|
||||||
(double)info->tcpi_rttvar/1000);
|
|
||||||
if (info->tcpi_ato)
|
|
||||||
printf(" ato:%g", (double)info->tcpi_ato/1000);
|
|
||||||
if (info->tcpi_snd_cwnd != 2)
|
|
||||||
printf(" cwnd:%d", info->tcpi_snd_cwnd);
|
|
||||||
if (info->tcpi_snd_ssthresh < 0xFFFF)
|
|
||||||
printf(" ssthresh:%d", info->tcpi_snd_ssthresh);
|
|
||||||
#else
|
|
||||||
#warning No TCP_INFO. Please, do not repeat this experiment, use right kernel.
|
|
||||||
printf(" MORE_INFO_PROVIDED_YOU_COMPILED_SS_RIGHT");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1397,8 +1428,12 @@ int tcp_show_netlink(struct filter *f, FILE *dump_fp)
|
||||||
req.r.tcpdiag_states = f->states;
|
req.r.tcpdiag_states = f->states;
|
||||||
if (show_mem)
|
if (show_mem)
|
||||||
req.r.tcpdiag_ext |= (1<<(TCPDIAG_MEMINFO-1));
|
req.r.tcpdiag_ext |= (1<<(TCPDIAG_MEMINFO-1));
|
||||||
if (show_tcpinfo)
|
if (show_tcpinfo) {
|
||||||
req.r.tcpdiag_ext |= (1<<(TCPDIAG_INFO-1));
|
req.r.tcpdiag_ext |= (1<<(TCPDIAG_INFO-1));
|
||||||
|
#ifdef TCPDIAG_VEGASINFO
|
||||||
|
req.r.tcpdiag_ext |= (1<<(TCPDIAG_VEGASINFO-1));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
iov[0] = (struct iovec){ &req, sizeof(req) };
|
iov[0] = (struct iovec){ &req, sizeof(req) };
|
||||||
if (f->f) {
|
if (f->f) {
|
||||||
|
|
@ -2285,7 +2320,7 @@ static void usage(void)
|
||||||
" ss [ OPTIONS ] [ FILTER ]\n"
|
" ss [ OPTIONS ] [ FILTER ]\n"
|
||||||
"where OPTIONS := { -h[elp] | -V[ersion] | -n[umeric] | -r[esolve] |\n"
|
"where OPTIONS := { -h[elp] | -V[ersion] | -n[umeric] | -r[esolve] |\n"
|
||||||
" -a[ll] -l[istening] -o[ptions] -e[xtended] -p[rocesses]\n"
|
" -a[ll] -l[istening] -o[ptions] -e[xtended] -p[rocesses]\n"
|
||||||
" -A QUERY } -s[ummary]\n"
|
" -A QUERY -i[nfo] } -s[ummary]\n"
|
||||||
" -f[amily] { inet | inet6 | link | unix } }\n"
|
" -f[amily] { inet | inet6 | link | unix } }\n"
|
||||||
" QUERY := {all|inet|tcp|udp|raw|unix|packet|netlink}[,QUERY]\n"
|
" QUERY := {all|inet|tcp|udp|raw|unix|packet|netlink}[,QUERY]\n"
|
||||||
" FILTER := [ state TCP-STATE ] [ EXPRESSION ]\n"
|
" FILTER := [ state TCP-STATE ] [ EXPRESSION ]\n"
|
||||||
|
|
@ -2294,7 +2329,7 @@ static void usage(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int scan_state(char *state)
|
int scan_state(const char *state)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (strcasecmp(state, "close") == 0 ||
|
if (strcasecmp(state, "close") == 0 ||
|
||||||
|
|
@ -2321,14 +2356,13 @@ int scan_state(char *state)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int do_default = 1;
|
int do_default = 1;
|
||||||
int saw_states = 0;
|
int saw_states = 0;
|
||||||
int saw_query = 0;
|
int saw_query = 0;
|
||||||
int do_summary = 0;
|
int do_summary = 0;
|
||||||
char *dump_tcpdiag = NULL;
|
const char *dump_tcpdiag = NULL;
|
||||||
FILE *filter_fp = NULL;
|
FILE *filter_fp = NULL;
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
|
|
@ -2336,7 +2370,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
current_filter.states = default_filter.states;
|
current_filter.states = default_filter.states;
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "h?aletuwxnro460spfmiA:D:F:vV")) != EOF) {
|
while ((ch = getopt(argc, argv, "h?aletuwxnro460spf:miA:D:F:vV")) != EOF) {
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
case 'n':
|
case 'n':
|
||||||
resolve_services = 0;
|
resolve_services = 0;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue