Date: Fri, 3 Nov 2006 15:50:10 -0800 From: "Josh Carroll" <josh.carroll@psualum.com> To: freebsd-hackers@freebsd.org Subject: Re: sockstat tcp/udp switches Message-ID: <8cb6106e0611031550y1381b67agdc74144b89de763b@mail.gmail.com> In-Reply-To: <20061103025442.GB16543@kobe.laptop> References: <8cb6106e0610311058s7144d38bp2b1dafd114e2b433@mail.gmail.com> <20061102094748.G75543@mignon.ki.iif.hu> <8cb6106e0611021507n6315b629kad8cbbf901343c2@mail.gmail.com> <20061103021803.GC8508@kobe.laptop> <8cb6106e0611021834h17737556y4bb2fda39a4bfa0c@mail.gmail.com> <20061103024621.GB16445@kobe.laptop> <20061103024837.GB79357@lor.one-eyed-alien.net> <20061103025442.GB16543@kobe.laptop>
next in thread | previous in thread | raw e-mail | index | archive | help
Below is an initial attempt at the -P argument implementation. I'm not sure if the method used to parse out the protocol is "up to snuff" for the FreeBSD project, but I'm welcome to suggestions/advice/etc. I tested the previous behavior and given the exact command line, sockstat works the same prior to the patch and with the patch. So the -P option is additive only (so as not to break legacy scripts/automation that may parse the sockstat output). I included a limitation on the maximum length of a proto (mostly to avoid buffer overflows) and 20 is probably way too large, so I can lower that if need be. The -P argument also will sense and ignore multiple commas, e.g.: -P tcp,,udp Will still just detect tcp and udp. I implemented the protocols with a sort of lookup table for the protocol types for arguments to -P. So adding another protocol should be as easy as adding a #define, incrementing the #defined for NUM_PROTOS and updating the add_proto_type function to recognize and properly store the new protocol type. Again, I'm open to any feedback on this particular approach. Thanks again for everyone's attetion on this. It's a nice little project to get me ramped back up into C and I do appreciate all the feedback! Regards, Josh --- sockstat.c.orig Thu Nov 2 15:04:39 2006 +++ sockstat.c Fri Nov 3 15:25:34 2006 @@ -66,8 +66,15 @@ static int opt_u; /* Show Unix domain sockets */ static int opt_v; /* Verbose mode */ +#define NUM_PROTOS 2 +#define MAX_PROTO_LEN 20 +#define TCP_PROTO 0 +#define UDP_PROTO 1 +static int *protos; /* protocols to use */ + static int *ports; + #define INT_BIT (sizeof(int)*CHAR_BIT) #define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) @@ -105,6 +112,97 @@ } static void +clear_protos(void) +{ + int i; + + for(i=0; i <= NUM_PROTOS; i++) + protos[i] = 0; + +} + +static void +init_protos(void) +{ + int i; + + if((protos = calloc(NUM_PROTOS, sizeof(int))) == NULL) + err(1, "calloc()"); + + for(i=0; i <= NUM_PROTOS; i++) + protos[i] = 0; + +} + + +/* this function needs to be updated to reflect additional protocols + that are to be supported */ +static int +add_proto_type(const char *proto) +{ + int found = 0; + + if(strlen(proto) == 0) + return 0; + + if(strncmp(proto, "tcp", 3) == 0) { + protos[TCP_PROTO] = 1; + found = 1; + } + else if(strncmp(proto, "udp", 3) == 0) { + protos[UDP_PROTO] = 1; + found = 1; + } else { + printf("Invalid protocol: %s\n", proto); + } + + return found; +} + +static int +parse_protos(const char *protospec) +{ + const char *p; + char curr_proto[MAX_PROTO_LEN]; + int proto_index = 0; + int protos_defined = 0; + + p = protospec; + while(*p != '\0') { + if(*p == ',') { + curr_proto[proto_index] = '\0'; + protos_defined += add_proto_type(curr_proto); + proto_index = 0; + } else { + curr_proto[proto_index++] = *p; + } + p++; + if(*p == '\0' && proto_index != 0) { + curr_proto[proto_index] = '\0'; + protos_defined += add_proto_type(curr_proto); + } + if(proto_index == MAX_PROTO_LEN) { + printf("Warning: truncating protocol\n"); + curr_proto[proto_index] = '\0'; + protos_defined += add_proto_type(curr_proto); + + /* need to seek to the next , or \0 now */ + while(*p != ',' && *p != '\0') + p++; + + /* if we're at a proto boundary (comma), move on */ + if(*p == ',') + p++; + + proto_index = 0; + } + } + + return protos_defined; +} + + +static void parse_ports(const char *portspec) { const char *p, *q; @@ -576,16 +674,24 @@ 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[]) { + /* if protos_defined remains -1, no -P was provided, sowe avoid + attempting to read from that int array later */ + int protos_defined = -1; + int o; - while ((o = getopt(argc, argv, "46clp:uv")) != -1) + /* initialize all protos to 0, if they're all still unset later + then -P wasn't use and the default is to display all of them */ + init_protos(); + + while ((o = getopt(argc, argv, "46clp:P:uv")) != -1) switch (o) { case '4': opt_4 = 1; @@ -602,6 +708,9 @@ case 'p': parse_ports(optarg); break; + case 'P': + protos_defined = parse_protos(optarg); + break; case 'u': opt_u = 1; break; @@ -618,17 +727,28 @@ if (argc > 0) usage(); - if (!opt_4 && !opt_6 && !opt_u) - opt_4 = opt_6 = opt_u = 1; + /* if -u was explicityl defined, zero out the protos array */ + if(opt_u && protos_defined == -1 && !opt_4 && !opt_6) { + clear_protos(); + protos_defined = 0; + } + + if (!opt_4 && !opt_6 && !opt_u && protos_defined == -1) + opt_u = 1; + 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); + if(protos[TCP_PROTO] == 1 || protos_defined == -1) + gather_inet(IPPROTO_TCP); + if(protos[UDP_PROTO] == 1 || protos_defined == -1) + gather_inet(IPPROTO_UDP); gather_inet(IPPROTO_DIVERT); } - if (opt_u) { + + if ( opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) { gather_unix(SOCK_STREAM); gather_unix(SOCK_DGRAM); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?8cb6106e0611031550y1381b67agdc74144b89de763b>