📄 drivers.c
字号:
O_RDONLY, data->errbuf)) == NULL) { ifstat_error("kvm_openfiles: %s", data->errbuf); return 0; } memset(&kvm_syms, 0, sizeof(kvm_syms)); kvm_syms[0].n_name = "_ifnet"; if (kvm_nlist(data->kvmfd, kvm_syms) < 0 || kvm_syms[0].n_value == 0) { kvm_syms[0].n_name = "ifnet"; if (kvm_nlist(data->kvmfd, kvm_syms) < 0) { ifstat_error("kvm_nlist: %s", data->errbuf); return 0; } } if (kvm_syms[0].n_value == 0) { ifstat_error("kvm: no _ifnet or ifnet symbol found"); return 0; } if (kvm_read(data->kvmfd, (unsigned long) kvm_syms[0].n_value, &ifnetaddr, sizeof(ifnetaddr)) < 0) { ifstat_error("kvm_read(ifnetaddr): %s", data->errbuf); return 0; } if (ifnetaddr == 0) { ifstat_error("kvm: ifnetaddr has null address."); return 0; } data->ifnetaddr = ifnetaddr; driver->data = (void *) data; return 1;}#ifdef HAVE_IFNET_IF_NEXT#define IFNET_NEXT(ifnet) (ifnet).if_next#else#ifdef HAVE_IFNET_IF_LINK#define if_list if_link#endif#ifndef TAILQ_NEXT#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)#endif#define IFNET_NEXT(ifnet) TAILQ_NEXT((&ifnet), if_list)#endifstatic int kvm_map_ifs(struct ifstat_driver *driver, int (*mapf)(char *name, struct ifnet *ifnet, void *data), void *mdata) { struct kvm_driver_data *data = driver->data; unsigned long ifaddr; struct ifnet ifnet;#ifndef HAVE_IFNET_IF_XNAME char ifname[IFNAMSIZ + 1];#endif char interface[IFNAMSIZ + 10]; for (ifaddr = data->ifnetaddr; ifaddr != 0; ifaddr = (unsigned long) IFNET_NEXT(ifnet)) { if (kvm_read(data->kvmfd, ifaddr, &ifnet, sizeof(ifnet)) < 0) { ifstat_error("kvm_read: %s", data->errbuf); return 0; }#ifdef HAVE_IFNET_IF_XNAME memcpy(interface, ifnet.if_xname, sizeof(interface)); interface[sizeof(interface) - 1] = '\0';#else if (kvm_read(data->kvmfd, (unsigned long) ifnet.if_name, &ifname, sizeof(ifname)) < 0) { ifstat_error("kvm_read: %s", data->errbuf); return 0; } ifname[sizeof(ifname) - 1] = '\0'; sprintf(interface, "%s%d", ifname, ifnet.if_unit);#endif if (!mapf(interface, &ifnet, mdata)) return 0; } return 1;}static int kvm_map_stats(char *name, struct ifnet *ifnet, void *data) { struct ifstat_data *cur; if ((cur = ifstat_get_interface((struct ifstat_list *) data, name)) == NULL) return 1; ifstat_set_interface_stats(cur, ifnet->if_ibytes, ifnet->if_obytes); return 1;}static int kvm_get_stats(struct ifstat_driver *driver, struct ifstat_list *ifs) { return kvm_map_ifs(driver, &kvm_map_stats, (void *) ifs);}static int kvm_map_scan(char *name, struct ifnet *ifnet, void *data) { examine_interface((struct ifstat_list *) data, name, ifnet->if_flags, ifnet->if_type); return 1;}static int kvm_scan_interfaces(struct ifstat_driver *driver, struct ifstat_list *ifs) { return kvm_map_ifs(driver, &kvm_map_scan, (void *) ifs);} static void kvm_close_driver(struct ifstat_driver *driver) { kvm_close(((struct kvm_driver_data *) driver->data)->kvmfd);}#endif#ifdef USE_IFMIBstatic int get_ifcount() { int ifcount[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM, IFMIB_IFCOUNT }; int count, size; size = sizeof(count); if (sysctl(ifcount, sizeof(ifcount) / sizeof(int), &count, &size, NULL, 0) < 0) { ifstat_perror("sysctl(net.link.generic.ifmib.ifcount)"); return -1; } return count;}static int get_ifdata(int index, struct ifmibdata * ifmd) { int ifinfo[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, index, IFDATA_GENERAL }; int size = sizeof(*ifmd); if (sysctl(ifinfo, sizeof(ifinfo) / sizeof(int), ifmd, &size, NULL, 0) < 0) return 0; return 1;}static int ifmib_scan_interfaces(struct ifstat_driver *driver, struct ifstat_list *ifs) { int count, i; struct ifmibdata ifmd; if ((count = get_ifcount()) <= 0) return 0; for (i = 1; i <= count; i++) { if (!get_ifdata(i, &ifmd)) continue; examine_interface(ifs, ifmd.ifmd_name, ifmd.ifmd_flags, ifmd.ifmd_data.ifi_type); } return 1;}static int ifmib_get_stats(struct ifstat_driver *driver, struct ifstat_list *ifs) { int count, i; struct ifmibdata ifmd; struct ifstat_data *cur; if (ifs->flags & IFSTAT_HASINDEX) { /* poll by index */ for (cur = ifs->first; cur != NULL; cur = cur->next) { i = ifstat_get_interface_index(cur); if (i < 0 || !get_ifdata(i, &ifmd)) continue; if (strcmp(ifstat_get_interface_name(cur), ifmd.ifmd_name)) continue; ifstat_set_interface_stats(cur, ifmd.ifmd_data.ifi_ibytes, ifmd.ifmd_data.ifi_obytes); ifstat_set_interface_index(cur, i); } return 1; } if ((count = get_ifcount()) <= 0) return 0; for (i = 1; i <= count; i++) { if (!get_ifdata(i, &ifmd)) continue; if ((cur = ifstat_get_interface(ifs, ifmd.ifmd_name)) == NULL) continue; ifstat_set_interface_stats(cur, ifmd.ifmd_data.ifi_ibytes, ifmd.ifmd_data.ifi_obytes); ifstat_set_interface_index(cur, i); } return 1;}#endif#ifdef USE_IFDATAstruct ifdata_driver_data { int sd;#ifdef HAVE_IFREQ_IFR_DATA struct if_data ifd;#else struct ifdatareq ifd;#endif };static int ifdata_open_driver(struct ifstat_driver *driver, char *options) { struct ifdata_driver_data *data; if ((data = malloc(sizeof(struct ifdata_driver_data))) == NULL) { ifstat_perror("malloc"); return 0; } if ((data->sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ifstat_perror("socket"); free(data); return 0; } driver->data = (void *) data; return 1;}static struct if_data *ifdata_get_data(struct ifdata_driver_data *data, char *name) {#ifdef HAVE_IFREQ_IFR_DATA struct ifreq ifr; strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); ifr.ifr_data = (caddr_t) &(data->ifd); if (ioctl(data->sd, SIOCGIFDATA, (char *) &ifr) < 0) return NULL; return &(data->ifd);#else strncpy(data->ifd.ifd_name, name, sizeof(data->ifd.ifd_name)); if (ioctl(data->sd, SIOCGIFDATA, (char *) &(data->ifd)) < 0) return NULL; return &(data->ifd.ifd_ifd);#endif}struct ifdata_scan_data { struct ifstat_list *ifs; struct ifdata_driver_data *data;};static int ifdata_map_scan(int sd, struct ifreq *ifr, void *pdata) { struct ifdata_scan_data *sdata = pdata; struct if_data *ifd; if (ioctl(sd, SIOCGIFFLAGS, (char *)ifr) != 0) return 1; if ((ifd = ifdata_get_data(sdata->data, ifr->ifr_name)) == NULL) return 1; examine_interface(sdata->ifs, ifr->ifr_name, ifr->ifr_flags, ifd->ifi_type); return 1;}static int ifdata_scan_interfaces(struct ifstat_driver *driver, struct ifstat_list *ifs) { struct ifdata_driver_data *data = driver->data; struct ifdata_scan_data sdata = { ifs, data }; return ioctl_map_ifs(data->sd, &ifdata_map_scan, &sdata);} static int ifdata_get_stats(struct ifstat_driver *driver, struct ifstat_list *ifs) { struct ifdata_driver_data *data = driver->data; struct if_data *ifd; struct ifstat_data *cur; for (cur = ifs->first; cur != NULL; cur = cur->next) { if (cur->flags & IFSTAT_TOTAL) continue; if ((ifd = ifdata_get_data(data, cur->name)) != NULL) ifstat_set_interface_stats(cur, ifd->ifi_ibytes, ifd->ifi_obytes); } return 1;}static void ifdata_close_driver(struct ifstat_driver *driver) { struct ifdata_driver_data *data = driver->data; if (data->sd >= 0) close(data->sd); free(data);}#endif#ifdef USE_PROCstruct proc_driver_data { char *file; int checked;};static int proc_open_driver(struct ifstat_driver *driver, char *options) { struct proc_driver_data *data; if ((data = malloc(sizeof(struct proc_driver_data))) == NULL) { ifstat_perror("malloc"); return 0; } data->file = (options != NULL) ? strdup(options) : NULL; data->checked = 0; driver->data = (void *) data; return 1;}static void proc_close_driver(struct ifstat_driver *driver) { struct proc_driver_data *data = driver->data; if (data->file != NULL) free(data->file); free(data);}static int proc_get_stats(struct ifstat_driver *driver, struct ifstat_list *ifs) { char buf[1024]; FILE *f; char *iface, *stats; unsigned long bytesin, bytesout; struct ifstat_data *cur; struct proc_driver_data *data = driver->data; char *file; if (data->file != NULL) file = data->file; else file = PROC_FILE; if ((f = fopen(file, "r")) == NULL) { ifstat_error("can't open %s: %s", file, strerror(errno)); return 0; } /* check first lines */ if (fgets(buf, sizeof(buf), f) == NULL) goto badproc; if (!data->checked && strncmp(buf, "Inter-|", 7)) goto badproc; if (fgets(buf, sizeof(buf), f) == NULL) goto badproc; if (!data->checked) { if (strncmp(buf, " face |by", 9)) goto badproc; data->checked = 1; } while (fgets(buf, sizeof(buf), f) != NULL) { if ((stats = strchr(buf, ':')) == NULL) continue; *stats++ = '\0'; iface = buf; while (*iface == ' ') iface++; if (*iface == '\0') continue; if (sscanf(stats, "%lu %*u %*u %*u %*u %*u %*u %*u %lu %*u", &bytesin, &bytesout) != 2) continue; if ((cur = ifstat_get_interface(ifs, iface)) != NULL) ifstat_set_interface_stats(cur, bytesin, bytesout); } fclose(f); return 1; badproc: fclose(f); ifstat_error("%s: unsupported format.", file); return 0;}#endif#ifdef USE_ROUTEstruct route_driver_data { char *buf; size_t size;};#define DEFAULT_SIZE 16384static int route_open_driver(struct ifstat_driver *driver, char *options) { struct route_driver_data *data; if ((data = malloc(sizeof(struct route_driver_data))) == NULL) { ifstat_perror("malloc"); return 0; } if ((data->buf = malloc(DEFAULT_SIZE)) < 0) { ifstat_perror("malloc"); free(data); return 0; } data->size = DEFAULT_SIZE; driver->data = (void *) data; return 1;}static int route_map_ifs(struct ifstat_driver *driver, int (*mapf)(char *name, struct if_msghdr *ifmsg, void *data), void *mdata) { struct route_driver_data *data = driver->data; int iflist[] = { CTL_NET, PF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }; struct if_msghdr *ifm; struct sockaddr_dl *dl; char *ptr; char ifname[IFNAMSIZ + 1]; size_t len; if (data->size != 0) { /* try with current buf size */ len = data->size; if (sysctl(iflist, sizeof(iflist) / sizeof(int), data->buf, &len, NULL, 0) < 0) { if (errno != ENOMEM) { ifstat_perror("sysctl"); return 0; } /* buffer too small */ free (data->buf); data->size = 0; } } if (data->size == 0) { /* ask for size */ if (sysctl(iflist, sizeof(iflist) / sizeof(int), NULL, &len, NULL, 0) < 0) { ifstat_perror("sysctl"); return 0; } if ((data->buf = malloc(len)) < 0) { ifstat_perror("malloc"); return 0; } if (sysctl(iflist, sizeof(iflist) / sizeof(int), data->buf, &len, NULL, 0) < 0) { ifstat_perror("sysctl"); return 0; } } /* browse interfaes */ for (ptr = data->buf; ptr < data->buf + len; ptr += ifm->ifm_msglen) { ifm = (struct if_msghdr *) ptr; if (ifm->ifm_type != RTM_IFINFO) continue; if (ifm->ifm_msglen <= sizeof(struct if_msghdr)) /* no address */ continue; dl = (struct sockaddr_dl *) (ptr + sizeof(struct if_msghdr)); if (dl->sdl_family != AF_LINK) continue; if (dl->sdl_nlen > (sizeof(ifname) - 1)) dl->sdl_nlen = sizeof(ifname) - 1; memcpy(ifname, dl->sdl_data, dl->sdl_nlen); ifname[dl->sdl_nlen] = '\0'; if (!mapf(ifname, ifm, mdata)) return 0; } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -