/** * Callback to parse scan results */ int wireless_network::scan_cb(struct nl_msg* msg, void* instance) { auto wn = static_cast<wireless_network*>(instance); auto gnlh = static_cast<genlmsghdr*>(nlmsg_data(nlmsg_hdr(msg))); struct nlattr* tb[NL80211_ATTR_MAX + 1]; struct nlattr* bss[NL80211_BSS_MAX + 1]; struct nla_policy bss_policy[NL80211_BSS_MAX + 1]{}; bss_policy[NL80211_BSS_TSF].type = NLA_U64; bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32; bss_policy[NL80211_BSS_BSSID].type = NLA_UNSPEC; bss_policy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16; bss_policy[NL80211_BSS_CAPABILITY].type = NLA_U16; bss_policy[NL80211_BSS_INFORMATION_ELEMENTS].type = NLA_UNSPEC; bss_policy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32; bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8; bss_policy[NL80211_BSS_STATUS].type = NLA_U32; if (nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), nullptr) < 0) { return NL_SKIP; } if (tb[NL80211_ATTR_BSS] == nullptr) { return NL_SKIP; } if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], bss_policy) != 0) { return NL_SKIP; } if (!wn->associated_or_joined(bss)) { return NL_SKIP; } wn->parse_essid(bss); wn->parse_frequency(bss); wn->parse_signal(bss); wn->parse_quality(bss); return NL_SKIP; }
void frequency_range(char *arg, struct misc_settings *ms) /* flesh out the tunes[] for scanning */ { struct channel_solve c; struct tuning_state *ts; int r, i, j, buf_len, length, hop_bins, logged_bins, planned_bins; int lower_edge, actual_bw, upper_perfect, remainder; fprintf(stderr, "Range: %s\n", arg); parse_frequency(arg, &c); c.downsample = 1; c.downsample_passes = 0; c.crop = ms->crop; if (ms->target_rate < 2 * MINIMUM_RATE) { ms->target_rate = 2 * MINIMUM_RATE; } if (ms->target_rate > MAXIMUM_RATE) { ms->target_rate = MAXIMUM_RATE; } if ((ms->crop < 0.0) || (ms->crop > 1.0)) { fprintf(stderr, "Crop value outside of 0 to 1.\n"); exit(1); } r = -1; if (c.bin_spec >= MINIMUM_RATE) { fprintf(stderr, "Mode: rms power\n"); solve_giant_bins(&c); } else if ((c.upper - c.lower) < MINIMUM_RATE) { fprintf(stderr, "Mode: downsampling\n"); solve_downsample(&c, ms->target_rate, ms->boxcar); } else if ((c.upper - c.lower) < MAXIMUM_RATE) { r = solve_single(&c, ms->target_rate); } else { fprintf(stderr, "Mode: hopping\n"); solve_hopping(&c, ms->target_rate); } if (r == 0) { fprintf(stderr, "Mode: single\n"); } else if (r == 1) { fprintf(stderr, "Mode: hopping\n"); solve_hopping(&c, ms->target_rate); } c.crop = c.crop_tmp; if ((tune_count+c.hops) > MAX_TUNES) { fprintf(stderr, "Error: bandwidth too wide.\n"); exit(1); } buf_len = 2 * (1<<c.bin_e) * c.downsample; if (buf_len < DEFAULT_BUF_LENGTH) { buf_len = DEFAULT_BUF_LENGTH; } /* build the array */ logged_bins = 0; lower_edge = c.lower; planned_bins = (c.upper - c.lower) / c.bin_spec; for (i=0; i < c.hops; i++) { ts = &tunes[tune_count + i]; /* copy common values */ ts->rate = c.bw_needed; ts->gain = ms->gain; ts->bin_e = c.bin_e; ts->samples = 0; ts->bin_spec = c.bin_spec; ts->crop = c.crop; ts->downsample = c.downsample; ts->downsample_passes = c.downsample_passes; ts->comp_fir_size = ms->comp_fir_size; ts->peak_hold = ms->peak_hold; ts->linear = ms->linear; ts->avg = (int64_t*)malloc((1<<c.bin_e) * sizeof(int64_t)); if (!ts->avg) { fprintf(stderr, "Error: malloc.\n"); exit(1); } for (j=0; j<(1<<c.bin_e); j++) { if (ts->peak_hold == -1) { ts->avg[j] = 1e6; } else { ts->avg[j] = 0L;} } ts->buf8 = (uint8_t*)malloc(buf_len * sizeof(uint8_t)); if (!ts->buf8) { fprintf(stderr, "Error: malloc.\n"); exit(1); } ts->buf_len = buf_len; length = 1 << c.bin_e; ts->window_coefs = malloc(length * sizeof(int)); for (j=0; j<length; j++) { ts->window_coefs[j] = (int)(256*ms->window_fn(j, length)); } /* calculate unique values */ ts->freq_low = lower_edge; hop_bins = c.bw_wanted / c.bin_spec; actual_bw = hop_bins * c.bin_spec; ts->freq_high = lower_edge + actual_bw; upper_perfect = c.lower + (i+1) * c.bw_wanted; if (ts->freq_high + c.bin_spec <= upper_perfect) { hop_bins += 1; actual_bw = hop_bins * c.bin_spec; ts->freq_high = lower_edge + actual_bw; } remainder = planned_bins - logged_bins - hop_bins; if (i == c.hops-1 && remainder > 0) { hop_bins += remainder; actual_bw = hop_bins * c.bin_spec; ts->freq_high = lower_edge + actual_bw; } logged_bins += hop_bins; ts->crop_i1 = (length - hop_bins) / 2; ts->crop_i2 = ts->crop_i1 + hop_bins - 1; ts->freq = (lower_edge - ts->crop_i1 * c.bin_spec) + c.bw_needed/(2*c.downsample); /* prep for next hop */ lower_edge = ts->freq_high; } tune_count += c.hops; /* report */ fprintf(stderr, "Number of frequency hops: %i\n", c.hops); fprintf(stderr, "Dongle bandwidth: %iHz\n", c.bw_needed); fprintf(stderr, "Downsampling by: %ix\n", c.downsample); fprintf(stderr, "Cropping by: %0.2f%%\n", c.crop*100); fprintf(stderr, "Total FFT bins: %i\n", c.hops * (1<<c.bin_e)); fprintf(stderr, "Logged FFT bins: %i\n", logged_bins); fprintf(stderr, "FFT bin size: %iHz\n", c.bin_spec); fprintf(stderr, "Buffer size: %i bytes (%0.2fms)\n", buf_len, 1000 * 0.5 * (float)buf_len / (float)c.bw_needed); fprintf(stderr, "\n"); }