netstat.c revision 74671
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1980, 1992, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3519234Swollman/* 361590Srgrimesstatic char sccsid[] = "@(#)netstat.c 8.1 (Berkeley) 6/6/93"; 3719234Swollman*/ 3819234Swollmanstatic const char rcsid[] = 3950477Speter "$FreeBSD: head/usr.bin/systat/netstat.c 74671 2001-03-23 03:58:25Z tmm $"; 401590Srgrimes#endif /* not lint */ 411590Srgrimes 421590Srgrimes/* 431590Srgrimes * netstat 441590Srgrimes */ 451590Srgrimes#include <sys/param.h> 4614543Sdg#include <sys/queue.h> 471590Srgrimes#include <sys/socket.h> 481590Srgrimes#include <sys/socketvar.h> 491590Srgrimes#include <sys/protosw.h> 501590Srgrimes 511590Srgrimes#include <netinet/in.h> 5236916Speter#include <arpa/inet.h> 531590Srgrimes#include <net/route.h> 541590Srgrimes#include <netinet/in_systm.h> 551590Srgrimes#include <netinet/ip.h> 561590Srgrimes#include <netinet/in_pcb.h> 571590Srgrimes#include <netinet/ip_icmp.h> 581590Srgrimes#include <netinet/icmp_var.h> 591590Srgrimes#include <netinet/ip_var.h> 601590Srgrimes#include <netinet/tcp.h> 611590Srgrimes#include <netinet/tcpip.h> 621590Srgrimes#include <netinet/tcp_seq.h> 6374671Stmm#include <netinet/tcp_var.h> 641590Srgrimes#define TCPSTATES 651590Srgrimes#include <netinet/tcp_fsm.h> 661590Srgrimes#include <netinet/tcp_timer.h> 671590Srgrimes#include <netinet/tcp_var.h> 681590Srgrimes#include <netinet/tcp_debug.h> 691590Srgrimes#include <netinet/udp.h> 701590Srgrimes#include <netinet/udp_var.h> 711590Srgrimes 721590Srgrimes#include <netdb.h> 731590Srgrimes#include <stdlib.h> 741590Srgrimes#include <string.h> 751590Srgrimes#include <nlist.h> 761590Srgrimes#include <paths.h> 771590Srgrimes#include "systat.h" 781590Srgrimes#include "extern.h" 791590Srgrimes 8074671Stmmstatic struct netinfo *enter __P((struct inpcb *, int, char *)); 8174671Stmmstatic void enter_kvm __P((struct inpcb *, struct socket *, int, char *)); 8274671Stmmstatic void enter_sysctl __P((struct inpcb *, struct xsocket *, int, char *)); 8374671Stmmstatic void fetchnetstat_kvm __P((void)); 8474671Stmmstatic void fetchnetstat_sysctl __P((void)); 851590Srgrimesstatic char *inetname __P((struct in_addr)); 861590Srgrimesstatic void inetprint __P((struct in_addr *, int, char *)); 871590Srgrimes 881590Srgrimes#define streq(a,b) (strcmp(a,b)==0) 8950635Speter#define YMAX(w) ((w)->_maxy-1) 901590Srgrimes 911590SrgrimesWINDOW * 921590Srgrimesopennetstat() 931590Srgrimes{ 941590Srgrimes sethostent(1); 951590Srgrimes setnetent(1); 961590Srgrimes return (subwin(stdscr, LINES-5-1, 0, 5, 0)); 971590Srgrimes} 981590Srgrimes 991590Srgrimesstruct netinfo { 10070523Sphk TAILQ_ENTRY(netinfo) chain; 1011590Srgrimes short ni_line; /* line on screen */ 1021590Srgrimes short ni_seen; /* 0 when not present in list */ 1031590Srgrimes short ni_flags; 1041590Srgrimes#define NIF_LACHG 0x1 /* local address changed */ 1051590Srgrimes#define NIF_FACHG 0x2 /* foreign address changed */ 1061590Srgrimes short ni_state; /* tcp state */ 1071590Srgrimes char *ni_proto; /* protocol */ 1081590Srgrimes struct in_addr ni_laddr; /* local address */ 1091590Srgrimes long ni_lport; /* local port */ 1101590Srgrimes struct in_addr ni_faddr; /* foreign address */ 1111590Srgrimes long ni_fport; /* foreign port */ 1121590Srgrimes long ni_rcvcc; /* rcv buffer character count */ 1131590Srgrimes long ni_sndcc; /* snd buffer character count */ 1141590Srgrimes}; 1151590Srgrimes 11670523SphkTAILQ_HEAD(netinfohead, netinfo) netcb = TAILQ_HEAD_INITIALIZER(netcb); 1171590Srgrimes 1181590Srgrimesstatic int aflag = 0; 1191590Srgrimesstatic int nflag = 0; 1201590Srgrimesstatic int lastrow = 1; 1211590Srgrimesstatic char *inetname(); 1221590Srgrimes 1231590Srgrimesvoid 1241590Srgrimesclosenetstat(w) 1251590Srgrimes WINDOW *w; 1261590Srgrimes{ 1271590Srgrimes register struct netinfo *p; 1281590Srgrimes 1291590Srgrimes endhostent(); 1301590Srgrimes endnetent(); 13170526Sphk TAILQ_FOREACH(p, &netcb, chain) { 1321590Srgrimes if (p->ni_line != -1) 1331590Srgrimes lastrow--; 1341590Srgrimes p->ni_line = -1; 1351590Srgrimes } 1361590Srgrimes if (w != NULL) { 1371590Srgrimes wclear(w); 1381590Srgrimes wrefresh(w); 1391590Srgrimes delwin(w); 1401590Srgrimes } 1411590Srgrimes} 1421590Srgrimes 14374671Stmmstatic char *miblist[] = { 14474671Stmm "net.inet.tcp.pcblist", 14574671Stmm "net.inet.udp.pcblist" 14674671Stmm}; 14774671Stmm 14874671Stmmstruct nlist namelist[] = { 1491590Srgrimes#define X_TCB 0 15074671Stmm { "tcb" }, 1511590Srgrimes#define X_UDB 1 15274671Stmm { "udb" }, 1531590Srgrimes { "" }, 1541590Srgrimes}; 1551590Srgrimes 1561590Srgrimesint 1571590Srgrimesinitnetstat() 1581590Srgrimes{ 1591590Srgrimes protos = TCP|UDP; 1601590Srgrimes return(1); 1611590Srgrimes} 1621590Srgrimes 1631590Srgrimesvoid 1641590Srgrimesfetchnetstat() 1651590Srgrimes{ 16674671Stmm if (use_kvm) 16774671Stmm fetchnetstat_kvm(); 16874671Stmm else 16974671Stmm fetchnetstat_sysctl(); 17074671Stmm} 17174671Stmm 17274671Stmmstatic void 17374671Stmmfetchnetstat_kvm() 17474671Stmm{ 17540060Sobrien register struct inpcb *next; 1761590Srgrimes register struct netinfo *p; 1777715Sdg struct inpcbhead head; 1781590Srgrimes struct inpcb inpcb; 1791590Srgrimes struct socket sockb; 1801590Srgrimes struct tcpcb tcpcb; 1811590Srgrimes void *off; 1821590Srgrimes int istcp; 1831590Srgrimes 1841590Srgrimes if (namelist[X_TCB].n_value == 0) 1851590Srgrimes return; 18670523Sphk TAILQ_FOREACH(p, &netcb, chain) 1871590Srgrimes p->ni_seen = 0; 1881590Srgrimes if (protos&TCP) { 1898874Srgrimes off = NPTR(X_TCB); 1901590Srgrimes istcp = 1; 1911590Srgrimes } 1921590Srgrimes else if (protos&UDP) { 1938874Srgrimes off = NPTR(X_UDB); 1941590Srgrimes istcp = 0; 1951590Srgrimes } 1961590Srgrimes else { 1971590Srgrimes error("No protocols to display"); 1981590Srgrimes return; 1991590Srgrimes } 2001590Srgrimesagain: 2017715Sdg KREAD(off, &head, sizeof (struct inpcbhead)); 20270523Sphk LIST_FOREACH(next, &head, inp_list) { 2031590Srgrimes KREAD(next, &inpcb, sizeof (inpcb)); 20470526Sphk next = &inpcb; 2051590Srgrimes if (!aflag && inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) 2061590Srgrimes continue; 2071590Srgrimes if (nhosts && !checkhost(&inpcb)) 2081590Srgrimes continue; 2091590Srgrimes if (nports && !checkport(&inpcb)) 2101590Srgrimes continue; 2111590Srgrimes KREAD(inpcb.inp_socket, &sockb, sizeof (sockb)); 2121590Srgrimes if (istcp) { 2131590Srgrimes KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb)); 21474671Stmm enter_kvm(&inpcb, &sockb, tcpcb.t_state, "tcp"); 2151590Srgrimes } else 21674671Stmm enter_kvm(&inpcb, &sockb, 0, "udp"); 2171590Srgrimes } 2181590Srgrimes if (istcp && (protos&UDP)) { 2191590Srgrimes istcp = 0; 2201590Srgrimes off = NPTR(X_UDB); 2211590Srgrimes goto again; 2221590Srgrimes } 2231590Srgrimes} 2241590Srgrimes 2251590Srgrimesstatic void 22674671Stmmfetchnetstat_sysctl() 22774671Stmm{ 22874671Stmm register struct netinfo *p; 22974671Stmm int idx; 23074671Stmm struct xinpgen *inpg; 23174671Stmm char *cur, *end; 23274671Stmm struct inpcb *inpcb; 23374671Stmm struct xinpcb *xip; 23474671Stmm struct xtcpcb *xtp; 23574671Stmm int plen; 23674671Stmm size_t lsz; 23774671Stmm 23874671Stmm TAILQ_FOREACH(p, &netcb, chain) 23974671Stmm p->ni_seen = 0; 24074671Stmm if (protos&TCP) { 24174671Stmm idx = 0; 24274671Stmm } else if (protos&UDP) { 24374671Stmm idx = 1; 24474671Stmm } else { 24574671Stmm error("No protocols to display"); 24674671Stmm return; 24774671Stmm } 24874671Stmm 24974671Stmm for (;idx < 2; idx++) { 25074671Stmm if (idx == 1 && !(protos&UDP)) 25174671Stmm break; 25274671Stmm inpg = (struct xinpgen *)sysctl_dynread(miblist[idx], &lsz); 25374671Stmm if (inpg == NULL) { 25474671Stmm error("sysctl(%s...) failed", miblist[idx]); 25574671Stmm continue; 25674671Stmm } 25774671Stmm /* 25874671Stmm * We currently do no require a consistent pcb list. 25974671Stmm * Try to be robust in case of struct size changes 26074671Stmm */ 26174671Stmm cur = ((char *)inpg) + inpg->xig_len; 26274671Stmm /* There is also a trailing struct xinpgen */ 26374671Stmm end = ((char *)inpg) + lsz - inpg->xig_len; 26474671Stmm if (end <= cur) { 26574671Stmm free(inpg); 26674671Stmm continue; 26774671Stmm } 26874671Stmm if (idx == 0) { /* TCP */ 26974671Stmm xtp = (struct xtcpcb *)cur; 27074671Stmm plen = xtp->xt_len; 27174671Stmm } else { 27274671Stmm xip = (struct xinpcb *)cur; 27374671Stmm plen = xip->xi_len; 27474671Stmm } 27574671Stmm while (cur + plen <= end) { 27674671Stmm if (idx == 0) { /* TCP */ 27774671Stmm xtp = (struct xtcpcb *)cur; 27874671Stmm inpcb = &xtp->xt_inp; 27974671Stmm } else { 28074671Stmm xip = (struct xinpcb *)cur; 28174671Stmm inpcb = &xip->xi_inp; 28274671Stmm } 28374671Stmm cur += plen; 28474671Stmm 28574671Stmm if (!aflag && inet_lnaof(inpcb->inp_laddr) == 28674671Stmm INADDR_ANY) 28774671Stmm continue; 28874671Stmm if (nhosts && !checkhost(inpcb)) 28974671Stmm continue; 29074671Stmm if (nports && !checkport(inpcb)) 29174671Stmm continue; 29274671Stmm if (idx == 0) /* TCP */ 29374671Stmm enter_sysctl(inpcb, &xtp->xt_socket, 29474671Stmm xtp->xt_tp.t_state, "tcp"); 29574671Stmm else /* UDP */ 29674671Stmm enter_sysctl(inpcb, &xip->xi_socket, 0, "udp"); 29774671Stmm } 29874671Stmm free(inpg); 29974671Stmm } 30074671Stmm} 30174671Stmm 30274671Stmmstatic void 30374671Stmmenter_kvm(inp, so, state, proto) 3041590Srgrimes register struct inpcb *inp; 3051590Srgrimes register struct socket *so; 3061590Srgrimes int state; 3071590Srgrimes char *proto; 3081590Srgrimes{ 3091590Srgrimes register struct netinfo *p; 3101590Srgrimes 31174671Stmm if ((p = enter(inp, state, proto)) != NULL) { 31274671Stmm p->ni_rcvcc = so->so_rcv.sb_cc; 31374671Stmm p->ni_sndcc = so->so_snd.sb_cc; 31474671Stmm } 31574671Stmm} 31674671Stmm 31774671Stmmstatic void 31874671Stmmenter_sysctl(inp, so, state, proto) 31974671Stmm register struct inpcb *inp; 32074671Stmm register struct xsocket *so; 32174671Stmm int state; 32274671Stmm char *proto; 32374671Stmm{ 32474671Stmm register struct netinfo *p; 32574671Stmm 32674671Stmm if ((p = enter(inp, state, proto)) != NULL) { 32774671Stmm p->ni_rcvcc = so->so_rcv.sb_cc; 32874671Stmm p->ni_sndcc = so->so_snd.sb_cc; 32974671Stmm } 33074671Stmm} 33174671Stmm 33274671Stmm 33374671Stmmstatic struct netinfo * 33474671Stmmenter(inp, state, proto) 33574671Stmm register struct inpcb *inp; 33674671Stmm int state; 33774671Stmm char *proto; 33874671Stmm{ 33974671Stmm register struct netinfo *p; 34074671Stmm 3411590Srgrimes /* 3421590Srgrimes * Only take exact matches, any sockets with 3431590Srgrimes * previously unbound addresses will be deleted 3441590Srgrimes * below in the display routine because they 3451590Srgrimes * will appear as ``not seen'' in the kernel 3461590Srgrimes * data structures. 3471590Srgrimes */ 34870523Sphk TAILQ_FOREACH(p, &netcb, chain) { 3491590Srgrimes if (!streq(proto, p->ni_proto)) 3501590Srgrimes continue; 3511590Srgrimes if (p->ni_lport != inp->inp_lport || 3521590Srgrimes p->ni_laddr.s_addr != inp->inp_laddr.s_addr) 3531590Srgrimes continue; 3541590Srgrimes if (p->ni_faddr.s_addr == inp->inp_faddr.s_addr && 3551590Srgrimes p->ni_fport == inp->inp_fport) 3561590Srgrimes break; 3571590Srgrimes } 35870523Sphk if (p == NULL) { 3591590Srgrimes if ((p = malloc(sizeof(*p))) == NULL) { 3601590Srgrimes error("Out of memory"); 36174671Stmm return NULL; 3621590Srgrimes } 36370523Sphk TAILQ_INSERT_HEAD(&netcb, p, chain); 3641590Srgrimes p->ni_line = -1; 3651590Srgrimes p->ni_laddr = inp->inp_laddr; 3661590Srgrimes p->ni_lport = inp->inp_lport; 3671590Srgrimes p->ni_faddr = inp->inp_faddr; 3681590Srgrimes p->ni_fport = inp->inp_fport; 3691590Srgrimes p->ni_proto = proto; 3701590Srgrimes p->ni_flags = NIF_LACHG|NIF_FACHG; 3711590Srgrimes } 3721590Srgrimes p->ni_state = state; 3731590Srgrimes p->ni_seen = 1; 37474671Stmm return p; 3751590Srgrimes} 3761590Srgrimes 3771590Srgrimes/* column locations */ 3781590Srgrimes#define LADDR 0 3791590Srgrimes#define FADDR LADDR+23 3801590Srgrimes#define PROTO FADDR+23 3811590Srgrimes#define RCVCC PROTO+6 3821590Srgrimes#define SNDCC RCVCC+7 3831590Srgrimes#define STATE SNDCC+7 3841590Srgrimes 3851590Srgrimes 3861590Srgrimesvoid 3871590Srgrimeslabelnetstat() 3881590Srgrimes{ 38974671Stmm if (use_kvm && namelist[X_TCB].n_type == 0) 3901590Srgrimes return; 3911590Srgrimes wmove(wnd, 0, 0); wclrtobot(wnd); 3921590Srgrimes mvwaddstr(wnd, 0, LADDR, "Local Address"); 3931590Srgrimes mvwaddstr(wnd, 0, FADDR, "Foreign Address"); 3941590Srgrimes mvwaddstr(wnd, 0, PROTO, "Proto"); 3951590Srgrimes mvwaddstr(wnd, 0, RCVCC, "Recv-Q"); 3961590Srgrimes mvwaddstr(wnd, 0, SNDCC, "Send-Q"); 3978874Srgrimes mvwaddstr(wnd, 0, STATE, "(state)"); 3981590Srgrimes} 3991590Srgrimes 4001590Srgrimesvoid 4011590Srgrimesshownetstat() 4021590Srgrimes{ 4031590Srgrimes register struct netinfo *p, *q; 4041590Srgrimes 4051590Srgrimes /* 4061590Srgrimes * First, delete any connections that have gone 4071590Srgrimes * away and adjust the position of connections 4081590Srgrimes * below to reflect the deleted line. 4091590Srgrimes */ 41074671Stmm p = TAILQ_FIRST(&netcb); 41174671Stmm while (p != NULL) { 41274671Stmm if (p->ni_line == -1 || p->ni_seen) { 41374671Stmm p = TAILQ_NEXT(p, chain); 4141590Srgrimes continue; 41574671Stmm } 4161590Srgrimes wmove(wnd, p->ni_line, 0); wdeleteln(wnd); 41770523Sphk TAILQ_FOREACH(q, &netcb, chain) 4181590Srgrimes if (q != p && q->ni_line > p->ni_line) { 4191590Srgrimes q->ni_line--; 4201590Srgrimes /* this shouldn't be necessary */ 4211590Srgrimes q->ni_flags |= NIF_LACHG|NIF_FACHG; 4221590Srgrimes } 4231590Srgrimes lastrow--; 42474671Stmm q = TAILQ_NEXT(p, chain); 42570523Sphk TAILQ_REMOVE(&netcb, p, chain); 4261590Srgrimes free(p); 4271590Srgrimes p = q; 4281590Srgrimes } 4291590Srgrimes /* 4301590Srgrimes * Update existing connections and add new ones. 4311590Srgrimes */ 43270523Sphk TAILQ_FOREACH(p, &netcb, chain) { 4331590Srgrimes if (p->ni_line == -1) { 4341590Srgrimes /* 4351590Srgrimes * Add a new entry if possible. 4361590Srgrimes */ 4371590Srgrimes if (lastrow > YMAX(wnd)) 4381590Srgrimes continue; 4391590Srgrimes p->ni_line = lastrow++; 4401590Srgrimes p->ni_flags |= NIF_LACHG|NIF_FACHG; 4411590Srgrimes } 4421590Srgrimes if (p->ni_flags & NIF_LACHG) { 4431590Srgrimes wmove(wnd, p->ni_line, LADDR); 4441590Srgrimes inetprint(&p->ni_laddr, p->ni_lport, p->ni_proto); 4451590Srgrimes p->ni_flags &= ~NIF_LACHG; 4461590Srgrimes } 4471590Srgrimes if (p->ni_flags & NIF_FACHG) { 4481590Srgrimes wmove(wnd, p->ni_line, FADDR); 4491590Srgrimes inetprint(&p->ni_faddr, p->ni_fport, p->ni_proto); 4501590Srgrimes p->ni_flags &= ~NIF_FACHG; 4511590Srgrimes } 4521590Srgrimes mvwaddstr(wnd, p->ni_line, PROTO, p->ni_proto); 4531590Srgrimes mvwprintw(wnd, p->ni_line, RCVCC, "%6d", p->ni_rcvcc); 4541590Srgrimes mvwprintw(wnd, p->ni_line, SNDCC, "%6d", p->ni_sndcc); 4551590Srgrimes if (streq(p->ni_proto, "tcp")) 4561590Srgrimes if (p->ni_state < 0 || p->ni_state >= TCP_NSTATES) 4571590Srgrimes mvwprintw(wnd, p->ni_line, STATE, "%d", 4581590Srgrimes p->ni_state); 4591590Srgrimes else 4601590Srgrimes mvwaddstr(wnd, p->ni_line, STATE, 4611590Srgrimes tcpstates[p->ni_state]); 4621590Srgrimes wclrtoeol(wnd); 4631590Srgrimes } 4641590Srgrimes if (lastrow < YMAX(wnd)) { 4651590Srgrimes wmove(wnd, lastrow, 0); wclrtobot(wnd); 4661590Srgrimes wmove(wnd, YMAX(wnd), 0); wdeleteln(wnd); /* XXX */ 4671590Srgrimes } 4681590Srgrimes} 4691590Srgrimes 4701590Srgrimes/* 4711590Srgrimes * Pretty print an Internet address (net address + port). 4721590Srgrimes * If the nflag was specified, use numbers instead of names. 4731590Srgrimes */ 4741590Srgrimesstatic void 4751590Srgrimesinetprint(in, port, proto) 4761590Srgrimes register struct in_addr *in; 4771590Srgrimes int port; 4781590Srgrimes char *proto; 4791590Srgrimes{ 4801590Srgrimes struct servent *sp = 0; 4811590Srgrimes char line[80], *cp, *index(); 4821590Srgrimes 48336789Simp snprintf(line, sizeof(line), "%.*s.", 16, inetname(*in)); 4841590Srgrimes cp = index(line, '\0'); 4851590Srgrimes if (!nflag && port) 4861590Srgrimes sp = getservbyport(port, proto); 4871590Srgrimes if (sp || port == 0) 48836789Simp snprintf(cp, sizeof(line) - (cp - line), "%.8s", 48936789Simp sp ? sp->s_name : "*"); 4901590Srgrimes else 49136789Simp snprintf(cp, sizeof(line) - (cp - line), "%d", 49236789Simp ntohs((u_short)port)); 4931590Srgrimes /* pad to full column to clear any garbage */ 4941590Srgrimes cp = index(line, '\0'); 4951590Srgrimes while (cp - line < 22) 4961590Srgrimes *cp++ = ' '; 49719330Sphk line[22] = '\0'; 4981590Srgrimes waddstr(wnd, line); 4991590Srgrimes} 5001590Srgrimes 5011590Srgrimes/* 5021590Srgrimes * Construct an Internet address representation. 5038874Srgrimes * If the nflag has been supplied, give 5041590Srgrimes * numeric value, otherwise try for symbolic name. 5051590Srgrimes */ 5061590Srgrimesstatic char * 5071590Srgrimesinetname(in) 5081590Srgrimes struct in_addr in; 5091590Srgrimes{ 5101590Srgrimes char *cp = 0; 5111590Srgrimes static char line[50]; 5121590Srgrimes struct hostent *hp; 5131590Srgrimes struct netent *np; 5141590Srgrimes 5151590Srgrimes if (!nflag && in.s_addr != INADDR_ANY) { 5161590Srgrimes int net = inet_netof(in); 5171590Srgrimes int lna = inet_lnaof(in); 5181590Srgrimes 5191590Srgrimes if (lna == INADDR_ANY) { 5201590Srgrimes np = getnetbyaddr(net, AF_INET); 5211590Srgrimes if (np) 5221590Srgrimes cp = np->n_name; 5231590Srgrimes } 5241590Srgrimes if (cp == 0) { 5251590Srgrimes hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); 5261590Srgrimes if (hp) 5271590Srgrimes cp = hp->h_name; 5281590Srgrimes } 5291590Srgrimes } 5301590Srgrimes if (in.s_addr == INADDR_ANY) 5311590Srgrimes strcpy(line, "*"); 5321590Srgrimes else if (cp) 53336789Simp snprintf(line, sizeof(line), "%s", cp); 5341590Srgrimes else { 5351590Srgrimes in.s_addr = ntohl(in.s_addr); 5361590Srgrimes#define C(x) ((x) & 0xff) 53736789Simp snprintf(line, sizeof(line), "%u.%u.%u.%u", C(in.s_addr >> 24), 5381590Srgrimes C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); 5391590Srgrimes } 5401590Srgrimes return (line); 5411590Srgrimes} 5421590Srgrimes 5431590Srgrimesint 5441590Srgrimescmdnetstat(cmd, args) 5451590Srgrimes char *cmd, *args; 5461590Srgrimes{ 5471590Srgrimes if (prefix(cmd, "all")) { 5481590Srgrimes aflag = !aflag; 5491590Srgrimes goto fixup; 5501590Srgrimes } 5511590Srgrimes if (prefix(cmd, "numbers") || prefix(cmd, "names")) { 55270523Sphk struct netinfo *p; 5531590Srgrimes int new; 5541590Srgrimes 5551590Srgrimes new = prefix(cmd, "numbers"); 5561590Srgrimes if (new == nflag) 5571590Srgrimes return (1); 55870523Sphk TAILQ_FOREACH(p, &netcb, chain) { 5591590Srgrimes if (p->ni_line == -1) 5601590Srgrimes continue; 5611590Srgrimes p->ni_flags |= NIF_LACHG|NIF_FACHG; 5621590Srgrimes } 5631590Srgrimes nflag = new; 5641590Srgrimes goto redisplay; 5651590Srgrimes } 5661590Srgrimes if (!netcmd(cmd, args)) 5671590Srgrimes return (0); 5681590Srgrimesfixup: 5691590Srgrimes fetchnetstat(); 5701590Srgrimesredisplay: 5711590Srgrimes shownetstat(); 5721590Srgrimes refresh(); 5731590Srgrimes return (1); 5741590Srgrimes} 575