]> git.proxmox.com Git - mirror_iproute2.git/commitdiff
ss: Replace unixstat struct by new sockstat struct
authorVadim Kochan <vadim4j@gmail.com>
Fri, 13 Feb 2015 20:14:00 +0000 (22:14 +0200)
committerStephen Hemminger <shemming@brocade.com>
Sun, 22 Feb 2015 00:40:26 +0000 (16:40 -0800)
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
misc/ss.c

index 4a7cbef140ae957d324e797e93d157e61efc80fc..03692a5dad52db82de36fe5bd4a42a79c0e9c902 100644 (file)
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -661,6 +661,18 @@ static int get_slabstat(struct slabstat *s)
        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[] = {
        "UNKNOWN",
        [SS_ESTABLISHED] = "ESTAB",
@@ -693,7 +705,8 @@ static const char *sstate_namel[] = {
 
 struct sockstat
 {
-       uint8_t             type;
+       struct sockstat    *next;
+       unsigned int        type;
        uint16_t            prot;
        inet_prefix         local;
        inet_prefix         remote;
@@ -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)
 {
-       char *addr, *pattern;
-       memcpy(&addr, a->data, sizeof(addr));
-       memcpy(&pattern, p->data, sizeof(pattern));
+       char *addr = sock_addr_get_str(a);
+       char *pattern = sock_addr_get_str(p);
+
        if (pattern == NULL)
                return 1;
        if (addr == NULL)
@@ -1015,8 +1028,7 @@ static int run_ssfilter(struct ssfilter *f, struct sockstat *s)
                 static int low, high=65535;
 
                if (s->local.family == AF_UNIX) {
-                       char *p;
-                       memcpy(&p, s->local.data, sizeof(p));
+                       char *p = sock_addr_get_str(&s->local);
                        return p == NULL || (p[0] == '@' && strlen(p) == 6 &&
                                             strspn(p+1, "0123456789abcdef") == 5);
                }
@@ -1336,7 +1348,7 @@ void *parse_hostcond(char *addr)
                        addr+=5;
                p = strdup(addr);
                a.addr.bitlen = 8*strlen(p);
-               memcpy(a.addr.data, &p, sizeof(p));
+               sock_addr_set_str(&a.addr, &p);
                fam = AF_UNIX;
                goto out;
        }
@@ -2427,31 +2439,21 @@ outerr:
        } 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,
                         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) {
-               struct unixstat *s = list;
+               struct sockstat *s = list;
+               char *name = sock_addr_get_str(&s->local);
+
                list = list->next;
-               if (s->name)
-                       free(s->name);
+
+               if (name)
+                       free(name);
                free(s);
        }
 }
@@ -2475,7 +2477,7 @@ static const char *unix_netid_name(int type)
        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)))
                return true;
@@ -2486,44 +2488,49 @@ static bool unix_type_skip(struct unixstat *s, struct filter *f)
        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;
-       char *peer;
+       struct sockstat *s;
+       char *local, *peer;
+       bool use_proc = unix_use_proc();
 
        for (s = list; s; s = s->next) {
-               if (!(f->states & (1<<s->state)))
+               if (!(f->states & (1 << s->state)))
                        continue;
                if (unix_type_skip(s, f))
                        continue;
 
-               peer = "*";
-               if (s->peer_name)
-                       peer = s->peer_name;
+               local = sock_addr_get_str(&s->local);
+               peer  = "*";
+
+               if (s->rport && use_proc) {
+                       struct sockstat *p;
 
-               if (s->peer && !s->peer_name) {
-                       struct unixstat *p;
                        for (p = list; p; p = p->next) {
-                               if (s->peer == p->ino)
+                               if (s->rport == p->lport)
                                        break;
                        }
+
                        if (!p) {
                                peer = "?";
                        } else {
-                               peer = p->name ? : "*";
+                               peer = sock_addr_get_str(&p->local);
+                               peer = peer ? : "*";
                        }
                }
 
                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)
-                               memset(st.remote.data, 0, sizeof(peer));
+                               memset(s->remote.data, 0, sizeof(char *));
                        else
-                               memcpy(st.remote.data, &peer, sizeof(peer));
-                       if (run_ssfilter(f->f, &st) == 0)
+                               sock_addr_set_str(&s->remote, &peer);
+
+                       if (run_ssfilter(f->f, s) == 0)
                                continue;
                }
 
