#include #include #include "mac_utils.h" #include "datastorage.h" #include "dawn_iwinfo.h" #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] char hostapd_dir_glob[HOSTAPD_DIR_LEN]; int call_iwinfo(char *client_addr); int parse_rssi(char *iwinfo_string); int get_rssi(const char *ifname, struct dawn_mac client_addr); int get_bandwidth(const char *ifname, struct dawn_mac client_addr, float *rx_rate, float *tx_rate); #define IWINFO_BUFSIZE 24 * 1024 #define IWINFO_ESSID_MAX_SIZE 32 int compare_essid_iwinfo(struct dawn_mac bssid_addr, struct dawn_mac bssid_addr_to_compare) { const struct iwinfo_ops *iw; char mac_buf[20]; char mac_buf_to_compare[20]; sprintf(mac_buf, MACSTR, MAC2STR(bssid_addr.u8)); sprintf(mac_buf_to_compare, MACSTR, MAC2STR(bssid_addr_to_compare.u8)); DIR *dirp; struct dirent *entry; dirp = opendir(hostapd_dir_glob); // error handling? if (!dirp) { fprintf(stderr, "[COMPARE ESSID] Failed to open %s\n", hostapd_dir_glob); return 0; } char *essid = NULL; char *essid_to_compare = NULL; char buf_essid[IWINFO_ESSID_MAX_SIZE + 1] = {0}; char buf_essid_to_compare[IWINFO_ESSID_MAX_SIZE + 1] = {0}; while ((entry = readdir(dirp)) != NULL && (essid == NULL || essid_to_compare == NULL)) { if (entry->d_type == DT_SOCK) { if (strcmp(entry->d_name, "global") == 0) continue; iw = iwinfo_backend(entry->d_name); // TODO: Magic number static char buf_bssid[18] = {0}; if (iw->bssid(entry->d_name, buf_bssid)) snprintf(buf_bssid, sizeof(buf_bssid), "00:00:00:00:00:00"); if (strcmp(mac_buf, buf_bssid) == 0) { if (iw->ssid(entry->d_name, buf_essid)) memset(buf_essid, 0, sizeof(buf_essid)); essid = buf_essid; } if (strcmp(mac_buf_to_compare, buf_bssid) == 0) { if (iw->ssid(entry->d_name, buf_essid_to_compare)) memset(buf_essid_to_compare, 0, sizeof(buf_essid_to_compare)); essid_to_compare = buf_essid_to_compare; } iwinfo_finish(); } } closedir(dirp); printf("Comparing: %s with %s\n", essid, essid_to_compare); if (essid == NULL || essid_to_compare == NULL) { return -1; } if (strcmp(essid, essid_to_compare) == 0) { return 0; } return -1; } int get_bandwidth_iwinfo(struct dawn_mac client_addr, float *rx_rate, float *tx_rate) { DIR *dirp; struct dirent *entry; dirp = opendir(hostapd_dir_glob); // error handling? if (!dirp) { fprintf(stderr, "[BANDWIDTH INFO] Failed to open %s\n", hostapd_dir_glob); return 0; } int sucess = 0; while ((entry = readdir(dirp)) != NULL) { if (entry->d_type == DT_SOCK) { if (get_bandwidth(entry->d_name, client_addr, rx_rate, tx_rate)) { sucess = 1; break; } } } closedir(dirp); return sucess; } int get_bandwidth(const char *ifname, struct dawn_mac client_addr, float *rx_rate, float *tx_rate) { int i, len; char buf[IWINFO_BUFSIZE]; struct iwinfo_assoclist_entry *e; const struct iwinfo_ops *iw; if (strcmp(ifname, "global") == 0) return 0; iw = iwinfo_backend(ifname); if (iw->assoclist(ifname, buf, &len)) { fprintf(stdout, "No information available\n"); iwinfo_finish(); return 0; } else if (len <= 0) { fprintf(stdout, "No station connected\n"); iwinfo_finish(); return 0; } for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry)) { e = (struct iwinfo_assoclist_entry *) &buf[i]; if (mac_is_equal(client_addr.u8, e->mac)) { *rx_rate = e->rx_rate.rate / 1000; *tx_rate = e->tx_rate.rate / 1000; iwinfo_finish(); return 1; } } iwinfo_finish(); return 0; } int get_rssi_iwinfo(struct dawn_mac client_addr) { DIR *dirp; struct dirent *entry; dirp = opendir(hostapd_dir_glob); // error handling? if (!dirp) { fprintf(stderr, "[RSSI INFO] No hostapd sockets!\n"); return INT_MIN; } int rssi = INT_MIN; while ((entry = readdir(dirp)) != NULL) { if (entry->d_type == DT_SOCK) { rssi = get_rssi(entry->d_name, client_addr); if (rssi != INT_MIN) break; } } closedir(dirp); return rssi; } int get_rssi(const char *ifname, struct dawn_mac client_addr) { int i, len; char buf[IWINFO_BUFSIZE]; struct iwinfo_assoclist_entry *e; const struct iwinfo_ops *iw; if (strcmp(ifname, "global") == 0) return INT_MIN; iw = iwinfo_backend(ifname); if (iw->assoclist(ifname, buf, &len)) { fprintf(stdout, "No information available\n"); iwinfo_finish(); return INT_MIN; } else if (len <= 0) { fprintf(stdout, "No station connected\n"); iwinfo_finish(); return INT_MIN; } for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry)) { e = (struct iwinfo_assoclist_entry *) &buf[i]; if (mac_is_equal(client_addr.u8, e->mac)) { iwinfo_finish(); return e->signal; } } iwinfo_finish(); return INT_MIN; } int get_expected_throughput_iwinfo(struct dawn_mac client_addr) { DIR *dirp; struct dirent *entry; dirp = opendir(hostapd_dir_glob); // error handling? if (!dirp) { fprintf(stderr, "[RSSI INFO] Failed to open dir:%s\n", hostapd_dir_glob); return INT_MIN; } int exp_thr = INT_MIN; while ((entry = readdir(dirp)) != NULL) { if (entry->d_type == DT_SOCK) { exp_thr = get_expected_throughput(entry->d_name, client_addr); if (exp_thr != INT_MIN) break; } } closedir(dirp); return exp_thr; } int get_expected_throughput(const char *ifname, struct dawn_mac client_addr) { int i, len; char buf[IWINFO_BUFSIZE]; struct iwinfo_assoclist_entry *e; const struct iwinfo_ops *iw; if (strcmp(ifname, "global") == 0) return INT_MIN; iw = iwinfo_backend(ifname); if (iw->assoclist(ifname, buf, &len)) { fprintf(stdout, "No information available\n"); iwinfo_finish(); return INT_MIN; } else if (len <= 0) { fprintf(stdout, "No station connected\n"); iwinfo_finish(); return INT_MIN; } for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry)) { e = (struct iwinfo_assoclist_entry *) &buf[i]; if (mac_is_equal(client_addr.u8, e->mac)) { iwinfo_finish(); return e->thr; } } iwinfo_finish(); return INT_MIN; } int get_bssid(const char *ifname, uint8_t bssid_addr[]) { const struct iwinfo_ops *iw; if (strcmp(ifname, "global") == 0) return 0; iw = iwinfo_backend(ifname); static char buf[18] = { 0 }; if (iw->bssid(ifname, buf)) snprintf(buf, sizeof(buf), "00:00:00:00:00:00"); hwaddr_aton(buf,bssid_addr); iwinfo_finish(); return 0; } int get_ssid(const char *ifname, char* ssid, size_t ssidmax) { const struct iwinfo_ops *iw; char buf[IWINFO_ESSID_MAX_SIZE+1] = { 0 }; if (strcmp(ifname, "global") == 0) return 0; iw = iwinfo_backend(ifname); if (iw->ssid(ifname, buf)) memset(buf, 0, sizeof(buf)); memcpy(ssid, buf, ssidmax); strcpy(ssid, buf); iwinfo_finish(); return 0; } int get_channel_utilization(const char *ifname, uint64_t *last_channel_time, uint64_t *last_channel_time_busy) { int len; const struct iwinfo_ops *iw; char buf[IWINFO_BUFSIZE]; struct iwinfo_survey_entry *e; int ret = 0; if (strcmp(ifname, "global") == 0) return 0; iw = iwinfo_backend(ifname); int freq; if (iw->frequency(ifname, &freq)) { iwinfo_finish(); return 0; } if (iw->survey(ifname, buf, &len)) { fprintf(stderr, "Survey not possible!\n\n"); iwinfo_finish(); return 0; } else if (len <= 0) { fprintf(stderr, "No survey results\n\n"); iwinfo_finish(); return 0; } for (int i = 0, x = 1; i < len; i += sizeof(struct iwinfo_survey_entry), x++) { e = (struct iwinfo_survey_entry *) &buf[i]; if(e->mhz == freq) { uint64_t dividend = e->busy_time - *last_channel_time_busy; uint64_t divisor = e->active_time - *last_channel_time; *last_channel_time = e->active_time; *last_channel_time_busy = e->busy_time; if(divisor) ret = (int)(dividend * 255 / divisor); break; } } iwinfo_finish(); return ret; } int support_ht(const char *ifname) { const struct iwinfo_ops *iw; if (strcmp(ifname, "global") == 0) return 0; iw = iwinfo_backend(ifname); int htmodes = 0; if (iw->htmodelist(ifname, &htmodes)) { printf("No HT mode information available\n"); iwinfo_finish(); return 0; } uint32_t ht_support_bitmask = (1 << 0) | (1 << 2); int ret = htmodes & ht_support_bitmask ? 1 : 0; iwinfo_finish(); return ret; } int support_vht(const char *ifname) { const struct iwinfo_ops *iw; if (strcmp(ifname, "global") == 0) return 0; iw = iwinfo_backend(ifname); int htmodes = 0; if (iw->htmodelist(ifname, &htmodes)) { fprintf(stderr, "No VHT mode information available\n"); iwinfo_finish(); return 0; } // TODO: 1 << 2 duplicated here, and also appears as HT mode mask uint32_t vht_support_bitmask = (1 << 2) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6); int ret = htmodes & vht_support_bitmask ? 1 : 0; iwinfo_finish(); return ret; }