PERFORCE change 130135 for review

Sam Leffler sam at FreeBSD.org
Mon Dec 3 20:11:37 PST 2007


http://perforce.freebsd.org/chv.cgi?CH=130135

Change 130135 by sam at sam_ebb on 2007/12/04 04:11:00

	sync w/ vap code base

Affected files ...

.. //depot/projects/vap/sbin/ifconfig/ifconfig.8#5 edit
.. //depot/projects/vap/sbin/ifconfig/ifieee80211.c#9 edit

Differences ...

==== //depot/projects/vap/sbin/ifconfig/ifconfig.8#5 (text+ko) ====

@@ -28,7 +28,7 @@
 .\"     From: @(#)ifconfig.8	8.3 (Berkeley) 1/5/94
 .\" $FreeBSD: src/sbin/ifconfig/ifconfig.8,v 1.144 2007/11/04 08:32:26 thompsa Exp $
 .\"
-.Dd October 31, 2007
+.Dd Deceober 3, 2007
 .Dt IFCONFIG 8
 .Os
 .Sh NAME
@@ -580,6 +580,28 @@
 Disabling the internal bridging
 is useful when traffic is to be processed with
 packet filtering.
+.It Cm ampdu
+When operating in 802.11n enable use of A-MPDU for transmitting
+and receiving packets.
+To disable use of A-MPDU
+.Fl ampdu
+can be used.
+To control A-MPDU receive only use
+.Cm ampdurx ;
+for transmit only use
+.Cm ampdutx .
+.It Cm amsdu
+When operating in 802.11n enable use of A-MSDU for transmitting
+and receiving packets.
+Note that A-MSDU receive must be supported but transmit support
+is optional.
+To disable use of A-MSDU
+.Fl amsdu
+can be used.
+To enable A-MSDU receive use
+.Cm amsdurx ;
+for transmit only use
+.Cm amsdutx .
 .It Cm authmode Ar mode
 Set the desired authentication mode in infrastructure mode.
 Not all adaptors support all modes.
@@ -755,18 +777,33 @@
 of the extension channel by appending ``+'' or ``-'' for above and below,
 respectively; e.g. ``2437:ht/40+'' specifies 40MHz wide HT operation 
 with the center channel at frequency 2437 and the extension channel above.
-.It Cm doth
-Enable inclusion of an 802.11h country information element in beacon
-frames transmitted when operating as an access point.
-By default 802.11h is enabled if the device is capable.
-To disable 802.11h use
-.Fl doth .
+.It Cm country Ar code
+Set the country code for regulatory constraints.
+The
+.Ar code
+is either a 2-letter ISO country code specification or the numeric
+mapping of the code.
 .It Cm deftxkey Ar index
 Set the default key to use for transmission.
 Typically this is only set when using WEP encryption.
 The
 .Cm weptxkey
 is an alias for this request; it is provided for backwards compatibility.
+.It Cm dfs
+Enable DFS support on the access point.
+When DFS is enabled channels marked as requiring DFS follow
+the DFS specification for monitoring and handling radar events.
+To disable DFS support, use
+.Fl dfs .
+.It Cm doth
+Enable 802.11h support on the access point.
+When 802.11h is enabled management frames indicate spectrum management
+in the capabilities and include country and
+power constraint information elements.
+Also, channel changes are handled in a staged fashion
+with Channel Switch Announcements (CSA).
+To disable 802.11h support, use
+.Fl doth .
 .It Cm dtimperiod Ar period
 Set the
 DTIM
@@ -794,6 +831,31 @@
 command to identify the channels where turbo mode may be used.
 To disable Dynamic Turbo mode use
 .Fl dturbo .
+.It Cm dwds
+Enable Dynamic Wireless Distribution System (DWDS) support on
+the access point or station.
+When DWDS is enabled on an ap, stations that associate and pass 4-address
+frames generate ``DWDS discovery events'' to a user application
+that can create a WDS interface associated with that station.
+Once plumbed into the system this interface establishes a conduit
+by which encapsulated wireless traffic can be passed.
+When DWDS is enabled on a station, 4-address frames are permitted to
+flow between the station and the peer access point.
+To disable DWDS support, use
+.Fl dwds .
+.It Cm ff
+Enable the use of Atheros Fast Frames when communicating with
+another Fast Frames-capable station.
+Fast Frames are an encapsulation technique by which two 802.3
+frames are transmitted in a single 802.11 frame.
+This can noticeably improve throughput but requires that the
+receiving station understand how to decapsulate the frame.
+Fast frame use is negotiated using the Atheros 802.11 vendor-specific
+protocol extension so enabling use is safe when communicating with
+non-Atheros devices.
+By default, use of fast frames is enabled if the device is capable.
+To explicitly disable fast frames, use
+.Fl ff .
 .It Cm fragthreshold Ar length
 Set the threshold for which transmitted frames are broken into fragments.
 The
@@ -816,19 +878,51 @@
 undirected probe request frames are answered.
 To re-enable the broadcast of the SSID etc., use
 .Fl hidessid .
