svn commit: r187872 - projects/vap7/sbin/ifconfig
Sam Leffler
sam at FreeBSD.org
Wed Jan 28 13:52:46 PST 2009
Author: sam
Date: Wed Jan 28 21:52:45 2009
New Revision: 187872
URL: http://svn.freebsd.org/changeset/base/187872
Log:
sync 802.11 changes with head
Modified:
projects/vap7/sbin/ifconfig/ (props changed)
projects/vap7/sbin/ifconfig/ifieee80211.c
Modified: projects/vap7/sbin/ifconfig/ifieee80211.c
==============================================================================
--- projects/vap7/sbin/ifconfig/ifieee80211.c Wed Jan 28 21:42:17 2009 (r187871)
+++ projects/vap7/sbin/ifconfig/ifieee80211.c Wed Jan 28 21:52:45 2009 (r187872)
@@ -79,6 +79,7 @@
#include <net80211/ieee80211_ioctl.h>
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -119,6 +120,8 @@
#define IEEE80211_NODE_RIFS 0x4000 /* RIFS enabled */
#endif
+#define MAXCHAN 1536 /* max 1.5K channels */
+
#define MAXCOL 78
static int col;
static char spacer;
@@ -145,7 +148,7 @@ static void print_channels(int, const st
static void regdomain_makechannels(struct ieee80211_regdomain_req *,
const struct ieee80211_devcaps_req *);
-static struct ieee80211req_chaninfo chaninfo;
+static struct ieee80211req_chaninfo *chaninfo;
static struct ieee80211_regdomain regdomain;
static int gotregdomain = 0;
static struct ieee80211_roamparams_req roamparams;
@@ -175,10 +178,14 @@ gethtconf(int s)
static void
getchaninfo(int s)
{
- if (chaninfo.ic_nchans != 0)
+ if (chaninfo != NULL)
return;
- if (get80211(s, IEEE80211_IOC_CHANINFO, &chaninfo, sizeof(chaninfo)) < 0)
- errx(1, "unable to get channel information");
+ chaninfo = malloc(IEEE80211_CHANINFO_SIZE(MAXCHAN));
+ if (chaninfo == NULL)
+ errx(1, "no space for channel list");
+ if (get80211(s, IEEE80211_IOC_CHANINFO, chaninfo,
+ IEEE80211_CHANINFO_SIZE(MAXCHAN)) < 0)
+ err(1, "unable to get channel information");
ifmr = ifmedia_getstate(s);
gethtconf(s);
}
@@ -205,19 +212,19 @@ getregdata(void)
static int
canpromote(int i, int from, int to)
{
- const struct ieee80211_channel *fc = &chaninfo.ic_chans[i];
+ const struct ieee80211_channel *fc = &chaninfo->ic_chans[i];
int j;
if ((fc->ic_flags & from) != from)
return i;
/* NB: quick check exploiting ordering of chans w/ same frequency */
- if (i+1 < chaninfo.ic_nchans &&
- chaninfo.ic_chans[i+1].ic_freq == fc->ic_freq &&
- (chaninfo.ic_chans[i+1].ic_flags & to) == to)
+ if (i+1 < chaninfo->ic_nchans &&
+ chaninfo->ic_chans[i+1].ic_freq == fc->ic_freq &&
+ (chaninfo->ic_chans[i+1].ic_flags & to) == to)
return i+1;
/* brute force search in case channel list is not ordered */
- for (j = 0; j < chaninfo.ic_nchans; j++) {
- const struct ieee80211_channel *tc = &chaninfo.ic_chans[j];
+ for (j = 0; j < chaninfo->ic_nchans; j++) {
+ const struct ieee80211_channel *tc = &chaninfo->ic_chans[j];
if (j != i &&
tc->ic_freq == fc->ic_freq && (tc->ic_flags & to) == to)
return j;
@@ -287,13 +294,13 @@ mapfreq(struct ieee80211_channel *chan,
{
int i;
- for (i = 0; i < chaninfo.ic_nchans; i++) {
- const struct ieee80211_channel *c = &chaninfo.ic_chans[i];
+ for (i = 0; i < chaninfo->ic_nchans; i++) {
+ const struct ieee80211_channel *c = &chaninfo->ic_chans[i];
if (c->ic_freq == freq && (c->ic_flags & flags) == flags) {
if (flags == 0) {
/* when ambiguous promote to ``best'' */
- c = &chaninfo.ic_chans[promote(i)];
+ c = &chaninfo->ic_chans[promote(i)];
}
*chan = *c;
return;
@@ -307,13 +314,13 @@ mapchan(struct ieee80211_channel *chan,
{
int i;
- for (i = 0; i < chaninfo.ic_nchans; i++) {
- const struct ieee80211_channel *c = &chaninfo.ic_chans[i];
+ for (i = 0; i < chaninfo->ic_nchans; i++) {
+ const struct ieee80211_channel *c = &chaninfo->ic_chans[i];
if (c->ic_ieee == ieee && (c->ic_flags & flags) == flags) {
if (flags == 0) {
/* when ambiguous promote to ``best'' */
- c = &chaninfo.ic_chans[promote(i)];
+ c = &chaninfo->ic_chans[promote(i)];
}
*chan = *c;
return;
@@ -331,7 +338,7 @@ getcurchan(int s)
int val;
/* fall back to legacy ioctl */
if (get80211val(s, IEEE80211_IOC_CHANNEL, &val) < 0)
- errx(-1, "cannot figure out current channel");
+ err(-1, "cannot figure out current channel");
getchaninfo(s);
mapchan(&curchan, val, 0);
}
@@ -370,7 +377,7 @@ getroam(int s)
return;
if (get80211(s, IEEE80211_IOC_ROAM,
&roamparams, sizeof(roamparams)) < 0)
- errx(1, "unable to get roaming parameters");
+ err(1, "unable to get roaming parameters");
gotroam = 1;
}
@@ -388,7 +395,7 @@ gettxparams(int s)
return;
if (get80211(s, IEEE80211_IOC_TXPARAMS,
&txparams, sizeof(txparams)) < 0)
- errx(1, "unable to get transmit parameters");
+ err(1, "unable to get transmit parameters");
gottxparams = 1;
}
@@ -406,23 +413,24 @@ getregdomain(int s)
return;
if (get80211(s, IEEE80211_IOC_REGDOMAIN,
®domain, sizeof(regdomain)) < 0)
- errx(1, "unable to get regulatory domain info");
+ err(1, "unable to get regulatory domain info");
gotregdomain = 1;
}
static void
getdevcaps(int s, struct ieee80211_devcaps_req *dc)
{
- if (get80211(s, IEEE80211_IOC_DEVCAPS, dc, sizeof(*dc)) < 0)
- errx(1, "unable to get device capabilities");
+ if (get80211(s, IEEE80211_IOC_DEVCAPS, dc,
+ IEEE80211_DEVCAPS_SPACE(dc)) < 0)
+ err(1, "unable to get device capabilities");
}
static void
setregdomain_cb(int s, void *arg)
{
- struct ieee80211_regdomain_req req;
+ struct ieee80211_regdomain_req *req;
struct ieee80211_regdomain *rd = arg;
- struct ieee80211_devcaps_req dc;
+ struct ieee80211_devcaps_req *dc;
struct regdata *rdp = getregdata();
if (rd->country != NO_COUNTRY) {
@@ -462,34 +470,52 @@ setregdomain_cb(int s, void *arg)
rp->name);
}
}
- req.rd = *rd;
/*
* Fetch the device capabilities and calculate the
* full set of netbands for which we request a new
* channel list be constructed. Once that's done we
* push the regdomain info + channel list to the kernel.
*/
- getdevcaps(s, &dc);
+ dc = malloc(IEEE80211_DEVCAPS_SIZE(MAXCHAN));
+ if (dc == NULL)
+ errx(1, "no space for device capabilities");
+ dc->dc_chaninfo.ic_nchans = MAXCHAN;
+ getdevcaps(s, dc);
#if 0
if (verbose) {
- printf("drivercaps: 0x%x\n", dc.dc_drivercaps);
- printf("cryptocaps: 0x%x\n", dc.dc_cryptocaps);
- printf("htcaps : 0x%x\n", dc.dc_htcaps);
- memcpy(&chaninfo, &dc.dc_chaninfo, sizeof(chaninfo));
- print_channels(s, &dc.dc_chaninfo, 1/*allchans*/, 1/*verbose*/);
+ printf("drivercaps: 0x%x\n", dc->dc_drivercaps);
+ printf("cryptocaps: 0x%x\n", dc->dc_cryptocaps);
+ printf("htcaps : 0x%x\n", dc->dc_htcaps);
+ memcpy(chaninfo, &dc->dc_chaninfo,
+ IEEE80211_CHANINFO_SPACE(&dc->dc_chaninfo));
+ print_channels(s, &dc->dc_chaninfo, 1/*allchans*/, 1/*verbose*/);
}
#endif
- regdomain_makechannels(&req, &dc);
+ req = malloc(IEEE80211_REGDOMAIN_SIZE(dc->dc_chaninfo.ic_nchans));
+ if (req == NULL)
+ errx(1, "no space for regdomain request");
+ req->rd = *rd;
+ regdomain_makechannels(req, dc);
if (verbose) {
LINE_INIT(':');
print_regdomain(rd, 1/*verbose*/);
LINE_BREAK();
- memcpy(&chaninfo, &req.chaninfo, sizeof(chaninfo));
- print_channels(s, &req.chaninfo, 1/*allchans*/, 1/*verbose*/);
+ /* blech, reallocate channel list for new data */
+ if (chaninfo != NULL)
+ free(chaninfo);
+ chaninfo = malloc(IEEE80211_CHANINFO_SPACE(&req->chaninfo));
+ if (chaninfo == NULL)
+ errx(1, "no space for channel list");
+ memcpy(chaninfo, &req->chaninfo,
+ IEEE80211_CHANINFO_SPACE(&req->chaninfo));
+ print_channels(s, &req->chaninfo, 1/*allchans*/, 1/*verbose*/);
}
- if (req.chaninfo.ic_nchans == 0)
+ if (req->chaninfo.ic_nchans == 0)
errx(1, "no channels calculated");
- set80211(s, IEEE80211_IOC_REGDOMAIN, 0, sizeof(req), &req);
+ set80211(s, IEEE80211_IOC_REGDOMAIN, 0,
+ IEEE80211_REGDOMAIN_SPACE(req), req);
+ free(req);
+ free(dc);
}
static int
@@ -980,7 +1006,6 @@ static void
set80211chanlist(const char *val, int d, int s, const struct afswtch *rafp)
{
struct ieee80211req_chanlist chanlist;
-#define MAXCHAN (sizeof(chanlist.ic_channels)*NBBY)
char *temp, *cp, *tp;
temp = malloc(strlen(val) + 1);
@@ -997,18 +1022,18 @@ set80211chanlist(const char *val, int d,
*tp++ = '\0';
switch (sscanf(cp, "%u-%u", &first, &last)) {
case 1:
- if (first > MAXCHAN)
+ if (first > IEEE80211_CHAN_MAX)
errx(-1, "channel %u out of range, max %zu",
- first, MAXCHAN);
+ first, IEEE80211_CHAN_MAX);
setbit(chanlist.ic_channels, first);
break;
case 2:
- if (first > MAXCHAN)
+ if (first > IEEE80211_CHAN_MAX)
errx(-1, "channel %u out of range, max %zu",
- first, MAXCHAN);
- if (last > MAXCHAN)
+ first, IEEE80211_CHAN_MAX);
+ if (last > IEEE80211_CHAN_MAX)
errx(-1, "channel %u out of range, max %zu",
- last, MAXCHAN);
+ last, IEEE80211_CHAN_MAX);
if (first > last)
errx(-1, "void channel range, %u > %u",
first, last);
@@ -1026,7 +1051,6 @@ set80211chanlist(const char *val, int d,
cp = tp;
}
set80211(s, IEEE80211_IOC_CHANLIST, 0, sizeof(chanlist), &chanlist);
-#undef MAXCHAN
}
static void
@@ -1641,7 +1665,7 @@ set80211amsdu(const char *val, int d, in
int amsdu;
if (get80211val(s, IEEE80211_IOC_AMSDU, &amsdu) < 0)
- errx(-1, "cannot get AMSDU setting");
+ err(-1, "cannot get AMSDU setting");
if (d < 0) {
d = -d;
amsdu &= ~d;
@@ -1765,6 +1789,19 @@ chanlookup(const struct ieee80211_channe
return NULL;
}
+static int
+chanfind(const struct ieee80211_channel chans[], int nchans, int flags)
+{
+ int i;
+
+ for (i = 0; i < nchans; i++) {
+ const struct ieee80211_channel *c = &chans[i];
+ if ((c->ic_flags & flags) == flags)
+ return 1;
+ }
+ return 0;
+}
+
static void
regdomain_addchans(struct ieee80211req_chaninfo *ci,
const netband_head *bands,
@@ -1775,53 +1812,72 @@ regdomain_addchans(struct ieee80211req_c
const struct netband *nb;
const struct freqband *b;
struct ieee80211_channel *c, *prev;
- int freq, channelSep;
+ int freq, channelSep, hasHalfChans, hasQuarterChans;
channelSep = (chanFlags & IEEE80211_CHAN_2GHZ) ? 0 : 40;
+ hasHalfChans = chanfind(avail->ic_chans, avail->ic_nchans,
+ IEEE80211_CHAN_HALF |
+ (chanFlags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ)));
+ hasQuarterChans = chanfind(avail->ic_chans, avail->ic_nchans,
+ IEEE80211_CHAN_QUARTER |
+ (chanFlags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ)));
LIST_FOREACH(nb, bands, next) {
b = nb->band;
- if (verbose)
- printf("%s: chanFlags 0x%x b %p\n",
- __func__, chanFlags, b);
+ if (verbose) {
+ printf("%s:", __func__);
+ printb(" chanFlags", chanFlags, IEEE80211_CHAN_BITS);
+ printb(" bandFlags", nb->flags | b->flags,
+ IEEE80211_CHAN_BITS);
+ putchar('\n');
+ }
prev = NULL;
for (freq = b->freqStart; freq <= b->freqEnd; freq += b->chanSep) {
uint32_t flags = nb->flags | b->flags;
/* check if device can operate on this frequency */
- if (chanlookup(avail->ic_chans, avail->ic_nchans, freq, chanFlags) == NULL) {
- if (verbose)
- printf("%u: skip, flags 0x%x not available\n", freq, chanFlags);
- continue;
- }
/*
- * NB: don't enforce 1/2 and 1/4 rate channels being
- * specified in the device's calibration list for
- * 900MHz cards because most are not self-identifying.
+ * XXX GSM frequency mapping is handled in the kernel
+ * so we cannot find them in the calibration table;
+ * just construct the list and the kernel will reject
+ * if it's wrong.
*/
- if ((flags & IEEE80211_CHAN_HALF) &&
- ((chanFlags & IEEE80211_CHAN_HALF) == 0 &&
- (flags & IEEE80211_CHAN_GSM) == 0)) {
+ if (chanlookup(avail->ic_chans, avail->ic_nchans, freq, chanFlags) == NULL &&
+ (flags & IEEE80211_CHAN_GSM) == 0) {
+ if (verbose) {
+ printf("%u: skip, ", freq);
+ printb("flags", chanFlags,
+ IEEE80211_CHAN_BITS);
+ printf(" not available\n");
+ }
+ continue;
+ }
+ if ((flags & IEEE80211_CHAN_HALF) && !hasHalfChans) {
if (verbose)
- printf("%u: skip, device does not support half-rate channels\n", freq);
+ printf("%u: skip, device does not "
+ "support half-rate channel\n",
+ freq);
continue;
}
if ((flags & IEEE80211_CHAN_QUARTER) &&
- ((chanFlags & IEEE80211_CHAN_QUARTER) == 0 &&
- (flags & IEEE80211_CHAN_GSM) == 0)) {
+ !hasQuarterChans) {
if (verbose)
- printf("%u: skip, device does not support quarter-rate channels\n", freq);
+ printf("%u: skip, device does not "
+ "support quarter-rate channel\n",
+ freq);
continue;
}
if ((flags & IEEE80211_CHAN_HT20) &&
(chanFlags & IEEE80211_CHAN_HT20) == 0) {
if (verbose)
- printf("%u: skip, device does not support HT20 operation\n", freq);
+ printf("%u: skip, device does not "
+ "support HT20 operation\n", freq);
continue;
}
if ((flags & IEEE80211_CHAN_HT40) &&
(chanFlags & IEEE80211_CHAN_HT40) == 0) {
if (verbose)
- printf("%u: skip, device does not support HT40 operation\n", freq);
+ printf("%u: skip, device does not "
+ "support HT40 operation\n", freq);
continue;
}
if ((flags & REQ_ECM) && !reg->ecm) {
@@ -1844,10 +1900,12 @@ regdomain_addchans(struct ieee80211req_c
}
if (ci->ic_nchans == IEEE80211_CHAN_MAX) {
if (verbose)
- printf("%u: skip, channel table full\n", freq);
+ printf("%u: skip, channel table full\n",
+ freq);
break;
}
c = &ci->ic_chans[ci->ic_nchans++];
+ memset(c, 0, sizeof(*c));
c->ic_freq = freq;
c->ic_flags = chanFlags |
(flags &~ (REQ_FLAGS | IEEE80211_CHAN_HT40));
@@ -1855,10 +1913,12 @@ regdomain_addchans(struct ieee80211req_c
c->ic_maxregpower = nb->maxPowerDFS;
else
c->ic_maxregpower = nb->maxPower;
- if (verbose)
- printf("[%3d] add freq %u flags 0x%x power %u\n",
- ci->ic_nchans-1, c->ic_freq, c->ic_flags,
- c->ic_maxregpower);
+ if (verbose) {
+ printf("[%3d] add freq %u ",
+ ci->ic_nchans-1, c->ic_freq);
+ printb("flags", c->ic_flags, IEEE80211_CHAN_BITS);
+ printf(" power %u\n", c->ic_maxregpower);
+ }
/* NB: kernel fills in other fields */
prev = c;
}
@@ -1896,30 +1956,23 @@ regdomain_makechannels(
errx(1, "internal error, regdomain %d not found",
reg->regdomain);
if (rd->sku != SKU_DEBUG) {
- memset(ci, 0, sizeof(*ci));
+ /*
+ * regdomain_addchans incrememnts the channel count for
+ * each channel it adds so initialize ic_nchans to zero.
+ * Note that we know we have enough space to hold all possible
+ * channels because the devcaps list size was used to
+ * allocate our request.
+ */
+ ci->ic_nchans = 0;
if (!LIST_EMPTY(&rd->bands_11b))
regdomain_addchans(ci, &rd->bands_11b, reg,
IEEE80211_CHAN_B, &dc->dc_chaninfo);
- if (!LIST_EMPTY(&rd->bands_11g)) {
+ if (!LIST_EMPTY(&rd->bands_11g))
regdomain_addchans(ci, &rd->bands_11g, reg,
IEEE80211_CHAN_G, &dc->dc_chaninfo);
- regdomain_addchans(ci, &rd->bands_11g, reg,
- IEEE80211_CHAN_G | IEEE80211_CHAN_HALF,
- &dc->dc_chaninfo);
- regdomain_addchans(ci, &rd->bands_11g, reg,
- IEEE80211_CHAN_G | IEEE80211_CHAN_QUARTER,
- &dc->dc_chaninfo);
- }
- if (!LIST_EMPTY(&rd->bands_11a)) {
+ if (!LIST_EMPTY(&rd->bands_11a))
regdomain_addchans(ci, &rd->bands_11a, reg,
IEEE80211_CHAN_A, &dc->dc_chaninfo);
- regdomain_addchans(ci, &rd->bands_11a, reg,
- IEEE80211_CHAN_A | IEEE80211_CHAN_HALF,
- &dc->dc_chaninfo);
- regdomain_addchans(ci, &rd->bands_11a, reg,
- IEEE80211_CHAN_A | IEEE80211_CHAN_QUARTER,
- &dc->dc_chaninfo);
- }
if (!LIST_EMPTY(&rd->bands_11na)) {
regdomain_addchans(ci, &rd->bands_11na, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT20,
@@ -1945,7 +1998,8 @@ regdomain_makechannels(
qsort(ci->ic_chans, ci->ic_nchans, sizeof(ci->ic_chans[0]),
regdomain_sort);
} else
- *ci = dc->dc_chaninfo;
+ memcpy(ci, &dc->dc_chaninfo,
+ IEEE80211_CHANINFO_SPACE(&dc->dc_chaninfo));
}
static void
@@ -3065,23 +3119,16 @@ get_chaninfo(const struct ieee80211_chan
buf[0] = '\0';
if (IEEE80211_IS_CHAN_FHSS(c))
strlcat(buf, " FHSS", bsize);
- if (IEEE80211_IS_CHAN_A(c)) {
- if (IEEE80211_IS_CHAN_HALF(c))
- strlcat(buf, " 11a/10Mhz", bsize);
- else if (IEEE80211_IS_CHAN_QUARTER(c))
- strlcat(buf, " 11a/5Mhz", bsize);
- else
- strlcat(buf, " 11a", bsize);
- }
- if (IEEE80211_IS_CHAN_ANYG(c)) {
- if (IEEE80211_IS_CHAN_HALF(c))
- strlcat(buf, " 11g/10Mhz", bsize);
- else if (IEEE80211_IS_CHAN_QUARTER(c))
- strlcat(buf, " 11g/5Mhz", bsize);
- else
- strlcat(buf, " 11g", bsize);
- } else if (IEEE80211_IS_CHAN_B(c))
+ if (IEEE80211_IS_CHAN_A(c))
+ strlcat(buf, " 11a", bsize);
+ else if (IEEE80211_IS_CHAN_ANYG(c))
+ strlcat(buf, " 11g", bsize);
+ else if (IEEE80211_IS_CHAN_B(c))
strlcat(buf, " 11b", bsize);
+ if (IEEE80211_IS_CHAN_HALF(c))
+ strlcat(buf, "/10Mhz", bsize);
+ if (IEEE80211_IS_CHAN_QUARTER(c))
+ strlcat(buf, "/5Mhz", bsize);
if (IEEE80211_IS_CHAN_TURBO(c))
strlcat(buf, " Turbo", bsize);
if (precise) {
@@ -3109,23 +3156,49 @@ print_chaninfo(const struct ieee80211_ch
get_chaninfo(c, verb, buf, sizeof(buf)));
}
+static int
+chanpref(const struct ieee80211_channel *c)
+{
+ if (IEEE80211_IS_CHAN_HT40(c))
+ return 40;
+ if (IEEE80211_IS_CHAN_HT20(c))
+ return 30;
+ if (IEEE80211_IS_CHAN_HALF(c))
+ return 10;
+ if (IEEE80211_IS_CHAN_QUARTER(c))
+ return 5;
+ if (IEEE80211_IS_CHAN_TURBO(c))
+ return 25;
+ if (IEEE80211_IS_CHAN_A(c))
+ return 20;
+ if (IEEE80211_IS_CHAN_G(c))
+ return 20;
+ if (IEEE80211_IS_CHAN_B(c))
+ return 15;
+ if (IEEE80211_IS_CHAN_PUREG(c))
+ return 15;
+ return 0;
+}
+
static void
print_channels(int s, const struct ieee80211req_chaninfo *chans,
int allchans, int verb)
{
- struct ieee80211req_chaninfo achans;
+ struct ieee80211req_chaninfo *achans;
uint8_t reported[IEEE80211_CHAN_BYTES];
const struct ieee80211_channel *c;
int i, half;
- memset(&achans, 0, sizeof(achans));
+ achans = malloc(IEEE80211_CHANINFO_SPACE(chans));
+ if (achans == NULL)
+ errx(1, "no space for active channel list");
+ achans->ic_nchans = 0;
memset(reported, 0, sizeof(reported));
if (!allchans) {
struct ieee80211req_chanlist active;
if (get80211(s, IEEE80211_IOC_CHANLIST, &active, sizeof(active)) < 0)
errx(1, "unable to get active channel list");
- memset(&achans, 0, sizeof(achans));
for (i = 0; i < chans->ic_nchans; i++) {
c = &chans->ic_chans[i];
if (!isset(active.ic_channels, c->ic_ieee))
@@ -3138,9 +3211,9 @@ print_channels(int s, const struct ieee8
*/
if (isset(reported, c->ic_ieee) && !verb) {
/* XXX we assume duplicates are adjacent */
- achans.ic_chans[achans.ic_nchans-1] = *c;
+ achans->ic_chans[achans->ic_nchans-1] = *c;
} else {
- achans.ic_chans[achans.ic_nchans++] = *c;
+ achans->ic_chans[achans->ic_nchans++] = *c;
setbit(reported, c->ic_ieee);
}
}
@@ -3150,33 +3223,37 @@ print_channels(int s, const struct ieee8
/* suppress duplicates as above */
if (isset(reported, c->ic_ieee) && !verb) {
/* XXX we assume duplicates are adjacent */
- achans.ic_chans[achans.ic_nchans-1] = *c;
+ struct ieee80211_channel *a =
+ &achans->ic_chans[achans->ic_nchans-1];
+ if (chanpref(c) > chanpref(a))
+ *a = *c;
} else {
- achans.ic_chans[achans.ic_nchans++] = *c;
+ achans->ic_chans[achans->ic_nchans++] = *c;
setbit(reported, c->ic_ieee);
}
}
}
- half = achans.ic_nchans / 2;
- if (achans.ic_nchans % 2)
+ half = achans->ic_nchans / 2;
+ if (achans->ic_nchans % 2)
half++;
- for (i = 0; i < achans.ic_nchans / 2; i++) {
- print_chaninfo(&achans.ic_chans[i], verb);
- print_chaninfo(&achans.ic_chans[half+i], verb);
+ for (i = 0; i < achans->ic_nchans / 2; i++) {
+ print_chaninfo(&achans->ic_chans[i], verb);
+ print_chaninfo(&achans->ic_chans[half+i], verb);
printf("\n");
}
- if (achans.ic_nchans % 2) {
- print_chaninfo(&achans.ic_chans[i], verb);
+ if (achans->ic_nchans % 2) {
+ print_chaninfo(&achans->ic_chans[i], verb);
printf("\n");
}
+ free(achans);
}
static void
list_channels(int s, int allchans)
{
getchaninfo(s);
- print_channels(s, &chaninfo, allchans, verbose);
+ print_channels(s, chaninfo, allchans, verbose);
}
static void
@@ -3201,48 +3278,52 @@ print_txpow_verbose(const struct ieee802
static void
list_txpow(int s)
{
- struct ieee80211req_chaninfo achans;
+ struct ieee80211req_chaninfo *achans;
uint8_t reported[IEEE80211_CHAN_BYTES];
struct ieee80211_channel *c, *prev;
int i, half;
getchaninfo(s);
- memset(&achans, 0, sizeof(achans));
+ achans = malloc(IEEE80211_CHANINFO_SPACE(chaninfo));
+ if (achans == NULL)
+ errx(1, "no space for active channel list");
+ achans->ic_nchans = 0;
memset(reported, 0, sizeof(reported));
- for (i = 0; i < chaninfo.ic_nchans; i++) {
- c = &chaninfo.ic_chans[i];
+ for (i = 0; i < chaninfo->ic_nchans; i++) {
+ c = &chaninfo->ic_chans[i];
/* suppress duplicates as above */
if (isset(reported, c->ic_ieee) && !verbose) {
/* XXX we assume duplicates are adjacent */
- prev = &achans.ic_chans[achans.ic_nchans-1];
+ prev = &achans->ic_chans[achans->ic_nchans-1];
/* display highest power on channel */
if (c->ic_maxpower > prev->ic_maxpower)
*prev = *c;
} else {
- achans.ic_chans[achans.ic_nchans++] = *c;
+ achans->ic_chans[achans->ic_nchans++] = *c;
setbit(reported, c->ic_ieee);
}
}
if (!verbose) {
- half = achans.ic_nchans / 2;
- if (achans.ic_nchans % 2)
+ half = achans->ic_nchans / 2;
+ if (achans->ic_nchans % 2)
half++;
- for (i = 0; i < achans.ic_nchans / 2; i++) {
- print_txpow(&achans.ic_chans[i]);
- print_txpow(&achans.ic_chans[half+i]);
+ for (i = 0; i < achans->ic_nchans / 2; i++) {
+ print_txpow(&achans->ic_chans[i]);
+ print_txpow(&achans->ic_chans[half+i]);
printf("\n");
}
- if (achans.ic_nchans % 2) {
- print_txpow(&achans.ic_chans[i]);
+ if (achans->ic_nchans % 2) {
+ print_txpow(&achans->ic_chans[i]);
printf("\n");
}
} else {
- for (i = 0; i < achans.ic_nchans; i++) {
- print_txpow_verbose(&achans.ic_chans[i]);
+ for (i = 0; i < achans->ic_nchans; i++) {
+ print_txpow_verbose(&achans->ic_chans[i]);
printf("\n");
}
}
+ free(achans);
}
static void
@@ -3256,29 +3337,34 @@ list_keys(int s)
"\21MONITOR\22DFS\30WPA1\31WPA2\32BURST\33WME\34WDS\36BGSCAN" \
"\37TXFRAG\40TDMA"
-#define IEEE80211_CRYPTO_BITS \
- "\20\1WEP\2TKIP\3AES\4AES_CCM\5TKIPMIC\6CKIP\12PMGT"
-
-#define IEEE80211_HTCAP_BITS \
- "\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \
- "\21AMPDU\22AMSDU\23HT"
-
static void
list_capabilities(int s)
{
- struct ieee80211_devcaps_req dc;
+ struct ieee80211_devcaps_req *dc;
- getdevcaps(s, &dc);
- printb("drivercaps", dc.dc_drivercaps, IEEE80211_C_BITS);
- if (dc.dc_cryptocaps != 0 || verbose) {
+ if (verbose)
+ dc = malloc(IEEE80211_DEVCAPS_SIZE(MAXCHAN));
+ else
+ dc = malloc(IEEE80211_DEVCAPS_SIZE(1));
+ if (dc == NULL)
+ errx(1, "no space for device capabilities");
+ dc->dc_chaninfo.ic_nchans = verbose ? MAXCHAN : 1;
+ getdevcaps(s, dc);
+ printb("drivercaps", dc->dc_drivercaps, IEEE80211_C_BITS);
+ if (dc->dc_cryptocaps != 0 || verbose) {
putchar('\n');
- printb("cryptocaps", dc.dc_cryptocaps, IEEE80211_CRYPTO_BITS);
+ printb("cryptocaps", dc->dc_cryptocaps, IEEE80211_CRYPTO_BITS);
}
- if (dc.dc_htcaps != 0 || verbose) {
+ if (dc->dc_htcaps != 0 || verbose) {
putchar('\n');
- printb("htcaps", dc.dc_htcaps, IEEE80211_HTCAP_BITS);
+ printb("htcaps", dc->dc_htcaps, IEEE80211_HTCAP_BITS);
}
putchar('\n');
+ if (verbose) {
+ chaninfo = &dc->dc_chaninfo; /* XXX */
+ print_channels(s, &dc->dc_chaninfo, 1/*allchans*/, verbose);
+ }
+ free(dc);
}
static int
@@ -3557,7 +3643,7 @@ list_regdomain(int s, int channelsalso)
spacer = ':';
print_regdomain(®domain, 1);
LINE_BREAK();
- print_channels(s, &chaninfo, 1/*allchans*/, 1/*verbose*/);
+ print_channels(s, chaninfo, 1/*allchans*/, 1/*verbose*/);
} else
print_regdomain(®domain, verbose);
}
@@ -4369,6 +4455,7 @@ get80211len(int s, int type, void *data,
(void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
ireq.i_type = type;
ireq.i_len = len;
+ assert(ireq.i_len == len); /* NB: check for 16-bit truncation */
ireq.i_data = data;
if (ioctl(s, SIOCG80211, &ireq) < 0)
return -1;
@@ -4400,6 +4487,7 @@ set80211(int s, int type, int val, int l
ireq.i_type = type;
ireq.i_val = val;
ireq.i_len = len;
+ assert(ireq.i_len == len); /* NB: check for 16-bit truncation */
ireq.i_data = data;
if (ioctl(s, SIOCS80211, &ireq) < 0)
err(1, "SIOCS80211");
More information about the svn-src-projects
mailing list