1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2010 The FreeBSD Foundation
5 *
6 * This software was developed by Shteryana Sotirova Shopova under
7 * sponsorship from the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/ioctl.h>
32 #include <sys/param.h>
33 #include <sys/module.h>
34 #include <sys/linker.h>
35 #include <sys/socket.h>
36 #include <sys/sysctl.h>
37
38 #include <net/if.h>
39 #include <net/if_dl.h>
40 #include <net/if_media.h>
41 #include <net/if_mib.h>
42 #include <net/if_types.h>
43 #include <net80211/ieee80211.h>
44 #include <net80211/ieee80211_ioctl.h>
45 #include <net80211/ieee80211_regdomain.h>
46
47 #include <errno.h>
48 #include <ifaddrs.h>
49 #include <stdarg.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <syslog.h>
54
55 #include <bsnmp/snmpmod.h>
56 #include <bsnmp/snmp_mibII.h>
57
58 #define SNMPTREE_TYPES
59 #include "wlan_tree.h"
60 #include "wlan_snmp.h"
61
62 static int sock = -1;
63
64 static int wlan_ioctl(char *, uint16_t, int *, void *, size_t *, int);
65 static int wlan_kmod_load(const char *);
66 static uint32_t wlan_drivercaps_to_snmp(uint32_t);
67 static uint32_t wlan_cryptocaps_to_snmp(uint32_t);
68 static uint32_t wlan_htcaps_to_snmp(uint32_t);
69 static uint32_t wlan_peerstate_to_snmp(uint32_t);
70 static uint32_t wlan_peercaps_to_snmp(uint32_t );
71 static enum WlanIfPhyMode wlan_channel_flags_to_snmp_phy(uint32_t);
72 static enum WlanRegDomainCode wlan_regdomain_to_snmp(int);
73 static uint32_t wlan_snmp_to_scan_flags(int);
74 static int wlan_config_snmp2ioctl(int);
75 static int wlan_snmp_to_regdomain(enum WlanRegDomainCode);
76 static int wlan_config_get_country(struct wlan_iface *);
77 static int wlan_config_set_country(struct wlan_iface *, char *, int);
78 static int wlan_config_get_dchannel(struct wlan_iface *wif);
79 static int wlan_config_set_dchannel(struct wlan_iface *wif, uint32_t);
80 static int wlan_config_get_bssid(struct wlan_iface *);
81 static int wlan_config_set_bssid(struct wlan_iface *, uint8_t *);
82 static void wlan_config_set_snmp_intval(struct wlan_iface *, int, int);
83 static int wlan_config_snmp2value(int, int, int *);
84 static int wlan_config_check(struct wlan_iface *, int);
85 static int wlan_config_get_intval(struct wlan_iface *, int);
86 static int wlan_config_set_intval(struct wlan_iface *, int, int);
87 static int wlan_add_new_scan_result(struct wlan_iface *,
88 const struct ieee80211req_scan_result *, uint8_t *);
89 static int wlan_add_mac_macinfo(struct wlan_iface *,
90 const struct ieee80211req_maclist *);
91 static struct wlan_peer *wlan_add_peerinfo(const struct ieee80211req_sta_info *);
92
93 int
wlan_ioctl_init(void)94 wlan_ioctl_init(void)
95 {
96 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
97 syslog(LOG_ERR, "cannot open socket : %s", strerror(errno));
98 return (-1);
99 }
100
101 return (0);
102 }
103 /*
104 * Load the needed modules in kernel if not already there.
105 */
106 enum wlan_kmodules {
107 WLAN_KMOD = 0,
108 WLAN_KMOD_ACL,
109 WLAN_KMOD_WEP,
110 WLAN_KMODS_MAX
111 };
112
113 static const char *wmod_names[] = {
114 "wlan",
115 "wlan_wlan_acl",
116 "wlan_wep",
117 NULL
118 };
119
120 static int
wlan_kmod_load(const char * modname)121 wlan_kmod_load(const char *modname)
122 {
123 int fileid, modid;
124 struct module_stat mstat;
125
126 mstat.version = sizeof(struct module_stat);
127 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
128 for (modid = kldfirstmod(fileid); modid > 0;
129 modid = modfnext(modid)) {
130 if (modstat(modid, &mstat) < 0)
131 continue;
132 if (strcmp(modname, mstat.name) == 0)
133 return (0);
134 }
135 }
136
137 /* Not present - load it. */
138 if (kldload(modname) < 0) {
139 syslog(LOG_ERR, "failed to load %s kernel module - %s", modname,
140 strerror(errno));
141 return (-1);
142 }
143
144 return (1);
145 }
146
147 int
wlan_kmodules_load(void)148 wlan_kmodules_load(void)
149 {
150 if (wlan_kmod_load(wmod_names[WLAN_KMOD]) < 0)
151 return (-1);
152
153 if (wlan_kmod_load(wmod_names[WLAN_KMOD_ACL]) > 0)
154 syslog(LOG_NOTICE, "SNMP wlan loaded %s module",
155 wmod_names[WLAN_KMOD_ACL]);
156
157 if (wlan_kmod_load(wmod_names[WLAN_KMOD_WEP]) > 0)
158 syslog(LOG_NOTICE, "SNMP wlan loaded %s module",
159 wmod_names[WLAN_KMOD_WEP]);
160
161 return (0);
162 }
163
164 /* XXX: FIXME */
165 static int
wlan_ioctl(char * wif_name,uint16_t req_type,int * val,void * arg,size_t * argsize,int set)166 wlan_ioctl(char *wif_name, uint16_t req_type, int *val, void *arg,
167 size_t *argsize, int set)
168 {
169 struct ieee80211req ireq;
170
171 memset(&ireq, 0, sizeof(struct ieee80211req));
172 strlcpy(ireq.i_name, wif_name, IFNAMSIZ);
173
174 ireq.i_type = req_type;
175 ireq.i_val = *val;
176 ireq.i_len = *argsize;
177 ireq.i_data = arg;
178
179 if (ioctl(sock, set ? SIOCS80211 : SIOCG80211, &ireq) < 0) {
180 syslog(LOG_ERR, "iface %s - %s param: ioctl(%d) "
181 "failed: %s", wif_name, set ? "set" : "get",
182 req_type, strerror(errno));
183 return (-1);
184 }
185
186 *argsize = ireq.i_len;
187 *val = ireq.i_val;
188
189 return (0);
190 }
191
192 int
wlan_check_media(char * ifname)193 wlan_check_media(char *ifname)
194 {
195 struct ifmediareq ifmr;
196
197 memset(&ifmr, 0, sizeof(struct ifmediareq));
198 strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
199
200 if (ioctl(sock, SIOCGIFMEDIA, &ifmr) < 0 || ifmr.ifm_count == 0)
201 return (0); /* Interface doesn't support SIOCGIFMEDIA. */
202
203 if ((ifmr.ifm_status & IFM_AVALID) == 0)
204 return (0);
205
206 return (IFM_TYPE(ifmr.ifm_active));
207 }
208
209 int
wlan_get_opmode(struct wlan_iface * wif)210 wlan_get_opmode(struct wlan_iface *wif)
211 {
212 struct ifmediareq ifmr;
213
214 memset(&ifmr, 0, sizeof(struct ifmediareq));
215 strlcpy(ifmr.ifm_name, wif->wname, sizeof(ifmr.ifm_name));
216
217 if (ioctl(sock, SIOCGIFMEDIA, &ifmr) < 0) {
218 if (errno == ENXIO)
219 return (-1);
220 wif->mode = WlanIfaceOperatingModeType_station;
221 return (0);
222 }
223
224 if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
225 if (ifmr.ifm_current & IFM_FLAG0)
226 wif->mode = WlanIfaceOperatingModeType_adhocDemo;
227 else
228 wif->mode = WlanIfaceOperatingModeType_ibss;
229 } else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
230 wif->mode = WlanIfaceOperatingModeType_hostAp;
231 else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
232 wif->mode = WlanIfaceOperatingModeType_monitor;
233 else if (ifmr.ifm_current & IFM_IEEE80211_MBSS)
234 wif->mode = WlanIfaceOperatingModeType_meshPoint;
235 else if (ifmr.ifm_current & IFM_IEEE80211_WDS)
236 wif->mode = WlanIfaceOperatingModeType_wds;
237
238 return (0);
239 }
240
241 int
wlan_config_state(struct wlan_iface * wif,uint8_t set)242 wlan_config_state(struct wlan_iface *wif, uint8_t set)
243 {
244 int flags;
245 struct ifreq ifr;
246
247 memset(&ifr, 0, sizeof(ifr));
248 strcpy(ifr.ifr_name, wif->wname);
249
250 if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
251 syslog(LOG_ERR, "set %s status: ioctl(SIOCGIFFLAGS) "
252 "failed: %s", wif->wname, strerror(errno));
253 return (-1);
254 }
255
256 if (set == 0) {
257 if ((ifr.ifr_flags & IFF_UP) != 0)
258 wif->state = wlanIfaceState_up;
259 else
260 wif->state = wlanIfaceState_down;
261 return (0);
262 }
263
264 flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
265
266 if (wif->state == wlanIfaceState_up)
267 flags |= IFF_UP;
268 else
269 flags &= ~IFF_UP;
270
271 ifr.ifr_flags = flags & 0xffff;
272 ifr.ifr_flagshigh = flags >> 16;
273 if (ioctl(sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
274 syslog(LOG_ERR, "set %s %s: ioctl(SIOCSIFFLAGS) failed: %s",
275 wif->wname, wif->state == wlanIfaceState_up?"up":"down",
276 strerror(errno));
277 return (-1);
278 }
279
280 return (0);
281 }
282
283 int
wlan_get_local_addr(struct wlan_iface * wif)284 wlan_get_local_addr(struct wlan_iface *wif)
285 {
286 int len;
287 char ifname[IFNAMSIZ];
288 struct ifaddrs *ifap, *ifa;
289 struct sockaddr_dl sdl;
290
291 if (getifaddrs(&ifap) != 0) {
292 syslog(LOG_ERR, "wlan get mac: getifaddrs() failed - %s",
293 strerror(errno));
294 return (-1);
295 }
296
297 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
298 if (ifa->ifa_addr->sa_family != AF_LINK)
299 continue;
300 memcpy(&sdl, ifa->ifa_addr, sizeof(struct sockaddr_dl));
301 if (sdl.sdl_alen > IEEE80211_ADDR_LEN)
302 continue;
303 if ((len = sdl.sdl_nlen) >= IFNAMSIZ)
304 len = IFNAMSIZ - 1;
305 memcpy(ifname, sdl.sdl_data, len);
306 ifname[len] = '\0';
307 if (strcmp(wif->wname, ifname) == 0)
308 break;
309 }
310
311 freeifaddrs(ifap);
312 return (0);
313 }
314
315 int
wlan_get_parent(struct wlan_iface * wif __unused)316 wlan_get_parent(struct wlan_iface *wif __unused)
317 {
318 /* XXX: There's no way to fetch this from the kernel. */
319 return (0);
320 }
321
322 /* XXX */
323 #define IEEE80211_C_STA 0x00000001 /* CAPABILITY: STA available */
324 #define IEEE80211_C_8023ENCAP 0x00000002 /* CAPABILITY: 802.3 encap */
325 #define IEEE80211_C_FF 0x00000040 /* CAPABILITY: ATH FF avail */
326 #define IEEE80211_C_TURBOP 0x00000080 /* CAPABILITY: ATH Turbo avail*/
327 #define IEEE80211_C_IBSS 0x00000100 /* CAPABILITY: IBSS available */
328 #define IEEE80211_C_PMGT 0x00000200 /* CAPABILITY: Power mgmt */
329 #define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */
330 #define IEEE80211_C_AHDEMO 0x00000800 /* CAPABILITY: Old Adhoc Demo */
331 #define IEEE80211_C_SWRETRY 0x00001000 /* CAPABILITY: sw tx retry */
332 #define IEEE80211_C_TXPMGT 0x00002000 /* CAPABILITY: tx power mgmt */
333 #define IEEE80211_C_SHSLOT 0x00004000 /* CAPABILITY: short slottime */
334 #define IEEE80211_C_SHPREAMBLE 0x00008000 /* CAPABILITY: short preamble */
335 #define IEEE80211_C_MONITOR 0x00010000 /* CAPABILITY: monitor mode */
336 #define IEEE80211_C_DFS 0x00020000 /* CAPABILITY: DFS/radar avail*/
337 #define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */
338 /* 0x7c0000 available */
339 #define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */
340 #define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */
341 #define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/
342 #define IEEE80211_C_BURST 0x02000000 /* CAPABILITY: frame bursting */
343 #define IEEE80211_C_WME 0x04000000 /* CAPABILITY: WME avail */
344 #define IEEE80211_C_WDS 0x08000000 /* CAPABILITY: 4-addr support */
345 /* 0x10000000 reserved */
346 #define IEEE80211_C_BGSCAN 0x20000000 /* CAPABILITY: bg scanning */
347 #define IEEE80211_C_TXFRAG 0x40000000 /* CAPABILITY: tx fragments */
348 #define IEEE80211_C_TDMA 0x80000000 /* CAPABILITY: TDMA avail */
349
350 static uint32_t
wlan_drivercaps_to_snmp(uint32_t dcaps)351 wlan_drivercaps_to_snmp(uint32_t dcaps)
352 {
353 uint32_t scaps = 0;
354
355 if ((dcaps & IEEE80211_C_STA) != 0)
356 scaps |= (0x1 << WlanDriverCaps_station);
357 if ((dcaps & IEEE80211_C_8023ENCAP) != 0)
358 scaps |= (0x1 << WlanDriverCaps_ieee8023encap);
359 if ((dcaps & IEEE80211_C_FF) != 0)
360 scaps |= (0x1 << WlanDriverCaps_athFastFrames);
361 if ((dcaps & IEEE80211_C_TURBOP) != 0)
362 scaps |= (0x1 << WlanDriverCaps_athTurbo);
363 if ((dcaps & IEEE80211_C_IBSS) != 0)
364 scaps |= (0x1 << WlanDriverCaps_ibss);
365 if ((dcaps & IEEE80211_C_PMGT) != 0)
366 scaps |= (0x1 << WlanDriverCaps_pmgt);
367 if ((dcaps & IEEE80211_C_HOSTAP) != 0)
368 scaps |= (0x1 << WlanDriverCaps_hostAp);
369 if ((dcaps & IEEE80211_C_AHDEMO) != 0)
370 scaps |= (0x1 << WlanDriverCaps_ahDemo);
371 if ((dcaps & IEEE80211_C_SWRETRY) != 0)
372 scaps |= (0x1 << WlanDriverCaps_swRetry);
373 if ((dcaps & IEEE80211_C_TXPMGT) != 0)
374 scaps |= (0x1 << WlanDriverCaps_txPmgt);
375 if ((dcaps & IEEE80211_C_SHSLOT) != 0)
376 scaps |= (0x1 << WlanDriverCaps_shortSlot);
377 if ((dcaps & IEEE80211_C_SHPREAMBLE) != 0)
378 scaps |= (0x1 << WlanDriverCaps_shortPreamble);
379 if ((dcaps & IEEE80211_C_MONITOR) != 0)
380 scaps |= (0x1 << WlanDriverCaps_monitor);
381 if ((dcaps & IEEE80211_C_DFS) != 0)
382 scaps |= (0x1 << WlanDriverCaps_dfs);
383 if ((dcaps & IEEE80211_C_MBSS) != 0)
384 scaps |= (0x1 << WlanDriverCaps_mbss);
385 if ((dcaps & IEEE80211_C_WPA1) != 0)
386 scaps |= (0x1 << WlanDriverCaps_wpa1);
387 if ((dcaps & IEEE80211_C_WPA2) != 0)
388 scaps |= (0x1 << WlanDriverCaps_wpa2);
389 if ((dcaps & IEEE80211_C_BURST) != 0)
390 scaps |= (0x1 << WlanDriverCaps_burst);
391 if ((dcaps & IEEE80211_C_WME) != 0)
392 scaps |= (0x1 << WlanDriverCaps_wme);
393 if ((dcaps & IEEE80211_C_WDS) != 0)
394 scaps |= (0x1 << WlanDriverCaps_wds);
395 if ((dcaps & IEEE80211_C_BGSCAN) != 0)
396 scaps |= (0x1 << WlanDriverCaps_bgScan);
397 if ((dcaps & IEEE80211_C_TXFRAG) != 0)
398 scaps |= (0x1 << WlanDriverCaps_txFrag);
399 if ((dcaps & IEEE80211_C_TDMA) != 0)
400 scaps |= (0x1 << WlanDriverCaps_tdma);
401
402 return (scaps);
403 }
404
405 static uint32_t
wlan_cryptocaps_to_snmp(uint32_t ccaps)406 wlan_cryptocaps_to_snmp(uint32_t ccaps)
407 {
408 uint32_t scaps = 0;
409
410 #if NOT_YET
411 if ((ccaps & IEEE80211_CRYPTO_WEP) != 0)
412 scaps |= (0x1 << wlanCryptoCaps_wep);
413 if ((ccaps & IEEE80211_CRYPTO_TKIP) != 0)
414 scaps |= (0x1 << wlanCryptoCaps_tkip);
415 if ((ccaps & IEEE80211_CRYPTO_AES_OCB) != 0)
416 scaps |= (0x1 << wlanCryptoCaps_aes);
417 if ((ccaps & IEEE80211_CRYPTO_AES_CCM) != 0)
418 scaps |= (0x1 << wlanCryptoCaps_aesCcm);
419 if ((ccaps & IEEE80211_CRYPTO_TKIPMIC) != 0)
420 scaps |= (0x1 << wlanCryptoCaps_tkipMic);
421 if ((ccaps & IEEE80211_CRYPTO_CKIP) != 0)
422 scaps |= (0x1 << wlanCryptoCaps_ckip);
423 #else /* !NOT_YET */
424 scaps = ccaps;
425 #endif
426 return (scaps);
427 }
428
429 #define IEEE80211_HTC_AMPDU 0x00010000 /* CAPABILITY: A-MPDU tx */
430 #define IEEE80211_HTC_AMSDU 0x00020000 /* CAPABILITY: A-MSDU tx */
431 /* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */
432 #define IEEE80211_HTC_HT 0x00040000 /* CAPABILITY: HT operation */
433 #define IEEE80211_HTC_SMPS 0x00080000 /* CAPABILITY: MIMO power save*/
434 #define IEEE80211_HTC_RIFS 0x00100000 /* CAPABILITY: RIFS support */
435
436 static uint32_t
wlan_htcaps_to_snmp(uint32_t hcaps)437 wlan_htcaps_to_snmp(uint32_t hcaps)
438 {
439 uint32_t scaps = 0;
440
441 if ((hcaps & IEEE80211_HTCAP_LDPC) != 0)
442 scaps |= (0x1 << WlanHTCaps_ldpc);
443 if ((hcaps & IEEE80211_HTCAP_CHWIDTH40) != 0)
444 scaps |= (0x1 << WlanHTCaps_chwidth40);
445 if ((hcaps & IEEE80211_HTCAP_GREENFIELD) != 0)
446 scaps |= (0x1 << WlanHTCaps_greenField);
447 if ((hcaps & IEEE80211_HTCAP_SHORTGI20) != 0)
448 scaps |= (0x1 << WlanHTCaps_shortGi20);
449 if ((hcaps & IEEE80211_HTCAP_SHORTGI40) != 0)
450 scaps |= (0x1 << WlanHTCaps_shortGi40);
451 if ((hcaps & IEEE80211_HTCAP_TXSTBC) != 0)
452 scaps |= (0x1 << WlanHTCaps_txStbc);
453 if ((hcaps & IEEE80211_HTCAP_DELBA) != 0)
454 scaps |= (0x1 << WlanHTCaps_delba);
455 if ((hcaps & IEEE80211_HTCAP_MAXAMSDU_7935) != 0)
456 scaps |= (0x1 << WlanHTCaps_amsdu7935);
457 if ((hcaps & IEEE80211_HTCAP_DSSSCCK40) != 0)
458 scaps |= (0x1 << WlanHTCaps_dssscck40);
459 if ((hcaps & IEEE80211_HTCAP_PSMP) != 0)
460 scaps |= (0x1 << WlanHTCaps_psmp);
461 if ((hcaps & IEEE80211_HTCAP_40INTOLERANT) != 0)
462 scaps |= (0x1 << WlanHTCaps_fortyMHzIntolerant);
463 if ((hcaps & IEEE80211_HTCAP_LSIGTXOPPROT) != 0)
464 scaps |= (0x1 << WlanHTCaps_lsigTxOpProt);
465 if ((hcaps & IEEE80211_HTC_AMPDU) != 0)
466 scaps |= (0x1 << WlanHTCaps_htcAmpdu);
467 if ((hcaps & IEEE80211_HTC_AMSDU) != 0)
468 scaps |= (0x1 << WlanHTCaps_htcAmsdu);
469 if ((hcaps & IEEE80211_HTC_HT) != 0)
470 scaps |= (0x1 << WlanHTCaps_htcHt);
471 if ((hcaps & IEEE80211_HTC_SMPS) != 0)
472 scaps |= (0x1 << WlanHTCaps_htcSmps);
473 if ((hcaps & IEEE80211_HTC_RIFS) != 0)
474 scaps |= (0x1 << WlanHTCaps_htcRifs);
475
476 return (scaps);
477 }
478
479 /* XXX: Not here? */
480 #define WLAN_SET_TDMA_OPMODE(w) do { \
481 if ((w)->mode == WlanIfaceOperatingModeType_adhocDemo && \
482 ((w)->drivercaps & WlanDriverCaps_tdma) != 0) \
483 (w)->mode = WlanIfaceOperatingModeType_tdma; \
484 } while (0)
485 int
wlan_get_driver_caps(struct wlan_iface * wif)486 wlan_get_driver_caps(struct wlan_iface *wif)
487 {
488 int val = 0;
489 size_t argsize;
490 struct ieee80211_devcaps_req dc;
491
492 memset(&dc, 0, sizeof(struct ieee80211_devcaps_req));
493 argsize = sizeof(struct ieee80211_devcaps_req);
494
495 if (wlan_ioctl(wif->wname, IEEE80211_IOC_DEVCAPS, &val, &dc,
496 &argsize, 0) < 0)
497 return (-1);
498
499 wif->drivercaps = wlan_drivercaps_to_snmp(dc.dc_drivercaps);
500 wif->cryptocaps = wlan_cryptocaps_to_snmp(dc.dc_cryptocaps);
501 wif->htcaps = wlan_htcaps_to_snmp(dc.dc_htcaps);
502
503 WLAN_SET_TDMA_OPMODE(wif);
504
505 argsize = dc.dc_chaninfo.ic_nchans * sizeof(struct ieee80211_channel);
506 wif->chanlist = (struct ieee80211_channel *)malloc(argsize);
507 if (wif->chanlist == NULL)
508 return (0);
509
510 memcpy(wif->chanlist, dc.dc_chaninfo.ic_chans, argsize);
511 wif->nchannels = dc.dc_chaninfo.ic_nchans;
512
513 return (0);
514 }
515
516 uint8_t
wlan_channel_state_to_snmp(uint8_t cstate)517 wlan_channel_state_to_snmp(uint8_t cstate)
518 {
519 uint8_t cs = 0;
520
521 if ((cstate & IEEE80211_CHANSTATE_RADAR) != 0)
522 cs |= (0x1 << WlanIfaceChannelStateType_radar);
523 if ((cstate & IEEE80211_CHANSTATE_CACDONE) != 0)
524 cs |= (0x1 << WlanIfaceChannelStateType_cacDone);
525 if ((cstate & IEEE80211_CHANSTATE_CWINT) != 0)
526 cs |= (0x1 << WlanIfaceChannelStateType_interferenceDetected);
527 if ((cstate & IEEE80211_CHANSTATE_NORADAR) != 0)
528 cs |= (0x1 << WlanIfaceChannelStateType_radarClear);
529
530 return (cs);
531 }
532
533 uint32_t
wlan_channel_flags_to_snmp(uint32_t cflags)534 wlan_channel_flags_to_snmp(uint32_t cflags)
535 {
536 uint32_t cf = 0;
537
538 if ((cflags & IEEE80211_CHAN_TURBO) != 0)
539 cf |= (0x1 << WlanIfaceChannelFlagsType_turbo);
540 if ((cflags & IEEE80211_CHAN_CCK) != 0)
541 cf |= (0x1 << WlanIfaceChannelFlagsType_cck);
542 if ((cflags & IEEE80211_CHAN_OFDM) != 0)
543 cf |= (0x1 << WlanIfaceChannelFlagsType_ofdm);
544 if ((cflags & IEEE80211_CHAN_2GHZ) != 0)
545 cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum2Ghz);
546 if ((cflags & IEEE80211_CHAN_5GHZ) != 0)
547 cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum5Ghz);
548 if ((cflags & IEEE80211_CHAN_PASSIVE) != 0)
549 cf |= (0x1 << WlanIfaceChannelFlagsType_passiveScan);
550 if ((cflags & IEEE80211_CHAN_DYN) != 0)
551 cf |= (0x1 << WlanIfaceChannelFlagsType_dynamicCckOfdm);
552 if ((cflags & IEEE80211_CHAN_GFSK) != 0)
553 cf |= (0x1 << WlanIfaceChannelFlagsType_gfsk);
554 if ((cflags & IEEE80211_CHAN_GSM) != 0)
555 cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum900Mhz);
556 if ((cflags & IEEE80211_CHAN_STURBO) != 0)
557 cf |= (0x1 << WlanIfaceChannelFlagsType_dot11aStaticTurbo);
558 if ((cflags & IEEE80211_CHAN_HALF) != 0)
559 cf |= (0x1 << WlanIfaceChannelFlagsType_halfRate);
560 if ((cflags & IEEE80211_CHAN_QUARTER) != 0)
561 cf |= (0x1 << WlanIfaceChannelFlagsType_quarterRate);
562 if ((cflags & IEEE80211_CHAN_HT20) != 0)
563 cf |= (0x1 << WlanIfaceChannelFlagsType_ht20);
564 if ((cflags & IEEE80211_CHAN_HT40U) != 0)
565 cf |= (0x1 << WlanIfaceChannelFlagsType_ht40u);
566 if ((cflags & IEEE80211_CHAN_HT40D) != 0)
567 cf |= (0x1 << WlanIfaceChannelFlagsType_ht40d);
568 if ((cflags & IEEE80211_CHAN_DFS) != 0)
569 cf |= (0x1 << WlanIfaceChannelFlagsType_dfs);
570 if ((cflags & IEEE80211_CHAN_4MSXMIT) != 0)
571 cf |= (0x1 << WlanIfaceChannelFlagsType_xmit4ms);
572 if ((cflags & IEEE80211_CHAN_NOADHOC) != 0)
573 cf |= (0x1 << WlanIfaceChannelFlagsType_noAdhoc);
574 if ((cflags & IEEE80211_CHAN_NOHOSTAP) != 0)
575 cf |= (0x1 << WlanIfaceChannelFlagsType_noHostAp);
576 if ((cflags & IEEE80211_CHAN_11D) != 0)
577 cf |= (0x1 << WlanIfaceChannelFlagsType_dot11d);
578
579 return (cf);
580 }
581
582 /* XXX: */
583 #define WLAN_SNMP_MAX_CHANS 256
584 int
wlan_get_channel_list(struct wlan_iface * wif)585 wlan_get_channel_list(struct wlan_iface *wif)
586 {
587 int val = 0;
588 uint32_t i, nchans;
589 size_t argsize;
590 struct ieee80211req_chaninfo *chaninfo;
591 struct ieee80211req_chanlist active;
592 const struct ieee80211_channel *c;
593
594 argsize = sizeof(struct ieee80211req_chaninfo) +
595 sizeof(struct ieee80211_channel) * WLAN_SNMP_MAX_CHANS;
596 chaninfo = (struct ieee80211req_chaninfo *)malloc(argsize);
597 if (chaninfo == NULL)
598 return (-1);
599
600 if (wlan_ioctl(wif->wname, IEEE80211_IOC_CHANINFO, &val, chaninfo,
601 &argsize, 0) < 0)
602 return (-1);
603
604 argsize = sizeof(active);
605 if (wlan_ioctl(wif->wname, IEEE80211_IOC_CHANLIST, &val, &active,
606 &argsize, 0) < 0)
607 goto error;
608
609 for (i = 0, nchans = 0; i < chaninfo->ic_nchans; i++) {
610 c = &chaninfo->ic_chans[i];
611 if (!isset(active.ic_channels, c->ic_ieee))
612 continue;
613 nchans++;
614 }
615 wif->chanlist = (struct ieee80211_channel *)reallocf(wif->chanlist,
616 nchans * sizeof(*c));
617 if (wif->chanlist == NULL)
618 goto error;
619 wif->nchannels = nchans;
620 for (i = 0, nchans = 0; i < chaninfo->ic_nchans; i++) {
621 c = &chaninfo->ic_chans[i];
622 if (!isset(active.ic_channels, c->ic_ieee))
623 continue;
624 memcpy(wif->chanlist + nchans, c, sizeof (*c));
625 nchans++;
626 }
627
628 free(chaninfo);
629 return (0);
630 error:
631 wif->nchannels = 0;
632 free(chaninfo);
633 return (-1);
634 }
635
636 static enum WlanIfPhyMode
wlan_channel_flags_to_snmp_phy(uint32_t cflags)637 wlan_channel_flags_to_snmp_phy(uint32_t cflags)
638 {
639 /* XXX: recheck */
640 if ((cflags & IEEE80211_CHAN_A) != 0)
641 return (WlanIfPhyMode_dot11a);
642 if ((cflags & IEEE80211_CHAN_B) != 0)
643 return (WlanIfPhyMode_dot11b);
644 if ((cflags & IEEE80211_CHAN_G) != 0 ||
645 (cflags & IEEE80211_CHAN_PUREG) != 0)
646 return (WlanIfPhyMode_dot11g);
647 if ((cflags & IEEE80211_CHAN_FHSS) != 0)
648 return (WlanIfPhyMode_fh);
649 if ((cflags & IEEE80211_CHAN_TURBO) != 0 &&
650 (cflags & IEEE80211_CHAN_A) != 0)
651 return (WlanIfPhyMode_turboA);
652 if ((cflags & IEEE80211_CHAN_TURBO) != 0 &&
653 (cflags & IEEE80211_CHAN_G) != 0)
654 return (WlanIfPhyMode_turboG);
655 if ((cflags & IEEE80211_CHAN_STURBO) != 0)
656 return (WlanIfPhyMode_sturboA);
657 if ((cflags & IEEE80211_CHAN_HALF) != 0)
658 return (WlanIfPhyMode_ofdmHalf);
659 if ((cflags & IEEE80211_CHAN_QUARTER) != 0)
660 return (WlanIfPhyMode_ofdmQuarter);
661
662 return (WlanIfPhyMode_auto);
663 }
664
665 int
wlan_get_roam_params(struct wlan_iface * wif)666 wlan_get_roam_params(struct wlan_iface *wif)
667 {
668 int val = 0;
669 size_t argsize;
670
671 argsize = sizeof(struct ieee80211_roamparams_req);
672 if (wlan_ioctl(wif->wname, IEEE80211_IOC_ROAM, &val,
673 &wif->roamparams, &argsize, 0) < 0)
674 return (-1);
675
676 return (0);
677 }
678
679 int
wlan_get_tx_params(struct wlan_iface * wif)680 wlan_get_tx_params(struct wlan_iface *wif)
681 {
682 int val = 0;
683 size_t argsize;
684
685 /*
686 * XXX: Reset IEEE80211_RATE_MCS bit on IEEE80211_MODE_11NA
687 * and IEEE80211_MODE_11NG modes.
688 */
689 argsize = sizeof(struct ieee80211_txparams_req);
690 if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPARAMS, &val,
691 &wif->txparams, &argsize, 0) < 0)
692 return (-1);
693
694 return (0);
695 }
696
697 int
wlan_set_tx_params(struct wlan_iface * wif,int32_t pmode __unused)698 wlan_set_tx_params(struct wlan_iface *wif, int32_t pmode __unused)
699 {
700 int val = 0;
701 size_t argsize;
702
703 /*
704 * XXX: Set IEEE80211_RATE_MCS bit on IEEE80211_MODE_11NA
705 * and IEEE80211_MODE_11NG modes.
706 */
707 argsize = sizeof(struct ieee80211_txparams_req);
708 if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPARAMS, &val,
709 &wif->txparams, &argsize, 1) < 0)
710 return (-1);
711
712 return (0);
713 }
714
715 int
wlan_clone_create(struct wlan_iface * wif)716 wlan_clone_create(struct wlan_iface *wif)
717 {
718 struct ifreq ifr;
719 struct ieee80211_clone_params wcp;
720 static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
721
722 memset(&wcp, 0, sizeof(wcp));
723 memset(&ifr, 0, sizeof(ifr));
724
725 /* Sanity checks. */
726 if (wif == NULL || wif->pname[0] == '\0' || wif->mode > WLAN_IFMODE_MAX)
727 return (SNMP_ERR_INCONS_VALUE);
728
729 if (wif->mode == WlanIfaceOperatingModeType_wds &&
730 memcmp(wif->dbssid, zerobssid, IEEE80211_ADDR_LEN) == 0)
731 return (SNMP_ERR_INCONS_VALUE);
732
733 strlcpy(wcp.icp_parent, wif->pname, IFNAMSIZ);
734 if ((wif->flags & WlanIfaceFlagsType_uniqueBssid) != 0)
735 wcp.icp_flags |= IEEE80211_CLONE_BSSID;
736 if ((wif->flags & WlanIfaceFlagsType_noBeacons) != 0)
737 wcp.icp_flags |= IEEE80211_CLONE_NOBEACONS;
738 if (wif->mode == WlanIfaceOperatingModeType_wds &&
739 (wif->flags & WlanIfaceFlagsType_wdsLegacy) != 0)
740 wcp.icp_flags |= IEEE80211_CLONE_WDSLEGACY;
741
742 switch (wif->mode) {
743 case WlanIfaceOperatingModeType_ibss:
744 wcp.icp_opmode = IEEE80211_M_IBSS;
745 break;
746 case WlanIfaceOperatingModeType_station:
747 wcp.icp_opmode = IEEE80211_M_STA;
748 break;
749 case WlanIfaceOperatingModeType_wds:
750 wcp.icp_opmode = IEEE80211_M_WDS;
751 break;
752 case WlanIfaceOperatingModeType_adhocDemo:
753 wcp.icp_opmode = IEEE80211_M_AHDEMO;
754 break;
755 case WlanIfaceOperatingModeType_hostAp:
756 wcp.icp_opmode = IEEE80211_M_HOSTAP;
757 break;
758 case WlanIfaceOperatingModeType_monitor:
759 wcp.icp_opmode = IEEE80211_M_MONITOR;
760 break;
761 case WlanIfaceOperatingModeType_meshPoint:
762 wcp.icp_opmode = IEEE80211_M_MBSS;
763 break;
764 case WlanIfaceOperatingModeType_tdma:
765 wcp.icp_opmode = IEEE80211_M_AHDEMO;
766 wcp.icp_flags |= IEEE80211_CLONE_TDMA;
767 break;
768 }
769
770 memcpy(wcp.icp_bssid, wif->dbssid, IEEE80211_ADDR_LEN);
771 if (memcmp(wif->dlmac, zerobssid, IEEE80211_ADDR_LEN) != 0) {
772 memcpy(wcp.icp_macaddr, wif->dlmac, IEEE80211_ADDR_LEN);
773 wcp.icp_flags |= IEEE80211_CLONE_MACADDR;
774 }
775
776 strlcpy(ifr.ifr_name, wif->wname, IFNAMSIZ);
777 ifr.ifr_data = (caddr_t) &wcp;
778
779 if (ioctl(sock, SIOCIFCREATE2, (caddr_t) &ifr) < 0) {
780 syslog(LOG_ERR, "wlan clone create: ioctl(SIOCIFCREATE2) "
781 "failed: %s", strerror(errno));
782 return (SNMP_ERR_GENERR);
783 }
784
785 return (SNMP_ERR_NOERROR);
786 }
787
788 int
wlan_clone_destroy(struct wlan_iface * wif)789 wlan_clone_destroy(struct wlan_iface *wif)
790 {
791 struct ifreq ifr;
792
793 if (wif == NULL)
794 return (SNMP_ERR_INCONS_VALUE);
795
796 memset(&ifr, 0, sizeof(ifr));
797 strcpy(ifr.ifr_name, wif->wname);
798
799 if (ioctl(sock, SIOCIFDESTROY, &ifr) < 0) {
800 syslog(LOG_ERR, "wlan clone destroy: ioctl(SIOCIFDESTROY) "
801 "failed: %s", strerror(errno));
802 return (SNMP_ERR_GENERR);
803 }
804
805 return (SNMP_ERR_NOERROR);
806 }
807
808 static int
wlan_config_snmp2ioctl(int which)809 wlan_config_snmp2ioctl(int which)
810 {
811 int op;
812
813 switch (which) {
814 case LEAF_wlanIfacePacketBurst:
815 op = IEEE80211_IOC_BURST;
816 break;
817 case LEAF_wlanIfaceCountryCode:
818 op = IEEE80211_IOC_REGDOMAIN;
819 break;
820 case LEAF_wlanIfaceRegDomain:
821 op = IEEE80211_IOC_REGDOMAIN;
822 break;
823 case LEAF_wlanIfaceDesiredSsid:
824 op = IEEE80211_IOC_SSID;
825 break;
826 case LEAF_wlanIfaceDesiredChannel:
827 op = IEEE80211_IOC_CURCHAN;
828 break;
829 case LEAF_wlanIfaceDynamicFreqSelection:
830 op = IEEE80211_IOC_DFS;
831 break;
832 case LEAF_wlanIfaceFastFrames:
833 op = IEEE80211_IOC_FF;
834 break;
835 case LEAF_wlanIfaceDturbo:
836 op = IEEE80211_IOC_TURBOP;
837 break;
838 case LEAF_wlanIfaceTxPower:
839 op = IEEE80211_IOC_TXPOWER;
840 break;
841 case LEAF_wlanIfaceFragmentThreshold:
842 op = IEEE80211_IOC_FRAGTHRESHOLD;
843 break;
844 case LEAF_wlanIfaceRTSThreshold:
845 op = IEEE80211_IOC_RTSTHRESHOLD;
846 break;
847 case LEAF_wlanIfaceWlanPrivacySubscribe:
848 op = IEEE80211_IOC_WPS;
849 break;
850 case LEAF_wlanIfaceBgScan:
851 op = IEEE80211_IOC_BGSCAN;
852 break;
853 case LEAF_wlanIfaceBgScanIdle:
854 op = IEEE80211_IOC_BGSCAN_IDLE;
855 break;
856 case LEAF_wlanIfaceBgScanInterval:
857 op = IEEE80211_IOC_BGSCAN_INTERVAL;
858 break;
859 case LEAF_wlanIfaceBeaconMissedThreshold:
860 op = IEEE80211_IOC_BMISSTHRESHOLD;
861 break;
862 case LEAF_wlanIfaceDesiredBssid:
863 op = IEEE80211_IOC_BSSID;
864 break;
865 case LEAF_wlanIfaceRoamingMode:
866 op = IEEE80211_IOC_ROAMING;
867 break;
868 case LEAF_wlanIfaceDot11d:
869 op = IEEE80211_IOC_DOTD;
870 break;
871 case LEAF_wlanIfaceDot11h:
872 op = IEEE80211_IOC_DOTH;
873 break;
874 case LEAF_wlanIfaceDynamicWds:
875 op = IEEE80211_IOC_DWDS;
876 break;
877 case LEAF_wlanIfacePowerSave:
878 op = IEEE80211_IOC_POWERSAVE;
879 break;
880 case LEAF_wlanIfaceApBridge:
881 op = IEEE80211_IOC_APBRIDGE;
882 break;
883 case LEAF_wlanIfaceBeaconInterval:
884 op = IEEE80211_IOC_BEACON_INTERVAL;
885 break;
886 case LEAF_wlanIfaceDtimPeriod:
887 op = IEEE80211_IOC_DTIM_PERIOD;
888 break;
889 case LEAF_wlanIfaceHideSsid:
890 op = IEEE80211_IOC_HIDESSID;
891 break;
892 case LEAF_wlanIfaceInactivityProccess:
893 op = IEEE80211_IOC_INACTIVITY;
894 break;
895 case LEAF_wlanIfaceDot11gProtMode:
896 op = IEEE80211_IOC_PROTMODE;
897 break;
898 case LEAF_wlanIfaceDot11gPureMode:
899 op = IEEE80211_IOC_PUREG;
900 break;
901 case LEAF_wlanIfaceDot11nPureMode:
902 op = IEEE80211_IOC_PUREN;
903 break;
904 case LEAF_wlanIfaceDot11nAmpdu:
905 op = IEEE80211_IOC_AMPDU;
906 break;
907 case LEAF_wlanIfaceDot11nAmpduDensity:
908 op = IEEE80211_IOC_AMPDU_DENSITY;
909 break;
910 case LEAF_wlanIfaceDot11nAmpduLimit:
911 op = IEEE80211_IOC_AMPDU_LIMIT;
912 break;
913 case LEAF_wlanIfaceDot11nAmsdu:
914 op = IEEE80211_IOC_AMSDU;
915 break;
916 case LEAF_wlanIfaceDot11nAmsduLimit:
917 op = IEEE80211_IOC_AMSDU_LIMIT;
918 break;
919 case LEAF_wlanIfaceDot11nHighThroughput:
920 op = IEEE80211_IOC_HTCONF;
921 break;
922 case LEAF_wlanIfaceDot11nHTCompatible:
923 op = IEEE80211_IOC_HTCOMPAT;
924 break;
925 case LEAF_wlanIfaceDot11nHTProtMode:
926 op = IEEE80211_IOC_HTPROTMODE;
927 break;
928 case LEAF_wlanIfaceDot11nRIFS:
929 op = IEEE80211_IOC_RIFS;
930 break;
931 case LEAF_wlanIfaceDot11nShortGI:
932 op = IEEE80211_IOC_SHORTGI;
933 break;
934 case LEAF_wlanIfaceDot11nSMPSMode:
935 op = IEEE80211_IOC_SMPS;
936 break;
937 case LEAF_wlanIfaceTdmaSlot:
938 op = IEEE80211_IOC_TDMA_SLOT;
939 break;
940 case LEAF_wlanIfaceTdmaSlotCount:
941 op = IEEE80211_IOC_TDMA_SLOTCNT;
942 break;
943 case LEAF_wlanIfaceTdmaSlotLength:
944 op = IEEE80211_IOC_TDMA_SLOTLEN;
945 break;
946 case LEAF_wlanIfaceTdmaBeaconInterval:
947 op = IEEE80211_IOC_TDMA_BINTERVAL;
948 break;
949 default:
950 op = -1;
951 }
952
953 return (op);
954 }
955
956 static enum WlanRegDomainCode
wlan_regdomain_to_snmp(int which)957 wlan_regdomain_to_snmp(int which)
958 {
959 enum WlanRegDomainCode reg_domain;
960
961 switch (which) {
962 case SKU_FCC:
963 reg_domain = WlanRegDomainCode_fcc;
964 break;
965 case SKU_CA:
966 reg_domain = WlanRegDomainCode_ca;
967 break;
968 case SKU_ETSI:
969 reg_domain = WlanRegDomainCode_etsi;
970 break;
971 case SKU_ETSI2:
972 reg_domain = WlanRegDomainCode_etsi2;
973 break;
974 case SKU_ETSI3:
975 reg_domain = WlanRegDomainCode_etsi3;
976 break;
977 case SKU_FCC3:
978 reg_domain = WlanRegDomainCode_fcc3;
979 break;
980 case SKU_JAPAN:
981 reg_domain = WlanRegDomainCode_japan;
982 break;
983 case SKU_KOREA:
984 reg_domain = WlanRegDomainCode_korea;
985 break;
986 case SKU_APAC:
987 reg_domain = WlanRegDomainCode_apac;
988 break;
989 case SKU_APAC2:
990 reg_domain = WlanRegDomainCode_apac2;
991 break;
992 case SKU_APAC3:
993 reg_domain = WlanRegDomainCode_apac3;
994 break;
995 case SKU_ROW:
996 reg_domain = WlanRegDomainCode_row;
997 break;
998 case SKU_NONE:
999 reg_domain = WlanRegDomainCode_none;
1000 break;
1001 case SKU_DEBUG:
1002 reg_domain = WlanRegDomainCode_debug;
1003 break;
1004 case SKU_SR9:
1005 reg_domain = WlanRegDomainCode_sr9;
1006 break;
1007 case SKU_XR9:
1008 reg_domain = WlanRegDomainCode_xr9;
1009 break;
1010 case SKU_GZ901:
1011 reg_domain = WlanRegDomainCode_gz901;
1012 break;
1013 case 0:
1014 reg_domain = WlanRegDomainCode_none;
1015 break;
1016 default:
1017 syslog(LOG_ERR, "unknown regdomain (0x%x) ", which);
1018 reg_domain = WlanRegDomainCode_none;
1019 break;
1020 }
1021
1022 return (reg_domain);
1023 }
1024
1025 static int
wlan_snmp_to_regdomain(enum WlanRegDomainCode regdomain)1026 wlan_snmp_to_regdomain(enum WlanRegDomainCode regdomain)
1027 {
1028 int which;
1029
1030 switch (regdomain) {
1031 case WlanRegDomainCode_fcc:
1032 which = SKU_FCC;
1033 break;
1034 case WlanRegDomainCode_ca:
1035 which = SKU_CA;
1036 break;
1037 case WlanRegDomainCode_etsi:
1038 which = SKU_ETSI;
1039 break;
1040 case WlanRegDomainCode_etsi2:
1041 which = SKU_ETSI2;
1042 break;
1043 case WlanRegDomainCode_etsi3:
1044 which = SKU_ETSI3;
1045 break;
1046 case WlanRegDomainCode_fcc3:
1047 which = SKU_FCC3;
1048 break;
1049 case WlanRegDomainCode_japan:
1050 which = SKU_JAPAN;
1051 break;
1052 case WlanRegDomainCode_korea:
1053 which = SKU_KOREA;
1054 break;
1055 case WlanRegDomainCode_apac:
1056 which = SKU_APAC;
1057 break;
1058 case WlanRegDomainCode_apac2:
1059 which = SKU_APAC2;
1060 break;
1061 case WlanRegDomainCode_apac3:
1062 which = SKU_APAC3;
1063 break;
1064 case WlanRegDomainCode_row:
1065 which = SKU_ROW;
1066 break;
1067 case WlanRegDomainCode_none:
1068 which = SKU_NONE;
1069 break;
1070 case WlanRegDomainCode_debug:
1071 which = SKU_DEBUG;
1072 break;
1073 case WlanRegDomainCode_sr9:
1074 which = SKU_SR9;
1075 break;
1076 case WlanRegDomainCode_xr9:
1077 which = SKU_XR9;
1078 break;
1079 case WlanRegDomainCode_gz901:
1080 which = SKU_GZ901;
1081 break;
1082 default:
1083 syslog(LOG_ERR, "unknown snmp regdomain (0x%x) ", regdomain);
1084 which = SKU_NONE;
1085 break;
1086 }
1087
1088 return (which);
1089 }
1090
1091 static int
wlan_config_get_country(struct wlan_iface * wif)1092 wlan_config_get_country(struct wlan_iface *wif)
1093 {
1094 int val = 0;
1095 size_t argsize;
1096 struct ieee80211_regdomain regdomain;
1097
1098 memset(®domain, 0, sizeof(regdomain));
1099 argsize = sizeof(regdomain);
1100
1101 if (wlan_ioctl(wif->wname, IEEE80211_IOC_REGDOMAIN, &val, ®domain,
1102 &argsize, 0) < 0)
1103 return (-1);
1104
1105 wif->reg_domain = wlan_regdomain_to_snmp(regdomain.regdomain);
1106 wif->country_code[0] = regdomain.isocc[0];
1107 wif->country_code[1] = regdomain.isocc[1];
1108 wif->country_code[2] = regdomain.location;
1109
1110 return (0);
1111 }
1112
1113 static int
wlan_config_set_country(struct wlan_iface * wif,char * ccode,int rdomain)1114 wlan_config_set_country(struct wlan_iface *wif, char *ccode, int rdomain)
1115 {
1116 int val = 0, txpowermax;
1117 uint32_t i;
1118 size_t argsize = 0;
1119 struct ieee80211_regdomain_req *regdomain;
1120
1121 if (wlan_get_channel_list(wif) < 0)
1122 return (-1);
1123
1124 if (wif->nchannels == 0) {
1125 syslog(LOG_ERR, "iface %s - set regdomain failed", wif->wname);
1126 return (-1);
1127 }
1128
1129 if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPOWMAX, &txpowermax, 0,
1130 &argsize, 0) < 0)
1131 return (-1);
1132
1133 regdomain = malloc(IEEE80211_REGDOMAIN_SIZE(wif->nchannels));
1134 if (regdomain == NULL)
1135 return (-1);
1136 memset(regdomain, 0, IEEE80211_REGDOMAIN_SIZE(wif->nchannels));
1137 argsize = IEEE80211_REGDOMAIN_SIZE(wif->nchannels);
1138
1139 /* XXX: recheck with how this is done by ifconfig(8) */
1140 regdomain->rd.regdomain = wlan_snmp_to_regdomain(rdomain);
1141 regdomain->rd.isocc[0] = ccode[0];
1142 regdomain->rd.isocc[1] = ccode[1];
1143 regdomain->rd.location = ccode[2];
1144
1145 /* XXX: fill the channel list properly */
1146 regdomain->chaninfo.ic_nchans = wif->nchannels;
1147 memcpy(regdomain->chaninfo.ic_chans, wif->chanlist,
1148 wif->nchannels * sizeof(struct ieee80211_channel));
1149 for (i = 0; i < wif->nchannels; i++)
1150 regdomain->chaninfo.ic_chans[i].ic_maxregpower = txpowermax;
1151
1152 wif->state = wlanIfaceState_down;
1153 if (wlan_config_state(wif, 1) < 0 ||
1154 wlan_ioctl(wif->wname, IEEE80211_IOC_REGDOMAIN, &val, regdomain,
1155 &argsize, 1) < 0) {
1156 free(regdomain);
1157 return (-1);
1158 }
1159
1160 wif->state = wlanIfaceState_up;
1161 (void)wlan_config_state(wif, 1);
1162 wif->reg_domain = wlan_regdomain_to_snmp(regdomain->rd.regdomain);
1163 wif->country_code[0] = regdomain->rd.isocc[0];
1164 wif->country_code[1] = regdomain->rd.isocc[1];
1165 wif->country_code[2] = regdomain->rd.location;
1166 free(regdomain);
1167
1168 return (0);
1169 }
1170
1171 int
wlan_config_get_dssid(struct wlan_iface * wif)1172 wlan_config_get_dssid(struct wlan_iface *wif)
1173 {
1174 int val = -1;
1175 size_t argsize = IEEE80211_NWID_LEN + 1;
1176 char ssid[IEEE80211_NWID_LEN + 1];
1177
1178 memset(ssid, 0, IEEE80211_NWID_LEN + 1);
1179
1180 if (wlan_ioctl(wif->wname,
1181 (wif->mode == WlanIfaceOperatingModeType_meshPoint) ?
1182 IEEE80211_IOC_MESH_ID : IEEE80211_IOC_SSID, &val, ssid,
1183 &argsize, 0) < 0)
1184 return (-1);
1185
1186 if (argsize > IEEE80211_NWID_LEN)
1187 argsize = IEEE80211_NWID_LEN;
1188 memcpy(wif->desired_ssid, ssid, argsize);
1189 wif->desired_ssid[argsize] = '\0';
1190
1191 return (0);
1192 }
1193
1194 int
wlan_config_set_dssid(struct wlan_iface * wif,char * ssid,int slen)1195 wlan_config_set_dssid(struct wlan_iface *wif, char *ssid, int slen)
1196 {
1197 int val = 0;
1198 size_t argsize = slen;
1199
1200 if (wlan_ioctl(wif->wname,
1201 (wif->mode == WlanIfaceOperatingModeType_meshPoint) ?
1202 IEEE80211_IOC_MESH_ID : IEEE80211_IOC_SSID, &val, ssid,
1203 &argsize, 1) < 0)
1204 return (-1);
1205
1206 if (argsize > IEEE80211_NWID_LEN)
1207 argsize = IEEE80211_NWID_LEN;
1208 memcpy(wif->desired_ssid, ssid, argsize);
1209 wif->desired_ssid[argsize] = '\0';
1210
1211 return (0);
1212 }
1213
1214 static int
wlan_config_get_dchannel(struct wlan_iface * wif)1215 wlan_config_get_dchannel(struct wlan_iface *wif)
1216 {
1217 uint32_t i = 0;
1218 int val = 0;
1219 size_t argsize = sizeof(struct ieee80211_channel);
1220 struct ieee80211_channel chan;
1221
1222 if (wlan_get_channel_list(wif) < 0)
1223 return (-1);
1224
1225 memset(&chan, 0, sizeof(chan));
1226 if (wlan_ioctl(wif->wname, IEEE80211_IOC_CURCHAN, &val, &chan,
1227 &argsize, 0) < 0)
1228 return (-1);
1229
1230 for (i = 0; i < wif->nchannels; i++)
1231 if (chan.ic_ieee == wif->chanlist[i].ic_ieee &&
1232 chan.ic_flags == wif->chanlist[i].ic_flags) {
1233 wif->desired_channel = i + 1;
1234 break;
1235 }
1236
1237 return (0);
1238 }
1239
1240 static int
wlan_config_set_dchannel(struct wlan_iface * wif,uint32_t dchannel)1241 wlan_config_set_dchannel(struct wlan_iface *wif, uint32_t dchannel)
1242 {
1243 int val = 0;
1244 size_t argsize = sizeof(struct ieee80211_channel);
1245 struct ieee80211_channel chan;
1246
1247 if (wlan_get_channel_list(wif) < 0)
1248 return (-1);
1249
1250 if (dchannel > wif->nchannels)
1251 return (-1);
1252
1253 memcpy(&chan, wif->chanlist + dchannel - 1, sizeof(chan));
1254 if (wlan_ioctl(wif->wname, IEEE80211_IOC_CURCHAN, &val, &chan,
1255 &argsize, 1) < 0)
1256 return (-1);
1257
1258 wif->desired_channel = dchannel;
1259
1260 return (0);
1261 }
1262
1263 static int
wlan_config_get_bssid(struct wlan_iface * wif)1264 wlan_config_get_bssid(struct wlan_iface *wif)
1265 {
1266 int val = 0;
1267 size_t argsize = IEEE80211_ADDR_LEN;
1268 char bssid[IEEE80211_ADDR_LEN];
1269
1270 memset(bssid, 0, IEEE80211_ADDR_LEN);
1271
1272 if (wlan_ioctl(wif->wname, IEEE80211_IOC_BSSID, &val, bssid,
1273 &argsize, 0) < 0 || argsize != IEEE80211_ADDR_LEN)
1274 return (-1);
1275
1276 memcpy(wif->desired_bssid, bssid, IEEE80211_ADDR_LEN);
1277
1278 return (0);
1279 }
1280
1281 static int
wlan_config_set_bssid(struct wlan_iface * wif,uint8_t * bssid)1282 wlan_config_set_bssid(struct wlan_iface *wif, uint8_t *bssid)
1283 {
1284 int val = 0;
1285 size_t argsize = IEEE80211_ADDR_LEN;
1286
1287 if (wlan_ioctl(wif->wname, IEEE80211_IOC_BSSID, &val, bssid,
1288 &argsize, 1) < 0 || argsize != IEEE80211_ADDR_LEN)
1289 return (-1);
1290
1291 memcpy(wif->desired_bssid, bssid, IEEE80211_ADDR_LEN);
1292
1293 return (0);
1294 }
1295
1296 /*
1297 * Convert the value returned by the kernel to the appropriate SNMP
1298 * representation and set the corresponding interface member accordingly.
1299 */
1300 static void
wlan_config_set_snmp_intval(struct wlan_iface * wif,int op,int val)1301 wlan_config_set_snmp_intval(struct wlan_iface *wif, int op, int val)
1302 {
1303 switch (op) {
1304 case IEEE80211_IOC_BURST:
1305 if (val == 0)
1306 wif->packet_burst = TruthValue_false;
1307 else
1308 wif->packet_burst = TruthValue_true;
1309 break;
1310 case IEEE80211_IOC_DFS:
1311 if (val == 0)
1312 wif->dyn_frequency = TruthValue_false;
1313 else
1314 wif->dyn_frequency = TruthValue_true;
1315 break;
1316 case IEEE80211_IOC_FF:
1317 if (val == 0)
1318 wif->fast_frames = TruthValue_false;
1319 else
1320 wif->fast_frames = TruthValue_true;
1321 break;
1322 case IEEE80211_IOC_TURBOP:
1323 if (val == 0)
1324 wif->dturbo = TruthValue_false;
1325 else
1326 wif->dturbo = TruthValue_true;
1327 break;
1328 case IEEE80211_IOC_TXPOWER:
1329 wif->tx_power = val / 2;
1330 break;
1331 case IEEE80211_IOC_FRAGTHRESHOLD:
1332 wif->frag_threshold = val;
1333 break;
1334 case IEEE80211_IOC_RTSTHRESHOLD:
1335 wif->rts_threshold = val;
1336 break;
1337 case IEEE80211_IOC_WPS:
1338 if (val == 0)
1339 wif->priv_subscribe = TruthValue_false;
1340 else
1341 wif->priv_subscribe = TruthValue_true;
1342 break;
1343 case IEEE80211_IOC_BGSCAN:
1344 if (val == 0)
1345 wif->bg_scan = TruthValue_false;
1346 else
1347 wif->bg_scan = TruthValue_true;
1348 break;
1349 case IEEE80211_IOC_BGSCAN_IDLE:
1350 wif->bg_scan_idle = val;
1351 break;
1352 case IEEE80211_IOC_BGSCAN_INTERVAL:
1353 wif->bg_scan_interval = val;
1354 break;
1355 case IEEE80211_IOC_BMISSTHRESHOLD:
1356 wif->beacons_missed = val;
1357 break;
1358 case IEEE80211_IOC_ROAMING:
1359 switch (val) {
1360 case IEEE80211_ROAMING_DEVICE:
1361 wif->roam_mode = wlanIfaceRoamingMode_device;
1362 break;
1363 case IEEE80211_ROAMING_MANUAL:
1364 wif->roam_mode = wlanIfaceRoamingMode_manual;
1365 break;
1366 case IEEE80211_ROAMING_AUTO:
1367 /* FALTHROUGH */
1368 default:
1369 wif->roam_mode = wlanIfaceRoamingMode_auto;
1370 break;
1371 }
1372 break;
1373 case IEEE80211_IOC_DOTD:
1374 if (val == 0)
1375 wif->dot11d = TruthValue_false;
1376 else
1377 wif->dot11d = TruthValue_true;
1378 break;
1379 case IEEE80211_IOC_DOTH:
1380 if (val == 0)
1381 wif->dot11h = TruthValue_false;
1382 else
1383 wif->dot11h = TruthValue_true;
1384 break;
1385 case IEEE80211_IOC_DWDS:
1386 if (val == 0)
1387 wif->dynamic_wds = TruthValue_false;
1388 else
1389 wif->dynamic_wds = TruthValue_true;
1390 break;
1391 case IEEE80211_IOC_POWERSAVE:
1392 if (val == 0)
1393 wif->power_save = TruthValue_false;
1394 else
1395 wif->power_save = TruthValue_true;
1396 break;
1397 case IEEE80211_IOC_APBRIDGE:
1398 if (val == 0)
1399 wif->ap_bridge = TruthValue_false;
1400 else
1401 wif->ap_bridge = TruthValue_true;
1402 break;
1403 case IEEE80211_IOC_BEACON_INTERVAL:
1404 wif->beacon_interval = val;
1405 break;
1406 case IEEE80211_IOC_DTIM_PERIOD:
1407 wif->dtim_period = val;
1408 break;
1409 case IEEE80211_IOC_HIDESSID:
1410 if (val == 0)
1411 wif->hide_ssid = TruthValue_false;
1412 else
1413 wif->hide_ssid = TruthValue_true;
1414 break;
1415 case IEEE80211_IOC_INACTIVITY:
1416 if (val == 0)
1417 wif->inact_process = TruthValue_false;
1418 else
1419 wif->inact_process = TruthValue_true;
1420 break;
1421 case IEEE80211_IOC_PROTMODE:
1422 switch (val) {
1423 case IEEE80211_PROTMODE_CTS:
1424 wif->do11g_protect = wlanIfaceDot11gProtMode_cts;
1425 break;
1426 case IEEE80211_PROTMODE_RTSCTS:
1427 wif->do11g_protect = wlanIfaceDot11gProtMode_rtscts;
1428 break;
1429 case IEEE80211_PROTMODE_OFF:
1430 /* FALLTHROUGH */
1431 default:
1432 wif->do11g_protect = wlanIfaceDot11gProtMode_off;
1433 break;
1434 }
1435 break;
1436 case IEEE80211_IOC_PUREG:
1437 if (val == 0)
1438 wif->dot11g_pure = TruthValue_false;
1439 else
1440 wif->dot11g_pure = TruthValue_true;
1441 break;
1442 case IEEE80211_IOC_PUREN:
1443 if (val == 0)
1444 wif->dot11n_pure = TruthValue_false;
1445 else
1446 wif->dot11n_pure = TruthValue_true;
1447 break;
1448 case IEEE80211_IOC_AMPDU:
1449 switch (val) {
1450 case 0:
1451 wif->ampdu = WlanIfaceDot11nPduType_disabled;
1452 break;
1453 case 1:
1454 wif->ampdu = WlanIfaceDot11nPduType_txOnly;
1455 break;
1456 case 2:
1457 wif->ampdu = WlanIfaceDot11nPduType_rxOnly;
1458 break;
1459 case 3:
1460 /* FALLTHROUGH */
1461 default:
1462 wif->ampdu = WlanIfaceDot11nPduType_txAndRx;
1463 break;
1464 }
1465 break;
1466 case IEEE80211_IOC_AMPDU_DENSITY:
1467 switch (val) {
1468 case IEEE80211_HTCAP_MPDUDENSITY_025:
1469 wif->ampdu_density = 25;
1470 break;
1471 case IEEE80211_HTCAP_MPDUDENSITY_05:
1472 wif->ampdu_density = 50;
1473 break;
1474 case IEEE80211_HTCAP_MPDUDENSITY_1:
1475 wif->ampdu_density = 100;
1476 break;
1477 case IEEE80211_HTCAP_MPDUDENSITY_2:
1478 wif->ampdu_density = 200;
1479 break;
1480 case IEEE80211_HTCAP_MPDUDENSITY_4:
1481 wif->ampdu_density = 400;
1482 break;
1483 case IEEE80211_HTCAP_MPDUDENSITY_8:
1484 wif->ampdu_density = 800;
1485 break;
1486 case IEEE80211_HTCAP_MPDUDENSITY_16:
1487 wif->ampdu_density = 1600;
1488 break;
1489 case IEEE80211_HTCAP_MPDUDENSITY_NA:
1490 default:
1491 wif->ampdu_density = 0;
1492 break;
1493 }
1494 break;
1495 case IEEE80211_IOC_AMPDU_LIMIT:
1496 switch (val) {
1497 case IEEE80211_HTCAP_MAXRXAMPDU_8K:
1498 wif->ampdu_limit = 8192;
1499 break;
1500 case IEEE80211_HTCAP_MAXRXAMPDU_16K:
1501 wif->ampdu_limit = 16384;
1502 break;
1503 case IEEE80211_HTCAP_MAXRXAMPDU_32K:
1504 wif->ampdu_limit = 32768;
1505 break;
1506 case IEEE80211_HTCAP_MAXRXAMPDU_64K:
1507 default:
1508 wif->ampdu_limit = 65536;
1509 break;
1510 }
1511 break;
1512 case IEEE80211_IOC_AMSDU:
1513 switch (val) {
1514 case 0:
1515 wif->amsdu = WlanIfaceDot11nPduType_disabled;
1516 break;
1517 case 1:
1518 wif->amsdu = WlanIfaceDot11nPduType_txOnly;
1519 break;
1520 case 3:
1521 wif->amsdu = WlanIfaceDot11nPduType_txAndRx;
1522 break;
1523 case 2:
1524 default:
1525 /* FALLTHROUGH */
1526 wif->amsdu = WlanIfaceDot11nPduType_rxOnly;
1527 break;
1528 }
1529 break;
1530 case IEEE80211_IOC_AMSDU_LIMIT:
1531 wif->amsdu_limit = val;
1532 break;
1533 case IEEE80211_IOC_HTCONF:
1534 if (val == 0) /* XXX */
1535 wif->ht_enabled = TruthValue_false;
1536 else
1537 wif->ht_enabled = TruthValue_true;
1538 break;
1539 case IEEE80211_IOC_HTCOMPAT:
1540 if (val == 0)
1541 wif->ht_compatible = TruthValue_false;
1542 else
1543 wif->ht_compatible = TruthValue_true;
1544 break;
1545 case IEEE80211_IOC_HTPROTMODE:
1546 if (val == IEEE80211_PROTMODE_RTSCTS)
1547 wif->ht_prot_mode = wlanIfaceDot11nHTProtMode_rts;
1548 else
1549 wif->ht_prot_mode = wlanIfaceDot11nHTProtMode_off;
1550 break;
1551 case IEEE80211_IOC_RIFS:
1552 if (val == 0)
1553 wif->rifs = TruthValue_false;
1554 else
1555 wif->rifs = TruthValue_true;
1556 break;
1557 case IEEE80211_IOC_SHORTGI:
1558 if (val == 0)
1559 wif->short_gi = TruthValue_false;
1560 else
1561 wif->short_gi = TruthValue_true;
1562 break;
1563 case IEEE80211_IOC_SMPS:
1564 switch (val) {
1565 case IEEE80211_HTCAP_SMPS_DYNAMIC:
1566 wif->smps_mode = wlanIfaceDot11nSMPSMode_dynamic;
1567 break;
1568 case IEEE80211_HTCAP_SMPS_ENA:
1569 wif->smps_mode = wlanIfaceDot11nSMPSMode_static;
1570 break;
1571 case IEEE80211_HTCAP_SMPS_OFF:
1572 /* FALLTHROUGH */
1573 default:
1574 wif->smps_mode = wlanIfaceDot11nSMPSMode_disabled;
1575 break;
1576 }
1577 break;
1578 case IEEE80211_IOC_TDMA_SLOT:
1579 wif->tdma_slot = val;
1580 break;
1581 case IEEE80211_IOC_TDMA_SLOTCNT:
1582 wif->tdma_slot_count = val;
1583 break;
1584 case IEEE80211_IOC_TDMA_SLOTLEN:
1585 wif->tdma_slot_length = val;
1586 break;
1587 case IEEE80211_IOC_TDMA_BINTERVAL:
1588 wif->tdma_binterval = val;
1589 break;
1590 default:
1591 break;
1592 }
1593 }
1594
1595 /*
1596 * Convert an SNMP value to the kernel equivalent and also do sanity check
1597 * for each specific type.
1598 */
1599 static int
wlan_config_snmp2value(int which,int sval,int * value)1600 wlan_config_snmp2value(int which, int sval, int *value)
1601 {
1602 *value = 0;
1603
1604 switch (which) {
1605 case IEEE80211_IOC_BURST:
1606 case IEEE80211_IOC_DFS:
1607 case IEEE80211_IOC_FF:
1608 case IEEE80211_IOC_TURBOP:
1609 case IEEE80211_IOC_WPS:
1610 case IEEE80211_IOC_BGSCAN:
1611 case IEEE80211_IOC_DOTD:
1612 case IEEE80211_IOC_DOTH:
1613 case IEEE80211_IOC_DWDS:
1614 case IEEE80211_IOC_POWERSAVE:
1615 case IEEE80211_IOC_APBRIDGE:
1616 case IEEE80211_IOC_HIDESSID:
1617 case IEEE80211_IOC_INACTIVITY:
1618 case IEEE80211_IOC_PUREG:
1619 case IEEE80211_IOC_PUREN:
1620 case IEEE80211_IOC_HTCONF:
1621 case IEEE80211_IOC_HTCOMPAT:
1622 case IEEE80211_IOC_RIFS:
1623 if (sval == TruthValue_true)
1624 *value = 1;
1625 else if (sval != TruthValue_false)
1626 return (SNMP_ERR_INCONS_VALUE);
1627 break;
1628 case IEEE80211_IOC_REGDOMAIN:
1629 break;
1630 case IEEE80211_IOC_SSID:
1631 break;
1632 case IEEE80211_IOC_CURCHAN:
1633 break;
1634 case IEEE80211_IOC_TXPOWER:
1635 *value = sval * 2;
1636 break;
1637 case IEEE80211_IOC_FRAGTHRESHOLD:
1638 if (sval < IEEE80211_FRAG_MIN || sval > IEEE80211_FRAG_MAX)
1639 return (SNMP_ERR_INCONS_VALUE);
1640 *value = sval;
1641 break;
1642 case IEEE80211_IOC_RTSTHRESHOLD:
1643 if (sval < IEEE80211_RTS_MIN || sval > IEEE80211_RTS_MAX)
1644 return (SNMP_ERR_INCONS_VALUE);
1645 *value = sval;
1646 break;
1647 case IEEE80211_IOC_BGSCAN_IDLE:
1648 if (sval < WLAN_BGSCAN_IDLE_MIN)
1649 return (SNMP_ERR_INCONS_VALUE);
1650 *value = sval;
1651 break;
1652 case IEEE80211_IOC_BGSCAN_INTERVAL:
1653 if (sval < WLAN_SCAN_VALID_MIN)
1654 return (SNMP_ERR_INCONS_VALUE);
1655 *value = sval;
1656 break;
1657 case IEEE80211_IOC_BMISSTHRESHOLD:
1658 if (sval < IEEE80211_HWBMISS_MIN || sval > IEEE80211_HWBMISS_MAX)
1659 return (SNMP_ERR_INCONS_VALUE);
1660 *value = sval;
1661 break;
1662 case IEEE80211_IOC_BSSID:
1663 break;
1664 case IEEE80211_IOC_ROAMING:
1665 switch (sval) {
1666 case wlanIfaceRoamingMode_device:
1667 *value = IEEE80211_ROAMING_DEVICE;
1668 break;
1669 case wlanIfaceRoamingMode_manual:
1670 *value = IEEE80211_ROAMING_MANUAL;
1671 break;
1672 case wlanIfaceRoamingMode_auto:
1673 *value = IEEE80211_ROAMING_AUTO;
1674 break;
1675 default:
1676 return (SNMP_ERR_INCONS_VALUE);
1677 }
1678 break;
1679 case IEEE80211_IOC_BEACON_INTERVAL:
1680 if (sval < IEEE80211_BINTVAL_MIN || sval > IEEE80211_BINTVAL_MAX)
1681 return (SNMP_ERR_INCONS_VALUE);
1682 *value = sval;
1683 break;
1684 case IEEE80211_IOC_DTIM_PERIOD:
1685 if (sval < IEEE80211_DTIM_MIN || sval > IEEE80211_DTIM_MAX)
1686 return (SNMP_ERR_INCONS_VALUE);
1687 *value = sval;
1688 break;
1689 case IEEE80211_IOC_PROTMODE:
1690 switch (sval) {
1691 case wlanIfaceDot11gProtMode_cts:
1692 *value = IEEE80211_PROTMODE_CTS;
1693 break;
1694 case wlanIfaceDot11gProtMode_rtscts:
1695 *value = IEEE80211_PROTMODE_RTSCTS;
1696 break;
1697 case wlanIfaceDot11gProtMode_off:
1698 *value = IEEE80211_PROTMODE_OFF;
1699 break;
1700 default:
1701 return (SNMP_ERR_INCONS_VALUE);
1702 }
1703 break;
1704 case IEEE80211_IOC_AMPDU:
1705 switch (sval) {
1706 case WlanIfaceDot11nPduType_disabled:
1707 break;
1708 case WlanIfaceDot11nPduType_txOnly:
1709 *value = 1;
1710 break;
1711 case WlanIfaceDot11nPduType_rxOnly:
1712 *value = 2;
1713 break;
1714 case WlanIfaceDot11nPduType_txAndRx:
1715 *value = 3;
1716 break;
1717 default:
1718 return (SNMP_ERR_INCONS_VALUE);
1719 }
1720 break;
1721 case IEEE80211_IOC_AMPDU_DENSITY:
1722 switch (sval) {
1723 case 0:
1724 *value = IEEE80211_HTCAP_MPDUDENSITY_NA;
1725 break;
1726 case 25:
1727 *value = IEEE80211_HTCAP_MPDUDENSITY_025;
1728 break;
1729 case 50:
1730 *value = IEEE80211_HTCAP_MPDUDENSITY_05;
1731 break;
1732 case 100:
1733 *value = IEEE80211_HTCAP_MPDUDENSITY_1;
1734 break;
1735 case 200:
1736 *value = IEEE80211_HTCAP_MPDUDENSITY_2;
1737 break;
1738 case 400:
1739 *value = IEEE80211_HTCAP_MPDUDENSITY_4;
1740 break;
1741 case 800:
1742 *value = IEEE80211_HTCAP_MPDUDENSITY_8;
1743 break;
1744 case 1600:
1745 *value = IEEE80211_HTCAP_MPDUDENSITY_16;
1746 break;
1747 default:
1748 return (SNMP_ERR_INCONS_VALUE);
1749 }
1750 break;
1751 case IEEE80211_IOC_AMPDU_LIMIT:
1752 switch (sval) {
1753 case 8192:
1754 *value = IEEE80211_HTCAP_MAXRXAMPDU_8K;
1755 break;
1756 case 16384:
1757 *value = IEEE80211_HTCAP_MAXRXAMPDU_16K;
1758 break;
1759 case 32768:
1760 *value = IEEE80211_HTCAP_MAXRXAMPDU_32K;
1761 break;
1762 case 65536:
1763 *value = IEEE80211_HTCAP_MAXRXAMPDU_64K;
1764 break;
1765 default:
1766 return (SNMP_ERR_INCONS_VALUE);
1767 }
1768 break;
1769 case IEEE80211_IOC_AMSDU:
1770 switch (sval) {
1771 case WlanIfaceDot11nPduType_disabled:
1772 break;
1773 case WlanIfaceDot11nPduType_txOnly:
1774 *value = 1;
1775 break;
1776 case WlanIfaceDot11nPduType_rxOnly:
1777 *value = 2;
1778 break;
1779 case WlanIfaceDot11nPduType_txAndRx:
1780 *value = 3;
1781 break;
1782 default:
1783 return (SNMP_ERR_INCONS_VALUE);
1784 }
1785 break;
1786 case IEEE80211_IOC_AMSDU_LIMIT:
1787 if (sval == 3839 || sval == 0)
1788 *value = IEEE80211_HTCAP_MAXAMSDU_3839;
1789 else if (sval == 7935)
1790 *value = IEEE80211_HTCAP_MAXAMSDU_7935;
1791 else
1792 return (SNMP_ERR_INCONS_VALUE);
1793 break;
1794 case IEEE80211_IOC_HTPROTMODE:
1795 switch (sval) {
1796 case wlanIfaceDot11nHTProtMode_rts:
1797 *value = IEEE80211_PROTMODE_RTSCTS;
1798 break;
1799 case wlanIfaceDot11nHTProtMode_off:
1800 break;
1801 default:
1802 return (SNMP_ERR_INCONS_VALUE);
1803 }
1804 break;
1805 case IEEE80211_IOC_SHORTGI:
1806 if (sval == TruthValue_true)
1807 *value = IEEE80211_HTCAP_SHORTGI20 |
1808 IEEE80211_HTCAP_SHORTGI40;
1809 else if (sval != TruthValue_false)
1810 return (SNMP_ERR_INCONS_VALUE);
1811 break;
1812 case IEEE80211_IOC_SMPS:
1813 switch (sval) {
1814 case wlanIfaceDot11nSMPSMode_disabled:
1815 *value = IEEE80211_HTCAP_SMPS_OFF;
1816 break;
1817 case wlanIfaceDot11nSMPSMode_static:
1818 *value = IEEE80211_HTCAP_SMPS_ENA;
1819 break;
1820 case wlanIfaceDot11nSMPSMode_dynamic:
1821 *value = IEEE80211_HTCAP_SMPS_DYNAMIC;
1822 break;
1823 default:
1824 return (SNMP_ERR_INCONS_VALUE);
1825 }
1826 break;
1827 case IEEE80211_IOC_TDMA_SLOT:
1828 if (sval < 0 || sval > WLAN_TDMA_MAXSLOTS) /* XXX */
1829 return (SNMP_ERR_INCONS_VALUE);
1830 *value = sval;
1831 break;
1832 case IEEE80211_IOC_TDMA_SLOTCNT:
1833 if (sval < 0 || sval > WLAN_TDMA_MAXSLOTS) /* XXX */
1834 return (SNMP_ERR_INCONS_VALUE);
1835 *value = sval;
1836 break;
1837 case IEEE80211_IOC_TDMA_SLOTLEN:
1838 if (sval < 2*100 || sval > 0xfffff) /* XXX */
1839 return (SNMP_ERR_INCONS_VALUE);
1840 *value = sval;
1841 break;
1842 case IEEE80211_IOC_TDMA_BINTERVAL:
1843 if (sval < 1) /* XXX */
1844 return (SNMP_ERR_INCONS_VALUE);
1845 *value = sval;
1846 break;
1847 default:
1848 return (SNMP_ERR_INCONS_VALUE);
1849 }
1850
1851 return (SNMP_ERR_NOERROR);
1852 }
1853
1854 /*
1855 * Sanity checks for the wlanIfaceConfigTable.
1856 */
1857 static int
wlan_config_check(struct wlan_iface * wif,int op)1858 wlan_config_check(struct wlan_iface *wif, int op)
1859 {
1860 switch (op) {
1861 case IEEE80211_IOC_BURST:
1862 if ((wif->drivercaps & (0x1 << WlanDriverCaps_burst)) == 0) {
1863 wif->packet_burst = TruthValue_false;
1864 return (-1);
1865 }
1866 break;
1867 case IEEE80211_IOC_DFS:
1868 if ((wif->drivercaps & (0x1 << WlanDriverCaps_dfs)) == 0) {
1869 wif->dyn_frequency = TruthValue_false;
1870 return (-1);
1871 }
1872 break;
1873 case IEEE80211_IOC_FF:
1874 if ((wif->drivercaps & (0x1 << WlanDriverCaps_athFastFrames))
1875 == 0) {
1876 wif->fast_frames = TruthValue_false;
1877 return (-1);
1878 }
1879 break;
1880 case IEEE80211_IOC_TURBOP:
1881 if ((wif->drivercaps & (0x1 << WlanDriverCaps_athTurbo)) == 0) {
1882 wif->dturbo = TruthValue_false;
1883 return (-1);
1884 }
1885 break;
1886 case IEEE80211_IOC_TXPOWER:
1887 if ((wif->drivercaps & (0x1 << WlanDriverCaps_txPmgt)) == 0) {
1888 wif->tx_power = 0;
1889 return (-1);
1890 }
1891 break;
1892 case IEEE80211_IOC_FRAGTHRESHOLD:
1893 if ((wif->drivercaps & (0x1 << WlanDriverCaps_txFrag)) == 0) {
1894 wif->frag_threshold = IEEE80211_FRAG_MAX;
1895 return (-1);
1896 }
1897 break;
1898 case IEEE80211_IOC_DWDS:
1899 if ((wif->drivercaps & (0x1 << WlanDriverCaps_wds)) == 0) {
1900 wif->dynamic_wds = TruthValue_false;
1901 return (-1);
1902 }
1903 break;
1904 case IEEE80211_IOC_POWERSAVE:
1905 if ((wif->drivercaps & (0x1 << WlanDriverCaps_pmgt)) == 0) {
1906 wif->power_save = TruthValue_false;
1907 return (-1);
1908 }
1909 break;
1910 case IEEE80211_IOC_BEACON_INTERVAL:
1911 if (wif->mode != WlanIfaceOperatingModeType_hostAp &&
1912 wif->mode != WlanIfaceOperatingModeType_meshPoint &&
1913 wif->mode != WlanIfaceOperatingModeType_ibss) {
1914 wif->beacon_interval = 100; /* XXX */
1915 return (-1);
1916 }
1917 break;
1918 case IEEE80211_IOC_DTIM_PERIOD:
1919 if (wif->mode != WlanIfaceOperatingModeType_hostAp &&
1920 wif->mode != WlanIfaceOperatingModeType_meshPoint &&
1921 wif->mode != WlanIfaceOperatingModeType_ibss) {
1922 wif->dtim_period = 1; /* XXX */
1923 return (-1);
1924 }
1925 break;
1926 case IEEE80211_IOC_PUREN:
1927 if ((wif->htcaps & (0x1 << WlanHTCaps_htcHt)) == 0) {
1928 wif->dot11n_pure = TruthValue_false;
1929 return (-1);
1930 }
1931 break;
1932 case IEEE80211_IOC_AMPDU:
1933 if ((wif->htcaps & (0x1 << WlanHTCaps_htcAmpdu)) == 0) {
1934 wif->ampdu = WlanIfaceDot11nPduType_disabled;
1935 return (-1);
1936 }
1937 break;
1938 case IEEE80211_IOC_AMSDU:
1939 if ((wif->htcaps & (0x1 << WlanHTCaps_htcAmsdu)) == 0) {
1940 wif->amsdu = WlanIfaceDot11nPduType_disabled;
1941 return (-1);
1942 }
1943 break;
1944 case IEEE80211_IOC_RIFS:
1945 if ((wif->htcaps & (0x1 << WlanHTCaps_htcRifs)) == 0) {
1946 wif->rifs = TruthValue_false;
1947 return (-1);
1948 }
1949 break;
1950 case IEEE80211_IOC_SHORTGI:
1951 if ((wif->htcaps & (0x1 << WlanHTCaps_shortGi20 |
1952 0x1 << WlanHTCaps_shortGi40)) == 0) {
1953 wif->short_gi = TruthValue_false;
1954 return (-1);
1955 }
1956 break;
1957 case IEEE80211_IOC_SMPS:
1958 if ((wif->htcaps & (0x1 << WlanHTCaps_htcSmps)) == 0) {
1959 wif->smps_mode = wlanIfaceDot11nSMPSMode_disabled;
1960 return (-1);
1961 }
1962 break;
1963 case IEEE80211_IOC_TDMA_SLOT:
1964 if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {
1965 wif->tdma_slot = 0;
1966 return (-1);
1967 }
1968 break;
1969 case IEEE80211_IOC_TDMA_SLOTCNT:
1970 if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {
1971 wif->tdma_slot_count = 0;
1972 return (-1);
1973 }
1974 break;
1975 case IEEE80211_IOC_TDMA_SLOTLEN:
1976 if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {
1977 wif->tdma_slot_length = 0;
1978 return (-1);
1979 }
1980 break;
1981 case IEEE80211_IOC_TDMA_BINTERVAL:
1982 if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {
1983 wif->tdma_binterval = 0;
1984 return (-1);
1985 }
1986 break;
1987 default:
1988 break;
1989 }
1990
1991 return (0);
1992 }
1993
1994 static int
wlan_config_get_intval(struct wlan_iface * wif,int op)1995 wlan_config_get_intval(struct wlan_iface *wif, int op)
1996 {
1997 int val = 0;
1998 size_t argsize = 0;
1999
2000 if (wlan_config_check(wif, op) < 0)
2001 return (0);
2002 if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 0) < 0)
2003 return (-1);
2004 wlan_config_set_snmp_intval(wif, op, val);
2005
2006 return (0);
2007 }
2008
2009 static int
wlan_config_set_intval(struct wlan_iface * wif,int op,int sval)2010 wlan_config_set_intval(struct wlan_iface *wif, int op, int sval)
2011 {
2012 size_t argsize = 0;
2013 int val;
2014
2015 if (wlan_config_check(wif, op) < 0)
2016 return (-1);
2017 if (wlan_config_snmp2value(op, sval, &val) != SNMP_ERR_NOERROR)
2018 return (-1);
2019 if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 1) < 0)
2020 return (-1);
2021 wlan_config_set_snmp_intval(wif, op, val);
2022
2023 return (0);
2024 }
2025
2026 int
wlan_config_get_ioctl(struct wlan_iface * wif,int which)2027 wlan_config_get_ioctl(struct wlan_iface *wif, int which)
2028 {
2029 int op;
2030
2031 switch (which) {
2032 case LEAF_wlanIfaceCountryCode:
2033 /* FALLTHROUGH */
2034 case LEAF_wlanIfaceRegDomain:
2035 return (wlan_config_get_country(wif));
2036 case LEAF_wlanIfaceDesiredSsid:
2037 return (wlan_config_get_dssid(wif));
2038 case LEAF_wlanIfaceDesiredChannel:
2039 return (wlan_config_get_dchannel(wif));
2040 case LEAF_wlanIfaceDesiredBssid:
2041 return (wlan_config_get_bssid(wif));
2042 default:
2043 op = wlan_config_snmp2ioctl(which);
2044 return (wlan_config_get_intval(wif, op));
2045 }
2046
2047 return (-1);
2048 }
2049
2050 int
wlan_config_set_ioctl(struct wlan_iface * wif,int which,int val,char * strval,int len)2051 wlan_config_set_ioctl(struct wlan_iface *wif, int which, int val,
2052 char *strval, int len)
2053 {
2054 int op;
2055
2056 switch (which) {
2057 case LEAF_wlanIfaceCountryCode:
2058 return (wlan_config_set_country(wif, strval,
2059 wif->reg_domain));
2060 case LEAF_wlanIfaceRegDomain:
2061 return (wlan_config_set_country(wif, wif->country_code,
2062 val));
2063 case LEAF_wlanIfaceDesiredSsid:
2064 return (wlan_config_set_dssid(wif, strval, len));
2065 case LEAF_wlanIfaceDesiredChannel:
2066 return (wlan_config_set_dchannel(wif, val));
2067 case LEAF_wlanIfaceDesiredBssid:
2068 return (wlan_config_set_bssid(wif, strval));
2069 default:
2070 op = wlan_config_snmp2ioctl(which);
2071 return (wlan_config_set_intval(wif, op, val));
2072 }
2073
2074 return (-1);
2075 }
2076
2077 static uint32_t
wlan_snmp_to_scan_flags(int flags)2078 wlan_snmp_to_scan_flags(int flags)
2079 {
2080 int sr_flags = 0;
2081
2082 if ((flags & (0x1 << WlanScanFlagsType_noSelection)) != 0)
2083 sr_flags |= IEEE80211_IOC_SCAN_NOPICK;
2084 if ((flags & (0x1 << WlanScanFlagsType_activeScan)) != 0)
2085 sr_flags |= IEEE80211_IOC_SCAN_ACTIVE;
2086 if ((flags & (0x1 << WlanScanFlagsType_pickFirst)) != 0)
2087 sr_flags |= IEEE80211_IOC_SCAN_PICK1ST;
2088 if ((flags & (0x1 << WlanScanFlagsType_backgroundScan)) != 0)
2089 sr_flags |= IEEE80211_IOC_SCAN_BGSCAN;
2090 if ((flags & (0x1 << WlanScanFlagsType_once)) != 0)
2091 sr_flags |= IEEE80211_IOC_SCAN_ONCE;
2092 if ((flags & (0x1 << WlanScanFlagsType_noBroadcast)) != 0)
2093 sr_flags |= IEEE80211_IOC_SCAN_NOBCAST;
2094 if ((flags & (0x1 << WlanScanFlagsType_noAutoSequencing)) != 0)
2095 sr_flags |= IEEE80211_IOC_SCAN_NOJOIN;
2096 if ((flags & (0x1 << WlanScanFlagsType_flushCashe)) != 0)
2097 sr_flags |= IEEE80211_IOC_SCAN_FLUSH;
2098 if ((flags & (0x1 << WlanScanFlagsType_chechCashe)) != 0)
2099 sr_flags |= IEEE80211_IOC_SCAN_CHECK;
2100
2101 return (sr_flags);
2102 }
2103
2104 int
wlan_set_scan_config(struct wlan_iface * wif)2105 wlan_set_scan_config(struct wlan_iface *wif)
2106 {
2107 int val = 0;
2108 size_t argsize;
2109 struct ieee80211_scan_req sr;
2110
2111
2112 memset(&sr, 0, sizeof(sr));
2113 argsize = sizeof(struct ieee80211_scan_req);
2114 sr.sr_flags = wlan_snmp_to_scan_flags(wif->scan_flags);
2115 sr.sr_flags |= IEEE80211_IOC_SCAN_BGSCAN;
2116 sr.sr_duration = wif->scan_duration;
2117 sr.sr_mindwell = wif->scan_mindwell;
2118 sr.sr_maxdwell = wif->scan_maxdwell;
2119 sr.sr_nssid = 0;
2120
2121 if (wlan_ioctl(wif->wname, IEEE80211_IOC_SCAN_REQ,
2122 &val, &sr, &argsize, 1) < 0)
2123 return (-1);
2124
2125 wif->scan_status = wlanScanConfigStatus_running;
2126 return (0);
2127 }
2128
2129 static uint32_t
wlan_peercaps_to_snmp(uint32_t pcaps)2130 wlan_peercaps_to_snmp(uint32_t pcaps)
2131 {
2132 uint32_t scaps = 0;
2133
2134 if ((pcaps & IEEE80211_CAPINFO_ESS) != 0)
2135 scaps |= (0x1 << WlanPeerCapabilityFlags_ess);
2136 if ((pcaps & IEEE80211_CAPINFO_IBSS) != 0)
2137 scaps |= (0x1 << WlanPeerCapabilityFlags_ibss);
2138 if ((pcaps & IEEE80211_CAPINFO_CF_POLLABLE) != 0)
2139 scaps |= (0x1 << WlanPeerCapabilityFlags_cfPollable);
2140 if ((pcaps & IEEE80211_CAPINFO_CF_POLLREQ) != 0)
2141 scaps |= (0x1 << WlanPeerCapabilityFlags_cfPollRequest);
2142 if ((pcaps & IEEE80211_CAPINFO_PRIVACY) != 0)
2143 scaps |= (0x1 << WlanPeerCapabilityFlags_privacy);
2144 if ((pcaps & IEEE80211_CAPINFO_SHORT_PREAMBLE) != 0)
2145 scaps |= (0x1 << WlanPeerCapabilityFlags_shortPreamble);
2146 if ((pcaps & IEEE80211_CAPINFO_PBCC) != 0)
2147 scaps |= (0x1 << WlanPeerCapabilityFlags_pbcc);
2148 if ((pcaps & IEEE80211_CAPINFO_CHNL_AGILITY) != 0)
2149 scaps |= (0x1 << WlanPeerCapabilityFlags_channelAgility);
2150 if ((pcaps & IEEE80211_CAPINFO_SHORT_SLOTTIME) != 0)
2151 scaps |= (0x1 << WlanPeerCapabilityFlags_shortSlotTime);
2152 if ((pcaps & IEEE80211_CAPINFO_RSN) != 0)
2153 scaps |= (0x1 << WlanPeerCapabilityFlags_rsn);
2154 if ((pcaps & IEEE80211_CAPINFO_DSSSOFDM) != 0)
2155 scaps |= (0x1 << WlanPeerCapabilityFlags_dsssofdm);
2156
2157 return (scaps);
2158 }
2159
2160 static int
wlan_add_new_scan_result(struct wlan_iface * wif,const struct ieee80211req_scan_result * isr,uint8_t * ssid)2161 wlan_add_new_scan_result(struct wlan_iface *wif,
2162 const struct ieee80211req_scan_result *isr, uint8_t *ssid)
2163 {
2164 struct wlan_scan_result *sr;
2165
2166 if ((sr = wlan_scan_new_result(ssid, isr->isr_bssid)) == NULL)
2167 return (-1);
2168
2169 sr->opchannel = wlan_channel_flags_to_snmp_phy(isr->isr_flags);
2170 sr->rssi = isr->isr_rssi;
2171 sr->frequency = isr->isr_freq;
2172 sr->noise = isr->isr_noise;
2173 sr->bintval = isr->isr_intval;
2174 sr->capinfo = wlan_peercaps_to_snmp(isr->isr_capinfo);
2175
2176 if (wlan_scan_add_result(wif, sr) < 0) {
2177 wlan_scan_free_result(sr);
2178 return (-1);
2179 }
2180
2181 return (0);
2182 }
2183
2184 int
wlan_get_scan_results(struct wlan_iface * wif)2185 wlan_get_scan_results(struct wlan_iface *wif)
2186 {
2187 int ssidlen, val = 0;
2188 uint8_t buf[24 * 1024];
2189 size_t argsize;
2190 const uint8_t *cp, *idp;
2191 uint8_t ssid[IEEE80211_NWID_LEN + 1];
2192 struct ieee80211req_scan_result isr;
2193
2194 argsize = sizeof(buf);
2195 if (wlan_ioctl(wif->wname, IEEE80211_IOC_SCAN_RESULTS, &val, &buf,
2196 &argsize, 0) < 0)
2197 return (-1);
2198
2199 if (argsize < sizeof(struct ieee80211req_scan_result))
2200 return (0);
2201
2202 cp = buf;
2203 do {
2204 memcpy(&isr, cp, sizeof(struct ieee80211req_scan_result));
2205 memset(ssid, 0, IEEE80211_NWID_LEN + 1);
2206
2207 if (isr.isr_meshid_len) {
2208 idp = cp + isr.isr_ie_off + isr.isr_ssid_len;
2209 ssidlen = isr.isr_meshid_len;
2210 } else {
2211 idp = cp + isr.isr_ie_off;
2212 ssidlen = isr.isr_ssid_len;
2213 }
2214 if (ssidlen > IEEE80211_NWID_LEN)
2215 ssidlen = IEEE80211_NWID_LEN;
2216 memcpy(ssid, idp, ssidlen);
2217 ssid[IEEE80211_NWID_LEN] = '\0';
2218 (void)wlan_add_new_scan_result(wif, &isr, ssid);
2219 cp += isr.isr_len;
2220 argsize -= isr.isr_len;
2221 } while (argsize >= sizeof(struct ieee80211req_scan_result));
2222
2223 return (0);
2224 }
2225
2226 int
wlan_get_stats(struct wlan_iface * wif)2227 wlan_get_stats(struct wlan_iface *wif)
2228 {
2229 struct ifreq ifr;
2230
2231 memset(&ifr, 0, sizeof(struct ifreq));
2232 strlcpy(ifr.ifr_name, wif->wname, IFNAMSIZ);
2233
2234 ifr.ifr_data = (caddr_t) &wif->stats;
2235
2236 if (ioctl(sock, SIOCG80211STATS, &ifr) < 0) {
2237 syslog(LOG_ERR, "iface %s - ioctl(SIOCG80211STATS) failed: %s",
2238 wif->wname, strerror(errno));
2239 return (-1);
2240 }
2241
2242 return (0);
2243 }
2244
2245 int
wlan_get_wepmode(struct wlan_iface * wif)2246 wlan_get_wepmode(struct wlan_iface *wif)
2247 {
2248 int val = 0;
2249 size_t argsize = 0;
2250
2251 if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEP, &val, NULL,
2252 &argsize, 0) < 0 || val == IEEE80211_WEP_NOSUP) {
2253 wif->wepsupported = 0; /* XXX */
2254 wif->wepmode = wlanWepMode_off;
2255 wif->weptxkey = 0;
2256 return (-1);
2257 }
2258
2259 wif->wepsupported = 1;
2260
2261 switch (val) {
2262 case IEEE80211_WEP_ON:
2263 wif->wepmode = wlanWepMode_on;
2264 break;
2265 case IEEE80211_WEP_MIXED:
2266 wif->wepmode = wlanWepMode_mixed;
2267 break;
2268 case IEEE80211_WEP_OFF:
2269 /* FALLTHROUGH */
2270 default:
2271 wif->wepmode = wlanWepMode_off;
2272 break;
2273 }
2274
2275 return (0);
2276 }
2277
2278 int
wlan_set_wepmode(struct wlan_iface * wif)2279 wlan_set_wepmode(struct wlan_iface *wif)
2280 {
2281 int val;
2282 size_t argsize = 0;
2283
2284 if (!wif->wepsupported)
2285 return (-1);
2286
2287 switch (wif->wepmode) {
2288 case wlanWepMode_off:
2289 val = IEEE80211_WEP_OFF;
2290 break;
2291 case wlanWepMode_on:
2292 val = IEEE80211_WEP_ON;
2293 break;
2294 case wlanWepMode_mixed:
2295 val = IEEE80211_WEP_MIXED;
2296 break;
2297 default:
2298 return (-1);
2299 }
2300
2301 if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEP, &val, NULL,
2302 &argsize, 1) < 0)
2303 return (-1);
2304
2305 return (0);
2306 }
2307
2308 int
wlan_get_weptxkey(struct wlan_iface * wif)2309 wlan_get_weptxkey(struct wlan_iface *wif)
2310 {
2311 int val;
2312 size_t argsize = 0;
2313
2314 if (!wif->wepsupported)
2315 return (0);
2316
2317 if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEPTXKEY, &val, NULL,
2318 &argsize, 0) < 0)
2319 return (-1);
2320
2321 if (val == IEEE80211_KEYIX_NONE)
2322 wif->weptxkey = 0;
2323 else
2324 wif->weptxkey = val + 1;
2325
2326 return (0);
2327 }
2328
2329 int
wlan_set_weptxkey(struct wlan_iface * wif)2330 wlan_set_weptxkey(struct wlan_iface *wif)
2331 {
2332 int val;
2333 size_t argsize = 0;
2334
2335 if (!wif->wepsupported)
2336 return (0);
2337
2338 if (wif->weptxkey >= IEEE80211_WEP_NKID)
2339 return (-1);
2340
2341 if (wif->weptxkey == 0)
2342 val = IEEE80211_KEYIX_NONE;
2343 else
2344 val = wif->weptxkey - 1;
2345 if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEPTXKEY, &val, NULL,
2346 &argsize, 1) < 0)
2347 return (-1);
2348
2349 return (0);
2350 }
2351
2352 int
wlan_get_wepkeys(struct wlan_iface * wif __unused)2353 wlan_get_wepkeys(struct wlan_iface *wif __unused)
2354 {
2355 /* XXX: should they be visible via SNMP */
2356 return (0);
2357 }
2358
2359 int
wlan_set_wepkeys(struct wlan_iface * wif __unused)2360 wlan_set_wepkeys(struct wlan_iface *wif __unused)
2361 {
2362 /* XXX: should they be configurable via SNMP */
2363 return (0);
2364 }
2365
2366 int
wlan_get_mac_policy(struct wlan_iface * wif)2367 wlan_get_mac_policy(struct wlan_iface *wif)
2368 {
2369 int val = IEEE80211_MACCMD_POLICY;
2370 size_t argsize = 0;
2371 struct ieee80211req ireq;
2372
2373 memset(&ireq, 0, sizeof(struct ieee80211req));
2374 strlcpy(ireq.i_name, wif->wname, IFNAMSIZ);
2375 ireq.i_type = IEEE80211_IOC_MACCMD;
2376 ireq.i_val = IEEE80211_MACCMD_POLICY;
2377
2378 if (ioctl(sock, SIOCG80211, &ireq) < 0) {
2379 if (errno != EINVAL) {
2380 syslog(LOG_ERR, "iface %s - get param: ioctl(%d) "
2381 "failed: %s", wif->wname, ireq.i_type,
2382 strerror(errno));
2383 wif->macsupported = 0;
2384 return (-1);
2385 } else {
2386 wif->macsupported = 1;
2387 wif->mac_policy = wlanMACAccessControlPolicy_open;
2388 return (0);
2389 }
2390
2391 }
2392
2393 wif->macsupported = 1;
2394
2395 switch (val) {
2396 case IEEE80211_MACCMD_POLICY_ALLOW:
2397 wif->mac_policy = wlanMACAccessControlPolicy_allow;
2398 break;
2399 case IEEE80211_MACCMD_POLICY_DENY:
2400 wif->mac_policy = wlanMACAccessControlPolicy_deny;
2401 break;
2402 case IEEE80211_MACCMD_POLICY_RADIUS:
2403 wif->mac_policy = wlanMACAccessControlPolicy_radius;
2404 break;
2405 case IEEE80211_MACCMD_POLICY_OPEN:
2406 /* FALLTHROUGH */
2407 default:
2408 wif->mac_policy = wlanMACAccessControlPolicy_open;
2409 break;
2410 }
2411
2412 argsize = 0;
2413 val = IEEE80211_MACCMD_LIST;
2414 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL,
2415 &argsize, 0) < 0)
2416 return (-1);
2417
2418 wif->mac_nacls = argsize / sizeof(struct ieee80211req_maclist *);
2419 return (0);
2420 }
2421
2422 int
wlan_set_mac_policy(struct wlan_iface * wif)2423 wlan_set_mac_policy(struct wlan_iface *wif)
2424 {
2425 int val;
2426 size_t argsize = 0;
2427
2428 if (!wif->macsupported)
2429 return (-1);
2430
2431 switch (wif->mac_policy) {
2432 case wlanMACAccessControlPolicy_allow:
2433 val = IEEE80211_MACCMD_POLICY_ALLOW;
2434 break;
2435 case wlanMACAccessControlPolicy_deny:
2436 val = IEEE80211_MACCMD_POLICY_DENY;
2437 break;
2438 case wlanMACAccessControlPolicy_radius:
2439 val = IEEE80211_MACCMD_POLICY_RADIUS;
2440 break;
2441 case wlanMACAccessControlPolicy_open:
2442 val = IEEE80211_MACCMD_POLICY_OPEN;
2443 break;
2444 default:
2445 return (-1);
2446 }
2447
2448 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL,
2449 &argsize, 1) < 0)
2450 return (-1);
2451
2452 return (0);
2453 }
2454
2455 int
wlan_flush_mac_mac(struct wlan_iface * wif)2456 wlan_flush_mac_mac(struct wlan_iface *wif)
2457 {
2458 int val = IEEE80211_MACCMD_FLUSH;
2459 size_t argsize = 0;
2460
2461 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL,
2462 &argsize, 1) < 0)
2463 return (-1);
2464
2465 return (0);
2466 }
2467
2468 static int
wlan_add_mac_macinfo(struct wlan_iface * wif,const struct ieee80211req_maclist * ml)2469 wlan_add_mac_macinfo(struct wlan_iface *wif,
2470 const struct ieee80211req_maclist *ml)
2471 {
2472 struct wlan_mac_mac *mmac;
2473
2474 if ((mmac = wlan_mac_new_mac(ml->ml_macaddr)) == NULL)
2475 return (-1);
2476
2477 mmac->mac_status = RowStatus_active;
2478 if (wlan_mac_add_mac(wif, mmac) < 0) {
2479 wlan_mac_free_mac(mmac);
2480 return (-1);
2481 }
2482
2483 return (0);
2484 }
2485
2486 int
wlan_get_mac_acl_macs(struct wlan_iface * wif)2487 wlan_get_mac_acl_macs(struct wlan_iface *wif)
2488 {
2489 int i, nacls, val = IEEE80211_MACCMD_LIST;
2490 size_t argsize = 0;
2491 uint8_t *data;
2492 struct ieee80211req ireq;
2493 const struct ieee80211req_maclist *acllist;
2494
2495 if (wif->mac_policy == wlanMACAccessControlPolicy_radius) {
2496 wif->mac_nacls = 0;
2497 return (0);
2498 }
2499
2500 memset(&ireq, 0, sizeof(struct ieee80211req));
2501 strlcpy(ireq.i_name, wif->wname, IFNAMSIZ);
2502 ireq.i_type = IEEE80211_IOC_MACCMD;
2503 ireq.i_val = IEEE80211_MACCMD_LIST;
2504
2505
2506 if (ioctl(sock, SIOCG80211, &ireq) < 0) {
2507 if (errno != EINVAL) {
2508 syslog(LOG_ERR, "iface %s - get param: ioctl(%d) "
2509 "failed: %s", wif->wname, ireq.i_type,
2510 strerror(errno));
2511 wif->macsupported = 0;
2512 return (-1);
2513 }
2514 }
2515
2516 if (argsize == 0) {
2517 wif->mac_nacls = 0;
2518 return (0);
2519 }
2520
2521 if ((data = (uint8_t *)malloc(argsize)) == NULL)
2522 return (-1);
2523
2524 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, data,
2525 &argsize, 0) < 0)
2526 return (-1);
2527
2528 nacls = argsize / sizeof(*acllist);
2529 acllist = (struct ieee80211req_maclist *) data;
2530 for (i = 0; i < nacls; i++)
2531 (void)wlan_add_mac_macinfo(wif, acllist + i);
2532
2533 wif->mac_nacls = nacls;
2534 return (0);
2535 }
2536
2537 int
wlan_add_mac_acl_mac(struct wlan_iface * wif,struct wlan_mac_mac * mmac)2538 wlan_add_mac_acl_mac(struct wlan_iface *wif, struct wlan_mac_mac *mmac)
2539 {
2540 int val = 0;
2541 size_t argsize = IEEE80211_ADDR_LEN;
2542 struct ieee80211req_mlme mlme;
2543
2544 if (wlan_ioctl(wif->wname, IEEE80211_IOC_ADDMAC, &val,
2545 mmac->mac, &argsize, 1) < 0)
2546 return (-1);
2547
2548 mmac->mac_status = RowStatus_active;
2549
2550 /* If policy is deny, try to kick the station just in case. */
2551 if (wif->mac_policy != wlanMACAccessControlPolicy_deny)
2552 return (0);
2553
2554 memset(&mlme, 0, sizeof(mlme));
2555 mlme.im_op = IEEE80211_MLME_DEAUTH;
2556 mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE;
2557 memcpy(mlme.im_macaddr, mmac->mac, IEEE80211_ADDR_LEN);
2558 argsize = sizeof(struct ieee80211req_mlme);
2559
2560 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MLME, &val, &mlme,
2561 &argsize, 1) < 0 && errno != ENOENT)
2562 return (-1);
2563
2564 return (0);
2565 }
2566
2567 int
wlan_del_mac_acl_mac(struct wlan_iface * wif,struct wlan_mac_mac * mmac)2568 wlan_del_mac_acl_mac(struct wlan_iface *wif, struct wlan_mac_mac *mmac)
2569 {
2570 int val = 0;
2571 size_t argsize = IEEE80211_ADDR_LEN;
2572 struct ieee80211req_mlme mlme;
2573
2574 if (wlan_ioctl(wif->wname, IEEE80211_IOC_DELMAC, &val,
2575 mmac->mac, &argsize, 1) < 0)
2576 return (-1);
2577
2578 mmac->mac_status = RowStatus_active;
2579
2580 /* If policy is allow, try to kick the station just in case. */
2581 if (wif->mac_policy != wlanMACAccessControlPolicy_allow)
2582 return (0);
2583
2584 memset(&mlme, 0, sizeof(mlme));
2585 mlme.im_op = IEEE80211_MLME_DEAUTH;
2586 mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE;
2587 memcpy(mlme.im_macaddr, mmac->mac, IEEE80211_ADDR_LEN);
2588 argsize = sizeof(struct ieee80211req_mlme);
2589
2590 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MLME, &val, &mlme,
2591 &argsize, 1) < 0 && errno != ENOENT)
2592 return (-1);
2593
2594 return (0);
2595 }
2596
2597 int
wlan_peer_set_vlan(struct wlan_iface * wif,struct wlan_peer * wip,int vlan)2598 wlan_peer_set_vlan(struct wlan_iface *wif, struct wlan_peer *wip, int vlan)
2599 {
2600 int val = 0;
2601 size_t argsize;
2602 struct ieee80211req_sta_vlan vreq;
2603
2604 memcpy(vreq.sv_macaddr, wip->pmac, IEEE80211_ADDR_LEN);
2605 vreq.sv_vlan = vlan;
2606 argsize = sizeof(struct ieee80211req_sta_vlan);
2607
2608 if (wlan_ioctl(wif->wname, IEEE80211_IOC_STA_VLAN,
2609 &val, &vreq, &argsize, 1) < 0)
2610 return (-1);
2611
2612 wip->vlan = vlan;
2613
2614 return (0);
2615 }
2616
2617 /* XXX */
2618 #ifndef IEEE80211_NODE_AUTH
2619 #define IEEE80211_NODE_AUTH 0x000001 /* authorized for data */
2620 #define IEEE80211_NODE_QOS 0x000002 /* QoS enabled */
2621 #define IEEE80211_NODE_ERP 0x000004 /* ERP enabled */
2622 #define IEEE80211_NODE_PWR_MGT 0x000010 /* power save mode enabled */
2623 #define IEEE80211_NODE_AREF 0x000020 /* authentication ref held */
2624 #define IEEE80211_NODE_HT 0x000040 /* HT enabled */
2625 #define IEEE80211_NODE_HTCOMPAT 0x000080 /* HT setup w/ vendor OUI's */
2626 #define IEEE80211_NODE_WPS 0x000100 /* WPS association */
2627 #define IEEE80211_NODE_TSN 0x000200 /* TSN association */
2628 #define IEEE80211_NODE_AMPDU_RX 0x000400 /* AMPDU rx enabled */
2629 #define IEEE80211_NODE_AMPDU_TX 0x000800 /* AMPDU tx enabled */
2630 #define IEEE80211_NODE_MIMO_PS 0x001000 /* MIMO power save enabled */
2631 #define IEEE80211_NODE_MIMO_RTS 0x002000 /* send RTS in MIMO PS */
2632 #define IEEE80211_NODE_RIFS 0x004000 /* RIFS enabled */
2633 #define IEEE80211_NODE_SGI20 0x008000 /* Short GI in HT20 enabled */
2634 #define IEEE80211_NODE_SGI40 0x010000 /* Short GI in HT40 enabled */
2635 #define IEEE80211_NODE_ASSOCID 0x020000 /* xmit requires associd */
2636 #define IEEE80211_NODE_AMSDU_RX 0x040000 /* AMSDU rx enabled */
2637 #define IEEE80211_NODE_AMSDU_TX 0x080000 /* AMSDU tx enabled */
2638 #endif
2639
2640 static uint32_t
wlan_peerstate_to_snmp(uint32_t pstate)2641 wlan_peerstate_to_snmp(uint32_t pstate)
2642 {
2643 uint32_t sstate = 0;
2644
2645 if ((pstate & IEEE80211_NODE_AUTH) != 0)
2646 sstate |= (0x1 << WlanIfacePeerFlagsType_authorizedForData);
2647 if ((pstate & IEEE80211_NODE_QOS) != 0)
2648 sstate |= (0x1 << WlanIfacePeerFlagsType_qosEnabled);
2649 if ((pstate & IEEE80211_NODE_ERP) != 0)
2650 sstate |= (0x1 << WlanIfacePeerFlagsType_erpEnabled);
2651 if ((pstate & IEEE80211_NODE_PWR_MGT) != 0)
2652 sstate |= (0x1 << WlanIfacePeerFlagsType_powerSaveMode);
2653 if ((pstate & IEEE80211_NODE_AREF) != 0)
2654 sstate |= (0x1 << WlanIfacePeerFlagsType_authRefHeld);
2655 if ((pstate & IEEE80211_NODE_HT) != 0)
2656 sstate |= (0x1 << WlanIfacePeerFlagsType_htEnabled);
2657 if ((pstate & IEEE80211_NODE_HTCOMPAT) != 0)
2658 sstate |= (0x1 << WlanIfacePeerFlagsType_htCompat);
2659 if ((pstate & IEEE80211_NODE_WPS) != 0)
2660 sstate |= (0x1 << WlanIfacePeerFlagsType_wpsAssoc);
2661 if ((pstate & IEEE80211_NODE_TSN) != 0)
2662 sstate |= (0x1 << WlanIfacePeerFlagsType_tsnAssoc);
2663 if ((pstate & IEEE80211_NODE_AMPDU_RX) != 0)
2664 sstate |= (0x1 << WlanIfacePeerFlagsType_ampduRx);
2665 if ((pstate & IEEE80211_NODE_AMPDU_TX) != 0)
2666 sstate |= (0x1 << WlanIfacePeerFlagsType_ampduTx);
2667 if ((pstate & IEEE80211_NODE_MIMO_PS) != 0)
2668 sstate |= (0x1 << WlanIfacePeerFlagsType_mimoPowerSave);
2669 if ((pstate & IEEE80211_NODE_MIMO_RTS) != 0)
2670 sstate |= (0x1 << WlanIfacePeerFlagsType_sendRts);
2671 if ((pstate & IEEE80211_NODE_RIFS) != 0)
2672 sstate |= (0x1 << WlanIfacePeerFlagsType_rifs);
2673 if ((pstate & IEEE80211_NODE_SGI20) != 0)
2674 sstate |= (0x1 << WlanIfacePeerFlagsType_shortGiHT20);
2675 if ((pstate & IEEE80211_NODE_SGI40) != 0)
2676 sstate |= (0x1 << WlanIfacePeerFlagsType_shortGiHT40);
2677 if ((pstate & IEEE80211_NODE_AMSDU_RX) != 0)
2678 sstate |= (0x1 << WlanIfacePeerFlagsType_amsduRx);
2679 if ((pstate & IEEE80211_NODE_AMSDU_TX) != 0)
2680 sstate |= (0x1 << WlanIfacePeerFlagsType_amsduTx);
2681
2682 return (sstate);
2683 }
2684
2685 static struct wlan_peer *
wlan_add_peerinfo(const struct ieee80211req_sta_info * si)2686 wlan_add_peerinfo(const struct ieee80211req_sta_info *si)
2687 {
2688 struct wlan_peer *wip;
2689
2690 if ((wip = wlan_new_peer(si->isi_macaddr))== NULL)
2691 return (NULL);
2692
2693 wip->associd = IEEE80211_AID(si->isi_associd);
2694 wip->vlan = si->isi_vlan;
2695 wip->frequency = si->isi_freq;
2696 wip->fflags = si->isi_flags;
2697 wip->txrate = si->isi_txrate;
2698 wip->rssi = si->isi_rssi;
2699 wip->idle = si->isi_inact;
2700 wip->txseqs = si->isi_txseqs[0]; /* XXX */
2701 wip->rxseqs = si->isi_rxseqs[0]; /* XXX */
2702 wip->txpower = si->isi_txpower;
2703 wip->capinfo = wlan_peercaps_to_snmp(si->isi_capinfo);
2704 wip->state = wlan_peerstate_to_snmp(si->isi_state);
2705 wip->local_id = si->isi_localid;
2706 wip->peer_id = si->isi_peerid;
2707
2708 return (wip);
2709 }
2710
2711 int
wlan_get_peerinfo(struct wlan_iface * wif)2712 wlan_get_peerinfo(struct wlan_iface *wif)
2713 {
2714 union {
2715 struct ieee80211req_sta_req req;
2716 uint8_t buf[24 * 1024];
2717 } u;
2718 const uint8_t *cp;
2719 int val = 0;
2720 size_t len;
2721 struct ieee80211req_sta_info si;
2722 struct wlan_peer *wip;
2723
2724 /* Get all stations - broadcast address */
2725 (void) memset(u.req.is_u.macaddr, 0xff, IEEE80211_ADDR_LEN);
2726 len = sizeof(u);
2727
2728 if (wlan_ioctl(wif->wname, IEEE80211_IOC_STA_INFO,
2729 & val, &u, &len, 0) < 0)
2730 return (-1);
2731
2732 if (len < sizeof(struct ieee80211req_sta_info))
2733 return (-1);
2734
2735 cp = (const uint8_t *) u.req.info;
2736 do {
2737 memcpy(&si, cp, sizeof(struct ieee80211req_sta_info));
2738 if ((wip = wlan_add_peerinfo(&si)) != NULL &&
2739 wlan_add_peer(wif, wip) < 0)
2740 wlan_free_peer(wip);
2741 cp += si.isi_len, len -= si.isi_len;
2742 } while (len >= sizeof(struct ieee80211req_sta_info));
2743
2744 return (0);
2745 }
2746
2747 /************************************************************************
2748 * Wireless MESH & HWMP sysctl config.
2749 */
2750 const char wlan_sysctl_name[] = "net.wlan.";
2751
2752 static const char *wlan_sysctl[] = {
2753 "mesh.retrytimeout",
2754 "mesh.holdingtimeout",
2755 "mesh.confirmtimeout",
2756 "mesh.maxretries",
2757 "hwmp.targetonly",
2758 "hwmp.replyforward",
2759 "hwmp.pathlifetime",
2760 "hwmp.roottimeout",
2761 "hwmp.rootint",
2762 "hwmp.rannint",
2763 "hwmp.inact",
2764 };
2765
2766 int32_t
wlan_do_sysctl(struct wlan_config * cfg,enum wlan_syscl which,int set)2767 wlan_do_sysctl(struct wlan_config *cfg, enum wlan_syscl which, int set)
2768 {
2769 char mib_name[100];
2770 int val, sval;
2771 size_t len, vlen;
2772
2773 if (set) {
2774 vlen = sizeof(sval);
2775 switch (which) {
2776 case WLAN_MESH_RETRY_TO:
2777 sval = cfg->mesh_retryto;
2778 break;
2779 case WLAN_MESH_HOLDING_TO:
2780 sval = cfg->mesh_holdingto;
2781 break;
2782 case WLAN_MESH_CONFIRM_TO:
2783 sval = cfg->mesh_confirmto;
2784 break;
2785 case WLAN_MESH_MAX_RETRIES:
2786 sval = cfg->mesh_maxretries;
2787 break;
2788 case WLAN_HWMP_TARGET_ONLY:
2789 sval = cfg->hwmp_targetonly;
2790 break;
2791 case WLAN_HWMP_REPLY_FORWARD:
2792 sval = cfg->hwmp_replyforward;
2793 break;
2794 case WLAN_HWMP_PATH_LIFETIME:
2795 sval = cfg->hwmp_pathlifetime;
2796 break;
2797 case WLAN_HWMP_ROOT_TO:
2798 sval = cfg->hwmp_roottimeout;
2799 break;
2800 case WLAN_HWMP_ROOT_INT:
2801 sval = cfg->hwmp_rootint;
2802 break;
2803 case WLAN_HWMP_RANN_INT:
2804 sval = cfg->hwmp_rannint;
2805 break;
2806 case WLAN_HWMP_INACTIVITY_TO:
2807 sval = cfg->hwmp_inact;
2808 break;
2809 default:
2810 return (-1);
2811 }
2812 } else {
2813 if (which >= WLAN_SYSCTL_MAX)
2814 return (-1);
2815 vlen = 0;
2816 }
2817
2818 strlcpy(mib_name, wlan_sysctl_name, sizeof(mib_name));
2819 strlcat(mib_name, wlan_sysctl[which], sizeof(mib_name));
2820 len = sizeof (val);
2821
2822 if (sysctlbyname(mib_name, &val, &len, (set? &sval : NULL), vlen) < 0) {
2823 syslog(LOG_ERR, "sysctl(%s) failed - %s", mib_name,
2824 strerror(errno));
2825 return (-1);
2826 }
2827
2828 switch (which) {
2829 case WLAN_MESH_RETRY_TO:
2830 cfg->mesh_retryto = val;
2831 break;
2832 case WLAN_MESH_HOLDING_TO:
2833 cfg->mesh_holdingto = val;
2834 break;
2835 case WLAN_MESH_CONFIRM_TO:
2836 cfg->mesh_confirmto = val;
2837 break;
2838 case WLAN_MESH_MAX_RETRIES:
2839 cfg->mesh_maxretries = val;
2840 break;
2841 case WLAN_HWMP_TARGET_ONLY:
2842 cfg->hwmp_targetonly = val;
2843 break;
2844 case WLAN_HWMP_REPLY_FORWARD:
2845 cfg->hwmp_replyforward = val;
2846 break;
2847 case WLAN_HWMP_PATH_LIFETIME:
2848 cfg->hwmp_pathlifetime = val;
2849 break;
2850 case WLAN_HWMP_ROOT_TO:
2851 cfg->hwmp_roottimeout = val;
2852 break;
2853 case WLAN_HWMP_ROOT_INT:
2854 cfg->hwmp_rootint = val;
2855 break;
2856 case WLAN_HWMP_RANN_INT:
2857 cfg->hwmp_rannint = val;
2858 break;
2859 case WLAN_HWMP_INACTIVITY_TO:
2860 cfg->hwmp_inact = val;
2861 break;
2862 default:
2863 /* NOTREACHED */
2864 abort();
2865 }
2866
2867 return (0);
2868 }
2869
2870 int
wlan_mesh_config_get(struct wlan_iface * wif,int which)2871 wlan_mesh_config_get(struct wlan_iface *wif, int which)
2872 {
2873 int op, val = 0;
2874 size_t argsize = 0;
2875 uint8_t data[32], *pd = NULL;
2876
2877 switch (which) {
2878 case LEAF_wlanMeshTTL:
2879 op = IEEE80211_IOC_MESH_TTL;
2880 break;
2881 case LEAF_wlanMeshPeeringEnabled:
2882 op = IEEE80211_IOC_MESH_AP;
2883 break;
2884 case LEAF_wlanMeshForwardingEnabled:
2885 op = IEEE80211_IOC_MESH_FWRD;
2886 break;
2887 case LEAF_wlanMeshMetric:
2888 op = IEEE80211_IOC_MESH_PR_METRIC;
2889 pd = data;
2890 argsize = sizeof(data);
2891 break;
2892 case LEAF_wlanMeshPath:
2893 op = IEEE80211_IOC_MESH_PR_PATH;
2894 pd = data;
2895 argsize = sizeof(data);
2896 break;
2897 case LEAF_wlanMeshRoutesFlush:
2898 return (0);
2899 default:
2900 return (-1);
2901 }
2902
2903 if (wlan_ioctl(wif->wname, op, &val, pd, &argsize, 0) < 0)
2904 return (-1);
2905
2906 switch (which) {
2907 case LEAF_wlanMeshTTL:
2908 wif->mesh_ttl = val;
2909 break;
2910 case LEAF_wlanMeshPeeringEnabled:
2911 if (val)
2912 wif->mesh_peering = wlanMeshPeeringEnabled_true;
2913 else
2914 wif->mesh_peering = wlanMeshPeeringEnabled_false;
2915 break;
2916 case LEAF_wlanMeshForwardingEnabled:
2917 if (val)
2918 wif->mesh_forwarding = wlanMeshForwardingEnabled_true;
2919 else
2920 wif->mesh_forwarding = wlanMeshForwardingEnabled_false;
2921 break;
2922 case LEAF_wlanMeshMetric:
2923 data[argsize] = '\0';
2924 if (strcmp(data, "AIRTIME") == 0)
2925 wif->mesh_metric = wlanMeshMetric_airtime;
2926 else
2927 wif->mesh_metric = wlanMeshMetric_unknown;
2928 break;
2929 case LEAF_wlanMeshPath:
2930 data[argsize] = '\0';
2931 if (strcmp(data, "HWMP") == 0)
2932 wif->mesh_path = wlanMeshPath_hwmp;
2933 else
2934 wif->mesh_path = wlanMeshPath_unknown;
2935 }
2936
2937 return (0);
2938 }
2939
2940 int
wlan_mesh_config_set(struct wlan_iface * wif,int which)2941 wlan_mesh_config_set(struct wlan_iface *wif, int which)
2942 {
2943 int op, val = 0;
2944 size_t argsize = 0;
2945 uint8_t data[32], *pd = NULL;
2946
2947 switch (which) {
2948 case LEAF_wlanMeshTTL:
2949 op = IEEE80211_IOC_MESH_TTL;
2950 val = wif->mesh_ttl;
2951 break;
2952 case LEAF_wlanMeshPeeringEnabled:
2953 op = IEEE80211_IOC_MESH_AP;
2954 if (wif->mesh_peering == wlanMeshPeeringEnabled_true)
2955 val = 1;
2956 break;
2957 case LEAF_wlanMeshForwardingEnabled:
2958 if (wif->mesh_forwarding == wlanMeshForwardingEnabled_true)
2959 val = 1;
2960 op = IEEE80211_IOC_MESH_FWRD;
2961 break;
2962 case LEAF_wlanMeshMetric:
2963 op = IEEE80211_IOC_MESH_PR_METRIC;
2964 if (wif->mesh_metric == wlanMeshMetric_airtime)
2965 strcpy(data, "AIRTIME");
2966 else
2967 return (-1);
2968 pd = data;
2969 argsize = sizeof(data);
2970 break;
2971 case LEAF_wlanMeshPath:
2972 op = IEEE80211_IOC_MESH_PR_PATH;
2973 if (wif->mesh_path == wlanMeshPath_hwmp)
2974 strcpy(data, "HWMP");
2975 else
2976 return (-1);
2977 pd = data;
2978 argsize = sizeof(data);
2979 break;
2980 default:
2981 return (-1);
2982 }
2983
2984 if (wlan_ioctl(wif->wname, op, &val, pd, &argsize, 1) < 0)
2985 return (-1);
2986
2987 return(0);
2988 }
2989
2990 int
wlan_mesh_flush_routes(struct wlan_iface * wif)2991 wlan_mesh_flush_routes(struct wlan_iface *wif)
2992 {
2993 int val = IEEE80211_MESH_RTCMD_FLUSH;
2994 size_t argsize = 0;
2995
2996 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, NULL,
2997 &argsize, 1) < 0)
2998 return (-1);
2999
3000 return (0);
3001 }
3002
3003 int
wlan_mesh_add_route(struct wlan_iface * wif,struct wlan_mesh_route * wmr)3004 wlan_mesh_add_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr)
3005 {
3006 int val = IEEE80211_MESH_RTCMD_ADD;
3007 size_t argsize = IEEE80211_ADDR_LEN;
3008
3009 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val,
3010 wmr->imroute.imr_dest, &argsize, 1) < 0)
3011 return (-1);
3012
3013 wmr->mroute_status = RowStatus_active;
3014
3015 return (0);
3016 }
3017
3018 int
wlan_mesh_del_route(struct wlan_iface * wif,struct wlan_mesh_route * wmr)3019 wlan_mesh_del_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr)
3020 {
3021 int val = IEEE80211_MESH_RTCMD_DELETE;
3022 size_t argsize = IEEE80211_ADDR_LEN;
3023
3024 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val,
3025 wmr->imroute.imr_dest, &argsize, 1) < 0)
3026 return (-1);
3027
3028 wmr->mroute_status = RowStatus_destroy;
3029
3030 return (0);
3031 }
3032
3033 int
wlan_mesh_get_routelist(struct wlan_iface * wif)3034 wlan_mesh_get_routelist(struct wlan_iface *wif)
3035 {
3036 int i, nroutes, val = IEEE80211_MESH_RTCMD_LIST;
3037 size_t argsize;
3038 struct ieee80211req_mesh_route routes[128];
3039 struct ieee80211req_mesh_route *rt;
3040 struct wlan_mesh_route *wmr;
3041
3042 argsize = sizeof(routes);
3043 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, routes,
3044 &argsize, 0) < 0) /* XXX: ENOMEM? */
3045 return (-1);
3046
3047 nroutes = argsize / sizeof(*rt);
3048 for (i = 0; i < nroutes; i++) {
3049 rt = routes + i;
3050 if ((wmr = wlan_mesh_new_route(rt->imr_dest)) == NULL)
3051 return (-1);
3052 memcpy(&wmr->imroute, rt, sizeof(*rt));
3053 wmr->mroute_status = RowStatus_active;
3054 if (wlan_mesh_add_rtentry(wif, wmr) < 0)
3055 wlan_mesh_free_route(wmr);
3056 }
3057
3058 return (0);
3059 }
3060
3061 int
wlan_hwmp_config_get(struct wlan_iface * wif,int which)3062 wlan_hwmp_config_get(struct wlan_iface *wif, int which)
3063 {
3064 int op, val = 0;
3065 size_t argsize = 0;
3066
3067 switch (which) {
3068 case LEAF_wlanHWMPRootMode:
3069 op = IEEE80211_IOC_HWMP_ROOTMODE;
3070 break;
3071 case LEAF_wlanHWMPMaxHops:
3072 op = IEEE80211_IOC_HWMP_MAXHOPS;
3073 break;
3074 default:
3075 return (-1);
3076 }
3077
3078 if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 0) < 0)
3079 return (-1);
3080
3081 switch (which) {
3082 case LEAF_wlanHWMPRootMode:
3083 switch (val) {
3084 case IEEE80211_HWMP_ROOTMODE_NORMAL:
3085 wif->hwmp_root_mode = wlanHWMPRootMode_normal;
3086 break;
3087 case IEEE80211_HWMP_ROOTMODE_PROACTIVE:
3088 wif->hwmp_root_mode = wlanHWMPRootMode_proactive;
3089 break;
3090 case IEEE80211_HWMP_ROOTMODE_RANN:
3091 wif->hwmp_root_mode = wlanHWMPRootMode_rann;
3092 break;
3093 case IEEE80211_HWMP_ROOTMODE_DISABLED:
3094 default:
3095 wif->hwmp_root_mode = wlanHWMPRootMode_disabled;
3096 break;
3097 }
3098 break;
3099 case LEAF_wlanHWMPMaxHops:
3100 wif->hwmp_max_hops = val;
3101 break;
3102 }
3103
3104 return (0);
3105 }
3106
3107 int
wlan_hwmp_config_set(struct wlan_iface * wif,int which)3108 wlan_hwmp_config_set(struct wlan_iface *wif, int which)
3109 {
3110 int op, val = 0;
3111 size_t argsize = 0;
3112
3113 switch (which) {
3114 case LEAF_wlanHWMPRootMode:
3115 op = IEEE80211_IOC_HWMP_ROOTMODE;
3116 switch (wif->hwmp_root_mode) {
3117 case wlanHWMPRootMode_disabled:
3118 val = IEEE80211_HWMP_ROOTMODE_DISABLED;
3119 break;
3120 case wlanHWMPRootMode_normal:
3121 val = IEEE80211_HWMP_ROOTMODE_NORMAL;
3122 break;
3123 case wlanHWMPRootMode_proactive:
3124 val = IEEE80211_HWMP_ROOTMODE_PROACTIVE;
3125 break;
3126 case wlanHWMPRootMode_rann:
3127 val = IEEE80211_HWMP_ROOTMODE_RANN;
3128 break;
3129 default:
3130 return (-1);
3131 }
3132 break;
3133 case LEAF_wlanHWMPMaxHops:
3134 op = IEEE80211_IOC_HWMP_MAXHOPS;
3135 val = wif->hwmp_max_hops;
3136 break;
3137 default:
3138 return (-1);
3139 }
3140
3141 if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 1) < 0)
3142 return (-1);
3143
3144 return (0);
3145 }
3146