1 /*
2 * Copyright (c) 1983, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 04/28/95";
10 #endif /* not lint */
11
12 #include <sys/types.h>
13 #include <sys/protosw.h>
14 #include <sys/socket.h>
15
16 #include <net/if.h>
17 #include <net/if_dl.h>
18 #include <netinet/in.h>
19 #include <netinet/in_var.h>
20 #include <netns/ns.h>
21 #include <netns/ns_if.h>
22 #include <netiso/iso.h>
23 #include <netiso/iso_var.h>
24 #include <arpa/inet.h>
25
26 #include <signal.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 #include "netstat.h"
32
33 #define YES 1
34 #define NO 0
35
36 static void sidewaysintpr __P((u_int, u_long));
37 static void catchalarm __P((int));
38
39 /*
40 * Print a description of the network interfaces.
41 */
42 void
intpr(interval,ifnetaddr)43 intpr(interval, ifnetaddr)
44 int interval;
45 u_long ifnetaddr;
46 {
47 struct ifnet ifnet;
48 union {
49 struct ifaddr ifa;
50 struct in_ifaddr in;
51 struct ns_ifaddr ns;
52 struct iso_ifaddr iso;
53 } ifaddr;
54 u_long ifaddraddr;
55 struct sockaddr *sa;
56 char name[16];
57
58 if (ifnetaddr == 0) {
59 printf("ifnet: symbol not defined\n");
60 return;
61 }
62 if (interval) {
63 sidewaysintpr((unsigned)interval, ifnetaddr);
64 return;
65 }
66 if (kread(ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr))
67 return;
68 printf("%-5.5s %-5.5s %-11.11s %-15.15s %8.8s %5.5s %8.8s %5.5s",
69 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
70 "Opkts", "Oerrs");
71 printf(" %5s", "Coll");
72 if (tflag)
73 printf(" %s", "Time");
74 if (dflag)
75 printf(" %s", "Drop");
76 putchar('\n');
77 ifaddraddr = 0;
78 while (ifnetaddr || ifaddraddr) {
79 struct sockaddr_in *sin;
80 register char *cp;
81 int n, m;
82
83 if (ifaddraddr == 0) {
84 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) ||
85 kread((u_long)ifnet.if_name, name, 16))
86 return;
87 name[15] = '\0';
88 ifnetaddr = (u_long)ifnet.if_next;
89 if (interface != 0 && (strcmp(name, interface) != 0 ||
90 unit != ifnet.if_unit))
91 continue;
92 cp = index(name, '\0');
93 cp += sprintf(cp, "%d", ifnet.if_unit);
94 if ((ifnet.if_flags&IFF_UP) == 0)
95 *cp++ = '*';
96 *cp = '\0';
97 ifaddraddr = (u_long)ifnet.if_addrlist;
98 }
99 printf("%-5.5s %-5d ", name, ifnet.if_mtu);
100 if (ifaddraddr == 0) {
101 printf("%-11.11s ", "none");
102 printf("%-15.15s ", "none");
103 } else {
104 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
105 ifaddraddr = 0;
106 continue;
107 }
108 #define CP(x) ((char *)(x))
109 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
110 CP(&ifaddr); sa = (struct sockaddr *)cp;
111 switch (sa->sa_family) {
112 case AF_UNSPEC:
113 printf("%-11.11s ", "none");
114 printf("%-15.15s ", "none");
115 break;
116 case AF_INET:
117 sin = (struct sockaddr_in *)sa;
118 #ifdef notdef
119 /* can't use inet_makeaddr because kernel
120 * keeps nets unshifted.
121 */
122 in = inet_makeaddr(ifaddr.in.ia_subnet,
123 INADDR_ANY);
124 printf("%-11.11s ", netname(in.s_addr,
125 ifaddr.in.ia_subnetmask));
126 #else
127 printf("%-11.11s ",
128 netname(htonl(ifaddr.in.ia_subnet),
129 ifaddr.in.ia_subnetmask));
130 #endif
131 printf("%-15.15s ",
132 routename(sin->sin_addr.s_addr));
133 break;
134 case AF_NS:
135 {
136 struct sockaddr_ns *sns =
137 (struct sockaddr_ns *)sa;
138 u_long net;
139 char netnum[8];
140
141 *(union ns_net *) &net = sns->sns_addr.x_net;
142 sprintf(netnum, "%lxH", ntohl(net));
143 upHex(netnum);
144 printf("ns:%-8s ", netnum);
145 printf("%-15s ",
146 ns_phost((struct sockaddr *)sns));
147 }
148 break;
149 case AF_LINK:
150 {
151 struct sockaddr_dl *sdl =
152 (struct sockaddr_dl *)sa;
153 cp = (char *)LLADDR(sdl);
154 n = sdl->sdl_alen;
155 }
156 m = printf("%-11.11s ", "<Link>");
157 goto hexprint;
158 default:
159 m = printf("(%d)", sa->sa_family);
160 for (cp = sa->sa_len + (char *)sa;
161 --cp > sa->sa_data && (*cp == 0);) {}
162 n = cp - sa->sa_data + 1;
163 cp = sa->sa_data;
164 hexprint:
165 while (--n >= 0)
166 m += printf("%x%c", *cp++ & 0xff,
167 n > 0 ? '.' : ' ');
168 m = 28 - m;
169 while (m-- > 0)
170 putchar(' ');
171 break;
172 }
173 ifaddraddr = (u_long)ifaddr.ifa.ifa_next;
174 }
175 printf("%8d %5d %8d %5d %5d",
176 ifnet.if_ipackets, ifnet.if_ierrors,
177 ifnet.if_opackets, ifnet.if_oerrors,
178 ifnet.if_collisions);
179 if (tflag)
180 printf(" %3d", ifnet.if_timer);
181 if (dflag)
182 printf(" %3d", ifnet.if_snd.ifq_drops);
183 putchar('\n');
184 }
185 }
186
187 #define MAXIF 10
188 struct iftot {
189 char ift_name[16]; /* interface name */
190 int ift_ip; /* input packets */
191 int ift_ie; /* input errors */
192 int ift_op; /* output packets */
193 int ift_oe; /* output errors */
194 int ift_co; /* collisions */
195 int ift_dr; /* drops */
196 } iftot[MAXIF];
197
198 u_char signalled; /* set if alarm goes off "early" */
199
200 /*
201 * Print a running summary of interface statistics.
202 * Repeat display every interval seconds, showing statistics
203 * collected over that interval. Assumes that interval is non-zero.
204 * First line printed at top of screen is always cumulative.
205 */
206 static void
sidewaysintpr(interval,off)207 sidewaysintpr(interval, off)
208 unsigned interval;
209 u_long off;
210 {
211 struct ifnet ifnet;
212 u_long firstifnet;
213 register struct iftot *ip, *total;
214 register int line;
215 struct iftot *lastif, *sum, *interesting;
216 int oldmask;
217
218 if (kread(off, (char *)&firstifnet, sizeof (u_long)))
219 return;
220 lastif = iftot;
221 sum = iftot + MAXIF - 1;
222 total = sum - 1;
223 interesting = iftot;
224 for (off = firstifnet, ip = iftot; off;) {
225 char *cp;
226
227 if (kread(off, (char *)&ifnet, sizeof ifnet))
228 break;
229 ip->ift_name[0] = '(';
230 if (kread((u_long)ifnet.if_name, ip->ift_name + 1, 15))
231 break;
232 if (interface && strcmp(ip->ift_name + 1, interface) == 0 &&
233 unit == ifnet.if_unit)
234 interesting = ip;
235 ip->ift_name[15] = '\0';
236 cp = index(ip->ift_name, '\0');
237 sprintf(cp, "%d)", ifnet.if_unit);
238 ip++;
239 if (ip >= iftot + MAXIF - 2)
240 break;
241 off = (u_long) ifnet.if_next;
242 }
243 lastif = ip;
244
245 (void)signal(SIGALRM, catchalarm);
246 signalled = NO;
247 (void)alarm(interval);
248 banner:
249 printf(" input %-6.6s output ", interesting->ift_name);
250 if (lastif - iftot > 0) {
251 if (dflag)
252 printf(" ");
253 printf(" input (Total) output");
254 }
255 for (ip = iftot; ip < iftot + MAXIF; ip++) {
256 ip->ift_ip = 0;
257 ip->ift_ie = 0;
258 ip->ift_op = 0;
259 ip->ift_oe = 0;
260 ip->ift_co = 0;
261 ip->ift_dr = 0;
262 }
263 putchar('\n');
264 printf("%8.8s %5.5s %8.8s %5.5s %5.5s ",
265 "packets", "errs", "packets", "errs", "colls");
266 if (dflag)
267 printf("%5.5s ", "drops");
268 if (lastif - iftot > 0)
269 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
270 "packets", "errs", "packets", "errs", "colls");
271 if (dflag)
272 printf(" %5.5s", "drops");
273 putchar('\n');
274 fflush(stdout);
275 line = 0;
276 loop:
277 sum->ift_ip = 0;
278 sum->ift_ie = 0;
279 sum->ift_op = 0;
280 sum->ift_oe = 0;
281 sum->ift_co = 0;
282 sum->ift_dr = 0;
283 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
284 if (kread(off, (char *)&ifnet, sizeof ifnet)) {
285 off = 0;
286 continue;
287 }
288 if (ip == interesting) {
289 printf("%8d %5d %8d %5d %5d",
290 ifnet.if_ipackets - ip->ift_ip,
291 ifnet.if_ierrors - ip->ift_ie,
292 ifnet.if_opackets - ip->ift_op,
293 ifnet.if_oerrors - ip->ift_oe,
294 ifnet.if_collisions - ip->ift_co);
295 if (dflag)
296 printf(" %5d",
297 ifnet.if_snd.ifq_drops - ip->ift_dr);
298 }
299 ip->ift_ip = ifnet.if_ipackets;
300 ip->ift_ie = ifnet.if_ierrors;
301 ip->ift_op = ifnet.if_opackets;
302 ip->ift_oe = ifnet.if_oerrors;
303 ip->ift_co = ifnet.if_collisions;
304 ip->ift_dr = ifnet.if_snd.ifq_drops;
305 sum->ift_ip += ip->ift_ip;
306 sum->ift_ie += ip->ift_ie;
307 sum->ift_op += ip->ift_op;
308 sum->ift_oe += ip->ift_oe;
309 sum->ift_co += ip->ift_co;
310 sum->ift_dr += ip->ift_dr;
311 off = (u_long) ifnet.if_next;
312 }
313 if (lastif - iftot > 0) {
314 printf(" %8d %5d %8d %5d %5d",
315 sum->ift_ip - total->ift_ip,
316 sum->ift_ie - total->ift_ie,
317 sum->ift_op - total->ift_op,
318 sum->ift_oe - total->ift_oe,
319 sum->ift_co - total->ift_co);
320 if (dflag)
321 printf(" %5d", sum->ift_dr - total->ift_dr);
322 }
323 *total = *sum;
324 putchar('\n');
325 fflush(stdout);
326 line++;
327 oldmask = sigblock(sigmask(SIGALRM));
328 if (! signalled) {
329 sigpause(0);
330 }
331 sigsetmask(oldmask);
332 signalled = NO;
333 (void)alarm(interval);
334 if (line == 21)
335 goto banner;
336 goto loop;
337 /*NOTREACHED*/
338 }
339
340 /*
341 * Called if an interval expires before sidewaysintpr has completed a loop.
342 * Sets a flag to not wait for the alarm.
343 */
344 static void
catchalarm(signo)345 catchalarm(signo)
346 int signo;
347 {
348 signalled = YES;
349 }
350