-.It Cm ff
-Enable the use of Atheros Fast Frames when communicating with
-another Fast Frames-capable station.
-Fast Frames are an encapsulation technique by which two 802.3
-frames are transmitted in a single 802.11 frame.
-This can noticeably improve throughput but requires that the
-receiving station understand how to decapsulate the frame.
-Fast frame use is negotiated using the Atheros 802.11 vendor-specific
-protocol extension so enabling use is safe when communicating with
-non-Atheros devices.
-By default, use of fast frames is enabled if the device is capable.
-To explicitly disable fast frames, use
-.Fl ff .
+.It Cm ht
+When operating with 802.11n enable HT operation (both HT20 and HT40).
+To disable this facility use
+.Fl ht .
+.It Cm ht20
+When operating with 802.11n enable only HT20 operation
+(HT over 20MHz wide channels).
+Disabling HT20 use is done with
+.Fl ht20
+and is equivalent to specifying
+.Fl ht .
+.It Cm htcompat
+When operating in 802.11n include Vendor Information Elements
+in management frames for compatibility with pre-Draft 1.10
+drivers and devices.
+To disable this facility use
+.Fl htcompat .
+.It Cm htprotmode Ar technique
+For interfaces operating in 802.11n, use the specified
+.Ar technique
+for protecting frames in a mixed HT/non-HT network.
+The set of valid techniques is
+.Cm off ,
+and
+.Cm rts
+(RTS/CTS).
+Technique names are case insensitive.
+.It Cm inact
+When operating as an access point or in adhoc mode, check for
+inactive stations and when the inactivity limit reaches a
+threshold probe the station to see if its still present.
+Inactive stations that do not respond to probes are dropped
+(disassociated when operating as an access point).
+Inactivity processing is done by default, to disable it use
+.Fl inact .
+.It Cm indoor
+Specify the physical location of the wireless device for
+regulatory purpose.
+This defines the location included in any 802.11h country information
+element included in beacons frames transmit when operating as an
+access point.
+When operating in station mode this setting is ignored if the
+access point provides the information in its beacon frame.
+See also
+.Cm outdoor .
 .It Cm list active
 Display the list of channels available for use taking into account
 any restrictions set with the
@@ -913,7 +1007,11 @@
 using extended transmit rates.
 .It Li H
 High Throughput (HT).
