blob: 867abfdc5b04329fa8f9953b9e94affa0aed1e11 [file] [log] [blame]
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <parlib/parlib.h>
#include <unistd.h>
#include <signal.h>
#include <iplib/iplib.h>
#include <dirent.h>
enum {
maxproto = 20,
};
void pip(char *, struct dirent *);
void nstat(char *, void (*)(char *, struct dirent *));
void pipifc(void);
FILE *out;
char *netroot;
char *proto[maxproto];
int nproto;
int notrans;
void usage(char *argv0)
{
fprintf(stderr, "usage: %s [-in] [-p proto] [network-dir]\n", argv0);
fprintf(stderr, "usage");
exit(1);
}
void main(int argc, char *argv[])
{
int justinterfaces = 0;
int i, tot, fd;
DIR *dir;
struct dirent *d;
char buf[128];
out = stdout;
argc--, argv++;
while (argc > 0 && *argv[0] == '-') {
switch (argv[0][1]) {
case 'i':
justinterfaces = 1;
break;
case 'n':
notrans = 1;
break;
case 'p':
if (nproto >= maxproto){
fprintf(stderr, "too many protos");
exit(1);
}
if (argc < 2)
usage("netstat");
argc--, argv++;
proto[nproto++] = argv[0];
break;
default:
usage("netstat");
}
argc--, argv++;
}
netroot = "/net";
switch (argc) {
case 0:
break;
case 1:
netroot = argv[0];
break;
default:
usage("netstat");
}
if (justinterfaces) {
pipifc();
exit(0);
}
if (nproto) {
for (i = 0; i < nproto; i++)
nstat(proto[i], pip);
} else {
dir = opendir(netroot);
if (!dir) {
fprintf(stderr, "open %s: %r", netroot);
exit(1);
}
while ((d = readdir(dir))) {
if (strcmp(d->d_name, "ipifc") == 0)
continue;
snprintf(buf, sizeof buf, "%s/%s/0/local", netroot,
d->d_name);
/* access is bogus for now. */
if (1 || access(buf, 0) >= 0)
nstat(d->d_name, pip);
else
fprintf(stderr, "Can't access %s\n", d->d_name);
}
}
exit(0);
}
void nstat(char *net, void (*f) (char *, struct dirent *))
{
int fdir, i, tot;
struct dirent *d;
DIR *dir;
char buf[128];
snprintf(buf, sizeof buf, "%s/%s", netroot, net);
dir = opendir(buf);
if (!dir)
return;
while ((d = readdir(dir))) {
(*f) (net, d);
}
/* leak dir */
}
char *getport(char *net, char *p)
{
static char port[10];
strncpy(port, p, sizeof(port) - 1);
port[sizeof(port) - 1] = 0;
//if(notrans || (p = csgetvalue(netroot, "port", p, net, nil)) == nil)
if (1)
return port;
strncpy(port, p, sizeof(port) - 1);
port[sizeof(port) - 1] = 0;
free(p);
return port;
}
void pip(char *net, struct dirent *db)
{
int n, fd;
char buf[128], *p;
char *dname;
if (strcmp(db->d_name, "clone") == 0)
return;
if (strcmp(db->d_name, "stats") == 0)
return;
snprintf(buf, sizeof buf, "%s/%s/%s/status", netroot, net, db->d_name);
fd = open(buf, O_RDONLY);
if (fd < 0)
return;
n = read(fd, buf, sizeof(buf));
close(fd);
if (n < 0)
return;
buf[n] = 0;
p = strchr(buf, ' ');
if (p != 0)
*p = 0;
p = strrchr(buf, '\n');
if (p != 0)
*p = 0;
fprintf(out, "%-4s %-4s %-12s ", net, db->d_name, /*db->uid, */ buf);
snprintf(buf, sizeof buf, "%s/%s/%s/local", netroot, net, db->d_name);
fd = open(buf, O_RDONLY);
if (fd < 0) {
fprintf(out, "\n");
return;
}
n = read(fd, buf, sizeof(buf));
close(fd);
if (n < 0) {
fprintf(out, "\n");
return;
}
buf[n - 1] = 0;
p = strchr(buf, '!');
if (p == 0) {
fprintf(out, "\n");
return;
}
*p = '\0';
fprintf(out, "%-10s ", getport(net, p + 1));
snprintf(buf, sizeof buf, "%s/%s/%s/remote", netroot, net, db->d_name);
fd = open(buf, O_RDONLY);
if (fd < 0) {
printf("\n");
return;
}
n = read(fd, buf, sizeof(buf));
close(fd);
if (n < 0) {
printf("\n");
return;
}
buf[n - 1] = 0;
p = strchr(buf, '!');
if (p != NULL)
*p++ = '\0';
if (notrans) {
fprintf(out, "%-10s %s\n", getport(net, p), buf);
return;
}
dname = NULL; //csgetvalue(netroot, "ip", buf, "dom", nil);
if (dname == NULL) {
fprintf(out, "%-10s %s\n", getport(net, p), buf);
return;
}
fprintf(out, "%-10s %s\n", getport(net, p), dname);
free(dname);
}
void pipifc(void)
{
struct ipifc *ip, *nip;
struct iplifc *lifc;
char buf[100];
int l, i;
// fmtinstall('I', eipfmt);
// fmtinstall('M', eipfmt);
ip = readipifc(netroot, NULL, -1);
l = 7;
for (nip = ip; nip; nip = nip->next) {
for (lifc = nip->lifc; lifc; lifc = lifc->next) {
i = snprintf(buf, sizeof buf, "%I", lifc->ip);
if (i > l)
l = i;
i = snprintf(buf, sizeof buf, "%I", lifc->net);
if (i > l)
l = i;
}
}
for (nip = ip; nip; nip = nip->next) {
for (lifc = nip->lifc; lifc; lifc = lifc->next)
fprintf(out, "%-12s %5d %-*I %5M %-*I %8lud %8lud %8lud %8lud\n",
nip->dev, nip->mtu,
l, lifc->ip, lifc->mask, l, lifc->net,
nip->pktin, nip->pktout, nip->errin,
nip->errout);
}
}