On 2006-11-11 16:48, Giorgos Keramidas <[EMAIL PROTECTED]> 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.

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 <[EMAIL PROTECTED]>

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);
 }
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to