📄 drivers.c
字号:
static int route_map_stats(char *name, struct if_msghdr *ifmsg, void *data) { struct ifstat_data *cur; if ((cur = ifstat_get_interface((struct ifstat_list *) data, name)) == NULL) return 1; ifstat_set_interface_stats(cur, ifmsg->ifm_data.ifi_ibytes, ifmsg->ifm_data.ifi_obytes); return 1;}static int route_get_stats(struct ifstat_driver *driver, struct ifstat_list *ifs) { return route_map_ifs(driver, &route_map_stats, ifs);}static int route_map_scan(char *name, struct if_msghdr *ifmsg, void *data) { examine_interface((struct ifstat_list *) data, name, ifmsg->ifm_flags, ifmsg->ifm_data.ifi_type); return 1;}static int route_scan_interfaces(struct ifstat_driver *driver, struct ifstat_list *ifs) { return route_map_ifs(driver, &route_map_scan, (void *) ifs);} static void route_close_driver(struct ifstat_driver *driver) { struct route_driver_data *data = driver->data; if (data->buf != NULL) free(data->buf); free(data);}#endif#ifdef USE_DLPI#define DLPI_DEFBUF_LEN 1024#define DLPI_NO_PPA -1#define DLPI_DEVICE "/dev/dlpi"struct dlpi_driver_data { int fd; unsigned int *buf; int maxlen; int ppa;};static int dlpi_open_driver(struct ifstat_driver *driver, char *options) { struct dlpi_driver_data *dlpi; if ((dlpi = malloc(sizeof(struct dlpi_driver_data))) == NULL) { ifstat_perror("malloc"); return 0; } if ((dlpi->fd = open(options != NULL ? options : DLPI_DEVICE, O_RDWR)) < 0) { ifstat_perror("open"); free(dlpi); return 0; } dlpi->maxlen = DLPI_DEFBUF_LEN; if ((dlpi->buf = malloc(dlpi->maxlen)) == NULL) { ifstat_perror("malloc"); free(dlpi); return 0; } dlpi->ppa = DLPI_NO_PPA; driver->data = (void *) dlpi; return 1;}static int dlpi_req (struct dlpi_driver_data *dlpi, void *req, int reqlen, int ackprim, void **ack, int *acklen) { struct strbuf ctlptr; int len, ret, flags; dl_error_ack_t *err_ack; ctlptr.maxlen = 0; ctlptr.len = reqlen; ctlptr.buf = req; if (putmsg(dlpi->fd, &ctlptr, NULL, 0) < 0) { ifstat_perror("putmsg"); return 0; } ctlptr.maxlen = dlpi->maxlen; ctlptr.buf = (char *) dlpi->buf; ctlptr.len = 0; len = 0; flags = 0; while ((ret = getmsg(dlpi->fd, &ctlptr, NULL, &flags)) == MORECTL) { /* duplicate size of buf */ dlpi->maxlen *= 2; if ((dlpi->buf = realloc(dlpi->buf, dlpi->maxlen)) == NULL) { ifstat_perror("malloc"); return 0; } len += ctlptr.len; ctlptr.buf = (char *) dlpi->buf + len; ctlptr.maxlen = dlpi->maxlen - len; ctlptr.len = 0; } if (ret < 0) { ifstat_perror("getmsg"); return 0; } len += ctlptr.len; err_ack = (dl_error_ack_t *) dlpi->buf; if (err_ack->dl_primitive != ackprim) { if (err_ack->dl_primitive == DL_ERROR_ACK) { errno = err_ack->dl_errno; ifstat_perror("dlpi"); } else { ifstat_error("dlpi: unexpected ack type returned"); } return 0; } if (ack != NULL) *ack = dlpi->buf; if (acklen != NULL) *acklen = len; return 1;}static int dlpi_attach(struct dlpi_driver_data *dlpi, int ppa) { dl_attach_req_t attach_req; dl_detach_req_t dettach_req; /* check if already attached */ if (dlpi->ppa == ppa) return 1; /* else detach */ if (dlpi->ppa != DLPI_NO_PPA) { dettach_req.dl_primitive = DL_DETACH_REQ; if (!dlpi_req(dlpi, &dettach_req, sizeof(dl_detach_req_t), DL_OK_ACK, NULL, NULL)) return 0; dlpi->ppa = DLPI_NO_PPA; if (ppa == DLPI_NO_PPA) return 1; /* we're done */ } /* attach */ attach_req.dl_primitive = DL_ATTACH_REQ; attach_req.dl_ppa = ppa; if (!dlpi_req(dlpi, &attach_req, sizeof(dl_attach_req_t), DL_OK_ACK, NULL, NULL)) return 0; dlpi->ppa = ppa; return 1;}static int dlpi_get_ifmib(struct dlpi_driver_data *dlpi, int ppa, mib_ifEntry *mib) { dl_get_statistics_req_t stats_req; dl_get_statistics_ack_t *stats_ack; int len; /* first attach to PPA */ if (!dlpi_attach(dlpi, ppa)) return 0; /* grab stats */ stats_req.dl_primitive = DL_GET_STATISTICS_REQ; if (!dlpi_req(dlpi, &stats_req, sizeof(dl_get_statistics_req_t), DL_GET_STATISTICS_ACK, (void **) &stats_ack, &len)) return 0; if (len < sizeof(dl_get_statistics_ack_t) || stats_ack->dl_stat_offset < 0 || stats_ack->dl_stat_offset + sizeof(mib_ifEntry) > len) { ifstat_error("dlpi: invalid data returned by stats ack"); } memcpy(mib, (char *) stats_ack + stats_ack->dl_stat_offset, sizeof(mib_ifEntry)); return 1;}static int dlpi_map_ifs(struct dlpi_driver_data *dlpi, int (*mapf)(mib_ifEntry *mib, int ppa, char *name, void *mdata), void *mdata) { dl_hp_ppa_req_t ppa_req; dl_hp_ppa_ack_t *ppa_ack; dl_hp_ppa_info_t *ppa_info; mib_ifEntry mib; void *buf; int len, i, ofs; char ifname[sizeof(ppa_info->dl_module_id_1) + 12]; if (!dlpi_attach(dlpi, DLPI_NO_PPA)) return 0; ppa_req.dl_primitive = DL_HP_PPA_REQ; if (!dlpi_req(dlpi, &ppa_req, sizeof(ppa_req), DL_HP_PPA_ACK, (void **) &ppa_ack, &len)) return 0; if (len < sizeof(dl_hp_ppa_ack_t)) { ifstat_error("dlpi: short read for ppa ack"); return 0; } /* copy buffer since used by later calls */ if ((buf = malloc(len)) == NULL) { perror("malloc"); return 0; } memcpy(buf, (void *) ppa_ack, len); ppa_ack = buf; /* browse interface list */ ofs = ppa_ack->dl_offset; for(i = 0; i < ppa_ack->dl_count; i++) { if (ofs < 0 || ofs + sizeof(dl_hp_ppa_info_t) > len) { ifstat_error("dlpi: data returned by ppa ack exceeds data buffer"); free(buf); return 0; } ppa_info = (dl_hp_ppa_info_t *) ((char *) ppa_ack + ofs); if (dlpi_get_ifmib(dlpi, ppa_info->dl_ppa, &mib)) { sprintf(ifname, "%s%d", ppa_info->dl_module_id_1, ppa_info->dl_instance_num); if (!mapf(&mib, ppa_info->dl_ppa, ifname, mdata)) { free(buf); return 0; } } ofs = ppa_ack->dl_offset + ppa_info->dl_next_offset; } free(buf); return 1;}static int dlpi_map_scan(mib_ifEntry *mib, int ppa, char *name, void *mdata) { examine_interface((struct ifstat_list *) mdata, name, (mib->ifOper == 1 ? IFF_UP : 0) | (mib->ifType == 24 ? IFF_LOOPBACK : 0), 0); return 1; }static int dlpi_scan_interfaces(struct ifstat_driver *driver, struct ifstat_list *ifs) { return dlpi_map_ifs(driver->data, &dlpi_map_scan, (void *) ifs);}static int dlpi_map_stats(mib_ifEntry *mib, int ppa, char *name, void *mdata) { struct ifstat_data *cur; if ((cur = ifstat_get_interface((struct ifstat_list *) mdata, name)) == NULL) return 1; ifstat_set_interface_stats(cur, mib->ifInOctets, mib->ifOutOctets); ifstat_set_interface_index(cur, ppa); return 1;}static int dlpi_get_stats(struct ifstat_driver *driver, struct ifstat_list *ifs) { int i; struct ifstat_data *cur; mib_ifEntry mib; if (ifs->flags & IFSTAT_HASINDEX) { /* poll by index (ppa) */ for (cur = ifs->first; cur != NULL; cur = cur->next) { i = ifstat_get_interface_index(cur); if (!dlpi_get_ifmib(driver->data, i, &mib)) continue; ifstat_set_interface_stats(cur, mib.ifInOctets, mib.ifOutOctets); ifstat_set_interface_index(cur, i); } return 1; } return dlpi_map_ifs(driver->data, &dlpi_map_stats, (void *) ifs);} void dlpi_close_driver(struct ifstat_driver *driver) { struct dlpi_driver_data *dlpi = driver->data; free(dlpi->buf); close(dlpi->fd); free(dlpi);}#endif#ifdef USE_WIN32struct win32_driver_data { void *buf; int len;};static int win32_open_driver(struct ifstat_driver *driver, char *options) { struct win32_driver_data *data; if ((data = malloc(sizeof(struct win32_driver_data))) == NULL) { ifstat_perror("malloc"); return 0; } data->buf = NULL; data->len = 0; driver->data = (void *) data; return 1;}static int win32_getiftable(struct ifstat_driver *driver, PMIB_IFTABLE *iftable) { struct win32_driver_data *data = driver->data; ULONG size; DWORD ret; size = data->len; while ((ret = GetIfTable((PMIB_IFTABLE) data->buf, &size, 1)) == ERROR_INSUFFICIENT_BUFFER) { data->len = size * 2; if ((data->buf = realloc(data->buf, data->len)) == NULL) { perror("realloc"); return 0; } } if (ret == NO_ERROR) { *iftable = (PMIB_IFTABLE) data->buf; return 1; } perror("GetIfTable"); return 0;}static int win32_scan_interfaces(struct ifstat_driver *driver, struct ifstat_list *ifs) { PMIB_IFTABLE iftable; DWORD i; if (!win32_getiftable(driver, &iftable)) return 0; for (i = 0; i < iftable->dwNumEntries; i++) examine_interface(ifs, iftable->table[i].bDescr, ((iftable->table[i].dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL) ? IFF_UP : 0) | ((iftable->table[i].dwType == MIB_IF_TYPE_LOOPBACK) ? IFF_LOOPBACK : 0), 0); return 1;}static int win32_get_stats(struct ifstat_driver *driver, struct ifstat_list *ifs) { PMIB_IFTABLE iftable; DWORD i; struct ifstat_data *cur; if (!win32_getiftable(driver, &iftable)) return 0; for (i = 0; i < iftable->dwNumEntries; i++) { if ((cur = ifstat_get_interface(ifs, iftable->table[i].bDescr)) != NULL) ifstat_set_interface_stats(cur, (unsigned long) iftable->table[i].dwInOctets, (unsigned long) iftable->table[i].dwOutOctets); } return 1;}void win32_close_driver(struct ifstat_driver *driver) { struct win32_driver_data *data = driver->data; if (data->buf != NULL) free(data->buf); free(data);}#endif static struct ifstat_driver drivers[] = {#ifdef USE_KSTAT { "kstat", &kstat_open_driver, &ioctl_scan_interfaces, &kstat_get_stats, &kstat_close_driver },#endif#ifdef USE_IFMIB { "ifmib", NULL, &ifmib_scan_interfaces, &ifmib_get_stats, NULL },#endif#ifdef USE_IFDATA { "ifdata", &ifdata_open_driver, &ifdata_scan_interfaces, &ifdata_get_stats, &ifdata_close_driver },#endif#ifdef USE_ROUTE { "route", &route_open_driver, &route_scan_interfaces, &route_get_stats, &route_close_driver },#endif #ifdef USE_KVM { "kvm", &kvm_open_driver, &kvm_scan_interfaces, &kvm_get_stats, &kvm_close_driver },#endif#ifdef USE_PROC { "proc", &proc_open_driver, &ioctl_scan_interfaces, &proc_get_stats, &proc_close_driver },#endif#ifdef USE_DLPI { "dlpi", &dlpi_open_driver, &dlpi_scan_interfaces, &dlpi_get_stats, &dlpi_close_driver },#endif#ifdef USE_WIN32 { "win32", &win32_open_driver, &win32_scan_interfaces, &win32_get_stats, &win32_close_driver },#endif #ifdef USE_SNMP { "snmp", &snmp_open_driver, &snmp_scan_interfaces, &snmp_get_stats, &snmp_close_driver },#endif { NULL } }; int ifstat_get_driver(char *name, struct ifstat_driver *driver) { int num = 0; if (name != NULL) for (num = 0; drivers[num].name != NULL; num++) if (!strcasecmp(drivers[num].name, name)) break; if (drivers[num].name == NULL) return 0; memcpy(driver, &(drivers[num]), sizeof(struct ifstat_driver)); driver->data = NULL; return 1;}char* ifstat_list_drivers() { int num; int len = 0, pos = 0; char *res; for(num = 0; drivers[num].name != NULL; num++) len += strlen(drivers[num].name) + 2; if ((res = malloc(len + 1)) == NULL) { ifstat_perror("malloc"); return NULL; } for(num = 0; drivers[num].name != NULL; num++) { if (num != 0) { memcpy(res + pos, ", ", 2); pos += 2; } len = strlen(drivers[num].name); memcpy(res + pos, drivers[num].name, len); pos += len; } res[pos] = '\0'; return res;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -