X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=misc%2Fss.c;h=651fe3b52476a84e131d60022f8c3ca05486e88a;hb=7132284647c15ca30d942926bc506d6019d3b61c;hp=f902560aa165a0f9ba7fa8aca879d1a7617e5f50;hpb=105da95218c9d30375efc43f9edd8ef32998fedb;p=iproute2.git diff --git a/misc/ss.c b/misc/ss.c index f902560..651fe3b 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -33,9 +33,8 @@ #include "libnetlink.h" #include "SNAPSHOT.h" +#include #include -#include -#include int resolve_hosts = 0; int resolve_services = 1; @@ -105,101 +104,98 @@ struct filter }; struct filter default_filter = { - dbs: (1<s_name; @@ -537,7 +534,7 @@ const char *resolve_service(int port) const char *res; int hash = (port^(((unsigned long)dg_proto)>>2))&255; - for (c = &cache[hash]; c; c = c->next) { + for (c = &cache[hash]; c; c = c->next) { if (c->port == port && c->proto == dg_proto) { if (c->name) @@ -647,7 +644,7 @@ int run_ssfilter(struct ssfilter *f, struct tcpstat *s) char *p; memcpy(&p, s->local.data, sizeof(p)); return p == NULL || (p[0] == '@' && strlen(p) == 6 && - strspn(p+1, "0123456789abcdef") == 5); + strspn(p+1, "0123456789abcdef") == 5); } if (s->local.family == AF_PACKET) return s->lport == 0 && s->local.data == 0; @@ -655,7 +652,7 @@ int run_ssfilter(struct ssfilter *f, struct tcpstat *s) return s->lport < 0; if (!low) { - FILE *fp = fdopen(ephemeral_ports_open(), "r"); + FILE *fp = ephemeral_ports_open(); if (fp) { fscanf(fp, "%d%d", &low, &high); fclose(fp); @@ -690,7 +687,7 @@ int run_ssfilter(struct ssfilter *f, struct tcpstat *s) do { if (!inet2_addr_match(&s->local, &a->addr, a->addr.bitlen)) return 1; - } while ((a = a->next) != NULL); + } while ((a = a->next) != NULL); return 0; } return 1; @@ -728,7 +725,7 @@ int run_ssfilter(struct ssfilter *f, struct tcpstat *s) } } -/* Relocate external jumps by reloc. */ +/* Relocate external jumps by reloc. */ static void ssfilter_patch(char *a, int len, int reloc) { while (len > 0) { @@ -868,7 +865,7 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode) static int remember_he(struct aafilter *a, struct hostent *he) { - char **ptr = he->h_addr_list; + char **ptr = he->h_addr_list; int cnt = 0; int len; @@ -1103,35 +1100,35 @@ void *parse_hostcond(char *addr) return res; } -static int tcp_show_line(char *line, struct filter *f, int family) +static int tcp_show_line(char *line, const struct filter *f, int family) { struct tcpstat s; char *loc, *rem, *data; char opt[256]; int n; char *p; - + if ((p = strchr(line, ':')) == NULL) return -1; loc = p+2; - + if ((p = strchr(loc, ':')) == NULL) return -1; p[5] = 0; rem = p+6; - + if ((p = strchr(rem, ':')) == NULL) return -1; p[5] = 0; data = p+6; - + do { int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0'); if (!(f->states & (1<f && run_ssfilter(f->f, &s) == 0) return 0; - + opt[0] = 0; - n = sscanf(data, "%x %x:%x %x:%x %x %d %d %d %d %llx %d %d %d %d %d %[^\n]\n", + n = sscanf(data, "%x %x:%x %x:%x %x %d %d %u %d %llx %d %d %d %d %d %[^\n]\n", &s.state, &s.wq, &s.rq, &s.timer, &s.timeout, &s.retrs, &s.uid, &s.probes, &s.ino, &s.refcnt, &s.sk, &s.rto, &s.ato, &s.qack, &s.cwnd, &s.ssthresh, opt); - + if (n < 17) opt[0] = 0; - + if (n < 12) { s.rto = 0; s.cwnd = 2; s.ssthresh = -1; s.ato = s.qack = 0; } - + if (netid_width) printf("%-*s ", netid_width, "tcp"); if (state_width) printf("%-*s ", state_width, sstate_name[s.state]); - + printf("%-6d %-6d ", s.rq, s.wq); - + formatted_print(&s.local, s.lport); formatted_print(&s.remote, s.rport); - + if (show_options) { if (s.timer) { if (s.timer > 4) @@ -1194,10 +1191,11 @@ static int tcp_show_line(char *line, struct filter *f, int family) } } if (show_tcpinfo) { - if (s.rto && s.rto != 3*get_hz()) - printf(" rto:%g", (double)s.rto/get_hz()); + int hz = get_user_hz(); + if (s.rto && s.rto != 3*hz) + printf(" rto:%g", (double)s.rto/hz); if (s.ato) - printf(" ato:%g", (double)s.ato/get_hz()); + printf(" ato:%g", (double)s.ato/hz); if (s.cwnd != 2) printf(" cwnd:%d", s.cwnd); if (s.ssthresh != -1) @@ -1215,7 +1213,7 @@ static int tcp_show_line(char *line, struct filter *f, int family) if (show_details) { if (s.uid) printf(" uid:%u", (unsigned)s.uid); - printf(" ino:%u", (unsigned)s.ino); + printf(" ino:%u", s.ino); printf(" sk:%llx", s.sk); if (opt[0]) printf(" opt:\"%s\"", opt); @@ -1225,73 +1223,35 @@ static int tcp_show_line(char *line, struct filter *f, int family) return 0; } -static int generic_record_read(int fd, char *buf, int bufsize, - int (*worker)(char*, struct filter *, int), - struct filter *f, int fam) +static int generic_record_read(FILE *fp, + int (*worker)(char*, const struct filter *, int), + const struct filter *f, int fam) { - int n; - int recsize; - int eof = 0; - char *p; + char line[256]; - /* Load the first chunk and calculate record length from it. */ - n = read(fd, buf, bufsize); - if (n < 0) + /* skip header */ + if (fgets(line, sizeof(line), fp) == NULL) goto outerr; - /* I _know_ that this is wrong, do not remind. :-) - * But this works nowadays. */ - if (n < bufsize) - eof = 1; - p = memchr(buf, '\n', n); - if (p == NULL || (p-buf) >= n) - goto outwrongformat; - recsize = (p-buf)+1; - p = buf+recsize; - - for (;;) { - while ((p+recsize) - buf <= n) { - if (p[recsize-1] != '\n') - goto outwrongformat; - p[recsize-1] = 0; - if (worker(p, f, fam) < 0) - goto done; - p += recsize; - } - if (!eof) { - int remains = (buf+bufsize) - p; - memcpy(buf, p, remains); - p = buf+remains; - n = read(fd, p, (buf+bufsize) - p); - if (n < 0) - goto outerr; - if (n < (buf+bufsize) - p) { - eof = 1; - if (n == 0) { - if (remains) - goto outwrongformat; - goto done; - } - } - n += remains; - p = buf; - } else { - if (p != buf+n) - goto outwrongformat; - goto done; + + while (fgets(line, sizeof(line), fp) != NULL) { + int n = strlen(line); + if (n == 0 || line[n-1] != '\n') { + errno = -EINVAL; + return -1; } - } -done: - return 0; + line[n-1] = 0; -outwrongformat: - errno = EINVAL; + if (worker(line, f, fam) < 0) + return 0; + } outerr: - return -1; + + return ferror(fp) ? -1 : 0; } - + static char *sprint_bw(char *buf, double bw) { - if (bw > 1000000.) + if (bw > 1000000.) sprintf(buf,"%.1fM", bw / 1000000.); else if (bw > 1000.) sprintf(buf,"%.1fK", bw / 1000.); @@ -1344,7 +1304,7 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r) if (tb[INET_DIAG_CONG]) printf("%s", (char *) RTA_DATA(tb[INET_DIAG_CONG])); - if (info->tcpi_options & TCPI_OPT_WSCALE) + if (info->tcpi_options & TCPI_OPT_WSCALE) printf(" wscale:%d,%d", info->tcpi_snd_wscale, info->tcpi_rcv_wscale); if (info->tcpi_rto && info->tcpi_rto != 3000000) @@ -1364,7 +1324,7 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r) const struct tcpvegas_info *vinfo = RTA_DATA(tb[INET_DIAG_VEGASINFO]); - if (vinfo->tcpv_enabled && + if (vinfo->tcpv_enabled && vinfo->tcpv_rtt && vinfo->tcpv_rtt != 0x7fffffff) rtt = vinfo->tcpv_rtt; } @@ -1384,7 +1344,7 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r) } } -int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f) +static int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f) { struct inet_diag_msg *r = NLMSG_DATA(nlh); struct tcpstat s; @@ -1432,7 +1392,7 @@ int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f) if (show_details) { if (r->idiag_uid) printf(" uid:%u", (unsigned)r->idiag_uid); - printf(" ino:%u", (unsigned)r->idiag_inode); + printf(" ino:%u", r->idiag_inode); printf(" sk:%08x", r->id.idiag_cookie[0]); if (r->id.idiag_cookie[1] != 0) printf("%08x", r->id.idiag_cookie[1]); @@ -1447,7 +1407,7 @@ int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f) return 0; } -int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype) +static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype) { int fd; struct sockaddr_nl nladdr; @@ -1477,7 +1437,7 @@ int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype) req.r.idiag_family = AF_INET; req.r.idiag_states = f->states; if (show_mem) - req.r.idiag_ext |= (1<<(INET_DIAG_MEMINFO-1)); + req.r.idiag_ext |= (1<<(INET_DIAG_MEMINFO-1)); if (show_tcpinfo) { req.r.idiag_ext |= (1<<(INET_DIAG_INFO-1)); @@ -1485,9 +1445,9 @@ int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype) req.r.idiag_ext |= (1<<(INET_DIAG_CONG-1)); } - iov[0] = (struct iovec){ - .iov_base = &req, - .iov_len = sizeof(req) + iov[0] = (struct iovec){ + .iov_base = &req, + .iov_len = sizeof(req) }; if (f->f) { bclen = ssfilter_bytecompile(f->f, &bc); @@ -1499,18 +1459,18 @@ int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype) } msg = (struct msghdr) { - .msg_name = (void*)&nladdr, + .msg_name = (void*)&nladdr, .msg_namelen = sizeof(nladdr), - .msg_iov = iov, + .msg_iov = iov, .msg_iovlen = f->f ? 3 : 1, }; if (sendmsg(fd, &msg, 0) < 0) return -1; - iov[0] = (struct iovec){ - .iov_base = buf, - .iov_len = sizeof(buf) + iov[0] = (struct iovec){ + .iov_base = buf, + .iov_len = sizeof(buf) }; while (1) { @@ -1543,6 +1503,7 @@ int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype) h = (struct nlmsghdr*)buf; while (NLMSG_OK(h, status)) { int err; + struct inet_diag_msg *r = NLMSG_DATA(h); if (/*h->nlmsg_pid != rth->local.nl_pid ||*/ h->nlmsg_seq != 123456) @@ -1561,6 +1522,10 @@ int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype) return 0; } if (!dump_fp) { + if (!(f->families & (1<idiag_family))) { + h = NLMSG_NEXT(h, status); + continue; + } err = tcp_show_sock(h, NULL); if (err < 0) return err; @@ -1581,7 +1546,7 @@ skip_it: return 0; } -int tcp_show_netlink_file(struct filter *f) +static int tcp_show_netlink_file(struct filter *f) { FILE *fp; char buf[8192]; @@ -1637,9 +1602,9 @@ int tcp_show_netlink_file(struct filter *f) } } -int tcp_show(struct filter *f, int socktype) +static int tcp_show(struct filter *f, int socktype) { - int fd = -1; + FILE *fp = NULL; char *buf = NULL; int bufsize = 64*1024; @@ -1654,6 +1619,7 @@ int tcp_show(struct filter *f, int socktype) /* Sigh... We have to parse /proc/net/tcp... */ + /* Estimate amount of sockets and try to allocate * huge buffer to read all the table at one read. * Limit it by 16MB though. The assumption is: as soon as @@ -1681,18 +1647,21 @@ int tcp_show(struct filter *f, int socktype) } if (f->families & (1<families & (1<= 0) { - if (generic_record_read(fd, buf, bufsize, tcp_show_line, f, AF_INET6)) + (fp = net_tcp6_open()) != NULL) { + setbuffer(fp, buf, bufsize); + if (generic_record_read(fp, tcp_show_line, f, AF_INET6)) goto outerr; - close(fd); + fclose(fp); } free(buf); @@ -1703,15 +1672,15 @@ outerr: int saved_errno = errno; if (buf) free(buf); - if (fd >= 0) - close(fd); + if (fp) + fclose(fp); errno = saved_errno; return -1; } while (0); } -int dgram_show_line(char *line, struct filter *f, int family) +int dgram_show_line(char *line, const struct filter *f, int family) { struct tcpstat s; char *loc, *rem, *data; @@ -1765,7 +1734,7 @@ int dgram_show_line(char *line, struct filter *f, int family) return 0; opt[0] = 0; - n = sscanf(data, "%x %x:%x %*x:%*x %*x %d %*d %d %d %llx %[^\n]\n", + n = sscanf(data, "%x %x:%x %*x:%*x %*x %d %*d %u %d %llx %[^\n]\n", &s.state, &s.wq, &s.rq, &s.uid, &s.ino, &s.refcnt, &s.sk, opt); @@ -1792,7 +1761,7 @@ int dgram_show_line(char *line, struct filter *f, int family) if (show_details) { if (s.uid) printf(" uid=%u", (unsigned)s.uid); - printf(" ino=%u", (unsigned)s.ino); + printf(" ino=%u", s.ino); printf(" sk=%llx", s.sk); if (opt[0]) printf(" opt:\"%s\"", opt); @@ -1805,33 +1774,31 @@ int dgram_show_line(char *line, struct filter *f, int family) int udp_show(struct filter *f) { - int fd = -1; - char buf[8192]; - int bufsize = sizeof(buf); + FILE *fp = NULL; dg_proto = UDP_PROTO; if (f->families&(1<families&(1<= 0) { - if (generic_record_read(fd, buf, bufsize, dgram_show_line, f, AF_INET6)) + (fp = net_udp6_open()) != NULL) { + if (generic_record_read(fp, dgram_show_line, f, AF_INET6)) goto outerr; - close(fd); + fclose(fp); } return 0; outerr: do { int saved_errno = errno; - if (fd >= 0) - close(fd); + if (fp) + fclose(fp); errno = saved_errno; return -1; } while (0); @@ -1839,33 +1806,31 @@ outerr: int raw_show(struct filter *f) { - int fd = -1; - char buf[8192]; - int bufsize = sizeof(buf); + FILE *fp = NULL; dg_proto = RAW_PROTO; if (f->families&(1<families&(1<= 0) { - if (generic_record_read(fd, buf, bufsize, dgram_show_line, f, AF_INET6)) + (fp = net_raw6_open()) != NULL) { + if (generic_record_read(fp, dgram_show_line, f, AF_INET6)) goto outerr; - close(fd); + fclose(fp); } return 0; outerr: do { int saved_errno = errno; - if (fd >= 0) - close(fd); + if (fp) + fclose(fp); errno = saved_errno; return -1; } while (0); @@ -1938,13 +1903,13 @@ void unix_list_print(struct unixstat *list, struct filter *f) if (strcmp(peer, "*") == 0) memset(tst.remote.data, 0, sizeof(peer)); else - memcpy(tst.remote.data, &peer, sizeof(peer)); + memcpy(tst.remote.data, &peer, sizeof(peer)); if (run_ssfilter(f->f, &tst) == 0) continue; } if (netid_width) - printf("%-*s ", netid_width, + printf("%-*s ", netid_width, s->type == SOCK_STREAM ? "u_str" : "u_dgr"); if (state_width) printf("%-*s ", state_width, sstate_name[s->state]); @@ -1970,11 +1935,11 @@ int unix_show(struct filter *f) int cnt; struct unixstat *list = NULL; - if ((fp = fdopen(net_unix_open(), "r")) == NULL) + if ((fp = net_unix_open()) == NULL) return -1; fgets(buf, sizeof(buf)-1, fp); - if (memcmp(buf, "Peer", 4) == 0) + if (memcmp(buf, "Peer", 4) == 0) newformat = 1; cnt = 0; @@ -2058,7 +2023,7 @@ int packet_show(struct filter *f) if (!(f->states & (1<states & (1<