/* * 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); }
/* * 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); }
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); }
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); }
/* * 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 ); } }