-Indicates that the station is using MCS to send/receive frames.
+Indicates that the station is using HT transmit rates.
+If a `+' follows immediately after then the station associated
+using deprecated mechanisms supported only when
+.Cm htcompat
+is enabled.
 .It Li P
 Power Save.
 Indicates that the station is operating in power save mode.
@@ -922,6 +1020,14 @@
 Indicates that the station is using QoS encapsulation for
 data frame.
 QoS encapsulation is enabled only when WME mode is enabled.
+.It Li T
+Transitional Security Network (TSN).
+Indicates that the station associated using TSN; see also
+.Cm tsn
+below.
+.It Li W
+Wi-Fi Protected Setup (WPS).
+Indicates that the station associated using WPS.
 .El
 .Pp
 By default information elements received from associated stations
@@ -942,6 +1048,16 @@
 This rate should be valid for the current operating conditions;
 if an invalid rate is specified drivers are free to chose an
 appropriate rate.
+.It Cm outdoor
+Specify the physical location of the wireless device for
+regulatory purpose.
+This defines the location included in any 802.11h country information
+element included in beacons frames transmit when operating as an
+access point.
+When operating in station mode this setting is ignored if the
+access point provides the information in its beacon frame.
+See also
+.Cm indoor .
 .It Cm powersave
 Enable powersave operation.
 When operating as a client, the station will conserve power by
@@ -977,6 +1093,17 @@
 permitted to associate).
 To allow both 11g and 11b-only stations to associate, use
 .Fl pureg .
+.It Cm puren
+When operating as an access point in 802.11n mode allow only
+HT-capable stations to associate (legacy stations are not
+permitted to associate).
+To allow both HT and legacy stations to associate, use
+.Fl puren .
+.It Cm regdomain Ar code
+Set the regulatory domain code for regulatory constraints.
+The
+.Ar code
+is either a SKU string or the numeric mapping of the string.
 .It Cm roaming Ar mode
 When operating as a station, control how the system will
 behave when communication with the current access point
@@ -996,12 +1123,11 @@
 Manual mode is used by applications such as
 .Xr wpa_supplicant 8
 that want to control the selection of an access point.
-.It Cm roam:rssi11a Ar rssi
-Set the threshold for controlling roaming when operating in an
-802.11a BSS.
+.It Cm roam:rssi Ar rssi
+Set the threshold for controlling roaming when operating as a station.
 The
 .Ar rssi
-parameter specifies the receive signal strength in dBm units
+parameter specifies the receive signal strength in .5 dBm units
 at which roaming should be considered.
 If the current rssi drops below this setting and background scanning
 is enabled, then the system will check if a more desirable access point is
@@ -1014,30 +1140,12 @@
 By default
 .Ar rssi
 is set to 7 dBm.
-.It Cm roam:rssi11b Ar rssi
-Set the threshold for controlling roaming when operating in an
-802.11b-only BSS.
-See 
-.Cm roam:rssi11a
-for a description of this parameter.
-By default
-.Ar rssi
-is set to 7 dBm.
-.It Cm roam:rssi11g Ar rssi
-Set the threshold for controlling roaming when operating in a
-(mixed) 802.11g BSS.
-See 
-.Cm roam:rssi11a
-for a description of this parameter.
-By default
-.Ar rssi
-is set to 7 dBm.
-.It Cm roam:rate11a Ar rate
-Set the threshold for controlling roaming when operating in an
-802.11a BSS.
+.It Cm roam:rate Ar rate
+Set the threshold for controlling roaming when operating as a station.
 The
 .Ar rate
-parameter specifies the transmit rate in megabits
+parameter specifies the legacy transmit rate in megabits, or the
+MCS when operating with HT enabled,
 at which roaming should be considered.
 If the current transmit rate drops below this setting and background scanning
 is enabled, then the system will check if a more desirable access point is
@@ -1049,25 +1157,9 @@
 any selection occurs.
 By default
 .Ar rate
-is set to 12 Mb/s.
-.It Cm roam:rate11b Ar rate
-Set the threshold for controlling roaming when operating in an
-802.11b-only BSS.
-See 
-.Cm roam:rate11a
-for a description of this parameter.
-By default
-.Ar rate
-is set to 1 Mb/s.
-.It Cm roam:rate11g Ar rate
-Set the threshold for controlling roaming when operating in a
-(mixed) 802.11g BSS.
-See 
-.Cm roam:rate11a
-for a description of this parameter.
-By default
-.Ar rate
-is set to 5 Mb/s.
+is set to 12 Mb/s for 802.11a,
+1 Mb/s for 802.11b, and
+5.5 Mb/s for 802.11g.
 .It Cm rtsthreshold Ar length
 Set the threshold for which
 transmitted frames are preceded by transmission of an
@@ -1086,6 +1178,13 @@
 .Cm -
 disables transmission of RTS frames.
 Not all adaptors support setting the RTS threshold.
+.It Cm shortgi
+Enable use of Short Guard Interval when operating in 802.11n
+on an HT channel.
+NB: this currently enables Short GI on both HT40 and HT20 channels;
+this will be split out shortly.
+To disable Short GI use
+.Fl shortgi .
 .It Cm ssid Ar ssid
 Set the desired Service Set Identifier (aka network name).
 The SSID is a string up to 32 characters
@@ -1192,6 +1291,11 @@
 As such it only
 seems to be meaningful to identical or virtually identical equipment.
 Setting the station name is identical in syntax to setting the SSID.
+.It Cm tsn
+When operating as an access point with WPA/802.11i allow legacy
+stations to associate using static key WEP and open authentication.
+To disallow legacy station use of WEP, use
+.Fl tsn .
 .It Cm txpower Ar power
 Set the power used to transmit frames.
 The

==== //depot/projects/vap/sbin/ifconfig/ifieee80211.c#9 (text+ko) ====

@@ -77,9 +77,8 @@
 #include <net/if_media.h>
 #include <net/route.h>
 
-#include <net80211/ieee80211.h>
-#include <net80211/ieee80211_crypto.h>
 #include <net80211/ieee80211_ioctl.h>
+#include <net80211/ieee80211_regdomain.h>
 
 #include <ctype.h>
 #include <err.h>
@@ -95,6 +94,21 @@
 
 #include "ifconfig.h"
 
+#ifndef IEEE80211_FIXED_RATE_NONE
+#define	IEEE80211_FIXED_RATE_NONE	0xff
+#endif
+/* XXX need these publicly defined or similar */
+#ifndef IEEE80211_NODE_AUTH
+#define	IEEE80211_NODE_AUTH	0x0001		/* authorized for data */
+#define	IEEE80211_NODE_QOS	0x0002		/* QoS enabled */
+#define	IEEE80211_NODE_ERP	0x0004		/* ERP enabled */
+#define	IEEE80211_NODE_PWR_MGT	0x0010		/* power save mode enabled */
+#define	IEEE80211_NODE_HT	0x0040		/* HT enabled */
+#define	IEEE80211_NODE_HTCOMPAT	0x0080		/* HT setup w/ vendor OUI's */
+#define	IEEE80211_NODE_WPS	0x0100		/* WPS association */
+#define	IEEE80211_NODE_TSN	0x0200		/* TSN association */
+#endif
+
 #define	MAXCOL	78
 static	int col;
 static	char spacer;
@@ -103,6 +117,50 @@
 static void LINE_BREAK(void);
 static void LINE_CHECK(const char *fmt, ...);
 
+#define	REQ_ECM		0x01000000	/* enable if ECM set */
+#define	REQ_OUTDOOR	0x02000000	/* enable for outdoor operation */
+#define	REQ_FLAGS	0xff000000	/* private flags, don't pass to os */
+
+struct freqband {
+	uint16_t	freqStart;	/* starting frequency (MHz) */
+	uint16_t	freqEnd;	/* ending frequency (MHz) */
+	uint8_t		chanWidth;	/* channel width (MHz) */
+	uint8_t		chanSep;	/* channel sepaaration (MHz) */
+	uint32_t	flags;		/* common operational constraints */
+};
+struct netband {
+	const struct freqband *b;	/* channel list description */
+	uint8_t		maxPower;	/* regulatory cap on tx power (dBm) */
+	uint8_t		maxPowerDFS;	/* regulatory cap w/ DFS (dBm) */
+	uint32_t	flags;		/* net80211 channel flags */
+};
+
+#define	MAXFBANDS	10		/* XXX could define per netband */
+
+struct regdomain {
+	enum RegdomainCode sku;		/* regdomain code/SKU */
+	const char *name;		/* printable name */ 
+	enum ISOCountryCode cc;		/* country code for 1-1/default map */
+
+	struct netband bands_11b[MAXFBANDS];	/* 11b operation */
+	struct netband bands_11g[MAXFBANDS];	/* 11g operation */
+	struct netband bands_11a[MAXFBANDS];	/* 11a operation */
+	struct netband bands_11ng[MAXFBANDS];	/* 11ng operation */
+	struct netband bands_11na[MAXFBANDS];	/* 11na operation */
+};
+
+struct countrycode {
+	enum ISOCountryCode	code;	   
+	const struct regdomain	*rd;
+	const char*		isoname;
+	const char*		name;
+};
+
+static const char *modename[] = {
+	"auto", "11a", "11b", "11g", "fh", "turboA", "turboG",
+	"sturbo", "11na", "11ng"
+};
+
 /* XXX need max array size */
 static const int htrates[16] = {
 	13,		/* IFM_IEEE80211_MCS0 */
@@ -123,18 +181,32 @@
 	260,		/* IFM_IEEE80211_MCS15 */
 };
 
+static void set80211(int s, int type, int val, int len, void *data);
 static int get80211(int s, int type, void *data, int len);
 static int get80211len(int s, int type, void *data, int len, int *plen);
 static int get80211val(int s, int type, int *val);
-static void set80211(int s, int type, int val, int len, void *data);
 static const char *get_string(const char *val, const char *sep,
     u_int8_t *buf, int *lenp);
 static void print_string(const u_int8_t *buf, int len);
+static void print_regdomain(const struct ieee80211_regdomain *, int);
+static void print_channels(int, const struct ieee80211req_chaninfo *,
+    int allchans, int verbose);
+static void regdomain_makechannels(struct ieee80211_regdomain_req *,
+    const struct ieee80211_devcaps_req *);
+static const struct regdomain *regdomain_lookupbyrd(enum RegdomainCode sku);
+static const struct regdomain *regdomain_lookupbyname(const char *name);
+static const struct countrycode *countrycode_lookupbycc(enum ISOCountryCode);
+static const struct countrycode *countrycode_lookupbyname(const char *);
 
 static struct ieee80211req_chaninfo chaninfo;
-static struct ifmediareq *ifmr;
+static struct ieee80211_regdomain regdomain;
+static struct ieee80211_roamparams_req roamparams;
+static int gotroam = 0;
+static struct ieee80211_txparams_req txparams;
+static int gottxparams = 0;
 static struct ieee80211_channel curchan;
 static int gotcurchan = 0;
+static struct ifmediareq *ifmr;
 static int htconf = 0;
 static	int gothtconf = 0;
 
@@ -159,7 +231,6 @@
 		return;
 	if (get80211(s, IEEE80211_IOC_CHANINFO, &chaninfo, sizeof(chaninfo)) < 0)
 		errx(1, "unable to get channel information");
-
 	ifmr = ifmedia_getstate(s);
 	gethtconf(s);
 }
@@ -308,6 +379,160 @@
 	return &curchan;
 }
 
+static enum ieee80211_phymode
+chan2mode(const struct ieee80211_channel *c)
+{
+	if (IEEE80211_IS_CHAN_HTA(c))
+		return IEEE80211_MODE_11NA;
+	if (IEEE80211_IS_CHAN_HTG(c))
+		return IEEE80211_MODE_11NG;
+	if (IEEE80211_IS_CHAN_108A(c))
+		return IEEE80211_MODE_TURBO_A;
+	if (IEEE80211_IS_CHAN_108G(c))
+		return IEEE80211_MODE_TURBO_G;
+	if (IEEE80211_IS_CHAN_ST(c))
+		return IEEE80211_MODE_STURBO_A;
+	if (IEEE80211_IS_CHAN_FHSS(c))
+		return IEEE80211_MODE_FH;
+	if (IEEE80211_IS_CHAN_A(c))
+		return IEEE80211_MODE_11A;
+	if (IEEE80211_IS_CHAN_ANYG(c))
+		return IEEE80211_MODE_11G;
+	if (IEEE80211_IS_CHAN_B(c))
+		return IEEE80211_MODE_11B;
+	return IEEE80211_MODE_AUTO;
+}
+
+static void
+getroam(int s)
+{
+	if (gotroam)
+		return;
+	if (get80211(s, IEEE80211_IOC_ROAM,
+	    &roamparams, sizeof(roamparams)) < 0)
+		errx(1, "unable to get roaming parameters");
+	gotroam = 1;
+}
+
+static void
+setroam_cb(int s, void *arg)
+{
+	struct ieee80211_roamparams_req *roam = arg;
+	set80211(s, IEEE80211_IOC_ROAM, 0, sizeof(*roam), roam);
+}
+
+static void
+gettxparams(int s)
+{
+	if (gottxparams)
+		return;
+	if (get80211(s, IEEE80211_IOC_TXPARAMS,
+	    &txparams, sizeof(txparams)) < 0)
+		errx(1, "unable to get transmit parameters");
+	gottxparams = 1;
+}
+
+static void
+settxparams_cb(int s, void *arg)
+{
+	struct ieee80211_txparams_req *txp = arg;
+	set80211(s, IEEE80211_IOC_TXPARAMS, 0, sizeof(*txp), txp);
+}
+
+static void
+getregdomain(int s)
+{
+	static int gotrd = 0;
+
+	if (gotrd)
+		return;
+	if (get80211(s, IEEE80211_IOC_REGDOMAIN,
+	    &regdomain, sizeof(regdomain)) < 0)
+		errx(1, "unable to get regulatory domain info");
+	gotrd = 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");
+}
+
+static void
+setregdomain_cb(int s, void *arg)
+{
+	struct ieee80211_regdomain_req req;
+	struct ieee80211_regdomain *rd = arg;
+	struct ieee80211_devcaps_req dc;
+
+	if (rd->country != 0) {
+		const struct countrycode *cc;
+		/*
+		 * Check current country seting to make sure it's
+		 * compatible with the new regdomain.  If not, then
+		 * override it with any default country for this
+		 * SKU.  If we cannot arrange a match, then abort.
+		 */
+		cc = countrycode_lookupbycc(rd->country);
+		if (cc == NULL)
+			errx(1, "unknown ISO country code %d", rd->country);
+		if (cc->rd->sku != rd->regdomain) {
+			const struct regdomain *rp;
+			/*
+			 * Check if country is incompatible with regdomain.
+			 * To enable multiple regdomains for a country code
+			 * we permit a mismatch between the regdomain and
+			 * the country's associated regdomain when the
+			 * regdomain is setup w/o a default country.  For
+			 * example, US is bound to the FCC regdomain but
+			 * we allow US to be combined with FCC3 because FCC3
+			 * has not default country.  This allows bogus
+			 * combinations like FCC3+DK which are resolved when
+			 * constructing the channel list by deferring to the
+			 * regdomain to construct the channel list.
+			 */
+			rp = regdomain_lookupbyrd(rd->regdomain);
+			if (rp == NULL)
+				errx(1, "country %s (%s) is not usable with "
+				    "regdomain %d", cc->isoname, cc->name,
+				    rd->regdomain);
+			else if (rp->cc != 0 && rp->cc != cc->code)
+				errx(1, "country %s (%s) is not usable with "
+				   "regdomain %s", cc->isoname, cc->name,
+				   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);
+#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*/);
+	}
+#endif
+	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*/);
+	}
+	if (req.chaninfo.ic_nchans == 0)
+		errx(1, "no channels calculated");
+	set80211(s, IEEE80211_IOC_REGDOMAIN, 0, sizeof(req), &req);
+}
+
 static int
 ieee80211_mhz2ieee(int freq, int flags)
 {
@@ -332,7 +557,7 @@
 
 	ssid = 0;
 	len = strlen(val);
-	if (len > 2 && isdigit(val[0]) && val[1] == ':') {
+	if (len > 2 && isdigit((int)val[0]) && val[1] == ':') {
 		ssid = atoi(val)-1;
 		val += 2;
 	}
@@ -503,6 +728,26 @@
 }
 
 static void
+set80211chanswitch(const char *val, int d, int s, const struct afswtch *rafp)
+{
+	struct ieee80211_chanswitch_req csr;
+	int v, flags;
+
+	memset(&csr, 0, sizeof(csr));
+	getchaninfo(s);
+	v = atoi(val);
+	flags = getchannelflags(val, v);
+	if (v > 255) {		/* treat as frequency */
+		mapfreq(&csr.csa_chan, v, flags);
+	} else {
+		mapchan(&csr.csa_chan, v, flags);
+	}
+	csr.csa_mode = 1;
+	csr.csa_count = 5;
+	set80211(s, IEEE80211_IOC_CHANSWITCH, 0, sizeof(csr), &csr);
+}
+
+static void
 set80211authmode(const char *val, int d, int s, const struct afswtch *rafp)
 {
 	int	mode;
@@ -609,7 +854,7 @@
 	int		len;
 	u_int8_t	data[IEEE80211_KEYBUF_SIZE];
 
-	if (isdigit(val[0]) && val[1] == ':') {
+	if (isdigit((int)val[0]) && val[1] == ':') {
 		key = atoi(val)-1;
 		val += 2;
 	}
@@ -635,7 +880,7 @@
 
 	set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL);
 
-	if (isdigit(val[0]) && val[1] == ':') {
+	if (isdigit((int)val[0]) && val[1] == ':') {
 		txkey = val[0]-'0'-1;
 		val += 2;
 
@@ -1040,47 +1285,271 @@
 	set80211(s, IEEE80211_IOC_SCANVALID, atoi(val), 0, NULL);
 }
 
-static
-DECL_CMD_FUNC(set80211roamrssi11a, val, d)
+/*
+ * Parse an optional trailing specification of which netbands
+ * to apply a parameter to.  This is basically the same syntax
+ * as used for channels but you can concatenate to specify
+ * multiple.  For example:
+ *	14:abg		apply to 11a, 11b, and 11g
+ *	6:ht		apply to 11na and 11ng
+ * We don't make a big effort to catch silly things; this is
+ * really a convenience mechanism.
+ */
+static int
+getmodeflags(const char *val)
 {
-	set80211(s, IEEE80211_IOC_ROAM_RSSI_11A, atoi(val), 0, NULL);
+	const char *cp;
+	int flags;
+
+	flags = 0;
+
+	cp = strchr(val, ':');
+	if (cp != NULL) {
+		for (cp++; isalpha((int) *cp); cp++) {
+			/* accept mixed case */
+			int c = *cp;
+			if (isupper(c))
+				c = tolower(c);
+			switch (c) {
+			case 'a':		/* 802.11a */
+				flags |= IEEE80211_CHAN_A;
+				break;
+			case 'b':		/* 802.11b */
+				flags |= IEEE80211_CHAN_B;
+				break;
+			case 'g':		/* 802.11g */
+				flags |= IEEE80211_CHAN_G;
+				break;
+			case 'h':		/* ht = 802.11n */
+			case 'n':		/* 802.11n */
+				flags |= IEEE80211_CHAN_HT;
+				break;
+			case 'd':		/* dt = Atheros Dynamic Turbo */
+				flags |= IEEE80211_CHAN_TURBO;
+				break;
+			case 't':		/* ht, dt, st, t */
+				/* dt and unadorned t specify Dynamic Turbo */
+				if ((flags & (IEEE80211_CHAN_STURBO|IEEE80211_CHAN_HT)) == 0)
+					flags |= IEEE80211_CHAN_TURBO;
+				break;
+			case 's':		/* st = Atheros Static Turbo */
+				flags |= IEEE80211_CHAN_STURBO;
+				break;
+			default:
+				errx(-1, "%s: Invalid mode attribute %c\n",
+				    val, *cp);
+			}
+		}
+	}
+	return flags;
 }
 
+#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT|IEEE80211_CHAN_5GHZ)
+#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT|IEEE80211_CHAN_2GHZ)
+
+#define	_APPLY(_flags, _base, _param, _v) do {				\
+    if (_flags & IEEE80211_CHAN_HT) {					\
+	    if ((_flags & (IEEE80211_CHAN_5GHZ|IEEE80211_CHAN_2GHZ)) == 0) {\
+		    _base.params[IEEE80211_MODE_11NA]._param = _v;	\
+		    _base.params[IEEE80211_MODE_11NG]._param = _v;	\
+	    } else if (_flags & IEEE80211_CHAN_5GHZ)			\
+		    _base.params[IEEE80211_MODE_11NA]._param = _v;	\
+	    else							\
+		    _base.params[IEEE80211_MODE_11NG]._param = _v;	\
+    }									\
+    if (_flags & IEEE80211_CHAN_TURBO) {				\
+	    if ((_flags & (IEEE80211_CHAN_5GHZ|IEEE80211_CHAN_2GHZ)) == 0) {\
+		    _base.params[IEEE80211_MODE_TURBO_A]._param = _v;	\
+		    _base.params[IEEE80211_MODE_TURBO_G]._param = _v;	\
+	    } else if (_flags & IEEE80211_CHAN_5GHZ)			\
+		    _base.params[IEEE80211_MODE_TURBO_A]._param = _v;	\
+	    else							\
+		    _base.params[IEEE80211_MODE_TURBO_G]._param = _v;	\
+    }									\
+    if (_flags & IEEE80211_CHAN_STURBO)					\
+	    _base.params[IEEE80211_MODE_STURBO_A]._param = _v;		\
+    if ((_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)		\
+	    _base.params[IEEE80211_MODE_11A]._param = _v;		\
+    if ((_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)		\
+	    _base.params[IEEE80211_MODE_11G]._param = _v;		\
+    if ((_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)		\
+	    _base.params[IEEE80211_MODE_11B]._param = _v;		\
+} while (0)
+#define	_APPLY1(_flags, _base, _param, _v) do {				\
+    if (_flags & IEEE80211_CHAN_HT) {					\
+	    if (_flags & IEEE80211_CHAN_5GHZ)				\
+		    _base.params[IEEE80211_MODE_11NA]._param = _v;	\
+	    else							\
+		    _base.params[IEEE80211_MODE_11NG]._param = _v;	\
+    } else if ((_flags & IEEE80211_CHAN_108A) == IEEE80211_CHAN_108A)	\
+	    _base.params[IEEE80211_MODE_TURBO_A]._param = _v;		\
+    else if ((_flags & IEEE80211_CHAN_108G) == IEEE80211_CHAN_108G)	\
+	    _base.params[IEEE80211_MODE_TURBO_G]._param = _v;		\
+    else if ((_flags & IEEE80211_CHAN_ST) == IEEE80211_CHAN_ST)		\
+	    _base.params[IEEE80211_MODE_STURBO_A]._param = _v;		\
+    else if ((_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)		\
+	    _base.params[IEEE80211_MODE_11A]._param = _v;		\
+    else if ((_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)		\
+	    _base.params[IEEE80211_MODE_11G]._param = _v;		\
+    else if ((_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)		\
+	    _base.params[IEEE80211_MODE_11B]._param = _v;		\
+} while (0)
+#define	_APPLY_RATE(_flags, _base, _param, _v) do {			\
+    if (_flags & IEEE80211_CHAN_HT) {					\
+	    if ((_flags & (IEEE80211_CHAN_5GHZ|IEEE80211_CHAN_2GHZ)) == 0) {\
+		    _base.params[IEEE80211_MODE_11NA]._param = _v|0x80;	\
+		    _base.params[IEEE80211_MODE_11NG]._param = _v|0x80;	\
+	    } else if (_flags & IEEE80211_CHAN_5GHZ)			\
+		    _base.params[IEEE80211_MODE_11NA]._param = _v|0x80;	\
+	    else							\
+		    _base.params[IEEE80211_MODE_11NG]._param = _v|0x80;	\
+    }									\
+    if (_flags & IEEE80211_CHAN_TURBO) {				\
+	    if ((_flags & (IEEE80211_CHAN_5GHZ|IEEE80211_CHAN_2GHZ)) == 0) {\
+		    _base.params[IEEE80211_MODE_TURBO_A]._param = 2*_v;	\
+		    _base.params[IEEE80211_MODE_TURBO_G]._param = 2*_v;	\
+	    } else if (_flags & IEEE80211_CHAN_5GHZ)			\
+		    _base.params[IEEE80211_MODE_TURBO_A]._param = 2*_v;	\
+	    else							\
+		    _base.params[IEEE80211_MODE_TURBO_G]._param = 2*_v;	\
+    }									\
+    if (_flags & IEEE80211_CHAN_STURBO)					\
+	    _base.params[IEEE80211_MODE_STURBO_A]._param = 2*_v;	\
+    if ((_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)		\
+	    _base.params[IEEE80211_MODE_11A]._param = 2*_v;		\
+    if ((_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)		\
+	    _base.params[IEEE80211_MODE_11G]._param = (_v == 5 ? 11 : 2*_v);\
+    if ((_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)		\
+	    _base.params[IEEE80211_MODE_11B]._param = (_v == 5 ? 11 : 2*_v);\
+} while (0)
+#define	_APPLY_RATE1(_flags, _base, _param, _v) do {			\
+    if (_flags & IEEE80211_CHAN_HT) {					\
+	    if (_flags & IEEE80211_CHAN_5GHZ)				\
+		    _base.params[IEEE80211_MODE_11NA]._param = _v|0x80;	\
+	    else							\
+		    _base.params[IEEE80211_MODE_11NG]._param = _v|0x80;	\
+    } else if ((_flags & IEEE80211_CHAN_108A) == IEEE80211_CHAN_108A)	\
+	    _base.params[IEEE80211_MODE_TURBO_A]._param = 2*_v;		\
+    else if ((_flags & IEEE80211_CHAN_108G) == IEEE80211_CHAN_108G)	\
+	    _base.params[IEEE80211_MODE_TURBO_G]._param = 2*_v;		\
+    else if ((_flags & IEEE80211_CHAN_ST) == IEEE80211_CHAN_ST)		\
+	    _base.params[IEEE80211_MODE_STURBO_A]._param = 2*_v;	\
+    else if ((_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)		\
+	    _base.params[IEEE80211_MODE_11A]._param = 2*_v;		\
+    else if ((_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)		\
+	    _base.params[IEEE80211_MODE_11G]._param = (_v == 5 ? 11 : 2*_v);\
+    else if ((_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)		\
+	    _base.params[IEEE80211_MODE_11B]._param = (_v == 5 ? 11 : 2*_v);\
+} while (0)
+
 static
-DECL_CMD_FUNC(set80211roamrssi11b, val, d)
+DECL_CMD_FUNC(set80211roamrssi, val, d)
 {
-	set80211(s, IEEE80211_IOC_ROAM_RSSI_11B, atoi(val), 0, NULL);
+	double v = atof(val);
+	int rssi, flags;
+
+	rssi = (int) (2*v);
+	if (rssi != 2*v)
+		errx(-1, "invalid rssi (must be .5 dBm units)");
+	flags = getmodeflags(val);
+	getroam(s);
+	if (flags == 0) {		/* NB: no flags => current channel */
+		flags = getcurchan(s)->ic_flags;
+		_APPLY1(flags, roamparams, rssi, rssi);
+	} else
+		_APPLY(flags, roamparams, rssi, rssi);
+	callback_register(setroam_cb, &roamparams);
 }
 
 static
-DECL_CMD_FUNC(set80211roamrssi11g, val, d)
+DECL_CMD_FUNC(set80211roamrate, val, d)
 {
-	set80211(s, IEEE80211_IOC_ROAM_RSSI_11G, atoi(val), 0, NULL);
+	int v = atoi(val), flags;
+
+	flags = getmodeflags(val);
+	getroam(s);
+	if (flags == 0) {		/* NB: no flags => current channel */
+		flags = getcurchan(s)->ic_flags;
+		_APPLY_RATE1(flags, roamparams, rate, v);
+	} else
+		_APPLY_RATE(flags, roamparams, rate, v);
+	callback_register(setroam_cb, &roamparams);
 }
 
 static
-DECL_CMD_FUNC(set80211roamrate11a, val, d)
+DECL_CMD_FUNC(set80211mcastrate, val, d)
 {
-	set80211(s, IEEE80211_IOC_ROAM_RATE_11A, 2*atoi(val), 0, NULL);
+	int v = atoi(val), flags;
+
+	flags = getmodeflags(val);
+	gettxparams(s);
+	if (flags == 0) {		/* NB: no flags => current channel */
+		flags = getcurchan(s)->ic_flags;
+		_APPLY_RATE1(flags, txparams, mcastrate, v);
+	} else
+		_APPLY_RATE(flags, txparams, mcastrate, v);
+	callback_register(settxparams_cb, &txparams);
 }
 
 static
-DECL_CMD_FUNC(set80211roamrate11b, val, d)
+DECL_CMD_FUNC(set80211mgtrate, val, d)
 {
-	set80211(s, IEEE80211_IOC_ROAM_RATE_11B, 2*atoi(val), 0, NULL);
+	int v = atoi(val), flags;
+
+	flags = getmodeflags(val);
+	gettxparams(s);
+	if (flags == 0) {		/* NB: no flags => current channel */
+		flags = getcurchan(s)->ic_flags;
+		_APPLY_RATE1(flags, txparams, mgmtrate, v);
+	} else
+		_APPLY_RATE(flags, txparams, mgmtrate, v);
+	callback_register(settxparams_cb, &txparams);
 }
 
 static
-DECL_CMD_FUNC(set80211roamrate11g, val, d)
+DECL_CMD_FUNC(set80211ucastrate, val, d)
 {
-	set80211(s, IEEE80211_IOC_ROAM_RATE_11G, 2*atoi(val), 0, NULL);
+	int v, flags;
+
+	gettxparams(s);
+	flags = getmodeflags(val);
+	if (isanyarg(val)) {
+		if (flags == 0) {	/* NB: no flags => current channel */
+			flags = getcurchan(s)->ic_flags;
+			_APPLY1(flags, txparams, ucastrate,
+			    IEEE80211_FIXED_RATE_NONE);
+		} else
+			_APPLY(flags, txparams, ucastrate,
+			    IEEE80211_FIXED_RATE_NONE);
+	} else {
+		v = atoi(val);
+		if (flags == 0) {	/* NB: no flags => current channel */
+			flags = getcurchan(s)->ic_flags;
+			_APPLY_RATE1(flags, txparams, ucastrate, v);
+		} else
+			_APPLY_RATE(flags, txparams, ucastrate, v);
+	}
+	callback_register(settxparams_cb, &txparams);
 }
 
 static
-DECL_CMD_FUNC(set80211mcastrate, val, d)
+DECL_CMD_FUNC(set80211maxretry, val, d)
 {
-	set80211(s, IEEE80211_IOC_MCAST_RATE, 2*atoi(val), 0, NULL);
+	int v = atoi(val), flags;
+
+	flags = getmodeflags(val);
+	gettxparams(s);
+	if (flags == 0) {		/* NB: no flags => current channel */
+		flags = getcurchan(s)->ic_flags;
+		_APPLY1(flags, txparams, maxretry, v);
+	} else
+		_APPLY(flags, txparams, maxretry, v);
+	callback_register(settxparams_cb, &txparams);
 }
+#undef _APPLY_RATE
+#undef _APPLY
+#undef IEEE80211_CHAN_HTA
+#undef IEEE80211_CHAN_HTG
 
 static
 DECL_CMD_FUNC(set80211fragthreshold, val, d)
@@ -1109,6 +1578,12 @@
 }
 
 static void
+set80211dfs(const char *val, int d, int s, const struct afswtch *rafp)
+{
+	set80211(s, IEEE80211_IOC_DFS, d, 0, NULL);
+}
+
+static void
 set80211shortgi(const char *val, int d, int s, const struct afswtch *rafp)

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list