Annotation of src/usr.bin/systat/netstat.c, Revision 1.26
1.26 ! deraadt 1: /* $OpenBSD: netstat.c,v 1.25 2004/04/26 19:22:30 itojun 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.26 ! deraadt 37: static char rcsid[] = "$OpenBSD: netstat.c,v 1.25 2004/04/26 19:22:30 itojun 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;
212:
1.12 itojun 213: if (inpcb.inp_flags & INP_IPV6)
1.1 deraadt 214: continue;
1.12 itojun 215:
216: if (!aflag) {
1.20 deraadt 217: if (!(inpcb.inp_flags & INP_IPV6) &&
218: inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
1.12 itojun 219: continue;
1.20 deraadt 220: if ((inpcb.inp_flags & INP_IPV6) &&
221: IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6))
1.12 itojun 222: continue;
223: }
1.1 deraadt 224: if (nhosts && !checkhost(&inpcb))
225: continue;
226: if (nports && !checkport(&inpcb))
227: continue;
228: KREAD(inpcb.inp_socket, &sockb, sizeof (sockb));
229: if (istcp) {
230: KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
231: enter(&inpcb, &sockb, tcpcb.t_state, "tcp");
232: } else
233: enter(&inpcb, &sockb, 0, "udp");
234: }
235: if (istcp && (protos&UDP)) {
236: istcp = 0;
237: off = NPTR(X_UDBTABLE);
238: goto again;
239: }
240: }
241:
242: static void
1.22 deraadt 243: enter(struct inpcb *inp, struct socket *so, int state, char *proto)
1.1 deraadt 244: {
1.17 mpech 245: struct netinfo *p;
1.1 deraadt 246:
247: /*
248: * Only take exact matches, any sockets with
249: * previously unbound addresses will be deleted
250: * below in the display routine because they
251: * will appear as ``not seen'' in the kernel
252: * data structures.
253: */
1.12 itojun 254: for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) {
255: if (p->nif_family == AF_INET && (inp->inp_flags & INP_IPV6))
256: continue;
257: if (p->nif_family == AF_INET6 && !(inp->inp_flags & INP_IPV6))
258: continue;
1.11 angelos 259: if (!streq(proto, p->nif_proto))
1.1 deraadt 260: continue;
1.12 itojun 261: if (p->nif_family == AF_INET) {
262: if (p->nif_lport != inp->inp_lport ||
263: p->nif_laddr.s_addr != inp->inp_laddr.s_addr)
264: continue;
265: if (p->nif_faddr.s_addr == inp->inp_faddr.s_addr &&
266: p->nif_fport == inp->inp_fport)
267: break;
268:
1.26 ! deraadt 269: } else if (p->nif_family == AF_INET6) {
1.12 itojun 270: if (p->nif_lport != inp->inp_lport ||
271: !IN6_ARE_ADDR_EQUAL(&p->nif_laddr6, &inp->inp_laddr6))
272: continue;
1.13 itojun 273: if (IN6_ARE_ADDR_EQUAL(&p->nif_faddr6, &inp->inp_faddr6) &&
1.12 itojun 274: p->nif_fport == inp->inp_fport)
275: break;
1.26 ! deraadt 276: } else
1.1 deraadt 277: continue;
278: }
279: if (p == (struct netinfo *)&netcb) {
280: if ((p = malloc(sizeof(*p))) == NULL) {
281: error("Out of memory");
282: return;
283: }
1.11 angelos 284: p->nif_prev = (struct netinfo *)&netcb;
285: p->nif_forw = netcb.nif_forw;
286: netcb.nif_forw->nif_prev = p;
287: netcb.nif_forw = p;
288: p->nif_line = -1;
289: p->nif_lport = inp->inp_lport;
290: p->nif_fport = inp->inp_fport;
291: p->nif_proto = proto;
292: p->nif_flags = NIF_LACHG|NIF_FACHG;
1.12 itojun 293: if (inp->inp_flags & INP_IPV6) {
294: p->nif_laddr6 = inp->inp_laddr6;
295: p->nif_faddr6 = inp->inp_faddr6;
296: p->nif_family = AF_INET6;
1.26 ! deraadt 297: } else {
1.12 itojun 298: p->nif_laddr = inp->inp_laddr;
299: p->nif_faddr = inp->inp_faddr;
300: p->nif_family = AF_INET;
301: }
1.11 angelos 302: }
303: p->nif_rcvcc = so->so_rcv.sb_cc;
304: p->nif_sndcc = so->so_snd.sb_cc;
305: p->nif_state = state;
306: p->nif_seen = 1;
1.1 deraadt 307: }
308:
309: /* column locations */
310: #define LADDR 0
311: #define FADDR LADDR+23
312: #define PROTO FADDR+23
313: #define RCVCC PROTO+6
314: #define SNDCC RCVCC+7
315: #define STATE SNDCC+7
316:
317:
318: void
1.22 deraadt 319: labelnetstat(void)
1.1 deraadt 320: {
321: if (namelist[X_TCBTABLE].n_type == 0)
322: return;
323: wmove(wnd, 0, 0); wclrtobot(wnd);
324: mvwaddstr(wnd, 0, LADDR, "Local Address");
325: mvwaddstr(wnd, 0, FADDR, "Foreign Address");
326: mvwaddstr(wnd, 0, PROTO, "Proto");
327: mvwaddstr(wnd, 0, RCVCC, "Recv-Q");
328: mvwaddstr(wnd, 0, SNDCC, "Send-Q");
1.20 deraadt 329: mvwaddstr(wnd, 0, STATE, "(state)");
1.1 deraadt 330: }
331:
332: void
1.22 deraadt 333: shownetstat(void)
1.1 deraadt 334: {
1.17 mpech 335: struct netinfo *p, *q;
1.1 deraadt 336:
337: /*
338: * First, delete any connections that have gone
339: * away and adjust the position of connections
340: * below to reflect the deleted line.
341: */
1.11 angelos 342: p = netcb.nif_forw;
1.1 deraadt 343: while (p != (struct netinfo *)&netcb) {
1.11 angelos 344: if (p->nif_line == -1 || p->nif_seen) {
345: p = p->nif_forw;
1.1 deraadt 346: continue;
347: }
1.11 angelos 348: wmove(wnd, p->nif_line, 0); wdeleteln(wnd);
349: q = netcb.nif_forw;
350: for (; q != (struct netinfo *)&netcb; q = q->nif_forw)
351: if (q != p && q->nif_line > p->nif_line) {
352: q->nif_line--;
1.1 deraadt 353: /* this shouldn't be necessary */
1.11 angelos 354: q->nif_flags |= NIF_LACHG|NIF_FACHG;
1.1 deraadt 355: }
356: lastrow--;
1.11 angelos 357: q = p->nif_forw;
358: p->nif_prev->nif_forw = p->nif_forw;
359: p->nif_forw->nif_prev = p->nif_prev;
1.1 deraadt 360: free(p);
361: p = q;
362: }
363: /*
364: * Update existing connections and add new ones.
365: */
1.12 itojun 366: for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) {
1.11 angelos 367: if (p->nif_line == -1) {
1.1 deraadt 368: /*
369: * Add a new entry if possible.
370: */
371: if (lastrow > YMAX(wnd))
372: continue;
1.11 angelos 373: p->nif_line = lastrow++;
374: p->nif_flags |= NIF_LACHG|NIF_FACHG;
1.1 deraadt 375: }
1.11 angelos 376: if (p->nif_flags & NIF_LACHG) {
377: wmove(wnd, p->nif_line, LADDR);
1.12 itojun 378: switch (p->nif_family) {
379: case AF_INET:
380: inetprint(&p->nif_laddr, p->nif_lport,
381: p->nif_proto);
382: break;
383: case AF_INET6:
384: inet6print(&p->nif_laddr6, p->nif_lport,
385: p->nif_proto);
386: break;
387: }
1.11 angelos 388: p->nif_flags &= ~NIF_LACHG;
1.1 deraadt 389: }
1.11 angelos 390: if (p->nif_flags & NIF_FACHG) {
391: wmove(wnd, p->nif_line, FADDR);
1.12 itojun 392: switch (p->nif_family) {
393: case AF_INET:
394: inetprint(&p->nif_faddr, p->nif_fport,
395: p->nif_proto);
396: break;
397: case AF_INET6:
398: inet6print(&p->nif_faddr6, p->nif_fport,
399: p->nif_proto);
400: break;
401: }
1.11 angelos 402: p->nif_flags &= ~NIF_FACHG;
1.1 deraadt 403: }
1.11 angelos 404: mvwaddstr(wnd, p->nif_line, PROTO, p->nif_proto);
1.12 itojun 405: if (p->nif_family == AF_INET6)
406: waddstr(wnd, "6");
1.11 angelos 407: mvwprintw(wnd, p->nif_line, RCVCC, "%6d", p->nif_rcvcc);
408: mvwprintw(wnd, p->nif_line, SNDCC, "%6d", p->nif_sndcc);
1.20 deraadt 409: if (streq(p->nif_proto, "tcp")) {
1.11 angelos 410: if (p->nif_state < 0 || p->nif_state >= TCP_NSTATES)
411: mvwprintw(wnd, p->nif_line, STATE, "%d",
412: p->nif_state);
1.1 deraadt 413: else
1.11 angelos 414: mvwaddstr(wnd, p->nif_line, STATE,
415: tcpstates[p->nif_state]);
1.20 deraadt 416: }
1.1 deraadt 417: wclrtoeol(wnd);
418: }
419: if (lastrow < YMAX(wnd)) {
420: wmove(wnd, lastrow, 0); wclrtobot(wnd);
421: wmove(wnd, YMAX(wnd), 0); wdeleteln(wnd); /* XXX */
422: }
423: }
424:
425: /*
426: * Pretty print an Internet address (net address + port).
427: * If the nflag was specified, use numbers instead of names.
428: */
429: static void
1.22 deraadt 430: inetprint(struct in_addr *in, int port, char *proto)
1.1 deraadt 431: {
432: struct servent *sp = 0;
1.6 millert 433: char line[80], *cp;
1.1 deraadt 434:
1.8 deraadt 435: snprintf(line, sizeof line, "%.*s.", 16, inetname(*in));
1.6 millert 436: cp = strchr(line, '\0');
1.1 deraadt 437: if (!nflag && port)
438: sp = getservbyport(port, proto);
439: if (sp || port == 0)
1.8 deraadt 440: snprintf(cp, sizeof line - strlen(cp), "%.8s",
441: sp ? sp->s_name : "*");
1.1 deraadt 442: else
1.8 deraadt 443: snprintf(cp, sizeof line - strlen(cp), "%d",
444: ntohs((u_short)port));
1.1 deraadt 445: /* pad to full column to clear any garbage */
1.6 millert 446: cp = strchr(line, '\0');
1.10 deraadt 447: while (cp - line < 22 && cp - line < sizeof line-1)
1.1 deraadt 448: *cp++ = ' ';
449: *cp = '\0';
450: waddstr(wnd, line);
451: }
452:
1.12 itojun 453: static void
1.22 deraadt 454: inet6print(struct in6_addr *in6, int port, char *proto)
1.12 itojun 455: {
456: struct servent *sp = 0;
457: char line[80], *cp;
458:
459: snprintf(line, sizeof line, "%.*s.", 16, inet6name(in6));
460: cp = strchr(line, '\0');
461: if (!nflag && port)
462: sp = getservbyport(port, proto);
463: if (sp || port == 0)
464: snprintf(cp, sizeof line - strlen(cp), "%.8s",
465: sp ? sp->s_name : "*");
466: else
467: snprintf(cp, sizeof line - strlen(cp), "%d",
468: ntohs((u_short)port));
469: /* pad to full column to clear any garbage */
470: cp = strchr(line, '\0');
471: while (cp - line < 22 && cp - line < sizeof line-1)
472: *cp++ = ' ';
473: *cp = '\0';
474: waddstr(wnd, line);
475: }
476:
1.1 deraadt 477: /*
478: * Construct an Internet address representation.
1.20 deraadt 479: * If the nflag has been supplied, give
1.1 deraadt 480: * numeric value, otherwise try for symbolic name.
481: */
1.12 itojun 482: static const char *
1.22 deraadt 483: inetname(struct in_addr in)
1.1 deraadt 484: {
485: char *cp = 0;
486: static char line[50];
487: struct hostent *hp;
488: struct netent *np;
489:
490: if (!nflag && in.s_addr != INADDR_ANY) {
491: int net = inet_netof(in);
492: int lna = inet_lnaof(in);
493:
494: if (lna == INADDR_ANY) {
495: np = getnetbyaddr(net, AF_INET);
496: if (np)
497: cp = np->n_name;
498: }
499: if (cp == 0) {
500: hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
501: if (hp)
502: cp = hp->h_name;
503: }
504: }
1.9 deraadt 505: if (in.s_addr == INADDR_ANY) {
1.15 lebel 506: strlcpy(line, "*", sizeof line);
1.9 deraadt 507: } else if (cp) {
1.15 lebel 508: strlcpy(line, cp, sizeof line);
1.9 deraadt 509: } else {
1.1 deraadt 510: in.s_addr = ntohl(in.s_addr);
511: #define C(x) ((x) & 0xff)
1.8 deraadt 512: snprintf(line, sizeof line, "%u.%u.%u.%u", C(in.s_addr >> 24),
1.20 deraadt 513: C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
1.1 deraadt 514: }
515: return (line);
516: }
1.12 itojun 517:
518: static const char *
1.22 deraadt 519: inet6name(struct in6_addr *in6)
1.12 itojun 520: {
521: static char line[NI_MAXHOST];
522: struct sockaddr_in6 sin6;
523: int flags;
524:
1.25 itojun 525: flags = nflag ? NI_NUMERICHOST : 0;
1.12 itojun 526: if (IN6_IS_ADDR_UNSPECIFIED(in6))
527: return "*";
528: memset(&sin6, 0, sizeof(sin6));
529: sin6.sin6_family = AF_INET6;
530: sin6.sin6_len = sizeof(struct sockaddr_in6);
531: sin6.sin6_addr = *in6;
532: if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
1.20 deraadt 533: line, sizeof(line), NULL, 0, flags) == 0)
1.12 itojun 534: return line;
535: return "?";
536: }
1.1 deraadt 537:
538: int
1.22 deraadt 539: cmdnetstat(char *cmd, char *args)
1.1 deraadt 540: {
1.17 mpech 541: struct netinfo *p;
1.1 deraadt 542:
543: if (prefix(cmd, "all")) {
544: aflag = !aflag;
545: goto fixup;
546: }
547: if (prefix(cmd, "numbers") || prefix(cmd, "names")) {
548: int new;
549:
550: new = prefix(cmd, "numbers");
551: if (new == nflag)
552: return (1);
1.11 angelos 553: p = netcb.nif_forw;
554: for (; p != (struct netinfo *)&netcb; p = p->nif_forw) {
555: if (p->nif_line == -1)
1.1 deraadt 556: continue;
1.11 angelos 557: p->nif_flags |= NIF_LACHG|NIF_FACHG;
1.1 deraadt 558: }
559: nflag = new;
1.4 deraadt 560: wclear(wnd);
561: labelnetstat();
1.1 deraadt 562: goto redisplay;
563: }
564: if (!netcmd(cmd, args))
565: return (0);
566: fixup:
567: fetchnetstat();
568: redisplay:
569: shownetstat();
570: refresh();
571: return (1);
572: }