1 /* $NetBSD: netstat.c,v 1.17 2000/01/10 21:06:16 itojun Exp $ */ 2 3 /*- 4 * Copyright (c) 1980, 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)netstat.c 8.1 (Berkeley) 6/6/93"; 40 #endif 41 __RCSID("$NetBSD: netstat.c,v 1.17 2000/01/10 21:06:16 itojun Exp $"); 42 #endif /* not lint */ 43 44 /* 45 * netstat 46 */ 47 #include <sys/param.h> 48 #include <sys/socket.h> 49 #include <sys/socketvar.h> 50 #include <sys/mbuf.h> 51 #include <sys/protosw.h> 52 53 #include <netinet/in.h> 54 55 #include <arpa/inet.h> 56 #include <net/route.h> 57 58 #include <netinet/in_systm.h> 59 #include <netinet/ip.h> 60 #include <netinet/in_pcb.h> 61 #include <netinet/ip_icmp.h> 62 #include <netinet/icmp_var.h> 63 #include <netinet/ip_var.h> 64 #ifdef INET6 65 #include <netinet/ip6.h> 66 #include <netinet6/in6_pcb.h> 67 #endif 68 #include <netinet/tcp.h> 69 #include <netinet/tcpip.h> 70 #include <netinet/tcp_seq.h> 71 #define TCPSTATES 72 #include <netinet/tcp_fsm.h> 73 #include <netinet/tcp_timer.h> 74 #include <netinet/tcp_var.h> 75 #include <netinet/tcp_debug.h> 76 #include <netinet/udp.h> 77 #include <netinet/udp_var.h> 78 79 #include <netdb.h> 80 #include <stdlib.h> 81 #include <string.h> 82 #include <nlist.h> 83 #include <paths.h> 84 #include "systat.h" 85 #include "extern.h" 86 87 static void fetchnetstat4 __P((void *, int)); 88 static void enter __P((struct inpcb *, struct socket *, int, char *)); 89 static const char *inetname __P((struct in_addr)); 90 static void inetprint __P((struct in_addr *, int, char *)); 91 #ifdef INET6 92 static void fetchnetstat6 __P((void *, int)); 93 static void enter6 __P((struct in6pcb *, struct socket *, int, char *)); 94 static const char *inet6name __P((struct in6_addr *)); 95 static void inet6print __P((struct in6_addr *, int, char *)); 96 #endif 97 98 #define streq(a,b) (strcmp(a,b)==0) 99 100 struct netinfo { 101 struct netinfo *ni_forw, *ni_prev; 102 int ni_family; 103 short ni_line; /* line on screen */ 104 short ni_seen; /* 0 when not present in list */ 105 short ni_flags; 106 #define NIF_LACHG 0x1 /* local address changed */ 107 #define NIF_FACHG 0x2 /* foreign address changed */ 108 short ni_state; /* tcp state */ 109 char *ni_proto; /* protocol */ 110 struct in_addr ni_laddr; /* local address */ 111 #ifdef INET6 112 struct in6_addr ni_laddr6; /* local address */ 113 #endif 114 long ni_lport; /* local port */ 115 struct in_addr ni_faddr; /* foreign address */ 116 #ifdef INET6 117 struct in6_addr ni_faddr6; /* foreign address */ 118 #endif 119 long ni_fport; /* foreign port */ 120 long ni_rcvcc; /* rcv buffer character count */ 121 long ni_sndcc; /* snd buffer character count */ 122 }; 123 124 static struct { 125 struct netinfo *ni_forw, *ni_prev; 126 } netcb; 127 128 static int aflag = 0; 129 int nflag = 0; 130 static int lastrow = 1; 131 132 WINDOW * 133 opennetstat() 134 { 135 136 sethostent(1); 137 setnetent(1); 138 return (subwin(stdscr, LINES-5-1, 0, 5, 0)); 139 } 140 141 void 142 closenetstat(w) 143 WINDOW *w; 144 { 145 struct netinfo *p; 146 147 endhostent(); 148 endnetent(); 149 p = (struct netinfo *)netcb.ni_forw; 150 while (p != (struct netinfo *)&netcb) { 151 if (p->ni_line != -1) 152 lastrow--; 153 p->ni_line = -1; 154 p = p->ni_forw; 155 } 156 if (w != NULL) { 157 wclear(w); 158 wrefresh(w); 159 delwin(w); 160 } 161 } 162 163 static struct nlist namelist[] = { 164 #define X_TCBTABLE 0 165 { "_tcbtable" }, 166 #define X_UDBTABLE 1 167 { "_udbtable" }, 168 #ifdef INET6 169 #define X_TCB6 2 170 { "_tcb6" }, 171 #define X_UDB6 3 172 { "_udb6" }, 173 #endif 174 { "" }, 175 }; 176 177 int 178 initnetstat() 179 { 180 int n; 181 182 n = kvm_nlist(kd, namelist); 183 if (n < 0) { 184 nlisterr(namelist); 185 return(0); 186 } else if (n == sizeof(namelist) / sizeof(namelist[0]) - 1) { 187 error("No symbols in namelist"); 188 return(0); 189 } 190 191 netcb.ni_forw = netcb.ni_prev = (struct netinfo *)&netcb; 192 protos = TCP|UDP; 193 return(1); 194 } 195 196 void 197 fetchnetstat() 198 { 199 struct netinfo *p; 200 201 if (namelist[X_TCBTABLE].n_value == 0) 202 return; 203 for (p = netcb.ni_forw; p != (struct netinfo *)&netcb; p = p->ni_forw) 204 p->ni_seen = 0; 205 206 if ((protos & (TCP | UDP)) == 0) { 207 error("No protocols to display"); 208 return; 209 } 210 if ((protos & TCP) && namelist[X_TCBTABLE].n_type) 211 fetchnetstat4(NPTR(X_TCBTABLE), 1); 212 if ((protos & UDP) && namelist[X_UDBTABLE].n_type) 213 fetchnetstat4(NPTR(X_UDBTABLE), 0); 214 #ifdef INET6 215 if ((protos & TCP) && namelist[X_TCB6].n_type) 216 fetchnetstat6(NPTR(X_TCB6), 1); 217 if ((protos & UDP) && namelist[X_UDB6].n_type) 218 fetchnetstat6(NPTR(X_UDB6), 0); 219 #endif 220 } 221 222 static void 223 fetchnetstat4(off, istcp) 224 void *off; 225 int istcp; 226 { 227 struct inpcbtable pcbtable; 228 struct inpcb *head, *prev, *next; 229 struct netinfo *p; 230 struct inpcb inpcb; 231 struct socket sockb; 232 struct tcpcb tcpcb; 233 234 KREAD(off, &pcbtable, sizeof pcbtable); 235 prev = head = (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue; 236 next = pcbtable.inpt_queue.cqh_first; 237 while (next != head) { 238 KREAD(next, &inpcb, sizeof (inpcb)); 239 if (inpcb.inp_queue.cqe_prev != prev) { 240 printf("prev = %p, head = %p, next = %p, inpcb...prev = %p\n", prev, head, next, inpcb.inp_queue.cqe_prev); 241 p = netcb.ni_forw; 242 for (; p != (struct netinfo *)&netcb; p = p->ni_forw) 243 p->ni_seen = 1; 244 error("Kernel state in transition"); 245 return; 246 } 247 prev = next; 248 next = inpcb.inp_queue.cqe_next; 249 250 if (!aflag && inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) 251 continue; 252 if (nhosts && !checkhost(&inpcb)) 253 continue; 254 if (nports && !checkport(&inpcb)) 255 continue; 256 KREAD(inpcb.inp_socket, &sockb, sizeof (sockb)); 257 if (istcp) { 258 KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb)); 259 enter(&inpcb, &sockb, tcpcb.t_state, "tcp"); 260 } else 261 enter(&inpcb, &sockb, 0, "udp"); 262 } 263 } 264 265 #ifdef INET6 266 static void 267 fetchnetstat6(off, istcp) 268 void *off; 269 int istcp; 270 { 271 struct netinfo *p; 272 struct socket sockb; 273 struct tcpcb tcpcb; 274 struct in6pcb in6pcb; 275 struct in6pcb *head6, *prev6, *next6; 276 277 KREAD(off, &in6pcb, sizeof (struct in6pcb)); 278 prev6 = head6 = (struct in6pcb *)off; 279 next6 = in6pcb.in6p_next; 280 while (next6 != head6) { 281 KREAD(next6, &in6pcb, sizeof (in6pcb)); 282 if (in6pcb.in6p_prev != prev6) { 283 printf("prev = %p, head = %p, next = %p, in6pcb...prev = %p\n", prev6, head6, next6, in6pcb.in6p_prev); 284 p = netcb.ni_forw; 285 for (; p != (struct netinfo *)&netcb; p = p->ni_forw) 286 p->ni_seen = 1; 287 error("Kernel state in transition"); 288 return; 289 } 290 prev6 = next6; 291 next6 = in6pcb.in6p_next; 292 293 if (!aflag && IN6_IS_ADDR_UNSPECIFIED(&in6pcb.in6p_laddr)) 294 continue; 295 if (nhosts && !checkhost6(&in6pcb)) 296 continue; 297 if (nports && !checkport6(&in6pcb)) 298 continue; 299 KREAD(in6pcb.in6p_socket, &sockb, sizeof (sockb)); 300 if (istcp) { 301 KREAD(in6pcb.in6p_ppcb, &tcpcb, sizeof (tcpcb)); 302 enter6(&in6pcb, &sockb, tcpcb.t_state, "tcp"); 303 } else 304 enter6(&in6pcb, &sockb, 0, "udp"); 305 } 306 } 307 #endif /*INET6*/ 308 309 static void 310 enter(inp, so, state, proto) 311 struct inpcb *inp; 312 struct socket *so; 313 int state; 314 char *proto; 315 { 316 struct netinfo *p; 317 318 /* 319 * Only take exact matches, any sockets with 320 * previously unbound addresses will be deleted 321 * below in the display routine because they 322 * will appear as ``not seen'' in the kernel 323 * data structures. 324 */ 325 for (p = netcb.ni_forw; p != (struct netinfo *)&netcb; p = p->ni_forw) { 326 if (p->ni_family != AF_INET) 327 continue; 328 if (!streq(proto, p->ni_proto)) 329 continue; 330 if (p->ni_lport != inp->inp_lport || 331 p->ni_laddr.s_addr != inp->inp_laddr.s_addr) 332 continue; 333 if (p->ni_faddr.s_addr == inp->inp_faddr.s_addr && 334 p->ni_fport == inp->inp_fport) 335 break; 336 } 337 if (p == (struct netinfo *)&netcb) { 338 if ((p = malloc(sizeof(*p))) == NULL) { 339 error("Out of memory"); 340 return; 341 } 342 p->ni_prev = (struct netinfo *)&netcb; 343 p->ni_forw = netcb.ni_forw; 344 netcb.ni_forw->ni_prev = p; 345 netcb.ni_forw = p; 346 p->ni_line = -1; 347 p->ni_laddr = inp->inp_laddr; 348 p->ni_lport = inp->inp_lport; 349 p->ni_faddr = inp->inp_faddr; 350 p->ni_fport = inp->inp_fport; 351 p->ni_proto = proto; 352 p->ni_flags = NIF_LACHG|NIF_FACHG; 353 p->ni_family = AF_INET; 354 } 355 p->ni_rcvcc = so->so_rcv.sb_cc; 356 p->ni_sndcc = so->so_snd.sb_cc; 357 p->ni_state = state; 358 p->ni_seen = 1; 359 } 360 361 #ifdef INET6 362 static void 363 enter6(in6p, so, state, proto) 364 struct in6pcb *in6p; 365 struct socket *so; 366 int state; 367 char *proto; 368 { 369 struct netinfo *p; 370 371 /* 372 * Only take exact matches, any sockets with 373 * previously unbound addresses will be deleted 374 * below in the display routine because they 375 * will appear as ``not seen'' in the kernel 376 * data structures. 377 */ 378 for (p = netcb.ni_forw; p != (struct netinfo *)&netcb; p = p->ni_forw) { 379 if (p->ni_family != AF_INET6) 380 continue; 381 if (!streq(proto, p->ni_proto)) 382 continue; 383 if (p->ni_lport != in6p->in6p_lport || 384 !IN6_ARE_ADDR_EQUAL(&p->ni_laddr6, &in6p->in6p_laddr)) 385 continue; 386 if (IN6_ARE_ADDR_EQUAL(&p->ni_faddr6, &in6p->in6p_faddr) && 387 p->ni_fport == in6p->in6p_fport) 388 break; 389 } 390 if (p == (struct netinfo *)&netcb) { 391 if ((p = malloc(sizeof(*p))) == NULL) { 392 error("Out of memory"); 393 return; 394 } 395 p->ni_prev = (struct netinfo *)&netcb; 396 p->ni_forw = netcb.ni_forw; 397 netcb.ni_forw->ni_prev = p; 398 netcb.ni_forw = p; 399 p->ni_line = -1; 400 p->ni_laddr6 = in6p->in6p_laddr; 401 p->ni_lport = in6p->in6p_lport; 402 p->ni_faddr6 = in6p->in6p_faddr; 403 p->ni_fport = in6p->in6p_fport; 404 p->ni_proto = proto; 405 p->ni_flags = NIF_LACHG|NIF_FACHG; 406 p->ni_family = AF_INET6; 407 } 408 p->ni_rcvcc = so->so_rcv.sb_cc; 409 p->ni_sndcc = so->so_snd.sb_cc; 410 p->ni_state = state; 411 p->ni_seen = 1; 412 } 413 #endif 414 415 /* column locations */ 416 #define LADDR 0 417 #define FADDR LADDR+23 418 #define PROTO FADDR+23 419 #define RCVCC PROTO+6 420 #define SNDCC RCVCC+7 421 #define STATE SNDCC+7 422 423 void 424 labelnetstat() 425 { 426 427 if (namelist[X_TCBTABLE].n_type == 0) 428 return; 429 wmove(wnd, 0, 0); wclrtobot(wnd); 430 mvwaddstr(wnd, 0, LADDR, "Local Address"); 431 mvwaddstr(wnd, 0, FADDR, "Foreign Address"); 432 mvwaddstr(wnd, 0, PROTO, "Proto"); 433 mvwaddstr(wnd, 0, RCVCC, "Recv-Q"); 434 mvwaddstr(wnd, 0, SNDCC, "Send-Q"); 435 mvwaddstr(wnd, 0, STATE, "(state)"); 436 } 437 438 void 439 shownetstat() 440 { 441 struct netinfo *p, *q; 442 443 /* 444 * First, delete any connections that have gone 445 * away and adjust the position of connections 446 * below to reflect the deleted line. 447 */ 448 p = netcb.ni_forw; 449 while (p != (struct netinfo *)&netcb) { 450 if (p->ni_line == -1 || p->ni_seen) { 451 p = p->ni_forw; 452 continue; 453 } 454 wmove(wnd, p->ni_line, 0); wdeleteln(wnd); 455 q = netcb.ni_forw; 456 for (; q != (struct netinfo *)&netcb; q = q->ni_forw) 457 if (q != p && q->ni_line > p->ni_line) { 458 q->ni_line--; 459 /* this shouldn't be necessary */ 460 q->ni_flags |= NIF_LACHG|NIF_FACHG; 461 } 462 lastrow--; 463 q = p->ni_forw; 464 p->ni_prev->ni_forw = p->ni_forw; 465 p->ni_forw->ni_prev = p->ni_prev; 466 free(p); 467 p = q; 468 } 469 /* 470 * Update existing connections and add new ones. 471 */ 472 for (p = netcb.ni_forw; p != (struct netinfo *)&netcb; p = p->ni_forw) { 473 if (p->ni_line == -1) { 474 /* 475 * Add a new entry if possible. 476 */ 477 if (lastrow > getmaxy(wnd)) 478 continue; 479 p->ni_line = lastrow++; 480 p->ni_flags |= NIF_LACHG|NIF_FACHG; 481 } 482 if (p->ni_flags & NIF_LACHG) { 483 wmove(wnd, p->ni_line, LADDR); 484 switch (p->ni_family) { 485 case AF_INET: 486 inetprint(&p->ni_laddr, p->ni_lport, 487 p->ni_proto); 488 break; 489 #ifdef INET6 490 case AF_INET6: 491 inet6print(&p->ni_laddr6, p->ni_lport, 492 p->ni_proto); 493 break; 494 #endif 495 } 496 p->ni_flags &= ~NIF_LACHG; 497 } 498 if (p->ni_flags & NIF_FACHG) { 499 wmove(wnd, p->ni_line, FADDR); 500 switch (p->ni_family) { 501 case AF_INET: 502 inetprint(&p->ni_faddr, p->ni_fport, 503 p->ni_proto); 504 break; 505 #ifdef INET6 506 case AF_INET6: 507 inet6print(&p->ni_faddr6, p->ni_fport, 508 p->ni_proto); 509 break; 510 #endif 511 } 512 p->ni_flags &= ~NIF_FACHG; 513 } 514 mvwaddstr(wnd, p->ni_line, PROTO, p->ni_proto); 515 #ifdef INET6 516 if (p->ni_family == AF_INET6) 517 waddstr(wnd, "6"); 518 #endif 519 mvwprintw(wnd, p->ni_line, RCVCC, "%6d", p->ni_rcvcc); 520 mvwprintw(wnd, p->ni_line, SNDCC, "%6d", p->ni_sndcc); 521 if (streq(p->ni_proto, "tcp")) { 522 if (p->ni_state < 0 || p->ni_state >= TCP_NSTATES) 523 mvwprintw(wnd, p->ni_line, STATE, "%d", 524 p->ni_state); 525 else 526 mvwaddstr(wnd, p->ni_line, STATE, 527 tcpstates[p->ni_state]); 528 } 529 wclrtoeol(wnd); 530 } 531 if (lastrow < getmaxy(wnd)) { 532 wmove(wnd, lastrow, 0); wclrtobot(wnd); 533 wmove(wnd, getmaxy(wnd), 0); wdeleteln(wnd); /* XXX */ 534 } 535 } 536 537 /* 538 * Pretty print an Internet address (net address + port). 539 * If the nflag was specified, use numbers instead of names. 540 */ 541 static void 542 inetprint(in, port, proto) 543 struct in_addr *in; 544 int port; 545 char *proto; 546 { 547 struct servent *sp = 0; 548 char line[80], *cp; 549 550 (void)snprintf(line, sizeof line, "%.*s.", 16, inetname(*in)); 551 cp = strchr(line, '\0'); 552 if (!nflag && port) 553 sp = getservbyport(port, proto); 554 if (sp || port == 0) 555 (void)snprintf(cp, line + sizeof line - cp, "%.8s", 556 sp ? sp->s_name : "*"); 557 else 558 (void)snprintf(cp, line + sizeof line - cp, "%d", 559 ntohs((u_short)port)); 560 /* pad to full column to clear any garbage */ 561 cp = strchr(line, '\0'); 562 while (cp - line < 22) 563 *cp++ = ' '; 564 *cp = '\0'; 565 waddstr(wnd, line); 566 } 567 568 #ifdef INET6 569 static void 570 inet6print(in6, port, proto) 571 struct in6_addr *in6; 572 int port; 573 char *proto; 574 { 575 struct servent *sp = 0; 576 char line[80], *cp; 577 578 (void)snprintf(line, sizeof line, "%.*s.", 16, inet6name(in6)); 579 cp = strchr(line, '\0'); 580 if (!nflag && port) 581 sp = getservbyport(port, proto); 582 if (sp || port == 0) 583 (void)snprintf(cp, line + sizeof line - cp, "%.8s", 584 sp ? sp->s_name : "*"); 585 else 586 (void)snprintf(cp, line + sizeof line - cp, "%d", 587 ntohs((u_short)port)); 588 /* pad to full column to clear any garbage */ 589 cp = strchr(line, '\0'); 590 while (cp - line < 22) 591 *cp++ = ' '; 592 *cp = '\0'; 593 waddstr(wnd, line); 594 } 595 #endif 596 597 /* 598 * Construct an Internet address representation. 599 * If the nflag has been supplied, give 600 * numeric value, otherwise try for symbolic name. 601 */ 602 static const char * 603 inetname(in) 604 struct in_addr in; 605 { 606 char *cp = 0; 607 static char line[50]; 608 struct hostent *hp; 609 struct netent *np; 610 611 if (!nflag && in.s_addr != INADDR_ANY) { 612 int net = inet_netof(in); 613 int lna = inet_lnaof(in); 614 615 if (lna == INADDR_ANY) { 616 np = getnetbyaddr(net, AF_INET); 617 if (np) 618 cp = np->n_name; 619 } 620 if (cp == 0) { 621 hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); 622 if (hp) 623 cp = hp->h_name; 624 } 625 } 626 if (in.s_addr == INADDR_ANY) 627 strncpy(line, "*", sizeof(line) - 1); 628 else if (cp) 629 strncpy(line, cp, sizeof(line) - 1); 630 else { 631 in.s_addr = ntohl(in.s_addr); 632 #define C(x) ((x) & 0xff) 633 (void)snprintf(line, sizeof line, "%u.%u.%u.%u", 634 C(in.s_addr >> 24), C(in.s_addr >> 16), 635 C(in.s_addr >> 8), C(in.s_addr)); 636 #undef C 637 } 638 line[sizeof(line) - 1] = '\0'; 639 return (line); 640 } 641 642 #ifdef INET6 643 static const char * 644 inet6name(in6) 645 struct in6_addr *in6; 646 { 647 static char line[NI_MAXHOST]; 648 struct sockaddr_in6 sin6; 649 int flags; 650 651 if (nflag) 652 flags = NI_NUMERICHOST; 653 else 654 flags = 0; 655 if (IN6_IS_ADDR_UNSPECIFIED(in6)) 656 return "*"; 657 memset(&sin6, 0, sizeof(sin6)); 658 sin6.sin6_family = AF_INET6; 659 sin6.sin6_len = sizeof(struct sockaddr_in6); 660 sin6.sin6_addr = *in6; 661 if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 662 line, sizeof(line), NULL, 0, flags) == 0) 663 return line; 664 return "?"; 665 } 666 #endif 667 668 /* please note: there are also some netstat commands in netcmds.c */ 669 670 void 671 netstat_all (args) 672 char *args; 673 { 674 aflag = !aflag; 675 fetchnetstat(); 676 shownetstat(); 677 refresh(); 678 } 679 680 void 681 netstat_names (args) 682 char *args; 683 { 684 struct netinfo *p; 685 686 if (nflag == 0) 687 return; 688 689 p = netcb.ni_forw; 690 for (; p != (struct netinfo *)&netcb; p = p->ni_forw) { 691 if (p->ni_line == -1) 692 continue; 693 p->ni_flags |= NIF_LACHG|NIF_FACHG; 694 } 695 nflag = 0; 696 wclear(wnd); 697 labelnetstat(); 698 shownetstat(); 699 refresh(); 700 } 701 702 void 703 netstat_numbers (args) 704 char *args; 705 { 706 struct netinfo *p; 707 708 if (nflag != 0) 709 return; 710 711 p = netcb.ni_forw; 712 for (; p != (struct netinfo *)&netcb; p = p->ni_forw) { 713 if (p->ni_line == -1) 714 continue; 715 p->ni_flags |= NIF_LACHG|NIF_FACHG; 716 } 717 nflag = 1; 718 wclear(wnd); 719 labelnetstat(); 720 shownetstat(); 721 refresh(); 722 } 723