Пример #1
0
/*
 * Print a description of the network interfaces.
 * NOTE: ifnetaddr is the location of the kernel global "ifnet",
 * which is a TAILQ_HEAD.
 */
void
intpr(int interval, int repeatcount)
{
	struct if_msghdr ifm;
	int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
	char name[IFNAMSIZ + 1];	/* + 1 for the '*' */
	char *buf, *next, *lim, *cp;
	struct rt_msghdr *rtm;
	struct ifa_msghdr *ifam;
	struct if_data *ifd;
	struct sockaddr *sa, *rti_info[RTAX_MAX];
	struct sockaddr_dl *sdl;
	u_int64_t total = 0;
	size_t len;

	if (interval) {
		sidewaysintpr((unsigned)interval, repeatcount);
		return;
	}

	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");

	printf("%-7.7s %-5.5s %-11.11s %-17.17s ",
	    "Name", "Mtu", "Network", "Address");
	if (bflag)
		printf("%10.10s %10.10s", "Ibytes", "Obytes");
	else
		printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
		    "Ipkts", "Ierrs", "Opkts", "Oerrs", "Colls");
	if (tflag)
		printf(" %s", "Time");
	if (dflag)
		printf(" %s", "Drop");
	putchar('\n');

	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;
			bcopy(next, &ifm, sizeof ifm);
			ifd = &ifm.ifm_data;

			sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
			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 ifnet.if_timer;
				if (dflag)
					total += 0; // XXX ifnet.if_snd.ifq_drops;
				if (total == 0)
					continue;
			}

			printf("%-7s %-5d ", 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 *)(next + rtm->rtm_hdrlen);
			get_rtaddrs(ifam->ifam_addrs, sa, rti_info);

			printf("%-7s %-5d ", name, ifd->ifi_mtu);
			print_addr(rti_info[RTAX_IFA], rti_info, ifd);
			break;
		}
	}
	free(buf);
}
Пример #2
0
/*
 * Print a description of the network interfaces.
 */