@@ -2534,8 +2541,8 @@ static void unix_stats_print(struct unixstat *list, struct filter *f)
                        printf("%-*s ", state_width, sstate_name[s->state]);
                printf("%-6d %-6d ", s->rq, s->wq);
                printf("%*s %-*d %*s %-*d",
-                      addr_width, s->name ? : "*", serv_width, s->ino,
-                      addr_width, peer, serv_width, s->peer);
+                      addr_width, local ? : "*", serv_width,
+                      s->lport, addr_width, peer, serv_width, s->rport);
                char *buf = NULL;
 
                if (show_proc_ctx || show_sock_ctx) {
@@ -2561,15 +2568,16 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
        struct filter *f = (struct filter *)arg;
        struct unix_diag_msg *r = NLMSG_DATA(nlh);
        struct rtattr *tb[UNIX_DIAG_MAX+1];
-       char name[128];
-       struct unixstat stat = { .name = "*" , .peer_name = "*" };
+       char *name = NULL;
+       struct sockstat stat = {};
 
        parse_rtattr(tb, UNIX_DIAG_MAX, (struct rtattr*)(r+1),
                     nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
 
        stat.type  = r->udiag_type;
        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))
                return 0;
@@ -2582,14 +2590,15 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
        if (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);
                name[len] = '\0';
                if (name[0] == '\0')
                        name[0] = '@';
-               stat.name = &name[0];
+               sock_addr_set_str(&stat.local, &name);
        }
        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);
 
@@ -2606,6 +2615,9 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
        }
        if (show_mem || show_details)
                printf("\n");
+
+       if (name)
+               free(name);
        return 0;
 }
 
@@ -2652,13 +2664,12 @@ static int unix_show(struct filter *f)
        char name[128];
        int  newformat = 0;
        int  cnt;
-       struct unixstat *list = NULL;
+       struct sockstat *list = NULL;
 
        if (!filter_af_get(f, AF_UNIX))
                return 0;
 
-       if (!getenv("PROC_NET_UNIX") && !getenv("PROC_ROOT")
-           && unix_show_netlink(f) == 0)
+       if (!unix_use_proc() && unix_show_netlink(f) == 0)
                return 0;
 
        if ((fp = net_unix_open()) == NULL)
@@ -2670,31 +2681,30 @@ static int unix_show(struct filter *f)
        cnt = 0;
 
        while (fgets(buf, sizeof(buf)-1, fp)) {
-               struct unixstat *u, **insp;
+               struct sockstat *u, **insp;
                int flags;
 
                if (!(u = malloc(sizeof(*u))))
                        break;
-               u->name = NULL;
-               u->peer_name = NULL;
 
                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)
                        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;
                } else {
                        u->state = unix_state_map[u->state-1];
-                       if (u->type == SOCK_DGRAM &&
-                           u->state == SS_CLOSE &&
-                           u->peer)
+                       if (u->type == SOCK_DGRAM && u->state == SS_CLOSE && u->rport)
                                u->state = SS_ESTABLISHED;
                }
 
                if (!newformat) {
-                       u->peer = 0;
+                       u->rport = 0;
                        u->rq = 0;
                        u->wq = 0;
                }
@@ -2711,9 +2721,8 @@ static int unix_show(struct filter *f)
                *insp = u;
 
                if (name[0]) {
-                       if ((u->name = malloc(strlen(name)+1)) == NULL)
-                               break;
-                       strcpy(u->name, name);
+                       char *tmp = strdup(name);
+                       sock_addr_set_str(&u->local, &tmp);
                }
                if (++cnt > MAX_UNIX_REMEMBER) {
                        unix_stats_print(list, f);