shithub: netgraph

Download patch

ref: 59402bf42b8b199218f1f0d111aaf273a3c1806a
parent: 9f31bb10802dc95999bf2923981a49486ccee3f0
author: sirjofri <sirjofri@sirjofri.de>
date: Thu Sep 4 07:30:44 EDT 2025

adds service listener fetcher

--- a/README
+++ b/README
@@ -5,7 +5,8 @@
           netgraph - generate a network graph of the Plan 9 system
 
      SYNOPSIS
-          netgraph [ -ip ] [ -s systuples ] [ -n ipnettuples ]
+          netgraph [ -ipl ] [ -s systuples ] [ -n ipnettuples ] [ -x
+          netmtpt ]
           fullnetgraph [ ... ]
 
      DESCRIPTION
@@ -41,6 +42,11 @@
                It is equivalent to running netgraph | ps2pdf
                -g1191x842 -r72, but the size adjusts automatically to
                the actual drawing.
+
+          -l   Netgraph tries to fetch a list of network listeners
+               based on files in /cfg/$sysname/service.
+
+          -x   Use this flag to use a different network device.
 
           -s systuples
                The user can adjust the relevant fields to search for
--- a/draw.c
+++ b/draw.c
@@ -6,6 +6,7 @@
 
 static int lineheight = 10;
 static int charwidth = 6;
+static int foldline = 32;
 
 static int boxoffsetx = 2;
 static int boxoffsety = 2;
@@ -78,6 +79,19 @@
 	p1.x, p2.y);
 }
 
+static char*
+strrnchr(char *str, int n, int c)
+{
+	char *s;
+	s = &str[n];
+	while (s > str) {
+		if (*s == c)
+			return s;
+		s--;
+	}
+	return nil;
+}
+
 static int
 isipnet(Tuple *t)
 {
@@ -89,6 +103,8 @@
 {
 	Color c;
 	Pos *p = aux;
+	char *s, *s2;
+	int n, fl;
 	int ipnet = isipnet(t);
 	
 	if (!showipnet && t->ipnet && !ipnet)
@@ -100,13 +116,29 @@
 		print("%f %f %f setrgbcolor\n", c.r, c.g, c.b);
 	}
 	
-	drawtext(*p, 1, "%s%s: %s", t->ipnet ? "*" : "", t->key, t->value);
+	fl = foldline - strlen(t->key) - 3;
+	s = t->value;
+	while (strlen(s) > fl) {
+		s2 = strrnchr(s, fl, ',');
+		if (!s2)
+			s2 = &s[fl];
+		n = s2 - s + 1;
+		drawtext(*p, 1, "%s%s: %.*s", t->ipnet ? "*" : "", t->key, n, s);
+		p->y -= lineheight;
+		s = s2;
+		if (*s == ',')
+			s++;
+		while (*s == ' ')
+			s++;
+	}
+	if (strlen(s)) {
+		drawtext(*p, 1, "%s%s: %s", t->ipnet ? "*" : "", t->key, s);
+		p->y -= lineheight;
+	}
 	
 	if (ipnet) {
 		print("grestore\n");
 	}
-	
-	p->y -= lineheight;
 }
 
 void
@@ -125,14 +157,36 @@
 tuplesize(Tuple *t, void *aux)
 {
 	Block *b = aux;
-	int w;
+	char *s, *s2;
+	int w, nw;
+	int fl;
 	
 	if (!showipnet && t->ipnet && !isipnet(t))
 		return;
 	
-	b->height += lineheight;
+	fl = foldline - strlen(t->key) - 3;
+	w = 0;
+	s = t->value;
+	while (strlen(s) > fl) {
+		s2 = strrnchr(s, fl, ',');
+		if (!s2)
+			s2 = &s[fl];
+		nw = s2 - s + 1;
+		if (nw > w) w = nw;
+		b->height += lineheight;
+		s = s2;
+		if (*s == ',')
+			s++;
+		while (*s == ' ')
+			s++;
+	}
+	if (strlen(s)) {
+		nw = strlen(s);
+		if (nw > w) w = nw;
+		b->height += lineheight;
+	}
 	
-	w = strlen(t->key) + strlen(t->value) + 3;
+	w = strlen(t->key) + w + 3;
 	if (w > b->width)
 		b->width = w;
 }
--- a/fns.h
+++ b/fns.h
@@ -22,6 +22,9 @@
 int numsystems(void);
 void forsysarg(int (*f)(char*,void*), void*);
 
+/* srv functions */
+void fetchsrv(Sys*,void*);
+
 /* conn functions */
 void addconn(Sys*, Sys*, char*);
 void forconn(void (*f)(Conn*,void*), void*);
