static struct nl80211_msg_conveyor * nl80211_ctl(int cmd, int flags) { if (nl80211_init() < 0) return NULL; return nl80211_new(nls->nlctrl, cmd, flags); }
void enter_rfmon_mac80211(const char *device, char **mondev) { int ret; short flags; uint32_t n; char phydev_path[256]; struct nl80211_state nlstate; /* XXX: is this already a monN device? */ get_mac80211_phydev(device, phydev_path, sizeof(phydev_path)); nl80211_init(&nlstate, device); for (n = 0; n < UINT_MAX; n++) { char mondevice[32]; slprintf(mondevice, sizeof(mondevice), "mon%u", n); ret = nl80211_add_mon_if(&nlstate, device, mondevice); if (ret == 0) { *mondev = xstrdup(mondevice); flags = device_get_flags(*mondev); flags |= IFF_UP | IFF_RUNNING; device_set_flags(*mondev, flags); nl80211_cleanup(&nlstate); return; } } panic("No free monN interfaces!\n"); }
static int run_iwraw(void) { int rc; rc = nl80211_init(); if (rc) return rc; if (!cmd_set) { rc = prepare_listen_events(); if (rc) return rc; rc = do_listen_events(); } else { ssize_t nla_stream_len; nla_stream_len = read_nla_stream(nla_input_stream, sizeof(nla_input_stream)); if (nla_stream_len < 0) return -1; rc = send_recv_nlcmd(nla_input_stream, nla_stream_len); } return rc; }
static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname, int cmd, int flags) { static struct nl80211_msg_conveyor cv; int ifidx = -1, phyidx = -1; struct nl_msg *req = NULL; struct nl_cb *cb = NULL; if (nl80211_init() < 0) goto err; if (!strncmp(ifname, "phy", 3)) phyidx = atoi(&ifname[3]); else if (!strncmp(ifname, "radio", 5)) phyidx = atoi(&ifname[5]); else if (!strncmp(ifname, "mon.", 4)) ifidx = if_nametoindex(&ifname[4]); else ifidx = if_nametoindex(ifname); if ((ifidx < 0) && (phyidx < 0)) return NULL; req = nlmsg_alloc(); if (!req) goto err; cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) goto err; genlmsg_put(req, 0, 0, genl_family_get_id(nls->nl80211), 0, flags, cmd, 0); if (ifidx > -1) NLA_PUT_U32(req, NL80211_ATTR_IFINDEX, ifidx); if (phyidx > -1) NLA_PUT_U32(req, NL80211_ATTR_WIPHY, phyidx); cv.msg = req; cv.cb = cb; return &cv; err: nla_put_failure: if (cb) nl_cb_put(cb); if (req) nlmsg_free(req); return NULL; }
void leave_rfmon_mac80211(const char *device, const char *mondev) { short flags; struct nl80211_state nlstate; flags = device_get_flags(mondev); flags &= ~(IFF_UP | IFF_RUNNING); device_set_flags(mondev, flags); nl80211_init(&nlstate, device); nl80211_del_mon_if(&nlstate, device, mondev); nl80211_cleanup(&nlstate); }
int set_wifi_power_saving(const char *iface, int state) { struct nl80211_state nlstate; int err; err = nl80211_init(&nlstate); if (err) return 1; enable_power_save = state; err = __handle_cmd(&nlstate, iface, 0); nl80211_cleanup(&nlstate); return err; }
int get_wifi_power_saving(const char *iface) { struct nl80211_state nlstate; int err; enable_power_save = 0; err = nl80211_init(&nlstate); if (err) return 1; err = __handle_cmd(&nlstate, iface, 1); nl80211_cleanup(&nlstate); if (err) /* not a wifi interface */ return 1; return enable_power_save; }
static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname, int cmd, int flags) { int ifidx = -1, phyidx = -1; struct nl80211_msg_conveyor *cv; if (nl80211_init() < 0) return NULL; if (!strncmp(ifname, "phy", 3)) phyidx = atoi(&ifname[3]); else if (!strncmp(ifname, "radio", 5)) phyidx = atoi(&ifname[5]); else if (!strncmp(ifname, "mon.", 4)) ifidx = if_nametoindex(&ifname[4]); else ifidx = if_nametoindex(ifname); if ((ifidx < 0) && (phyidx < 0)) return NULL; cv = nl80211_new(nls->nl80211, cmd, flags); if (!cv) return NULL; if (ifidx > -1) NLA_PUT_U32(cv->msg, NL80211_ATTR_IFINDEX, ifidx); if (phyidx > -1) NLA_PUT_U32(cv->msg, NL80211_ATTR_WIPHY, phyidx); return cv; nla_put_failure: nl80211_free(cv); return NULL; }
int main(int argc, char *argv[]) { uint8_t fft_period = 15; uint8_t period = 1; double noise_thld = -95; uint16_t intval = 100; int option = -1; while ((option = getopt (argc, argv, "hp:f:P:t:i:")) != -1) { switch (option) { case 'h': fprintf(stderr, "Description\n"); fprintf(stderr, "-----------\n"); fprintf(stderr, BOLD "COR" RESET " is a wrapper for the atheros Wi-Fi chipsets (i.e. AR92xx and AR93xx) which collects Wi-Fi spectral samples and store\n"); fprintf(stderr, "the information into a database. The information stored is pre-processed twice, first by calculating the energies present in the Wi-Fi\n"); fprintf(stderr, "and zigbee channels and second by reducing the amount of information using different holding methods such as\n"); fprintf(stderr, "MAX_HOLD, MIN_HOLD and AVG_HOLD for a specific amount of time.\n\n"); fprintf(stderr, "Argument list\n"); fprintf(stderr, "-------------\n"); fprintf(stderr, "-h\t\t\thelp menu\n"); fprintf(stderr, "-p phy_name\t\tphysical interface name of the wireless card [eg. -p phy0]\n"); fprintf(stderr, "-f fft_period\t\twhen active and triggered, PHY passes FFT frames to MAC every (fft_period+1)*4uS [eg. -f 15]\n"); fprintf(stderr, "-P period\t\ttime period between successive spectral scan entry points (period*256*Tclk) [eg. -P 1]\n"); fprintf(stderr, "-t noise_thld\t\tWi-Fi noise threshold (dBm) for COR calculation [eg. -t -95]\n"); fprintf(stderr, "-i intval\t\tinterval (msec) of a periodic report [eg. -i 100]\n\n"); fprintf(stderr, "Example\n"); fprintf(stderr, "-------\n"); fprintf(stderr, BOLD "./COR -n 10.11.31.5 -u CREW_BM -k CREW_BM -d benchmarking -p phy0 -f 15 -P 255 -t -95 -i 100\n" RESET); return 1; case 'p': phy_name = strdup(optarg); break; case 'f': fft_period = atoi(optarg); break; case 'P': period = atoi(optarg); break; case 't': noise_thld = atof(optarg); break; case 'i': intval = atoi(optarg); break; default: fprintf(stderr, "COR: missing operand. Type './COR -h' for more information\n"); return 1; } } int fd; // User space and kernel space scan result counter char command[128]; uint32_t scan_count_temp, COR_count; struct timeval systime; uint64_t start_time, current_time; uint16_t previous_dur, current_dur; char subbuf[SUB_BUF_SIZE]; struct fft_sample_ht20 *sample; uint16_t freq; int i, j, datasquaresum, num_of_read; struct pollfd pfds; struct nl80211_state nlstate; char sniffer_mac[18]; // Calculate bin threshold from noise threshold double bin_thld = 10*log10f(pow(10,noise_thld/10)/SPECTRAL_HT20_NUM_BINS); // handle SIGTERM and SIGINT signal(SIGINT, cleanup); signal(SIGTERM, cleanup); // Initialize netlink handler if (nl80211_init(&nlstate)) return 1; // Make sure there exists a monitor mode interface with in the given physical interface if(ret_mon_IF(&nlstate) > 0) return 1; if(IF_name[0] == '\0') { fprintf(stderr, "%s does not expose a monitor interface. Create one before running spectrum scanning.\n", phy_name); fprintf(stderr, "E.g. sudo iw phy %s interface add wlanMoni type monitor && sudo ifconfig wlanMoni up\n", phy_name); return 1; } // Retrieve mac address ret_phyIF_MAC(phy_name, sniffer_mac); // Log the starting time gettimeofday(&systime, NULL); start_time = 1e3*systime.tv_sec + (int)(systime.tv_usec/1e3); previous_dur = (start_time % intval); /* Open CPU-0 spectral relay file */ sprintf(command,"%s/%s/ath9k/spectral_scan0", ieee80211_debug_path, phy_name); fd = open(command, O_RDONLY); if (fd < 0) { fprintf(stderr, "open failure for file spectral_scan0: %s\n", strerror(errno)); return 1; } // Polling file descriptor and input event request pfds.fd = fd; pfds.events = POLLIN; // Initialize spectral parameters sprintf(command,"echo %u > %s/%s/ath9k/spectral_fft_period", fft_period, ieee80211_debug_path, phy_name); if(system(command) == -1) return 1; sprintf(command,"echo %u > %s/%s/ath9k/spectral_period", period, ieee80211_debug_path, phy_name); if(system(command) == -1) return 1; // Enable background spectral scan sprintf(command,"echo background > %s/%s/ath9k/spectral_scan_ctl", ieee80211_debug_path, phy_name); if(system(command) == -1) return 1; // Trigger the spectral scan sprintf(command,"echo trigger > %s/%s/ath9k/spectral_scan_ctl", ieee80211_debug_path, phy_name); if(system(command) == -1) return 1; // Initialize the user space scan result counter scan_count_temp = 0; COR_count = 0; while(1) { if(finished == 1) break; // Before timeout (100 msec) expires, wait the sub buffer to become full. If not, restart the interface and trigger the spectral scan. poll(&pfds, 1, 100); if(!(pfds.revents & POLLIN)) { // Reset monitor mode interface if(reset_mon_IF() < 0) { fprintf(stderr, "Monitor interface %s reset error.\n", IF_name); break; } // Trigger background spectral scan once again sprintf(command,"echo trigger > %s/%s/ath9k/spectral_scan_ctl", ieee80211_debug_path, phy_name); if(system(command) == -1) break; continue; } else { num_of_read = read(fd, subbuf, SAMPLE_SIZE_PER_SUB_BUF); if(num_of_read < 0) { fprintf(stderr, "spectral_scan0 read error: %s\n", strerror(errno)); break; } else if(num_of_read < sizeof(struct fft_sample_ht20)) { continue; } else { // Iterate through the buffer and parse the spectrum data for (i = 0; i < num_of_read/sizeof(struct fft_sample_ht20); i++) { sample = (struct fft_sample_ht20 *)(subbuf + i*sizeof(struct fft_sample_ht20)); // If sample does not contain a spectrum data if((sample->tlv.type != ATH_FFT_SAMPLE_HT20) || (be16toh(sample->tlv.length) != sizeof(struct fft_sample_ht20)-sizeof(struct fft_sample_tlv))) continue; // Determine spectral frequency if(i == 0) { freq = sample->freq; } // If spectral frequency changes, reset COR counters else if(freq != sample->freq) { scan_count_temp = 0; COR_count = 0; } /* calculate the data square sum */ datasquaresum = 0; for (j = 0; j < SPECTRAL_HT20_NUM_BINS; j++) datasquaresum += (sample->data[j] << sample->max_exp) * (sample->data[j] << sample->max_exp); // Check for empty result if(datasquaresum == 0) continue; // Increment the scan result temporary counter scan_count_temp++; // Calculate COR per each fft bin for (j = 0; j < SPECTRAL_HT20_NUM_BINS; j++) { double signal; int data; data = sample->data[j] << sample->max_exp; if (data == 0) data = 1; // Signal calculation (i.e. http://wireless.kernel.org/en/users/Drivers/ath9k/spectral_scan/) signal = sample->noise + sample->rssi + 20*log10f(data) - 10*log10f(datasquaresum); // If instantaneous bin energy is above noise threshold, channel is occupied if(signal > bin_thld) COR_count++; } } } } // Get the current time gettimeofday(&systime, NULL); current_time = 1e3*systime.tv_sec + (int)(systime.tv_usec/1e3); current_dur = (current_time % intval); if(current_dur < previous_dur) { // Generate the query statement printf("%lu\t%s\t%d\t%.5f\t%u\n", current_time, sniffer_mac, ntohs(sample->freq), (100.0*COR_count)/(scan_count_temp*SPECTRAL_HT20_NUM_BINS), previous_dur); // Update parameters for next round scan_count_temp = 0; COR_count = 0; } // Update parameter for next round previous_dur = current_dur; } // Disable spectrum scanning sprintf(command,"echo disable > %s/%s/ath9k/spectral_scan_ctl", ieee80211_debug_path, phy_name); if(system(command) == -1) return 1; /* Close the spectral scan relay file */ close(fd); return 1; }
int main(int argc, char **argv) { struct nl80211_state nlstate; int devidx = 0; char *devname; int err; unsigned int surveys = 10; /* strip off self */ argc--; argv0 = *argv++; if (argc > 0 && strcmp(*argv, "--debug") == 0) { nl_debug = 1; argc--; argv++; } if (argc > 0 && strcmp(*argv, "--version") == 0) { version(); return 0; } /* need to treat "help" command specially so it works w/o nl80211 */ if (argc == 0 || strcmp(*argv, "help") == 0) { usage(); return 0; } err = nl80211_init(&nlstate); if (err) return 1; if (argc <= 0) { return 1; } devidx = if_nametoindex(*argv); if (devidx == 0) devidx = -1; devname = *argv; argc--; argv++; if (devidx < 0) return -errno; if (!is_link_up(devname)) { err = -ENOLINK; printf("Link for %s must be up to use acs\n", devname); goto nl_cleanup; } /* * XXX: we should probably get channel list properly here * but I'm lazy. THIS IS A REQUIREMENT, given that if a device * is down and comes up we won't have any survey data to study. */ err = get_freq_list(&nlstate, devidx); if (err) return err; while (surveys--) { err = study_freqs(&nlstate, devidx); if (err) return err; } parse_freq_list(); parse_freq_int_factor(); nl_cleanup: nl80211_cleanup(&nlstate); clear_offchan_ops_list(); clean_freq_list(); return err; }