wlan_sys.c revision 310901
1210502Ssyrinx/*-
2210502Ssyrinx * Copyright (c) 2010 The FreeBSD Foundation
3210502Ssyrinx * All rights reserved.
4310901Sngie
5210502Ssyrinx * This software was developed by Shteryana Sotirova Shopova under
6210502Ssyrinx * sponsorship from the FreeBSD Foundation.
7210502Ssyrinx *
8210502Ssyrinx * Redistribution and use in source and binary forms, with or without
9210502Ssyrinx * modification, are permitted provided that the following conditions
10210502Ssyrinx * are met:
11210502Ssyrinx * 1. Redistributions of source code must retain the above copyright
12210502Ssyrinx *    notice, this list of conditions and the following disclaimer.
13210502Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright
14210502Ssyrinx *    notice, this list of conditions and the following disclaimer in the
15210502Ssyrinx *    documentation and/or other materials provided with the distribution.
16210502Ssyrinx *
17210502Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18210502Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19210502Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20210502Ssyrinx * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21210502Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22210502Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23210502Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24210502Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25210502Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26210502Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27210502Ssyrinx * SUCH DAMAGE.
28210502Ssyrinx *
29210502Ssyrinx * $FreeBSD: stable/11/usr.sbin/bsnmpd/modules/snmp_wlan/wlan_sys.c 310901 2016-12-31 10:32:49Z ngie $
30210502Ssyrinx */
31210502Ssyrinx
32210502Ssyrinx#include <sys/ioctl.h>
33210502Ssyrinx#include <sys/param.h>
34210502Ssyrinx#include <sys/module.h>
35210502Ssyrinx#include <sys/linker.h>
36210502Ssyrinx#include <sys/socket.h>
37210502Ssyrinx#include <sys/sysctl.h>
38210502Ssyrinx
39210502Ssyrinx#include <net/if.h>
40210502Ssyrinx#include <net/if_dl.h>
41210502Ssyrinx#include <net/if_media.h>
42210502Ssyrinx#include <net/if_mib.h>
43210502Ssyrinx#include <net/if_types.h>
44210502Ssyrinx#include <net80211/ieee80211.h>
45210502Ssyrinx#include <net80211/ieee80211_ioctl.h>
46210502Ssyrinx#include <net80211/ieee80211_regdomain.h>
47210502Ssyrinx
48210502Ssyrinx#include <errno.h>
49210502Ssyrinx#include <ifaddrs.h>
50210502Ssyrinx#include <stdarg.h>
51210502Ssyrinx#include <stdlib.h>
52210502Ssyrinx#include <stdio.h>
53210502Ssyrinx#include <string.h>
54210502Ssyrinx#include <syslog.h>
55210502Ssyrinx
56210502Ssyrinx#include <bsnmp/snmpmod.h>
57210502Ssyrinx#include <bsnmp/snmp_mibII.h>
58210502Ssyrinx
59210502Ssyrinx#include "wlan_tree.h"
60210502Ssyrinx#include "wlan_snmp.h"
61210502Ssyrinx
62210502Ssyrinxstatic int sock = -1;
63210502Ssyrinx
64210502Ssyrinxstatic int	wlan_ioctl(char *, uint16_t, int *, void *, size_t *, int);
65210502Ssyrinxstatic int	wlan_kmod_load(const char *);
66210502Ssyrinxstatic uint32_t	wlan_drivercaps_to_snmp(uint32_t);
67210502Ssyrinxstatic uint32_t	wlan_cryptocaps_to_snmp(uint32_t);
68210502Ssyrinxstatic uint32_t	wlan_htcaps_to_snmp(uint32_t);
69210502Ssyrinxstatic uint32_t	wlan_peerstate_to_snmp(uint32_t);
70210502Ssyrinxstatic uint32_t	wlan_peercaps_to_snmp(uint32_t );
71210502Ssyrinxstatic uint32_t	wlan_channel_flags_to_snmp_phy(uint32_t);
72210502Ssyrinxstatic uint32_t	wlan_regdomain_to_snmp(int);
73210502Ssyrinxstatic uint32_t	wlan_snmp_to_scan_flags(int);
74210502Ssyrinxstatic int	wlan_config_snmp2ioctl(int);
75210502Ssyrinxstatic int	wlan_snmp_to_regdomain(enum WlanRegDomainCode);
76210502Ssyrinxstatic int	wlan_config_get_country(struct wlan_iface *);
77210502Ssyrinxstatic int	wlan_config_set_country(struct wlan_iface *, char *, int);
78210502Ssyrinxstatic int	wlan_config_get_dchannel(struct wlan_iface *wif);
79210502Ssyrinxstatic int	wlan_config_set_dchannel(struct wlan_iface *wif, uint32_t);
80210502Ssyrinxstatic int	wlan_config_get_bssid(struct wlan_iface *);
81210502Ssyrinxstatic int	wlan_config_set_bssid(struct wlan_iface *, uint8_t *);
82210502Ssyrinxstatic void	wlan_config_set_snmp_intval(struct wlan_iface *, int, int);
83210502Ssyrinxstatic int	wlan_config_snmp2value(int, int, int *);
84210502Ssyrinxstatic int	wlan_config_check(struct wlan_iface *, int);
85210502Ssyrinxstatic int	wlan_config_get_intval(struct wlan_iface *, int);
86210502Ssyrinxstatic int	wlan_config_set_intval(struct wlan_iface *, int, int);
87210502Ssyrinxstatic int	wlan_add_new_scan_result(struct wlan_iface *,
88210502Ssyrinx    const struct ieee80211req_scan_result *, uint8_t *);
89210502Ssyrinxstatic int	wlan_add_mac_macinfo(struct wlan_iface *,
90210502Ssyrinx    const struct ieee80211req_maclist *);
91210502Ssyrinxstatic struct wlan_peer *wlan_add_peerinfo(const struct ieee80211req_sta_info *);
92210502Ssyrinx
93210502Ssyrinxint
94210502Ssyrinxwlan_ioctl_init(void)
95210502Ssyrinx{
96210502Ssyrinx	if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
97210502Ssyrinx		syslog(LOG_ERR, "cannot open socket : %s", strerror(errno));
98210502Ssyrinx		return (-1);
99210502Ssyrinx	}
100210502Ssyrinx
101210502Ssyrinx	return (0);
102210502Ssyrinx}
103210502Ssyrinx/*
104210502Ssyrinx * Load the needed modules in kernel if not already there.
105210502Ssyrinx */
106210502Ssyrinxenum wlan_kmodules {
107210502Ssyrinx	WLAN_KMOD = 0,
108210502Ssyrinx	WLAN_KMOD_ACL,
109210502Ssyrinx	WLAN_KMOD_WEP,
110210502Ssyrinx	WLAN_KMODS_MAX
111210502Ssyrinx};
112210502Ssyrinx
113210502Ssyrinxstatic const char *wmod_names[] = {
114210502Ssyrinx	"wlan",
115210502Ssyrinx	"wlan_wlan_acl",
116210502Ssyrinx	"wlan_wep",
117210502Ssyrinx	NULL
118210502Ssyrinx};
119210502Ssyrinx
120210502Ssyrinxstatic int
121210502Ssyrinxwlan_kmod_load(const char *modname)
122210502Ssyrinx{
123210502Ssyrinx	int fileid, modid;
124210502Ssyrinx	struct module_stat mstat;
125210502Ssyrinx
126210502Ssyrinx	mstat.version = sizeof(struct module_stat);
127210502Ssyrinx	for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
128210502Ssyrinx		for (modid = kldfirstmod(fileid); modid > 0;
129210502Ssyrinx			modid = modfnext(modid)) {
130210502Ssyrinx			if (modstat(modid, &mstat) < 0)
131210502Ssyrinx				continue;
132210502Ssyrinx			if (strcmp(modname, mstat.name) == 0)
133210502Ssyrinx				return (0);
134210502Ssyrinx		}
135210502Ssyrinx	}
136210502Ssyrinx
137210502Ssyrinx	/* Not present - load it. */
138210502Ssyrinx	if (kldload(modname) < 0) {
139210502Ssyrinx		syslog(LOG_ERR, "failed to load %s kernel module - %s", modname,
140210502Ssyrinx		    strerror(errno));
141210502Ssyrinx		return (-1);
142210502Ssyrinx	}
143210502Ssyrinx
144210502Ssyrinx	return (1);
145210502Ssyrinx}
146210502Ssyrinx
147210502Ssyrinxint
148210502Ssyrinxwlan_kmodules_load(void)
149210502Ssyrinx{
150210502Ssyrinx	if (wlan_kmod_load(wmod_names[WLAN_KMOD]) < 0)
151210502Ssyrinx		return (-1);
152210502Ssyrinx
153210502Ssyrinx	if (wlan_kmod_load(wmod_names[WLAN_KMOD_ACL]) > 0)
154210502Ssyrinx		syslog(LOG_NOTICE, "SNMP wlan loaded %s module",
155210502Ssyrinx		    wmod_names[WLAN_KMOD_ACL]);
156210502Ssyrinx
157210502Ssyrinx	if (wlan_kmod_load(wmod_names[WLAN_KMOD_WEP]) > 0)
158210502Ssyrinx		syslog(LOG_NOTICE, "SNMP wlan loaded %s module",
159210502Ssyrinx		    wmod_names[WLAN_KMOD_WEP]);
160210502Ssyrinx
161310901Sngie	return (0);
162210502Ssyrinx}
163210502Ssyrinx
164210502Ssyrinx/* XXX: FIXME */
165210502Ssyrinxstatic int
166210502Ssyrinxwlan_ioctl(char *wif_name, uint16_t req_type, int *val, void *arg,
167210502Ssyrinx     size_t *argsize, int set)
168210502Ssyrinx{
169210502Ssyrinx	struct ieee80211req ireq;
170210502Ssyrinx
171210502Ssyrinx	memset(&ireq, 0, sizeof(struct ieee80211req));
172210502Ssyrinx	strlcpy(ireq.i_name, wif_name, IFNAMSIZ);
173210502Ssyrinx
174210502Ssyrinx	ireq.i_type = req_type;
175210502Ssyrinx	ireq.i_val = *val;
176210502Ssyrinx	ireq.i_len = *argsize;
177210502Ssyrinx	ireq.i_data = arg;
178210502Ssyrinx
179210502Ssyrinx	if (ioctl(sock, set ? SIOCS80211 : SIOCG80211, &ireq) < 0) {
180210502Ssyrinx		syslog(LOG_ERR, "iface %s - %s param: ioctl(%d) "
181210502Ssyrinx		    "failed: %s", wif_name, set ? "set" : "get",
182210502Ssyrinx		    req_type, strerror(errno));
183210502Ssyrinx		return (-1);
184210502Ssyrinx	}
185210502Ssyrinx
186210502Ssyrinx	*argsize = ireq.i_len;
187210502Ssyrinx	*val = ireq.i_val;
188210502Ssyrinx
189210502Ssyrinx	return (0);
190210502Ssyrinx}
191210502Ssyrinx
192210502Ssyrinxint
193210502Ssyrinxwlan_check_media(char *ifname)
194210502Ssyrinx{
195210502Ssyrinx	struct ifmediareq ifmr;
196210502Ssyrinx
197210502Ssyrinx	memset(&ifmr, 0, sizeof(struct ifmediareq));
198210502Ssyrinx	strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
199210502Ssyrinx
200210502Ssyrinx	if (ioctl(sock, SIOCGIFMEDIA, &ifmr) < 0 || ifmr.ifm_count == 0)
201210502Ssyrinx		return (0);     /* Interface doesn't support SIOCGIFMEDIA. */
202210502Ssyrinx
203210502Ssyrinx	if ((ifmr.ifm_status & IFM_AVALID) == 0)
204210502Ssyrinx		return (0);
205210502Ssyrinx
206210502Ssyrinx	return (IFM_TYPE(ifmr.ifm_active));
207210502Ssyrinx}
208210502Ssyrinx
209210502Ssyrinxint
210210502Ssyrinxwlan_get_opmode(struct wlan_iface *wif)
211210502Ssyrinx{
212210502Ssyrinx	struct ifmediareq ifmr;
213210502Ssyrinx
214210502Ssyrinx	memset(&ifmr, 0, sizeof(struct ifmediareq));
215210502Ssyrinx	strlcpy(ifmr.ifm_name, wif->wname, sizeof(ifmr.ifm_name));
216210502Ssyrinx
217210502Ssyrinx	if (ioctl(sock, SIOCGIFMEDIA, &ifmr) < 0) {
218210502Ssyrinx		if (errno == ENXIO)
219210502Ssyrinx			return (-1);
220210502Ssyrinx		wif->mode = WlanIfaceOperatingModeType_station;
221210502Ssyrinx		return (0);
222210502Ssyrinx	}
223210502Ssyrinx
224210502Ssyrinx	if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
225210502Ssyrinx		if (ifmr.ifm_current & IFM_FLAG0)
226210502Ssyrinx			wif->mode = WlanIfaceOperatingModeType_adhocDemo;
227210502Ssyrinx		else
228210502Ssyrinx			wif->mode = WlanIfaceOperatingModeType_ibss;
229210502Ssyrinx	} else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
230210502Ssyrinx		wif->mode = WlanIfaceOperatingModeType_hostAp;
231210502Ssyrinx	else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
232210502Ssyrinx		wif->mode = WlanIfaceOperatingModeType_monitor;
233210502Ssyrinx	else if (ifmr.ifm_current & IFM_IEEE80211_MBSS)
234210502Ssyrinx		wif->mode = WlanIfaceOperatingModeType_meshPoint;
235210502Ssyrinx	else if (ifmr.ifm_current & IFM_IEEE80211_WDS)
236210502Ssyrinx		wif->mode = WlanIfaceOperatingModeType_wds;
237210502Ssyrinx
238210502Ssyrinx	return (0);
239210502Ssyrinx}
240210502Ssyrinx
241210502Ssyrinxint
242210502Ssyrinxwlan_config_state(struct wlan_iface *wif, uint8_t set)
243210502Ssyrinx{
244210502Ssyrinx	int	flags;
245210502Ssyrinx	struct ifreq ifr;
246210502Ssyrinx
247210502Ssyrinx	memset(&ifr, 0, sizeof(ifr));
248210502Ssyrinx	strcpy(ifr.ifr_name, wif->wname);
249210502Ssyrinx
250210502Ssyrinx	if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
251210502Ssyrinx		syslog(LOG_ERR, "set %s status: ioctl(SIOCGIFFLAGS) "
252210502Ssyrinx		    "failed: %s", wif->wname, strerror(errno));
253210502Ssyrinx		return (-1);
254210502Ssyrinx	}
255210502Ssyrinx
256210502Ssyrinx	if (set == 0) {
257210502Ssyrinx		if ((ifr.ifr_flags & IFF_UP) != 0)
258210502Ssyrinx			wif->state = wlanIfaceState_up;
259210502Ssyrinx		else
260210502Ssyrinx			wif->state = wlanIfaceState_down;
261210502Ssyrinx		return (0);
262210502Ssyrinx	}
263210502Ssyrinx
264210502Ssyrinx	flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
265210502Ssyrinx
266210502Ssyrinx	if (wif->state == wlanIfaceState_up)
267210502Ssyrinx		flags |= IFF_UP;
268210502Ssyrinx	else
269210502Ssyrinx		flags &= ~IFF_UP;
270210502Ssyrinx
271210502Ssyrinx	ifr.ifr_flags = flags & 0xffff;
272210502Ssyrinx	ifr.ifr_flagshigh = flags >> 16;
273210502Ssyrinx	if (ioctl(sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
274210502Ssyrinx		syslog(LOG_ERR, "set %s %s: ioctl(SIOCSIFFLAGS) failed: %s",
275210502Ssyrinx		    wif->wname, wif->state == wlanIfaceState_up?"up":"down",
276210502Ssyrinx		    strerror(errno));
277210502Ssyrinx		return (-1);
278210502Ssyrinx	}
279210502Ssyrinx
280210502Ssyrinx	return (0);
281210502Ssyrinx}
282210502Ssyrinx
283210502Ssyrinxint
284210502Ssyrinxwlan_get_local_addr(struct wlan_iface *wif)
285210502Ssyrinx{
286210502Ssyrinx	int len;
287210502Ssyrinx	char ifname[IFNAMSIZ];
288210502Ssyrinx	struct ifaddrs *ifap, *ifa;
289210502Ssyrinx	struct sockaddr_dl sdl;
290210502Ssyrinx
291210502Ssyrinx	if (getifaddrs(&ifap) != 0) {
292210502Ssyrinx		syslog(LOG_ERR, "wlan get mac: getifaddrs() failed - %s",
293210502Ssyrinx		    strerror(errno));
294210502Ssyrinx		return (-1);
295210502Ssyrinx	}
296210502Ssyrinx
297210502Ssyrinx	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
298210502Ssyrinx		if (ifa->ifa_addr->sa_family != AF_LINK)
299210502Ssyrinx			continue;
300210502Ssyrinx		memcpy(&sdl, ifa->ifa_addr, sizeof(struct sockaddr_dl));
301210502Ssyrinx		if (sdl.sdl_alen > IEEE80211_ADDR_LEN)
302210502Ssyrinx			continue;
303210502Ssyrinx		if ((len = sdl.sdl_nlen) >= IFNAMSIZ)
304210502Ssyrinx			len = IFNAMSIZ - 1;
305210502Ssyrinx		memcpy(ifname, sdl.sdl_data, len);
306210502Ssyrinx		ifname[len] = '\0';
307210502Ssyrinx		if (strcmp(wif->wname, ifname) == 0)
308210502Ssyrinx			break;
309210502Ssyrinx	}
310210502Ssyrinx
311210502Ssyrinx	freeifaddrs(ifap);
312210502Ssyrinx	return (0);
313210502Ssyrinx}
314210502Ssyrinx
315210502Ssyrinxint
316210502Ssyrinxwlan_get_parent(struct wlan_iface *wif __unused)
317210502Ssyrinx{
318210502Ssyrinx	/* XXX: There's no way to fetch this from the kernel. */
319210502Ssyrinx	return (0);
320210502Ssyrinx}
321210502Ssyrinx
322210502Ssyrinx/* XXX */
323210502Ssyrinx#define	IEEE80211_C_STA		0x00000001	/* CAPABILITY: STA available */
324210502Ssyrinx#define	IEEE80211_C_8023ENCAP	0x00000002	/* CAPABILITY: 802.3 encap */
325210502Ssyrinx#define	IEEE80211_C_FF		0x00000040	/* CAPABILITY: ATH FF avail */
326210502Ssyrinx#define	IEEE80211_C_TURBOP	0x00000080	/* CAPABILITY: ATH Turbo avail*/
327210502Ssyrinx#define	IEEE80211_C_IBSS	0x00000100	/* CAPABILITY: IBSS available */
328210502Ssyrinx#define	IEEE80211_C_PMGT	0x00000200	/* CAPABILITY: Power mgmt */
329210502Ssyrinx#define	IEEE80211_C_HOSTAP	0x00000400	/* CAPABILITY: HOSTAP avail */
330210502Ssyrinx#define	IEEE80211_C_AHDEMO	0x00000800	/* CAPABILITY: Old Adhoc Demo */
331210502Ssyrinx#define	IEEE80211_C_SWRETRY	0x00001000	/* CAPABILITY: sw tx retry */
332210502Ssyrinx#define	IEEE80211_C_TXPMGT	0x00002000	/* CAPABILITY: tx power mgmt */
333210502Ssyrinx#define	IEEE80211_C_SHSLOT	0x00004000	/* CAPABILITY: short slottime */
334210502Ssyrinx#define	IEEE80211_C_SHPREAMBLE	0x00008000	/* CAPABILITY: short preamble */
335210502Ssyrinx#define	IEEE80211_C_MONITOR	0x00010000	/* CAPABILITY: monitor mode */
336210502Ssyrinx#define	IEEE80211_C_DFS		0x00020000	/* CAPABILITY: DFS/radar avail*/
337210502Ssyrinx#define	IEEE80211_C_MBSS	0x00040000	/* CAPABILITY: MBSS available */
338210502Ssyrinx/* 0x7c0000 available */
339210502Ssyrinx#define	IEEE80211_C_WPA1	0x00800000	/* CAPABILITY: WPA1 avail */
340210502Ssyrinx#define	IEEE80211_C_WPA2	0x01000000	/* CAPABILITY: WPA2 avail */
341210502Ssyrinx#define	IEEE80211_C_WPA		0x01800000	/* CAPABILITY: WPA1+WPA2 avail*/
342210502Ssyrinx#define	IEEE80211_C_BURST	0x02000000	/* CAPABILITY: frame bursting */
343210502Ssyrinx#define	IEEE80211_C_WME		0x04000000	/* CAPABILITY: WME avail */
344210502Ssyrinx#define	IEEE80211_C_WDS		0x08000000	/* CAPABILITY: 4-addr support */
345210502Ssyrinx/* 0x10000000 reserved */
346210502Ssyrinx#define	IEEE80211_C_BGSCAN	0x20000000	/* CAPABILITY: bg scanning */
347210502Ssyrinx#define	IEEE80211_C_TXFRAG	0x40000000	/* CAPABILITY: tx fragments */
348210502Ssyrinx#define	IEEE80211_C_TDMA	0x80000000	/* CAPABILITY: TDMA avail */
349210502Ssyrinx
350210502Ssyrinxstatic uint32_t
351210502Ssyrinxwlan_drivercaps_to_snmp(uint32_t dcaps)
352210502Ssyrinx{
353210502Ssyrinx	uint32_t scaps = 0;
354210502Ssyrinx
355210502Ssyrinx	if ((dcaps & IEEE80211_C_STA) != 0)
356210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_station);
357210502Ssyrinx	if ((dcaps & IEEE80211_C_8023ENCAP) != 0)
358210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_ieee8023encap);
359210502Ssyrinx	if ((dcaps & IEEE80211_C_FF) != 0)
360210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_athFastFrames);
361210502Ssyrinx	if ((dcaps & IEEE80211_C_TURBOP) != 0)
362210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_athTurbo);
363210502Ssyrinx	if ((dcaps & IEEE80211_C_IBSS) != 0)
364210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_ibss);
365210502Ssyrinx	if ((dcaps & IEEE80211_C_PMGT) != 0)
366210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_pmgt);
367210502Ssyrinx	if ((dcaps & IEEE80211_C_HOSTAP) != 0)
368210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_hostAp);
369210502Ssyrinx	if ((dcaps & IEEE80211_C_AHDEMO) != 0)
370210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_ahDemo);
371210502Ssyrinx	if ((dcaps & IEEE80211_C_SWRETRY) != 0)
372210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_swRetry);
373210502Ssyrinx	if ((dcaps & IEEE80211_C_TXPMGT) != 0)
374210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_txPmgt);
375210502Ssyrinx	if ((dcaps & IEEE80211_C_SHSLOT) != 0)
376210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_shortSlot);
377210502Ssyrinx	if ((dcaps & IEEE80211_C_SHPREAMBLE) != 0)
378210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_shortPreamble);
379210502Ssyrinx	if ((dcaps & IEEE80211_C_MONITOR) != 0)
380210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_monitor);
381210502Ssyrinx	if ((dcaps & IEEE80211_C_DFS) != 0)
382210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_dfs);
383210502Ssyrinx	if ((dcaps & IEEE80211_C_MBSS) != 0)
384210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_mbss);
385210502Ssyrinx	if ((dcaps & IEEE80211_C_WPA1) != 0)
386210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_wpa1);
387210502Ssyrinx	if ((dcaps & IEEE80211_C_WPA2) != 0)
388210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_wpa2);
389210502Ssyrinx	if ((dcaps & IEEE80211_C_BURST) != 0)
390210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_burst);
391210502Ssyrinx	if ((dcaps & IEEE80211_C_WME) != 0)
392210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_wme);
393210502Ssyrinx	if ((dcaps & IEEE80211_C_WDS) != 0)
394210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_wds);
395210502Ssyrinx	if ((dcaps & IEEE80211_C_BGSCAN) != 0)
396210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_bgScan);
397210502Ssyrinx	if ((dcaps & IEEE80211_C_TXFRAG) != 0)
398210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_txFrag);
399210502Ssyrinx	if ((dcaps & IEEE80211_C_TDMA) != 0)
400210502Ssyrinx		scaps |= (0x1 << WlanDriverCaps_tdma);
401210502Ssyrinx
402210502Ssyrinx	return (scaps);
403210502Ssyrinx}
404210502Ssyrinx
405210502Ssyrinxstatic uint32_t
406210502Ssyrinxwlan_cryptocaps_to_snmp(uint32_t ccaps)
407210502Ssyrinx{
408210502Ssyrinx	uint32_t scaps = 0;
409210502Ssyrinx
410210502Ssyrinx#if NOT_YET
411210502Ssyrinx	if ((ccaps & IEEE80211_CRYPTO_WEP) != 0)
412210502Ssyrinx		scaps |= (0x1 << wlanCryptoCaps_wep);
413210502Ssyrinx	if ((ccaps & IEEE80211_CRYPTO_TKIP) != 0)
414210502Ssyrinx		scaps |= (0x1 << wlanCryptoCaps_tkip);
415210502Ssyrinx	if ((ccaps & IEEE80211_CRYPTO_AES_OCB) != 0)
416210502Ssyrinx		scaps |= (0x1 << wlanCryptoCaps_aes);
417210502Ssyrinx	if ((ccaps & IEEE80211_CRYPTO_AES_CCM) != 0)
418210502Ssyrinx		scaps |= (0x1 << wlanCryptoCaps_aesCcm);
419210502Ssyrinx	if ((ccaps & IEEE80211_CRYPTO_TKIPMIC) != 0)
420210502Ssyrinx		scaps |= (0x1 << wlanCryptoCaps_tkipMic);
421210502Ssyrinx	if ((ccaps & IEEE80211_CRYPTO_CKIP) != 0)
422210502Ssyrinx		scaps |= (0x1 << wlanCryptoCaps_ckip);
423210502Ssyrinx#else /* !NOT_YET */
424210502Ssyrinx	scaps = ccaps;
425210502Ssyrinx#endif
426210502Ssyrinx	return (scaps);
427210502Ssyrinx}
428210502Ssyrinx
429210502Ssyrinx#define	IEEE80211_HTC_AMPDU	0x00010000	/* CAPABILITY: A-MPDU tx */
430210502Ssyrinx#define	IEEE80211_HTC_AMSDU	0x00020000	/* CAPABILITY: A-MSDU tx */
431210502Ssyrinx/* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */
432210502Ssyrinx#define	IEEE80211_HTC_HT	0x00040000	/* CAPABILITY: HT operation */
433210502Ssyrinx#define	IEEE80211_HTC_SMPS	0x00080000	/* CAPABILITY: MIMO power save*/
434210502Ssyrinx#define	IEEE80211_HTC_RIFS	0x00100000	/* CAPABILITY: RIFS support */
435210502Ssyrinx
436210502Ssyrinxstatic uint32_t
437210502Ssyrinxwlan_htcaps_to_snmp(uint32_t hcaps)
438210502Ssyrinx{
439210502Ssyrinx	uint32_t scaps = 0;
440210502Ssyrinx
441210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_LDPC) != 0)
442210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_ldpc);
443210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_CHWIDTH40) != 0)
444210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_chwidth40);
445210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_GREENFIELD) != 0)
446210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_greenField);
447210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_SHORTGI20) != 0)
448210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_shortGi20);
449210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_SHORTGI40) != 0)
450210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_shortGi40);
451210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_TXSTBC) != 0)
452210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_txStbc);
453210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_DELBA) != 0)
454210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_delba);
455210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_MAXAMSDU_7935) != 0)
456210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_amsdu7935);
457210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_DSSSCCK40) != 0)
458210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_dssscck40);
459210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_PSMP) != 0)
460210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_psmp);
461210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_40INTOLERANT) != 0)
462210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_fortyMHzIntolerant);
463210502Ssyrinx	if ((hcaps & IEEE80211_HTCAP_LSIGTXOPPROT) != 0)
464210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_lsigTxOpProt);
465210502Ssyrinx	if ((hcaps & IEEE80211_HTC_AMPDU) != 0)
466210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_htcAmpdu);
467210502Ssyrinx	if ((hcaps & IEEE80211_HTC_AMSDU) != 0)
468210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_htcAmsdu);
469210502Ssyrinx	if ((hcaps & IEEE80211_HTC_HT) != 0)
470210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_htcHt);
471210502Ssyrinx	if ((hcaps & IEEE80211_HTC_SMPS) != 0)
472210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_htcSmps);
473210502Ssyrinx	if ((hcaps & IEEE80211_HTC_RIFS) != 0)
474210502Ssyrinx		scaps |= (0x1 << WlanHTCaps_htcRifs);
475210502Ssyrinx
476210502Ssyrinx	return (scaps);
477210502Ssyrinx}
478210502Ssyrinx
479210502Ssyrinx/* XXX: Not here? */
480210502Ssyrinx#define	WLAN_SET_TDMA_OPMODE(w) do {						\
481210502Ssyrinx	if ((w)->mode == WlanIfaceOperatingModeType_adhocDemo &&		\
482210502Ssyrinx	    ((w)->drivercaps & WlanDriverCaps_tdma) != 0)			\
483210502Ssyrinx		(w)->mode = WlanIfaceOperatingModeType_tdma;			\
484210502Ssyrinx} while (0)
485210502Ssyrinxint
486210502Ssyrinxwlan_get_driver_caps(struct wlan_iface *wif)
487210502Ssyrinx{
488210502Ssyrinx	int val = 0;
489210502Ssyrinx	size_t argsize;
490210502Ssyrinx	struct ieee80211_devcaps_req dc;
491210502Ssyrinx
492210502Ssyrinx	memset(&dc, 0, sizeof(struct ieee80211_devcaps_req));
493210502Ssyrinx	argsize = sizeof(struct ieee80211_devcaps_req);
494210502Ssyrinx
495210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_DEVCAPS, &val, &dc,
496210502Ssyrinx	    &argsize, 0) < 0)
497210502Ssyrinx		return (-1);
498210502Ssyrinx
499210502Ssyrinx	wif->drivercaps = wlan_drivercaps_to_snmp(dc.dc_drivercaps);
500210502Ssyrinx	wif->cryptocaps = wlan_cryptocaps_to_snmp(dc.dc_cryptocaps);
501210502Ssyrinx	wif->htcaps = wlan_htcaps_to_snmp(dc.dc_htcaps);
502210502Ssyrinx
503210502Ssyrinx	WLAN_SET_TDMA_OPMODE(wif);
504210502Ssyrinx
505210502Ssyrinx	argsize = dc.dc_chaninfo.ic_nchans * sizeof(struct ieee80211_channel);
506210502Ssyrinx	wif->chanlist = (struct ieee80211_channel *)malloc(argsize);
507210502Ssyrinx	if (wif->chanlist == NULL)
508210502Ssyrinx		return (0);
509210502Ssyrinx
510210502Ssyrinx	memcpy(wif->chanlist, dc.dc_chaninfo.ic_chans, argsize);
511210502Ssyrinx	wif->nchannels = dc.dc_chaninfo.ic_nchans;
512210502Ssyrinx
513210502Ssyrinx	return (0);
514210502Ssyrinx}
515210502Ssyrinx
516210502Ssyrinxuint8_t
517210502Ssyrinxwlan_channel_state_to_snmp(uint8_t cstate)
518210502Ssyrinx{
519210502Ssyrinx	uint8_t cs = 0;
520210502Ssyrinx
521210502Ssyrinx	if ((cstate & IEEE80211_CHANSTATE_RADAR) != 0)
522210502Ssyrinx		cs |= (0x1 << WlanIfaceChannelStateType_radar);
523210502Ssyrinx	if ((cstate & IEEE80211_CHANSTATE_CACDONE) != 0)
524210502Ssyrinx		cs |= (0x1 << WlanIfaceChannelStateType_cacDone);
525210502Ssyrinx	if ((cstate & IEEE80211_CHANSTATE_CWINT) != 0)
526210502Ssyrinx		cs |= (0x1 << WlanIfaceChannelStateType_interferenceDetected);
527210502Ssyrinx	if ((cstate & IEEE80211_CHANSTATE_NORADAR) != 0)
528210502Ssyrinx		cs |= (0x1 << WlanIfaceChannelStateType_radarClear);
529210502Ssyrinx
530210502Ssyrinx	return (cs);
531210502Ssyrinx}
532210502Ssyrinx
533210502Ssyrinxuint32_t
534210502Ssyrinxwlan_channel_flags_to_snmp(uint32_t cflags)
535210502Ssyrinx{
536210502Ssyrinx	uint32_t cf = 0;
537210502Ssyrinx
538210502Ssyrinx	if ((cflags & IEEE80211_CHAN_TURBO) != 0)
539210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_turbo);
540210502Ssyrinx	if ((cflags & IEEE80211_CHAN_CCK) != 0)
541210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_cck);
542210502Ssyrinx	if ((cflags & IEEE80211_CHAN_OFDM) != 0)
543210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_ofdm);
544210502Ssyrinx	if ((cflags & IEEE80211_CHAN_2GHZ) != 0)
545210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum2Ghz);
546210502Ssyrinx	if ((cflags & IEEE80211_CHAN_5GHZ) != 0)
547210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum5Ghz);
548210502Ssyrinx	if ((cflags & IEEE80211_CHAN_PASSIVE) != 0)
549210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_passiveScan);
550210502Ssyrinx	if ((cflags & IEEE80211_CHAN_DYN) != 0)
551210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_dynamicCckOfdm);
552210502Ssyrinx	if ((cflags & IEEE80211_CHAN_GFSK) != 0)
553210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_gfsk);
554210502Ssyrinx	if ((cflags & IEEE80211_CHAN_GSM) != 0)
555210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum900Mhz);
556210502Ssyrinx	if ((cflags & IEEE80211_CHAN_STURBO) != 0)
557210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_dot11aStaticTurbo);
558210502Ssyrinx	if ((cflags & IEEE80211_CHAN_HALF) != 0)
559210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_halfRate);
560210502Ssyrinx	if ((cflags & IEEE80211_CHAN_QUARTER) != 0)
561210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_quarterRate);
562210502Ssyrinx	if ((cflags & IEEE80211_CHAN_HT20) != 0)
563210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_ht20);
564210502Ssyrinx	if ((cflags & IEEE80211_CHAN_HT40U) != 0)
565210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_ht40u);
566210502Ssyrinx	if ((cflags & IEEE80211_CHAN_HT40D) != 0)
567210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_ht40d);
568210502Ssyrinx	if ((cflags & IEEE80211_CHAN_DFS) != 0)
569210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_dfs);
570210502Ssyrinx	if ((cflags & IEEE80211_CHAN_4MSXMIT) != 0)
571210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_xmit4ms);
572210502Ssyrinx	if ((cflags & IEEE80211_CHAN_NOADHOC) != 0)
573210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_noAdhoc);
574210502Ssyrinx	if ((cflags & IEEE80211_CHAN_NOHOSTAP) != 0)
575210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_noHostAp);
576210502Ssyrinx	if ((cflags & IEEE80211_CHAN_11D) != 0)
577210502Ssyrinx		cf |= (0x1 << WlanIfaceChannelFlagsType_dot11d);
578210502Ssyrinx
579210502Ssyrinx	return (cf);
580210502Ssyrinx}
581210502Ssyrinx
582210502Ssyrinx/* XXX: */
583210502Ssyrinx#define WLAN_SNMP_MAX_CHANS	256
584210502Ssyrinxint
585210502Ssyrinxwlan_get_channel_list(struct wlan_iface *wif)
586210502Ssyrinx{
587210502Ssyrinx	int val = 0;
588210502Ssyrinx	uint32_t i, nchans;
589210502Ssyrinx	size_t argsize;
590210502Ssyrinx	struct ieee80211req_chaninfo *chaninfo;
591210502Ssyrinx	struct ieee80211req_chanlist active;
592210502Ssyrinx	const struct ieee80211_channel *c;
593210502Ssyrinx
594210502Ssyrinx	argsize = sizeof(struct ieee80211req_chaninfo) +
595210502Ssyrinx	    sizeof(struct ieee80211_channel) * WLAN_SNMP_MAX_CHANS;
596210502Ssyrinx	chaninfo = (struct ieee80211req_chaninfo *)malloc(argsize);
597210502Ssyrinx	if (chaninfo == NULL)
598210502Ssyrinx		return (-1);
599210502Ssyrinx
600210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_CHANINFO, &val, chaninfo,
601210502Ssyrinx	    &argsize, 0) < 0)
602210502Ssyrinx		return (-1);
603210502Ssyrinx
604210502Ssyrinx	argsize = sizeof(active);
605210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_CHANLIST, &val, &active,
606210502Ssyrinx	    &argsize, 0) < 0)
607210502Ssyrinx		goto error;
608210502Ssyrinx
609210502Ssyrinx	for (i = 0, nchans = 0; i < chaninfo->ic_nchans; i++) {
610210502Ssyrinx		c = &chaninfo->ic_chans[i];
611210502Ssyrinx		if (!isset(active.ic_channels, c->ic_ieee))
612210502Ssyrinx				continue;
613210502Ssyrinx		nchans++;
614210502Ssyrinx	}
615210502Ssyrinx	wif->chanlist = (struct ieee80211_channel *)reallocf(wif->chanlist,
616210502Ssyrinx	    nchans * sizeof(*c));
617210502Ssyrinx	if (wif->chanlist == NULL)
618210502Ssyrinx		goto error;
619210502Ssyrinx	wif->nchannels = nchans;
620210502Ssyrinx	for (i = 0, nchans = 0; i < chaninfo->ic_nchans; i++) {
621210502Ssyrinx		c = &chaninfo->ic_chans[i];
622210502Ssyrinx		if (!isset(active.ic_channels, c->ic_ieee))
623210502Ssyrinx				continue;
624210502Ssyrinx		memcpy(wif->chanlist + nchans, c, sizeof (*c));
625210502Ssyrinx		nchans++;
626210502Ssyrinx	}
627210502Ssyrinx
628210502Ssyrinx	free(chaninfo);
629210502Ssyrinx	return (0);
630210502Ssyrinxerror:
631210502Ssyrinx	wif->nchannels = 0;
632210502Ssyrinx	free(chaninfo);
633210502Ssyrinx	return (-1);
634210502Ssyrinx}
635210502Ssyrinx
636210502Ssyrinxstatic enum WlanIfPhyMode
637210502Ssyrinxwlan_channel_flags_to_snmp_phy(uint32_t cflags)
638210502Ssyrinx{
639210502Ssyrinx	/* XXX: recheck */
640210502Ssyrinx	if ((cflags & IEEE80211_CHAN_A) != 0)
641210502Ssyrinx		return (WlanIfPhyMode_dot11a);
642210502Ssyrinx	if ((cflags & IEEE80211_CHAN_B) != 0)
643210502Ssyrinx		return (WlanIfPhyMode_dot11b);
644210502Ssyrinx	if ((cflags & IEEE80211_CHAN_G) != 0 ||
645210502Ssyrinx	    (cflags & IEEE80211_CHAN_PUREG) != 0)
646210502Ssyrinx		return (WlanIfPhyMode_dot11g);
647210502Ssyrinx	if ((cflags & IEEE80211_CHAN_FHSS) != 0)
648210502Ssyrinx		return (WlanIfPhyMode_fh);
649210502Ssyrinx	if ((cflags & IEEE80211_CHAN_TURBO) != 0 &&
650210502Ssyrinx	    (cflags & IEEE80211_CHAN_A) != 0)
651210502Ssyrinx		return (WlanIfPhyMode_turboA);
652210502Ssyrinx	if ((cflags & IEEE80211_CHAN_TURBO) != 0 &&
653210502Ssyrinx	    (cflags & IEEE80211_CHAN_G) != 0)
654210502Ssyrinx		return (WlanIfPhyMode_turboG);
655210502Ssyrinx	if ((cflags & IEEE80211_CHAN_STURBO) != 0)
656210502Ssyrinx		return (WlanIfPhyMode_sturboA);
657210502Ssyrinx	if ((cflags & IEEE80211_CHAN_HALF) != 0)
658210502Ssyrinx		return (WlanIfPhyMode_ofdmHalf);
659210502Ssyrinx	if ((cflags & IEEE80211_CHAN_QUARTER) != 0)
660210502Ssyrinx		return (WlanIfPhyMode_ofdmQuarter);
661210502Ssyrinx
662210502Ssyrinx	return (WlanIfPhyMode_auto);
663210502Ssyrinx}
664210502Ssyrinx
665210502Ssyrinxint
666210502Ssyrinxwlan_get_roam_params(struct wlan_iface *wif)
667210502Ssyrinx{
668210502Ssyrinx	int val = 0;
669210502Ssyrinx	size_t argsize;
670210502Ssyrinx
671210502Ssyrinx	argsize = sizeof(struct ieee80211_roamparams_req);
672210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_ROAM, &val,
673210502Ssyrinx	    &wif->roamparams, &argsize, 0) < 0)
674210502Ssyrinx		return (-1);
675210502Ssyrinx
676210502Ssyrinx	return (0);
677210502Ssyrinx}
678210502Ssyrinx
679210502Ssyrinxint
680210502Ssyrinxwlan_get_tx_params(struct wlan_iface *wif)
681210502Ssyrinx{
682210502Ssyrinx	int val = 0;
683210502Ssyrinx	size_t argsize;
684210502Ssyrinx
685210502Ssyrinx	/*
686210502Ssyrinx	 * XXX: Reset IEEE80211_RATE_MCS bit on IEEE80211_MODE_11NA
687210502Ssyrinx	 * and IEEE80211_MODE_11NG modes.
688210502Ssyrinx	 */
689210502Ssyrinx	argsize = sizeof(struct ieee80211_txparams_req);
690210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPARAMS, &val,
691210502Ssyrinx	    &wif->txparams, &argsize, 0) < 0)
692210502Ssyrinx		return (-1);
693210502Ssyrinx
694210502Ssyrinx	return (0);
695210502Ssyrinx}
696210502Ssyrinx
697210502Ssyrinxint
698210502Ssyrinxwlan_set_tx_params(struct wlan_iface *wif, int32_t pmode __unused)
699210502Ssyrinx{
700210502Ssyrinx	int val = 0;
701210502Ssyrinx	size_t argsize;
702210502Ssyrinx
703210502Ssyrinx	/*
704210502Ssyrinx	 * XXX: Set IEEE80211_RATE_MCS bit on IEEE80211_MODE_11NA
705210502Ssyrinx	 * and IEEE80211_MODE_11NG modes.
706210502Ssyrinx	 */
707210502Ssyrinx	argsize = sizeof(struct ieee80211_txparams_req);
708210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPARAMS, &val,
709210502Ssyrinx	    &wif->txparams, &argsize, 1) < 0)
710210502Ssyrinx		return (-1);
711210502Ssyrinx
712210502Ssyrinx	return (0);
713210502Ssyrinx}
714210502Ssyrinx
715210502Ssyrinxint
716210502Ssyrinxwlan_clone_create(struct wlan_iface *wif)
717210502Ssyrinx{
718210502Ssyrinx	struct ifreq ifr;
719210502Ssyrinx	struct ieee80211_clone_params wcp;
720210502Ssyrinx	static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
721210502Ssyrinx
722210502Ssyrinx	memset(&wcp, 0, sizeof(wcp));
723210502Ssyrinx	memset(&ifr, 0, sizeof(ifr));
724210502Ssyrinx
725210502Ssyrinx	/* Sanity checks. */
726210502Ssyrinx	if (wif == NULL || wif->pname[0] == '\0' || wif->mode > WLAN_IFMODE_MAX)
727210502Ssyrinx		return (SNMP_ERR_INCONS_VALUE);
728210502Ssyrinx
729210502Ssyrinx	if (wif->mode == WlanIfaceOperatingModeType_wds &&
730210502Ssyrinx	    memcmp(wif->dbssid, zerobssid, IEEE80211_ADDR_LEN) == 0)
731210502Ssyrinx		return (SNMP_ERR_INCONS_VALUE);
732210502Ssyrinx
733210502Ssyrinx	strlcpy(wcp.icp_parent, wif->pname, IFNAMSIZ);
734210502Ssyrinx	if ((wif->flags & WlanIfaceFlagsType_uniqueBssid) != 0)
735210502Ssyrinx		wcp.icp_flags |= IEEE80211_CLONE_BSSID;
736210502Ssyrinx	if ((wif->flags & WlanIfaceFlagsType_noBeacons) != 0)
737210502Ssyrinx		wcp.icp_flags |= IEEE80211_CLONE_NOBEACONS;
738210502Ssyrinx	if (wif->mode == WlanIfaceOperatingModeType_wds &&
739210502Ssyrinx	    (wif->flags & WlanIfaceFlagsType_wdsLegacy) != 0)
740210502Ssyrinx		wcp.icp_flags |= IEEE80211_CLONE_WDSLEGACY;
741210502Ssyrinx
742210502Ssyrinx	switch (wif->mode) {
743210502Ssyrinx	case WlanIfaceOperatingModeType_ibss:
744210502Ssyrinx		wcp.icp_opmode = IEEE80211_M_IBSS;
745210502Ssyrinx		break;
746210502Ssyrinx	case WlanIfaceOperatingModeType_station:
747210502Ssyrinx		wcp.icp_opmode = IEEE80211_M_STA;
748210502Ssyrinx		break;
749210502Ssyrinx	case WlanIfaceOperatingModeType_wds:
750210502Ssyrinx		wcp.icp_opmode = IEEE80211_M_WDS;
751210502Ssyrinx		break;
752210502Ssyrinx	case WlanIfaceOperatingModeType_adhocDemo:
753210502Ssyrinx		wcp.icp_opmode = IEEE80211_M_AHDEMO;
754210502Ssyrinx		break;
755210502Ssyrinx	case WlanIfaceOperatingModeType_hostAp:
756210502Ssyrinx		wcp.icp_opmode = IEEE80211_M_HOSTAP;
757210502Ssyrinx		break;
758210502Ssyrinx	case WlanIfaceOperatingModeType_monitor:
759210502Ssyrinx		wcp.icp_opmode = IEEE80211_M_MONITOR;
760210502Ssyrinx		break;
761210502Ssyrinx	case WlanIfaceOperatingModeType_meshPoint:
762210502Ssyrinx		wcp.icp_opmode = IEEE80211_M_MBSS;
763210502Ssyrinx		break;
764210502Ssyrinx	case WlanIfaceOperatingModeType_tdma:
765210502Ssyrinx		wcp.icp_opmode = IEEE80211_M_AHDEMO;
766210502Ssyrinx		wcp.icp_flags |= IEEE80211_CLONE_TDMA;
767210502Ssyrinx		break;
768210502Ssyrinx	}
769210502Ssyrinx
770210502Ssyrinx	memcpy(wcp.icp_bssid, wif->dbssid, IEEE80211_ADDR_LEN);
771210502Ssyrinx	if (memcmp(wif->dlmac, zerobssid, IEEE80211_ADDR_LEN) != 0) {
772210502Ssyrinx		memcpy(wcp.icp_macaddr, wif->dlmac, IEEE80211_ADDR_LEN);
773210502Ssyrinx		wcp.icp_flags |= IEEE80211_CLONE_MACADDR;
774210502Ssyrinx	}
775210502Ssyrinx
776210502Ssyrinx	strlcpy(ifr.ifr_name, wif->wname, IFNAMSIZ);
777210502Ssyrinx	ifr.ifr_data = (caddr_t) &wcp;
778210502Ssyrinx
779210502Ssyrinx	if (ioctl(sock, SIOCIFCREATE2, (caddr_t) &ifr) < 0) {
780210502Ssyrinx		syslog(LOG_ERR, "wlan clone create: ioctl(SIOCIFCREATE2) "
781210502Ssyrinx		    "failed: %s", strerror(errno));
782210502Ssyrinx		return (SNMP_ERR_GENERR);
783210502Ssyrinx	}
784210502Ssyrinx
785210502Ssyrinx	return (SNMP_ERR_NOERROR);
786210502Ssyrinx}
787210502Ssyrinx
788210502Ssyrinxint
789210502Ssyrinxwlan_clone_destroy(struct wlan_iface *wif)
790210502Ssyrinx{
791210502Ssyrinx	struct ifreq ifr;
792210502Ssyrinx
793210502Ssyrinx	if (wif == NULL)
794210502Ssyrinx		return (SNMP_ERR_INCONS_VALUE);
795210502Ssyrinx
796210502Ssyrinx	memset(&ifr, 0, sizeof(ifr));
797210502Ssyrinx	strcpy(ifr.ifr_name, wif->wname);
798210502Ssyrinx
799210502Ssyrinx	if (ioctl(sock, SIOCIFDESTROY, &ifr) < 0) {
800210502Ssyrinx		syslog(LOG_ERR, "wlan clone destroy: ioctl(SIOCIFDESTROY) "
801210502Ssyrinx		    "failed: %s", strerror(errno));
802210502Ssyrinx		return (SNMP_ERR_GENERR);
803210502Ssyrinx	}
804210502Ssyrinx
805210502Ssyrinx	return (SNMP_ERR_NOERROR);
806210502Ssyrinx}
807210502Ssyrinx
808210502Ssyrinxstatic int
809210502Ssyrinxwlan_config_snmp2ioctl(int which)
810210502Ssyrinx{
811210502Ssyrinx	int op;
812210502Ssyrinx
813210502Ssyrinx	switch (which) {
814210502Ssyrinx	case LEAF_wlanIfacePacketBurst:
815210502Ssyrinx		op = IEEE80211_IOC_BURST;
816210502Ssyrinx		break;
817210502Ssyrinx	case LEAF_wlanIfaceCountryCode:
818210502Ssyrinx		op = IEEE80211_IOC_REGDOMAIN;
819210502Ssyrinx		break;
820210502Ssyrinx	case LEAF_wlanIfaceRegDomain:
821210502Ssyrinx		op = IEEE80211_IOC_REGDOMAIN;
822210502Ssyrinx		break;
823210502Ssyrinx	case LEAF_wlanIfaceDesiredSsid:
824210502Ssyrinx		op = IEEE80211_IOC_SSID;
825210502Ssyrinx		break;
826210502Ssyrinx	case LEAF_wlanIfaceDesiredChannel:
827210502Ssyrinx		op = IEEE80211_IOC_CURCHAN;
828210502Ssyrinx		break;
829210502Ssyrinx	case LEAF_wlanIfaceDynamicFreqSelection:
830210502Ssyrinx		op = IEEE80211_IOC_DFS;
831210502Ssyrinx		break;
832210502Ssyrinx	case LEAF_wlanIfaceFastFrames:
833210502Ssyrinx		op = IEEE80211_IOC_FF;
834210502Ssyrinx		break;
835210502Ssyrinx	case LEAF_wlanIfaceDturbo:
836210502Ssyrinx		op = IEEE80211_IOC_TURBOP;
837210502Ssyrinx		break;
838210502Ssyrinx	case LEAF_wlanIfaceTxPower:
839210502Ssyrinx		op = IEEE80211_IOC_TXPOWER;
840210502Ssyrinx		break;
841210502Ssyrinx	case LEAF_wlanIfaceFragmentThreshold:
842210502Ssyrinx		op = IEEE80211_IOC_FRAGTHRESHOLD;
843210502Ssyrinx		break;
844210502Ssyrinx	case LEAF_wlanIfaceRTSThreshold:
845210502Ssyrinx		op = IEEE80211_IOC_RTSTHRESHOLD;
846210502Ssyrinx		break;
847210502Ssyrinx	case LEAF_wlanIfaceWlanPrivacySubscribe:
848210502Ssyrinx		op = IEEE80211_IOC_WPS;
849210502Ssyrinx		break;
850210502Ssyrinx	case LEAF_wlanIfaceBgScan:
851210502Ssyrinx		op = IEEE80211_IOC_BGSCAN;
852210502Ssyrinx		break;
853210502Ssyrinx	case LEAF_wlanIfaceBgScanIdle:
854210502Ssyrinx		op = IEEE80211_IOC_BGSCAN_IDLE;
855210502Ssyrinx		break;
856210502Ssyrinx	case LEAF_wlanIfaceBgScanInterval:
857210502Ssyrinx		op = IEEE80211_IOC_BGSCAN_INTERVAL;
858210502Ssyrinx		break;
859210502Ssyrinx	case LEAF_wlanIfaceBeaconMissedThreshold:
860210502Ssyrinx		op = IEEE80211_IOC_BMISSTHRESHOLD;
861210502Ssyrinx		break;
862210502Ssyrinx	case LEAF_wlanIfaceDesiredBssid:
863210502Ssyrinx		op = IEEE80211_IOC_BSSID;
864210502Ssyrinx		break;
865210502Ssyrinx	case LEAF_wlanIfaceRoamingMode:
866210502Ssyrinx		op = IEEE80211_IOC_ROAMING;
867210502Ssyrinx		break;
868210502Ssyrinx	case LEAF_wlanIfaceDot11d:
869210502Ssyrinx		op = IEEE80211_IOC_DOTD;
870210502Ssyrinx		break;
871210502Ssyrinx	case LEAF_wlanIfaceDot11h:
872210502Ssyrinx		op = IEEE80211_IOC_DOTH;
873210502Ssyrinx		break;
874210502Ssyrinx	case LEAF_wlanIfaceDynamicWds:
875210502Ssyrinx		op = IEEE80211_IOC_DWDS;
876210502Ssyrinx		break;
877210502Ssyrinx	case LEAF_wlanIfacePowerSave:
878210502Ssyrinx		op = IEEE80211_IOC_POWERSAVE;
879210502Ssyrinx		break;
880210502Ssyrinx	case LEAF_wlanIfaceApBridge:
881210502Ssyrinx		op = IEEE80211_IOC_APBRIDGE;
882210502Ssyrinx		break;
883210502Ssyrinx	case LEAF_wlanIfaceBeaconInterval:
884210502Ssyrinx		op = IEEE80211_IOC_BEACON_INTERVAL;
885210502Ssyrinx		break;
886210502Ssyrinx	case LEAF_wlanIfaceDtimPeriod:
887210502Ssyrinx		op = IEEE80211_IOC_DTIM_PERIOD;
888210502Ssyrinx		break;
889210502Ssyrinx	case LEAF_wlanIfaceHideSsid:
890210502Ssyrinx		op = IEEE80211_IOC_HIDESSID;
891210502Ssyrinx		break;
892210502Ssyrinx	case LEAF_wlanIfaceInactivityProccess:
893210502Ssyrinx		op = IEEE80211_IOC_INACTIVITY;
894210502Ssyrinx		break;
895210502Ssyrinx	case LEAF_wlanIfaceDot11gProtMode:
896210502Ssyrinx		op = IEEE80211_IOC_PROTMODE;
897210502Ssyrinx		break;
898210502Ssyrinx	case LEAF_wlanIfaceDot11gPureMode:
899210502Ssyrinx		op = IEEE80211_IOC_PUREG;
900210502Ssyrinx		break;
901210502Ssyrinx	case LEAF_wlanIfaceDot11nPureMode:
902210502Ssyrinx		op = IEEE80211_IOC_PUREN;
903210502Ssyrinx		break;
904210502Ssyrinx	case LEAF_wlanIfaceDot11nAmpdu:
905210502Ssyrinx		op = IEEE80211_IOC_AMPDU;
906210502Ssyrinx		break;
907210502Ssyrinx	case LEAF_wlanIfaceDot11nAmpduDensity:
908210502Ssyrinx		op = IEEE80211_IOC_AMPDU_DENSITY;
909210502Ssyrinx		break;
910210502Ssyrinx	case LEAF_wlanIfaceDot11nAmpduLimit:
911210502Ssyrinx		op = IEEE80211_IOC_AMPDU_LIMIT;
912210502Ssyrinx		break;
913210502Ssyrinx	case LEAF_wlanIfaceDot11nAmsdu:
914210502Ssyrinx		op = IEEE80211_IOC_AMSDU;
915210502Ssyrinx		break;
916210502Ssyrinx	case LEAF_wlanIfaceDot11nAmsduLimit:
917210502Ssyrinx		op = IEEE80211_IOC_AMSDU_LIMIT;
918210502Ssyrinx		break;
919210502Ssyrinx	case LEAF_wlanIfaceDot11nHighThroughput:
920210502Ssyrinx		op = IEEE80211_IOC_HTCONF;
921210502Ssyrinx		break;
922210502Ssyrinx	case LEAF_wlanIfaceDot11nHTCompatible:
923210502Ssyrinx		op = IEEE80211_IOC_HTCOMPAT;
924210502Ssyrinx		break;
925210502Ssyrinx	case LEAF_wlanIfaceDot11nHTProtMode:
926210502Ssyrinx		op = IEEE80211_IOC_HTPROTMODE;
927210502Ssyrinx		break;
928210502Ssyrinx	case LEAF_wlanIfaceDot11nRIFS:
929210502Ssyrinx		op = IEEE80211_IOC_RIFS;
930210502Ssyrinx		break;
931210502Ssyrinx	case LEAF_wlanIfaceDot11nShortGI:
932210502Ssyrinx		op = IEEE80211_IOC_SHORTGI;
933210502Ssyrinx		break;
934210502Ssyrinx	case LEAF_wlanIfaceDot11nSMPSMode:
935210502Ssyrinx		op = IEEE80211_IOC_SMPS;
936210502Ssyrinx		break;
937210502Ssyrinx	case LEAF_wlanIfaceTdmaSlot:
938210502Ssyrinx		op = IEEE80211_IOC_TDMA_SLOT;
939210502Ssyrinx		break;
940210502Ssyrinx	case LEAF_wlanIfaceTdmaSlotCount:
941210502Ssyrinx		op = IEEE80211_IOC_TDMA_SLOTCNT;
942210502Ssyrinx		break;
943210502Ssyrinx	case LEAF_wlanIfaceTdmaSlotLength:
944210502Ssyrinx		op = IEEE80211_IOC_TDMA_SLOTLEN;
945210502Ssyrinx		break;
946210502Ssyrinx	case LEAF_wlanIfaceTdmaBeaconInterval:
947210502Ssyrinx		op = IEEE80211_IOC_TDMA_BINTERVAL;
948210502Ssyrinx		break;
949210502Ssyrinx	default:
950210502Ssyrinx		op = -1;
951210502Ssyrinx	}
952210502Ssyrinx
953210502Ssyrinx	return (op);
954210502Ssyrinx}
955210502Ssyrinx
956210502Ssyrinxstatic enum WlanRegDomainCode
957210502Ssyrinxwlan_regdomain_to_snmp(int which)
958210502Ssyrinx{
959210502Ssyrinx	enum WlanRegDomainCode reg_domain;
960210502Ssyrinx
961210502Ssyrinx	switch (which) {
962210502Ssyrinx	case SKU_FCC:
963210502Ssyrinx		reg_domain = WlanRegDomainCode_fcc;
964210502Ssyrinx		break;
965210502Ssyrinx	case SKU_CA:
966210502Ssyrinx		reg_domain = WlanRegDomainCode_ca;
967210502Ssyrinx		break;
968210502Ssyrinx	case SKU_ETSI:
969210502Ssyrinx		reg_domain = WlanRegDomainCode_etsi;
970210502Ssyrinx		break;
971210502Ssyrinx	case SKU_ETSI2:
972210502Ssyrinx		reg_domain = WlanRegDomainCode_etsi2;
973210502Ssyrinx		break;
974210502Ssyrinx	case SKU_ETSI3:
975210502Ssyrinx		reg_domain = WlanRegDomainCode_etsi3;
976210502Ssyrinx		break;
977210502Ssyrinx	case SKU_FCC3:
978210502Ssyrinx		reg_domain = WlanRegDomainCode_fcc3;
979210502Ssyrinx		break;
980210502Ssyrinx	case SKU_JAPAN:
981210502Ssyrinx		reg_domain = WlanRegDomainCode_japan;
982210502Ssyrinx		break;
983210502Ssyrinx	case SKU_KOREA:
984210502Ssyrinx		reg_domain = WlanRegDomainCode_korea;
985210502Ssyrinx		break;
986210502Ssyrinx	case SKU_APAC:
987210502Ssyrinx		reg_domain = WlanRegDomainCode_apac;
988210502Ssyrinx		break;
989210502Ssyrinx	case SKU_APAC2:
990210502Ssyrinx		reg_domain = WlanRegDomainCode_apac2;
991210502Ssyrinx		break;
992210502Ssyrinx	case SKU_APAC3:
993210502Ssyrinx		reg_domain = WlanRegDomainCode_apac3;
994210502Ssyrinx		break;
995210502Ssyrinx	case SKU_ROW:
996210502Ssyrinx		reg_domain = WlanRegDomainCode_row;
997210502Ssyrinx		break;
998210502Ssyrinx	case SKU_NONE:
999210502Ssyrinx		reg_domain = WlanRegDomainCode_none;
1000210502Ssyrinx		break;
1001210502Ssyrinx	case SKU_DEBUG:
1002210502Ssyrinx		reg_domain = WlanRegDomainCode_debug;
1003210502Ssyrinx		break;
1004210502Ssyrinx	case SKU_SR9:
1005210502Ssyrinx		reg_domain = WlanRegDomainCode_sr9;
1006210502Ssyrinx		break;
1007210502Ssyrinx	case SKU_XR9:
1008210502Ssyrinx		reg_domain = WlanRegDomainCode_xr9;
1009210502Ssyrinx		break;
1010210502Ssyrinx	case SKU_GZ901:
1011210502Ssyrinx		reg_domain = WlanRegDomainCode_gz901;
1012210502Ssyrinx		break;
1013210502Ssyrinx	case 0:
1014210502Ssyrinx		reg_domain = WlanRegDomainCode_none;
1015210502Ssyrinx		break;
1016210502Ssyrinx	default:
1017210502Ssyrinx		syslog(LOG_ERR, "unknown regdomain (0x%x) ", which);
1018210502Ssyrinx		reg_domain = WlanRegDomainCode_none;
1019210502Ssyrinx		break;
1020210502Ssyrinx	}
1021210502Ssyrinx
1022210502Ssyrinx	return (reg_domain);
1023210502Ssyrinx}
1024210502Ssyrinx
1025210502Ssyrinxstatic int
1026210502Ssyrinxwlan_snmp_to_regdomain(enum WlanRegDomainCode regdomain)
1027210502Ssyrinx{
1028210502Ssyrinx	int which;
1029210502Ssyrinx
1030210502Ssyrinx	switch (regdomain) {
1031210502Ssyrinx	case WlanRegDomainCode_fcc:
1032210502Ssyrinx		which = SKU_FCC;
1033210502Ssyrinx		break;
1034210502Ssyrinx	case WlanRegDomainCode_ca:
1035210502Ssyrinx		which = SKU_CA;
1036210502Ssyrinx		break;
1037210502Ssyrinx	case WlanRegDomainCode_etsi:
1038210502Ssyrinx		which = SKU_ETSI;
1039210502Ssyrinx		break;
1040210502Ssyrinx	case WlanRegDomainCode_etsi2:
1041210502Ssyrinx		which = SKU_ETSI2;
1042210502Ssyrinx		break;
1043210502Ssyrinx	case WlanRegDomainCode_etsi3:
1044210502Ssyrinx		which = SKU_ETSI3;
1045210502Ssyrinx		break;
1046210502Ssyrinx	case WlanRegDomainCode_fcc3:
1047210502Ssyrinx		which = SKU_FCC3;
1048210502Ssyrinx		break;
1049210502Ssyrinx	case WlanRegDomainCode_japan:
1050210502Ssyrinx		which = SKU_JAPAN;
1051210502Ssyrinx		break;
1052210502Ssyrinx	case WlanRegDomainCode_korea:
1053210502Ssyrinx		which = SKU_KOREA;
1054210502Ssyrinx		break;
1055210502Ssyrinx	case WlanRegDomainCode_apac:
1056210502Ssyrinx		which = SKU_APAC;
1057210502Ssyrinx		break;
1058210502Ssyrinx	case WlanRegDomainCode_apac2:
1059210502Ssyrinx		which = SKU_APAC2;
1060210502Ssyrinx		break;
1061210502Ssyrinx	case WlanRegDomainCode_apac3:
1062210502Ssyrinx		which = SKU_APAC3;
1063210502Ssyrinx		break;
1064210502Ssyrinx	case WlanRegDomainCode_row:
1065210502Ssyrinx		which = SKU_ROW;
1066210502Ssyrinx		break;
1067210502Ssyrinx	case WlanRegDomainCode_none:
1068210502Ssyrinx		which = SKU_NONE;
1069210502Ssyrinx		break;
1070210502Ssyrinx	case WlanRegDomainCode_debug:
1071210502Ssyrinx		which = SKU_DEBUG;
1072210502Ssyrinx		break;
1073210502Ssyrinx	case WlanRegDomainCode_sr9:
1074210502Ssyrinx		which = SKU_SR9;
1075210502Ssyrinx		break;
1076210502Ssyrinx	case WlanRegDomainCode_xr9:
1077210502Ssyrinx		which = SKU_XR9;
1078210502Ssyrinx		break;
1079210502Ssyrinx	case WlanRegDomainCode_gz901:
1080210502Ssyrinx		which = SKU_GZ901;
1081210502Ssyrinx		break;
1082210502Ssyrinx	default:
1083210502Ssyrinx		syslog(LOG_ERR, "unknown snmp regdomain (0x%x) ", regdomain);
1084210502Ssyrinx		which = SKU_NONE;
1085210502Ssyrinx		break;
1086210502Ssyrinx	}
1087210502Ssyrinx
1088210502Ssyrinx	return (which);
1089210502Ssyrinx}
1090210502Ssyrinx
1091210502Ssyrinxstatic int
1092210502Ssyrinxwlan_config_get_country(struct wlan_iface *wif)
1093210502Ssyrinx{
1094210502Ssyrinx	int val = 0;
1095210502Ssyrinx	size_t argsize;
1096210502Ssyrinx	struct ieee80211_regdomain regdomain;
1097210502Ssyrinx
1098210502Ssyrinx	memset(&regdomain, 0, sizeof(regdomain));
1099210502Ssyrinx	argsize = sizeof(regdomain);
1100210502Ssyrinx
1101210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_REGDOMAIN, &val, &regdomain,
1102210502Ssyrinx	    &argsize, 0) < 0)
1103210502Ssyrinx		return (-1);
1104210502Ssyrinx
1105210502Ssyrinx	wif->reg_domain = wlan_regdomain_to_snmp(regdomain.regdomain);
1106210502Ssyrinx	wif->country_code[0] = regdomain.isocc[0];
1107210502Ssyrinx	wif->country_code[1] = regdomain.isocc[1];
1108210502Ssyrinx	wif->country_code[2] = regdomain.location;
1109210502Ssyrinx
1110210502Ssyrinx	return (0);
1111210502Ssyrinx}
1112210502Ssyrinx
1113210502Ssyrinxstatic int
1114210502Ssyrinxwlan_config_set_country(struct wlan_iface *wif, char *ccode, int rdomain)
1115210502Ssyrinx{
1116210502Ssyrinx	int val = 0, txpowermax;
1117210502Ssyrinx	uint32_t i;
1118210502Ssyrinx	size_t argsize = 0;
1119210502Ssyrinx	struct ieee80211_regdomain_req *regdomain;
1120210502Ssyrinx
1121210502Ssyrinx	if (wlan_get_channel_list(wif) < 0)
1122210502Ssyrinx		return (-1);
1123210502Ssyrinx
1124210502Ssyrinx	if (wif->nchannels == 0) {
1125210502Ssyrinx		syslog(LOG_ERR, "iface %s - set regdomain failed", wif->wname);
1126210502Ssyrinx		return (-1);
1127210502Ssyrinx	}
1128210502Ssyrinx
1129210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPOWMAX, &txpowermax, 0,
1130210502Ssyrinx	    &argsize, 0) < 0)
1131210502Ssyrinx		return (-1);
1132210502Ssyrinx
1133210502Ssyrinx	regdomain = malloc(IEEE80211_REGDOMAIN_SIZE(wif->nchannels));
1134210502Ssyrinx	if (regdomain == NULL)
1135210502Ssyrinx		return (-1);
1136210502Ssyrinx	memset(regdomain, 0, IEEE80211_REGDOMAIN_SIZE(wif->nchannels));
1137210502Ssyrinx	argsize = IEEE80211_REGDOMAIN_SIZE(wif->nchannels);
1138210502Ssyrinx
1139210502Ssyrinx	/* XXX: recheck with how this is done by ifconfig(8) */
1140210502Ssyrinx	regdomain->rd.regdomain = wlan_snmp_to_regdomain(rdomain);
1141210502Ssyrinx	regdomain->rd.isocc[0] = ccode[0];
1142210502Ssyrinx	regdomain->rd.isocc[1] = ccode[1];
1143210502Ssyrinx	regdomain->rd.location = ccode[2];
1144210502Ssyrinx
1145210502Ssyrinx	/* XXX: fill the channel list properly */
1146210502Ssyrinx	regdomain->chaninfo.ic_nchans = wif->nchannels;
1147210502Ssyrinx	memcpy(regdomain->chaninfo.ic_chans, wif->chanlist,
1148210502Ssyrinx	    wif->nchannels * sizeof(struct ieee80211_channel));
1149210502Ssyrinx	for (i = 0; i < wif->nchannels; i++)
1150210502Ssyrinx		regdomain->chaninfo.ic_chans[i].ic_maxregpower = txpowermax;
1151210502Ssyrinx
1152210502Ssyrinx	wif->state = wlanIfaceState_down;
1153210502Ssyrinx	if (wlan_config_state(wif, 1) < 0 ||
1154210502Ssyrinx	    wlan_ioctl(wif->wname, IEEE80211_IOC_REGDOMAIN, &val, regdomain,
1155210502Ssyrinx	    &argsize, 1) < 0) {
1156210502Ssyrinx		free(regdomain);
1157210502Ssyrinx		return (-1);
1158210502Ssyrinx	}
1159210502Ssyrinx
1160210502Ssyrinx	wif->state = wlanIfaceState_up;
1161210502Ssyrinx	(void)wlan_config_state(wif, 1);
1162210502Ssyrinx	wif->reg_domain = wlan_regdomain_to_snmp(regdomain->rd.regdomain);
1163210502Ssyrinx	wif->country_code[0] = regdomain->rd.isocc[0];
1164210502Ssyrinx	wif->country_code[1] = regdomain->rd.isocc[1];
1165210502Ssyrinx	wif->country_code[2] = regdomain->rd.location;
1166210502Ssyrinx	free(regdomain);
1167210502Ssyrinx
1168210502Ssyrinx	return (0);
1169210502Ssyrinx}
1170210502Ssyrinx
1171210502Ssyrinxint
1172210502Ssyrinxwlan_config_get_dssid(struct wlan_iface *wif)
1173210502Ssyrinx{
1174210502Ssyrinx	int val = -1;
1175210502Ssyrinx	size_t argsize = IEEE80211_NWID_LEN + 1;
1176210502Ssyrinx	char ssid[IEEE80211_NWID_LEN + 1];
1177210502Ssyrinx
1178210502Ssyrinx	memset(ssid, 0, IEEE80211_NWID_LEN + 1);
1179210502Ssyrinx
1180210502Ssyrinx	if (wlan_ioctl(wif->wname,
1181210502Ssyrinx	    (wif->mode == WlanIfaceOperatingModeType_meshPoint) ?
1182210502Ssyrinx	    IEEE80211_IOC_MESH_ID : IEEE80211_IOC_SSID, &val, ssid,
1183210502Ssyrinx	    &argsize, 0) < 0)
1184210502Ssyrinx		return (-1);
1185210502Ssyrinx
1186210502Ssyrinx	if (argsize > IEEE80211_NWID_LEN)
1187210502Ssyrinx		argsize = IEEE80211_NWID_LEN;
1188210502Ssyrinx	memcpy(wif->desired_ssid, ssid, argsize);
1189210502Ssyrinx	wif->desired_ssid[argsize] = '\0';
1190210502Ssyrinx
1191210502Ssyrinx	return (0);
1192210502Ssyrinx}
1193210502Ssyrinx
1194210502Ssyrinxint
1195210502Ssyrinxwlan_config_set_dssid(struct wlan_iface *wif, char *ssid, int slen)
1196210502Ssyrinx{
1197210502Ssyrinx	int val = 0;
1198210502Ssyrinx	size_t argsize = slen;
1199210502Ssyrinx
1200210502Ssyrinx	if (wlan_ioctl(wif->wname,
1201210502Ssyrinx	    (wif->mode == WlanIfaceOperatingModeType_meshPoint) ?
1202210502Ssyrinx	    IEEE80211_IOC_MESH_ID : IEEE80211_IOC_SSID, &val, ssid,
1203210502Ssyrinx	    &argsize, 1) < 0)
1204210502Ssyrinx		return (-1);
1205210502Ssyrinx
1206210502Ssyrinx	if (argsize > IEEE80211_NWID_LEN)
1207210502Ssyrinx		argsize = IEEE80211_NWID_LEN;
1208210502Ssyrinx	memcpy(wif->desired_ssid, ssid, argsize);
1209210502Ssyrinx	wif->desired_ssid[argsize] = '\0';
1210210502Ssyrinx
1211210502Ssyrinx	return (0);
1212210502Ssyrinx}
1213210502Ssyrinx
1214210502Ssyrinxstatic int
1215210502Ssyrinxwlan_config_get_dchannel(struct wlan_iface *wif)
1216210502Ssyrinx{
1217210502Ssyrinx	uint32_t i = 0;
1218210502Ssyrinx	int val = 0;
1219210502Ssyrinx	size_t argsize = sizeof(struct ieee80211_channel);
1220210502Ssyrinx	struct ieee80211_channel chan;
1221210502Ssyrinx
1222210502Ssyrinx	if (wlan_get_channel_list(wif) < 0)
1223210502Ssyrinx		return (-1);
1224210502Ssyrinx
1225210502Ssyrinx	memset(&chan, 0, sizeof(chan));
1226210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_CURCHAN, &val, &chan,
1227210502Ssyrinx	    &argsize, 0) < 0)
1228210502Ssyrinx		return (-1);
1229210502Ssyrinx
1230210502Ssyrinx	for (i = 0; i < wif->nchannels; i++)
1231210502Ssyrinx		if (chan.ic_ieee == wif->chanlist[i].ic_ieee &&
1232210502Ssyrinx		    chan.ic_flags == wif->chanlist[i].ic_flags) {
1233210502Ssyrinx			wif->desired_channel = i + 1;
1234210502Ssyrinx			break;
1235210502Ssyrinx		}
1236210502Ssyrinx
1237210502Ssyrinx	return (0);
1238210502Ssyrinx}
1239210502Ssyrinx
1240210502Ssyrinxstatic int
1241210502Ssyrinxwlan_config_set_dchannel(struct wlan_iface *wif, uint32_t dchannel)
1242210502Ssyrinx{
1243210502Ssyrinx	int val = 0;
1244210502Ssyrinx	size_t argsize = sizeof(struct ieee80211_channel);
1245210502Ssyrinx	struct ieee80211_channel chan;
1246210502Ssyrinx
1247210502Ssyrinx	if (wlan_get_channel_list(wif) < 0)
1248210502Ssyrinx		return (-1);
1249210502Ssyrinx
1250210502Ssyrinx	if (dchannel > wif->nchannels)
1251210502Ssyrinx		return (-1);
1252210502Ssyrinx
1253210502Ssyrinx	memcpy(&chan, wif->chanlist + dchannel - 1, sizeof(chan));
1254210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_CURCHAN, &val, &chan,
1255210502Ssyrinx	    &argsize, 1) < 0)
1256210502Ssyrinx		return (-1);
1257210502Ssyrinx
1258210502Ssyrinx	wif->desired_channel = dchannel;
1259210502Ssyrinx
1260210502Ssyrinx	return (0);
1261210502Ssyrinx}
1262210502Ssyrinx
1263210502Ssyrinxstatic int
1264210502Ssyrinxwlan_config_get_bssid(struct wlan_iface *wif)
1265210502Ssyrinx{
1266210502Ssyrinx	int val = 0;
1267210502Ssyrinx	size_t argsize = IEEE80211_ADDR_LEN;
1268210502Ssyrinx	char bssid[IEEE80211_ADDR_LEN];
1269210502Ssyrinx
1270210502Ssyrinx	memset(bssid, 0, IEEE80211_ADDR_LEN);
1271210502Ssyrinx
1272210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_BSSID, &val, bssid,
1273210502Ssyrinx	    &argsize, 0) < 0 || argsize != IEEE80211_ADDR_LEN)
1274210502Ssyrinx		return (-1);
1275210502Ssyrinx
1276210502Ssyrinx	memcpy(wif->desired_bssid, bssid, IEEE80211_ADDR_LEN);
1277210502Ssyrinx
1278210502Ssyrinx	return (0);
1279210502Ssyrinx}
1280210502Ssyrinx
1281210502Ssyrinxstatic int
1282210502Ssyrinxwlan_config_set_bssid(struct wlan_iface *wif, uint8_t *bssid)
1283210502Ssyrinx{
1284210502Ssyrinx	int val = 0;
1285210502Ssyrinx	size_t argsize = IEEE80211_ADDR_LEN;
1286210502Ssyrinx
1287210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_BSSID, &val, bssid,
1288210502Ssyrinx	    &argsize, 1) < 0 || argsize != IEEE80211_ADDR_LEN)
1289210502Ssyrinx		return (-1);
1290210502Ssyrinx
1291210502Ssyrinx	memcpy(wif->desired_bssid, bssid, IEEE80211_ADDR_LEN);
1292210502Ssyrinx
1293210502Ssyrinx	return (0);
1294210502Ssyrinx}
1295210502Ssyrinx
1296210502Ssyrinx/*
1297210502Ssyrinx * Convert the value returned by the kernel to the appropriate SNMP
1298210502Ssyrinx * representation and set the corresponding interface member accordingly.
1299210502Ssyrinx */
1300210502Ssyrinxstatic void
1301210502Ssyrinxwlan_config_set_snmp_intval(struct wlan_iface *wif, int op, int val)
1302210502Ssyrinx{
1303210502Ssyrinx	switch (op) {
1304210502Ssyrinx	case IEEE80211_IOC_BURST:
1305210502Ssyrinx		if (val == 0)
1306210502Ssyrinx			wif->packet_burst = TruthValue_false;
1307210502Ssyrinx		else
1308210502Ssyrinx			wif->packet_burst = TruthValue_true;
1309210502Ssyrinx		break;
1310210502Ssyrinx	case IEEE80211_IOC_DFS:
1311210502Ssyrinx		if (val == 0)
1312210502Ssyrinx			wif->dyn_frequency = TruthValue_false;
1313210502Ssyrinx		else
1314210502Ssyrinx			wif->dyn_frequency = TruthValue_true;
1315210502Ssyrinx		break;
1316210502Ssyrinx	case IEEE80211_IOC_FF:
1317210502Ssyrinx		if (val == 0)
1318210502Ssyrinx			wif->fast_frames = TruthValue_false;
1319210502Ssyrinx		else
1320210502Ssyrinx			wif->fast_frames = TruthValue_true;
1321210502Ssyrinx		break;
1322210502Ssyrinx	case IEEE80211_IOC_TURBOP:
1323210502Ssyrinx		if (val == 0)
1324210502Ssyrinx			wif->dturbo = TruthValue_false;
1325210502Ssyrinx		else
1326210502Ssyrinx			wif->dturbo = TruthValue_true;
1327210502Ssyrinx		break;
1328210502Ssyrinx	case IEEE80211_IOC_TXPOWER:
1329210502Ssyrinx		wif->tx_power = val / 2;
1330210502Ssyrinx		break;
1331210502Ssyrinx	case IEEE80211_IOC_FRAGTHRESHOLD:
1332210502Ssyrinx		wif->frag_threshold = val;
1333210502Ssyrinx		break;
1334210502Ssyrinx	case IEEE80211_IOC_RTSTHRESHOLD:
1335210502Ssyrinx		wif->rts_threshold = val;
1336210502Ssyrinx		break;
1337210502Ssyrinx	case IEEE80211_IOC_WPS:
1338210502Ssyrinx		if (val == 0)
1339210502Ssyrinx			wif->priv_subscribe = TruthValue_false;
1340210502Ssyrinx		else
1341210502Ssyrinx			wif->priv_subscribe = TruthValue_true;
1342210502Ssyrinx		break;
1343210502Ssyrinx	case IEEE80211_IOC_BGSCAN:
1344210502Ssyrinx		if (val == 0)
1345210502Ssyrinx			wif->bg_scan = TruthValue_false;
1346210502Ssyrinx		else
1347210502Ssyrinx			wif->bg_scan = TruthValue_true;
1348210502Ssyrinx		break;
1349210502Ssyrinx	case IEEE80211_IOC_BGSCAN_IDLE:
1350210502Ssyrinx		wif->bg_scan_idle = val;
1351210502Ssyrinx		break;
1352210502Ssyrinx	case IEEE80211_IOC_BGSCAN_INTERVAL:
1353210502Ssyrinx		wif->bg_scan_interval = val;
1354210502Ssyrinx		break;
1355210502Ssyrinx	case IEEE80211_IOC_BMISSTHRESHOLD:
1356210502Ssyrinx		wif->beacons_missed = val;
1357210502Ssyrinx		break;
1358210502Ssyrinx	case IEEE80211_IOC_ROAMING:
1359210502Ssyrinx		switch (val) {
1360210502Ssyrinx		case IEEE80211_ROAMING_DEVICE:
1361210502Ssyrinx			wif->roam_mode = wlanIfaceRoamingMode_device;
1362210502Ssyrinx			break;
1363210502Ssyrinx		case IEEE80211_ROAMING_MANUAL:
1364210502Ssyrinx			wif->roam_mode = wlanIfaceRoamingMode_manual;
1365210502Ssyrinx			break;
1366210502Ssyrinx		case IEEE80211_ROAMING_AUTO:
1367210502Ssyrinx			/* FALTHROUGH */
1368210502Ssyrinx		default:
1369210502Ssyrinx			wif->roam_mode = wlanIfaceRoamingMode_auto;
1370210502Ssyrinx			break;
1371210502Ssyrinx		}
1372210502Ssyrinx		break;
1373210502Ssyrinx	case IEEE80211_IOC_DOTD:
1374210502Ssyrinx		if (val == 0)
1375210502Ssyrinx			wif->dot11d = TruthValue_false;
1376210502Ssyrinx		else
1377210502Ssyrinx			wif->dot11d = TruthValue_true;
1378210502Ssyrinx		break;
1379210502Ssyrinx	case IEEE80211_IOC_DOTH:
1380210502Ssyrinx		if (val == 0)
1381210502Ssyrinx			wif->dot11h = TruthValue_false;
1382210502Ssyrinx		else
1383210502Ssyrinx			wif->dot11h = TruthValue_true;
1384210502Ssyrinx		break;
1385210502Ssyrinx	case IEEE80211_IOC_DWDS:
1386210502Ssyrinx		if (val == 0)
1387210502Ssyrinx			wif->dynamic_wds = TruthValue_false;
1388210502Ssyrinx		else
1389210502Ssyrinx			wif->dynamic_wds = TruthValue_true;
1390210502Ssyrinx		break;
1391210502Ssyrinx	case IEEE80211_IOC_POWERSAVE:
1392210502Ssyrinx		if (val == 0)
1393210502Ssyrinx			wif->power_save = TruthValue_false;
1394210502Ssyrinx		else
1395210502Ssyrinx			wif->power_save = TruthValue_true;
1396210502Ssyrinx		break;
1397210502Ssyrinx	case IEEE80211_IOC_APBRIDGE:
1398210502Ssyrinx		if (val == 0)
1399210502Ssyrinx			wif->ap_bridge = TruthValue_false;
1400210502Ssyrinx		else
1401210502Ssyrinx			wif->ap_bridge = TruthValue_true;
1402210502Ssyrinx		break;
1403210502Ssyrinx	case IEEE80211_IOC_BEACON_INTERVAL:
1404210502Ssyrinx		wif->beacon_interval = val;
1405210502Ssyrinx		break;
1406210502Ssyrinx	case IEEE80211_IOC_DTIM_PERIOD:
1407210502Ssyrinx		wif->dtim_period = val;
1408210502Ssyrinx		break;
1409210502Ssyrinx	case IEEE80211_IOC_HIDESSID:
1410210502Ssyrinx		if (val == 0)
1411210502Ssyrinx			wif->hide_ssid = TruthValue_false;
1412210502Ssyrinx		else
1413210502Ssyrinx			wif->hide_ssid = TruthValue_true;
1414210502Ssyrinx		break;
1415210502Ssyrinx	case IEEE80211_IOC_INACTIVITY:
1416210502Ssyrinx		if (val == 0)
1417210502Ssyrinx			wif->inact_process = TruthValue_false;
1418210502Ssyrinx		else
1419210502Ssyrinx			wif->inact_process = TruthValue_true;
1420210502Ssyrinx		break;
1421210502Ssyrinx	case IEEE80211_IOC_PROTMODE:
1422210502Ssyrinx		switch (val) {
1423210502Ssyrinx		case IEEE80211_PROTMODE_CTS:
1424210502Ssyrinx			wif->do11g_protect = wlanIfaceDot11gProtMode_cts;
1425210502Ssyrinx			break;
1426210502Ssyrinx		case IEEE80211_PROTMODE_RTSCTS:
1427210502Ssyrinx			wif->do11g_protect = wlanIfaceDot11gProtMode_rtscts;
1428210502Ssyrinx			break;
1429210502Ssyrinx		case IEEE80211_PROTMODE_OFF:
1430210502Ssyrinx			/* FALLTHROUGH */
1431210502Ssyrinx		default:
1432210502Ssyrinx			wif->do11g_protect = wlanIfaceDot11gProtMode_off;
1433210502Ssyrinx			break;
1434210502Ssyrinx		}
1435210502Ssyrinx		break;
1436210502Ssyrinx	case IEEE80211_IOC_PUREG:
1437210502Ssyrinx		if (val == 0)
1438210502Ssyrinx			wif->dot11g_pure = TruthValue_false;
1439210502Ssyrinx		else
1440210502Ssyrinx			wif->dot11g_pure = TruthValue_true;
1441210502Ssyrinx		break;
1442210502Ssyrinx	case IEEE80211_IOC_PUREN:
1443210502Ssyrinx		if (val == 0)
1444210502Ssyrinx			wif->dot11n_pure = TruthValue_false;
1445210502Ssyrinx		else
1446210502Ssyrinx			wif->dot11n_pure = TruthValue_true;
1447210502Ssyrinx		break;
1448210502Ssyrinx	case IEEE80211_IOC_AMPDU:
1449210502Ssyrinx		switch (val) {
1450210502Ssyrinx		case 0:
1451210502Ssyrinx			wif->ampdu = WlanIfaceDot11nPduType_disabled;
1452210502Ssyrinx			break;
1453210502Ssyrinx		case 1:
1454210502Ssyrinx			wif->ampdu = WlanIfaceDot11nPduType_txOnly;
1455210502Ssyrinx			break;
1456210502Ssyrinx		case 2:
1457210502Ssyrinx			wif->ampdu = WlanIfaceDot11nPduType_rxOnly;
1458210502Ssyrinx			break;
1459210502Ssyrinx		case 3:
1460210502Ssyrinx			/* FALLTHROUGH */
1461210502Ssyrinx		default:
1462210502Ssyrinx			wif->ampdu = WlanIfaceDot11nPduType_txAndRx;
1463210502Ssyrinx			break;
1464210502Ssyrinx		}
1465210502Ssyrinx		break;
1466210502Ssyrinx	case IEEE80211_IOC_AMPDU_DENSITY:
1467210502Ssyrinx		switch (val) {
1468210502Ssyrinx		case IEEE80211_HTCAP_MPDUDENSITY_025:
1469210502Ssyrinx			wif->ampdu_density = 25;
1470210502Ssyrinx			break;
1471210502Ssyrinx		case IEEE80211_HTCAP_MPDUDENSITY_05:
1472210502Ssyrinx			wif->ampdu_density = 50;
1473210502Ssyrinx			break;
1474210502Ssyrinx		case IEEE80211_HTCAP_MPDUDENSITY_1:
1475210502Ssyrinx			wif->ampdu_density = 100;
1476210502Ssyrinx			break;
1477210502Ssyrinx		case IEEE80211_HTCAP_MPDUDENSITY_2:
1478210502Ssyrinx			wif->ampdu_density = 200;
1479210502Ssyrinx			break;
1480210502Ssyrinx		case IEEE80211_HTCAP_MPDUDENSITY_4:
1481210502Ssyrinx			wif->ampdu_density = 400;
1482210502Ssyrinx			break;
1483210502Ssyrinx		case IEEE80211_HTCAP_MPDUDENSITY_8:
1484210502Ssyrinx			wif->ampdu_density = 800;
1485210502Ssyrinx			break;
1486210502Ssyrinx		case IEEE80211_HTCAP_MPDUDENSITY_16:
1487210502Ssyrinx			wif->ampdu_density = 1600;
1488210502Ssyrinx			break;
1489210502Ssyrinx		case IEEE80211_HTCAP_MPDUDENSITY_NA:
1490210502Ssyrinx		default:
1491210502Ssyrinx			wif->ampdu_density = 0;
1492210502Ssyrinx			break;
1493210502Ssyrinx		}
1494210502Ssyrinx		break;
1495210502Ssyrinx	case IEEE80211_IOC_AMPDU_LIMIT:
1496210502Ssyrinx		switch (val) {
1497210502Ssyrinx		case IEEE80211_HTCAP_MAXRXAMPDU_8K:
1498210502Ssyrinx			wif->ampdu_limit = 8192;
1499210502Ssyrinx			break;
1500210502Ssyrinx		case IEEE80211_HTCAP_MAXRXAMPDU_16K:
1501210502Ssyrinx			wif->ampdu_limit = 16384;
1502210502Ssyrinx			break;
1503210502Ssyrinx		case IEEE80211_HTCAP_MAXRXAMPDU_32K:
1504210502Ssyrinx			wif->ampdu_limit = 32768;
1505210502Ssyrinx			break;
1506210502Ssyrinx		case IEEE80211_HTCAP_MAXRXAMPDU_64K:
1507210502Ssyrinx		default:
1508210502Ssyrinx			wif->ampdu_limit = 65536;
1509210502Ssyrinx			break;
1510210502Ssyrinx		}
1511210502Ssyrinx		break;
1512210502Ssyrinx	case IEEE80211_IOC_AMSDU:
1513210502Ssyrinx		switch (val) {
1514210502Ssyrinx		case 0:
1515210502Ssyrinx			wif->amsdu = WlanIfaceDot11nPduType_disabled;
1516210502Ssyrinx			break;
1517210502Ssyrinx		case 1:
1518210502Ssyrinx			wif->amsdu = WlanIfaceDot11nPduType_txOnly;
1519210502Ssyrinx			break;
1520210502Ssyrinx		case 3:
1521210502Ssyrinx			wif->amsdu = WlanIfaceDot11nPduType_txAndRx;
1522210502Ssyrinx			break;
1523210502Ssyrinx		case 2:
1524210502Ssyrinx		default:
1525210502Ssyrinx			/* FALLTHROUGH */
1526210502Ssyrinx			wif->amsdu = WlanIfaceDot11nPduType_rxOnly;
1527210502Ssyrinx			break;
1528210502Ssyrinx		}
1529210502Ssyrinx		break;
1530210502Ssyrinx	case IEEE80211_IOC_AMSDU_LIMIT:
1531210502Ssyrinx		wif->amsdu_limit = val;
1532210502Ssyrinx		break;
1533210502Ssyrinx	case IEEE80211_IOC_HTCONF:
1534210502Ssyrinx		if (val == 0) /* XXX */
1535210502Ssyrinx			wif->ht_enabled = TruthValue_false;
1536210502Ssyrinx		else
1537210502Ssyrinx			wif->ht_enabled = TruthValue_true;
1538210502Ssyrinx		break;
1539210502Ssyrinx	case IEEE80211_IOC_HTCOMPAT:
1540210502Ssyrinx		if (val == 0)
1541210502Ssyrinx			wif->ht_compatible = TruthValue_false;
1542210502Ssyrinx		else
1543210502Ssyrinx			wif->ht_compatible = TruthValue_true;
1544210502Ssyrinx		break;
1545210502Ssyrinx	case IEEE80211_IOC_HTPROTMODE:
1546210502Ssyrinx		if (val == IEEE80211_PROTMODE_RTSCTS)
1547210502Ssyrinx			wif->ht_prot_mode = wlanIfaceDot11nHTProtMode_rts;
1548210502Ssyrinx		else
1549210502Ssyrinx			wif->ht_prot_mode = wlanIfaceDot11nHTProtMode_off;
1550210502Ssyrinx		break;
1551210502Ssyrinx	case IEEE80211_IOC_RIFS:
1552210502Ssyrinx		if (val == 0)
1553210502Ssyrinx			wif->rifs = TruthValue_false;
1554210502Ssyrinx		else
1555210502Ssyrinx			wif->rifs = TruthValue_true;
1556210502Ssyrinx		break;
1557210502Ssyrinx	case IEEE80211_IOC_SHORTGI:
1558210502Ssyrinx		if (val == 0)
1559210502Ssyrinx			wif->short_gi = TruthValue_false;
1560210502Ssyrinx		else
1561210502Ssyrinx			wif->short_gi = TruthValue_true;
1562210502Ssyrinx		break;
1563210502Ssyrinx	case IEEE80211_IOC_SMPS:
1564210502Ssyrinx		switch (val) {
1565210502Ssyrinx		case IEEE80211_HTCAP_SMPS_DYNAMIC:
1566210502Ssyrinx			wif->smps_mode = wlanIfaceDot11nSMPSMode_dynamic;
1567210502Ssyrinx			break;
1568210502Ssyrinx		case IEEE80211_HTCAP_SMPS_ENA:
1569210502Ssyrinx			wif->smps_mode = wlanIfaceDot11nSMPSMode_static;
1570210502Ssyrinx			break;
1571210502Ssyrinx		case IEEE80211_HTCAP_SMPS_OFF:
1572210502Ssyrinx			/* FALLTHROUGH */
1573210502Ssyrinx		default:
1574210502Ssyrinx			wif->smps_mode = wlanIfaceDot11nSMPSMode_disabled;
1575210502Ssyrinx			break;
1576210502Ssyrinx		}
1577210502Ssyrinx		break;
1578210502Ssyrinx	case IEEE80211_IOC_TDMA_SLOT:
1579210502Ssyrinx		wif->tdma_slot = val;
1580210502Ssyrinx		break;
1581210502Ssyrinx	case IEEE80211_IOC_TDMA_SLOTCNT:
1582210502Ssyrinx		wif->tdma_slot_count = val;
1583210502Ssyrinx		break;
1584210502Ssyrinx	case IEEE80211_IOC_TDMA_SLOTLEN:
1585210502Ssyrinx		wif->tdma_slot_length = val;
1586210502Ssyrinx		break;
1587210502Ssyrinx	case IEEE80211_IOC_TDMA_BINTERVAL:
1588210502Ssyrinx		wif->tdma_binterval = val;
1589210502Ssyrinx		break;
1590210502Ssyrinx	default:
1591210502Ssyrinx		break;
1592210502Ssyrinx	}
1593210502Ssyrinx}
1594210502Ssyrinx
1595210502Ssyrinx/*
1596210502Ssyrinx * Convert an SNMP value to the kernel equivalent and also do sanity check
1597210502Ssyrinx * for each specific type.
1598210502Ssyrinx */
1599210502Ssyrinxstatic int
1600210502Ssyrinxwlan_config_snmp2value(int which, int sval, int *value)
1601210502Ssyrinx{
1602210502Ssyrinx	*value = 0;
1603210502Ssyrinx
1604210502Ssyrinx	switch (which) {
1605210502Ssyrinx	case IEEE80211_IOC_BURST:
1606210502Ssyrinx	case IEEE80211_IOC_DFS:
1607210502Ssyrinx	case IEEE80211_IOC_FF:
1608210502Ssyrinx	case IEEE80211_IOC_TURBOP:
1609210502Ssyrinx	case IEEE80211_IOC_WPS:
1610210502Ssyrinx	case IEEE80211_IOC_BGSCAN:
1611210502Ssyrinx	case IEEE80211_IOC_DOTD:
1612210502Ssyrinx	case IEEE80211_IOC_DOTH:
1613210502Ssyrinx	case IEEE80211_IOC_DWDS:
1614210502Ssyrinx	case IEEE80211_IOC_POWERSAVE:
1615210502Ssyrinx	case IEEE80211_IOC_APBRIDGE:
1616210502Ssyrinx	case IEEE80211_IOC_HIDESSID:
1617210502Ssyrinx	case IEEE80211_IOC_INACTIVITY:
1618210502Ssyrinx	case IEEE80211_IOC_PUREG:
1619210502Ssyrinx	case IEEE80211_IOC_PUREN:
1620210502Ssyrinx	case IEEE80211_IOC_HTCONF:
1621210502Ssyrinx	case IEEE80211_IOC_HTCOMPAT:
1622210502Ssyrinx	case IEEE80211_IOC_RIFS:
1623210502Ssyrinx		if (sval == TruthValue_true)
1624210502Ssyrinx			*value = 1;
1625210502Ssyrinx		else if (sval != TruthValue_false)
1626210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1627210502Ssyrinx		break;
1628210502Ssyrinx	case IEEE80211_IOC_REGDOMAIN:
1629210502Ssyrinx		break;
1630210502Ssyrinx	case IEEE80211_IOC_SSID:
1631210502Ssyrinx		break;
1632210502Ssyrinx	case IEEE80211_IOC_CURCHAN:
1633210502Ssyrinx		break;
1634210502Ssyrinx	case IEEE80211_IOC_TXPOWER:
1635210502Ssyrinx		*value = sval * 2;
1636210502Ssyrinx		break;
1637210502Ssyrinx	case IEEE80211_IOC_FRAGTHRESHOLD:
1638210502Ssyrinx		if (sval < IEEE80211_FRAG_MIN || sval > IEEE80211_FRAG_MAX)
1639210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1640210502Ssyrinx		*value = sval;
1641210502Ssyrinx		break;
1642210502Ssyrinx	case IEEE80211_IOC_RTSTHRESHOLD:
1643210502Ssyrinx		if (sval < IEEE80211_RTS_MIN || sval > IEEE80211_RTS_MAX)
1644210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1645210502Ssyrinx		*value = sval;
1646210502Ssyrinx		break;
1647210502Ssyrinx	case IEEE80211_IOC_BGSCAN_IDLE:
1648210502Ssyrinx		if (sval < WLAN_BGSCAN_IDLE_MIN)
1649210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1650210502Ssyrinx		*value = sval;
1651210502Ssyrinx		break;
1652210502Ssyrinx	case IEEE80211_IOC_BGSCAN_INTERVAL:
1653210502Ssyrinx		if (sval < WLAN_SCAN_VALID_MIN)
1654210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1655210502Ssyrinx		*value = sval;
1656210502Ssyrinx		break;
1657210502Ssyrinx	case IEEE80211_IOC_BMISSTHRESHOLD:
1658210502Ssyrinx		if (sval < IEEE80211_HWBMISS_MIN || sval > IEEE80211_HWBMISS_MAX)
1659210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1660210502Ssyrinx		*value = sval;
1661210502Ssyrinx		break;
1662210502Ssyrinx	case IEEE80211_IOC_BSSID:
1663210502Ssyrinx		break;
1664210502Ssyrinx	case IEEE80211_IOC_ROAMING:
1665210502Ssyrinx		switch (sval) {
1666210502Ssyrinx		case wlanIfaceRoamingMode_device:
1667210502Ssyrinx			*value = IEEE80211_ROAMING_DEVICE;
1668210502Ssyrinx			break;
1669210502Ssyrinx		case wlanIfaceRoamingMode_manual:
1670210502Ssyrinx			*value = IEEE80211_ROAMING_MANUAL;
1671210502Ssyrinx			break;
1672210502Ssyrinx		case wlanIfaceRoamingMode_auto:
1673210502Ssyrinx			*value = IEEE80211_ROAMING_AUTO;
1674210502Ssyrinx			break;
1675210502Ssyrinx		default:
1676210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1677210502Ssyrinx		}
1678210502Ssyrinx		break;
1679210502Ssyrinx	case IEEE80211_IOC_BEACON_INTERVAL:
1680210502Ssyrinx		if (sval < IEEE80211_BINTVAL_MIN || sval > IEEE80211_BINTVAL_MAX)
1681210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1682210502Ssyrinx		*value = sval;
1683210502Ssyrinx		break;
1684210502Ssyrinx	case IEEE80211_IOC_DTIM_PERIOD:
1685210502Ssyrinx		if (sval < IEEE80211_DTIM_MIN || sval > IEEE80211_DTIM_MAX)
1686210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1687210502Ssyrinx		*value = sval;
1688210502Ssyrinx		break;
1689210502Ssyrinx	case IEEE80211_IOC_PROTMODE:
1690210502Ssyrinx		switch (sval) {
1691210502Ssyrinx		case wlanIfaceDot11gProtMode_cts:
1692210502Ssyrinx			*value = IEEE80211_PROTMODE_CTS;
1693210502Ssyrinx			break;
1694210502Ssyrinx		case wlanIfaceDot11gProtMode_rtscts:
1695210502Ssyrinx			*value = IEEE80211_PROTMODE_RTSCTS;
1696210502Ssyrinx			break;
1697210502Ssyrinx		case wlanIfaceDot11gProtMode_off:
1698210502Ssyrinx			*value = IEEE80211_PROTMODE_OFF;
1699210502Ssyrinx			break;
1700210502Ssyrinx		default:
1701210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1702210502Ssyrinx		}
1703210502Ssyrinx		break;
1704210502Ssyrinx	case IEEE80211_IOC_AMPDU:
1705210502Ssyrinx		switch (sval) {
1706210502Ssyrinx		case WlanIfaceDot11nPduType_disabled:
1707210502Ssyrinx			break;
1708210502Ssyrinx		case WlanIfaceDot11nPduType_txOnly:
1709210502Ssyrinx			*value = 1;
1710210502Ssyrinx			break;
1711210502Ssyrinx		case WlanIfaceDot11nPduType_rxOnly:
1712210502Ssyrinx			*value = 2;
1713210502Ssyrinx			break;
1714210502Ssyrinx		case WlanIfaceDot11nPduType_txAndRx:
1715210502Ssyrinx			*value = 3;
1716210502Ssyrinx			break;
1717210502Ssyrinx		default:
1718210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1719210502Ssyrinx		}
1720210502Ssyrinx		break;
1721210502Ssyrinx	case IEEE80211_IOC_AMPDU_DENSITY:
1722210502Ssyrinx		switch (sval) {
1723210502Ssyrinx		case 0:
1724210502Ssyrinx			*value = IEEE80211_HTCAP_MPDUDENSITY_NA;
1725210502Ssyrinx			break;
1726210502Ssyrinx		case 25:
1727210502Ssyrinx			*value = IEEE80211_HTCAP_MPDUDENSITY_025;
1728210502Ssyrinx			break;
1729210502Ssyrinx		case 50:
1730210502Ssyrinx			*value = IEEE80211_HTCAP_MPDUDENSITY_05;
1731210502Ssyrinx			break;
1732210502Ssyrinx		case 100:
1733210502Ssyrinx			*value = IEEE80211_HTCAP_MPDUDENSITY_1;
1734210502Ssyrinx			break;
1735210502Ssyrinx		case 200:
1736210502Ssyrinx			*value = IEEE80211_HTCAP_MPDUDENSITY_2;
1737210502Ssyrinx			break;
1738210502Ssyrinx		case 400:
1739210502Ssyrinx			*value = IEEE80211_HTCAP_MPDUDENSITY_4;
1740210502Ssyrinx			break;
1741210502Ssyrinx		case 800:
1742210502Ssyrinx			*value = IEEE80211_HTCAP_MPDUDENSITY_8;
1743210502Ssyrinx			break;
1744210502Ssyrinx		case 1600:
1745210502Ssyrinx			*value = IEEE80211_HTCAP_MPDUDENSITY_16;
1746210502Ssyrinx			break;
1747210502Ssyrinx		default:
1748210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1749210502Ssyrinx		}
1750210502Ssyrinx		break;
1751210502Ssyrinx	case IEEE80211_IOC_AMPDU_LIMIT:
1752210502Ssyrinx		switch (sval) {
1753210502Ssyrinx		case 8192:
1754210502Ssyrinx			*value = IEEE80211_HTCAP_MAXRXAMPDU_8K;
1755210502Ssyrinx			break;
1756210502Ssyrinx		case 16384:
1757210502Ssyrinx			*value = IEEE80211_HTCAP_MAXRXAMPDU_16K;
1758210502Ssyrinx			break;
1759210502Ssyrinx		case 32768:
1760210502Ssyrinx			*value = IEEE80211_HTCAP_MAXRXAMPDU_32K;
1761210502Ssyrinx			break;
1762210502Ssyrinx		case 65536:
1763210502Ssyrinx			*value = IEEE80211_HTCAP_MAXRXAMPDU_64K;
1764210502Ssyrinx			break;
1765210502Ssyrinx		default:
1766210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1767210502Ssyrinx		}
1768210502Ssyrinx		break;
1769210502Ssyrinx	case IEEE80211_IOC_AMSDU:
1770210502Ssyrinx		switch (sval) {
1771210502Ssyrinx		case WlanIfaceDot11nPduType_disabled:
1772210502Ssyrinx			break;
1773210502Ssyrinx		case WlanIfaceDot11nPduType_txOnly:
1774210502Ssyrinx			*value = 1;
1775210502Ssyrinx			break;
1776210502Ssyrinx		case WlanIfaceDot11nPduType_rxOnly:
1777210502Ssyrinx			*value = 2;
1778210502Ssyrinx			break;
1779210502Ssyrinx		case WlanIfaceDot11nPduType_txAndRx:
1780210502Ssyrinx			*value = 3;
1781210502Ssyrinx			break;
1782210502Ssyrinx		default:
1783210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1784210502Ssyrinx		}
1785210502Ssyrinx		break;
1786210502Ssyrinx	case IEEE80211_IOC_AMSDU_LIMIT:
1787210502Ssyrinx		if (sval == 3839 || sval == 0)
1788210502Ssyrinx			*value = IEEE80211_HTCAP_MAXAMSDU_3839;
1789210502Ssyrinx		else if (sval == 7935)
1790210502Ssyrinx			*value = IEEE80211_HTCAP_MAXAMSDU_7935;
1791210502Ssyrinx		else
1792210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1793210502Ssyrinx		break;
1794210502Ssyrinx	case IEEE80211_IOC_HTPROTMODE:
1795210502Ssyrinx		switch (sval) {
1796210502Ssyrinx		case wlanIfaceDot11nHTProtMode_rts:
1797210502Ssyrinx			*value = IEEE80211_PROTMODE_RTSCTS;
1798210502Ssyrinx			break;
1799210502Ssyrinx		case wlanIfaceDot11nHTProtMode_off:
1800210502Ssyrinx			break;
1801210502Ssyrinx		default:
1802210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1803210502Ssyrinx		}
1804210502Ssyrinx		break;
1805210502Ssyrinx	case IEEE80211_IOC_SHORTGI:
1806210502Ssyrinx		if (sval == TruthValue_true)
1807210502Ssyrinx			*value = IEEE80211_HTCAP_SHORTGI20 |
1808210502Ssyrinx			    IEEE80211_HTCAP_SHORTGI40;
1809210502Ssyrinx		else if (sval != TruthValue_false)
1810210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1811210502Ssyrinx		break;
1812210502Ssyrinx	case IEEE80211_IOC_SMPS:
1813210502Ssyrinx		switch (sval) {
1814210502Ssyrinx		case wlanIfaceDot11nSMPSMode_disabled:
1815210502Ssyrinx			*value = IEEE80211_HTCAP_SMPS_OFF;
1816210502Ssyrinx			break;
1817210502Ssyrinx		case wlanIfaceDot11nSMPSMode_static:
1818210502Ssyrinx			*value = IEEE80211_HTCAP_SMPS_ENA;
1819210502Ssyrinx			break;
1820210502Ssyrinx		case wlanIfaceDot11nSMPSMode_dynamic:
1821210502Ssyrinx			*value = IEEE80211_HTCAP_SMPS_DYNAMIC;
1822210502Ssyrinx			break;
1823210502Ssyrinx		default:
1824210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1825210502Ssyrinx		}
1826210502Ssyrinx		break;
1827210502Ssyrinx	case IEEE80211_IOC_TDMA_SLOT:
1828210502Ssyrinx		if (sval < 0 || sval > WLAN_TDMA_MAXSLOTS) /* XXX */
1829210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1830210502Ssyrinx		*value = sval;
1831210502Ssyrinx		break;
1832210502Ssyrinx	case IEEE80211_IOC_TDMA_SLOTCNT:
1833210502Ssyrinx		if (sval < 0 || sval > WLAN_TDMA_MAXSLOTS) /* XXX */
1834210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1835210502Ssyrinx		*value = sval;
1836210502Ssyrinx		break;
1837210502Ssyrinx	case IEEE80211_IOC_TDMA_SLOTLEN:
1838210502Ssyrinx		if (sval < 2*100 || sval > 0xfffff) /* XXX */
1839210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1840210502Ssyrinx		*value = sval;
1841210502Ssyrinx		break;
1842210502Ssyrinx	case IEEE80211_IOC_TDMA_BINTERVAL:
1843210502Ssyrinx		if (sval < 1) /* XXX */
1844210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1845210502Ssyrinx		*value = sval;
1846210502Ssyrinx		break;
1847210502Ssyrinx	default:
1848210502Ssyrinx		return (SNMP_ERR_INCONS_VALUE);
1849210502Ssyrinx	}
1850210502Ssyrinx
1851210502Ssyrinx	return (SNMP_ERR_NOERROR);
1852210502Ssyrinx}
1853210502Ssyrinx
1854210502Ssyrinx/*
1855210502Ssyrinx * Sanity checks for the wlanIfaceConfigTable.
1856210502Ssyrinx */
1857210502Ssyrinxstatic int
1858210502Ssyrinxwlan_config_check(struct wlan_iface *wif, int op)
1859210502Ssyrinx{
1860210502Ssyrinx	switch (op) {
1861210502Ssyrinx	case IEEE80211_IOC_BURST:
1862210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_burst)) == 0) {
1863210502Ssyrinx			wif->packet_burst = TruthValue_false;
1864210502Ssyrinx			return (-1);
1865210502Ssyrinx		}
1866210502Ssyrinx		break;
1867210502Ssyrinx	case IEEE80211_IOC_DFS:
1868210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_dfs)) == 0) {
1869210502Ssyrinx			wif->dyn_frequency = TruthValue_false;
1870210502Ssyrinx			return (-1);
1871210502Ssyrinx		}
1872210502Ssyrinx		break;
1873210502Ssyrinx	case IEEE80211_IOC_FF:
1874210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_athFastFrames))
1875210502Ssyrinx		    == 0) {
1876210502Ssyrinx			wif->fast_frames = TruthValue_false;
1877210502Ssyrinx			return (-1);
1878210502Ssyrinx		}
1879210502Ssyrinx		break;
1880210502Ssyrinx	case IEEE80211_IOC_TURBOP:
1881210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_athTurbo)) == 0) {
1882210502Ssyrinx			wif->dturbo = TruthValue_false;
1883210502Ssyrinx			return (-1);
1884210502Ssyrinx		}
1885210502Ssyrinx		break;
1886210502Ssyrinx	case IEEE80211_IOC_TXPOWER:
1887210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_txPmgt)) == 0) {
1888210502Ssyrinx			wif->tx_power = 0;
1889210502Ssyrinx			return (-1);
1890210502Ssyrinx		}
1891210502Ssyrinx		break;
1892210502Ssyrinx	case IEEE80211_IOC_FRAGTHRESHOLD:
1893210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_txFrag)) == 0) {
1894210502Ssyrinx			wif->frag_threshold = IEEE80211_FRAG_MAX;
1895210502Ssyrinx			return (-1);
1896210502Ssyrinx		}
1897210502Ssyrinx		break;
1898210502Ssyrinx	case IEEE80211_IOC_DWDS:
1899210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_wds)) == 0) {
1900210502Ssyrinx			wif->dynamic_wds = TruthValue_false;
1901210502Ssyrinx			return (-1);
1902210502Ssyrinx		}
1903210502Ssyrinx		break;
1904210502Ssyrinx	case IEEE80211_IOC_POWERSAVE:
1905210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_pmgt)) == 0) {
1906210502Ssyrinx			wif->power_save = TruthValue_false;
1907210502Ssyrinx			return (-1);
1908210502Ssyrinx		}
1909210502Ssyrinx		break;
1910210502Ssyrinx	case IEEE80211_IOC_BEACON_INTERVAL:
1911210502Ssyrinx		if (wif->mode != WlanIfaceOperatingModeType_hostAp &&
1912210502Ssyrinx		    wif->mode != WlanIfaceOperatingModeType_meshPoint &&
1913210502Ssyrinx		    wif->mode != WlanIfaceOperatingModeType_ibss) {
1914210502Ssyrinx			wif->beacon_interval = 100; /* XXX */
1915210502Ssyrinx			return (-1);
1916210502Ssyrinx		}
1917210502Ssyrinx		break;
1918210502Ssyrinx	case IEEE80211_IOC_DTIM_PERIOD:
1919210502Ssyrinx		if (wif->mode != WlanIfaceOperatingModeType_hostAp &&
1920210502Ssyrinx		    wif->mode != WlanIfaceOperatingModeType_meshPoint &&
1921210502Ssyrinx		    wif->mode != WlanIfaceOperatingModeType_ibss) {
1922210502Ssyrinx			wif->dtim_period = 1; /* XXX */
1923210502Ssyrinx			return (-1);
1924210502Ssyrinx		}
1925210502Ssyrinx		break;
1926210502Ssyrinx	case IEEE80211_IOC_PUREN:
1927210502Ssyrinx		if ((wif->htcaps & (0x1 << WlanHTCaps_htcHt)) == 0) {
1928210502Ssyrinx			wif->dot11n_pure = TruthValue_false;
1929210502Ssyrinx			return (-1);
1930210502Ssyrinx		}
1931210502Ssyrinx		break;
1932210502Ssyrinx	case IEEE80211_IOC_AMPDU:
1933210502Ssyrinx		if ((wif->htcaps & (0x1 << WlanHTCaps_htcAmpdu)) == 0) {
1934210502Ssyrinx			wif->ampdu = WlanIfaceDot11nPduType_disabled;
1935210502Ssyrinx			return (-1);
1936210502Ssyrinx		}
1937210502Ssyrinx		break;
1938210502Ssyrinx	case IEEE80211_IOC_AMSDU:
1939210502Ssyrinx		if ((wif->htcaps & (0x1 << WlanHTCaps_htcAmsdu)) == 0) {
1940210502Ssyrinx			wif->amsdu = WlanIfaceDot11nPduType_disabled;
1941210502Ssyrinx			return (-1);
1942210502Ssyrinx		}
1943210502Ssyrinx		break;
1944210502Ssyrinx	case IEEE80211_IOC_RIFS:
1945210502Ssyrinx		if ((wif->htcaps & (0x1 << WlanHTCaps_htcRifs)) == 0) {
1946210502Ssyrinx			wif->rifs = TruthValue_false;
1947210502Ssyrinx			return (-1);
1948210502Ssyrinx		}
1949210502Ssyrinx		break;
1950210502Ssyrinx	case IEEE80211_IOC_SHORTGI:
1951210502Ssyrinx		if ((wif->htcaps & (0x1 << WlanHTCaps_shortGi20 |
1952210502Ssyrinx		    0x1 << WlanHTCaps_shortGi40)) == 0) {
1953210502Ssyrinx			wif->short_gi = TruthValue_false;
1954210502Ssyrinx			return (-1);
1955210502Ssyrinx		}
1956210502Ssyrinx		break;
1957210502Ssyrinx	case IEEE80211_IOC_SMPS:
1958210502Ssyrinx		if ((wif->htcaps & (0x1 << WlanHTCaps_htcSmps)) == 0) {
1959210502Ssyrinx			wif->smps_mode = wlanIfaceDot11nSMPSMode_disabled;
1960210502Ssyrinx			return (-1);
1961210502Ssyrinx		}
1962210502Ssyrinx		break;
1963210502Ssyrinx	case IEEE80211_IOC_TDMA_SLOT:
1964210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {
1965210502Ssyrinx			wif->tdma_slot = 0;
1966210502Ssyrinx			return (-1);
1967210502Ssyrinx		}
1968210502Ssyrinx		break;
1969210502Ssyrinx	case IEEE80211_IOC_TDMA_SLOTCNT:
1970210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {
1971210502Ssyrinx			wif->tdma_slot_count = 0;
1972210502Ssyrinx			return (-1);
1973210502Ssyrinx		}
1974210502Ssyrinx		break;
1975210502Ssyrinx	case IEEE80211_IOC_TDMA_SLOTLEN:
1976210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {
1977210502Ssyrinx			wif->tdma_slot_length = 0;
1978210502Ssyrinx			return (-1);
1979210502Ssyrinx		}
1980210502Ssyrinx		break;
1981210502Ssyrinx	case IEEE80211_IOC_TDMA_BINTERVAL:
1982210502Ssyrinx		if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {
1983210502Ssyrinx			wif->tdma_binterval = 0;
1984210502Ssyrinx			return (-1);
1985210502Ssyrinx		}
1986210502Ssyrinx		break;
1987210502Ssyrinx	default:
1988210502Ssyrinx		break;
1989210502Ssyrinx	}
1990210502Ssyrinx
1991210502Ssyrinx	return (0);
1992210502Ssyrinx}
1993210502Ssyrinx
1994210502Ssyrinxstatic int
1995210502Ssyrinxwlan_config_get_intval(struct wlan_iface *wif, int op)
1996210502Ssyrinx{
1997210502Ssyrinx	int val = 0;
1998210502Ssyrinx	size_t argsize = 0;
1999210502Ssyrinx
2000210502Ssyrinx	if (wlan_config_check(wif, op) < 0)
2001210502Ssyrinx		return (0);
2002210502Ssyrinx	if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 0) < 0)
2003210502Ssyrinx		return (-1);
2004210502Ssyrinx	wlan_config_set_snmp_intval(wif, op, val);
2005210502Ssyrinx
2006210502Ssyrinx	return (0);
2007210502Ssyrinx}
2008210502Ssyrinx
2009210502Ssyrinxstatic int
2010210502Ssyrinxwlan_config_set_intval(struct wlan_iface *wif, int op, int sval)
2011210502Ssyrinx{
2012210502Ssyrinx	size_t argsize = 0;
2013210502Ssyrinx	int val;
2014210502Ssyrinx
2015210502Ssyrinx	if (wlan_config_check(wif, op) < 0)
2016210502Ssyrinx		return (-1);
2017210502Ssyrinx	if (wlan_config_snmp2value(op, sval, &val) != SNMP_ERR_NOERROR)
2018210502Ssyrinx		return (-1);
2019210502Ssyrinx	if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 1) < 0)
2020210502Ssyrinx		return (-1);
2021210502Ssyrinx	wlan_config_set_snmp_intval(wif, op, val);
2022210502Ssyrinx
2023210502Ssyrinx	return (0);
2024210502Ssyrinx}
2025210502Ssyrinx
2026210502Ssyrinxint
2027210502Ssyrinxwlan_config_get_ioctl(struct wlan_iface *wif, int which)
2028210502Ssyrinx{
2029210502Ssyrinx	int op;
2030210502Ssyrinx
2031210502Ssyrinx	switch (which) {
2032210502Ssyrinx		case LEAF_wlanIfaceCountryCode:
2033210502Ssyrinx			/* FALLTHROUGH */
2034210502Ssyrinx		case LEAF_wlanIfaceRegDomain:
2035210502Ssyrinx			return (wlan_config_get_country(wif));
2036210502Ssyrinx		case LEAF_wlanIfaceDesiredSsid:
2037210502Ssyrinx			return (wlan_config_get_dssid(wif));
2038210502Ssyrinx		case LEAF_wlanIfaceDesiredChannel:
2039210502Ssyrinx			return (wlan_config_get_dchannel(wif));
2040210502Ssyrinx		case LEAF_wlanIfaceDesiredBssid:
2041210502Ssyrinx			return (wlan_config_get_bssid(wif));
2042210502Ssyrinx		default:
2043210502Ssyrinx			op = wlan_config_snmp2ioctl(which);
2044210502Ssyrinx			return (wlan_config_get_intval(wif, op));
2045210502Ssyrinx	}
2046210502Ssyrinx
2047210502Ssyrinx	return (-1);
2048210502Ssyrinx}
2049210502Ssyrinx
2050210502Ssyrinxint
2051210502Ssyrinxwlan_config_set_ioctl(struct wlan_iface *wif, int which, int val,
2052210502Ssyrinx    char *strval, int len)
2053210502Ssyrinx{
2054210502Ssyrinx	int op;
2055210502Ssyrinx
2056210502Ssyrinx	switch (which) {
2057210502Ssyrinx		case LEAF_wlanIfaceCountryCode:
2058210502Ssyrinx			return (wlan_config_set_country(wif, strval,
2059210502Ssyrinx			    wif->reg_domain));
2060210502Ssyrinx		case LEAF_wlanIfaceRegDomain:
2061210502Ssyrinx			return (wlan_config_set_country(wif, wif->country_code,
2062210502Ssyrinx			    val));
2063210502Ssyrinx		case LEAF_wlanIfaceDesiredSsid:
2064210502Ssyrinx			return (wlan_config_set_dssid(wif, strval, len));
2065210502Ssyrinx		case LEAF_wlanIfaceDesiredChannel:
2066210502Ssyrinx			return (wlan_config_set_dchannel(wif, val));
2067210502Ssyrinx		case LEAF_wlanIfaceDesiredBssid:
2068210502Ssyrinx			return (wlan_config_set_bssid(wif, strval));
2069210502Ssyrinx		default:
2070210502Ssyrinx			op = wlan_config_snmp2ioctl(which);
2071210502Ssyrinx			return (wlan_config_set_intval(wif, op, val));
2072210502Ssyrinx	}
2073210502Ssyrinx
2074210502Ssyrinx	return (-1);
2075210502Ssyrinx}
2076210502Ssyrinx
2077210502Ssyrinxstatic uint32_t
2078210502Ssyrinxwlan_snmp_to_scan_flags(int flags)
2079210502Ssyrinx{
2080210502Ssyrinx	int sr_flags = 0;
2081210502Ssyrinx
2082210502Ssyrinx	if ((flags & (0x1 << WlanScanFlagsType_noSelection)) != 0)
2083210502Ssyrinx		sr_flags |= IEEE80211_IOC_SCAN_NOPICK;
2084210502Ssyrinx	if ((flags & (0x1 << WlanScanFlagsType_activeScan)) != 0)
2085210502Ssyrinx		sr_flags |= IEEE80211_IOC_SCAN_ACTIVE;
2086210502Ssyrinx	if ((flags & (0x1 << WlanScanFlagsType_pickFirst)) != 0)
2087210502Ssyrinx		sr_flags |= IEEE80211_IOC_SCAN_PICK1ST;
2088210502Ssyrinx	if ((flags & (0x1 << WlanScanFlagsType_backgroundScan)) != 0)
2089210502Ssyrinx		sr_flags |= IEEE80211_IOC_SCAN_BGSCAN;
2090210502Ssyrinx	if ((flags & (0x1 << WlanScanFlagsType_once)) != 0)
2091210502Ssyrinx		sr_flags |= IEEE80211_IOC_SCAN_ONCE;
2092210502Ssyrinx	if ((flags & (0x1 << WlanScanFlagsType_noBroadcast)) != 0)
2093210502Ssyrinx		sr_flags |= IEEE80211_IOC_SCAN_NOBCAST;
2094210502Ssyrinx	if ((flags & (0x1 << WlanScanFlagsType_noAutoSequencing)) != 0)
2095210502Ssyrinx		sr_flags |= IEEE80211_IOC_SCAN_NOJOIN;
2096210502Ssyrinx	if ((flags & (0x1 << WlanScanFlagsType_flushCashe)) != 0)
2097210502Ssyrinx		sr_flags |= IEEE80211_IOC_SCAN_FLUSH;
2098210502Ssyrinx	if ((flags & (0x1 << WlanScanFlagsType_chechCashe)) != 0)
2099210502Ssyrinx		sr_flags |= IEEE80211_IOC_SCAN_CHECK;
2100210502Ssyrinx
2101210502Ssyrinx	return (sr_flags);
2102210502Ssyrinx}
2103210502Ssyrinx
2104210502Ssyrinxint
2105210502Ssyrinxwlan_set_scan_config(struct wlan_iface *wif)
2106210502Ssyrinx{
2107210502Ssyrinx	int val = 0;
2108210502Ssyrinx	size_t argsize;
2109210502Ssyrinx	struct ieee80211_scan_req sr;
2110210502Ssyrinx
2111210502Ssyrinx
2112210502Ssyrinx	memset(&sr, 0, sizeof(sr));
2113210502Ssyrinx	argsize = sizeof(struct ieee80211_scan_req);
2114210502Ssyrinx	sr.sr_flags = wlan_snmp_to_scan_flags(wif->scan_flags);
2115210502Ssyrinx	sr.sr_flags |= IEEE80211_IOC_SCAN_BGSCAN;
2116210502Ssyrinx	sr.sr_duration = wif->scan_duration;
2117210502Ssyrinx	sr.sr_mindwell = wif->scan_mindwell;
2118210502Ssyrinx	sr.sr_maxdwell = wif->scan_maxdwell;
2119210502Ssyrinx	sr.sr_nssid = 0;
2120210502Ssyrinx
2121210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_SCAN_REQ,
2122210502Ssyrinx	    &val, &sr, &argsize, 1) < 0)
2123210502Ssyrinx		return (-1);
2124210502Ssyrinx
2125210502Ssyrinx	wif->scan_status = wlanScanConfigStatus_running;
2126210502Ssyrinx	return (0);
2127210502Ssyrinx}
2128210502Ssyrinx
2129210502Ssyrinxstatic uint32_t
2130210502Ssyrinxwlan_peercaps_to_snmp(uint32_t pcaps)
2131210502Ssyrinx{
2132210502Ssyrinx	uint32_t scaps = 0;
2133210502Ssyrinx
2134210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_ESS) != 0)
2135210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_ess);
2136210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_IBSS) != 0)
2137210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_ibss);
2138210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_CF_POLLABLE) != 0)
2139210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_cfPollable);
2140210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_CF_POLLREQ) != 0)
2141210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_cfPollRequest);
2142210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_PRIVACY) != 0)
2143210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_privacy);
2144210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_SHORT_PREAMBLE) != 0)
2145210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_shortPreamble);
2146210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_PBCC) != 0)
2147210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_pbcc);
2148210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_CHNL_AGILITY) != 0)
2149210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_channelAgility);
2150210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_SHORT_SLOTTIME) != 0)
2151210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_shortSlotTime);
2152210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_RSN) != 0)
2153210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_rsn);
2154210502Ssyrinx	if ((pcaps & IEEE80211_CAPINFO_DSSSOFDM) != 0)
2155210502Ssyrinx		scaps |= (0x1 << WlanPeerCapabilityFlags_dsssofdm);
2156210502Ssyrinx
2157210502Ssyrinx	return (scaps);
2158210502Ssyrinx}
2159210502Ssyrinx
2160210502Ssyrinxstatic int
2161210502Ssyrinxwlan_add_new_scan_result(struct wlan_iface *wif,
2162210502Ssyrinx    const struct ieee80211req_scan_result *isr, uint8_t *ssid)
2163210502Ssyrinx{
2164210502Ssyrinx	struct wlan_scan_result *sr;
2165210502Ssyrinx
2166210502Ssyrinx	if ((sr = wlan_scan_new_result(ssid, isr->isr_bssid)) == NULL)
2167210502Ssyrinx		return (-1);
2168210502Ssyrinx
2169210502Ssyrinx	sr->opchannel = wlan_channel_flags_to_snmp_phy(isr->isr_flags);
2170210502Ssyrinx	sr->rssi = isr->isr_rssi;
2171210502Ssyrinx	sr->frequency = isr->isr_freq;
2172210502Ssyrinx	sr->noise = isr->isr_noise;
2173210502Ssyrinx	sr->bintval = isr->isr_intval;
2174210502Ssyrinx	sr->capinfo = wlan_peercaps_to_snmp(isr->isr_capinfo);
2175210502Ssyrinx
2176210502Ssyrinx	if (wlan_scan_add_result(wif, sr) < 0) {
2177210502Ssyrinx		wlan_scan_free_result(sr);
2178210502Ssyrinx		return (-1);
2179210502Ssyrinx	}
2180210502Ssyrinx
2181210502Ssyrinx	return (0);
2182210502Ssyrinx}
2183210502Ssyrinx
2184210502Ssyrinxint
2185210502Ssyrinxwlan_get_scan_results(struct wlan_iface *wif)
2186210502Ssyrinx{
2187210502Ssyrinx	int ssidlen, val = 0;
2188210502Ssyrinx	uint8_t buf[24 * 1024];
2189210502Ssyrinx	size_t argsize;
2190210502Ssyrinx	const uint8_t *cp, *idp;
2191210502Ssyrinx	uint8_t ssid[IEEE80211_NWID_LEN + 1];
2192210502Ssyrinx	struct ieee80211req_scan_result isr;
2193210502Ssyrinx
2194210502Ssyrinx	argsize = sizeof(buf);
2195210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_SCAN_RESULTS, &val, &buf,
2196210502Ssyrinx	    &argsize, 0) < 0)
2197210502Ssyrinx		return (-1);
2198210502Ssyrinx
2199210502Ssyrinx	if (argsize < sizeof(struct ieee80211req_scan_result))
2200210502Ssyrinx		return (0);
2201210502Ssyrinx
2202210502Ssyrinx	cp = buf;
2203210502Ssyrinx	do {
2204210502Ssyrinx		memcpy(&isr, cp, sizeof(struct ieee80211req_scan_result));
2205210502Ssyrinx		memset(ssid, 0, IEEE80211_NWID_LEN + 1);
2206210502Ssyrinx
2207210502Ssyrinx		if (isr.isr_meshid_len) {
2208210502Ssyrinx			idp = cp + isr.isr_ie_off + isr.isr_ssid_len;
2209210502Ssyrinx			ssidlen = isr.isr_meshid_len;
2210210502Ssyrinx		} else {
2211210502Ssyrinx			idp = cp + isr.isr_ie_off;
2212210502Ssyrinx			ssidlen = isr.isr_ssid_len;
2213210502Ssyrinx		}
2214210502Ssyrinx		if (ssidlen > IEEE80211_NWID_LEN)
2215210502Ssyrinx			ssidlen = IEEE80211_NWID_LEN;
2216210502Ssyrinx		memcpy(ssid, idp, ssidlen);
2217210502Ssyrinx		ssid[IEEE80211_NWID_LEN] = '\0';
2218210502Ssyrinx		(void)wlan_add_new_scan_result(wif, &isr, ssid);
2219210502Ssyrinx		cp += isr.isr_len;
2220210502Ssyrinx		argsize -= isr.isr_len;
2221210502Ssyrinx	} while (argsize >= sizeof(struct ieee80211req_scan_result));
2222210502Ssyrinx
2223210502Ssyrinx	return (0);
2224210502Ssyrinx}
2225210502Ssyrinx
2226210502Ssyrinxint
2227210502Ssyrinxwlan_get_stats(struct wlan_iface *wif)
2228210502Ssyrinx{
2229210502Ssyrinx	struct ifreq ifr;
2230210502Ssyrinx
2231210502Ssyrinx	memset(&ifr, 0, sizeof(struct ifreq));
2232210502Ssyrinx	strlcpy(ifr.ifr_name, wif->wname, IFNAMSIZ);
2233210502Ssyrinx
2234210502Ssyrinx	ifr.ifr_data = (caddr_t) &wif->stats;
2235210502Ssyrinx
2236210502Ssyrinx	if (ioctl(sock, SIOCG80211STATS, &ifr) < 0) {
2237210502Ssyrinx		syslog(LOG_ERR, "iface %s - ioctl(SIOCG80211STATS) failed: %s",
2238210502Ssyrinx		    wif->wname, strerror(errno));
2239210502Ssyrinx		return (-1);
2240210502Ssyrinx	}
2241210502Ssyrinx
2242210502Ssyrinx	return (0);
2243210502Ssyrinx}
2244210502Ssyrinx
2245210502Ssyrinxint
2246210502Ssyrinxwlan_get_wepmode(struct wlan_iface *wif)
2247210502Ssyrinx{
2248210502Ssyrinx	int val = 0;
2249210502Ssyrinx	size_t argsize = 0;
2250210502Ssyrinx
2251210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEP, &val, NULL,
2252210502Ssyrinx	    &argsize, 0) < 0 || val == IEEE80211_WEP_NOSUP) {
2253210502Ssyrinx		wif->wepsupported = 0; /* XXX */
2254210502Ssyrinx		wif->wepmode = wlanWepMode_off;
2255210502Ssyrinx		wif->weptxkey = 0;
2256210502Ssyrinx		return (-1);
2257210502Ssyrinx	}
2258210502Ssyrinx
2259210502Ssyrinx	wif->wepsupported = 1;
2260210502Ssyrinx
2261210502Ssyrinx	switch (val) {
2262210502Ssyrinx	case IEEE80211_WEP_ON:
2263210502Ssyrinx		wif->wepmode = wlanWepMode_on;
2264210502Ssyrinx		break;
2265210502Ssyrinx	case IEEE80211_WEP_MIXED:
2266210502Ssyrinx		wif->wepmode = wlanWepMode_mixed;
2267210502Ssyrinx		break;
2268210502Ssyrinx	case IEEE80211_WEP_OFF:
2269210502Ssyrinx		/* FALLTHROUGH */
2270210502Ssyrinx	default:
2271210502Ssyrinx		wif->wepmode = wlanWepMode_off;
2272210502Ssyrinx		break;
2273210502Ssyrinx	}
2274210502Ssyrinx
2275210502Ssyrinx	return (0);
2276210502Ssyrinx}
2277210502Ssyrinx
2278210502Ssyrinxint
2279210502Ssyrinxwlan_set_wepmode(struct wlan_iface *wif)
2280210502Ssyrinx{
2281210502Ssyrinx	int val;
2282210502Ssyrinx	size_t argsize = 0;
2283210502Ssyrinx
2284210502Ssyrinx	if (!wif->wepsupported)
2285210502Ssyrinx		return (-1);
2286210502Ssyrinx
2287210502Ssyrinx	switch (wif->wepmode) {
2288210502Ssyrinx	case wlanWepMode_off:
2289210502Ssyrinx		val = IEEE80211_WEP_OFF;
2290210502Ssyrinx		break;
2291210502Ssyrinx	case wlanWepMode_on:
2292210502Ssyrinx		val = IEEE80211_WEP_ON;
2293210502Ssyrinx		break;
2294210502Ssyrinx	case wlanWepMode_mixed:
2295210502Ssyrinx		val = IEEE80211_WEP_MIXED;
2296210502Ssyrinx		break;
2297210502Ssyrinx	default:
2298210502Ssyrinx		return (-1);
2299210502Ssyrinx	}
2300210502Ssyrinx
2301210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEP, &val, NULL,
2302210502Ssyrinx	    &argsize, 1) < 0)
2303210502Ssyrinx		return (-1);
2304210502Ssyrinx
2305210502Ssyrinx	return (0);
2306210502Ssyrinx}
2307210502Ssyrinx
2308210502Ssyrinxint
2309210502Ssyrinxwlan_get_weptxkey(struct wlan_iface *wif)
2310210502Ssyrinx{
2311210502Ssyrinx	int val;
2312210502Ssyrinx	size_t argsize = 0;
2313210502Ssyrinx
2314210502Ssyrinx	if (!wif->wepsupported)
2315210502Ssyrinx		return (0);
2316210502Ssyrinx
2317210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEPTXKEY, &val, NULL,
2318210502Ssyrinx	    &argsize, 0) < 0)
2319210502Ssyrinx		return (-1);
2320210502Ssyrinx
2321210502Ssyrinx	if (val == IEEE80211_KEYIX_NONE)
2322210502Ssyrinx		wif->weptxkey = 0;
2323210502Ssyrinx	else
2324210502Ssyrinx		wif->weptxkey = val + 1;
2325210502Ssyrinx
2326210502Ssyrinx	return (0);
2327210502Ssyrinx}
2328210502Ssyrinx
2329210502Ssyrinxint
2330210502Ssyrinxwlan_set_weptxkey(struct wlan_iface *wif)
2331210502Ssyrinx{
2332210502Ssyrinx	int val;
2333210502Ssyrinx	size_t argsize = 0;
2334210502Ssyrinx
2335210502Ssyrinx	if (!wif->wepsupported)
2336210502Ssyrinx		return (0);
2337210502Ssyrinx
2338210502Ssyrinx	if (wif->weptxkey >= IEEE80211_WEP_NKID)
2339210502Ssyrinx		return (-1);
2340210502Ssyrinx
2341210502Ssyrinx	if (wif->weptxkey == 0)
2342210502Ssyrinx		val = IEEE80211_KEYIX_NONE;
2343210502Ssyrinx	else
2344210502Ssyrinx		val = wif->weptxkey - 1;
2345210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEPTXKEY, &val, NULL,
2346210502Ssyrinx	    &argsize, 1) < 0)
2347210502Ssyrinx		return (-1);
2348210502Ssyrinx
2349210502Ssyrinx	return (0);
2350210502Ssyrinx}
2351210502Ssyrinx
2352210502Ssyrinxint
2353210502Ssyrinxwlan_get_wepkeys(struct wlan_iface *wif __unused)
2354210502Ssyrinx{
2355210502Ssyrinx	/* XXX: should they be visible via SNMP */
2356210502Ssyrinx	return (0);
2357210502Ssyrinx}
2358210502Ssyrinx
2359210502Ssyrinxint
2360210502Ssyrinxwlan_set_wepkeys(struct wlan_iface *wif __unused)
2361210502Ssyrinx{
2362210502Ssyrinx	/* XXX: should they be configurable via SNMP */
2363210502Ssyrinx	return (0);
2364210502Ssyrinx}
2365210502Ssyrinx
2366210502Ssyrinxint
2367210502Ssyrinxwlan_get_mac_policy(struct wlan_iface *wif)
2368210502Ssyrinx{
2369210502Ssyrinx	int val = IEEE80211_MACCMD_POLICY;
2370210502Ssyrinx	size_t argsize = 0;
2371210502Ssyrinx	struct ieee80211req ireq;
2372210502Ssyrinx
2373210502Ssyrinx	memset(&ireq, 0, sizeof(struct ieee80211req));
2374210502Ssyrinx	strlcpy(ireq.i_name, wif->wname, IFNAMSIZ);
2375210502Ssyrinx	ireq.i_type = IEEE80211_IOC_MACCMD;
2376210502Ssyrinx	ireq.i_val = IEEE80211_MACCMD_POLICY;
2377210502Ssyrinx
2378210502Ssyrinx	if (ioctl(sock, SIOCG80211, &ireq) < 0) {
2379210502Ssyrinx		if (errno != EINVAL) {
2380210502Ssyrinx			syslog(LOG_ERR, "iface %s - get param: ioctl(%d) "
2381210502Ssyrinx			    "failed: %s", wif->wname, ireq.i_type,
2382210502Ssyrinx			    strerror(errno));
2383210502Ssyrinx			wif->macsupported = 0;
2384210502Ssyrinx			return (-1);
2385210502Ssyrinx		} else {
2386210502Ssyrinx			wif->macsupported = 1;
2387210502Ssyrinx			wif->mac_policy = wlanMACAccessControlPolicy_open;
2388210502Ssyrinx			return (0);
2389210502Ssyrinx		}
2390310901Sngie
2391210502Ssyrinx	}
2392210502Ssyrinx
2393210502Ssyrinx	wif->macsupported = 1;
2394210502Ssyrinx
2395210502Ssyrinx	switch (val) {
2396210502Ssyrinx	case IEEE80211_MACCMD_POLICY_ALLOW:
2397210502Ssyrinx		wif->mac_policy = wlanMACAccessControlPolicy_allow;
2398210502Ssyrinx		break;
2399210502Ssyrinx	case IEEE80211_MACCMD_POLICY_DENY:
2400210502Ssyrinx		wif->mac_policy = wlanMACAccessControlPolicy_deny;
2401210502Ssyrinx		break;
2402210502Ssyrinx	case IEEE80211_MACCMD_POLICY_RADIUS:
2403210502Ssyrinx		wif->mac_policy = wlanMACAccessControlPolicy_radius;
2404210502Ssyrinx		break;
2405210502Ssyrinx	case IEEE80211_MACCMD_POLICY_OPEN:
2406210502Ssyrinx		/* FALLTHROUGH */
2407210502Ssyrinx	default:
2408210502Ssyrinx		wif->mac_policy = wlanMACAccessControlPolicy_open;
2409210502Ssyrinx		break;
2410210502Ssyrinx	}
2411210502Ssyrinx
2412210502Ssyrinx	argsize = 0;
2413210502Ssyrinx	val = IEEE80211_MACCMD_LIST;
2414210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL,
2415210502Ssyrinx	    &argsize, 0) < 0)
2416210502Ssyrinx		return (-1);
2417210502Ssyrinx
2418210502Ssyrinx	wif->mac_nacls = argsize / sizeof(struct ieee80211req_maclist *);
2419210502Ssyrinx	return (0);
2420210502Ssyrinx}
2421210502Ssyrinx
2422210502Ssyrinxint
2423210502Ssyrinxwlan_set_mac_policy(struct wlan_iface *wif)
2424210502Ssyrinx{
2425210502Ssyrinx	int val;
2426210502Ssyrinx	size_t argsize = 0;
2427210502Ssyrinx
2428210502Ssyrinx	if (!wif->macsupported)
2429210502Ssyrinx		return (-1);
2430210502Ssyrinx
2431210502Ssyrinx	switch (wif->mac_policy) {
2432210502Ssyrinx	case wlanMACAccessControlPolicy_allow:
2433210502Ssyrinx		val = IEEE80211_MACCMD_POLICY_ALLOW;
2434210502Ssyrinx		break;
2435210502Ssyrinx	case wlanMACAccessControlPolicy_deny:
2436210502Ssyrinx		val = IEEE80211_MACCMD_POLICY_DENY;
2437210502Ssyrinx		break;
2438210502Ssyrinx	case wlanMACAccessControlPolicy_radius:
2439210502Ssyrinx		val = IEEE80211_MACCMD_POLICY_RADIUS;
2440210502Ssyrinx		break;
2441210502Ssyrinx	case wlanMACAccessControlPolicy_open:
2442210502Ssyrinx		val = IEEE80211_MACCMD_POLICY_OPEN;
2443210502Ssyrinx		break;
2444210502Ssyrinx	default:
2445210502Ssyrinx		return (-1);
2446210502Ssyrinx	}
2447210502Ssyrinx
2448210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL,
2449210502Ssyrinx	    &argsize, 1) < 0)
2450210502Ssyrinx		return (-1);
2451210502Ssyrinx
2452210502Ssyrinx	return (0);
2453210502Ssyrinx}
2454210502Ssyrinx
2455210502Ssyrinxint
2456210502Ssyrinxwlan_flush_mac_mac(struct wlan_iface *wif)
2457210502Ssyrinx{
2458210502Ssyrinx	int val = IEEE80211_MACCMD_FLUSH;
2459210502Ssyrinx	size_t argsize = 0;
2460210502Ssyrinx
2461210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL,
2462210502Ssyrinx	    &argsize, 1) < 0)
2463210502Ssyrinx		return (-1);
2464210502Ssyrinx
2465210502Ssyrinx	return (0);
2466210502Ssyrinx}
2467210502Ssyrinx
2468210502Ssyrinxstatic int
2469210502Ssyrinxwlan_add_mac_macinfo(struct wlan_iface *wif,
2470210502Ssyrinx    const struct ieee80211req_maclist *ml)
2471210502Ssyrinx{
2472210502Ssyrinx	struct wlan_mac_mac *mmac;
2473210502Ssyrinx
2474210502Ssyrinx	if ((mmac = wlan_mac_new_mac(ml->ml_macaddr)) == NULL)
2475210502Ssyrinx		return (-1);
2476210502Ssyrinx
2477210502Ssyrinx	mmac->mac_status = RowStatus_active;
2478210502Ssyrinx	if (wlan_mac_add_mac(wif, mmac) < 0) {
2479210502Ssyrinx		wlan_mac_free_mac(mmac);
2480210502Ssyrinx		return (-1);
2481210502Ssyrinx	}
2482210502Ssyrinx
2483210502Ssyrinx	return (0);
2484210502Ssyrinx}
2485210502Ssyrinx
2486210502Ssyrinxint
2487210502Ssyrinxwlan_get_mac_acl_macs(struct wlan_iface *wif)
2488210502Ssyrinx{
2489210502Ssyrinx	int i, nacls, val = IEEE80211_MACCMD_LIST;
2490210502Ssyrinx	size_t argsize = 0;
2491210502Ssyrinx	uint8_t *data;
2492210502Ssyrinx	struct ieee80211req ireq;
2493210502Ssyrinx	const struct ieee80211req_maclist *acllist;
2494210502Ssyrinx
2495210502Ssyrinx	if (wif->mac_policy == wlanMACAccessControlPolicy_radius) {
2496210502Ssyrinx		wif->mac_nacls = 0;
2497210502Ssyrinx		return (0);
2498210502Ssyrinx	}
2499210502Ssyrinx
2500210502Ssyrinx	memset(&ireq, 0, sizeof(struct ieee80211req));
2501210502Ssyrinx	strlcpy(ireq.i_name, wif->wname, IFNAMSIZ);
2502210502Ssyrinx	ireq.i_type = IEEE80211_IOC_MACCMD;
2503210502Ssyrinx	ireq.i_val = IEEE80211_MACCMD_LIST;
2504210502Ssyrinx
2505210502Ssyrinx
2506210502Ssyrinx	if (ioctl(sock, SIOCG80211, &ireq) < 0) {
2507210502Ssyrinx		if (errno != EINVAL) {
2508210502Ssyrinx			syslog(LOG_ERR, "iface %s - get param: ioctl(%d) "
2509210502Ssyrinx			    "failed: %s", wif->wname, ireq.i_type,
2510210502Ssyrinx			    strerror(errno));
2511210502Ssyrinx			wif->macsupported = 0;
2512210502Ssyrinx			return (-1);
2513210502Ssyrinx		}
2514210502Ssyrinx	}
2515210502Ssyrinx
2516210502Ssyrinx	if (argsize == 0) {
2517210502Ssyrinx		wif->mac_nacls = 0;
2518210502Ssyrinx		return (0);
2519210502Ssyrinx	}
2520210502Ssyrinx
2521210502Ssyrinx	if ((data = (uint8_t *)malloc(argsize)) == NULL)
2522210502Ssyrinx		return (-1);
2523210502Ssyrinx
2524210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, data,
2525210502Ssyrinx	    &argsize, 0) < 0)
2526210502Ssyrinx		return (-1);
2527210502Ssyrinx
2528210502Ssyrinx	nacls = argsize / sizeof(*acllist);
2529210502Ssyrinx	acllist = (struct ieee80211req_maclist *) data;
2530210502Ssyrinx	for (i = 0; i < nacls; i++)
2531210502Ssyrinx		(void)wlan_add_mac_macinfo(wif, acllist + i);
2532210502Ssyrinx
2533210502Ssyrinx	wif->mac_nacls = nacls;
2534210502Ssyrinx	return (0);
2535210502Ssyrinx}
2536210502Ssyrinx
2537210502Ssyrinxint
2538210502Ssyrinxwlan_add_mac_acl_mac(struct wlan_iface *wif, struct wlan_mac_mac *mmac)
2539210502Ssyrinx{
2540210502Ssyrinx	int val = 0;
2541210502Ssyrinx	size_t argsize = IEEE80211_ADDR_LEN;
2542210502Ssyrinx	struct ieee80211req_mlme mlme;
2543210502Ssyrinx
2544210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_ADDMAC, &val,
2545210502Ssyrinx	    mmac->mac, &argsize, 1) < 0)
2546210502Ssyrinx		return (-1);
2547210502Ssyrinx
2548210502Ssyrinx	mmac->mac_status = RowStatus_active;
2549210502Ssyrinx
2550210502Ssyrinx	/* If policy is deny, try to kick the station just in case. */
2551210502Ssyrinx	if (wif->mac_policy != wlanMACAccessControlPolicy_deny)
2552210502Ssyrinx		return (0);
2553210502Ssyrinx
2554210502Ssyrinx	memset(&mlme, 0, sizeof(mlme));
2555210502Ssyrinx	mlme.im_op = IEEE80211_MLME_DEAUTH;
2556210502Ssyrinx	mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE;
2557210502Ssyrinx	memcpy(mlme.im_macaddr, mmac->mac, IEEE80211_ADDR_LEN);
2558210502Ssyrinx	argsize = sizeof(struct ieee80211req_mlme);
2559210502Ssyrinx
2560210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_MLME, &val, &mlme,
2561210502Ssyrinx	    &argsize, 1) < 0 && errno != ENOENT)
2562210502Ssyrinx		return (-1);
2563210502Ssyrinx
2564210502Ssyrinx	return (0);
2565210502Ssyrinx}
2566210502Ssyrinx
2567210502Ssyrinxint
2568210502Ssyrinxwlan_del_mac_acl_mac(struct wlan_iface *wif, struct wlan_mac_mac *mmac)
2569210502Ssyrinx{
2570210502Ssyrinx	int val = 0;
2571210502Ssyrinx	size_t argsize = IEEE80211_ADDR_LEN;
2572210502Ssyrinx	struct ieee80211req_mlme mlme;
2573210502Ssyrinx
2574210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_DELMAC, &val,
2575210502Ssyrinx	    mmac->mac, &argsize, 1) < 0)
2576210502Ssyrinx		return (-1);
2577210502Ssyrinx
2578210502Ssyrinx	mmac->mac_status = RowStatus_active;
2579210502Ssyrinx
2580210502Ssyrinx	/* If policy is allow, try to kick the station just in case. */
2581210502Ssyrinx	if (wif->mac_policy != wlanMACAccessControlPolicy_allow)
2582210502Ssyrinx		return (0);
2583210502Ssyrinx
2584210502Ssyrinx	memset(&mlme, 0, sizeof(mlme));
2585210502Ssyrinx	mlme.im_op = IEEE80211_MLME_DEAUTH;
2586210502Ssyrinx	mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE;
2587210502Ssyrinx	memcpy(mlme.im_macaddr, mmac->mac, IEEE80211_ADDR_LEN);
2588210502Ssyrinx	argsize = sizeof(struct ieee80211req_mlme);
2589210502Ssyrinx
2590210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_MLME, &val, &mlme,
2591210502Ssyrinx	    &argsize, 1) < 0 && errno != ENOENT)
2592210502Ssyrinx		return (-1);
2593210502Ssyrinx
2594210502Ssyrinx	return (0);
2595210502Ssyrinx}
2596210502Ssyrinx
2597210502Ssyrinxint
2598210502Ssyrinxwlan_peer_set_vlan(struct wlan_iface *wif, struct wlan_peer *wip, int vlan)
2599210502Ssyrinx{
2600210502Ssyrinx	int val = 0;
2601210502Ssyrinx	size_t argsize;
2602210502Ssyrinx	struct ieee80211req_sta_vlan vreq;
2603210502Ssyrinx
2604210502Ssyrinx	memcpy(vreq.sv_macaddr, wip->pmac, IEEE80211_ADDR_LEN);
2605210502Ssyrinx	vreq.sv_vlan = vlan;
2606210502Ssyrinx	argsize = sizeof(struct ieee80211req_sta_vlan);
2607210502Ssyrinx
2608210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_STA_VLAN,
2609210502Ssyrinx	    &val, &vreq, &argsize, 1) < 0)
2610210502Ssyrinx		return (-1);
2611210502Ssyrinx
2612210502Ssyrinx	wip->vlan = vlan;
2613210502Ssyrinx
2614210502Ssyrinx	return (0);
2615210502Ssyrinx}
2616210502Ssyrinx
2617210502Ssyrinx/* XXX */
2618210502Ssyrinx#ifndef IEEE80211_NODE_AUTH
2619210502Ssyrinx#define	IEEE80211_NODE_AUTH	0x000001	/* authorized for data */
2620210502Ssyrinx#define	IEEE80211_NODE_QOS	0x000002	/* QoS enabled */
2621210502Ssyrinx#define	IEEE80211_NODE_ERP	0x000004	/* ERP enabled */
2622210502Ssyrinx#define	IEEE80211_NODE_PWR_MGT	0x000010	/* power save mode enabled */
2623210502Ssyrinx#define	IEEE80211_NODE_AREF	0x000020	/* authentication ref held */
2624210502Ssyrinx#define	IEEE80211_NODE_HT	0x000040	/* HT enabled */
2625210502Ssyrinx#define	IEEE80211_NODE_HTCOMPAT	0x000080	/* HT setup w/ vendor OUI's */
2626210502Ssyrinx#define	IEEE80211_NODE_WPS	0x000100	/* WPS association */
2627210502Ssyrinx#define	IEEE80211_NODE_TSN	0x000200	/* TSN association */
2628210502Ssyrinx#define	IEEE80211_NODE_AMPDU_RX	0x000400	/* AMPDU rx enabled */
2629210502Ssyrinx#define	IEEE80211_NODE_AMPDU_TX	0x000800	/* AMPDU tx enabled */
2630210502Ssyrinx#define	IEEE80211_NODE_MIMO_PS	0x001000	/* MIMO power save enabled */
2631210502Ssyrinx#define	IEEE80211_NODE_MIMO_RTS	0x002000	/* send RTS in MIMO PS */
2632210502Ssyrinx#define	IEEE80211_NODE_RIFS	0x004000	/* RIFS enabled */
2633210502Ssyrinx#define	IEEE80211_NODE_SGI20	0x008000	/* Short GI in HT20 enabled */
2634210502Ssyrinx#define	IEEE80211_NODE_SGI40	0x010000	/* Short GI in HT40 enabled */
2635210502Ssyrinx#define	IEEE80211_NODE_ASSOCID	0x020000	/* xmit requires associd */
2636210502Ssyrinx#define	IEEE80211_NODE_AMSDU_RX	0x040000	/* AMSDU rx enabled */
2637210502Ssyrinx#define	IEEE80211_NODE_AMSDU_TX	0x080000	/* AMSDU tx enabled */
2638210502Ssyrinx#endif
2639210502Ssyrinx
2640210502Ssyrinxstatic uint32_t
2641210502Ssyrinxwlan_peerstate_to_snmp(uint32_t pstate)
2642210502Ssyrinx{
2643210502Ssyrinx	uint32_t sstate = 0;
2644210502Ssyrinx
2645210502Ssyrinx	if ((pstate & IEEE80211_NODE_AUTH) != 0)
2646210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_authorizedForData);
2647210502Ssyrinx	if ((pstate & IEEE80211_NODE_QOS) != 0)
2648210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_qosEnabled);
2649210502Ssyrinx	if ((pstate & IEEE80211_NODE_ERP) != 0)
2650210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_erpEnabled);
2651210502Ssyrinx	if ((pstate & IEEE80211_NODE_PWR_MGT) != 0)
2652210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_powerSaveMode);
2653210502Ssyrinx	if ((pstate & IEEE80211_NODE_AREF) != 0)
2654210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_authRefHeld);
2655210502Ssyrinx	if ((pstate & IEEE80211_NODE_HT) != 0)
2656210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_htEnabled);
2657210502Ssyrinx	if ((pstate & IEEE80211_NODE_HTCOMPAT) != 0)
2658210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_htCompat);
2659210502Ssyrinx	if ((pstate & IEEE80211_NODE_WPS) != 0)
2660210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_wpsAssoc);
2661210502Ssyrinx	if ((pstate & IEEE80211_NODE_TSN) != 0)
2662210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_tsnAssoc);
2663210502Ssyrinx	if ((pstate & IEEE80211_NODE_AMPDU_RX) != 0)
2664210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_ampduRx);
2665210502Ssyrinx	if ((pstate & IEEE80211_NODE_AMPDU_TX) != 0)
2666210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_ampduTx);
2667210502Ssyrinx	if ((pstate & IEEE80211_NODE_MIMO_PS) != 0)
2668210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_mimoPowerSave);
2669210502Ssyrinx	if ((pstate & IEEE80211_NODE_MIMO_RTS) != 0)
2670210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_sendRts);
2671210502Ssyrinx	if ((pstate & IEEE80211_NODE_RIFS) != 0)
2672210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_rifs);
2673210502Ssyrinx	if ((pstate & IEEE80211_NODE_SGI20) != 0)
2674210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_shortGiHT20);
2675210502Ssyrinx	if ((pstate & IEEE80211_NODE_SGI40) != 0)
2676210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_shortGiHT40);
2677210502Ssyrinx	if ((pstate & IEEE80211_NODE_AMSDU_RX) != 0)
2678210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_amsduRx);
2679210502Ssyrinx	if ((pstate & IEEE80211_NODE_AMSDU_TX) != 0)
2680210502Ssyrinx		sstate |= (0x1 << WlanIfacePeerFlagsType_amsduTx);
2681210502Ssyrinx
2682210502Ssyrinx	return (sstate);
2683210502Ssyrinx}
2684210502Ssyrinx
2685210502Ssyrinxstatic struct wlan_peer *
2686210502Ssyrinxwlan_add_peerinfo(const struct ieee80211req_sta_info *si)
2687210502Ssyrinx{
2688210502Ssyrinx	struct wlan_peer *wip;
2689210502Ssyrinx
2690210502Ssyrinx	if ((wip = wlan_new_peer(si->isi_macaddr))== NULL)
2691210502Ssyrinx		return (NULL);
2692210502Ssyrinx
2693210502Ssyrinx	wip->associd = IEEE80211_AID(si->isi_associd);
2694210502Ssyrinx	wip->vlan = si->isi_vlan;
2695210502Ssyrinx	wip->frequency =  si->isi_freq;
2696210502Ssyrinx	wip->fflags = si->isi_flags;
2697210502Ssyrinx	wip->txrate = si->isi_txrate;
2698210502Ssyrinx	wip->rssi = si->isi_rssi;
2699210502Ssyrinx	wip->idle = si->isi_inact;
2700210502Ssyrinx	wip->txseqs = si->isi_txseqs[0]; /* XXX */
2701210502Ssyrinx	wip->rxseqs = si->isi_rxseqs[0]; /* XXX */
2702210502Ssyrinx	wip->txpower = si->isi_txpower;
2703210502Ssyrinx	wip->capinfo = wlan_peercaps_to_snmp(si->isi_capinfo);
2704210502Ssyrinx	wip->state = wlan_peerstate_to_snmp(si->isi_state);
2705210502Ssyrinx	wip->local_id = si->isi_localid;
2706210502Ssyrinx	wip->peer_id = si->isi_peerid;
2707210502Ssyrinx
2708210502Ssyrinx	return (wip);
2709210502Ssyrinx}
2710210502Ssyrinx
2711210502Ssyrinxint
2712210502Ssyrinxwlan_get_peerinfo(struct wlan_iface *wif)
2713210502Ssyrinx{
2714210502Ssyrinx	union {
2715210502Ssyrinx		struct ieee80211req_sta_req req;
2716210502Ssyrinx		uint8_t buf[24 * 1024];
2717210502Ssyrinx	} u;
2718210502Ssyrinx	const uint8_t *cp;
2719210502Ssyrinx	int val = 0;
2720210502Ssyrinx	size_t len;
2721210502Ssyrinx	struct ieee80211req_sta_info si;
2722210502Ssyrinx	struct wlan_peer *wip;
2723210502Ssyrinx
2724210502Ssyrinx	/* Get all stations - broadcast address */
2725210502Ssyrinx	(void) memset(u.req.is_u.macaddr, 0xff, IEEE80211_ADDR_LEN);
2726210502Ssyrinx	len =  sizeof(u);
2727210502Ssyrinx
2728210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_STA_INFO,
2729210502Ssyrinx	    & val, &u, &len, 0) < 0)
2730210502Ssyrinx		return (-1);
2731210502Ssyrinx
2732210502Ssyrinx	if (len < sizeof(struct ieee80211req_sta_info))
2733210502Ssyrinx		return (-1);
2734210502Ssyrinx
2735210502Ssyrinx	cp = (const uint8_t *) u.req.info;
2736210502Ssyrinx	do {
2737210502Ssyrinx		memcpy(&si, cp, sizeof(struct ieee80211req_sta_info));
2738210502Ssyrinx		if ((wip = wlan_add_peerinfo(&si)) != NULL &&
2739210502Ssyrinx		    wlan_add_peer(wif, wip) < 0)
2740210502Ssyrinx			wlan_free_peer(wip);
2741210502Ssyrinx		cp += si.isi_len, len -= si.isi_len;
2742210502Ssyrinx	} while (len >= sizeof(struct ieee80211req_sta_info));
2743210502Ssyrinx
2744210502Ssyrinx	return (0);
2745210502Ssyrinx}
2746210502Ssyrinx
2747210502Ssyrinx/************************************************************************
2748210502Ssyrinx * Wireless MESH & HWMP sysctl config.
2749210502Ssyrinx */
2750210502Ssyrinxconst char wlan_sysctl_name[] = "net.wlan.";
2751210502Ssyrinx
2752210502Ssyrinxstatic const char *wlan_sysctl[] = {
2753210502Ssyrinx	"mesh.retrytimeout",
2754210502Ssyrinx	"mesh.holdingtimeout",
2755210502Ssyrinx	"mesh.confirmtimeout",
2756210502Ssyrinx	"mesh.maxretries",
2757210502Ssyrinx	"hwmp.targetonly",
2758210502Ssyrinx	"hwmp.replyforward",
2759210502Ssyrinx	"hwmp.pathlifetime",
2760210502Ssyrinx	"hwmp.roottimeout",
2761210502Ssyrinx	"hwmp.rootint",
2762210502Ssyrinx	"hwmp.rannint",
2763210502Ssyrinx	"hwmp.inact",
2764210502Ssyrinx};
2765210502Ssyrinx
2766210502Ssyrinxint32_t
2767210502Ssyrinxwlan_do_sysctl(struct wlan_config *cfg, enum wlan_syscl which, int set)
2768210502Ssyrinx{
2769210502Ssyrinx	char mib_name[100];
2770210502Ssyrinx	int val, sval;
2771210502Ssyrinx	size_t len, vlen;
2772210502Ssyrinx
2773210502Ssyrinx	if (set) {
2774210502Ssyrinx		vlen = sizeof(sval);
2775210502Ssyrinx		switch (which) {
2776210502Ssyrinx		case WLAN_MESH_RETRY_TO:
2777210502Ssyrinx			sval = cfg->mesh_retryto;
2778210502Ssyrinx			break;
2779210502Ssyrinx		case WLAN_MESH_HOLDING_TO:
2780210502Ssyrinx			sval = cfg->mesh_holdingto;
2781210502Ssyrinx			break;
2782210502Ssyrinx		case WLAN_MESH_CONFIRM_TO:
2783210502Ssyrinx			sval = cfg->mesh_confirmto;
2784210502Ssyrinx			break;
2785210502Ssyrinx		case WLAN_MESH_MAX_RETRIES:
2786210502Ssyrinx			sval = cfg->mesh_maxretries;
2787210502Ssyrinx			break;
2788210502Ssyrinx		case WLAN_HWMP_TARGET_ONLY:
2789210502Ssyrinx			sval = cfg->hwmp_targetonly;
2790210502Ssyrinx			break;
2791210502Ssyrinx		case WLAN_HWMP_REPLY_FORWARD:
2792210502Ssyrinx			sval = cfg->hwmp_replyforward;
2793210502Ssyrinx			break;
2794210502Ssyrinx		case WLAN_HWMP_PATH_LIFETIME:
2795210502Ssyrinx			sval = cfg->hwmp_pathlifetime;
2796210502Ssyrinx			break;
2797210502Ssyrinx		case WLAN_HWMP_ROOT_TO:
2798210502Ssyrinx			sval = cfg->hwmp_roottimeout;
2799210502Ssyrinx			break;
2800210502Ssyrinx		case WLAN_HWMP_ROOT_INT:
2801210502Ssyrinx			sval = cfg->hwmp_rootint;
2802210502Ssyrinx			break;
2803210502Ssyrinx		case WLAN_HWMP_RANN_INT:
2804210502Ssyrinx			sval = cfg->hwmp_rannint;
2805210502Ssyrinx			break;
2806210502Ssyrinx		case WLAN_HWMP_INACTIVITY_TO:
2807210502Ssyrinx			sval = cfg->hwmp_inact;
2808210502Ssyrinx			break;
2809210502Ssyrinx		default:
2810210502Ssyrinx			return (-1);
2811210502Ssyrinx		}
2812210502Ssyrinx	} else {
2813210502Ssyrinx		if (which >= WLAN_SYSCTL_MAX)
2814210502Ssyrinx			return (-1);
2815210502Ssyrinx		vlen = 0;
2816210502Ssyrinx	}
2817210502Ssyrinx
2818210502Ssyrinx	strlcpy(mib_name, wlan_sysctl_name, sizeof(mib_name));
2819210502Ssyrinx	strlcat(mib_name, wlan_sysctl[which], sizeof(mib_name));
2820210502Ssyrinx	len = sizeof (val);
2821210502Ssyrinx
2822210502Ssyrinx	if (sysctlbyname(mib_name, &val, &len, (set? &sval : NULL), vlen) < 0) {
2823210502Ssyrinx		syslog(LOG_ERR, "sysctl(%s) failed - %s", mib_name,
2824210502Ssyrinx		    strerror(errno));
2825210502Ssyrinx		return (-1);
2826210502Ssyrinx	}
2827210502Ssyrinx
2828210502Ssyrinx	switch (which) {
2829210502Ssyrinx	case WLAN_MESH_RETRY_TO:
2830210502Ssyrinx		cfg->mesh_retryto = val;
2831210502Ssyrinx		break;
2832210502Ssyrinx	case WLAN_MESH_HOLDING_TO:
2833210502Ssyrinx		cfg->mesh_holdingto = val;
2834210502Ssyrinx		break;
2835210502Ssyrinx	case WLAN_MESH_CONFIRM_TO:
2836210502Ssyrinx		cfg->mesh_confirmto = val;
2837210502Ssyrinx		break;
2838210502Ssyrinx	case WLAN_MESH_MAX_RETRIES:
2839210502Ssyrinx		cfg->mesh_maxretries = val;
2840210502Ssyrinx		break;
2841210502Ssyrinx	case WLAN_HWMP_TARGET_ONLY:
2842210502Ssyrinx		cfg->hwmp_targetonly = val;
2843210502Ssyrinx		break;
2844210502Ssyrinx	case WLAN_HWMP_REPLY_FORWARD:
2845210502Ssyrinx		cfg->hwmp_replyforward = val;
2846210502Ssyrinx		break;
2847210502Ssyrinx	case WLAN_HWMP_PATH_LIFETIME:
2848210502Ssyrinx		cfg->hwmp_pathlifetime = val;
2849210502Ssyrinx		break;
2850210502Ssyrinx	case WLAN_HWMP_ROOT_TO:
2851210502Ssyrinx		cfg->hwmp_roottimeout = val;
2852210502Ssyrinx		break;
2853210502Ssyrinx	case WLAN_HWMP_ROOT_INT:
2854210502Ssyrinx		cfg->hwmp_rootint = val;
2855210502Ssyrinx		break;
2856210502Ssyrinx	case WLAN_HWMP_RANN_INT:
2857210502Ssyrinx		cfg->hwmp_rannint = val;
2858210502Ssyrinx		break;
2859210502Ssyrinx	case WLAN_HWMP_INACTIVITY_TO:
2860210502Ssyrinx		cfg->hwmp_inact = val;
2861210502Ssyrinx		break;
2862210502Ssyrinx	default:
2863210502Ssyrinx		/* NOTREACHED */
2864210502Ssyrinx		abort();
2865210502Ssyrinx	}
2866210502Ssyrinx
2867210502Ssyrinx	return (0);
2868210502Ssyrinx}
2869210502Ssyrinx
2870210502Ssyrinxint
2871210502Ssyrinxwlan_mesh_config_get(struct wlan_iface *wif, int which)
2872210502Ssyrinx{
2873210502Ssyrinx	int op, val = 0;
2874210502Ssyrinx	size_t argsize = 0;
2875210502Ssyrinx	uint8_t data[32], *pd = NULL;
2876210502Ssyrinx
2877210502Ssyrinx	switch (which) {
2878210502Ssyrinx	case LEAF_wlanMeshTTL:
2879210502Ssyrinx		op = IEEE80211_IOC_MESH_TTL;
2880210502Ssyrinx		break;
2881210502Ssyrinx	case LEAF_wlanMeshPeeringEnabled:
2882210502Ssyrinx		op = IEEE80211_IOC_MESH_AP;
2883210502Ssyrinx		break;
2884210502Ssyrinx	case LEAF_wlanMeshForwardingEnabled:
2885210502Ssyrinx		op = IEEE80211_IOC_MESH_FWRD;
2886210502Ssyrinx		break;
2887210502Ssyrinx	case LEAF_wlanMeshMetric:
2888210502Ssyrinx		op = IEEE80211_IOC_MESH_PR_METRIC;
2889210502Ssyrinx		pd = data;
2890210502Ssyrinx		argsize = sizeof(data);
2891210502Ssyrinx		break;
2892210502Ssyrinx	case LEAF_wlanMeshPath:
2893210502Ssyrinx		op = IEEE80211_IOC_MESH_PR_PATH;
2894210502Ssyrinx		pd = data;
2895210502Ssyrinx		argsize = sizeof(data);
2896210502Ssyrinx		break;
2897210502Ssyrinx	case LEAF_wlanMeshRoutesFlush:
2898210502Ssyrinx		return (0);
2899210502Ssyrinx	default:
2900210502Ssyrinx		return (-1);
2901210502Ssyrinx	}
2902210502Ssyrinx
2903210502Ssyrinx	if (wlan_ioctl(wif->wname, op, &val, pd, &argsize, 0) < 0)
2904210502Ssyrinx		return (-1);
2905210502Ssyrinx
2906210502Ssyrinx	switch (which) {
2907210502Ssyrinx	case LEAF_wlanMeshTTL:
2908210502Ssyrinx		wif->mesh_ttl = val;
2909210502Ssyrinx		break;
2910210502Ssyrinx	case LEAF_wlanMeshPeeringEnabled:
2911210502Ssyrinx		if (val)
2912210502Ssyrinx			wif->mesh_peering = wlanMeshPeeringEnabled_true;
2913210502Ssyrinx		else
2914210502Ssyrinx			wif->mesh_peering = wlanMeshPeeringEnabled_false;
2915210502Ssyrinx		break;
2916210502Ssyrinx	case LEAF_wlanMeshForwardingEnabled:
2917210502Ssyrinx		if (val)
2918210502Ssyrinx			wif->mesh_forwarding = wlanMeshForwardingEnabled_true;
2919210502Ssyrinx		else
2920210502Ssyrinx			wif->mesh_forwarding = wlanMeshForwardingEnabled_false;
2921210502Ssyrinx		break;
2922210502Ssyrinx	case LEAF_wlanMeshMetric:
2923210502Ssyrinx		data[argsize] = '\0';
2924210502Ssyrinx		if (strcmp(data, "AIRTIME") == 0)
2925210502Ssyrinx			wif->mesh_metric = wlanMeshMetric_airtime;
2926210502Ssyrinx		else
2927210502Ssyrinx			wif->mesh_metric = wlanMeshMetric_unknown;
2928210502Ssyrinx		break;
2929210502Ssyrinx	case LEAF_wlanMeshPath:
2930210502Ssyrinx		data[argsize] = '\0';
2931210502Ssyrinx		if (strcmp(data, "HWMP") == 0)
2932210502Ssyrinx			wif->mesh_path = wlanMeshPath_hwmp;
2933210502Ssyrinx		else
2934210502Ssyrinx			wif->mesh_path = wlanMeshPath_unknown;
2935210502Ssyrinx	}
2936210502Ssyrinx
2937210502Ssyrinx	return (0);
2938210502Ssyrinx}
2939210502Ssyrinx
2940210502Ssyrinxint
2941210502Ssyrinxwlan_mesh_config_set(struct wlan_iface *wif, int which)
2942210502Ssyrinx{
2943210502Ssyrinx	int op, val = 0;
2944210502Ssyrinx	size_t argsize = 0;
2945210502Ssyrinx	uint8_t data[32], *pd = NULL;
2946210502Ssyrinx
2947210502Ssyrinx	switch (which) {
2948210502Ssyrinx	case LEAF_wlanMeshTTL:
2949210502Ssyrinx		op = IEEE80211_IOC_MESH_TTL;
2950210502Ssyrinx		val = wif->mesh_ttl;
2951210502Ssyrinx		break;
2952210502Ssyrinx	case LEAF_wlanMeshPeeringEnabled:
2953210502Ssyrinx		op = IEEE80211_IOC_MESH_AP;
2954210502Ssyrinx		if (wif->mesh_peering == wlanMeshPeeringEnabled_true)
2955210502Ssyrinx			val = 1;
2956210502Ssyrinx		break;
2957210502Ssyrinx	case LEAF_wlanMeshForwardingEnabled:
2958210502Ssyrinx		if (wif->mesh_forwarding == wlanMeshForwardingEnabled_true)
2959210502Ssyrinx			val = 1;
2960210502Ssyrinx		op = IEEE80211_IOC_MESH_FWRD;
2961210502Ssyrinx		break;
2962210502Ssyrinx	case LEAF_wlanMeshMetric:
2963210502Ssyrinx		op = IEEE80211_IOC_MESH_PR_METRIC;
2964210502Ssyrinx		if (wif->mesh_metric == wlanMeshMetric_airtime)
2965210502Ssyrinx			strcpy(data, "AIRTIME");
2966210502Ssyrinx		else
2967210502Ssyrinx			return (-1);
2968210502Ssyrinx		pd = data;
2969210502Ssyrinx		argsize = sizeof(data);
2970210502Ssyrinx		break;
2971210502Ssyrinx	case LEAF_wlanMeshPath:
2972210502Ssyrinx		op = IEEE80211_IOC_MESH_PR_PATH;
2973210502Ssyrinx		if (wif->mesh_path == wlanMeshPath_hwmp)
2974210502Ssyrinx			strcpy(data, "HWMP");
2975210502Ssyrinx		else
2976210502Ssyrinx			return (-1);
2977210502Ssyrinx		pd = data;
2978210502Ssyrinx		argsize = sizeof(data);
2979210502Ssyrinx		break;
2980210502Ssyrinx	default:
2981210502Ssyrinx		return (-1);
2982210502Ssyrinx	}
2983210502Ssyrinx
2984210502Ssyrinx	if (wlan_ioctl(wif->wname, op, &val, pd, &argsize, 1) < 0)
2985210502Ssyrinx		return (-1);
2986210502Ssyrinx
2987210502Ssyrinx	return(0);
2988210502Ssyrinx}
2989210502Ssyrinx
2990210502Ssyrinxint
2991210502Ssyrinxwlan_mesh_flush_routes(struct wlan_iface *wif)
2992210502Ssyrinx{
2993210502Ssyrinx	int val = IEEE80211_MESH_RTCMD_FLUSH;
2994210502Ssyrinx	size_t argsize = 0;
2995210502Ssyrinx
2996210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, NULL,
2997210502Ssyrinx	    &argsize, 1) < 0)
2998210502Ssyrinx		return (-1);
2999210502Ssyrinx
3000210502Ssyrinx	return (0);
3001210502Ssyrinx}
3002210502Ssyrinx
3003210502Ssyrinxint
3004210502Ssyrinxwlan_mesh_add_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr)
3005210502Ssyrinx{
3006210502Ssyrinx	int val = IEEE80211_MESH_RTCMD_ADD;
3007210502Ssyrinx	size_t argsize = IEEE80211_ADDR_LEN;
3008210502Ssyrinx
3009210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val,
3010210502Ssyrinx	    wmr->imroute.imr_dest, &argsize, 1) < 0)
3011210502Ssyrinx		return (-1);
3012210502Ssyrinx
3013210502Ssyrinx	wmr->mroute_status = RowStatus_active;
3014210502Ssyrinx
3015210502Ssyrinx	return (0);
3016210502Ssyrinx}
3017210502Ssyrinx
3018210502Ssyrinxint
3019210502Ssyrinxwlan_mesh_del_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr)
3020210502Ssyrinx{
3021210502Ssyrinx	int val = IEEE80211_MESH_RTCMD_DELETE;
3022210502Ssyrinx	size_t argsize = IEEE80211_ADDR_LEN;
3023210502Ssyrinx
3024210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val,
3025210502Ssyrinx	    wmr->imroute.imr_dest, &argsize, 1) < 0)
3026210502Ssyrinx		return (-1);
3027210502Ssyrinx
3028210502Ssyrinx	wmr->mroute_status = RowStatus_destroy;
3029210502Ssyrinx
3030210502Ssyrinx	return (0);
3031210502Ssyrinx}
3032210502Ssyrinx
3033210502Ssyrinxint
3034210502Ssyrinxwlan_mesh_get_routelist(struct wlan_iface *wif)
3035210502Ssyrinx{
3036210502Ssyrinx	int i, nroutes, val = IEEE80211_MESH_RTCMD_LIST;
3037210502Ssyrinx	size_t argsize;
3038210502Ssyrinx	struct ieee80211req_mesh_route routes[128];
3039210502Ssyrinx	struct ieee80211req_mesh_route *rt;
3040210502Ssyrinx	struct wlan_mesh_route *wmr;
3041210502Ssyrinx
3042210502Ssyrinx	argsize = sizeof(routes);
3043210502Ssyrinx	if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, routes,
3044210502Ssyrinx	    &argsize, 0) < 0) /* XXX: ENOMEM? */
3045210502Ssyrinx		return (-1);
3046210502Ssyrinx
3047210502Ssyrinx	nroutes = argsize / sizeof(*rt);
3048210502Ssyrinx	for (i = 0; i < nroutes; i++) {
3049210502Ssyrinx		rt = routes + i;
3050210502Ssyrinx		if ((wmr = wlan_mesh_new_route(rt->imr_dest)) == NULL)
3051210502Ssyrinx			return (-1);
3052210502Ssyrinx		memcpy(&wmr->imroute, rt, sizeof(*rt));
3053210502Ssyrinx		wmr->mroute_status = RowStatus_active;
3054210502Ssyrinx		if (wlan_mesh_add_rtentry(wif, wmr) < 0)
3055210502Ssyrinx			wlan_mesh_free_route(wmr);
3056210502Ssyrinx	}
3057210502Ssyrinx
3058210502Ssyrinx	return (0);
3059210502Ssyrinx}
3060210502Ssyrinx
3061210502Ssyrinxint
3062210502Ssyrinxwlan_hwmp_config_get(struct wlan_iface *wif, int which)
3063210502Ssyrinx{
3064210502Ssyrinx	int op, val = 0;
3065210502Ssyrinx	size_t argsize = 0;
3066210502Ssyrinx
3067210502Ssyrinx	switch (which) {
3068210502Ssyrinx	case LEAF_wlanHWMPRootMode:
3069210502Ssyrinx		op = IEEE80211_IOC_HWMP_ROOTMODE;
3070210502Ssyrinx		break;
3071210502Ssyrinx	case LEAF_wlanHWMPMaxHops:
3072210502Ssyrinx		op = IEEE80211_IOC_HWMP_MAXHOPS;
3073210502Ssyrinx		break;
3074210502Ssyrinx	default:
3075210502Ssyrinx		return (-1);
3076210502Ssyrinx	}
3077210502Ssyrinx
3078210502Ssyrinx	if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 0) < 0)
3079210502Ssyrinx		return (-1);
3080210502Ssyrinx
3081210502Ssyrinx	switch (which) {
3082210502Ssyrinx	case LEAF_wlanHWMPRootMode:
3083210502Ssyrinx		switch (val) {
3084210502Ssyrinx		case IEEE80211_HWMP_ROOTMODE_NORMAL:
3085210502Ssyrinx			wif->hwmp_root_mode = wlanHWMPRootMode_normal;
3086210502Ssyrinx			break;
3087210502Ssyrinx		case IEEE80211_HWMP_ROOTMODE_PROACTIVE:
3088210502Ssyrinx			wif->hwmp_root_mode = wlanHWMPRootMode_proactive;
3089210502Ssyrinx			break;
3090210502Ssyrinx		case IEEE80211_HWMP_ROOTMODE_RANN:
3091210502Ssyrinx			wif->hwmp_root_mode = wlanHWMPRootMode_rann;
3092210502Ssyrinx			break;
3093210502Ssyrinx		case IEEE80211_HWMP_ROOTMODE_DISABLED:
3094210502Ssyrinx		default:
3095210502Ssyrinx			wif->hwmp_root_mode = wlanHWMPRootMode_disabled;
3096210502Ssyrinx			break;
3097210502Ssyrinx		}
3098210502Ssyrinx		break;
3099210502Ssyrinx	case LEAF_wlanHWMPMaxHops:
3100210502Ssyrinx		wif->hwmp_max_hops = val;
3101210502Ssyrinx		break;
3102210502Ssyrinx	}
3103210502Ssyrinx
3104210502Ssyrinx	return (0);
3105210502Ssyrinx}
3106210502Ssyrinx
3107210502Ssyrinxint
3108210502Ssyrinxwlan_hwmp_config_set(struct wlan_iface *wif, int which)
3109210502Ssyrinx{
3110210502Ssyrinx	int op, val = 0;
3111210502Ssyrinx	size_t argsize = 0;
3112210502Ssyrinx
3113210502Ssyrinx	switch (which) {
3114210502Ssyrinx	case LEAF_wlanHWMPRootMode:
3115210502Ssyrinx		op = IEEE80211_IOC_HWMP_ROOTMODE;
3116210502Ssyrinx		switch (wif->hwmp_root_mode) {
3117210502Ssyrinx		case wlanHWMPRootMode_disabled:
3118210502Ssyrinx			val = IEEE80211_HWMP_ROOTMODE_DISABLED;
3119210502Ssyrinx			break;
3120210502Ssyrinx		case wlanHWMPRootMode_normal:
3121210502Ssyrinx			val = IEEE80211_HWMP_ROOTMODE_NORMAL;
3122210502Ssyrinx			break;
3123210502Ssyrinx		case wlanHWMPRootMode_proactive:
3124210502Ssyrinx			val = IEEE80211_HWMP_ROOTMODE_PROACTIVE;
3125210502Ssyrinx			break;
3126210502Ssyrinx		case wlanHWMPRootMode_rann:
3127210502Ssyrinx			val = IEEE80211_HWMP_ROOTMODE_RANN;
3128210502Ssyrinx			break;
3129210502Ssyrinx		default:
3130210502Ssyrinx			return (-1);
3131210502Ssyrinx		}
3132210502Ssyrinx		break;
3133210502Ssyrinx	case LEAF_wlanHWMPMaxHops:
3134210502Ssyrinx		op = IEEE80211_IOC_HWMP_MAXHOPS;
3135210502Ssyrinx		val = wif->hwmp_max_hops;
3136210502Ssyrinx		break;
3137210502Ssyrinx	default:
3138210502Ssyrinx		return (-1);
3139210502Ssyrinx	}
3140210502Ssyrinx
3141210502Ssyrinx	if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 1) < 0)
3142210502Ssyrinx		return (-1);
3143210502Ssyrinx
3144210502Ssyrinx	return (0);
3145210502Ssyrinx}
3146