void
intpro(int interval)
{
	oid varname[MAX_OID_LEN], *instance, *ifentry;
	size_t varname_len;
	int ifnum, cfg_nnets;
	oid curifip [4];
	struct variable_list *var;
	struct snmp_pdu *request, *response;
	int status;
	int ifindex, oldindex = 0;
	struct _if_info {
	    int ifindex;
	    char name[128];
	    char ip[128], route[128];
	    char ioctets[20], ierrs[20], ooctets[20], oerrs[20], outqueue[20];
	    int operstatus;
	    u_long netmask;
	    struct in_addr ifip, ifroute;
	} *if_table, *cur_if;
	int max_name = 4, max_route = 7, max_ip = 7, max_ioctets = 7, max_ooctets = 7;
	int i;

	if (interval) {
		sidewaysintpr((unsigned)interval);
		return;
	}
	var = getvarbyname(Session, oid_cfg_nnets, sizeof(oid_cfg_nnets) / sizeof(oid));
	if (var && var->val.integer) {
	    cfg_nnets = *var->val.integer;
	    snmp_free_var(var);
	}
	else {
	    fprintf (stderr, "No response when requesting number of interfaces.\n");
	    return;
	}
	DEBUGMSGTL (("netstat:if", "cfg_nnets = %d\n", cfg_nnets));

	memset (curifip, 0, sizeof (curifip));
	if_table = (struct _if_info *) calloc (cfg_nnets, sizeof (*if_table));
	cur_if = if_table;

	for (ifnum = 1; ifnum <= cfg_nnets; ifnum++) {
		register char *cp;

		request = snmp_pdu_create (SNMP_MSG_GETNEXT);
		memmove (varname, oid_ipadentaddr, sizeof (oid_ipadentaddr));
		varname_len = sizeof (oid_ipadentaddr) / sizeof (oid);
		instance = varname + 9;
		memmove (varname + 10, curifip, sizeof (curifip));
		*instance = IPIFINDEX;
		snmp_add_null_var (request, varname, varname_len);
		*instance = IPADDR;
		snmp_add_null_var (request, varname, varname_len);
		*instance = IPNETMASK;
		snmp_add_null_var (request, varname, varname_len);

		status = snmp_synch_response (Session, request, &response);
		if (status != STAT_SUCCESS || response->errstat != SNMP_ERR_NOERROR) {
		    fprintf (stderr, "SNMP request failed for interface %d, variable %ld out of %d interfaces (IP)\n", ifnum, response->errindex, cfg_nnets);
		    cfg_nnets = ifnum;
		    break;
		}
		for (var = response->variables; var; var = var->next_variable) {
                  if (snmp_get_do_debugging()) {
		    print_variable (var->name, var->name_length, var);
                  }
		    switch (var->name [9]) {
		    case IPIFINDEX:
			ifindex = *var->val.integer;
			for (cur_if = if_table; cur_if->ifindex != ifindex && cur_if->ifindex != 0; cur_if++);
			cur_if->ifindex = ifindex;
			break;
		    case IPADDR:
			memmove (curifip, var->name+10, sizeof (curifip));
			memmove (&cur_if->ifip, var->val.string, sizeof (u_long));
			break;
		    case IPNETMASK:
			memmove (&cur_if->netmask, var->val.string, sizeof (u_long));
		    }
		}
		cur_if->ifroute.s_addr = cur_if->ifip.s_addr & cur_if->netmask;
		if (cur_if->ifroute.s_addr)
			strcpy(cur_if->route, netname (cur_if->ifroute, cur_if->netmask));
		else strcpy(cur_if->route, "none");
		if ((i = strlen(cur_if->route)) > max_route) max_route = i;
		if (cur_if->ifip.s_addr)
			strcpy(cur_if->ip, routename (cur_if->ifip));
		else strcpy(cur_if->ip, "none");
		if ((i = strlen(cur_if->ip)) > max_ip) max_ip = i;

		snmp_free_pdu (response);

		memmove (varname, oid_ifname, sizeof(oid_ifname));
		varname_len = sizeof(oid_ifname) / sizeof(oid);
		ifentry = varname + 9;
		instance = varname + 10;
		request = snmp_pdu_create (SNMP_MSG_GETNEXT);

		*instance = oldindex;
		*ifentry = IFINDEX;
		snmp_add_null_var (request, varname, varname_len);
		*ifentry = IFNAME;
		snmp_add_null_var (request, varname, varname_len);
		*ifentry = IFOPERSTATUS;
		snmp_add_null_var (request, varname, varname_len);
		*ifentry = INOCTETS;
		snmp_add_null_var (request, varname, varname_len);
		*ifentry = OUTOCTETS;
		snmp_add_null_var (request, varname, varname_len);

		while ((status = snmp_synch_response (Session, request, &response)) == STAT_SUCCESS) {
		    if (response->errstat != SNMP_ERR_NOSUCHNAME)
			break;
		    if ((request = snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) == NULL)
			break;
		    snmp_free_pdu(response);
		}
		if (status != STAT_SUCCESS || response->errstat != SNMP_ERR_NOERROR) {
		    fprintf (stderr, "SNMP request failed for interface %d, variable %ld out of %d interfaces (IF)\n", ifnum, response->errindex, cfg_nnets);
		    cfg_nnets = ifnum;
		    break;
		}
		for (var = response->variables; var; var = var->next_variable) {
		    if (snmp_get_do_debugging()) {
			print_variable (var->name, var->name_length, var);
		    }
		    if (!var->val.integer) continue;
		    switch (var->name [9]) {
		    case IFINDEX:
			ifindex = *var->val.integer;
			for (cur_if = if_table; cur_if->ifindex != ifindex && cur_if->ifindex != 0; cur_if++);
			cur_if->ifindex = ifindex;
			break;
		    case INOCTETS:
			sprintf(cur_if->ioctets, "%lu",  *var->val.integer);
			i = strlen(cur_if->ioctets);
			if (i > max_ioctets) max_ioctets = i;
			break;
		    case OUTOCTETS:
			sprintf(cur_if->ooctets, "%lu",  *var->val.integer);
			i = strlen(cur_if->ooctets);
			if (i > max_ooctets) max_ooctets = i;
			break;
		    case IFNAME:
			oldindex = var->name[10];
			if (var->val_len >= sizeof(cur_if->name))
			    var->val_len = sizeof(cur_if->name) - 1;
			memmove (cur_if->name, var->val.string, var->val_len);
			cur_if->name [var->val_len] = 0;
			if ((i = strlen(cur_if->name)+1) > max_name) max_name = i;
			break;
		    case IFOPERSTATUS:
			cur_if->operstatus = *var->val.integer; break;
		    }
		}

		snmp_free_pdu (response);

		if (intrface != NULL && strcmp(cur_if->name, intrface) != 0) {
			cur_if->name [0] = 0;
			continue;
		}
		if (cur_if->operstatus != MIB_IFSTATUS_UP) {
			cp = strchr(cur_if->name, '\0');
			*cp++ = '*';
			*cp = '\0';
		}
	}

	printf("%*.*s %*.*s %*.*s %*.*s %*.*s ",
		-max_name, max_name, "Name",
		-max_route, max_route, "Network",
		-max_ip, max_ip, "Address",
		max_ioctets, max_ioctets, "Ioctets",
		max_ooctets, max_ooctets, "Ooctets");
	putchar('\n');
	for (ifnum = 0, cur_if = if_table; ifnum < cfg_nnets; ifnum++, cur_if++) {
		if (cur_if->name [0] == 0) continue;
		printf("%*.*s ", -max_name, max_name, cur_if->name);
		printf("%*.*s ", -max_route, max_route, cur_if->route);
		printf("%*.*s ", -max_ip, max_ip, cur_if->ip);
		printf("%*s %*s", max_ioctets, cur_if->ioctets,
		    max_ioctets, cur_if->ooctets);
		putchar('\n');
	}
	free(if_table);
}
Пример #3
0
int
main(int argc, char **argv)
{
	u_int interval;
	int clientOnly = -1;
	int serverOnly = -1;
	int ch;
	char *memf, *nlistf;
	char errbuf[_POSIX2_LINE_MAX];

	interval = 0;
	memf = nlistf = NULL;
	while ((ch = getopt(argc, argv, "csWM:N:w:")) != -1)
		switch(ch) {
		case 'M':
			memf = optarg;
			break;
		case 'N':
			nlistf = optarg;
			break;
		case 'W':
			widemode = 1;
			break;
		case 'w':
			interval = atoi(optarg);
			break;
		case 'c':
			clientOnly = 1;
			if (serverOnly < 0)
				serverOnly = 0;
			break;
		case 's':
			serverOnly = 1;
			if (clientOnly < 0)
				clientOnly = 0;
			break;
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

#define	BACKWARD_COMPATIBILITY
#ifdef	BACKWARD_COMPATIBILITY
	if (*argv) {
		interval = atoi(*argv);
		if (*++argv) {
			nlistf = *argv;
			if (*++argv)
				memf = *argv;
		}
	}
#endif
	if (nlistf != NULL || memf != NULL) {
		deadkernel = 1;

		if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY,
					errbuf)) == NULL) {
			errx(1, "kvm_openfiles: %s", errbuf);
		}
		if (kvm_nlist(kd, nl) != 0) {
			errx(1, "kvm_nlist: can't get names");
		}
	}

	if (interval)
		sidewaysintpr(interval, clientOnly, serverOnly);
	else
		intpr(clientOnly, serverOnly);
	exit(0);
}
Пример #4
0
int
main(int argc, char **argv)
{
	u_int interval;
	int clientOnly = -1;
	int serverOnly = -1;
	int ch;
	char *memf, *nlistf;
	char errbuf[_POSIX2_LINE_MAX];

	interval = 0;
	memf = nlistf = NULL;
	while ((ch = getopt(argc, argv, "cesWM:N:ow:z")) != -1)
		switch(ch) {
		case 'M':
			memf = optarg;
			break;
		case 'N':
			nlistf = optarg;
			break;
		case 'W':
			widemode = 1;
			break;
		case 'w':
			interval = atoi(optarg);
			break;
		case 'c':
			clientOnly = 1;
			if (serverOnly < 0)
				serverOnly = 0;
			break;
		case 's':
			serverOnly = 1;
			if (clientOnly < 0)
				clientOnly = 0;
			break;
		case 'z':
			zflag = 1;
			break;
		case 'o':
			if (extra_output != 0)
				err(1, "-o incompatible with -e");
			run_v4 = 0;
			break;
		case 'e':
			if (run_v4 == 0)
				err(1, "-e incompatible with -o");
			extra_output = 1;
			break;
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

#define	BACKWARD_COMPATIBILITY
#ifdef	BACKWARD_COMPATIBILITY
	if (*argv) {
		interval = atoi(*argv);
		if (*++argv) {
			nlistf = *argv;
			if (*++argv)
				memf = *argv;
		}
	}
#endif
	if (run_v4 != 0 && modfind("nfscommon") < 0)
		errx(1, "new client/server not loaded");

	if (run_v4 == 0 && (nlistf != NULL || memf != NULL)) {
		deadkernel = 1;

		if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY,
					errbuf)) == 0) {
			errx(1, "kvm_openfiles: %s", errbuf);
		}
		if (kvm_nlist(kd, nl) != 0) {
			errx(1, "kvm_nlist: can't get names");
		}
	}

	if (interval) {
		if (run_v4 > 0)
			exp_sidewaysintpr(interval, clientOnly, serverOnly);
		else
			sidewaysintpr(interval, clientOnly, serverOnly);
	} else {
		if (extra_output != 0)
			exp_intpr(clientOnly, serverOnly);
		else
			intpr(clientOnly, serverOnly);
	}
	exit(0);
}
Пример #5
0
/*
 * Print a description of the network interfaces.
 */