--- a/mkfile
+++ b/mkfile
@@ -9,6 +9,7 @@
 	ipnet.$O\
 	tuple.$O\
 	conns.$O\
+	srv.$O\
 
 HFILES=dat.h fns.h
 
--- a/netgraph.c
+++ b/netgraph.c
@@ -9,7 +9,7 @@
 static void
 usage(void)
 {
-	fprint(2, "usage: %s [-ip] [-s systuples] [-n ipnettuples]\n", argv0);
+	fprint(2, "usage: %s [-ipl] [-s systuples] [-n ipnettuples] [-x netmtpt]\n", argv0);
 	exits("usage");
 }
 
@@ -29,6 +29,7 @@
 int pageheight = 842;
 
 int showipnet = 0;
+int showsrv = 0;
 
 static void
 procrequest(char *key, char *val)
@@ -236,6 +237,9 @@
 	case 'i':
 		showipnet++;
 		break;
+	case 'l': /* listeners */
+		showsrv++;
+		break;
 	case 'p':
 		pdf++;
 		break;
@@ -259,6 +263,8 @@
 	Bterm(bin);
 	
 	/* calculation stage */
+	if (showsrv)
+		forsys(fetchsrv, nil);
 	i = 0;
 	forsys(calcsyslayout, &i);
 	
--- a/netgraph1
+++ b/netgraph1
@@ -4,15 +4,16 @@
 .SH SYNOPSIS
 .B netgraph
 [
-.B -ip
-]
-[
+.B -ipl
+] [
 .B -s
 .I systuples
-]
-[
+] [
 .B -n
 .I ipnettuples
+] [
+.B -x
+.I netmtpt
 ]
 .br
 .B fullnetgraph
@@ -66,6 +67,12 @@
 It is equivalent to running
 .BR "netgraph | ps2pdf -g1191x842 -r72" ,
 but the size adjusts automatically to the actual drawing.
+.IP \fL-l\fR
+.I Netgraph
+tries to fetch a list of network listeners based on files in
+.BR /cfg/$sysname/service .
+.IP \fL-x\fR \fInetmtpt\fR
+Use this flag to use a different network device.
 .IP "\fL-s\fR \fIsystuples\fR"
 The user can adjust the relevant fields to search for by providing a comma separated list of field names.
 .IP "\fL-n\fR \fIipnettuples\fR"
--- /dev/null
+++ b/srv.c
@@ -1,0 +1,104 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ndb.h>
+#include <String.h>
+#include "dat.h"
+#include "fns.h"
+
+static char *protos[] = {
+	"tcp", "udp", "il",
+};
+
+static char*
+findnumber(char *s)
+{
+	while (*s) {
+		if (*s >= '0' && *s <= '9')
+			return s;
+		s++;
+	}
+	return nil;
+}
+
+static int
+validproto(char *proto)
+{
+	int n = sizeof(protos) / sizeof(*protos);
+	for (int i = 0; i < n; i++)
+		if (strcmp(proto, protos[i]) == 0)
+			return 1;
+	return 0;
+}
+
+static char*
+getport(char *num, char *proto)
+{
+	char *s;
+	
+	if (!validproto(proto))
+		return nil;
+	
+	s = csgetvalue(netdir, "port", num, proto, nil);
+	return s ? s : strdup(num);
+}
+
+static void
+condadd(Sys *sys, char *name)
+{
+	char *s;
+	char num[6];
+	Tuple *t;
+	int n;
+	
+	if (name[0] == '!')
+		return;
+	
+	s = findnumber(name);
+	strncpy(num, s, sizeof(num));
+	*s = 0;
+	
+	s = getport(num, name);
+	if (!s)
+		return;
+	
+	t = findtuple(sys, name);
+	if (!t) {
+		addtuple(sys, strdup(name), s, 0);
+		return;
+	}
+	
+	/* lengths + ", " + 0 */
+	n = strlen(t->value);
+	t->value = realloc(t->value, n + strlen(s) + 2 + 1);
+	strcpy(&t->value[n], ", ");
+	strcpy(&t->value[n+2], s);
+	free(s);
+}
+
+void
+fetchsrv(Sys *sys, void*)
+{
+	char path[128];
+	int fd;
+	Tuple *t;
+	int n;
+	Dir *d;
+	
+	t = findtuple(sys, "sys");
+	if (!t)
+		return;
+	
+	snprint(path, sizeof(path), "/cfg/%s/service", t->value);
+	fd = open(path, OREAD);
+	if (fd < 0)
+		return;
+	while ((n = dirread(fd, &d)) > 0) {
+		for (int i = 0; i < n; i++) {
+			if (!(d[i].mode & DMEXEC))
+				continue;
+			condadd(sys, d[i].name);
+		}
+		free(d);
+	}
+}
--