Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/netstat Checkin work in progress to make netstat use...



details:   https://anonhg.NetBSD.org/src/rev/ccea5b4ba7c4
branches:  trunk
changeset: 747387:ccea5b4ba7c4
user:      elad <elad%NetBSD.org@localhost>
date:      Sun Sep 13 02:53:17 2009 +0000

description:
Checkin work in progress to make netstat use sysctl rather than kvm(3).

This commit mostly adds code written by Claudio Jeker for OpenBSD to
support sysctl in the interface printing parts (-i, -I, -w). The port has
been ported to NetBSD with tiny adjustments -- of course all bugs etc.
are mine.

Also add and document a -X flag to force sysctl usage. The documentation
notes this flag may be removed at any time and its presence should not be
relied on.

Some misc. comments/#ifdef changes/code snippet moves as well.

Please note that no functionality should change as the routing and
interface printing code is still not fully supported.

Mailing list reference:

    http://mail-index.netbsd.org/tech-userlevel/2009/09/09/msg002604.html

diffstat:

 usr.bin/netstat/if.c      |  872 +++++++++++++++++++++++++++++++++------------
 usr.bin/netstat/main.c    |   20 +-
 usr.bin/netstat/netstat.1 |   15 +-
 usr.bin/netstat/netstat.h |    3 +-
 usr.bin/netstat/show.c    |   10 +-
 5 files changed, 677 insertions(+), 243 deletions(-)

diffs (truncated from 1153 to 300 lines):

diff -r 52c15235284a -r ccea5b4ba7c4 usr.bin/netstat/if.c
--- a/usr.bin/netstat/if.c      Sat Sep 12 22:22:33 2009 +0000
+++ b/usr.bin/netstat/if.c      Sun Sep 13 02:53:17 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.c,v 1.63 2009/04/12 16:08:37 lukem Exp $    */
+/*     $NetBSD: if.c,v 1.64 2009/09/13 02:53:17 elad Exp $     */
 
 /*
  * Copyright (c) 1983, 1988, 1993
@@ -34,18 +34,21 @@
 #if 0
 static char sccsid[] = "from: @(#)if.c 8.2 (Berkeley) 2/21/94";
 #else
-__RCSID("$NetBSD: if.c,v 1.63 2009/04/12 16:08:37 lukem Exp $");
+__RCSID("$NetBSD: if.c,v 1.64 2009/09/13 02:53:17 elad Exp $");
 #endif
 #endif /* not lint */
 
+#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/time.h>
+#include <sys/sysctl.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
+#include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_var.h>
 #include <netiso/iso.h>
@@ -59,14 +62,40 @@
 #include <string.h>
 #include <unistd.h>
 #include <netdb.h>
+#include <err.h>
 
 #include "netstat.h"
 
-#define        YES     1
-#define        NO      0
+#define        MAXIF   100
+
+struct iftot {
+       char ift_name[IFNAMSIZ];        /* interface name */
+       u_quad_t ift_ip;                /* input packets */
+       u_quad_t ift_ib;                /* input bytes */
+       u_quad_t ift_ie;                /* input errors */
+       u_quad_t ift_op;                /* output packets */
+       u_quad_t ift_ob;                /* output bytes */
+       u_quad_t ift_oe;                /* output errors */
+       u_quad_t ift_co;                /* collisions */
+       int ift_dr;                     /* drops */
+};
 
-static void sidewaysintpr __P((u_int, u_long));
+static void print_addr(struct sockaddr *, struct sockaddr **, struct if_data *);
+static void sidewaysintpr(u_int, u_long);
+
+static void iftot_banner(struct iftot *);
+static void iftot_print_sum(struct iftot *, struct iftot *);
+static void iftot_print(struct iftot *, struct iftot *);
+
 static void catchalarm __P((int));
