Date: Sat, 11 Nov 2006 17:09:32 +0100 From: Giorgos Keramidas <keramida@freebsd.org> To: Josh Carroll <josh.carroll@psualum.com> Cc: freebsd-hackers@freebsd.org Subject: Re: sockstat tcp/udp switches Message-ID: <20061111160931.GB3979@kobe.laptop> In-Reply-To: <20061111154849.GC1972@kobe.laptop> References: <20061103024621.GB16445@kobe.laptop> <20061103024837.GB79357@lor.one-eyed-alien.net> <20061103025442.GB16543@kobe.laptop> <8cb6106e0611031550y1381b67agdc74144b89de763b@mail.gmail.com> <20061104062439.GD854@turion.vk2pj.dyndns.org> <8cb6106e0611061517k62c9193fnbbfc8e36db328282@mail.gmail.com> <20061107174151.GA51473@lor.one-eyed-alien.net> <8cb6106e0611071008y6811a79x9ba056c2be94d773@mail.gmail.com> <8cb6106e0611071051y6cbbca1padc24ba315d4a2b3@mail.gmail.com> <20061111154849.GC1972@kobe.laptop>
next in thread | previous in thread | raw e-mail | index | archive | help
--EeQfGwPcQSOJBaQU Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On 2006-11-11 16:48, Giorgos Keramidas <keramida@freebsd.org> wrote: > This patch still has some points which are in need of a slight > modification or rearrangement, but it works fine here. > > My comments, and a proposed patch to replace it (after some style fixes > and partial rewrite of the added code), are below: Maxim Konovalov reminded me of another style(9) issue we have to address. All 'return' statements should use parentheses: return (foo); The attached version of my last patch fixes that too, in the sockstat.c parts which are new. --EeQfGwPcQSOJBaQU Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="sockstat-protocol.patch" Add support for filtering sockets by protocol type. The default behavior of sockstat(1) will still be to show "udp", "tcp" and "divert" protocols, but we can now provide a (comma-separated) list of protocols, as in: % sockstat -P tcp to list only TCP sockets, or we can filter more than one protocol by separating the protocol names with a comma: % sockstat -P tcp,udp Protocol names are parsed with getprotobyname(3), so any protocol whose name is listed in `/etc/protocols' should work fine. Submitted by: Josh Carroll <josh.carroll@psualum.com> diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c --- a/usr.bin/sockstat/sockstat.c +++ b/usr.bin/sockstat/sockstat.c @@ -66,6 +66,16 @@ static int opt_u; /* Show Unix domain static int opt_u; /* Show Unix domain sockets */ static int opt_v; /* Verbose mode */ +/* + * Default protocols to use if no -P was defined. + */ +static const char *default_protos[] = {"tcp", "udp", "divert" }; +static size_t default_numprotos = + sizeof(default_protos) / sizeof(default_protos[0]); + +static int *protos; /* protocols to use */ +static size_t numprotos; /* allocated size of protos[] */ + static int *ports; #define INT_BIT (sizeof(int)*CHAR_BIT) @@ -103,6 +113,66 @@ xprintf(const char *fmt, ...) err(1, "printf()"); return (len); } + + +static int +get_proto_type(const char *proto) +{ + struct protoent *pent; + + if (strlen(proto) == 0) + return (0); + pent = getprotobyname(proto); + if (pent == NULL) { + warn("getprotobyname"); + return (-1); + } + return (pent->p_proto); +} + + +static void init_protos(int num) +{ + int proto_count = 0; + + if (num > 0) { + proto_count = num; + } else { + /* Find the maximum number of possible protocols. */ + while (getprotoent() != NULL) + proto_count++; + endprotoent(); + } + + if ((protos = malloc(sizeof(int) * proto_count)) == NULL) + err(1, "malloc"); + numprotos = proto_count; +} + + +static int +parse_protos(char *protospec) +{ + char *prot; + char *tmp = protospec; + int proto_type, proto_index; + + if (protospec == NULL) + return (-1); + + init_protos(0); + proto_index = 0; + while ((prot = strsep(&tmp, ",")) != NULL) { + if (strlen(prot) == 0) + continue; + proto_type = get_proto_type(prot); + if (proto_type != -1) + protos[proto_index++] = proto_type; + } + numprotos = proto_index; + return (proto_index); +} + static void parse_ports(const char *portspec) @@ -209,7 +279,7 @@ gather_inet(int proto) protoname = "div"; break; default: - abort(); + errx(1, "protocol %d not supported", proto); } buf = NULL; @@ -264,7 +334,7 @@ gather_inet(int proto) so = &xip->xi_socket; break; default: - abort(); + errx(1, "protocol %d not supported", proto); } if ((inp->inp_vflag & vflag) == 0) continue; @@ -573,19 +643,40 @@ display(void) } } +static int set_default_protos(void) +{ + struct protoent *prot; + const char *pname; + size_t pindex; + + init_protos(default_numprotos); + + for (pindex = 0; pindex < default_numprotos; pindex++) { + pname = default_protos[pindex]; + prot = getprotobyname(pname); + if (prot == NULL) + err(1, "getprotobyname: %s", pname); + protos[pindex] = prot->p_proto; + } + numprotos = pindex; + return (pindex); +} + + static void usage(void) { - fprintf(stderr, "Usage: sockstat [-46clu] [-p ports]\n"); + fprintf(stderr, "Usage: sockstat [-46clu] [-p ports] [-P protos]\n"); exit(1); } int main(int argc, char *argv[]) { - int o; - - while ((o = getopt(argc, argv, "46clp:uv")) != -1) + int protos_defined = -1; + int o, i; + + while ((o = getopt(argc, argv, "46clp:P:uv")) != -1) switch (o) { case '4': opt_4 = 1; @@ -602,6 +693,9 @@ main(int argc, char *argv[]) case 'p': parse_ports(optarg); break; + case 'P': + protos_defined = parse_protos(optarg); + break; case 'u': opt_u = 1; break; @@ -618,22 +712,30 @@ main(int argc, char *argv[]) if (argc > 0) usage(); - if (!opt_4 && !opt_6 && !opt_u) - opt_4 = opt_6 = opt_u = 1; + /* + * If protos_defined remains -1, no -P was provided, so we have to + * set up the default protocol list in protos[] first. + */ + if (!opt_4 && !opt_6 && !opt_u && protos_defined == -1) { + opt_u = 1; + protos_defined = set_default_protos(); + } + + if (!opt_4 && !opt_6) + opt_4 = opt_6 = 1; if (!opt_c && !opt_l) opt_c = opt_l = 1; if (opt_4 || opt_6) { - gather_inet(IPPROTO_TCP); - gather_inet(IPPROTO_UDP); - gather_inet(IPPROTO_DIVERT); - } - if (opt_u) { + for (i = 0; i < protos_defined; i++) + gather_inet(protos[i]); + } + + if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) { gather_unix(SOCK_STREAM); gather_unix(SOCK_DGRAM); } getfiles(); display(); - exit(0); } --EeQfGwPcQSOJBaQU--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20061111160931.GB3979>