[BACK]Return to netstat.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / systat

Diff for /src/usr.bin/systat/netstat.c between version 1.30 and 1.31

version 1.30, 2007/02/25 18:21:24 version 1.31, 2008/06/12 22:26:01
Line 30 
Line 30 
  * SUCH DAMAGE.   * SUCH DAMAGE.
  */   */
   
 #ifndef lint  
 #if 0  
 static char sccsid[] = "@(#)netstat.c   8.1 (Berkeley) 6/6/93";  
 #endif  
 static char rcsid[] = "$OpenBSD$";  
 #endif /* not lint */  
   
 /*  /*
  * netstat   * netstat
  */   */
Line 73 
Line 66 
 #include <nlist.h>  #include <nlist.h>
 #include <paths.h>  #include <paths.h>
 #include "systat.h"  #include "systat.h"
 #include "extern.h"  #include "engine.h"
   
   struct netinfo {
           union {
                   struct  in_addr nif_laddr;      /* local address */
                   struct  in6_addr nif_laddr6;    /* local address */
           } l;
           union {
                   struct  in_addr nif_faddr;      /* foreign address */
                   struct  in6_addr nif_faddr6;    /* foreign address */
           } f;
           char    *nif_proto;             /* protocol */
           long    nif_rcvcc;              /* rcv buffer character count */
           long    nif_sndcc;              /* snd buffer character count */
           short   nif_lport;              /* local port */
           short   nif_fport;              /* foreign port */
           short   nif_state;              /* tcp state */
           short   nif_family;
   };
   
   #define nif_laddr  l.nif_laddr
   #define nif_laddr6 l.nif_laddr6
   #define nif_faddr  f.nif_faddr
   #define nif_faddr6 f.nif_faddr6
   
 static void enter(struct inpcb *, struct socket *, int, char *);  static void enter(struct inpcb *, struct socket *, int, char *);
 static const char *inetname(struct in_addr);  static const char *inetname(struct in_addr);
 static void inetprint(struct in_addr *, int, char *);  static void inetprint(struct in_addr *, int, char *, field_def *);
 static const char *inet6name(struct in6_addr *);  static const char *inet6name(struct in6_addr *);
 static void inet6print(struct in6_addr *, int, char *);  static void inet6print(struct in6_addr *, int, char *, field_def *);
   static void shownetstat(struct netinfo *p);
   
   void print_ns(void);
   int read_ns(void);
   int select_ns(void);
   int ns_keyboard_callback(int);
   
 #define streq(a,b)      (strcmp(a,b)==0)  #define streq(a,b)      (strcmp(a,b)==0)
 #define YMAX(w)         ((w)->_maxy-1)  
   
 WINDOW *  static  int aflag = 0;
 opennetstat(void)  
 {  
         sethostent(1);  
         setnetent(1);  
         return (subwin(stdscr, LINES-1-2, 0, 2, 0));  
 }  
   
 struct netinfo {  static struct nlist namelist[] = {
         struct  netinfo *nif_forw, *nif_prev;  #define X_TCBTABLE      0               /* no sysctl */
         int     nif_family;          { "_tcbtable" },
         short   nif_line;               /* line on screen */  #define X_UDBTABLE      1               /* no sysctl */
         short   nif_seen;               /* 0 when not present in list */          { "_udbtable" },
         short   nif_flags;          { "" },
 #define NIF_LACHG       0x1             /* local address changed */  
 #define NIF_FACHG       0x2             /* foreign address changed */  
         short   nif_state;              /* tcp state */  
         char    *nif_proto;             /* protocol */  
         struct  in_addr nif_laddr;      /* local address */  
         struct  in6_addr nif_laddr6;    /* local address */  
         long    nif_lport;              /* local port */  
         struct  in_addr nif_faddr;      /* foreign address */  
         struct  in6_addr nif_faddr6;    /* foreign address */  
         long    nif_fport;              /* foreign port */  
         long    nif_rcvcc;              /* rcv buffer character count */  
         long    nif_sndcc;              /* snd buffer character count */  
 };  };
   #define ADD_ALLOC  1000
   
 static struct {  
         struct  netinfo *nif_forw, *nif_prev;  
 } netcb;  
   
 static  int aflag = 0;  int protos;
 static  int lastrow = 1;  
   
 void  struct netinfo *netinfos = NULL;
 closenetstat(WINDOW *w)  size_t num_ns = 0;
   static size_t num_alloc = 0;
   
   
   field_def fields_ns[] = {
           {"LOCAL ADDRESS", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
           {"FOREIGN ADDRESS", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
           {"PROTO", 4, 9, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
           {"RECV-Q", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
           {"SEND-Q", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
           {"STATE", 5, 11, 6, FLD_ALIGN_LEFT, -1, 0, 0, 0},
   };
   
   #define FIELD_ADDR(x) (&fields_ns[x])
   
   #define FLD_NS_LOCAL    FIELD_ADDR(0)
   #define FLD_NS_FOREIGN  FIELD_ADDR(1)
   #define FLD_NS_PROTO    FIELD_ADDR(2)
   #define FLD_NS_RECV_Q   FIELD_ADDR(3)
   #define FLD_NS_SEND_Q   FIELD_ADDR(4)
   #define FLD_NS_STATE    FIELD_ADDR(5)
   
   /* Define views */
   field_def *view_ns_0[] = {
           FLD_NS_LOCAL, FLD_NS_FOREIGN, FLD_NS_PROTO,
           FLD_NS_RECV_Q, FLD_NS_SEND_Q, FLD_NS_STATE, NULL
   };
   
   /* Define view managers */
   struct view_manager netstat_mgr = {
           "Netstat", select_ns, read_ns, NULL, print_header,
           print_ns, ns_keyboard_callback, NULL, NULL
   };
   
   field_view views_ns[] = {
           {view_ns_0, "netstat", '0', &netstat_mgr},
           {NULL, NULL, 0, NULL}
   };
   
   
   
   
   struct netinfo *
   next_ns(void)
 {  {
           if (num_alloc <= num_ns) {
                   struct netinfo *ni;
                   size_t a = num_alloc + ADD_ALLOC;
                   if (a < num_alloc)
                           return NULL;
                   ni = realloc(netinfos, a * sizeof(*ni));
                   if (ni == NULL)
                           return NULL;
                   netinfos = ni;
                   num_alloc = a;
           }
   
           return &netinfos[num_ns++];
   }
   
   static void
   enter(struct inpcb *inp, struct socket *so, int state, char *proto)
   {
         struct netinfo *p;          struct netinfo *p;
   
         endhostent();          p = next_ns();
         endnetent();          if (p == NULL) {
         p = (struct netinfo *)netcb.nif_forw;                  error("Out of Memory!");
         while (p != (struct netinfo *)&netcb) {                  return;
                 if (p->nif_line != -1)  
                         lastrow--;  
                 p->nif_line = -1;  
                 p = p->nif_forw;  
         }          }
         if (w != NULL) {  
                 wclear(w);          p->nif_lport = inp->inp_lport;
                 wrefresh(w);          p->nif_fport = inp->inp_fport;
                 delwin(w);          p->nif_proto = proto;
   
           if (inp->inp_flags & INP_IPV6) {
                   p->nif_laddr6 = inp->inp_laddr6;
                   p->nif_faddr6 = inp->inp_faddr6;
                   p->nif_family = AF_INET6;
           } else {
                   p->nif_laddr = inp->inp_laddr;
                   p->nif_faddr = inp->inp_faddr;
                   p->nif_family = AF_INET;
         }          }
   
           p->nif_rcvcc = so->so_rcv.sb_cc;
           p->nif_sndcc = so->so_snd.sb_cc;
           p->nif_state = state;
 }  }
   
 static struct nlist namelist[] = {  
 #define X_TCBTABLE      0               /* no sysctl */  
         { "_tcbtable" },  
 #define X_UDBTABLE      1               /* no sysctl */  
         { "_udbtable" },  
         { "" },  
 };  
   
   /* netstat callback functions */
   
 int  int
 initnetstat(void)  select_ns(void)
 {  {
         int ret;          static int init = 0;
           if (kd == NULL) {
                   num_disp = 1;
                   return (0);
           }
   
         if ((ret = kvm_nlist(kd, namelist)) == -1)          if (!init) {
                 errx(1, "%s", kvm_geterr(kd));                  sethostent(1);
         else if (ret)                  setnetent(1);
                 nlisterr(namelist);                  init = 1;
         if (namelist[X_TCBTABLE].n_value == 0) {  
                 error("No symbols in namelist");  
                 return(0);  
         }          }
         netcb.nif_forw = netcb.nif_prev = (struct netinfo *)&netcb;  
         protos = TCP|UDP;          num_disp = num_ns;
         return(1);          return (0);
 }  }
   
 void  int
 fetchnetstat(void)  read_ns(void)
 {  {
         struct inpcbtable pcbtable;          struct inpcbtable pcbtable;
         struct inpcb *head, *prev, *next;          struct inpcb *head, *prev, *next;
         struct netinfo *p;  
         struct inpcb inpcb;          struct inpcb inpcb;
         struct socket sockb;          struct socket sockb;
         struct tcpcb tcpcb;          struct tcpcb tcpcb;
         void *off;          void *off;
         int istcp;          int istcp;
   
           if (kd == NULL) {
                   return (0);
           }
   
           num_ns = 0;
   
         if (namelist[X_TCBTABLE].n_value == 0)          if (namelist[X_TCBTABLE].n_value == 0)
                 return;                  return 0;
         for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw)  
                 p->nif_seen = 0;          if (protos & TCP) {
         if (protos&TCP) {  
                 off = NPTR(X_TCBTABLE);                  off = NPTR(X_TCBTABLE);
                 istcp = 1;                  istcp = 1;
         } else if (protos&UDP) {          } else if (protos & UDP) {
                 off = NPTR(X_UDBTABLE);                  off = NPTR(X_UDBTABLE);
                 istcp = 0;                  istcp = 0;
         } else {          } else {
                 error("No protocols to display");                  error("No protocols to display");
                 return;                  return 0;
         }          }
   
 again:  again:
         KREAD(off, &pcbtable, sizeof (struct inpcbtable));          KREAD(off, &pcbtable, sizeof (struct inpcbtable));
   
         prev = head = (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue;          prev = head = (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue;
         next = CIRCLEQ_FIRST(&pcbtable.inpt_queue);          next = CIRCLEQ_FIRST(&pcbtable.inpt_queue);
   
         while (next != head) {          while (next != head) {
                 KREAD(next, &inpcb, sizeof (inpcb));                  KREAD(next, &inpcb, sizeof (inpcb));
                 if (CIRCLEQ_PREV(&inpcb, inp_queue) != prev) {                  if (CIRCLEQ_PREV(&inpcb, inp_queue) != prev) {
                         printf("prev = %p, head = %p, next = %p, inpcb...prev = %p\n",  
                             prev, head, next, CIRCLEQ_PREV(&inpcb, inp_queue));  
                         p = netcb.nif_forw;  
                         for (; p != (struct netinfo *)&netcb; p = p->nif_forw)  
                                 p->nif_seen = 1;  
                         error("Kernel state in transition");                          error("Kernel state in transition");
                         return;                          return 0;
                 }                  }
                 prev = next;                  prev = next;
                 next = CIRCLEQ_NEXT(&inpcb, inp_queue);                  next = CIRCLEQ_NEXT(&inpcb, inp_queue);
Line 218 
Line 286 
                             IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6))                              IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6))
                                 continue;                                  continue;
                 }                  }
                 if (nhosts && !checkhost(&inpcb))  
                         continue;  
                 if (nports && !checkport(&inpcb))  
                         continue;  
                 KREAD(inpcb.inp_socket, &sockb, sizeof (sockb));                  KREAD(inpcb.inp_socket, &sockb, sizeof (sockb));
                 if (istcp) {                  if (istcp) {
                         KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));                          KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
Line 229 
Line 293 
                 } else                  } else
                         enter(&inpcb, &sockb, 0, "udp");                          enter(&inpcb, &sockb, 0, "udp");
         }          }
         if (istcp && (protos&UDP)) {          if (istcp && (protos & UDP)) {
                 istcp = 0;                  istcp = 0;
                 off = NPTR(X_UDBTABLE);                  off = NPTR(X_UDBTABLE);
                 goto again;                  goto again;
         }          }
   
           num_disp = num_ns;
           return 0;
 }  }
   
 static void  void
 enter(struct inpcb *inp, struct socket *so, int state, char *proto)  print_ns(void)
 {  {
         struct netinfo *p;          int n, count = 0;
   
         /*          if (kd == NULL) {
          * Only take exact matches, any sockets with                  print_fld_str(FLD_NS_LOCAL, "Failed to initialize KVM!");
          * previously unbound addresses will be deleted                  print_fld_str(FLD_NS_FOREIGN, "Failed to initialize KVM!");
          * below in the display routine because they                  end_line();
          * will appear as ``not seen'' in the kernel                  return;
          * data structures.          }
          */  
         for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) {  
                 if (p->nif_family == AF_INET && (inp->inp_flags & INP_IPV6))  
                         continue;  
                 if (p->nif_family == AF_INET6 && !(inp->inp_flags & INP_IPV6))  
                         continue;  
                 if (!streq(proto, p->nif_proto))  
                         continue;  
                 if (p->nif_family == AF_INET) {  
                         if (p->nif_lport != inp->inp_lport ||  
                             p->nif_laddr.s_addr != inp->inp_laddr.s_addr)  
                                 continue;  
                         if (p->nif_faddr.s_addr == inp->inp_faddr.s_addr &&  
                             p->nif_fport == inp->inp_fport)  
                                 break;  
   
                 } else if (p->nif_family == AF_INET6) {          for (n = dispstart; n < num_disp; n++) {
                         if (p->nif_lport != inp->inp_lport ||                  shownetstat(netinfos + n);
                             !IN6_ARE_ADDR_EQUAL(&p->nif_laddr6, &inp->inp_laddr6))                  count++;
                                 continue;                  if (maxprint > 0 && count >= maxprint)
                         if (IN6_ARE_ADDR_EQUAL(&p->nif_faddr6, &inp->inp_faddr6) &&                          break;
                             p->nif_fport == inp->inp_fport)  
                                 break;  
                 } else  
                         continue;  
         }          }
         if (p == (struct netinfo *)&netcb) {  
                 if ((p = malloc(sizeof(*p))) == NULL) {  
                         error("Out of memory");  
                         return;  
                 }  
                 p->nif_prev = (struct netinfo *)&netcb;  
                 p->nif_forw = netcb.nif_forw;  
                 netcb.nif_forw->nif_prev = p;  
                 netcb.nif_forw = p;  
                 p->nif_line = -1;  
                 p->nif_lport = inp->inp_lport;  
                 p->nif_fport = inp->inp_fport;  
                 p->nif_proto = proto;  
                 p->nif_flags = NIF_LACHG|NIF_FACHG;  
                 if (inp->inp_flags & INP_IPV6) {  
                         p->nif_laddr6 = inp->inp_laddr6;  
                         p->nif_faddr6 = inp->inp_faddr6;  
                         p->nif_family = AF_INET6;  
                 } else {  
                         p->nif_laddr = inp->inp_laddr;  
                         p->nif_faddr = inp->inp_faddr;  
                         p->nif_family = AF_INET;  
                 }  
         }  
         p->nif_rcvcc = so->so_rcv.sb_cc;  
         p->nif_sndcc = so->so_snd.sb_cc;  
         p->nif_state = state;  
         p->nif_seen = 1;  
 }  }
   
 /* column locations */  
 #define LADDR   0  
 #define FADDR   LADDR+23  
 #define PROTO   FADDR+23  
 #define RCVCC   PROTO+6  
 #define SNDCC   RCVCC+7  
 #define STATE   SNDCC+7  
   
   int
 void  initnetstat(void)
 labelnetstat(void)  
 {  {
         if (namelist[X_TCBTABLE].n_type == 0)          field_view *v;
                 return;          int ret;
         wmove(wnd, 0, 0);  
         wclrtobot(wnd);  
         mvwaddstr(wnd, 0, LADDR, "Local Address");  
         mvwaddstr(wnd, 0, FADDR, "Foreign Address");  
         mvwaddstr(wnd, 0, PROTO, "Proto");  
         mvwaddstr(wnd, 0, RCVCC, "Recv-Q");  
         mvwaddstr(wnd, 0, SNDCC, "Send-Q");  
         mvwaddstr(wnd, 0, STATE, "(state)");  
 }  
   
 void          if (kd) {
 shownetstat(void)                  if ((ret = kvm_nlist(kd, namelist)) == -1)
 {                          errx(1, "%s", kvm_geterr(kd));
         struct netinfo *p, *q;                  else if (ret)
                           nlisterr(namelist);
   
         /*                  if (namelist[X_TCBTABLE].n_value == 0) {
          * First, delete any connections that have gone                          error("No symbols in namelist");
          * away and adjust the position of connections                          return(0);
          * below to reflect the deleted line.  
          */  
         p = netcb.nif_forw;  
         while (p != (struct netinfo *)&netcb) {  
                 if (p->nif_line == -1 || p->nif_seen) {  
                         p = p->nif_forw;  
                         continue;  
                 }                  }
                 wmove(wnd, p->nif_line, 0);  
                 wdeleteln(wnd);  
                 q = netcb.nif_forw;  
                 for (; q != (struct netinfo *)&netcb; q = q->nif_forw)  
                         if (q != p && q->nif_line > p->nif_line) {  
                                 q->nif_line--;  
                                 /* this shouldn't be necessary */  
                                 q->nif_flags |= NIF_LACHG|NIF_FACHG;  
                         }  
                 lastrow--;  
                 q = p->nif_forw;  
                 p->nif_prev->nif_forw = p->nif_forw;  
                 p->nif_forw->nif_prev = p->nif_prev;  
                 free(p);  
                 p = q;  
         }          }
         /*          protos = TCP|UDP;
          * Update existing connections and add new ones.  
          */          for (v = views_ns; v->name != NULL; v++)
         for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) {                  add_view(v);
                 if (p->nif_line == -1) {  
                         /*          return(1);
                          * Add a new entry if possible.  }
                          */  
                         if (lastrow > YMAX(wnd))  static void
                                 continue;  shownetstat(struct netinfo *p)
                         p->nif_line = lastrow++;  {
                         p->nif_flags |= NIF_LACHG|NIF_FACHG;          switch (p->nif_family) {
                 }          case AF_INET:
                 if (p->nif_flags & NIF_LACHG) {                  inetprint(&p->nif_laddr, p->nif_lport,
                         wmove(wnd, p->nif_line, LADDR);                            p->nif_proto, FLD_NS_LOCAL);
                         switch (p->nif_family) {                  inetprint(&p->nif_faddr, p->nif_fport,
                         case AF_INET:                            p->nif_proto, FLD_NS_FOREIGN);
                                 inetprint(&p->nif_laddr, p->nif_lport,                  break;
                                     p->nif_proto);          case AF_INET6:
                                 break;                  inet6print(&p->nif_laddr6, p->nif_lport,
                         case AF_INET6:                             p->nif_proto, FLD_NS_LOCAL);
                                 inet6print(&p->nif_laddr6, p->nif_lport,                  inet6print(&p->nif_faddr6, p->nif_fport,
                                     p->nif_proto);                             p->nif_proto, FLD_NS_FOREIGN);
                                 break;                  break;
                         }  
                         p->nif_flags &= ~NIF_LACHG;  
                 }  
                 if (p->nif_flags & NIF_FACHG) {  
                         wmove(wnd, p->nif_line, FADDR);  
                         switch (p->nif_family) {  
                         case AF_INET:  
                                 inetprint(&p->nif_faddr, p->nif_fport,  
                                     p->nif_proto);  
                                 break;  
                         case AF_INET6:  
                                 inet6print(&p->nif_faddr6, p->nif_fport,  
                                     p->nif_proto);  
                                 break;  
                         }  
                         p->nif_flags &= ~NIF_FACHG;  
                 }  
                 mvwaddstr(wnd, p->nif_line, PROTO, p->nif_proto);  
                 if (p->nif_family == AF_INET6)  
                         waddstr(wnd, "6");  
                 mvwprintw(wnd, p->nif_line, RCVCC, "%6d", p->nif_rcvcc);  
                 mvwprintw(wnd, p->nif_line, SNDCC, "%6d", p->nif_sndcc);  
                 if (streq(p->nif_proto, "tcp")) {  
                         if (p->nif_state < 0 || p->nif_state >= TCP_NSTATES)  
                                 mvwprintw(wnd, p->nif_line, STATE, "%d",  
                                     p->nif_state);  
                         else  
                                 mvwaddstr(wnd, p->nif_line, STATE,  
                                     tcpstates[p->nif_state]);  
                 }  
                 wclrtoeol(wnd);  
         }          }
         if (lastrow < YMAX(wnd)) {  
                 wmove(wnd, lastrow, 0);          tb_start();
                 wclrtobot(wnd);          tbprintf("%s", p->nif_proto);
                 wmove(wnd, YMAX(wnd), 0);          if (p->nif_family == AF_INET6)
                 wdeleteln(wnd); /* XXX */                  tbprintf("6");
   
           print_fld_tb(FLD_NS_PROTO);
   
           print_fld_size(FLD_NS_RECV_Q, p->nif_rcvcc);
           print_fld_size(FLD_NS_SEND_Q, p->nif_sndcc);
   
           if (streq(p->nif_proto, "tcp")) {
                   if (p->nif_state < 0 || p->nif_state >= TCP_NSTATES)
                           print_fld_uint(FLD_NS_STATE, p->nif_state);
                   else
                           print_fld_str(FLD_NS_STATE, tcpstates[p->nif_state]);
         }          }
           end_line();
 }  }
   
 /*  /*
Line 428 
Line 391 
  * If the nflag was specified, use numbers instead of names.   * If the nflag was specified, use numbers instead of names.
  */   */
 static void  static void
 inetprint(struct in_addr *in, int port, char *proto)  inetprint(struct in_addr *in, int port, char *proto, field_def *fld)
 {  {
         struct servent *sp = 0;          struct servent *sp = 0;
         char line[80], *cp;  
   
         snprintf(line, sizeof line, "%.*s.", 16, inetname(*in));          tb_start();
         cp = strchr(line, '\0');          tbprintf("%s", inetname(*in));
   
         if (!nflag && port)          if (!nflag && port)
                 sp = getservbyport(port, proto);                  sp = getservbyport(port, proto);
         if (sp || port == 0)          if (sp || port == 0)
                 snprintf(cp, sizeof line - strlen(cp), "%.8s",                  tbprintf(":%s", sp ? sp->s_name : "*");
                     sp ? sp->s_name : "*");  
         else          else
                 snprintf(cp, sizeof line - strlen(cp), "%d",                  tbprintf(":%d", ntohs((u_short)port));
                     ntohs((u_short)port));  
         /* pad to full column to clear any garbage */          print_fld_tb(fld);
         cp = strchr(line, '\0');  
         while (cp - line < 22 && cp - line < sizeof line-1)  
                 *cp++ = ' ';  
         *cp = '\0';  
         waddstr(wnd, line);  
 }  }
   
 static void  static void
 inet6print(struct in6_addr *in6, int port, char *proto)  inet6print(struct in6_addr *in6, int port, char *proto, field_def *fld)
 {  {
         struct servent *sp = 0;          struct servent *sp = 0;
         char line[80], *cp;  
   
         snprintf(line, sizeof line, "%.*s.", 16, inet6name(in6));          tb_start();
         cp = strchr(line, '\0');  
           tbprintf("%s", inet6name(in6));
         if (!nflag && port)          if (!nflag && port)
                 sp = getservbyport(port, proto);                  sp = getservbyport(port, proto);
         if (sp || port == 0)          if (sp || port == 0)
                 snprintf(cp, sizeof line - strlen(cp), "%.8s",                  tbprintf(":%s", sp ? sp->s_name : "*");
                     sp ? sp->s_name : "*");  
         else          else
                 snprintf(cp, sizeof line - strlen(cp), "%d",                  tbprintf(":%d", ntohs((u_short)port));
                     ntohs((u_short)port));  
         /* pad to full column to clear any garbage */  
         cp = strchr(line, '\0');  
         while (cp - line < 22 && cp - line < sizeof line-1)  
                 *cp++ = ' ';  
         *cp = '\0';  
         waddstr(wnd, line);  
 }  
   
 /*          print_fld_tb(fld);
  * Construct an Internet address representation.  
  * If the nflag has been supplied, give  
  * numeric value, otherwise try for symbolic name.  
  */  
 static const char *  
 inetname(struct in_addr in)  
 {  
         char *cp = 0;  
         static char line[50];  
         struct hostent *hp;  
         struct netent *np;  
   
         if (!nflag && in.s_addr != INADDR_ANY) {  
                 int net = inet_netof(in);  
                 int lna = inet_lnaof(in);  
   
                 if (lna == INADDR_ANY) {  
                         np = getnetbyaddr(net, AF_INET);  
                         if (np)  
                                 cp = np->n_name;  
                 }  
                 if (cp == 0) {  
                         hp = gethostbyaddr(&in, sizeof (in), AF_INET);  
                         if (hp)  
                                 cp = hp->h_name;  
                 }  
         }  
         if (in.s_addr == INADDR_ANY) {  
                 strlcpy(line, "*", sizeof line);  
         } else if (cp) {  
                 strlcpy(line, cp, sizeof line);  
         } else {  
                 in.s_addr = ntohl(in.s_addr);  
 #define C(x)    ((x) & 0xff)  
                 snprintf(line, sizeof line, "%u.%u.%u.%u", C(in.s_addr >> 24),  
                     C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));  
         }  
         return (line);  
 }  }
   
 static const char *  static const char *
Line 536 
Line 446 
         return "?";          return "?";
 }  }
   
 int  static const char *
 cmdnetstat(char *cmd, char *args)  inetname(struct in_addr in)
 {  {
         struct netinfo *p;          static char line[NI_MAXHOST];
           struct sockaddr_in sin;
           int flags, e;
   
         if (prefix(cmd, "all")) {          flags = nflag ? NI_NUMERICHOST : 0;
                 aflag = !aflag;          if (in.s_addr == INADDR_ANY)
                 goto fixup;                  return "*";
         }  
         if  (prefix(cmd, "numbers") || prefix(cmd, "names")) {  
                 int new;  
   
                 new = prefix(cmd, "numbers");          memset(&sin, 0, sizeof(sin));
                 if (new == nflag)          sin.sin_family = AF_INET;
                         return (1);          sin.sin_len = sizeof(struct sockaddr_in);
                 p = netcb.nif_forw;          sin.sin_addr = in;
                 for (; p != (struct netinfo *)&netcb; p = p->nif_forw) {  
                         if (p->nif_line == -1)          e = getnameinfo((struct sockaddr *)&sin, sin.sin_len,
                                 continue;                          line, sizeof(line), NULL, 0, flags);
                         p->nif_flags |= NIF_LACHG|NIF_FACHG;  
                 }          if (e == 0)
                 nflag = new;                  return line;
                 wclear(wnd);  
                 labelnetstat();          error("Lookup: %s", gai_strerror(e));
                 goto redisplay;  
         }          return "?";
         if (!netcmd(cmd, args))  }
   
   int
   kvm_ckread(void *a, void *b, size_t l)
   {
           if (kvm_read(kd, (u_long)a, b, l) != l) {
                   if (verbose)
                           error("error reading kmem at %x\n", a);
                 return (0);                  return (0);
 fixup:          } else
         fetchnetstat();                  return (1);
 redisplay:  
         shownetstat();  
         refresh();  
         return (1);  
 }  }
   
   
   int
   ns_keyboard_callback(int ch)
   {
           switch (ch) {
           case 'n':
                   nflag = !nflag;
                   gotsig_alarm = 1;
                   break;
           case 't':
                   protos ^= TCP;
                   gotsig_alarm = 1;
                   break;
           case 'u':
                   protos ^= UDP;
                   gotsig_alarm = 1;
                   break;
           default:
                   return keyboard_callback(ch);
           };
   
           return 1;
   }
   

Legend:
Removed from v.1.30  
changed lines
  Added in v.1.31