+static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
+static void fetchifs(void);
+
+static void intpr_sysctl(void);
+static void intpr_kvm(u_long, void (*)(const char *));
+
+struct iftot iftot[MAXIF], ip_cur, ip_old, sum_cur, sum_old;
+bool   signalled;                      /* set if alarm goes off "early" */
 
 /*
  * Print a description of the network interfaces.
@@ -79,41 +108,23 @@
        u_long ifnetaddr;
        void (*pfunc)(const char *);
 {
-       struct ifnet ifnet;
-       union {
-               struct ifaddr ifa;
-               struct in_ifaddr in;
-#ifdef INET6
-               struct in6_ifaddr in6;
-#endif /* INET6 */
-               struct iso_ifaddr iso;
-       } ifaddr;
-       u_long ifaddraddr;
-       struct sockaddr *sa;
-       struct ifnet_head ifhead;       /* TAILQ_HEAD */
-       char name[IFNAMSIZ + 1];        /* + 1 for `*' */
-       char hbuf[NI_MAXHOST];          /* for getnameinfo() */
-#ifdef INET6
-       const int niflag = NI_NUMERICHOST;
-#endif
 
-       if (ifnetaddr == 0) {
-               printf("ifnet: symbol not defined\n");
-               return;
-       }
        if (interval) {
                sidewaysintpr((unsigned)interval, ifnetaddr);
                return;
        }
 
