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