Commit ec4d0d8a authored by Vadim Kochan's avatar Vadim Kochan Committed by Stephen Hemminger

ss: Replace unixstat struct by new sockstat struct

Signed-off-by: default avatarVadim Kochan <vadim4j@gmail.com>
parent 89f634f9
...@@ -661,6 +661,18 @@ static int get_slabstat(struct slabstat *s) ...@@ -661,6 +661,18 @@ static int get_slabstat(struct slabstat *s)
return 0; return 0;
} }
static inline void sock_addr_set_str(inet_prefix *prefix, char **ptr)
{
memcpy(prefix->data, ptr, sizeof(char *));
}
static inline char *sock_addr_get_str(const inet_prefix *prefix)
{
char *tmp ;
memcpy(&tmp, prefix->data, sizeof(char *));
return tmp;
}
static const char *sstate_name[] = { static const char *sstate_name[] = {
"UNKNOWN", "UNKNOWN",
[SS_ESTABLISHED] = "ESTAB", [SS_ESTABLISHED] = "ESTAB",
...@@ -693,7 +705,8 @@ static const char *sstate_namel[] = { ...@@ -693,7 +705,8 @@ static const char *sstate_namel[] = {
struct sockstat struct sockstat
{ {
uint8_t type; struct sockstat *next;
unsigned int type;
uint16_t prot; uint16_t prot;
inet_prefix local; inet_prefix local;
inet_prefix remote; inet_prefix remote;
...@@ -997,9 +1010,9 @@ static int inet2_addr_match(const inet_prefix *a, const inet_prefix *p, ...@@ -997,9 +1010,9 @@ static int inet2_addr_match(const inet_prefix *a, const inet_prefix *p,
static int unix_match(const inet_prefix *a, const inet_prefix *p) static int unix_match(const inet_prefix *a, const inet_prefix *p)
{ {
char *addr, *pattern; char *addr = sock_addr_get_str(a);
memcpy(&addr, a->data, sizeof(addr)); char *pattern = sock_addr_get_str(p);
memcpy(&pattern, p->data, sizeof(pattern));
if (pattern == NULL) if (pattern == NULL)
return 1; return 1;
if (addr == NULL) if (addr == NULL)
...@@ -1015,8 +1028,7 @@ static int run_ssfilter(struct ssfilter *f, struct sockstat *s) ...@@ -1015,8 +1028,7 @@ static int run_ssfilter(struct ssfilter *f, struct sockstat *s)
static int low, high=65535; static int low, high=65535;
if (s->local.family == AF_UNIX) { if (s->local.family == AF_UNIX) {
char *p; char *p = sock_addr_get_str(&s->local);
memcpy(&p, s->local.data, sizeof(p));
return p == NULL || (p[0] == '@' && strlen(p) == 6 && return p == NULL || (p[0] == '@' && strlen(p) == 6 &&
strspn(p+1, "0123456789abcdef") == 5); strspn(p+1, "0123456789abcdef") == 5);
} }
...@@ -1336,7 +1348,7 @@ void *parse_hostcond(char *addr) ...@@ -1336,7 +1348,7 @@ void *parse_hostcond(char *addr)
addr+=5; addr+=5;
p = strdup(addr); p = strdup(addr);
a.addr.bitlen = 8*strlen(p); a.addr.bitlen = 8*strlen(p);
memcpy(a.addr.data, &p, sizeof(p)); sock_addr_set_str(&a.addr, &p);
fam = AF_UNIX; fam = AF_UNIX;
goto out; goto out;
} }
...@@ -2427,31 +2439,21 @@ outerr: ...@@ -2427,31 +2439,21 @@ outerr:
} while (0); } while (0);
} }
struct unixstat
{
struct unixstat *next;
int ino;
int peer;
char *peer_name;
int rq;
int wq;
int state;
int type;
char *name;
};
int unix_state_map[] = { SS_CLOSE, SS_SYN_SENT, int unix_state_map[] = { SS_CLOSE, SS_SYN_SENT,
SS_ESTABLISHED, SS_CLOSING }; SS_ESTABLISHED, SS_CLOSING };
#define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct unixstat)) #define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct sockstat))
static void unix_list_free(struct unixstat *list) static void unix_list_free(struct sockstat *list)
{ {
while (list) { while (list) {
struct unixstat *s = list; struct sockstat *s = list;
char *name = sock_addr_get_str(&s->local);
list = list->next; list = list->next;
if (s->name)
free(s->name); if (name)
free(name);
free(s); free(s);
} }
} }
...@@ -2475,7 +2477,7 @@ static const char *unix_netid_name(int type) ...@@ -2475,7 +2477,7 @@ static const char *unix_netid_name(int type)
return netid; return netid;
} }
static bool unix_type_skip(struct unixstat *s, struct filter *f) static bool unix_type_skip(struct sockstat *s, struct filter *f)
{ {
if (s->type == SOCK_STREAM && !(f->dbs&(1<<UNIX_ST_DB))) if (s->type == SOCK_STREAM && !(f->dbs&(1<<UNIX_ST_DB)))
return true; return true;
...@@ -2486,44 +2488,49 @@ static bool unix_type_skip(struct unixstat *s, struct filter *f) ...@@ -2486,44 +2488,49 @@ static bool unix_type_skip(struct unixstat *s, struct filter *f)
return false; return false;
} }
static void unix_stats_print(struct unixstat *list, struct filter *f) static bool unix_use_proc(void)
{
return getenv("PROC_NET_UNIX") || getenv("PROC_ROOT");
}
static void unix_stats_print(struct sockstat *list, struct filter *f)
{ {
struct unixstat *s; struct sockstat *s;
char *peer; char *local, *peer;
bool use_proc = unix_use_proc();
for (s = list; s; s = s->next) { for (s = list; s; s = s->next) {
if (!(f->states & (1<<s->state))) if (!(f->states & (1 << s->state)))
continue; continue;
if (unix_type_skip(s, f)) if (unix_type_skip(s, f))
continue; continue;
peer = "*"; local = sock_addr_get_str(&s->local);
if (s->peer_name) peer = "*";
peer = s->peer_name;
if (s->rport && use_proc) {
struct sockstat *p;
if (s->peer && !s->peer_name) {
struct unixstat *p;
for (p = list; p; p = p->next) { for (p = list; p; p = p->next) {
if (s->peer == p->ino) if (s->rport == p->lport)
break; break;
} }
if (!p) { if (!p) {
peer = "?"; peer = "?";
} else { } else {
peer = p->name ? : "*"; peer = sock_addr_get_str(&p->local);
peer = peer ? : "*";
} }
} }
if (f->f) { if (f->f) {
struct sockstat st;
st.local.family = AF_UNIX;
st.remote.family = AF_UNIX;
memcpy(st.local.data, &s->name, sizeof(s->name));
if (strcmp(peer, "*") == 0) if (strcmp(peer, "*") == 0)
memset(st.remote.data, 0, sizeof(peer)); memset(s->remote.data, 0, sizeof(char *));
else else
memcpy(st.remote.data, &peer, sizeof(peer)); sock_addr_set_str(&s->remote, &peer);
if (run_ssfilter(f->f, &st) == 0)
if (run_ssfilter(f->f, s) == 0)
continue; continue;
} }
...@@ -2534,8 +2541,8 @@ static void unix_stats_print(struct unixstat *list, struct filter *f) ...@@ -2534,8 +2541,8 @@ static void unix_stats_print(struct unixstat *list, struct filter *f)
printf("%-*s ", state_width, sstate_name[s->state]); printf("%-*s ", state_width, sstate_name[s->state]);
printf("%-6d %-6d ", s->rq, s->wq); printf("%-6d %-6d ", s->rq, s->wq);
printf("%*s %-*d %*s %-*d", printf("%*s %-*d %*s %-*d",
addr_width, s->name ? : "*", serv_width, s->ino, addr_width, local ? : "*", serv_width,
addr_width, peer, serv_width, s->peer); s->lport, addr_width, peer, serv_width, s->rport);
char *buf = NULL; char *buf = NULL;
if (show_proc_ctx || show_sock_ctx) { if (show_proc_ctx || show_sock_ctx) {
...@@ -2561,15 +2568,16 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh, ...@@ -2561,15 +2568,16 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
struct filter *f = (struct filter *)arg; struct filter *f = (struct filter *)arg;
struct unix_diag_msg *r = NLMSG_DATA(nlh); struct unix_diag_msg *r = NLMSG_DATA(nlh);
struct rtattr *tb[UNIX_DIAG_MAX+1]; struct rtattr *tb[UNIX_DIAG_MAX+1];
char name[128]; char *name = NULL;
struct unixstat stat = { .name = "*" , .peer_name = "*" }; struct sockstat stat = {};
parse_rtattr(tb, UNIX_DIAG_MAX, (struct rtattr*)(r+1), parse_rtattr(tb, UNIX_DIAG_MAX, (struct rtattr*)(r+1),
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
stat.type = r->udiag_type; stat.type = r->udiag_type;
stat.state = r->udiag_state; stat.state = r->udiag_state;
stat.ino = r->udiag_ino; stat.ino = stat.lport = r->udiag_ino;
stat.local.family = stat.remote.family = AF_UNIX;
if (unix_type_skip(&stat, f)) if (unix_type_skip(&stat, f))
return 0; return 0;
...@@ -2582,14 +2590,15 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh, ...@@ -2582,14 +2590,15 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
if (tb[UNIX_DIAG_NAME]) { if (tb[UNIX_DIAG_NAME]) {
int len = RTA_PAYLOAD(tb[UNIX_DIAG_NAME]); int len = RTA_PAYLOAD(tb[UNIX_DIAG_NAME]);
name = malloc(len + 1);
memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len); memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len);
name[len] = '\0'; name[len] = '\0';
if (name[0] == '\0') if (name[0] == '\0')
name[0] = '@'; name[0] = '@';
stat.name = &name[0]; sock_addr_set_str(&stat.local, &name);
} }
if (tb[UNIX_DIAG_PEER]) if (tb[UNIX_DIAG_PEER])
stat.peer = rta_getattr_u32(tb[UNIX_DIAG_PEER]); stat.rport = rta_getattr_u32(tb[UNIX_DIAG_PEER]);
unix_stats_print(&stat, f); unix_stats_print(&stat, f);
...@@ -2606,6 +2615,9 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh, ...@@ -2606,6 +2615,9 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
} }
if (show_mem || show_details) if (show_mem || show_details)
printf("\n"); printf("\n");
if (name)
free(name);
return 0; return 0;
} }
...@@ -2652,13 +2664,12 @@ static int unix_show(struct filter *f) ...@@ -2652,13 +2664,12 @@ static int unix_show(struct filter *f)
char name[128]; char name[128];
int newformat = 0; int newformat = 0;
int cnt; int cnt;
struct unixstat *list = NULL; struct sockstat *list = NULL;
if (!filter_af_get(f, AF_UNIX)) if (!filter_af_get(f, AF_UNIX))
return 0; return 0;
if (!getenv("PROC_NET_UNIX") && !getenv("PROC_ROOT") if (!unix_use_proc() && unix_show_netlink(f) == 0)
&& unix_show_netlink(f) == 0)
return 0; return 0;
if ((fp = net_unix_open()) == NULL) if ((fp = net_unix_open()) == NULL)
...@@ -2670,31 +2681,30 @@ static int unix_show(struct filter *f) ...@@ -2670,31 +2681,30 @@ static int unix_show(struct filter *f)
cnt = 0; cnt = 0;
while (fgets(buf, sizeof(buf)-1, fp)) { while (fgets(buf, sizeof(buf)-1, fp)) {
struct unixstat *u, **insp; struct sockstat *u, **insp;
int flags; int flags;
if (!(u = malloc(sizeof(*u)))) if (!(u = malloc(sizeof(*u))))
break; break;
u->name = NULL;
u->peer_name = NULL;
if (sscanf(buf, "%x: %x %x %x %x %x %d %s", if (sscanf(buf, "%x: %x %x %x %x %x %d %s",
&u->peer, &u->rq, &u->wq, &flags, &u->type, &u->rport, &u->rq, &u->wq, &flags, &u->type,
&u->state, &u->ino, name) < 8) &u->state, &u->ino, name) < 8)
name[0] = 0; name[0] = 0;
if (flags&(1<<16)) { u->lport = u->ino;
u->local.family = u->remote.family = AF_UNIX;
if (flags & (1 << 16)) {
u->state = SS_LISTEN; u->state = SS_LISTEN;
} else { } else {
u->state = unix_state_map[u->state-1]; u->state = unix_state_map[u->state-1];
if (u->type == SOCK_DGRAM && if (u->type == SOCK_DGRAM && u->state == SS_CLOSE && u->rport)
u->state == SS_CLOSE &&
u->peer)
u->state = SS_ESTABLISHED; u->state = SS_ESTABLISHED;
} }
if (!newformat) { if (!newformat) {
u->peer = 0; u->rport = 0;
u->rq = 0; u->rq = 0;
u->wq = 0; u->wq = 0;
} }
...@@ -2711,9 +2721,8 @@ static int unix_show(struct filter *f) ...@@ -2711,9 +2721,8 @@ static int unix_show(struct filter *f)
*insp = u; *insp = u;
if (name[0]) { if (name[0]) {
if ((u->name = malloc(strlen(name)+1)) == NULL) char *tmp = strdup(name);
break; sock_addr_set_str(&u->local, &tmp);
strcpy(u->name, name);
} }
if (++cnt > MAX_UNIX_REMEMBER) { if (++cnt > MAX_UNIX_REMEMBER) {
unix_stats_print(list, f); unix_stats_print(list, f);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment