[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.44 and 1.45

version 1.44, 2015/01/20 18:26:57 version 1.45, 2015/03/12 01:03:00
Line 34 
Line 34 
  * netstat   * netstat
  */   */
   
 #include <sys/signal.h>  #include <kvm.h>
   #include <sys/types.h>
   #include <sys/sysctl.h>
 #include <sys/socket.h>  #include <sys/socket.h>
 #include <sys/socketvar.h>  #define _KERNEL
 #include <sys/mbuf.h>  #include <sys/file.h>
 #include <sys/protosw.h>  #undef _KERNEL
   
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <net/route.h>  
 #include <netinet/ip.h>  
 #include <netinet/in_pcb.h>  
 #include <netinet/ip_icmp.h>  
 #include <netinet/icmp_var.h>  
 #include <netinet/ip_var.h>  
 #include <netinet/tcp.h>  #include <netinet/tcp.h>
 #include <netinet/tcp_seq.h>  #include <netinet/tcp_seq.h>
 #define TCPSTATES  #define TCPSTATES
 #include <netinet/tcp_fsm.h>  #include <netinet/tcp_fsm.h>
 #include <netinet/tcp_timer.h>  
 #include <netinet/tcp_var.h>  
 #include <netinet/udp.h>  
 #include <netinet/udp_var.h>  
 #include <arpa/inet.h>  #include <arpa/inet.h>
   
 #include <netdb.h>  #include <netdb.h>
   #include <signal.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <err.h>  #include <err.h>
Line 66 
Line 59 
 #include "systat.h"  #include "systat.h"
 #include "engine.h"  #include "engine.h"
   
   #define TCP     0x1
   #define UDP     0x2
   #define OTHER   0x4
   
 struct netinfo {  struct netinfo {
         union {          union {
                 struct  in_addr nif_laddr;      /* local address */                  struct  in_addr nif_laddr;      /* local address */
Line 75 
Line 72 
                 struct  in_addr nif_faddr;      /* foreign address */                  struct  in_addr nif_faddr;      /* foreign address */
                 struct  in6_addr nif_faddr6;    /* foreign address */                  struct  in6_addr nif_faddr6;    /* foreign address */
         } f;          } f;
         char    *nif_proto;             /* protocol */  
         long    nif_rcvcc;              /* rcv buffer character count */          long    nif_rcvcc;              /* rcv buffer character count */
         long    nif_sndcc;              /* snd buffer character count */          long    nif_sndcc;              /* snd buffer character count */
         short   nif_lport;              /* local port */          short   nif_lport;              /* local port */
         short   nif_fport;              /* foreign port */          short   nif_fport;              /* foreign port */
         short   nif_state;              /* tcp state */          short   nif_state;              /* tcp state */
         short   nif_family;          short   nif_family;
           short   nif_proto;              /* protocol */
           short   nif_ipproto;
 };  };
   
 #define nif_laddr  l.nif_laddr  #define nif_laddr  l.nif_laddr
Line 89 
Line 87 
 #define nif_faddr  f.nif_faddr  #define nif_faddr  f.nif_faddr
 #define nif_faddr6 f.nif_faddr6  #define nif_faddr6 f.nif_faddr6
   
 static void enter(struct inpcb *, struct socket *, int, char *);  static void enter(struct kinfo_file *);
   static int kf_comp(const void *, const void *);
 static void inetprint(struct in_addr *, int, char *, field_def *);  static void inetprint(struct in_addr *, int, char *, field_def *);
 static void inet6print(struct in6_addr *, int, char *, field_def *);  static void inet6print(struct in6_addr *, int, char *, field_def *);
 static void shownetstat(struct netinfo *p);  static void shownetstat(struct netinfo *p);
Line 103 
Line 102 
   
 static  int aflag = 0;  static  int aflag = 0;
   
 static struct nlist namelist[] = {  
 #define X_TCBTABLE      0               /* no sysctl */  
         { "_tcbtable" },  
 #define X_UDBTABLE      1               /* no sysctl */  
         { "_udbtable" },  
         { "" },  
 };  
 #define ADD_ALLOC  1000  #define ADD_ALLOC  1000
   
   
 int protos;  int protos;
   
 struct netinfo *netinfos = NULL;  struct netinfo *netinfos = NULL;
Line 175 
Line 166 
 }  }
   
 static void  static void
 enter(struct inpcb *inp, struct socket *so, int state, char *proto)  enter(struct kinfo_file *kf)
 {  {
   #define s6_addr32 __u6_addr.__u6_addr32
         struct netinfo *p;          struct netinfo *p;
   
           /* first filter out unwanted sockets */
           if (kf->so_family != AF_INET && kf->so_family != AF_INET6)
                   return;
   
           switch (kf->so_protocol) {
           case IPPROTO_TCP:
                   if ((protos & TCP) == 0)
                           return;
                   break;
           case IPPROTO_UDP:
                   if ((protos & UDP) == 0)
                           return;
                   break;
           default:
                   if ((protos & OTHER) == 0)
                           return;
                   break;
           }
   
           if (!aflag) {
                   struct in6_addr faddr6;
   
                   switch (kf->so_family) {
                   case AF_INET:
                           if (kf->inp_faddru[0] == INADDR_ANY)
                                   return;
                           break;
                   case AF_INET6:
                           faddr6.s6_addr32[0] = kf->inp_faddru[0];
                           faddr6.s6_addr32[1] = kf->inp_faddru[1];
                           faddr6.s6_addr32[2] = kf->inp_faddru[2];
                           faddr6.s6_addr32[3] = kf->inp_faddru[3];
                           if (IN6_IS_ADDR_UNSPECIFIED(&faddr6))
                                   return;
                           break;
                   }
           }
   
           /* finally enter the socket to the table */
         p = next_ns();          p = next_ns();
         if (p == NULL) {          if (p == NULL) {
                 error("Out of Memory!");                  error("Out of Memory!");
                 return;                  return;
         }          }
   
         p->nif_lport = inp->inp_lport;          p->nif_lport = kf->inp_lport;
         p->nif_fport = inp->inp_fport;          p->nif_fport = kf->inp_fport;
         p->nif_proto = proto;          p->nif_proto = kf->so_protocol;
           p->nif_ipproto = kf->inp_proto;
         if (inp->inp_flags & INP_IPV6) {  
                 p->nif_laddr6 = inp->inp_laddr6;          switch (kf->so_family) {
                 p->nif_faddr6 = inp->inp_faddr6;          case AF_INET:
                 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_family = AF_INET;
                   p->nif_laddr.s_addr = kf->inp_laddru[0];
                   p->nif_faddr.s_addr = kf->inp_faddru[0];
                   break;
           case AF_INET6:
                   p->nif_family = AF_INET6;
                   p->nif_laddr6.s6_addr32[0] = kf->inp_laddru[0];
                   p->nif_laddr6.s6_addr32[1] = kf->inp_laddru[1];
                   p->nif_laddr6.s6_addr32[2] = kf->inp_laddru[2];
                   p->nif_laddr6.s6_addr32[3] = kf->inp_laddru[3];
                   p->nif_faddr6.s6_addr32[0] = kf->inp_faddru[0];
                   p->nif_faddr6.s6_addr32[1] = kf->inp_faddru[1];
                   p->nif_faddr6.s6_addr32[2] = kf->inp_faddru[2];
                   p->nif_faddr6.s6_addr32[3] = kf->inp_faddru[3];
                   break;
         }          }
   
         p->nif_rcvcc = so->so_rcv.sb_cc;          p->nif_rcvcc = kf->so_rcv_cc;
         p->nif_sndcc = so->so_snd.sb_cc;          p->nif_sndcc = kf->so_snd_cc;
         p->nif_state = state;          p->nif_state = kf->t_state;
   #undef s6_addr32
 }  }
   
   
Line 210 
Line 252 
 int  int
 select_ns(void)  select_ns(void)
 {  {
         if (kd == NULL) {  
                 num_disp = 1;  
                 return (0);  
         }  
         num_disp = num_ns;          num_disp = num_ns;
         return (0);          return (0);
 }  }
   
   static int type_map[] = { -1, 2, 3, 1, 4, 5 };
   
   static int
   kf_comp(const void *a, const void *b)
   {
           const struct kinfo_file *ka = a, *kb = b;
   
           if (ka->so_family != kb->so_family) {
                   /* AF_INET < AF_INET6 < AF_LOCAL */
                   if (ka->so_family == AF_INET)
                           return (-1);
                   if (ka->so_family == AF_LOCAL)
                           return (1);
                   if (kb->so_family == AF_LOCAL)
                           return (-1);
                   return (1);
           }
           if (ka->so_family == AF_LOCAL) {
                   if (type_map[ka->so_type] < type_map[kb->so_type])
                           return (-1);
                   if (type_map[ka->so_type] > type_map[kb->so_type])
                           return (1);
           } else if (ka->so_family == AF_INET || ka->so_family == AF_INET6) {
                   if (ka->so_protocol < kb->so_protocol)
                           return (-1);
                   if (ka->so_protocol > kb->so_protocol)
                           return (1);
                   if (ka->so_type == SOCK_DGRAM || ka->so_type == SOCK_STREAM) {
                           /* order sockets by remote port desc */
                           if (ka->inp_fport > kb->inp_fport)
                                   return (-1);
                           if (ka->inp_fport < kb->inp_fport)
                                   return (1);
                   } else if (ka->so_type == SOCK_RAW) {
                           if (ka->inp_proto > kb->inp_proto)
                                   return (-1);
                           if (ka->inp_proto < kb->inp_proto)
                                   return (1);
                   }
           }
           return (0);
   }
   
   
 int  int
 read_ns(void)  read_ns(void)
 {  {
         struct inpcbtable pcbtable;          struct kinfo_file *kf;
         struct inpcb *next, *prev;          int i, fcnt;
         struct inpcb inpcb, prevpcb;  
         struct socket sockb;  
         struct tcpcb tcpcb;  
         void *off;  
         int istcp;  
   
         if (kd == NULL) {          if (kd == NULL) {
                   error("Failed to initialize KVM!");
                 return (0);                  return (0);
         }          }
           kf = kvm_getfiles(kd, KERN_FILE_BYFILE, DTYPE_SOCKET,
         num_ns = 0;              sizeof(*kf), &fcnt);
           if (kf == NULL) {
         if (namelist[X_TCBTABLE].n_value == 0)                  error("Out of Memory!");
                 return 0;                  return (0);
   
         if (protos & TCP) {  
                 off = NPTR(X_TCBTABLE);  
                 istcp = 1;  
         } else if (protos & UDP) {  
                 off = NPTR(X_UDBTABLE);  
                 istcp = 0;  
         } else {  
                 error("No protocols to display");  
                 return 0;  
         }          }
   
 again:          /* sort sockets by AF, proto and type */
         KREAD(off, &pcbtable, sizeof (struct inpcbtable));          qsort(kf, fcnt, sizeof(*kf), kf_comp);
   
         prev = NULL;          num_ns = 0;
         next = TAILQ_FIRST(&pcbtable.inpt_queue);  
   
         while (next != NULL) {          for (i = 0; i < fcnt; i++)
                 KREAD(next, &inpcb, sizeof (inpcb));                  enter(&kf[i]);
                 if (prev != NULL) {  
                         KREAD(prev, &prevpcb, sizeof (prevpcb));  
                         if (TAILQ_NEXT(&prevpcb, inp_queue) != next) {  
                                 error("Kernel state in transition");  
                                 return 0;  
                         }  
                 }  
                 prev = next;  
                 next = TAILQ_NEXT(&inpcb, inp_queue);  
   
                 if (!aflag) {  
                         if (!(inpcb.inp_flags & INP_IPV6) &&  
                             inet_lnaof(inpcb.inp_faddr) == INADDR_ANY)  
                                 continue;  
                         if ((inpcb.inp_flags & INP_IPV6) &&  
                             IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_faddr6))  
                                 continue;  
                 }  
                 KREAD(inpcb.inp_socket, &sockb, sizeof (sockb));  
                 if (istcp) {  
                         KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));  
                         if (!aflag && tcpcb.t_state <= TCPS_LISTEN)  
                                 continue;  
                         enter(&inpcb, &sockb, tcpcb.t_state, "tcp");  
                 } else  
                         enter(&inpcb, &sockb, 0, "udp");  
         }  
         if (istcp && (protos & UDP)) {  
                 istcp = 0;  
                 off = NPTR(X_UDBTABLE);  
                 goto again;  
         }  
   
         num_disp = num_ns;          num_disp = num_ns;
         return 0;          return 0;
 }  }
Line 299 
Line 334 
 {  {
         int n, count = 0;          int n, count = 0;
   
         if (kd == NULL) {  
                 print_fld_str(FLD_NS_LOCAL, "Failed to initialize KVM!");  
                 print_fld_str(FLD_NS_FOREIGN, "Failed to initialize KVM!");  
                 end_line();  
                 return;  
         }  
   
         for (n = dispstart; n < num_disp; n++) {          for (n = dispstart; n < num_disp; n++) {
                 shownetstat(netinfos + n);                  shownetstat(netinfos + n);
                 count++;                  count++;
Line 319 
Line 347 
 initnetstat(void)  initnetstat(void)
 {  {
         field_view *v;          field_view *v;
         int ret;  
   
         if (kd) {          protos = TCP|UDP|OTHER;
                 if ((ret = kvm_nlist(kd, namelist)) == -1)  
                         errx(1, "%s", kvm_geterr(kd));  
                 else if (ret)  
                         nlisterr(namelist);  
   
                 if (namelist[X_TCBTABLE].n_value == 0) {  
                         error("No symbols in namelist");  
                         return(0);  
                 }  
         }  
         protos = TCP|UDP;  
   
         for (v = views_ns; v->name != NULL; v++)          for (v = views_ns; v->name != NULL; v++)
                 add_view(v);                  add_view(v);
   
Line 343 
Line 358 
 static void  static void
 shownetstat(struct netinfo *p)  shownetstat(struct netinfo *p)
 {  {
           char *proto = NULL;
   
           switch (p->nif_proto) {
           case IPPROTO_TCP:
                   proto = "tcp";
                   break;
           case IPPROTO_UDP:
                   proto = "udp";
                   break;
           }
   
         switch (p->nif_family) {          switch (p->nif_family) {
         case AF_INET:          case AF_INET:
                 inetprint(&p->nif_laddr, p->nif_lport,                  inetprint(&p->nif_laddr, p->nif_lport,
                           p->nif_proto, FLD_NS_LOCAL);                            proto, FLD_NS_LOCAL);
                 inetprint(&p->nif_faddr, p->nif_fport,                  inetprint(&p->nif_faddr, p->nif_fport,
                           p->nif_proto, FLD_NS_FOREIGN);                            proto, FLD_NS_FOREIGN);
                 break;                  break;
         case AF_INET6:          case AF_INET6:
                 inet6print(&p->nif_laddr6, p->nif_lport,                  inet6print(&p->nif_laddr6, p->nif_lport,
                            p->nif_proto, FLD_NS_LOCAL);                             proto, FLD_NS_LOCAL);
                 inet6print(&p->nif_faddr6, p->nif_fport,                  inet6print(&p->nif_faddr6, p->nif_fport,
                            p->nif_proto, FLD_NS_FOREIGN);                             proto, FLD_NS_FOREIGN);
                 break;                  break;
         }          }
   
         tb_start();          tb_start();
         tbprintf("%s", p->nif_proto);          switch (p->nif_proto) {
         if (p->nif_family == AF_INET6)          case IPPROTO_TCP:
                 tbprintf("6");          case IPPROTO_UDP:
                   tbprintf(proto);
                   if (p->nif_family == AF_INET6)
                           tbprintf("6");
                   break;
           case IPPROTO_DIVERT:
                   tbprintf("divert");
                   if (p->nif_family == AF_INET6)
                           tbprintf("6");
                   break;
           default:
                   tbprintf("%d", p->nif_ipproto);
                   break;
           }
   
         print_fld_tb(FLD_NS_PROTO);          print_fld_tb(FLD_NS_PROTO);
   
         print_fld_size(FLD_NS_RECV_Q, p->nif_rcvcc);          print_fld_size(FLD_NS_RECV_Q, p->nif_rcvcc);
         print_fld_size(FLD_NS_SEND_Q, p->nif_sndcc);          print_fld_size(FLD_NS_SEND_Q, p->nif_sndcc);
   
         if (streq(p->nif_proto, "tcp")) {          if (p->nif_proto == IPPROTO_TCP) {
                 if (p->nif_state < 0 || p->nif_state >= TCP_NSTATES)                  if (p->nif_state < 0 || p->nif_state >= TCP_NSTATES)
                         print_fld_uint(FLD_NS_STATE, p->nif_state);                          print_fld_uint(FLD_NS_STATE, p->nif_state);
                 else                  else
Line 418 
Line 457 
 }  }
   
 int  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\n");  
                 return (0);  
         } else  
                 return (1);  
 }  
   
   
 int  
 ns_keyboard_callback(int ch)  ns_keyboard_callback(int ch)
 {  {
         switch (ch) {          switch (ch) {
Line 439 
Line 466 
                 break;                  break;
         case 'n':          case 'n':
                 nflag = !nflag;                  nflag = !nflag;
                   gotsig_alarm = 1;
                   break;
           case 'o':
                   protos ^= OTHER;
                 gotsig_alarm = 1;                  gotsig_alarm = 1;
                 break;                  break;
         case 'r':          case 'r':

Legend:
Removed from v.1.44  
changed lines
  Added in v.1.45