Annotation of src/usr.bin/systat/netstat.c, Revision 1.27
1.27 ! deraadt 1: /* $OpenBSD: netstat.c,v 1.26 2004/09/29 21:59:28 deraadt Exp $ */
1.1 deraadt 2: /* $NetBSD: netstat.c,v 1.3 1995/06/18 23:53:07 cgd Exp $ */
3:
4: /*-
5: * Copyright (c) 1980, 1992, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.24 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: #if 0
35: static char sccsid[] = "@(#)netstat.c 8.1 (Berkeley) 6/6/93";
36: #endif
1.27 ! deraadt 37: static char rcsid[] = "$OpenBSD: netstat.c,v 1.26 2004/09/29 21:59:28 deraadt Exp $";
1.1 deraadt 38: #endif /* not lint */
39:
40: /*
41: * netstat
42: */
43: #include <sys/param.h>
44: #include <sys/socket.h>
45: #include <sys/socketvar.h>
46: #include <sys/mbuf.h>
47: #include <sys/protosw.h>
48:
49: #include <netinet/in.h>
50: #include <net/route.h>
51: #include <netinet/in_systm.h>
52: #include <netinet/ip.h>
53: #include <netinet/in_pcb.h>
54: #include <netinet/ip_icmp.h>
55: #include <netinet/icmp_var.h>
56: #include <netinet/ip_var.h>
57: #include <netinet/tcp.h>
58: #include <netinet/tcpip.h>
59: #include <netinet/tcp_seq.h>
60: #define TCPSTATES
61: #include <netinet/tcp_fsm.h>
62: #include <netinet/tcp_timer.h>
63: #include <netinet/tcp_var.h>
64: #include <netinet/tcp_debug.h>
65: #include <netinet/udp.h>
66: #include <netinet/udp_var.h>
1.7 millert 67: #include <arpa/inet.h>
1.1 deraadt 68:
69: #include <netdb.h>
70: #include <stdlib.h>
71: #include <string.h>
1.16 pvalchev 72: #include <err.h>
1.1 deraadt 73: #include <nlist.h>
74: #include <paths.h>
75: #include "systat.h"
76: #include "extern.h"
77:
1.21 millert 78: static void enter(struct inpcb *, struct socket *, int, char *);
79: static const char *inetname(struct in_addr);
80: static void inetprint(struct in_addr *, int, char *);
81: static const char *inet6name(struct in6_addr *);
82: static void inet6print(struct in6_addr *, int, char *);
1.1 deraadt 83:
84: #define streq(a,b) (strcmp(a,b)==0)
1.2 mickey 85: #define YMAX(w) ((w)->_maxy-1)
1.1 deraadt 86:
87: WINDOW *
1.22 deraadt 88: opennetstat(void)
1.1 deraadt 89: {
90: sethostent(1);
91: setnetent(1);
92: return (subwin(stdscr, LINES-5-1, 0, 5, 0));
93: }
94:
95: struct netinfo {
1.11 angelos 96: struct netinfo *nif_forw, *nif_prev;
1.12 itojun 97: int nif_family;
1.11 angelos 98: short nif_line; /* line on screen */
99: short nif_seen; /* 0 when not present in list */
100: short nif_flags;
1.1 deraadt 101: #define NIF_LACHG 0x1 /* local address changed */
102: #define NIF_FACHG 0x2 /* foreign address changed */
1.11 angelos 103: short nif_state; /* tcp state */
104: char *nif_proto; /* protocol */
105: struct in_addr nif_laddr; /* local address */
1.12 itojun 106: struct in6_addr nif_laddr6; /* local address */
1.11 angelos 107: long nif_lport; /* local port */
108: struct in_addr nif_faddr; /* foreign address */
1.12 itojun 109: struct in6_addr nif_faddr6; /* foreign address */
1.11 angelos 110: long nif_fport; /* foreign port */
111: long nif_rcvcc; /* rcv buffer character count */
112: long nif_sndcc; /* snd buffer character count */
1.1 deraadt 113: };
114:
115: static struct {
1.11 angelos 116: struct netinfo *nif_forw, *nif_prev;
1.1 deraadt 117: } netcb;
118:
119: static int aflag = 0;
120: static int lastrow = 1;
121:
122: void
1.22 deraadt 123: closenetstat(WINDOW *w)
1.1 deraadt 124: {
1.17 mpech 125: struct netinfo *p;
1.1 deraadt 126:
127: endhostent();
128: endnetent();
1.11 angelos 129: p = (struct netinfo *)netcb.nif_forw;
1.1 deraadt 130: while (p != (struct netinfo *)&netcb) {
1.11 angelos 131: if (p->nif_line != -1)
1.1 deraadt 132: lastrow--;
1.11 angelos 133: p->nif_line = -1;
134: p = p->nif_forw;
1.1 deraadt 135: }
1.20 deraadt 136: if (w != NULL) {
1.1 deraadt 137: wclear(w);
138: wrefresh(w);
139: delwin(w);
140: }
141: }
142:
143: static struct nlist namelist[] = {
1.23 deraadt 144: #define X_TCBTABLE 0 /* no sysctl */
1.1 deraadt 145: { "_tcbtable" },
1.23 deraadt 146: #define X_UDBTABLE 1 /* no sysctl */
1.1 deraadt 147: { "_udbtable" },
148: { "" },
149: };
150:
151: int
1.22 deraadt 152: initnetstat(void)
1.1 deraadt 153: {
1.14 ericj 154: int ret;
155:
156: if ((ret = kvm_nlist(kd, namelist)) == -1)
157: errx(1, "%s", kvm_geterr(kd));
158: else if (ret)
1.1 deraadt 159: nlisterr(namelist);
160: if (namelist[X_TCBTABLE].n_value == 0) {
161: error("No symbols in namelist");
162: return(0);
163: }
1.11 angelos 164: netcb.nif_forw = netcb.nif_prev = (struct netinfo *)&netcb;
1.1 deraadt 165: protos = TCP|UDP;
166: return(1);
167: }
168:
169: void
1.22 deraadt 170: fetchnetstat(void)
1.1 deraadt 171: {
172: struct inpcbtable pcbtable;
1.17 mpech 173: struct inpcb *head, *prev, *next;
174: struct netinfo *p;
1.1 deraadt 175: struct inpcb inpcb;
176: struct socket sockb;
177: struct tcpcb tcpcb;
178: void *off;
179: int istcp;
180:
181: if (namelist[X_TCBTABLE].n_value == 0)
182: return;
1.11 angelos 183: for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw)
184: p->nif_seen = 0;
1.1 deraadt 185: if (protos&TCP) {
1.20 deraadt 186: off = NPTR(X_TCBTABLE);
1.1 deraadt 187: istcp = 1;
1.20 deraadt 188: } else if (protos&UDP) {
189: off = NPTR(X_UDBTABLE);
1.1 deraadt 190: istcp = 0;
1.20 deraadt 191: } else {
1.1 deraadt 192: error("No protocols to display");
193: return;
194: }
195: again:
196: KREAD(off, &pcbtable, sizeof (struct inpcbtable));
197: prev = head = (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue;
198: next = pcbtable.inpt_queue.cqh_first;
199: while (next != head) {
200: KREAD(next, &inpcb, sizeof (inpcb));
201: if (inpcb.inp_queue.cqe_prev != prev) {
1.22 deraadt 202: printf("prev = %p, head = %p, next = %p, inpcb...prev = %p\n",
203: prev, head, next, inpcb.inp_queue.cqe_prev);
1.11 angelos 204: p = netcb.nif_forw;
205: for (; p != (struct netinfo *)&netcb; p = p->nif_forw)
206: p->nif_seen = 1;
1.1 deraadt 207: error("Kernel state in transition");
208: return;
209: }
210: prev = next;
211: next = inpcb.inp_queue.cqe_next;
1.12 itojun 212:
213: if (!aflag) {
1.20 deraadt 214: if (!(inpcb.inp_flags & INP_IPV6) &&
215: inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
1.12 itojun 216: continue;
1.20 deraadt 217: if ((inpcb.inp_flags & INP_IPV6) &&
218: IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6))
1.12 itojun 219: continue;
220: }
1.1 deraadt 221: if (nhosts && !checkhost(&inpcb))
222: continue;
223: if (nports && !checkport(&inpcb))
224: continue;
225: KREAD(inpcb.inp_socket, &sockb, sizeof (sockb));
226: if (istcp) {
227: KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
228: enter(&inpcb, &sockb, tcpcb.t_state, "tcp");
229: } else
230: enter(&inpcb, &sockb, 0, "udp");
231: }
232: if (istcp && (protos&UDP)) {
233: istcp = 0;
234: off = NPTR(X_UDBTABLE);
235: goto again;
236: }
237: }
238:
239: static void
1.22 deraadt 240: enter(struct inpcb *inp, struct socket *so, int state, char *proto)
1.1 deraadt 241: {
1.17 mpech 242: struct netinfo *p;
1.1 deraadt 243:
244: /*
245: * Only take exact matches, any sockets with
246: * previously unbound addresses will be deleted
247: * below in the display routine because they
248: * will appear as ``not seen'' in the kernel
249: * data structures.
250: */
1.12 itojun 251: for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) {
252: if (p->nif_family == AF_INET && (inp->inp_flags & INP_IPV6))
253: continue;
254: if (p->nif_family == AF_INET6 && !(inp->inp_flags & INP_IPV6))
255: continue;
1.11 angelos 256: if (!streq(proto, p->nif_proto))
1.1 deraadt 257: continue;
1.12 itojun 258: if (p->nif_family == AF_INET) {
259: if (p->nif_lport != inp->inp_lport ||
260: p->nif_laddr.s_addr != inp->inp_laddr.s_addr)
261: continue;
262: if (p->nif_faddr.s_addr == inp->inp_faddr.s_addr &&
263: p->nif_fport == inp->inp_fport)
264: break;
265:
1.26 deraadt 266: } else if (p->nif_family == AF_INET6) {
1.12 itojun 267: if (p->nif_lport != inp->inp_lport ||
268: !IN6_ARE_ADDR_EQUAL(&p->nif_laddr6, &inp->inp_laddr6))
269: continue;
1.13 itojun 270: if (IN6_ARE_ADDR_EQUAL(&p->nif_faddr6, &inp->inp_faddr6) &&
1.12 itojun 271: p->nif_fport == inp->inp_fport)
272: break;
1.26 deraadt 273: } else
1.1 deraadt 274: continue;
275: }
276: if (p == (struct netinfo *)&netcb) {
277: if ((p = malloc(sizeof(*p))) == NULL) {
278: error("Out of memory");
279: return;
280: }
1.11 angelos 281: p->nif_prev = (struct netinfo *)&netcb;
282: p->nif_forw = netcb.nif_forw;
283: netcb.nif_forw->nif_prev = p;
284: netcb.nif_forw = p;
285: p->nif_line = -1;
286: p->nif_lport = inp->inp_lport;
287: p->nif_fport = inp->inp_fport;
288: p->nif_proto = proto;
289: p->nif_flags = NIF_LACHG|NIF_FACHG;
1.12 itojun 290: if (inp->inp_flags & INP_IPV6) {
291: p->nif_laddr6 = inp->inp_laddr6;
292: p->nif_faddr6 = inp->inp_faddr6;
293: p->nif_family = AF_INET6;
1.26 deraadt 294: } else {
1.12 itojun 295: p->nif_laddr = inp->inp_laddr;
296: p->nif_faddr = inp->inp_faddr;
297: p->nif_family = AF_INET;
298: }
1.11 angelos 299: }
300: p->nif_rcvcc = so->so_rcv.sb_cc;
301: p->nif_sndcc = so->so_snd.sb_cc;
302: p->nif_state = state;
303: p->nif_seen = 1;
1.1 deraadt 304: }
305:
306: /* column locations */
307: #define LADDR 0
308: #define FADDR LADDR+23
309: #define PROTO FADDR+23
310: #define RCVCC PROTO+6
311: #define SNDCC RCVCC+7
312: #define STATE SNDCC+7
313:
314:
315: void
1.22 deraadt 316: labelnetstat(void)
1.1 deraadt 317: {
318: if (namelist[X_TCBTABLE].n_type == 0)
319: return;
320: wmove(wnd, 0, 0); wclrtobot(wnd);
321: mvwaddstr(wnd, 0, LADDR, "Local Address");
322: mvwaddstr(wnd, 0, FADDR, "Foreign Address");
323: mvwaddstr(wnd, 0, PROTO, "Proto");
324: mvwaddstr(wnd, 0, RCVCC, "Recv-Q");
325: mvwaddstr(wnd, 0, SNDCC, "Send-Q");
1.20 deraadt 326: mvwaddstr(wnd, 0, STATE, "(state)");
1.1 deraadt 327: }
328:
329: void
1.22 deraadt 330: shownetstat(void)
1.1 deraadt 331: {
1.17 mpech 332: struct netinfo *p, *q;
1.1 deraadt 333:
334: /*
335: * First, delete any connections that have gone
336: * away and adjust the position of connections
337: * below to reflect the deleted line.
338: */
1.11 angelos 339: p = netcb.nif_forw;
1.1 deraadt 340: while (p != (struct netinfo *)&netcb) {
1.11 angelos 341: if (p->nif_line == -1 || p->nif_seen) {
342: p = p->nif_forw;
1.1 deraadt 343: continue;
344: }
1.11 angelos 345: wmove(wnd, p->nif_line, 0); wdeleteln(wnd);
346: q = netcb.nif_forw;
347: for (; q != (struct netinfo *)&netcb; q = q->nif_forw)
348: if (q != p && q->nif_line > p->nif_line) {
349: q->nif_line--;
1.1 deraadt 350: /* this shouldn't be necessary */
1.11 angelos 351: q->nif_flags |= NIF_LACHG|NIF_FACHG;
1.1 deraadt 352: }
353: lastrow--;
1.11 angelos 354: q = p->nif_forw;
355: p->nif_prev->nif_forw = p->nif_forw;
356: p->nif_forw->nif_prev = p->nif_prev;
1.1 deraadt 357: free(p);
358: p = q;
359: }
360: /*
361: * Update existing connections and add new ones.
362: */
1.12 itojun 363: for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) {
1.11 angelos 364: if (p->nif_line == -1) {
1.1 deraadt 365: /*
366: * Add a new entry if possible.
367: */
368: if (lastrow > YMAX(wnd))
369: continue;
1.11 angelos 370: p->nif_line = lastrow++;
371: p->nif_flags |= NIF_LACHG|NIF_FACHG;
1.1 deraadt 372: }
1.11 angelos 373: if (p->nif_flags & NIF_LACHG) {
374: wmove(wnd, p->nif_line, LADDR);
1.12 itojun 375: switch (p->nif_family) {
376: case AF_INET:
377: inetprint(&p->nif_laddr, p->nif_lport,
378: p->nif_proto);
379: break;
380: case AF_INET6:
381: inet6print(&p->nif_laddr6, p->nif_lport,
382: p->nif_proto);
383: break;
384: }
1.11 angelos 385: p->nif_flags &= ~NIF_LACHG;
1.1 deraadt 386: }
1.11 angelos 387: if (p->nif_flags & NIF_FACHG) {
388: wmove(wnd, p->nif_line, FADDR);
1.12 itojun 389: switch (p->nif_family) {
390: case AF_INET:
391: inetprint(&p->nif_faddr, p->nif_fport,
392: p->nif_proto);
393: break;
394: case AF_INET6:
395: inet6print(&p->nif_faddr6, p->nif_fport,
396: p->nif_proto);
397: break;
398: }
1.11 angelos 399: p->nif_flags &= ~NIF_FACHG;
1.1 deraadt 400: }
1.11 angelos 401: mvwaddstr(wnd, p->nif_line, PROTO, p->nif_proto);
1.12 itojun 402: if (p->nif_family == AF_INET6)
403: waddstr(wnd, "6");
1.11 angelos 404: mvwprintw(wnd, p->nif_line, RCVCC, "%6d", p->nif_rcvcc);
405: mvwprintw(wnd, p->nif_line, SNDCC, "%6d", p->nif_sndcc);
1.20 deraadt 406: if (streq(p->nif_proto, "tcp")) {
1.11 angelos 407: if (p->nif_state < 0 || p->nif_state >= TCP_NSTATES)
408: mvwprintw(wnd, p->nif_line, STATE, "%d",
409: p->nif_state);
1.1 deraadt 410: else
1.11 angelos 411: mvwaddstr(wnd, p->nif_line, STATE,
412: tcpstates[p->nif_state]);
1.20 deraadt 413: }
1.1 deraadt 414: wclrtoeol(wnd);
415: }
416: if (lastrow < YMAX(wnd)) {
417: wmove(wnd, lastrow, 0); wclrtobot(wnd);
418: wmove(wnd, YMAX(wnd), 0); wdeleteln(wnd); /* XXX */
419: }
420: }
421:
422: /*
423: * Pretty print an Internet address (net address + port).
424: * If the nflag was specified, use numbers instead of names.
425: */
426: static void
1.22 deraadt 427: inetprint(struct in_addr *in, int port, char *proto)
1.1 deraadt 428: {
429: struct servent *sp = 0;
1.6 millert 430: char line[80], *cp;
1.1 deraadt 431:
1.8 deraadt 432: snprintf(line, sizeof line, "%.*s.", 16, inetname(*in));
1.6 millert 433: cp = strchr(line, '\0');
1.1 deraadt 434: if (!nflag && port)
435: sp = getservbyport(port, proto);
436: if (sp || port == 0)
1.8 deraadt 437: snprintf(cp, sizeof line - strlen(cp), "%.8s",
438: sp ? sp->s_name : "*");
1.1 deraadt 439: else
1.8 deraadt 440: snprintf(cp, sizeof line - strlen(cp), "%d",
441: ntohs((u_short)port));
1.1 deraadt 442: /* pad to full column to clear any garbage */
1.6 millert 443: cp = strchr(line, '\0');
1.10 deraadt 444: while (cp - line < 22 && cp - line < sizeof line-1)
1.1 deraadt 445: *cp++ = ' ';
446: *cp = '\0';
447: waddstr(wnd, line);
448: }
449:
1.12 itojun 450: static void
1.22 deraadt 451: inet6print(struct in6_addr *in6, int port, char *proto)
1.12 itojun 452: {
453: struct servent *sp = 0;
454: char line[80], *cp;
455:
456: snprintf(line, sizeof line, "%.*s.", 16, inet6name(in6));
457: cp = strchr(line, '\0');
458: if (!nflag && port)
459: sp = getservbyport(port, proto);
460: if (sp || port == 0)
461: snprintf(cp, sizeof line - strlen(cp), "%.8s",
462: sp ? sp->s_name : "*");
463: else
464: snprintf(cp, sizeof line - strlen(cp), "%d",
465: ntohs((u_short)port));
466: /* pad to full column to clear any garbage */
467: cp = strchr(line, '\0');
468: while (cp - line < 22 && cp - line < sizeof line-1)
469: *cp++ = ' ';
470: *cp = '\0';
471: waddstr(wnd, line);
472: }
473:
1.1 deraadt 474: /*
475: * Construct an Internet address representation.
1.20 deraadt 476: * If the nflag has been supplied, give
1.1 deraadt 477: * numeric value, otherwise try for symbolic name.
478: */
1.12 itojun 479: static const char *
1.22 deraadt 480: inetname(struct in_addr in)
1.1 deraadt 481: {
482: char *cp = 0;
483: static char line[50];
484: struct hostent *hp;
485: struct netent *np;
486:
487: if (!nflag && in.s_addr != INADDR_ANY) {
488: int net = inet_netof(in);
489: int lna = inet_lnaof(in);
490:
491: if (lna == INADDR_ANY) {
492: np = getnetbyaddr(net, AF_INET);
493: if (np)
494: cp = np->n_name;
495: }
496: if (cp == 0) {
497: hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
498: if (hp)
499: cp = hp->h_name;
500: }
501: }
1.9 deraadt 502: if (in.s_addr == INADDR_ANY) {
1.15 lebel 503: strlcpy(line, "*", sizeof line);
1.9 deraadt 504: } else if (cp) {
1.15 lebel 505: strlcpy(line, cp, sizeof line);
1.9 deraadt 506: } else {
1.1 deraadt 507: in.s_addr = ntohl(in.s_addr);
508: #define C(x) ((x) & 0xff)
1.8 deraadt 509: snprintf(line, sizeof line, "%u.%u.%u.%u", C(in.s_addr >> 24),
1.20 deraadt 510: C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
1.1 deraadt 511: }
512: return (line);
513: }
1.12 itojun 514:
515: static const char *
1.22 deraadt 516: inet6name(struct in6_addr *in6)
1.12 itojun 517: {
518: static char line[NI_MAXHOST];
519: struct sockaddr_in6 sin6;
520: int flags;
521:
1.25 itojun 522: flags = nflag ? NI_NUMERICHOST : 0;
1.12 itojun 523: if (IN6_IS_ADDR_UNSPECIFIED(in6))
524: return "*";
525: memset(&sin6, 0, sizeof(sin6));
526: sin6.sin6_family = AF_INET6;
527: sin6.sin6_len = sizeof(struct sockaddr_in6);
528: sin6.sin6_addr = *in6;
529: if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
1.20 deraadt 530: line, sizeof(line), NULL, 0, flags) == 0)
1.12 itojun 531: return line;
532: return "?";
533: }
1.1 deraadt 534:
535: int
1.22 deraadt 536: cmdnetstat(char *cmd, char *args)
1.1 deraadt 537: {
1.17 mpech 538: struct netinfo *p;
1.1 deraadt 539:
540: if (prefix(cmd, "all")) {
541: aflag = !aflag;
542: goto fixup;
543: }
544: if (prefix(cmd, "numbers") || prefix(cmd, "names")) {
545: int new;
546:
547: new = prefix(cmd, "numbers");
548: if (new == nflag)
549: return (1);
1.11 angelos 550: p = netcb.nif_forw;
551: for (; p != (struct netinfo *)&netcb; p = p->nif_forw) {
552: if (p->nif_line == -1)
1.1 deraadt 553: continue;
1.11 angelos 554: p->nif_flags |= NIF_LACHG|NIF_FACHG;
1.1 deraadt 555: }
556: nflag = new;
1.4 deraadt 557: wclear(wnd);
558: labelnetstat();
1.1 deraadt 559: goto redisplay;
560: }
561: if (!netcmd(cmd, args))
562: return (0);
563: fixup:
564: fetchnetstat();
565: redisplay:
566: shownetstat();
567: refresh();
568: return (1);
569: }