void
intpr(int interval)
{
    oid    ifcol_oid[]  = { 1,3,6,1,2,1,2,2,1,0 };
    size_t ifcol_len    = OID_LENGTH( ifcol_oid );

    struct _if_info *if_head, *if_tail, *cur_if;
    netsnmp_variable_list *var, *vp;
           /*
            * Track maximum field widths, expanding as necessary
            *   This is one reason why results can't be
            *   displayed immediately they are retrieved.
            */
    int    max_name  = 4, max_ip    = 7, max_route = 7, max_outq  = 5;
    int    max_ipkts = 5, max_ierrs = 5, max_opkts = 5, max_oerrs = 5;
    int    max_ibytes = 6, max_obytes = 6;
    int    i;


    if (interval) {
        sidewaysintpr((unsigned)interval);
        return;
    }

        /*
         * The traditional "netstat -i" output combines information
         *   from two SNMP tables:
         *      ipAddrTable   (for the IP address/network)
         *      ifTable       (for the interface statistics)
         *
         * The previous approach was to retrieve (and save) the
         *   address information first. Then walk the main ifTable,
         *   add the relevant stored addresses, and saving the
         *   full information for each interface, before displaying 
         *   the results as a separate pass.
         *
         * This code reverses this general structure, by first retrieving
         *   (and storing) the interface statistics for the whole table,
         *   then inserting the address information obtained from the
         *   ipAddrTable, and finally displaying the results.
         * Such an arrangement should make it easier to extend this
         *   to handle non-IP interfaces (hence not in ipAddrTable)
         */
    if_head = NULL;
    if_tail = NULL;
    var     = NULL;

#define ADD_IFVAR( x ) ifcol_oid[ ifcol_len-1 ] = x; \
    snmp_varlist_add_variable( &var, ifcol_oid, ifcol_len, ASN_NULL, NULL,  0)
    ADD_IFVAR( 2 );                 /* ifName  */
    ADD_IFVAR( 4 );                 /* ifMtu   */
    ADD_IFVAR( 8 );                 /* ifOperStatus */
    /*
     * The Net/Open-BSD behaviour is to display *either* byte
     *   counts *or* packet/error counts (but not both). FreeBSD
     *   integrates the byte counts into the traditional display.
     *
     * The previous 'snmpnetstat' implementation followed the
     *   separatist model.  This re-write offers an opportunity
     *   to adopt the (more useful, IMO) Free-BSD approach.
     *
     * Or we could perhaps support both styles? :-)
     */
    if (bflag || oflag) {
        ADD_IFVAR( 10 );            /* ifInOctets   */
        ADD_IFVAR( 16 );            /* ifOutOctets  */
    }
    if (!oflag) {
        ADD_IFVAR( 11 );            /* ifInUcastPkts  */
        ADD_IFVAR( 12 );            /* ifInNUcastPkts */
        ADD_IFVAR( 14 );            /* ifInErrors     */
        ADD_IFVAR( 17 );            /* ifOutUcastPkts */
        ADD_IFVAR( 18 );            /* ifOutNUcastPkts */
        ADD_IFVAR( 20 );            /* ifOutErrors    */
        ADD_IFVAR( 21 );            /* ifOutQLen      */
    }
#if 0
    if (tflag) {
        ADD_IFVAR( XX );            /* ??? */
    }
#endif
    if (dflag) {
        ADD_IFVAR( 19 );            /* ifOutDiscards  */
    }
#undef ADD_IFVAR

        /*
	 * Now walk the ifTable, creating a list of interfaces
	 */
    while ( 1 ) {
        if (netsnmp_query_getnext( var, ss ) != SNMP_ERR_NOERROR)
            break;
        ifcol_oid[ ifcol_len-1 ] = 2;	/* ifDescr */
        if ( snmp_oid_compare( ifcol_oid, ifcol_len,
                               var->name, ifcol_len) != 0 )
            break;    /* End of Table */
        cur_if = SNMP_MALLOC_TYPEDEF( struct _if_info );
        if (!cur_if)
            break;
        cur_if->ifindex = var->name[ var->name_length-1 ];
        for ( vp=var; vp; vp=vp->next_variable ) {
            if ( ! vp->val.integer )
                continue;
            if ( var->name[ var->name_length-1 ] != cur_if->ifindex ) {
                /*
                 * Inconsistent index information
                 * XXX - Try to recover ?
                 */
                SNMP_FREE( cur_if );
                cur_if = NULL;
                break;    /* not for now, no */
            }
            switch ( vp->name[ var->name_length-2 ] ) {
            case 2:     /* ifDescr */
                if (vp->val_len >= sizeof(cur_if->name))
                    vp->val_len  = sizeof(cur_if->name)-1;
                memmove( cur_if->name, vp->val.string, vp->val_len );
                cur_if->name[vp->val_len] = 0;
                if ((i = strlen(cur_if->name) + 1) > max_name)
                    max_name = i;
                break;
            case 4:     /* ifMtu   */
                cur_if->mtu = *vp->val.integer;
                break;
            case 8:     /* ifOperStatus   */
                cur_if->operstatus = *vp->val.integer;
                /* XXX - any special processing ?? */
                break;
            case 10:	/* ifInOctets     */
                sprintf(cur_if->s_ibytes, "%lu", *vp->val.integer);
                i = strlen(cur_if->s_ibytes);
                if (i > max_ibytes)
                    max_ibytes = i;
                break;
            case 11:	/* ifInUcastPkts  */
                cur_if->ipkts += *vp->val.integer;
                sprintf(cur_if->s_ipkts, "%lu", cur_if->ipkts);
                i = strlen(cur_if->s_ipkts);
                if (i > max_ipkts)
                    max_ipkts = i;
                break;
            case 12:	/* ifInNUcastPkts  */
                cur_if->ipkts += *vp->val.integer;
                sprintf(cur_if->s_ipkts, "%lu", cur_if->ipkts);
                i = strlen(cur_if->s_ipkts);
                if (i > max_ipkts)
                    max_ipkts = i;
                break;
            case 14:	/* ifInErrors      */
                sprintf(cur_if->s_ierrs, "%lu", *vp->val.integer);
                i = strlen(cur_if->s_ierrs);
                if (i > max_ierrs)
                    max_ierrs = i;
                break;
            case 16:	/* ifOutOctets      */
                sprintf(cur_if->s_obytes, "%lu", *vp->val.integer);
                i = strlen(cur_if->s_obytes);
                if (i > max_obytes)
                    max_obytes = i;
                break;
            case 17:	/* ifOutUcastPkts */
                cur_if->opkts += *vp->val.integer;
                sprintf(cur_if->s_opkts, "%lu", cur_if->opkts);
                i = strlen(cur_if->s_opkts);
                if (i > max_opkts)
                    max_opkts = i;
                break;
            case 18:	/* ifOutNUcastPkts */
                cur_if->opkts += *vp->val.integer;
                sprintf(cur_if->s_opkts, "%lu", cur_if->opkts);
                i = strlen(cur_if->s_opkts);
                if (i > max_opkts)
                    max_opkts = i;
                break;
            case 19:    /* ifOutDiscards   */
                cur_if->drops = *vp->val.integer;
                break;
            case 20:	/* ifOutErrors     */
                sprintf(cur_if->s_oerrs, "%lu", *vp->val.integer);
                i = strlen(cur_if->s_oerrs);
                if (i > max_oerrs)
                    max_oerrs = i;
                break;
            case 21:	/* ifOutQLen       */
                sprintf(cur_if->s_outq, "%lu", *vp->val.integer);
                i = strlen(cur_if->s_outq);
                if (i > max_outq)
                    max_outq = i;
                break;
            }
        }

        /*
         *  XXX - Perhaps query ifXTable for additional info ??
         *    (ifName/ifAlias, or HC counters)
         */

        /*
         * If we're to monitor a particular interface, then
         *   ignore all others.  It would be more efficient
         *   to check this earlier (as part of processing 
         *   the varbind list).  But performing this test here
         *   means we can recognise ifXTable names as well)
         */
        if ( intrface && strcmp( cur_if->name, intrface ) != 0) {
            SNMP_FREE( cur_if );
            cur_if = NULL;
        }

        /*
         * Insert the IP address and network settings, and
         *   add the new _if_stat structure to the list.
         */
        if ( cur_if ) {
            _set_address( cur_if );
            i = strlen(cur_if->ip);
            if (i > max_ip)
                max_ip = i;
            i = strlen(cur_if->route);
            if (i > max_route)
                max_route = i;

            if ( if_tail ) {
                if_tail->next = cur_if;
                if_tail       = cur_if;
            } else {
                if_head       = cur_if;
                if_tail       = cur_if;
            }
        }
    }   /* while (1) */

        /*
         * Now display the specified results (in Free-BSD format)
         *   setting the field widths appropriately....
         */
    printf("%*.*s %5.5s %*.*s %*.*s",
           -max_name,  max_name,  "Name", "Mtu",
           -max_route, max_route, "Network",
           -max_ip,    max_ip,    "Address");
    if (oflag) {
        printf(" %*s %*s", max_ibytes,  "Ibytes",
                           max_obytes,  "Obytes");
    } else {
        printf(" %*s %*s", max_ipkts,   "Ipkts",
                           max_ierrs,   "Ierrs");
        if (bflag) 
            printf(" %*s", max_ibytes,  "Ibytes");

        printf(" %*s %*s", max_opkts,   "Opkts",
                           max_oerrs,   "Oerrs");
        if (bflag) 
            printf(" %*s", max_obytes,  "Obytes");

        printf(" %*s",     max_outq,    "Queue");
    }
 /* if (tflag)
        printf(" %s", "Time");
  */
    if (dflag)
        printf(" %s", "Drop");
    putchar('\n');

    for (cur_if = if_head; cur_if; cur_if=cur_if->next) {
        if (cur_if->name[0] == 0)
            continue;
        printf( "%*.*s %5d", -max_name,  max_name,  cur_if->name, cur_if->mtu);
        printf(" %*.*s",     -max_route, max_route, cur_if->route);
        printf(" %*.*s",     -max_ip,    max_ip,    cur_if->ip);

        if (oflag) {
            printf(" %*s %*s", max_ibytes,  cur_if->s_ibytes,
                               max_obytes,  cur_if->s_obytes);
        } else {
            printf(" %*s %*s", max_ipkts,   cur_if->s_ipkts,
                               max_ierrs,   cur_if->s_ierrs);
            if (bflag) 
                printf(" %*s", max_ibytes,  cur_if->s_ibytes);
    
            printf(" %*s %*s", max_opkts,   cur_if->s_opkts,
                               max_oerrs,   cur_if->s_oerrs);
            if (bflag) 
                printf(" %*s", max_obytes,  cur_if->s_obytes);
            printf(" %*s",     max_outq,    cur_if->s_outq);
        }
     /* if (tflag)
            printf(" %4d", cur_if->???);
      */
        if (dflag)
            printf(" %4d", cur_if->drops);
        putchar('\n');
    }

        /*
         * ... and tidy up.
         */
    for (cur_if = if_head; cur_if; cur_if=if_head) {
        if_head=cur_if->next;
        cur_if->next = NULL;
        SNMP_FREE( cur_if );
    }
}