-       /*
-        * Find the pointer to the first ifnet structure.  Replace
-        * the pointer to the TAILQ_HEAD with the actual pointer
-        * to the first list element.
-        */
-       if (kread(ifnetaddr, (char *)&ifhead, sizeof ifhead))
-               return;
-       ifnetaddr = (u_long)ifhead.tqh_first;
+       if (use_sysctl) {
+               intpr_sysctl();
+       } else {
+               intpr_kvm(ifnetaddr, pfunc);
+       }
+
+}
+
+static void
+intpr_header(void)
+{
 
        if (!sflag & !pflag) {
                if (bflag) {
@@ -133,14 +144,139 @@
                        printf(" %5.5s", "Drops");
                putchar('\n');
        }
+}
+
+static void
+intpr_sysctl(void)
+{
+       struct if_msghdr *ifm;
+       int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
+       char *buf = NULL, *next, *lim, *cp;
+       struct rt_msghdr *rtm;
+       struct ifa_msghdr *ifam;
+       struct if_data *ifd = NULL;
+       struct sockaddr *sa, *rti_info[RTAX_MAX];
+       struct sockaddr_dl *sdl;
+       uint64_t total = 0;
+       size_t len;
+       char name[IFNAMSIZ + 1];        /* + 1 for `*' */
+
+       if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
+               err(1, "sysctl");
+       if ((buf = malloc(len)) == NULL)
+               err(1, NULL);
+       if (sysctl(mib, 6, buf, &len, NULL, 0) == -1)
+               err(1, "sysctl");
+
+       intpr_header();
+
+       lim = buf + len;
+       for (next = buf; next < lim; next += rtm->rtm_msglen) {
+               rtm = (struct rt_msghdr *)next;
+               if (rtm->rtm_version != RTM_VERSION)
+                       continue;
+               switch (rtm->rtm_type) {
+               case RTM_IFINFO:
+                       total = 0;
+                       ifm = (struct if_msghdr *)next;
+                       ifd = &ifm->ifm_data;
+
+                       sa = (struct sockaddr *)(ifm + 1);
+                       get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
+
+                       sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
+                       if (sdl == NULL || sdl->sdl_family != AF_LINK) {
+                               continue;
+                       }
+                       bzero(name, sizeof(name));
+                       if (sdl->sdl_nlen >= IFNAMSIZ)
+                               memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
+                       else if (sdl->sdl_nlen > 0) 
+                               memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
+
+                       if (interface != 0 && strcmp(name, interface) != 0)
+                               continue;
+
+                       /* mark inactive interfaces with a '*' */
+                       cp = strchr(name, '\0');
+                       if ((ifm->ifm_flags & IFF_UP) == 0)
+                               *cp++ = '*';
+                       *cp = '\0';
+
+                       if (qflag) {
+                               total = ifd->ifi_ibytes + ifd->ifi_obytes +
+                                   ifd->ifi_ipackets + ifd->ifi_ierrors +
+                                   ifd->ifi_opackets + ifd->ifi_oerrors +
+                                   ifd->ifi_collisions;
+                               if (tflag)
+                                       total += 0; // XXX-elad ifnet.if_timer;
+                               if (dflag)
+                                       total += 0; // XXX-elad ifnet.if_snd.ifq_drops;
+                               if (total == 0)
+                                       continue;
+                       }
+
+                       printf("%-5s %-5qu ", name, ifd->ifi_mtu);
+                       print_addr(rti_info[RTAX_IFP], rti_info, ifd);
+                       break;
+
+               case RTM_NEWADDR:
+                       if (qflag && total == 0)
+                               continue;
+                       if (interface != 0 && strcmp(name, interface) != 0)
+                               continue;
+                       ifam = (struct ifa_msghdr *)next;
+                       if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
+                           RTA_BRD)) == 0)
+                               break;
+
+                       sa = (struct sockaddr *)(ifam + 1);
+
+                       get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
+
+                       printf("%-5s %-5qu ", name, ifd->ifi_mtu);
+                       print_addr(rti_info[RTAX_IFA], rti_info, ifd);
+                       break;
+               }
+       }
+}
+
+static void
+intpr_kvm(u_long ifnetaddr, void (*pfunc)(const char *))
+{
+       struct ifnet ifnet;
+       union {
+               struct ifaddr ifa;
+               struct in_ifaddr in;
+#ifdef INET6
+               struct in6_ifaddr in6;
+#endif /* INET6 */
+               struct iso_ifaddr iso;
+       } ifaddr;
+       u_long ifaddraddr;
+       struct ifnet_head ifhead;       /* TAILQ_HEAD */
+       char name[IFNAMSIZ + 1];        /* + 1 for `*' */
+
+       if (ifnetaddr == 0) {
+               printf("ifnet: symbol not defined\n");
+               return;
+       }
+
+       /*
+        * Find the pointer to the first ifnet structure.  Replace
+        * the pointer to the TAILQ_HEAD with the actual pointer
+        * to the first list element.
+        */
+       if (kread(ifnetaddr, (char *)&ifhead, sizeof ifhead))
+               return;
+       ifnetaddr = (u_long)ifhead.tqh_first;
+
+       intpr_header();
+
        ifaddraddr = 0;
        while (ifnetaddr || ifaddraddr) {
-               struct sockaddr_in *sin;
-#ifdef INET6
-               struct sockaddr_in6 *sin6;
-#endif /* INET6 */
                char *cp;
-               int n, m;
+               int n;
 
                if (ifaddraddr == 0) {
                        if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
@@ -172,8 +308,8 @@
                        printf("%-13.13s ", "none");
                        printf("%-17.17s ", "none");
                } else {
-                       char hexsep = '.';              /* for hexprint */
-                       static const char hexfmt[] = "%02x%c";  /* for hexprint */
+                       struct sockaddr *sa;
+
                        if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
                                ifaddraddr = 0;
                                continue;
@@ -182,215 +318,363 @@
                        cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
                            CP(&ifaddr);
                        sa = (struct sockaddr *)cp;
-                       switch (sa->sa_family) {
-                       case AF_UNSPEC:
-                               printf("%-13.13s ", "none");
-                               printf("%-17.17s ", "none");
-                               break;
-                       case AF_INET:
-                               sin = (struct sockaddr_in *)sa;
+                       print_addr(sa, (void *)&ifaddr, &ifnet.if_data);
+               }
+               ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next;
+       }



Home | Main Index | Thread Index | Old Index