cons: Clamp the amount written to the console
[akaros.git] / tests / netstat.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9 #include <sys/types.h>
10
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <parlib/parlib.h>
16 #include <unistd.h>
17 #include <signal.h>
18 #include <iplib/iplib.h>
19 #include <dirent.h>
20
21 enum {
22         maxproto = 20,
23 };
24 void pip(char *, struct dirent *);
25 void nstat(char *, void (*)(char *, struct dirent *));
26 void pipifc(void);
27
28 FILE *out;
29 char *netroot;
30 char *proto[maxproto];
31 int nproto;
32 int notrans;
33
34 void usage(char *argv0)
35 {
36         fprintf(stderr, "usage: %s [-in] [-p proto] [network-dir]\n", argv0);
37         fprintf(stderr, "usage");
38         exit(1);
39 }
40
41 void main(int argc, char *argv[])
42 {
43         int justinterfaces = 0;
44         int i, tot, fd;
45         DIR *dir;
46         struct dirent *d;
47         char buf[128];
48         out = stdout;
49         argc--, argv++;
50         while (argc > 0 && *argv[0] == '-') {
51                 switch (argv[0][1]) {
52                         case 'i':
53                                 justinterfaces = 1;
54                                 break;
55                         case 'n':
56                                 notrans = 1;
57                                 break;
58                         case 'p':
59                                 if (nproto >= maxproto){
60                                         fprintf(stderr, "too many protos");
61                                         exit(1);
62                                 }
63                                 if (argc < 2)
64                                         usage("netstat");
65                                 argc--, argv++;
66                                 proto[nproto++] = argv[0];
67                                 break;
68                         default:
69                                 usage("netstat");
70                 }
71                 argc--, argv++;
72         }
73
74         netroot = "/net";
75         switch (argc) {
76                 case 0:
77                         break;
78                 case 1:
79                         netroot = argv[0];
80                         break;
81                 default:
82                         usage("netstat");
83         }
84
85         if (justinterfaces) {
86                 pipifc();
87                 exit(0);
88         }
89
90         if (nproto) {
91                 for (i = 0; i < nproto; i++)
92                         nstat(proto[i], pip);
93         } else {
94                 dir = opendir(netroot);
95                 if (!dir) {
96                         fprintf(stderr, "open %s: %r", netroot);
97                         exit(1);
98                 }
99
100                 while ((d = readdir(dir))) {
101                         if (strcmp(d->d_name, "ipifc") == 0)
102                                 continue;
103                         snprintf(buf, sizeof buf, "%s/%s/0/local", netroot, d->d_name);
104                         /* access is bogus for now. */
105                         if (1 || access(buf, 0) >= 0)
106                                 nstat(d->d_name, pip);
107                         else
108                                 fprintf(stderr, "Can't access %s\n", d->d_name);
109                 }
110         }
111
112         exit(0);
113 }
114
115 void nstat(char *net, void (*f) (char *, struct dirent *))
116 {
117         int fdir, i, tot;
118         struct dirent *d;
119         DIR *dir;
120         char buf[128];
121
122         snprintf(buf, sizeof buf, "%s/%s", netroot, net);
123         dir = opendir(buf);
124         if (!dir)
125                 return;
126
127         while ((d = readdir(dir))) {
128                 (*f) (net, d);
129         }
130         /* leak dir */
131 }
132
133 char *getport(char *net, char *p)
134 {
135         static char port[10];
136
137         strncpy(port, p, sizeof(port) - 1);
138         port[sizeof(port) - 1] = 0;
139         if (1)  //if(notrans || (p = csgetvalue(netroot, "port", p, net, nil)) == nil)
140                 return port;
141         strncpy(port, p, sizeof(port) - 1);
142         port[sizeof(port) - 1] = 0;
143         free(p);
144         return port;
145 }
146
147 void pip(char *net, struct dirent *db)
148 {
149         int n, fd;
150         char buf[128], *p;
151         char *dname;
152
153         if (strcmp(db->d_name, "clone") == 0)
154                 return;
155         if (strcmp(db->d_name, "stats") == 0)
156                 return;
157
158         snprintf(buf, sizeof buf, "%s/%s/%s/status", netroot, net, db->d_name);
159         fd = open(buf, O_RDONLY);
160         if (fd < 0)
161                 return;
162         n = read(fd, buf, sizeof(buf));
163         close(fd);
164         if (n < 0)
165                 return;
166         buf[n] = 0;
167
168         p = strchr(buf, ' ');
169         if (p != 0)
170                 *p = 0;
171         p = strrchr(buf, '\n');
172         if (p != 0)
173                 *p = 0;
174         fprintf(out, "%-4s %-4s %-12s ", net, db->d_name, /*db->uid, */ buf);
175
176         snprintf(buf, sizeof buf, "%s/%s/%s/local", netroot, net, db->d_name);
177         fd = open(buf, O_RDONLY);
178         if (fd < 0) {
179                 fprintf(out, "\n");
180                 return;
181         }
182         n = read(fd, buf, sizeof(buf));
183         close(fd);
184         if (n < 0) {
185                 fprintf(out, "\n");
186                 return;
187         }
188         buf[n - 1] = 0;
189         p = strchr(buf, '!');
190         if (p == 0) {
191                 fprintf(out, "\n");
192                 return;
193         }
194         *p = '\0';
195         fprintf(out, "%-10s ", getport(net, p + 1));
196
197         snprintf(buf, sizeof buf, "%s/%s/%s/remote", netroot, net, db->d_name);
198         fd = open(buf, O_RDONLY);
199         if (fd < 0) {
200                 printf("\n");
201                 return;
202         }
203         n = read(fd, buf, sizeof(buf));
204         close(fd);
205         if (n < 0) {
206                 printf("\n");
207                 return;
208         }
209         buf[n - 1] = 0;
210         p = strchr(buf, '!');
211         if (p != NULL)
212                 *p++ = '\0';
213
214         if (notrans) {
215                 fprintf(out, "%-10s %s\n", getport(net, p), buf);
216                 return;
217         }
218         dname = NULL;   //csgetvalue(netroot, "ip", buf, "dom", nil);
219         if (dname == NULL) {
220                 fprintf(out, "%-10s %s\n", getport(net, p), buf);
221                 return;
222         }
223         fprintf(out, "%-10s %s\n", getport(net, p), dname);
224         free(dname);
225 }
226
227 void pipifc(void)
228 {
229         struct ipifc *ip, *nip;
230         struct iplifc *lifc;
231         char buf[100];
232         int l, i;
233
234 //  fmtinstall('I', eipfmt);
235 //  fmtinstall('M', eipfmt);
236
237         ip = readipifc(netroot, NULL, -1);
238
239         l = 7;
240         for (nip = ip; nip; nip = nip->next) {
241                 for (lifc = nip->lifc; lifc; lifc = lifc->next) {
242                         i = snprintf(buf, sizeof buf, "%I", lifc->ip);
243                         if (i > l)
244                                 l = i;
245                         i = snprintf(buf, sizeof buf, "%I", lifc->net);
246                         if (i > l)
247                                 l = i;
248                 }
249         }
250
251         for (nip = ip; nip; nip = nip->next) {
252                 for (lifc = nip->lifc; lifc; lifc = lifc->next)
253                         fprintf(out, "%-12s %5d %-*I %5M %-*I %8lud %8lud %8lud %8lud\n",
254                                         nip->dev, nip->mtu,
255                                         l, lifc->ip, lifc->mask, l, lifc->net,
256                                         nip->pktin, nip->pktout, nip->errin, nip->errout);
257         }
258 }