xref: /freebsd/usr.sbin/bsnmpd/modules/snmp_wlan/wlan_snmp.c (revision b9f654b163bce26de79705e77b872427c9f2afa1)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2010 The FreeBSD Foundation
5  * All rights reserved.
6  *
7  * This software was developed by Shteryana Sotirova Shopova under
8  * sponsorship from the FreeBSD Foundation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD$
32  */
33 
34 #include <sys/queue.h>
35 #include <sys/socket.h>
36 #include <sys/types.h>
37 
38 #include <net/if.h>
39 #include <net/if_media.h>
40 #include <net/if_mib.h>
41 #include <net/if_types.h>
42 #include <net80211/ieee80211.h>
43 #include <net80211/ieee80211_ioctl.h>
44 
45 #include <errno.h>
46 #include <stdarg.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <syslog.h>
51 
52 #include <bsnmp/snmpmod.h>
53 #include <bsnmp/snmp_mibII.h>
54 
55 #define	SNMPTREE_TYPES
56 #include "wlan_tree.h"
57 #include "wlan_snmp.h"
58 #include "wlan_oid.h"
59 
60 static struct lmodule *wlan_module;
61 
62 /* For the registration. */
63 static const struct asn_oid oid_wlan = OIDX_begemotWlan;
64 /* The registration. */
65 static uint reg_wlan;
66 
67 /* Periodic timer for polling the module's data. */
68 static void *wlan_data_timer;
69 
70 /*
71  * Poll data from kernel every 15 minutes unless explicitly requested by an
72  * SNMP client.
73  * XXX: make that configurable.
74  */
75 static int wlan_poll_ticks = (15 * 60) * 100;
76 
77 /* The age of each table. */
78 #define	WLAN_LIST_MAXAGE	5
79 
80 static time_t wlan_iflist_age;
81 static time_t wlan_peerlist_age;
82 static time_t wlan_chanlist_age;
83 static time_t wlan_roamlist_age;
84 static time_t wlan_tx_paramlist_age;
85 static time_t wlan_scanlist_age;
86 static time_t wlan_maclist_age;
87 static time_t wlan_mrlist_age;
88 
89 /*
90  * The list of all virtual wireless interfaces - sorted by name.
91  */
92 SLIST_HEAD(wlan_ifaces, wlan_iface);
93 static struct wlan_ifaces wlan_ifaces = SLIST_HEAD_INITIALIZER(wlan_ifaces);
94 
95 static struct wlan_config wlan_config;
96 
97 /* Forward declarations */
98 static int	bits_get(struct snmp_value *, const u_char *, ssize_t);
99 
100 static int	wlan_add_wif(struct wlan_iface *);
101 static void	wlan_delete_wif(struct wlan_iface *);
102 static int	wlan_attach_newif(struct mibif *);
103 static int	wlan_iface_create(struct wlan_iface *);
104 static int	wlan_iface_destroy(struct wlan_iface *);
105 static struct wlan_iface *	wlan_new_wif(char *);
106 
107 static void	wlan_free_interface(struct wlan_iface *);
108 static void	wlan_free_iflist(void);
109 static void	wlan_free_peerlist(struct wlan_iface *);
110 static void	wlan_scan_free_results(struct wlan_iface *);
111 static void	wlan_mac_free_maclist(struct wlan_iface *);
112 static void	wlan_mesh_free_routes(struct wlan_iface *);
113 
114 static int	wlan_update_interface(struct wlan_iface *);
115 static void	wlan_update_interface_list(void);
116 static void	wlan_update_peers(void);
117 static void	wlan_update_channels(void);
118 static void	wlan_update_roam_params(void);
119 static void	wlan_update_tx_params(void);
120 static void	wlan_scan_update_results(void);
121 static void	wlan_mac_update_aclmacs(void);
122 static void	wlan_mesh_update_routes(void);
123 
124 static struct wlan_iface *	wlan_find_interface(const char *);
125 static struct wlan_peer *	wlan_find_peer(struct wlan_iface *, uint8_t *);
126 static struct ieee80211_channel*	wlan_find_channel(struct wlan_iface *,
127     uint32_t);
128 static struct wlan_scan_result *	wlan_scan_find_result(struct wlan_iface *,
129     uint8_t *, uint8_t *);
130 static struct wlan_mac_mac *		wlan_mac_find_mac(struct wlan_iface *,
131     uint8_t *);
132 static struct wlan_mesh_route *		wlan_mesh_find_route(struct wlan_iface *,
133     uint8_t *);
134 
135 static struct wlan_iface *	wlan_first_interface(void);
136 static struct wlan_iface *	wlan_next_interface(struct wlan_iface *);
137 static struct wlan_iface *	wlan_mesh_first_interface(void);
138 static struct wlan_iface *	wlan_mesh_next_interface(struct wlan_iface *);
139 
140 static struct wlan_iface *	wlan_get_interface(const struct asn_oid *, uint);
141 static struct wlan_iface *	wlan_get_snmp_interface(const struct asn_oid *,
142     uint);
143 static struct wlan_peer *	wlan_get_peer(const struct asn_oid *, uint,
144     struct wlan_iface **);
145 static struct ieee80211_channel *wlan_get_channel(const struct asn_oid *, uint,
146     struct wlan_iface **);
147 static struct ieee80211_roamparam *wlan_get_roam_param(const struct asn_oid *,
148     uint, struct wlan_iface **);
149 static struct ieee80211_txparam *wlan_get_tx_param(const struct asn_oid *,
150     uint, struct wlan_iface **, uint32_t *);
151 static struct wlan_scan_result *wlan_get_scanr(const struct asn_oid *, uint,
152     struct wlan_iface **);
153 static struct wlan_mac_mac *	wlan_get_acl_mac(const struct asn_oid *,
154     uint, struct wlan_iface **);
155 static struct wlan_iface *	wlan_mesh_get_iface(const struct asn_oid *, uint);
156 static struct wlan_peer *	wlan_mesh_get_peer(const struct asn_oid *, uint,
157     struct wlan_iface **);
158 static struct wlan_mesh_route *	wlan_mesh_get_route(const struct asn_oid *,
159     uint, struct wlan_iface **);
160 
161 static struct wlan_iface *	wlan_get_next_interface(const struct asn_oid *,
162     uint);
163 static struct wlan_iface *	wlan_get_next_snmp_interface(const struct
164     asn_oid *, uint);
165 static struct wlan_peer *	wlan_get_next_peer(const struct asn_oid *, uint,
166     struct wlan_iface **);
167 static struct ieee80211_channel *wlan_get_next_channel(const struct asn_oid *,
168     uint, struct wlan_iface **);
169 static struct ieee80211_roamparam *wlan_get_next_roam_param(const struct
170     asn_oid *, uint sub, struct wlan_iface **, uint32_t *);
171 static struct ieee80211_txparam *wlan_get_next_tx_param(const struct asn_oid *,
172     uint, struct wlan_iface **, uint32_t *);
173 static struct wlan_scan_result *wlan_get_next_scanr(const struct asn_oid *,
174     uint , struct wlan_iface **);
175 static struct wlan_mac_mac *	wlan_get_next_acl_mac(const struct asn_oid *,
176     uint, struct wlan_iface **);
177 static struct wlan_iface *	wlan_mesh_get_next_iface(const struct asn_oid *,
178     uint);
179 static struct wlan_peer *	wlan_mesh_get_next_peer(const struct asn_oid *,
180     uint, struct wlan_iface **);
181 static struct wlan_mesh_route *	wlan_mesh_get_next_route(const struct asn_oid *,
182     uint sub, struct wlan_iface **);
183 
184 static uint8_t *wlan_get_ifname(const struct asn_oid *, uint, uint8_t *);
185 static int	wlan_mac_index_decode(const struct asn_oid *, uint, char *,
186     uint8_t *);
187 static int	wlan_channel_index_decode(const struct asn_oid *, uint,
188     char *, uint32_t *);
189 static int	wlan_phy_index_decode(const struct asn_oid *, uint, char *,
190     uint32_t *);
191 static int wlan_scanr_index_decode(const struct asn_oid *oid, uint sub,
192     char *wname, uint8_t *ssid, uint8_t *bssid);
193 
194 static void	wlan_append_ifindex(struct asn_oid *, uint,
195     const struct wlan_iface *);
196 static void	wlan_append_mac_index(struct asn_oid *, uint, char *, uint8_t *);
197 static void	wlan_append_channel_index(struct asn_oid *, uint,
198     const struct wlan_iface *, const struct ieee80211_channel *);
199 static void	wlan_append_phy_index(struct asn_oid *, uint, char *, uint32_t);
200 static void	wlan_append_scanr_index(struct asn_oid *, uint, char *,
201     uint8_t *, uint8_t *);
202 
203 static int	wlan_acl_mac_set_status(struct snmp_context *,
204     struct snmp_value *, uint);
205 static int	wlan_mesh_route_set_status(struct snmp_context *,
206     struct snmp_value *, uint);
207 
208 static int32_t	wlan_get_channel_type(struct ieee80211_channel *);
209 static int	wlan_scan_compare_result(struct wlan_scan_result *,
210     struct wlan_scan_result *);
211 static int	wlan_mac_delete_mac(struct wlan_iface *, struct wlan_mac_mac *);
212 static int	wlan_mesh_delete_route(struct wlan_iface *,
213     struct wlan_mesh_route *);
214 
215 /*
216  * The module's GET/SET data hooks per each table or group of objects as
217  * required by bsnmpd(1).
218  */
219 int
220 op_wlan_iface(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
221     uint32_t iidx __unused, enum snmp_op op)
222 {
223 	int rc;
224 	char wname[IFNAMSIZ];
225 	struct wlan_iface *wif;
226 
227 	wlan_update_interface_list();
228 
229 	switch (op) {
230 	case SNMP_OP_GET:
231 		if ((wif = wlan_get_snmp_interface(&val->var, sub)) == NULL)
232 			return (SNMP_ERR_NOSUCHNAME);
233 		break;
234 
235 	case SNMP_OP_GETNEXT:
236 		if ((wif = wlan_get_next_snmp_interface(&val->var, sub)) == NULL)
237 			return (SNMP_ERR_NOSUCHNAME);
238 		wlan_append_ifindex(&val->var, sub, wif);
239 		break;
240 
241 	case SNMP_OP_SET:
242 		if ((wif = wlan_get_snmp_interface(&val->var, sub)) == NULL) {
243 			if (val->var.subs[sub - 1] != LEAF_wlanIfaceName)
244 				return (SNMP_ERR_NOSUCHNAME);
245 			if (wlan_get_ifname(&val->var, sub, wname) == NULL)
246 				return (SNMP_ERR_INCONS_VALUE);
247 			if ((wif = wlan_new_wif(wname)) == NULL)
248 				return (SNMP_ERR_GENERR);
249 			wif->internal = 1;
250 		}
251 		if (wif->status == RowStatus_active &&
252 		    val->var.subs[sub - 1] != LEAF_wlanIfaceStatus &&
253 		    val->var.subs[sub - 1] != LEAF_wlanIfaceState)
254 			return (SNMP_ERR_INCONS_VALUE);
255 
256 		switch (val->var.subs[sub - 1]) {
257 		case LEAF_wlanIfaceIndex:
258 			return (SNMP_ERR_NOT_WRITEABLE);
259 
260 		case LEAF_wlanIfaceName:
261 			if (val->v.octetstring.len >= IFNAMSIZ)
262 				return (SNMP_ERR_INCONS_VALUE);
263 			if ((ctx->scratch->ptr1 = malloc(IFNAMSIZ)) == NULL)
264 				return (SNMP_ERR_GENERR);
265 			strlcpy(ctx->scratch->ptr1, wif->wname, IFNAMSIZ);
266 			memcpy(wif->wname, val->v.octetstring.octets,
267 			    val->v.octetstring.len);
268 			wif->wname[val->v.octetstring.len] = '\0';
269 			return (SNMP_ERR_NOERROR);
270 
271 		case LEAF_wlanParentIfName:
272 			if (val->v.octetstring.len >= IFNAMSIZ)
273 				return (SNMP_ERR_INCONS_VALUE);
274 			if ((ctx->scratch->ptr1 = malloc(IFNAMSIZ)) == NULL)
275 				return (SNMP_ERR_GENERR);
276 			strlcpy(ctx->scratch->ptr1, wif->pname, IFNAMSIZ);
277 			memcpy(wif->pname, val->v.octetstring.octets,
278 			    val->v.octetstring.len);
279 			wif->pname[val->v.octetstring.len] = '\0';
280 			return (SNMP_ERR_NOERROR);
281 
282 		case LEAF_wlanIfaceOperatingMode:
283 			ctx->scratch->int1 = wif->mode;
284 			wif->mode = val->v.integer;
285 			return (SNMP_ERR_NOERROR);
286 
287 		case LEAF_wlanIfaceFlags:
288 			if (val->v.octetstring.len > sizeof(wif->flags))
289 				return (SNMP_ERR_INCONS_VALUE);
290 			ctx->scratch->ptr1 = malloc(sizeof(wif->flags));
291 			if (ctx->scratch->ptr1 == NULL)
292 				return (SNMP_ERR_GENERR);
293 			memcpy(ctx->scratch->ptr1, (uint8_t *)&wif->flags,
294 			    sizeof(wif->flags));
295 			memcpy((uint8_t *)&wif->flags, val->v.octetstring.octets,
296 			    sizeof(wif->flags));
297 			return (SNMP_ERR_NOERROR);
298 
299 		case LEAF_wlanIfaceBssid:
300 			if (val->v.octetstring.len != IEEE80211_ADDR_LEN)
301 				return (SNMP_ERR_INCONS_VALUE);
302 			ctx->scratch->ptr1 = malloc(IEEE80211_ADDR_LEN);
303 			if (ctx->scratch->ptr1 == NULL)
304 				return (SNMP_ERR_GENERR);
305 			memcpy(ctx->scratch->ptr1, wif->dbssid,
306 			    IEEE80211_ADDR_LEN);
307 			memcpy(wif->dbssid, val->v.octetstring.octets,
308 			    IEEE80211_ADDR_LEN);
309 			return (SNMP_ERR_NOERROR);
310 
311 		case LEAF_wlanIfaceLocalAddress:
312 			if (val->v.octetstring.len != IEEE80211_ADDR_LEN)
313 				return (SNMP_ERR_INCONS_VALUE);
314 			ctx->scratch->ptr1 = malloc(IEEE80211_ADDR_LEN);
315 			if (ctx->scratch->ptr1 == NULL)
316 				return (SNMP_ERR_GENERR);
317 			memcpy(ctx->scratch->ptr1, wif->dlmac,
318 			    IEEE80211_ADDR_LEN);
319 			memcpy(wif->dlmac, val->v.octetstring.octets,
320 			    IEEE80211_ADDR_LEN);
321 			return (SNMP_ERR_NOERROR);
322 
323 		case LEAF_wlanIfaceStatus:
324 			ctx->scratch->int1 = wif->status;
325 			wif->status = val->v.integer;
326 			if (wif->status == RowStatus_active) {
327 				rc = wlan_iface_create(wif); /* XXX */
328 				if (rc != SNMP_ERR_NOERROR) {
329 					wif->status = ctx->scratch->int1;
330 					return (rc);
331 				}
332 			} else if (wif->status == RowStatus_destroy)
333 				return (wlan_iface_destroy(wif));
334 			else
335 				wif->status = RowStatus_notReady;
336 			return (SNMP_ERR_NOERROR);
337 
338 		case LEAF_wlanIfaceState:
339 			ctx->scratch->int1 = wif->state;
340 			wif->state = val->v.integer;
341 			if (wif->status == RowStatus_active)
342 				if (wlan_config_state(wif, 1) < 0)
343 					return (SNMP_ERR_GENERR);
344 			return (SNMP_ERR_NOERROR);
345 		}
346 		abort();
347 
348 	case SNMP_OP_ROLLBACK:
349 		if ((wif = wlan_get_snmp_interface(&val->var, sub)) == NULL)
350 			return (SNMP_ERR_NOSUCHNAME);
351 		switch (val->var.subs[sub - 1]) {
352 		case LEAF_wlanIfaceName:
353 			strlcpy(wif->wname, ctx->scratch->ptr1, IFNAMSIZ);
354 			free(ctx->scratch->ptr1);
355 			break;
356 
357 		case LEAF_wlanParentIfName:
358 			strlcpy(wif->pname, ctx->scratch->ptr1, IFNAMSIZ);
359 			free(ctx->scratch->ptr1);
360 			break;
361 
362 		case LEAF_wlanIfaceOperatingMode:
363 			wif->mode = ctx->scratch->int1;
364 			break;
365 
366 		case LEAF_wlanIfaceFlags:
367 			memcpy((uint8_t *)&wif->flags, ctx->scratch->ptr1,
368 			    sizeof(wif->flags));
369 			free(ctx->scratch->ptr1);
370 			break;
371 
372 		case LEAF_wlanIfaceBssid:
373 			memcpy(wif->dbssid, ctx->scratch->ptr1,
374 			    IEEE80211_ADDR_LEN);
375 			free(ctx->scratch->ptr1);
376 			break;
377 
378 		case LEAF_wlanIfaceLocalAddress:
379 			memcpy(wif->dlmac, ctx->scratch->ptr1,
380 			    IEEE80211_ADDR_LEN);
381 			free(ctx->scratch->ptr1);
382 			break;
383 
384 		case LEAF_wlanIfaceStatus:
385 			wif->status = ctx->scratch->int1;
386 			if (ctx->scratch->int1 == RowStatus_active)
387 				return (SNMP_ERR_GENERR); /* XXX: FIXME */
388 			else if (wif->internal != 0)
389 				return (wlan_iface_destroy(wif));
390 			break;
391 
392 		case LEAF_wlanIfaceState:
393 			wif->state = ctx->scratch->int1;
394 			if (wif->status == RowStatus_active)
395 				if (wlan_config_state(wif, 1) < 0)
396 					return (SNMP_ERR_GENERR);
397 			break;
398 		}
399 		return (SNMP_ERR_NOERROR);
400 
401 	case SNMP_OP_COMMIT:
402 		switch (val->var.subs[sub - 1]) {
403 		case LEAF_wlanIfaceName:
404 		case LEAF_wlanParentIfName:
405 		case LEAF_wlanIfaceFlags:
406 		case LEAF_wlanIfaceBssid:
407 		case LEAF_wlanIfaceLocalAddress:
408 			free(ctx->scratch->ptr1);
409 			/* FALLTHROUGH */
410 		default:
411 			return (SNMP_ERR_NOERROR);
412 		}
413 	default:
414 		abort();
415 	}
416 
417 	switch (val->var.subs[sub - 1]) {
418 	case LEAF_wlanIfaceIndex:
419 		val->v.integer = wif->index;
420 		return (SNMP_ERR_NOERROR);
421 	case LEAF_wlanIfaceName:
422 		return (string_get(val, wif->wname, -1));
423 	case LEAF_wlanParentIfName:
424 		return (string_get(val, wif->pname, -1));
425 	case LEAF_wlanIfaceOperatingMode:
426 		val->v.integer = wif->mode;
427 		return (SNMP_ERR_NOERROR);
428 	case LEAF_wlanIfaceFlags:
429 		return (bits_get(val, (uint8_t *)&wif->flags,
430 		    sizeof(wif->flags)));
431 	case LEAF_wlanIfaceBssid:
432 		return (string_get(val, wif->dbssid, IEEE80211_ADDR_LEN));
433 	case LEAF_wlanIfaceLocalAddress:
434 		return (string_get(val, wif->dlmac, IEEE80211_ADDR_LEN));
435 	case LEAF_wlanIfaceStatus:
436 		val->v.integer = wif->status;
437 		return (SNMP_ERR_NOERROR);
438 	case LEAF_wlanIfaceState:
439 		val->v.integer = wif->state;
440 		return (SNMP_ERR_NOERROR);
441 	}
442 
443 	abort();
444 }
445 
446 int
447 op_wlan_if_parent(struct snmp_context *ctx __unused, struct snmp_value *val,
448     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
449 {
450 	struct wlan_iface *wif;
451 
452 	wlan_update_interface_list();
453 
454 	switch (op) {
455 	case SNMP_OP_GET:
456 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
457 			return (SNMP_ERR_NOSUCHNAME);
458 		break;
459 	case SNMP_OP_GETNEXT:
460 		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
461 			return (SNMP_ERR_NOSUCHNAME);
462 		wlan_append_ifindex(&val->var, sub, wif);
463 		break;
464 	case SNMP_OP_SET:
465 		return (SNMP_ERR_NOT_WRITEABLE);
466 	case SNMP_OP_COMMIT:
467 		/* FALLTHROUGH */
468 	case SNMP_OP_ROLLBACK:
469 		/* FALLTHROUGH */
470 	default:
471 		abort();
472 	}
473 
474 	switch (val->var.subs[sub - 1]) {
475 	case LEAF_wlanIfParentDriverCapabilities:
476 		return (bits_get(val, (uint8_t *)&wif->drivercaps,
477 		    sizeof(wif->drivercaps)));
478 	case LEAF_wlanIfParentCryptoCapabilities:
479 		return (bits_get(val, (uint8_t *)&wif->cryptocaps,
480 		    sizeof(wif->cryptocaps)));
481 	case LEAF_wlanIfParentHTCapabilities:
482 		return (bits_get(val, (uint8_t *)&wif->htcaps,
483 		    sizeof(wif->htcaps)));
484 	}
485 
486 	abort();
487 }
488 
489 int
490 op_wlan_iface_config(struct snmp_context *ctx, struct snmp_value *val,
491     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
492 {
493 	int intval, vlen, rc;
494 	char *strval;
495 	struct wlan_iface *wif;
496 
497 	wlan_update_interface_list();
498 
499 	switch (op) {
500 	case SNMP_OP_GET:
501 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
502 			return (SNMP_ERR_NOSUCHNAME);
503 		goto get_config;
504 
505 	case SNMP_OP_GETNEXT:
506 		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
507 			return (SNMP_ERR_NOSUCHNAME);
508 		wlan_append_ifindex(&val->var, sub, wif);
509 		goto get_config;
510 
511 	case SNMP_OP_SET:
512 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
513 			return (SNMP_ERR_NOSUCHNAME);
514 
515 		intval = val->v.integer;
516 		strval = NULL;
517 		vlen = 0;
518 
519 		/* Simple sanity checks & save old data. */
520 		switch (val->var.subs[sub - 1]) {
521 		case LEAF_wlanIfaceCountryCode:
522 			if (val->v.octetstring.len != WLAN_COUNTRY_CODE_SIZE)
523 				return (SNMP_ERR_INCONS_VALUE);
524 			break;
525 		case LEAF_wlanIfaceDesiredSsid:
526 			if (val->v.octetstring.len > IEEE80211_NWID_LEN)
527 				return (SNMP_ERR_INCONS_VALUE);
528 			break;
529 		case LEAF_wlanIfaceDesiredBssid:
530 			if (val->v.octetstring.len != IEEE80211_ADDR_LEN)
531 				return (SNMP_ERR_INCONS_VALUE);
532 			break;
533 		case LEAF_wlanIfacePacketBurst:
534 			ctx->scratch->int1 = wif->packet_burst;
535 			break;
536 		case LEAF_wlanIfaceRegDomain:
537 			ctx->scratch->int1 = wif->reg_domain;
538 			break;
539 		case LEAF_wlanIfaceDesiredChannel:
540 			ctx->scratch->int1 = wif->desired_channel;
541 			break;
542 		case LEAF_wlanIfaceDynamicFreqSelection:
543 			ctx->scratch->int1 = wif->dyn_frequency;
544 			break;
545 		case LEAF_wlanIfaceFastFrames:
546 			ctx->scratch->int1 = wif->fast_frames;
547 			break;
548 		case LEAF_wlanIfaceDturbo:
549 			ctx->scratch->int1 = wif->dturbo;
550 			break;
551 		case LEAF_wlanIfaceTxPower:
552 			ctx->scratch->int1 = wif->tx_power;
553 			break;
554 		case LEAF_wlanIfaceFragmentThreshold:
555 			ctx->scratch->int1 = wif->frag_threshold;
556 			break;
557 		case LEAF_wlanIfaceRTSThreshold:
558 			ctx->scratch->int1 = wif->rts_threshold;
559 			break;
560 		case LEAF_wlanIfaceWlanPrivacySubscribe:
561 			ctx->scratch->int1 = wif->priv_subscribe;
562 			break;
563 		case LEAF_wlanIfaceBgScan:
564 			ctx->scratch->int1 = wif->bg_scan;
565 			break;
566 		case LEAF_wlanIfaceBgScanIdle:
567 			ctx->scratch->int1 = wif->bg_scan_idle;
568 			break;
569 		case LEAF_wlanIfaceBgScanInterval:
570 			ctx->scratch->int1 = wif->bg_scan_interval;
571 			break;
572 		case LEAF_wlanIfaceBeaconMissedThreshold:
573 			ctx->scratch->int1 = wif->beacons_missed;
574 			break;
575 		case LEAF_wlanIfaceRoamingMode:
576 			ctx->scratch->int1 = wif->roam_mode;
577 			break;
578 		case LEAF_wlanIfaceDot11d:
579 			ctx->scratch->int1 = wif->dot11d;
580 			break;
581 		case LEAF_wlanIfaceDot11h:
582 			ctx->scratch->int1 = wif->dot11h;
583 			break;
584 		case LEAF_wlanIfaceDynamicWds:
585 			ctx->scratch->int1 = wif->dynamic_wds;
586 			break;
587 		case LEAF_wlanIfacePowerSave:
588 			ctx->scratch->int1 = wif->power_save;
589 			break;
590 		case LEAF_wlanIfaceApBridge:
591 			ctx->scratch->int1 = wif->ap_bridge;
592 			break;
593 		case LEAF_wlanIfaceBeaconInterval:
594 			ctx->scratch->int1 = wif->beacon_interval;
595 			break;
596 		case LEAF_wlanIfaceDtimPeriod:
597 			ctx->scratch->int1 = wif->dtim_period;
598 			break;
599 		case LEAF_wlanIfaceHideSsid:
600 			ctx->scratch->int1 = wif->hide_ssid;
601 			break;
602 		case LEAF_wlanIfaceInactivityProccess:
603 			ctx->scratch->int1 = wif->inact_process;
604 			break;
605 		case LEAF_wlanIfaceDot11gProtMode:
606 			ctx->scratch->int1 = wif->do11g_protect;
607 			break;
608 		case LEAF_wlanIfaceDot11gPureMode:
609 			ctx->scratch->int1 = wif->dot11g_pure;
610 			break;
611 		case LEAF_wlanIfaceDot11nPureMode:
612 			ctx->scratch->int1 = wif->dot11n_pure;
613 			break;
614 		case LEAF_wlanIfaceDot11nAmpdu:
615 			ctx->scratch->int1 = wif->ampdu;
616 			break;
617 		case LEAF_wlanIfaceDot11nAmpduDensity:
618 			ctx->scratch->int1 = wif->ampdu_density;
619 			break;
620 		case LEAF_wlanIfaceDot11nAmpduLimit:
621 			ctx->scratch->int1 = wif->ampdu_limit;
622 			break;
623 		case LEAF_wlanIfaceDot11nAmsdu:
624 			ctx->scratch->int1 = wif->amsdu;
625 			break;
626 		case LEAF_wlanIfaceDot11nAmsduLimit:
627 			ctx->scratch->int1 = wif->amsdu_limit;
628 			break;
629 		case LEAF_wlanIfaceDot11nHighThroughput:
630 			ctx->scratch->int1 = wif->ht_enabled;
631 			break;
632 		case LEAF_wlanIfaceDot11nHTCompatible:
633 			ctx->scratch->int1 = wif->ht_compatible;
634 			break;
635 		case LEAF_wlanIfaceDot11nHTProtMode:
636 			ctx->scratch->int1 = wif->ht_prot_mode;
637 			break;
638 		case LEAF_wlanIfaceDot11nRIFS:
639 			ctx->scratch->int1 = wif->rifs;
640 			break;
641 		case LEAF_wlanIfaceDot11nShortGI:
642 			ctx->scratch->int1 = wif->short_gi;
643 			break;
644 		case LEAF_wlanIfaceDot11nSMPSMode:
645 			ctx->scratch->int1 = wif->smps_mode;
646 			break;
647 		case LEAF_wlanIfaceTdmaSlot:
648 			ctx->scratch->int1 = wif->tdma_slot;
649 			break;
650 		case LEAF_wlanIfaceTdmaSlotCount:
651 			ctx->scratch->int1 = wif->tdma_slot_count;
652 			break;
653 		case LEAF_wlanIfaceTdmaSlotLength:
654 			ctx->scratch->int1 = wif->tdma_slot_length;
655 			break;
656 		case LEAF_wlanIfaceTdmaBeaconInterval:
657 			ctx->scratch->int1 = wif->tdma_binterval;
658 			break;
659 		default:
660 			abort();
661 		}
662 
663 		if (val->syntax != SNMP_SYNTAX_OCTETSTRING)
664 			goto set_config;
665 
666 		ctx->scratch->int1 = val->v.octetstring.len;
667 		ctx->scratch->ptr1 = malloc(val->v.octetstring.len + 1);
668 		if (ctx->scratch->ptr1 == NULL)
669 			return (SNMP_ERR_GENERR); /* XXX */
670 		if (val->var.subs[sub - 1] == LEAF_wlanIfaceDesiredSsid)
671 			strlcpy(ctx->scratch->ptr1, val->v.octetstring.octets,
672 			    val->v.octetstring.len + 1);
673 		else
674 			memcpy(ctx->scratch->ptr1, val->v.octetstring.octets,
675 			    val->v.octetstring.len);
676 		strval = val->v.octetstring.octets;
677 		vlen = val->v.octetstring.len;
678 		goto set_config;
679 
680 	case SNMP_OP_ROLLBACK:
681 		intval = ctx->scratch->int1;
682 		strval = NULL;
683 		vlen = 0;
684 
685 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
686 			return (SNMP_ERR_NOSUCHNAME);
687 		switch (val->var.subs[sub - 1]) {
688 		case LEAF_wlanIfaceCountryCode:
689 		case LEAF_wlanIfaceDesiredSsid:
690 		case LEAF_wlanIfaceDesiredBssid:
691 			strval = ctx->scratch->ptr1;
692 			vlen = ctx->scratch->int1;
693 			break;
694 		default:
695 			break;
696 		}
697 		goto set_config;
698 
699 	case SNMP_OP_COMMIT:
700 		switch (val->var.subs[sub - 1]) {
701 		case LEAF_wlanIfaceCountryCode:
702 		case LEAF_wlanIfaceDesiredSsid:
703 		case LEAF_wlanIfaceDesiredBssid:
704 			free(ctx->scratch->ptr1);
705 			/* FALLTHROUGH */
706 		default:
707 			return (SNMP_ERR_NOERROR);
708 		}
709 	}
710 	abort();
711 
712 get_config:
713 
714 	if (wlan_config_get_ioctl(wif, val->var.subs[sub - 1]) < 0)
715 		return (SNMP_ERR_GENERR);
716 
717 	switch (val->var.subs[sub - 1]) {
718 	case LEAF_wlanIfacePacketBurst:
719 		val->v.integer = wif->packet_burst;
720 		break;
721 	case LEAF_wlanIfaceCountryCode:
722 		return (string_get(val, wif->country_code,
723 		    WLAN_COUNTRY_CODE_SIZE));
724 	case LEAF_wlanIfaceRegDomain:
725 		val->v.integer = wif->reg_domain;
726 		break;
727 	case LEAF_wlanIfaceDesiredSsid:
728 		return (string_get(val, wif->desired_ssid, -1));
729 	case LEAF_wlanIfaceDesiredChannel:
730 		val->v.integer = wif->desired_channel;
731 		break;
732 	case LEAF_wlanIfaceDynamicFreqSelection:
733 		val->v.integer = wif->dyn_frequency;
734 		break;
735 	case LEAF_wlanIfaceFastFrames:
736 		val->v.integer = wif->fast_frames;
737 		break;
738 	case LEAF_wlanIfaceDturbo:
739 		val->v.integer = wif->dturbo;
740 		break;
741 	case LEAF_wlanIfaceTxPower:
742 		val->v.integer = wif->tx_power;
743 		break;
744 	case LEAF_wlanIfaceFragmentThreshold:
745 		val->v.integer = wif->frag_threshold;
746 		break;
747 	case LEAF_wlanIfaceRTSThreshold:
748 		val->v.integer = wif->rts_threshold;
749 		break;
750 	case LEAF_wlanIfaceWlanPrivacySubscribe:
751 		val->v.integer = wif->priv_subscribe;
752 		break;
753 	case LEAF_wlanIfaceBgScan:
754 		val->v.integer = wif->bg_scan;
755 		break;
756 	case LEAF_wlanIfaceBgScanIdle:
757 		val->v.integer = wif->bg_scan_idle;
758 		break;
759 	case LEAF_wlanIfaceBgScanInterval:
760 		val->v.integer = wif->bg_scan_interval;
761 		break;
762 	case LEAF_wlanIfaceBeaconMissedThreshold:
763 		val->v.integer = wif->beacons_missed;
764 		break;
765 	case LEAF_wlanIfaceDesiredBssid:
766 		return (string_get(val, wif->desired_bssid,
767 		    IEEE80211_ADDR_LEN));
768 	case LEAF_wlanIfaceRoamingMode:
769 		val->v.integer = wif->roam_mode;
770 		break;
771 	case LEAF_wlanIfaceDot11d:
772 		val->v.integer = wif->dot11d;
773 		break;
774 	case LEAF_wlanIfaceDot11h:
775 		val->v.integer = wif->dot11h;
776 		break;
777 	case LEAF_wlanIfaceDynamicWds:
778 		val->v.integer = wif->dynamic_wds;
779 		break;
780 	case LEAF_wlanIfacePowerSave:
781 		val->v.integer = wif->power_save;
782 		break;
783 	case LEAF_wlanIfaceApBridge:
784 		val->v.integer = wif->ap_bridge;
785 		break;
786 	case LEAF_wlanIfaceBeaconInterval:
787 		val->v.integer = wif->beacon_interval;
788 		break;
789 	case LEAF_wlanIfaceDtimPeriod:
790 		val->v.integer = wif->dtim_period;
791 		break;
792 	case LEAF_wlanIfaceHideSsid:
793 		val->v.integer = wif->hide_ssid;
794 		break;
795 	case LEAF_wlanIfaceInactivityProccess:
796 		val->v.integer = wif->inact_process;
797 		break;
798 	case LEAF_wlanIfaceDot11gProtMode:
799 		val->v.integer = wif->do11g_protect;
800 		break;
801 	case LEAF_wlanIfaceDot11gPureMode:
802 		val->v.integer = wif->dot11g_pure;
803 		break;
804 	case LEAF_wlanIfaceDot11nPureMode:
805 		val->v.integer = wif->dot11n_pure;
806 		break;
807 	case LEAF_wlanIfaceDot11nAmpdu:
808 		val->v.integer = wif->ampdu;
809 		break;
810 	case LEAF_wlanIfaceDot11nAmpduDensity:
811 		val->v.integer = wif->ampdu_density;
812 		break;
813 	case LEAF_wlanIfaceDot11nAmpduLimit:
814 		val->v.integer = wif->ampdu_limit;
815 		break;
816 	case LEAF_wlanIfaceDot11nAmsdu:
817 		val->v.integer = wif->amsdu;
818 		break;
819 	case LEAF_wlanIfaceDot11nAmsduLimit:
820 		val->v.integer = wif->amsdu_limit;
821 		break;
822 	case LEAF_wlanIfaceDot11nHighThroughput:
823 		val->v.integer = wif->ht_enabled;
824 		break;
825 	case LEAF_wlanIfaceDot11nHTCompatible:
826 		val->v.integer = wif->ht_compatible;
827 		break;
828 	case LEAF_wlanIfaceDot11nHTProtMode:
829 		val->v.integer = wif->ht_prot_mode;
830 		break;
831 	case LEAF_wlanIfaceDot11nRIFS:
832 		val->v.integer = wif->rifs;
833 		break;
834 	case LEAF_wlanIfaceDot11nShortGI:
835 		val->v.integer = wif->short_gi;
836 		break;
837 	case LEAF_wlanIfaceDot11nSMPSMode:
838 		val->v.integer = wif->smps_mode;
839 		break;
840 	case LEAF_wlanIfaceTdmaSlot:
841 		val->v.integer = wif->tdma_slot;
842 		break;
843 	case LEAF_wlanIfaceTdmaSlotCount:
844 		val->v.integer = wif->tdma_slot_count;
845 		break;
846 	case LEAF_wlanIfaceTdmaSlotLength:
847 		val->v.integer = wif->tdma_slot_length;
848 		break;
849 	case LEAF_wlanIfaceTdmaBeaconInterval:
850 		val->v.integer = wif->tdma_binterval;
851 		break;
852 	}
853 
854 	return (SNMP_ERR_NOERROR);
855 
856 set_config:
857 	rc = wlan_config_set_ioctl(wif, val->var.subs[sub - 1], intval,
858 	    strval, vlen);
859 
860 	if (op == SNMP_OP_ROLLBACK) {
861 		switch (val->var.subs[sub - 1]) {
862 		case LEAF_wlanIfaceCountryCode:
863 		case LEAF_wlanIfaceDesiredSsid:
864 		case LEAF_wlanIfaceDesiredBssid:
865 			free(ctx->scratch->ptr1);
866 			/* FALLTHROUGH */
867 		default:
868 			break;
869 		}
870 	}
871 
872 	if (rc < 0)
873 		return (SNMP_ERR_GENERR);
874 
875 	return (SNMP_ERR_NOERROR);
876 }
877 
878 int
879 op_wlan_if_peer(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
880     uint32_t iidx __unused, enum snmp_op op)
881 {
882 	struct wlan_peer *wip;
883 	struct wlan_iface *wif;
884 
885 	wlan_update_interface_list();
886 	wlan_update_peers();
887 
888 	switch (op) {
889 	case SNMP_OP_GET:
890 		if ((wip = wlan_get_peer(&val->var, sub, &wif)) == NULL)
891 			return (SNMP_ERR_NOSUCHNAME);
892 		break;
893 	case SNMP_OP_GETNEXT:
894 		if ((wip = wlan_get_next_peer(&val->var, sub, &wif)) == NULL)
895 			return (SNMP_ERR_NOSUCHNAME);
896 		wlan_append_mac_index(&val->var, sub, wif->wname, wip->pmac);
897 		break;
898 	case SNMP_OP_SET:
899 		if ((wip = wlan_get_peer(&val->var, sub, &wif)) == NULL)
900 			return (SNMP_ERR_NOSUCHNAME);
901 		if (val->var.subs[sub - 1] != LEAF_wlanIfacePeerVlanTag)
902 			return (SNMP_ERR_GENERR);
903 		ctx->scratch->int1 = wip->vlan;
904 		if (wlan_peer_set_vlan(wif, wip, val->v.integer) < 0)
905 			return (SNMP_ERR_GENERR);
906 		return (SNMP_ERR_NOERROR);
907 	case SNMP_OP_COMMIT:
908 		return (SNMP_ERR_NOERROR);
909 	case SNMP_OP_ROLLBACK:
910 		if ((wip = wlan_get_peer(&val->var, sub, &wif)) == NULL)
911 			return (SNMP_ERR_NOSUCHNAME);
912 		if (val->var.subs[sub - 1] != LEAF_wlanIfacePeerVlanTag)
913 			return (SNMP_ERR_GENERR);
914 		if (wlan_peer_set_vlan(wif, wip, ctx->scratch->int1) < 0)
915 			return (SNMP_ERR_GENERR);
916 		return (SNMP_ERR_NOERROR);
917 	default:
918 		abort();
919 	}
920 
921 	switch (val->var.subs[sub - 1]) {
922 	case LEAF_wlanIfacePeerAddress:
923 		return (string_get(val, wip->pmac, IEEE80211_ADDR_LEN));
924 	case LEAF_wlanIfacePeerAssociationId:
925 		val->v.integer = wip->associd;
926 		break;
927 	case LEAF_wlanIfacePeerVlanTag:
928 		val->v.integer = wip->vlan;
929 		break;
930 	case LEAF_wlanIfacePeerFrequency:
931 		val->v.integer = wip->frequency;
932 		break;
933 	case LEAF_wlanIfacePeerCurrentTXRate:
934 		val->v.integer = wip->txrate;
935 		break;
936 	case LEAF_wlanIfacePeerRxSignalStrength:
937 		val->v.integer = wip->rssi;
938 		break;
939 	case LEAF_wlanIfacePeerIdleTimer:
940 		val->v.integer = wip->idle;
941 		break;
942 	case LEAF_wlanIfacePeerTxSequenceNo:
943 		val->v.integer = wip->txseqs;
944 		break;
945 	case LEAF_wlanIfacePeerRxSequenceNo:
946 		val->v.integer = wip->rxseqs;
947 		break;
948 	case LEAF_wlanIfacePeerTxPower:
949 		val->v.integer = wip->txpower;
950 		break;
951 	case LEAF_wlanIfacePeerCapabilities:
952 		return (bits_get(val, (uint8_t *)&wip->capinfo,
953 		    sizeof(wip->capinfo)));
954 	case LEAF_wlanIfacePeerFlags:
955 		return (bits_get(val, (uint8_t *)&wip->state,
956 		    sizeof(wip->state)));
957 	default:
958 		abort();
959 	}
960 
961 	return (SNMP_ERR_NOERROR);
962 }
963 
964 int
965 op_wlan_channels(struct snmp_context *ctx __unused, struct snmp_value *val,
966     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
967 {
968 	int32_t bits;
969 	struct ieee80211_channel *channel;
970 	struct wlan_iface *wif;
971 
972 	wlan_update_interface_list();
973 	wlan_update_channels();
974 
975 	switch (op) {
976 	case SNMP_OP_GET:
977 		if ((channel = wlan_get_channel(&val->var, sub, &wif)) == NULL)
978 			return (SNMP_ERR_NOSUCHNAME);
979 		break;
980 	case SNMP_OP_GETNEXT:
981 		channel = wlan_get_next_channel(&val->var, sub, &wif);
982 		if (channel == NULL || wif == NULL)
983 			return (SNMP_ERR_NOSUCHNAME);
984 		wlan_append_channel_index(&val->var, sub, wif, channel);
985 		break;
986 	case SNMP_OP_SET:
987 		return (SNMP_ERR_NOT_WRITEABLE);
988 	case SNMP_OP_COMMIT:
989 		/* FALLTHROUGH */
990 	case SNMP_OP_ROLLBACK:
991 		/* FALLTHROUGH */
992 	default:
993 		abort();
994 	}
995 
996 	switch (val->var.subs[sub - 1]) {
997 	case LEAF_wlanIfaceChannelIeeeId:
998 		val->v.integer = channel->ic_ieee;
999 		break;
1000 	case LEAF_wlanIfaceChannelType:
1001 		val->v.integer = wlan_get_channel_type(channel);
1002 		break;
1003 	case LEAF_wlanIfaceChannelFlags:
1004 		bits = wlan_channel_flags_to_snmp(channel->ic_flags);
1005 		return (bits_get(val, (uint8_t *)&bits, sizeof(bits)));
1006 	case LEAF_wlanIfaceChannelFrequency:
1007 		val->v.integer = channel->ic_freq;
1008 		break;
1009 	case LEAF_wlanIfaceChannelMaxRegPower:
1010 		val->v.integer = channel->ic_maxregpower;
1011 		break;
1012 	case LEAF_wlanIfaceChannelMaxTxPower:
1013 		val->v.integer = channel->ic_maxpower;
1014 		break;
1015 	case LEAF_wlanIfaceChannelMinTxPower:
1016 		val->v.integer = channel->ic_minpower;
1017 		break;
1018 	case LEAF_wlanIfaceChannelState:
1019 		bits = wlan_channel_state_to_snmp(channel->ic_state);
1020 		return (bits_get(val, (uint8_t *)&bits, sizeof(bits)));
1021 	case LEAF_wlanIfaceChannelHTExtension:
1022 		val->v.integer = channel->ic_extieee;
1023 		break;
1024 	case LEAF_wlanIfaceChannelMaxAntennaGain:
1025 		val->v.integer = channel->ic_maxantgain;
1026 		break;
1027 	}
1028 
1029 	return (SNMP_ERR_NOERROR);
1030 }
1031 
1032 int
1033 op_wlan_roam_params(struct snmp_context *ctx __unused, struct snmp_value *val,
1034     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1035 {
1036 	uint32_t phy;
1037 	struct ieee80211_roamparam *rparam;
1038 	struct wlan_iface *wif;
1039 
1040 	wlan_update_interface_list();
1041 	wlan_update_roam_params();
1042 
1043 	switch (op) {
1044 	case SNMP_OP_GET:
1045 		rparam = wlan_get_roam_param(&val->var, sub, &wif);
1046 		if (rparam == NULL)
1047 			return (SNMP_ERR_NOSUCHNAME);
1048 		break;
1049 	case SNMP_OP_GETNEXT:
1050 		rparam = wlan_get_next_roam_param(&val->var, sub, &wif, &phy);
1051 		if (rparam == NULL || wif == NULL)
1052 			return (SNMP_ERR_NOSUCHNAME);
1053 		wlan_append_phy_index(&val->var, sub, wif->wname, phy);
1054 		break;
1055 	case SNMP_OP_SET:
1056 		return (SNMP_ERR_NOT_WRITEABLE);
1057 	case SNMP_OP_COMMIT:
1058 		/* FALLTHROUGH */
1059 	case SNMP_OP_ROLLBACK:
1060 		/* FALLTHROUGH */
1061 	default:
1062 		abort();
1063 	}
1064 
1065 	switch (val->var.subs[sub - 1]) {
1066 	case LEAF_wlanIfRoamRxSignalStrength:
1067 		val->v.integer = rparam->rssi/2;
1068 		break;
1069 	case LEAF_wlanIfRoamTxRateThreshold:
1070 		val->v.integer = rparam->rate/2;
1071 		break;
1072 	default:
1073 		abort();
1074 	}
1075 
1076 	return (SNMP_ERR_NOERROR);
1077 }
1078 
1079 int
1080 op_wlan_tx_params(struct snmp_context *ctx, struct snmp_value *val,
1081     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1082 {
1083 	uint32_t phy;
1084 	struct ieee80211_txparam *txparam;
1085 	struct wlan_iface *wif;
1086 
1087 	wlan_update_interface_list();
1088 	wlan_update_tx_params();
1089 
1090 	switch (op) {
1091 	case SNMP_OP_GET:
1092 		txparam = wlan_get_tx_param(&val->var, sub, &wif, &phy);
1093 		if (txparam == NULL)
1094 			return (SNMP_ERR_NOSUCHNAME);
1095 		goto get_txparams;
1096 
1097 	case SNMP_OP_GETNEXT:
1098 		txparam = wlan_get_next_tx_param(&val->var, sub, &wif, &phy);
1099 		if (txparam == NULL || wif == NULL)
1100 			return (SNMP_ERR_NOSUCHNAME);
1101 		wlan_append_phy_index(&val->var, sub, wif->wname, phy);
1102 		goto get_txparams;
1103 
1104 	case SNMP_OP_SET:
1105 		txparam = wlan_get_tx_param(&val->var, sub, &wif, &phy);
1106 		if (txparam == NULL || wif == NULL)
1107 			return (SNMP_ERR_NOSUCHNAME);
1108 		switch (val->var.subs[sub - 1]) {
1109 		case LEAF_wlanIfTxUnicastRate:
1110 			ctx->scratch->int1 = txparam->ucastrate;
1111 			txparam->ucastrate = val->v.integer * 2;
1112 			break;
1113 		case LEAF_wlanIfTxMcastRate:
1114 			ctx->scratch->int1 = txparam->mcastrate;
1115 			txparam->mcastrate = val->v.integer * 2;
1116 			break;
1117 		case LEAF_wlanIfTxMgmtRate:
1118 			ctx->scratch->int1 = txparam->mgmtrate;
1119 			txparam->mgmtrate = val->v.integer * 2;
1120 			break;
1121 		case LEAF_wlanIfTxMaxRetryCount:
1122 			ctx->scratch->int1 = txparam->maxretry;
1123 			txparam->maxretry = val->v.integer;
1124 			break;
1125 		default:
1126 			abort();
1127 		}
1128 		if (wlan_set_tx_params(wif, phy) < 0)
1129 			return (SNMP_ERR_GENERR);
1130 		return (SNMP_ERR_NOERROR);
1131 
1132 	case SNMP_OP_COMMIT:
1133 		return (SNMP_ERR_NOERROR);
1134 
1135 	case SNMP_OP_ROLLBACK:
1136 		txparam = wlan_get_tx_param(&val->var, sub, &wif, &phy);
1137 		if (txparam == NULL || wif == NULL)
1138 			return (SNMP_ERR_NOSUCHNAME);
1139 		switch (val->var.subs[sub - 1]) {
1140 		case LEAF_wlanIfTxUnicastRate:
1141 			txparam->ucastrate = ctx->scratch->int1;
1142 			break;
1143 		case LEAF_wlanIfTxMcastRate:
1144 			txparam->mcastrate = ctx->scratch->int1;
1145 			break;
1146 		case LEAF_wlanIfTxMgmtRate:
1147 			txparam->mgmtrate = ctx->scratch->int1;
1148 			break;
1149 		case LEAF_wlanIfTxMaxRetryCount:
1150 			txparam->maxretry = ctx->scratch->int1;
1151 			break;
1152 		default:
1153 			abort();
1154 		}
1155 		if (wlan_set_tx_params(wif, phy) < 0)
1156 			return (SNMP_ERR_GENERR);
1157 		return (SNMP_ERR_NOERROR);
1158 	default:
1159 		abort();
1160 	}
1161 
1162 get_txparams:
1163 	switch (val->var.subs[sub - 1]) {
1164 	case LEAF_wlanIfTxUnicastRate:
1165 		val->v.integer = txparam->ucastrate / 2;
1166 		break;
1167 	case LEAF_wlanIfTxMcastRate:
1168 		val->v.integer = txparam->mcastrate / 2;
1169 		break;
1170 	case LEAF_wlanIfTxMgmtRate:
1171 		val->v.integer = txparam->mgmtrate / 2;
1172 		break;
1173 	case LEAF_wlanIfTxMaxRetryCount:
1174 		val->v.integer = txparam->maxretry;
1175 		break;
1176 	default:
1177 		abort();
1178 	}
1179 
1180 	return (SNMP_ERR_NOERROR);
1181 }
1182 
1183 int
1184 op_wlan_scan_config(struct snmp_context *ctx, struct snmp_value *val,
1185     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1186 {
1187 	struct wlan_iface *wif;
1188 
1189 	wlan_update_interface_list();
1190 
1191 	switch (op) {
1192 	case SNMP_OP_GET:
1193 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1194 			return (SNMP_ERR_NOSUCHNAME);
1195 		break;
1196 
1197 	case SNMP_OP_GETNEXT:
1198 		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
1199 			return (SNMP_ERR_NOSUCHNAME);
1200 		wlan_append_ifindex(&val->var, sub, wif);
1201 		break;
1202 
1203 	case SNMP_OP_SET:
1204 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1205 			return (SNMP_ERR_NOSUCHNAME);
1206 		if (wif->scan_status ==  wlanScanConfigStatus_running
1207 		    && val->var.subs[sub - 1] != LEAF_wlanScanConfigStatus)
1208 			return (SNMP_ERR_INCONS_VALUE);
1209 		switch (val->var.subs[sub - 1]) {
1210 		case LEAF_wlanScanFlags:
1211 			ctx->scratch->int1 = wif->scan_flags;
1212 			wif->scan_flags = val->v.integer;
1213 			break;
1214 		case LEAF_wlanScanDuration:
1215 			ctx->scratch->int1 = wif->scan_duration;
1216 			wif->scan_duration = val->v.integer;
1217 			break;
1218 		case LEAF_wlanScanMinChannelDwellTime:
1219 			ctx->scratch->int1 = wif->scan_mindwell;
1220 			wif->scan_mindwell = val->v.integer;
1221 			break;
1222 		case LEAF_wlanScanMaxChannelDwellTime:
1223 			ctx->scratch->int1 = wif->scan_maxdwell;
1224 			wif->scan_maxdwell = val->v.integer;
1225 			break;
1226 		case LEAF_wlanScanConfigStatus:
1227 			if (val->v.integer == wlanScanConfigStatus_running ||
1228 			    val->v.integer == wlanScanConfigStatus_cancel) {
1229 				ctx->scratch->int1 = wif->scan_status;
1230 				wif->scan_status = val->v.integer;
1231 				break;
1232 			}
1233 			return (SNMP_ERR_INCONS_VALUE);
1234 		}
1235 		return (SNMP_ERR_NOERROR);
1236 
1237 	case SNMP_OP_COMMIT:
1238 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1239 			return (SNMP_ERR_NOSUCHNAME);
1240 		if (val->var.subs[sub - 1] == LEAF_wlanScanConfigStatus)
1241 			if (wif->scan_status == wlanScanConfigStatus_running)
1242 				(void)wlan_set_scan_config(wif); /* XXX */
1243 		return (SNMP_ERR_NOERROR);
1244 
1245 	case SNMP_OP_ROLLBACK:
1246 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1247 			return (SNMP_ERR_NOSUCHNAME);
1248 		switch (val->var.subs[sub - 1]) {
1249 		case LEAF_wlanScanFlags:
1250 			wif->scan_flags = ctx->scratch->int1;
1251 			break;
1252 		case LEAF_wlanScanDuration:
1253 			wif->scan_duration = ctx->scratch->int1;
1254 			break;
1255 		case LEAF_wlanScanMinChannelDwellTime:
1256 			wif->scan_mindwell = ctx->scratch->int1;
1257 			break;
1258 		case LEAF_wlanScanMaxChannelDwellTime:
1259 			wif->scan_maxdwell = ctx->scratch->int1;
1260 			break;
1261 		case LEAF_wlanScanConfigStatus:
1262 			wif->scan_status = ctx->scratch->int1;
1263 			break;
1264 		}
1265 		return (SNMP_ERR_NOERROR);
1266 	default:
1267 		abort();
1268 	}
1269 
1270 	switch (val->var.subs[sub - 1]) {
1271 	case LEAF_wlanScanFlags:
1272 		val->v.integer = wif->scan_flags;
1273 		break;
1274 	case LEAF_wlanScanDuration:
1275 		val->v.integer = wif->scan_duration;
1276 		break;
1277 	case LEAF_wlanScanMinChannelDwellTime:
1278 		val->v.integer = wif->scan_mindwell;
1279 		break;
1280 	case LEAF_wlanScanMaxChannelDwellTime:
1281 		val->v.integer = wif->scan_maxdwell;
1282 		break;
1283 	case LEAF_wlanScanConfigStatus:
1284 		val->v.integer = wif->scan_status;
1285 		break;
1286 	}
1287 
1288 	return (SNMP_ERR_NOERROR);
1289 }
1290 
1291 int
1292 op_wlan_scan_results(struct snmp_context *ctx __unused, struct snmp_value *val,
1293     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1294 {
1295 	struct wlan_scan_result *sr;
1296 	struct wlan_iface *wif;
1297 
1298 	wlan_update_interface_list();
1299 	wlan_scan_update_results();
1300 
1301 	switch (op) {
1302 	case SNMP_OP_GET:
1303 		if ((sr = wlan_get_scanr(&val->var, sub, &wif)) == NULL)
1304 			return (SNMP_ERR_NOSUCHNAME);
1305 		break;
1306 
1307 	case SNMP_OP_GETNEXT:
1308 		if ((sr = wlan_get_next_scanr(&val->var, sub, &wif)) == NULL)
1309 			return (SNMP_ERR_NOSUCHNAME);
1310 		wlan_append_scanr_index(&val->var, sub, wif->wname, sr->ssid,
1311 		    sr->bssid);
1312 		break;
1313 
1314 	case SNMP_OP_SET:
1315 		return (SNMP_ERR_NOT_WRITEABLE);
1316 	case SNMP_OP_COMMIT:
1317 		/* FALLTHROUGH */
1318 	case SNMP_OP_ROLLBACK:
1319 		/* FALLTHROUGH */
1320 	default:
1321 		abort();
1322 	}
1323 
1324 	switch (val->var.subs[sub - 1]) {
1325 	case LEAF_wlanScanResultID:
1326 		return (string_get(val, sr->ssid, -1));
1327 	case LEAF_wlanScanResultBssid:
1328 		return (string_get(val, sr->bssid, IEEE80211_ADDR_LEN));
1329 	case LEAF_wlanScanResultChannel:
1330 		val->v.integer = sr->opchannel; /* XXX */
1331 		break;
1332 	case LEAF_wlanScanResultRate:
1333 		val->v.integer = sr->rssi;
1334 		break;
1335 	case LEAF_wlanScanResultNoise:
1336 		val->v.integer = sr->noise;
1337 		break;
1338 	case LEAF_wlanScanResultBeaconInterval:
1339 		val->v.integer = sr->bintval;
1340 		break;
1341 	case LEAF_wlanScanResultCapabilities:
1342 		return (bits_get(val, &sr->capinfo, sizeof(sr->capinfo)));
1343 	default:
1344 		abort();
1345 	}
1346 
1347 	return (SNMP_ERR_NOERROR);
1348 }
1349 
1350 int
1351 op_wlan_iface_stats(struct snmp_context *ctx __unused, struct snmp_value *val,
1352     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1353 {
1354 	struct wlan_iface *wif;
1355 
1356 	wlan_update_interface_list();
1357 
1358 	switch (op) {
1359 	case SNMP_OP_GET:
1360 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1361 			return (SNMP_ERR_NOSUCHNAME);
1362 		break;
1363 	case SNMP_OP_GETNEXT:
1364 		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
1365 			return (SNMP_ERR_NOSUCHNAME);
1366 		wlan_append_ifindex(&val->var, sub, wif);
1367 		break;
1368 	case SNMP_OP_SET:
1369 		/* XXX: LEAF_wlanStatsReset */
1370 		return (SNMP_ERR_NOT_WRITEABLE);
1371 	case SNMP_OP_COMMIT:
1372 		/* FALLTHROUGH */
1373 	case SNMP_OP_ROLLBACK:
1374 		/* FALLTHROUGH */
1375 	default:
1376 		abort();
1377 	}
1378 
1379 	if (wlan_get_stats(wif) < 0)
1380 		return (SNMP_ERR_GENERR);
1381 
1382 	switch (val->var.subs[sub - 1]) {
1383 	case LEAF_wlanStatsRxBadVersion:
1384 		val->v.uint32 = wif->stats.is_rx_badversion;
1385 		break;
1386 	case LEAF_wlanStatsRxTooShort:
1387 		val->v.uint32 = wif->stats.is_rx_tooshort;
1388 		break;
1389 	case LEAF_wlanStatsRxWrongBssid:
1390 		val->v.uint32 = wif->stats.is_rx_wrongbss;
1391 		break;
1392 	case LEAF_wlanStatsRxDiscardedDups:
1393 		val->v.uint32 = wif->stats.is_rx_dup;
1394 		break;
1395 	case LEAF_wlanStatsRxWrongDir:
1396 		val->v.uint32 = wif->stats.is_rx_wrongdir;
1397 		break;
1398 	case LEAF_wlanStatsRxDiscardMcastEcho:
1399 		val->v.uint32 = wif->stats.is_rx_mcastecho;
1400 		break;
1401 	case LEAF_wlanStatsRxDiscardNoAssoc:
1402 		val->v.uint32 = wif->stats.is_rx_notassoc;
1403 		break;
1404 	case LEAF_wlanStatsRxWepNoPrivacy:
1405 		val->v.uint32 = wif->stats.is_rx_noprivacy;
1406 		break;
1407 	case LEAF_wlanStatsRxWepUnencrypted:
1408 		val->v.uint32 = wif->stats.is_rx_unencrypted;
1409 		break;
1410 	case LEAF_wlanStatsRxWepFailed:
1411 		val->v.uint32 = wif->stats.is_rx_wepfail;
1412 		break;
1413 	case LEAF_wlanStatsRxDecapsulationFailed:
1414 		val->v.uint32 = wif->stats.is_rx_decap;
1415 		break;
1416 	case LEAF_wlanStatsRxDiscardMgmt:
1417 		val->v.uint32 = wif->stats.is_rx_mgtdiscard;
1418 		break;
1419 	case LEAF_wlanStatsRxControl:
1420 		val->v.uint32 = wif->stats.is_rx_ctl;
1421 		break;
1422 	case LEAF_wlanStatsRxBeacon:
1423 		val->v.uint32 = wif->stats.is_rx_beacon;
1424 		break;
1425 	case LEAF_wlanStatsRxRateSetTooBig:
1426 		val->v.uint32 = wif->stats.is_rx_rstoobig;
1427 		break;
1428 	case LEAF_wlanStatsRxElemMissing:
1429 		val->v.uint32 = wif->stats.is_rx_elem_missing;
1430 		break;
1431 	case LEAF_wlanStatsRxElemTooBig:
1432 		val->v.uint32 = wif->stats.is_rx_elem_toobig;
1433 		break;
1434 	case LEAF_wlanStatsRxElemTooSmall:
1435 		val->v.uint32 = wif->stats.is_rx_elem_toosmall;
1436 		break;
1437 	case LEAF_wlanStatsRxElemUnknown:
1438 		val->v.uint32 = wif->stats.is_rx_elem_unknown;
1439 		break;
1440 	case LEAF_wlanStatsRxChannelMismatch:
1441 		val->v.uint32 = wif->stats.is_rx_chanmismatch;
1442 		break;
1443 	case LEAF_wlanStatsRxDropped:
1444 		val->v.uint32 = wif->stats.is_rx_nodealloc;
1445 		break;
1446 	case LEAF_wlanStatsRxSsidMismatch:
1447 		val->v.uint32 = wif->stats.is_rx_ssidmismatch;
1448 		break;
1449 	case LEAF_wlanStatsRxAuthNotSupported:
1450 		val->v.uint32 = wif->stats.is_rx_auth_unsupported;
1451 		break;
1452 	case LEAF_wlanStatsRxAuthFailed:
1453 		val->v.uint32 = wif->stats.is_rx_auth_fail;
1454 		break;
1455 	case LEAF_wlanStatsRxAuthCM:
1456 		val->v.uint32 = wif->stats.is_rx_auth_countermeasures;
1457 		break;
1458 	case LEAF_wlanStatsRxAssocWrongBssid:
1459 		val->v.uint32 = wif->stats.is_rx_assoc_bss;
1460 		break;
1461 	case LEAF_wlanStatsRxAssocNoAuth:
1462 		val->v.uint32 = wif->stats.is_rx_assoc_notauth;
1463 		break;
1464 	case LEAF_wlanStatsRxAssocCapMismatch:
1465 		val->v.uint32 = wif->stats.is_rx_assoc_capmismatch;
1466 		break;
1467 	case LEAF_wlanStatsRxAssocNoRateMatch:
1468 		val->v.uint32 = wif->stats.is_rx_assoc_norate;
1469 		break;
1470 	case LEAF_wlanStatsRxBadWpaIE:
1471 		val->v.uint32 = wif->stats.is_rx_assoc_badwpaie;
1472 		break;
1473 	case LEAF_wlanStatsRxDeauthenticate:
1474 		val->v.uint32 = wif->stats.is_rx_deauth;
1475 		break;
1476 	case LEAF_wlanStatsRxDisassociate:
1477 		val->v.uint32 = wif->stats.is_rx_disassoc;
1478 		break;
1479 	case LEAF_wlanStatsRxUnknownSubtype:
1480 		val->v.uint32 = wif->stats.is_rx_badsubtype;
1481 		break;
1482 	case LEAF_wlanStatsRxFailedNoBuf:
1483 		val->v.uint32 = wif->stats.is_rx_nobuf;
1484 		break;
1485 	case LEAF_wlanStatsRxBadAuthRequest:
1486 		val->v.uint32 = wif->stats.is_rx_bad_auth;
1487 		break;
1488 	case LEAF_wlanStatsRxUnAuthorized:
1489 		val->v.uint32 = wif->stats.is_rx_unauth;
1490 		break;
1491 	case LEAF_wlanStatsRxBadKeyId:
1492 		val->v.uint32 = wif->stats.is_rx_badkeyid;
1493 		break;
1494 	case LEAF_wlanStatsRxCCMPSeqViolation:
1495 		val->v.uint32 = wif->stats.is_rx_ccmpreplay;
1496 		break;
1497 	case LEAF_wlanStatsRxCCMPBadFormat:
1498 		val->v.uint32 = wif->stats.is_rx_ccmpformat;
1499 		break;
1500 	case LEAF_wlanStatsRxCCMPFailedMIC:
1501 		val->v.uint32 = wif->stats.is_rx_ccmpmic;
1502 		break;
1503 	case LEAF_wlanStatsRxTKIPSeqViolation:
1504 		val->v.uint32 = wif->stats.is_rx_tkipreplay;
1505 		break;
1506 	case LEAF_wlanStatsRxTKIPBadFormat:
1507 		val->v.uint32 = wif->stats.is_rx_tkipformat;
1508 		break;
1509 	case LEAF_wlanStatsRxTKIPFailedMIC:
1510 		val->v.uint32 = wif->stats.is_rx_tkipmic;
1511 		break;
1512 	case LEAF_wlanStatsRxTKIPFailedICV:
1513 		val->v.uint32 = wif->stats.is_rx_tkipicv;
1514 		break;
1515 	case LEAF_wlanStatsRxDiscardACL:
1516 		val->v.uint32 = wif->stats.is_rx_acl;
1517 		break;
1518 	case LEAF_wlanStatsTxFailedNoBuf:
1519 		val->v.uint32 = wif->stats.is_tx_nobuf;
1520 		break;
1521 	case LEAF_wlanStatsTxFailedNoNode:
1522 		val->v.uint32 = wif->stats.is_tx_nonode;
1523 		break;
1524 	case LEAF_wlanStatsTxUnknownMgmt:
1525 		val->v.uint32 = wif->stats.is_tx_unknownmgt;
1526 		break;
1527 	case LEAF_wlanStatsTxBadCipher:
1528 		val->v.uint32 = wif->stats.is_tx_badcipher;
1529 		break;
1530 	case LEAF_wlanStatsTxNoDefKey:
1531 		val->v.uint32 = wif->stats.is_tx_nodefkey;
1532 		break;
1533 	case LEAF_wlanStatsTxFragmented:
1534 		val->v.uint32 = wif->stats.is_tx_fragframes;
1535 		break;
1536 	case LEAF_wlanStatsTxFragmentsCreated:
1537 		val->v.uint32 = wif->stats.is_tx_frags;
1538 		break;
1539 	case LEAF_wlanStatsActiveScans:
1540 		val->v.uint32 = wif->stats.is_scan_active;
1541 		break;
1542 	case LEAF_wlanStatsPassiveScans:
1543 		val->v.uint32 = wif->stats.is_scan_passive;
1544 		break;
1545 	case LEAF_wlanStatsTimeoutInactivity:
1546 		val->v.uint32 = wif->stats.is_node_timeout;
1547 		break;
1548 	case LEAF_wlanStatsCryptoNoMem:
1549 		val->v.uint32 = wif->stats.is_crypto_nomem;
1550 		break;
1551 	case LEAF_wlanStatsSwCryptoTKIP:
1552 		val->v.uint32 = wif->stats.is_crypto_tkip;
1553 		break;
1554 	case LEAF_wlanStatsSwCryptoTKIPEnMIC:
1555 		val->v.uint32 = wif->stats.is_crypto_tkipenmic;
1556 		break;
1557 	case LEAF_wlanStatsSwCryptoTKIPDeMIC:
1558 		val->v.uint32 = wif->stats.is_crypto_tkipdemic;
1559 		break;
1560 	case LEAF_wlanStatsCryptoTKIPCM:
1561 		val->v.uint32 = wif->stats.is_crypto_tkipcm;
1562 		break;
1563 	case LEAF_wlanStatsSwCryptoCCMP:
1564 		val->v.uint32 = wif->stats.is_crypto_ccmp;
1565 		break;
1566 	case LEAF_wlanStatsSwCryptoWEP:
1567 		val->v.uint32 = wif->stats.is_crypto_wep;
1568 		break;
1569 	case LEAF_wlanStatsCryptoCipherKeyRejected:
1570 		val->v.uint32 = wif->stats.is_crypto_setkey_cipher;
1571 		break;
1572 	case LEAF_wlanStatsCryptoNoKey:
1573 		val->v.uint32 = wif->stats.is_crypto_setkey_nokey;
1574 		break;
1575 	case LEAF_wlanStatsCryptoDeleteKeyFailed:
1576 		val->v.uint32 = wif->stats.is_crypto_delkey;
1577 		break;
1578 	case LEAF_wlanStatsCryptoUnknownCipher:
1579 		val->v.uint32 = wif->stats.is_crypto_badcipher;
1580 		break;
1581 	case LEAF_wlanStatsCryptoAttachFailed:
1582 		val->v.uint32 = wif->stats.is_crypto_attachfail;
1583 		break;
1584 	case LEAF_wlanStatsCryptoKeyFailed:
1585 		val->v.uint32 = wif->stats.is_crypto_keyfail;
1586 		break;
1587 	case LEAF_wlanStatsCryptoEnMICFailed:
1588 		val->v.uint32 = wif->stats.is_crypto_enmicfail;
1589 		break;
1590 	case LEAF_wlanStatsIBSSCapMismatch:
1591 		val->v.uint32 = wif->stats.is_ibss_capmismatch;
1592 		break;
1593 	case LEAF_wlanStatsUnassocStaPSPoll:
1594 		val->v.uint32 = wif->stats.is_ps_unassoc;
1595 		break;
1596 	case LEAF_wlanStatsBadAidPSPoll:
1597 		val->v.uint32 = wif->stats.is_ps_badaid;
1598 		break;
1599 	case LEAF_wlanStatsEmptyPSPoll:
1600 		val->v.uint32 = wif->stats.is_ps_qempty;
1601 		break;
1602 	case LEAF_wlanStatsRxFFBadHdr:
1603 		val->v.uint32 = wif->stats.is_ff_badhdr;
1604 		break;
1605 	case LEAF_wlanStatsRxFFTooShort:
1606 		val->v.uint32 = wif->stats.is_ff_tooshort;
1607 		break;
1608 	case LEAF_wlanStatsRxFFSplitError:
1609 		val->v.uint32 = wif->stats.is_ff_split;
1610 		break;
1611 	case LEAF_wlanStatsRxFFDecap:
1612 		val->v.uint32 = wif->stats.is_ff_decap;
1613 		break;
1614 	case LEAF_wlanStatsTxFFEncap:
1615 		val->v.uint32 = wif->stats.is_ff_encap;
1616 		break;
1617 	case LEAF_wlanStatsRxBadBintval:
1618 		val->v.uint32 = wif->stats.is_rx_badbintval;
1619 		break;
1620 	case LEAF_wlanStatsRxDemicFailed:
1621 		val->v.uint32 = wif->stats.is_rx_demicfail;
1622 		break;
1623 	case LEAF_wlanStatsRxDefragFailed:
1624 		val->v.uint32 = wif->stats.is_rx_defrag;
1625 		break;
1626 	case LEAF_wlanStatsRxMgmt:
1627 		val->v.uint32 = wif->stats.is_rx_mgmt;
1628 		break;
1629 	case LEAF_wlanStatsRxActionMgmt:
1630 		val->v.uint32 = wif->stats.is_rx_action;
1631 		break;
1632 	case LEAF_wlanStatsRxAMSDUTooShort:
1633 		val->v.uint32 = wif->stats.is_amsdu_tooshort;
1634 		break;
1635 	case LEAF_wlanStatsRxAMSDUSplitError:
1636 		val->v.uint32 = wif->stats.is_amsdu_split;
1637 		break;
1638 	case LEAF_wlanStatsRxAMSDUDecap:
1639 		val->v.uint32 = wif->stats.is_amsdu_decap;
1640 		break;
1641 	case LEAF_wlanStatsTxAMSDUEncap:
1642 		val->v.uint32 = wif->stats.is_amsdu_encap;
1643 		break;
1644 	case LEAF_wlanStatsAMPDUBadBAR:
1645 		val->v.uint32 = wif->stats.is_ampdu_bar_bad;
1646 		break;
1647 	case LEAF_wlanStatsAMPDUOowBar:
1648 		val->v.uint32 = wif->stats.is_ampdu_bar_oow;
1649 		break;
1650 	case LEAF_wlanStatsAMPDUMovedBAR:
1651 		val->v.uint32 = wif->stats.is_ampdu_bar_move;
1652 		break;
1653 	case LEAF_wlanStatsAMPDURxBAR:
1654 		val->v.uint32 = wif->stats.is_ampdu_bar_rx;
1655 		break;
1656 	case LEAF_wlanStatsAMPDURxOor:
1657 		val->v.uint32 = wif->stats.is_ampdu_rx_oor;
1658 		break;
1659 	case LEAF_wlanStatsAMPDURxCopied:
1660 		val->v.uint32 = wif->stats.is_ampdu_rx_copy;
1661 		break;
1662 	case LEAF_wlanStatsAMPDURxDropped:
1663 		val->v.uint32 = wif->stats.is_ampdu_rx_drop;
1664 		break;
1665 	case LEAF_wlanStatsTxDiscardBadState:
1666 		val->v.uint32 = wif->stats.is_tx_badstate;
1667 		break;
1668 	case LEAF_wlanStatsTxFailedNoAssoc:
1669 		val->v.uint32 = wif->stats.is_tx_notassoc;
1670 		break;
1671 	case LEAF_wlanStatsTxClassifyFailed:
1672 		val->v.uint32 = wif->stats.is_tx_classify;
1673 		break;
1674 	case LEAF_wlanStatsDwdsMcastDiscard:
1675 		val->v.uint32 = wif->stats.is_dwds_mcast;
1676 		break;
1677 	case LEAF_wlanStatsHTAssocRejectNoHT:
1678 		val->v.uint32 = wif->stats.is_ht_assoc_nohtcap;
1679 		break;
1680 	case LEAF_wlanStatsHTAssocDowngrade:
1681 		val->v.uint32 = wif->stats.is_ht_assoc_downgrade;
1682 		break;
1683 	case LEAF_wlanStatsHTAssocRateMismatch:
1684 		val->v.uint32 = wif->stats.is_ht_assoc_norate;
1685 		break;
1686 	case LEAF_wlanStatsAMPDURxAge:
1687 		val->v.uint32 = wif->stats.is_ampdu_rx_age;
1688 		break;
1689 	case LEAF_wlanStatsAMPDUMoved:
1690 		val->v.uint32 = wif->stats.is_ampdu_rx_move;
1691 		break;
1692 	case LEAF_wlanStatsADDBADisabledReject:
1693 		val->v.uint32 = wif->stats.is_addba_reject;
1694 		break;
1695 	case LEAF_wlanStatsADDBANoRequest:
1696 		val->v.uint32 = wif->stats.is_addba_norequest;
1697 		break;
1698 	case LEAF_wlanStatsADDBABadToken:
1699 		val->v.uint32 = wif->stats.is_addba_badtoken;
1700 		break;
1701 	case LEAF_wlanStatsADDBABadPolicy:
1702 		val->v.uint32 = wif->stats.is_addba_badpolicy;
1703 		break;
1704 	case LEAF_wlanStatsAMPDUStopped:
1705 		val->v.uint32 = wif->stats.is_ampdu_stop;
1706 		break;
1707 	case LEAF_wlanStatsAMPDUStopFailed:
1708 		val->v.uint32 = wif->stats.is_ampdu_stop_failed;
1709 		break;
1710 	case LEAF_wlanStatsAMPDURxReorder:
1711 		val->v.uint32 = wif->stats.is_ampdu_rx_reorder;
1712 		break;
1713 	case LEAF_wlanStatsScansBackground:
1714 		val->v.uint32 = wif->stats.is_scan_bg;
1715 		break;
1716 	case LEAF_wlanLastDeauthReason:
1717 		val->v.uint32 = wif->stats.is_rx_deauth_code;
1718 		break;
1719 	case LEAF_wlanLastDissasocReason:
1720 		val->v.uint32 = wif->stats.is_rx_disassoc_code;
1721 		break;
1722 	case LEAF_wlanLastAuthFailReason:
1723 		val->v.uint32 = wif->stats.is_rx_authfail_code;
1724 		break;
1725 	case LEAF_wlanStatsBeaconMissedEvents:
1726 		val->v.uint32 = wif->stats.is_beacon_miss;
1727 		break;
1728 	case LEAF_wlanStatsRxDiscardBadStates:
1729 		val->v.uint32 = wif->stats.is_rx_badstate;
1730 		break;
1731 	case LEAF_wlanStatsFFFlushed:
1732 		val->v.uint32 = wif->stats.is_ff_flush;
1733 		break;
1734 	case LEAF_wlanStatsTxControlFrames:
1735 		val->v.uint32 = wif->stats.is_tx_ctl;
1736 		break;
1737 	case LEAF_wlanStatsAMPDURexmt:
1738 		val->v.uint32 = wif->stats.is_ampdu_rexmt;
1739 		break;
1740 	case LEAF_wlanStatsAMPDURexmtFailed:
1741 		val->v.uint32 = wif->stats.is_ampdu_rexmt_fail;
1742 		break;
1743 	case LEAF_wlanStatsReset:
1744 		val->v.uint32 = wlanStatsReset_no_op;
1745 		break;
1746 	default:
1747 		abort();
1748 	}
1749 
1750 	return (SNMP_ERR_NOERROR);
1751 }
1752 
1753 int
1754 op_wlan_wep_iface(struct snmp_context *ctx, struct snmp_value *val,
1755     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1756 {
1757 	struct wlan_iface *wif;
1758 
1759 	wlan_update_interface_list();
1760 
1761 	switch (op) {
1762 	case SNMP_OP_GET:
1763 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||
1764 		    !wif->wepsupported)
1765 			return (SNMP_ERR_NOSUCHNAME);
1766 		break;
1767 
1768 	case SNMP_OP_GETNEXT:
1769 		/* XXX: filter wif->wepsupported */
1770 		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
1771 			return (SNMP_ERR_NOSUCHNAME);
1772 		wlan_append_ifindex(&val->var, sub, wif);
1773 		break;
1774 
1775 	case SNMP_OP_SET:
1776 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||
1777 		    !wif->wepsupported)
1778 			return (SNMP_ERR_NOSUCHNAME);
1779 		switch (val->var.subs[sub - 1]) {
1780 		case LEAF_wlanWepMode:
1781 			if (val->v.integer < wlanWepMode_off ||
1782 			    val->v.integer > wlanWepMode_mixed)
1783 				return (SNMP_ERR_INCONS_VALUE);
1784 			ctx->scratch->int1 = wif->wepmode;
1785 			wif->wepmode = val->v.integer;
1786 			if (wlan_set_wepmode(wif) < 0) {
1787 				wif->wepmode = ctx->scratch->int1;
1788 				return (SNMP_ERR_GENERR);
1789 			}
1790 			break;
1791 		case LEAF_wlanWepDefTxKey:
1792 			if (val->v.integer < 0 ||
1793 			    val->v.integer > IEEE80211_WEP_NKID)
1794 				return (SNMP_ERR_INCONS_VALUE);
1795 			ctx->scratch->int1 = wif->weptxkey;
1796 			wif->weptxkey = val->v.integer;
1797 			if (wlan_set_weptxkey(wif) < 0) {
1798 				wif->weptxkey = ctx->scratch->int1;
1799 				return (SNMP_ERR_GENERR);
1800 			}
1801 			break;
1802 		default:
1803 			abort();
1804 		}
1805 		return (SNMP_ERR_NOERROR);
1806 
1807 	case SNMP_OP_COMMIT:
1808 		return (SNMP_ERR_NOERROR);
1809 
1810 	case SNMP_OP_ROLLBACK:
1811 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1812 			return (SNMP_ERR_NOSUCHNAME);
1813 		switch (val->var.subs[sub - 1]) {
1814 		case LEAF_wlanWepMode:
1815 			wif->wepmode = ctx->scratch->int1;
1816 			if (wlan_set_wepmode(wif) < 0)
1817 				return (SNMP_ERR_GENERR);
1818 			break;
1819 		case LEAF_wlanWepDefTxKey:
1820 			wif->weptxkey = ctx->scratch->int1;
1821 			if (wlan_set_weptxkey(wif) < 0)
1822 				return (SNMP_ERR_GENERR);
1823 			break;
1824 		default:
1825 			abort();
1826 		}
1827 		return (SNMP_ERR_NOERROR);
1828 
1829 	default:
1830 		abort();
1831 	}
1832 
1833 	switch (val->var.subs[sub - 1]) {
1834 	case LEAF_wlanWepMode:
1835 		if (wlan_get_wepmode(wif) < 0)
1836 			return (SNMP_ERR_GENERR);
1837 		val->v.integer = wif->wepmode;
1838 		break;
1839 	case LEAF_wlanWepDefTxKey:
1840 		if (wlan_get_weptxkey(wif) < 0)
1841 			return (SNMP_ERR_GENERR);
1842 		val->v.integer = wif->weptxkey;
1843 		break;
1844 	default:
1845 		abort();
1846 	}
1847 
1848 	return (SNMP_ERR_NOERROR);
1849 }
1850 
1851 int
1852 op_wlan_wep_key(struct snmp_context *ctx __unused,
1853     struct snmp_value *val __unused, uint32_t sub __unused,
1854     uint32_t iidx __unused, enum snmp_op op __unused)
1855 {
1856 	return (SNMP_ERR_NOSUCHNAME);
1857 }
1858 
1859 int
1860 op_wlan_mac_access_control(struct snmp_context *ctx, struct snmp_value *val,
1861     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1862 {
1863 	struct wlan_iface *wif;
1864 
1865 	wlan_update_interface_list();
1866 
1867 	switch (op) {
1868 	case SNMP_OP_GET:
1869 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||
1870 		    !wif->macsupported)
1871 			return (SNMP_ERR_NOSUCHNAME);
1872 		break;
1873 
1874 	case SNMP_OP_GETNEXT:
1875 		/* XXX: filter wif->macsupported */
1876 		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
1877 			return (SNMP_ERR_NOSUCHNAME);
1878 		wlan_append_ifindex(&val->var, sub, wif);
1879 		break;
1880 
1881 	case SNMP_OP_SET:
1882 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||
1883 		    !wif->macsupported)
1884 			return (SNMP_ERR_NOSUCHNAME);
1885 		switch (val->var.subs[sub - 1]) {
1886 		case LEAF_wlanMACAccessControlPolicy:
1887 			ctx->scratch->int1 = wif->mac_policy;
1888 			wif->mac_policy = val->v.integer;
1889 			break;
1890 		case LEAF_wlanMACAccessControlNacl:
1891 			return (SNMP_ERR_NOT_WRITEABLE);
1892 		case LEAF_wlanMACAccessControlFlush:
1893 			break;
1894 		default:
1895 			abort();
1896 		}
1897 		return (SNMP_ERR_NOERROR);
1898 
1899 	case SNMP_OP_COMMIT:
1900 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1901 			return (SNMP_ERR_NOSUCHNAME);
1902 		switch (val->var.subs[sub - 1]) {
1903 		case LEAF_wlanMACAccessControlPolicy:
1904 			if (wlan_set_mac_policy(wif) < 0) {
1905 				wif->mac_policy = ctx->scratch->int1;
1906 				return (SNMP_ERR_GENERR);
1907 			}
1908 			break;
1909 		case LEAF_wlanMACAccessControlFlush:
1910 			if (wlan_flush_mac_mac(wif) < 0)
1911 				return (SNMP_ERR_GENERR);
1912 			break;
1913 		default:
1914 			abort();
1915 		}
1916 		return (SNMP_ERR_NOERROR);
1917 
1918 	case SNMP_OP_ROLLBACK:
1919 		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1920 			return (SNMP_ERR_NOSUCHNAME);
1921 		if (val->var.subs[sub - 1] == LEAF_wlanMACAccessControlPolicy)
1922 			wif->mac_policy = ctx->scratch->int1;
1923 		return (SNMP_ERR_NOERROR);
1924 
1925 	default:
1926 		abort();
1927 	}
1928 
1929 	if (wlan_get_mac_policy(wif) < 0)
1930 		return (SNMP_ERR_GENERR);
1931 
1932 	switch (val->var.subs[sub - 1]) {
1933 	case LEAF_wlanMACAccessControlPolicy:
1934 		val->v.integer = wif->mac_policy;
1935 		break;
1936 	case LEAF_wlanMACAccessControlNacl:
1937 		val->v.integer = wif->mac_nacls;
1938 		break;
1939 	case LEAF_wlanMACAccessControlFlush:
1940 		val->v.integer = wlanMACAccessControlFlush_no_op;
1941 		break;
1942 	default:
1943 		abort();
1944 	}
1945 
1946 	return (SNMP_ERR_NOERROR);
1947 }
1948 
1949 int
1950 op_wlan_mac_acl_mac(struct snmp_context *ctx, struct snmp_value *val,
1951     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1952 {
1953 	struct wlan_iface *wif;
1954 	struct wlan_mac_mac *macl;
1955 
1956 	wlan_update_interface_list();
1957 	wlan_mac_update_aclmacs();
1958 
1959 	switch (op) {
1960 	case SNMP_OP_GET:
1961 		if ((macl = wlan_get_acl_mac(&val->var, sub, &wif)) == NULL)
1962 			return (SNMP_ERR_NOSUCHNAME);
1963 		break;
1964 
1965 	case SNMP_OP_GETNEXT:
1966 		if ((macl = wlan_get_next_acl_mac(&val->var, sub, &wif))
1967 		    == NULL)
1968 			return (SNMP_ERR_NOSUCHNAME);
1969 		wlan_append_mac_index(&val->var, sub, wif->wname, macl->mac);
1970 		break;
1971 
1972 	case SNMP_OP_SET:
1973 		switch (val->var.subs[sub - 1]) {
1974 		case LEAF_wlanMACAccessControlMAC:
1975 			return (SNMP_ERR_INCONS_NAME);
1976 		case LEAF_wlanMACAccessControlMACStatus:
1977 			return(wlan_acl_mac_set_status(ctx, val, sub));
1978 		default:
1979 			abort();
1980 		}
1981 
1982 	case SNMP_OP_COMMIT:
1983 		if ((macl = wlan_get_acl_mac(&val->var, sub, &wif)) == NULL)
1984 			return (SNMP_ERR_NOSUCHNAME);
1985 		if (val->v.integer == RowStatus_destroy &&
1986 		    wlan_mac_delete_mac(wif, macl) < 0)
1987 			return (SNMP_ERR_GENERR);
1988 		return (SNMP_ERR_NOERROR);
1989 
1990 	case SNMP_OP_ROLLBACK:
1991 		if ((macl = wlan_get_acl_mac(&val->var, sub, &wif)) == NULL)
1992 			return (SNMP_ERR_NOSUCHNAME);
1993 		if (ctx->scratch->int1 == RowStatus_destroy &&
1994 		    wlan_mac_delete_mac(wif, macl) < 0)
1995 			return (SNMP_ERR_GENERR);
1996 		return (SNMP_ERR_NOERROR);
1997 
1998 	default:
1999 		abort();
2000 	}
2001 
2002 	switch (val->var.subs[sub - 1]) {
2003 	case LEAF_wlanMACAccessControlMAC:
2004 		return (string_get(val, macl->mac, IEEE80211_ADDR_LEN));
2005 	case LEAF_wlanMACAccessControlMACStatus:
2006 		val->v.integer = macl->mac_status;
2007 		break;
2008 	default:
2009 		abort();
2010 	}
2011 
2012 	return (SNMP_ERR_NOERROR);
2013 }
2014 
2015 int
2016 op_wlan_mesh_config(struct snmp_context *ctx, struct snmp_value *val,
2017     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2018 {
2019 	int which;
2020 
2021 	switch (val->var.subs[sub - 1]) {
2022 	case LEAF_wlanMeshMaxRetries:
2023 		which = WLAN_MESH_MAX_RETRIES;
2024 		break;
2025 	case LEAF_wlanMeshHoldingTimeout:
2026 		which = WLAN_MESH_HOLDING_TO;
2027 		break;
2028 	case LEAF_wlanMeshConfirmTimeout:
2029 		which = WLAN_MESH_CONFIRM_TO;
2030 		break;
2031 	case LEAF_wlanMeshRetryTimeout:
2032 		which = WLAN_MESH_RETRY_TO;
2033 		break;
2034 	default:
2035 		abort();
2036 	}
2037 
2038 	switch (op) {
2039 	case SNMP_OP_GET:
2040 		if (wlan_do_sysctl(&wlan_config, which, 0) < 0)
2041 			return (SNMP_ERR_GENERR);
2042 		break;
2043 
2044 	case SNMP_OP_GETNEXT:
2045 		abort();
2046 
2047 	case SNMP_OP_SET:
2048 		switch (val->var.subs[sub - 1]) {
2049 		case LEAF_wlanMeshRetryTimeout :
2050 			ctx->scratch->int1 = wlan_config.mesh_retryto;
2051 			wlan_config.mesh_retryto = val->v.integer;
2052 			break;
2053 		case LEAF_wlanMeshHoldingTimeout:
2054 			ctx->scratch->int1 = wlan_config.mesh_holdingto;
2055 			wlan_config.mesh_holdingto = val->v.integer;
2056 			break;
2057 		case LEAF_wlanMeshConfirmTimeout:
2058 			ctx->scratch->int1 = wlan_config.mesh_confirmto;
2059 			wlan_config.mesh_confirmto = val->v.integer;
2060 			break;
2061 		case LEAF_wlanMeshMaxRetries:
2062 			ctx->scratch->int1 = wlan_config.mesh_maxretries;
2063 			wlan_config.mesh_maxretries = val->v.integer;
2064 			break;
2065 		}
2066 		if (wlan_do_sysctl(&wlan_config, which, 1) < 0)
2067 			return (SNMP_ERR_GENERR);
2068 		return (SNMP_ERR_NOERROR);
2069 
2070 	case SNMP_OP_COMMIT:
2071 		return (SNMP_ERR_NOERROR);
2072 
2073 	case SNMP_OP_ROLLBACK:
2074 		switch (val->var.subs[sub - 1]) {
2075 		case LEAF_wlanMeshRetryTimeout:
2076 			wlan_config.mesh_retryto = ctx->scratch->int1;
2077 			break;
2078 		case LEAF_wlanMeshConfirmTimeout:
2079 			wlan_config.mesh_confirmto = ctx->scratch->int1;
2080 			break;
2081 		case LEAF_wlanMeshHoldingTimeout:
2082 			wlan_config.mesh_holdingto= ctx->scratch->int1;
2083 			break;
2084 		case LEAF_wlanMeshMaxRetries:
2085 			wlan_config.mesh_maxretries = ctx->scratch->int1;
2086 			break;
2087 		}
2088 		if (wlan_do_sysctl(&wlan_config, which, 1) < 0)
2089 			return (SNMP_ERR_GENERR);
2090 		return (SNMP_ERR_NOERROR);
2091 
2092 	default:
2093 		abort();
2094 	}
2095 
2096 	switch (val->var.subs[sub - 1]) {
2097 	case LEAF_wlanMeshRetryTimeout:
2098 		val->v.integer = wlan_config.mesh_retryto;
2099 		break;
2100 	case LEAF_wlanMeshHoldingTimeout:
2101 		val->v.integer = wlan_config.mesh_holdingto;
2102 		break;
2103 	case LEAF_wlanMeshConfirmTimeout:
2104 		val->v.integer = wlan_config.mesh_confirmto;
2105 		break;
2106 	case LEAF_wlanMeshMaxRetries:
2107 		val->v.integer = wlan_config.mesh_maxretries;
2108 		break;
2109 	}
2110 
2111 	return (SNMP_ERR_NOERROR);
2112 }
2113 
2114 int
2115 op_wlan_mesh_iface(struct snmp_context *ctx, struct snmp_value *val,
2116     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2117 {
2118 	int rc;
2119 	struct wlan_iface *wif;
2120 
2121 	wlan_update_interface_list();
2122 
2123 	switch (op) {
2124 	case SNMP_OP_GET:
2125 		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2126 			return (SNMP_ERR_NOSUCHNAME);
2127 		break;
2128 
2129 	case SNMP_OP_GETNEXT:
2130 		if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)
2131 			return (SNMP_ERR_NOSUCHNAME);
2132 		wlan_append_ifindex(&val->var, sub, wif);
2133 		break;
2134 
2135 	case SNMP_OP_SET:
2136 		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2137 			return (SNMP_ERR_NOSUCHNAME);
2138 		switch (val->var.subs[sub - 1]) {
2139 		case LEAF_wlanMeshId:
2140 			if (val->v.octetstring.len > IEEE80211_NWID_LEN)
2141 				return (SNMP_ERR_INCONS_VALUE);
2142 			ctx->scratch->ptr1 = malloc(val->v.octetstring.len + 1);
2143 			if (ctx->scratch->ptr1 == NULL)
2144 				return (SNMP_ERR_GENERR);
2145 			strlcpy(ctx->scratch->ptr1, wif->desired_ssid,
2146 			    val->v.octetstring.len + 1);
2147 			ctx->scratch->int1 = strlen(wif->desired_ssid);
2148 			memcpy(wif->desired_ssid, val->v.octetstring.octets,
2149 			    val->v.octetstring.len);
2150 			wif->desired_ssid[val->v.octetstring.len] = '\0';
2151 			break;
2152 		case LEAF_wlanMeshTTL:
2153 			ctx->scratch->int1 = wif->mesh_ttl;
2154 			wif->mesh_ttl = val->v.integer;
2155 			break;
2156 		case LEAF_wlanMeshPeeringEnabled:
2157 			ctx->scratch->int1 = wif->mesh_peering;
2158 			wif->mesh_peering = val->v.integer;
2159 			break;
2160 		case LEAF_wlanMeshForwardingEnabled:
2161 			ctx->scratch->int1 = wif->mesh_forwarding;
2162 			wif->mesh_forwarding = val->v.integer;
2163 			break;
2164 		case LEAF_wlanMeshMetric:
2165 			ctx->scratch->int1 = wif->mesh_metric;
2166 			wif->mesh_metric = val->v.integer;
2167 			break;
2168 		case LEAF_wlanMeshPath:
2169 			ctx->scratch->int1 = wif->mesh_path;
2170 			wif->mesh_path = val->v.integer;
2171 			break;
2172 		case LEAF_wlanMeshRoutesFlush:
2173 			if (val->v.integer != wlanMeshRoutesFlush_flush)
2174 				return (SNMP_ERR_INCONS_VALUE);
2175 			return (SNMP_ERR_NOERROR);
2176 		default:
2177 			abort();
2178 		}
2179 		if (val->var.subs[sub - 1] == LEAF_wlanMeshId)
2180 			rc = wlan_config_set_dssid(wif,
2181 			    val->v.octetstring.octets, val->v.octetstring.len);
2182 		else
2183 			rc = wlan_mesh_config_set(wif, val->var.subs[sub - 1]);
2184 		if (rc < 0)
2185 			return (SNMP_ERR_GENERR);
2186 		return (SNMP_ERR_NOERROR);
2187 
2188 	case SNMP_OP_COMMIT:
2189 		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2190 			return (SNMP_ERR_NOSUCHNAME);
2191 		if (val->var.subs[sub - 1] == LEAF_wlanMeshRoutesFlush &&
2192 		    wlan_mesh_flush_routes(wif) < 0)
2193 			return (SNMP_ERR_GENERR);
2194 		if (val->var.subs[sub - 1] == LEAF_wlanMeshId)
2195 			free(ctx->scratch->ptr1);
2196 		return (SNMP_ERR_NOERROR);
2197 
2198 	case SNMP_OP_ROLLBACK:
2199 		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2200 			return (SNMP_ERR_NOSUCHNAME);
2201 		switch (val->var.subs[sub - 1]) {
2202 		case LEAF_wlanMeshId:
2203 			strlcpy(wif->desired_ssid, ctx->scratch->ptr1,
2204 			    IEEE80211_NWID_LEN);
2205 			free(ctx->scratch->ptr1);
2206 			break;
2207 		case LEAF_wlanMeshTTL:
2208 			wif->mesh_ttl = ctx->scratch->int1;
2209 			break;
2210 		case LEAF_wlanMeshPeeringEnabled:
2211 			wif->mesh_peering = ctx->scratch->int1;
2212 			break;
2213 		case LEAF_wlanMeshForwardingEnabled:
2214 			wif->mesh_forwarding = ctx->scratch->int1;
2215 			break;
2216 		case LEAF_wlanMeshMetric:
2217 			wif->mesh_metric = ctx->scratch->int1;
2218 			break;
2219 		case LEAF_wlanMeshPath:
2220 			wif->mesh_path = ctx->scratch->int1;
2221 			break;
2222 		case LEAF_wlanMeshRoutesFlush:
2223 			return (SNMP_ERR_NOERROR);
2224 		default:
2225 			abort();
2226 		}
2227 		if (val->var.subs[sub - 1] == LEAF_wlanMeshId)
2228 			rc = wlan_config_set_dssid(wif, wif->desired_ssid,
2229 			    strlen(wif->desired_ssid));
2230 		else
2231 			rc = wlan_mesh_config_set(wif, val->var.subs[sub - 1]);
2232 		if (rc < 0)
2233 			return (SNMP_ERR_GENERR);
2234 		return (SNMP_ERR_NOERROR);
2235 
2236 	default:
2237 		abort();
2238 	}
2239 
2240 	if (val->var.subs[sub - 1] == LEAF_wlanMeshId)
2241 		rc = wlan_config_get_dssid(wif);
2242 	else
2243 		rc = wlan_mesh_config_get(wif, val->var.subs[sub - 1]);
2244 	if (rc < 0)
2245 		return (SNMP_ERR_GENERR);
2246 
2247 	switch (val->var.subs[sub - 1]) {
2248 	case LEAF_wlanMeshId:
2249 		return (string_get(val, wif->desired_ssid, -1));
2250 	case LEAF_wlanMeshTTL:
2251 		val->v.integer = wif->mesh_ttl;
2252 		break;
2253 	case LEAF_wlanMeshPeeringEnabled:
2254 		val->v.integer = wif->mesh_peering;
2255 		break;
2256 	case LEAF_wlanMeshForwardingEnabled:
2257 		val->v.integer = wif->mesh_forwarding;
2258 		break;
2259 	case LEAF_wlanMeshMetric:
2260 		val->v.integer = wif->mesh_metric;
2261 		break;
2262 	case LEAF_wlanMeshPath:
2263 		val->v.integer = wif->mesh_path;
2264 		break;
2265 	case LEAF_wlanMeshRoutesFlush:
2266 		val->v.integer = wlanMeshRoutesFlush_no_op;
2267 		break;
2268 	default:
2269 		abort();
2270 	}
2271 
2272 	return (SNMP_ERR_NOERROR);
2273 }
2274 
2275 int
2276 op_wlan_mesh_neighbor(struct snmp_context *ctx __unused, struct snmp_value *val,
2277     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2278 {
2279 	struct wlan_peer *wip;
2280 	struct wlan_iface *wif;
2281 
2282 	wlan_update_interface_list();
2283 	wlan_update_peers();
2284 
2285 	switch (op) {
2286 	case SNMP_OP_GET:
2287 		if ((wip = wlan_mesh_get_peer(&val->var, sub, &wif)) == NULL)
2288 			return (SNMP_ERR_NOSUCHNAME);
2289 		break;
2290 	case SNMP_OP_GETNEXT:
2291 		wip = wlan_mesh_get_next_peer(&val->var, sub, &wif);
2292 		if (wip == NULL)
2293 			return (SNMP_ERR_NOSUCHNAME);
2294 		wlan_append_mac_index(&val->var, sub, wif->wname,
2295 		    wip->pmac);
2296 		break;
2297 	case SNMP_OP_SET:
2298 		return (SNMP_ERR_NOT_WRITEABLE);
2299 	case SNMP_OP_COMMIT:
2300 		/* FALLTHROUGH */
2301 	case SNMP_OP_ROLLBACK:
2302 		/* FALLTHROUGH */
2303 	default:
2304 		abort();
2305 	}
2306 
2307 	switch (val->var.subs[sub - 1]) {
2308 	case LEAF_wlanMeshNeighborAddress:
2309 		return (string_get(val, wip->pmac, IEEE80211_ADDR_LEN));
2310 	case LEAF_wlanMeshNeighborFrequency:
2311 		val->v.integer = wip->frequency;
2312 		break;
2313 	case LEAF_wlanMeshNeighborLocalId:
2314 		val->v.integer = wip->local_id;
2315 		break;
2316 	case LEAF_wlanMeshNeighborPeerId:
2317 		val->v.integer = wip->peer_id;
2318 		break;
2319 	case LEAF_wlanMeshNeighborPeerState:
2320 		return (bits_get(val, (uint8_t *)&wip->state,
2321 		    sizeof(wip->state)));
2322 	case LEAF_wlanMeshNeighborCurrentTXRate:
2323 		val->v.integer = wip->txrate;
2324 		break;
2325 	case LEAF_wlanMeshNeighborRxSignalStrength:
2326 		val->v.integer = wip->rssi;
2327 		break;
2328 	case LEAF_wlanMeshNeighborIdleTimer:
2329 		val->v.integer = wip->idle;
2330 		break;
2331 	case LEAF_wlanMeshNeighborTxSequenceNo:
2332 		val->v.integer = wip->txseqs;
2333 		break;
2334 	case LEAF_wlanMeshNeighborRxSequenceNo:
2335 		val->v.integer = wip->rxseqs;
2336 		break;
2337 	default:
2338 		abort();
2339 	}
2340 
2341 	return (SNMP_ERR_NOERROR);
2342 }
2343 
2344 int
2345 op_wlan_mesh_route(struct snmp_context *ctx, struct snmp_value *val,
2346     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2347 {
2348 	struct wlan_mesh_route *wmr;
2349 	struct wlan_iface *wif;
2350 
2351 	wlan_update_interface_list();
2352 	wlan_mesh_update_routes();
2353 
2354 	switch (op) {
2355 	case SNMP_OP_GET:
2356 		if ((wmr = wlan_mesh_get_route(&val->var, sub, &wif)) == NULL)
2357 			return (SNMP_ERR_NOSUCHNAME);
2358 		break;
2359 
2360 	case SNMP_OP_GETNEXT:
2361 		wmr = wlan_mesh_get_next_route(&val->var, sub, &wif);
2362 		if (wmr == NULL)
2363 			return (SNMP_ERR_NOSUCHNAME);
2364 		wlan_append_mac_index(&val->var, sub, wif->wname,
2365 		    wmr->imroute.imr_dest);
2366 		break;
2367 
2368 	case SNMP_OP_SET:
2369 		switch (val->var.subs[sub - 1]) {
2370 		case LEAF_wlanMeshRouteDestination:
2371 			return (SNMP_ERR_INCONS_NAME);
2372 		case LEAF_wlanMeshRouteStatus:
2373 			return(wlan_mesh_route_set_status(ctx, val, sub));
2374 		default:
2375 			return (SNMP_ERR_NOT_WRITEABLE);
2376 		}
2377 		abort();
2378 
2379 	case SNMP_OP_COMMIT:
2380 		if ((wmr = wlan_mesh_get_route(&val->var, sub, &wif)) == NULL)
2381 			return (SNMP_ERR_NOSUCHNAME);
2382 		if (val->v.integer == RowStatus_destroy &&
2383 		    wlan_mesh_delete_route(wif, wmr) < 0)
2384 			return (SNMP_ERR_GENERR);
2385 		return (SNMP_ERR_NOERROR);
2386 
2387 	case SNMP_OP_ROLLBACK:
2388 		if ((wmr = wlan_mesh_get_route(&val->var, sub, &wif)) == NULL)
2389 			return (SNMP_ERR_NOSUCHNAME);
2390 		if (ctx->scratch->int1 == RowStatus_destroy &&
2391 		    wlan_mesh_delete_route(wif, wmr) < 0)
2392 			return (SNMP_ERR_GENERR);
2393 		return (SNMP_ERR_NOERROR);
2394 
2395 	default:
2396 		abort();
2397 	}
2398 
2399 	switch (val->var.subs[sub - 1]) {
2400 	case LEAF_wlanMeshRouteDestination:
2401 		return (string_get(val, wmr->imroute.imr_dest,
2402 		    IEEE80211_ADDR_LEN));
2403 	case LEAF_wlanMeshRouteNextHop:
2404 		return (string_get(val, wmr->imroute.imr_nexthop,
2405 		    IEEE80211_ADDR_LEN));
2406 	case LEAF_wlanMeshRouteHops:
2407 		val->v.integer = wmr->imroute.imr_nhops;
2408 		break;
2409 	case LEAF_wlanMeshRouteMetric:
2410 		val->v.integer = wmr->imroute.imr_metric;
2411 		break;
2412 	case LEAF_wlanMeshRouteLifeTime:
2413 		val->v.integer = wmr->imroute.imr_lifetime;
2414 		break;
2415 	case LEAF_wlanMeshRouteLastMseq:
2416 		val->v.integer = wmr->imroute.imr_lastmseq;
2417 		break;
2418 	case LEAF_wlanMeshRouteFlags:
2419 		val->v.integer = 0;
2420 		if ((wmr->imroute.imr_flags &
2421 		    IEEE80211_MESHRT_FLAGS_VALID) != 0)
2422 			val->v.integer |= (0x1 << wlanMeshRouteFlags_valid);
2423 		if ((wmr->imroute.imr_flags &
2424 		    IEEE80211_MESHRT_FLAGS_PROXY) != 0)
2425 			val->v.integer |= (0x1 << wlanMeshRouteFlags_proxy);
2426 		return (bits_get(val, (uint8_t *)&val->v.integer,
2427 		    sizeof(val->v.integer)));
2428 	case LEAF_wlanMeshRouteStatus:
2429 		val->v.integer = wmr->mroute_status;
2430 		break;
2431 	}
2432 
2433 	return (SNMP_ERR_NOERROR);
2434 }
2435 
2436 int
2437 op_wlan_mesh_stats(struct snmp_context *ctx __unused, struct snmp_value *val,
2438     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2439 {
2440 	struct wlan_iface *wif;
2441 
2442 	wlan_update_interface_list();
2443 
2444 	switch (op) {
2445 	case SNMP_OP_GET:
2446 		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2447 			return (SNMP_ERR_NOSUCHNAME);
2448 		break;
2449 	case SNMP_OP_GETNEXT:
2450 		if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)
2451 			return (SNMP_ERR_NOSUCHNAME);
2452 		wlan_append_ifindex(&val->var, sub, wif);
2453 		break;
2454 	case SNMP_OP_SET:
2455 		return (SNMP_ERR_NOT_WRITEABLE);
2456 	case SNMP_OP_COMMIT:
2457 		/* FALLTHROUGH */
2458 	case SNMP_OP_ROLLBACK:
2459 		/* FALLTHROUGH */
2460 	default:
2461 		abort();
2462 	}
2463 
2464 	if (wlan_get_stats(wif) < 0)
2465 		return (SNMP_ERR_GENERR);
2466 
2467 	switch (val->var.subs[sub - 1]) {
2468 	case LEAF_wlanMeshDroppedBadSta:
2469 		val->v.uint32 = wif->stats.is_mesh_wrongmesh;
2470 		break;
2471 	case LEAF_wlanMeshDroppedNoLink:
2472 		val->v.uint32 = wif->stats.is_mesh_nolink;
2473 		break;
2474 	case LEAF_wlanMeshNoFwdTtl:
2475 		val->v.uint32 = wif->stats.is_mesh_fwd_ttl;
2476 		break;
2477 	case LEAF_wlanMeshNoFwdBuf:
2478 		val->v.uint32 = wif->stats.is_mesh_fwd_nobuf;
2479 		break;
2480 	case LEAF_wlanMeshNoFwdTooShort:
2481 		val->v.uint32 = wif->stats.is_mesh_fwd_tooshort;
2482 		break;
2483 	case LEAF_wlanMeshNoFwdDisabled:
2484 		val->v.uint32 = wif->stats.is_mesh_fwd_disabled;
2485 		break;
2486 	case LEAF_wlanMeshNoFwdPathUnknown:
2487 		val->v.uint32 = wif->stats.is_mesh_fwd_nopath;
2488 		break;
2489 	case LEAF_wlanMeshDroppedBadAE:
2490 		val->v.uint32 = wif->stats.is_mesh_badae;
2491 		break;
2492 	case LEAF_wlanMeshRouteAddFailed:
2493 		val->v.uint32 = wif->stats.is_mesh_rtaddfailed;
2494 		break;
2495 	case LEAF_wlanMeshDroppedNoProxy:
2496 		val->v.uint32 = wif->stats.is_mesh_notproxy;
2497 		break;
2498 	case LEAF_wlanMeshDroppedMisaligned:
2499 		val->v.uint32 = wif->stats.is_rx_badalign;
2500 		break;
2501 	default:
2502 		abort();
2503 	}
2504 
2505 	return (SNMP_ERR_NOERROR);
2506 }
2507 
2508 int
2509 op_wlan_hwmp_config(struct snmp_context *ctx, struct snmp_value *val,
2510     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2511 {
2512 	int which;
2513 
2514 	switch (val->var.subs[sub - 1]) {
2515 	case LEAF_wlanHWMPRouteInactiveTimeout:
2516 		which = WLAN_HWMP_INACTIVITY_TO;
2517 		break;
2518 	case LEAF_wlanHWMPRootAnnounceInterval:
2519 		which = WLAN_HWMP_RANN_INT;
2520 		break;
2521 	case LEAF_wlanHWMPRootInterval:
2522 		which = WLAN_HWMP_ROOT_INT;
2523 		break;
2524 	case LEAF_wlanHWMPRootTimeout:
2525 		which = WLAN_HWMP_ROOT_TO;
2526 		break;
2527 	case LEAF_wlanHWMPPathLifetime:
2528 		which = WLAN_HWMP_PATH_LIFETIME;
2529 		break;
2530 	case LEAF_wlanHWMPReplyForwardBit:
2531 		which = WLAN_HWMP_REPLY_FORWARD;
2532 		break;
2533 	case LEAF_wlanHWMPTargetOnlyBit:
2534 		which = WLAN_HWMP_TARGET_ONLY;
2535 		break;
2536 	default:
2537 		abort();
2538 	}
2539 
2540 	switch (op) {
2541 	case SNMP_OP_GET:
2542 		if (wlan_do_sysctl(&wlan_config, which, 0) < 0)
2543 			return (SNMP_ERR_GENERR);
2544 		break;
2545 
2546 	case SNMP_OP_GETNEXT:
2547 		abort();
2548 
2549 	case SNMP_OP_SET:
2550 		switch (val->var.subs[sub - 1]) {
2551 		case LEAF_wlanHWMPRouteInactiveTimeout:
2552 			ctx->scratch->int1 = wlan_config.hwmp_inact;
2553 			wlan_config.hwmp_inact = val->v.integer;
2554 			break;
2555 		case LEAF_wlanHWMPRootAnnounceInterval:
2556 			ctx->scratch->int1 = wlan_config.hwmp_rannint;
2557 			wlan_config.hwmp_rannint = val->v.integer;
2558 			break;
2559 		case LEAF_wlanHWMPRootInterval:
2560 			ctx->scratch->int1 = wlan_config.hwmp_rootint;
2561 			wlan_config.hwmp_rootint = val->v.integer;
2562 			break;
2563 		case LEAF_wlanHWMPRootTimeout:
2564 			ctx->scratch->int1 = wlan_config.hwmp_roottimeout;
2565 			wlan_config.hwmp_roottimeout = val->v.integer;
2566 			break;
2567 		case LEAF_wlanHWMPPathLifetime:
2568 			ctx->scratch->int1 = wlan_config.hwmp_pathlifetime;
2569 			wlan_config.hwmp_pathlifetime = val->v.integer;
2570 			break;
2571 		case LEAF_wlanHWMPReplyForwardBit:
2572 			ctx->scratch->int1 = wlan_config.hwmp_replyforward;
2573 			wlan_config.hwmp_replyforward = val->v.integer;
2574 			break;
2575 		case LEAF_wlanHWMPTargetOnlyBit:
2576 			ctx->scratch->int1 = wlan_config.hwmp_targetonly;
2577 			wlan_config.hwmp_targetonly = val->v.integer;
2578 			break;
2579 		}
2580 		if (wlan_do_sysctl(&wlan_config, which, 1) < 0)
2581 			return (SNMP_ERR_GENERR);
2582 		return (SNMP_ERR_NOERROR);
2583 
2584 	case SNMP_OP_COMMIT:
2585 		return (SNMP_ERR_NOERROR);
2586 
2587 	case SNMP_OP_ROLLBACK:
2588 		switch (val->var.subs[sub - 1]) {
2589 		case LEAF_wlanHWMPRouteInactiveTimeout:
2590 			wlan_config.hwmp_inact = ctx->scratch->int1;
2591 			break;
2592 		case LEAF_wlanHWMPRootAnnounceInterval:
2593 			wlan_config.hwmp_rannint = ctx->scratch->int1;
2594 			break;
2595 		case LEAF_wlanHWMPRootInterval:
2596 			wlan_config.hwmp_rootint = ctx->scratch->int1;
2597 			break;
2598 		case LEAF_wlanHWMPRootTimeout:
2599 			wlan_config.hwmp_roottimeout = ctx->scratch->int1;
2600 			break;
2601 		case LEAF_wlanHWMPPathLifetime:
2602 			wlan_config.hwmp_pathlifetime = ctx->scratch->int1;
2603 			break;
2604 		case LEAF_wlanHWMPReplyForwardBit:
2605 			wlan_config.hwmp_replyforward = ctx->scratch->int1;
2606 			break;
2607 		case LEAF_wlanHWMPTargetOnlyBit:
2608 			wlan_config.hwmp_targetonly = ctx->scratch->int1;
2609 			break;
2610 		}
2611 		if (wlan_do_sysctl(&wlan_config, which, 1) < 0)
2612 			return (SNMP_ERR_GENERR);
2613 		return (SNMP_ERR_NOERROR);
2614 
2615 	default:
2616 		abort();
2617 	}
2618 
2619 	switch (val->var.subs[sub - 1]) {
2620 	case LEAF_wlanHWMPRouteInactiveTimeout:
2621 		val->v.integer = wlan_config.hwmp_inact;
2622 		break;
2623 	case LEAF_wlanHWMPRootAnnounceInterval:
2624 		val->v.integer = wlan_config.hwmp_rannint;
2625 		break;
2626 	case LEAF_wlanHWMPRootInterval:
2627 		val->v.integer = wlan_config.hwmp_rootint;
2628 		break;
2629 	case LEAF_wlanHWMPRootTimeout:
2630 		val->v.integer = wlan_config.hwmp_roottimeout;
2631 		break;
2632 	case LEAF_wlanHWMPPathLifetime:
2633 		val->v.integer = wlan_config.hwmp_pathlifetime;
2634 		break;
2635 	case LEAF_wlanHWMPReplyForwardBit:
2636 		val->v.integer = wlan_config.hwmp_replyforward;
2637 		break;
2638 	case LEAF_wlanHWMPTargetOnlyBit:
2639 		val->v.integer = wlan_config.hwmp_targetonly;
2640 		break;
2641 	}
2642 
2643 	return (SNMP_ERR_NOERROR);
2644 }
2645 
2646 int
2647 op_wlan_hwmp_iface(struct snmp_context *ctx, struct snmp_value *val,
2648     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2649 {
2650 	struct wlan_iface *wif;
2651 
2652 	wlan_update_interface_list();
2653 
2654 	switch (op) {
2655 	case SNMP_OP_GET:
2656 		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2657 			return (SNMP_ERR_NOSUCHNAME);
2658 		break;
2659 
2660 	case SNMP_OP_GETNEXT:
2661 		if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)
2662 			return (SNMP_ERR_NOSUCHNAME);
2663 		wlan_append_ifindex(&val->var, sub, wif);
2664 		break;
2665 
2666 	case SNMP_OP_SET:
2667 		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2668 			return (SNMP_ERR_NOSUCHNAME);
2669 		switch (val->var.subs[sub - 1]) {
2670 		case LEAF_wlanHWMPRootMode:
2671 			ctx->scratch->int1 = wif->hwmp_root_mode;
2672 			wif->hwmp_root_mode = val->v.integer;
2673 			break;
2674 		case LEAF_wlanHWMPMaxHops:
2675 			ctx->scratch->int1 = wif->hwmp_max_hops;
2676 			wif->hwmp_max_hops = val->v.integer;
2677 			break;
2678 		default:
2679 			abort();
2680 		}
2681 		if (wlan_hwmp_config_set(wif, val->var.subs[sub - 1]) < 0)
2682 			return (SNMP_ERR_GENERR);
2683 		return (SNMP_ERR_NOERROR);
2684 
2685 	case SNMP_OP_COMMIT:
2686 		return (SNMP_ERR_NOERROR);
2687 
2688 	case SNMP_OP_ROLLBACK:
2689 		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2690 			return (SNMP_ERR_NOSUCHNAME);
2691 		switch (val->var.subs[sub - 1]) {
2692 		case LEAF_wlanHWMPRootMode:
2693 			wif->hwmp_root_mode = ctx->scratch->int1;
2694 			break;
2695 		case LEAF_wlanHWMPMaxHops:
2696 			wif->hwmp_max_hops = ctx->scratch->int1;
2697 			break;
2698 		default:
2699 			abort();
2700 		}
2701 		if (wlan_hwmp_config_set(wif, val->var.subs[sub - 1]) < 0)
2702 			return (SNMP_ERR_GENERR);
2703 		return (SNMP_ERR_NOERROR);
2704 
2705 	default:
2706 		abort();
2707 	}
2708 
2709 	if (wlan_hwmp_config_get(wif, val->var.subs[sub - 1]) < 0)
2710 		return (SNMP_ERR_GENERR);
2711 
2712 	switch (val->var.subs[sub - 1]) {
2713 	case LEAF_wlanHWMPRootMode:
2714 		val->v.integer = wif->hwmp_root_mode;
2715 		break;
2716 	case LEAF_wlanHWMPMaxHops:
2717 		val->v.integer = wif->hwmp_max_hops;
2718 		break;
2719 	default:
2720 		abort();
2721 	}
2722 
2723 	return (SNMP_ERR_NOERROR);
2724 }
2725 
2726 int
2727 op_wlan_hwmp_stats(struct snmp_context *ctx __unused, struct snmp_value *val,
2728     uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2729 {
2730 	struct wlan_iface *wif;
2731 
2732 	wlan_update_interface_list();
2733 
2734 	switch (op) {
2735 	case SNMP_OP_GET:
2736 		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2737 			return (SNMP_ERR_NOSUCHNAME);
2738 		break;
2739 	case SNMP_OP_GETNEXT:
2740 		if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)
2741 			return (SNMP_ERR_NOSUCHNAME);
2742 		wlan_append_ifindex(&val->var, sub, wif);
2743 		break;
2744 	case SNMP_OP_SET:
2745 		return (SNMP_ERR_NOT_WRITEABLE);
2746 	case SNMP_OP_COMMIT:
2747 		/* FALLTHROUGH */
2748 	case SNMP_OP_ROLLBACK:
2749 		/* FALLTHROUGH */
2750 	default:
2751 		abort();
2752 	}
2753 
2754 	if (wlan_get_stats(wif) < 0)
2755 		return (SNMP_ERR_GENERR);
2756 
2757 	switch (val->var.subs[sub - 1]) {
2758 	case LEAF_wlanMeshHWMPWrongSeqNo:
2759 		val->v.uint32 = wif->stats.is_hwmp_wrongseq;
2760 		break;
2761 	case LEAF_wlanMeshHWMPTxRootPREQ:
2762 		val->v.uint32 = wif->stats.is_hwmp_rootreqs;
2763 		break;
2764 	case LEAF_wlanMeshHWMPTxRootRANN:
2765 		val->v.uint32 = wif->stats.is_hwmp_rootrann;
2766 		break;
2767 	case LEAF_wlanMeshHWMPProxy:
2768 		val->v.uint32 = wif->stats.is_hwmp_proxy;
2769 		break;
2770 	default:
2771 		abort();
2772 	}
2773 
2774 	return (SNMP_ERR_NOERROR);
2775 }
2776 
2777 /*
2778  * Encode BITS type for a response packet - XXX: this belongs to the snmp lib.
2779  */
2780 static int
2781 bits_get(struct snmp_value *value, const u_char *ptr, ssize_t len)
2782 {
2783 	int size;
2784 
2785 	if (ptr == NULL) {
2786 		value->v.octetstring.len = 0;
2787 		value->v.octetstring.octets = NULL;
2788 		return (SNMP_ERR_NOERROR);
2789 	}
2790 
2791 	/* Determine length - up to 8 octets supported so far. */
2792 	for (size = len; size > 0; size--)
2793 		if (ptr[size - 1] != 0)
2794 			break;
2795 	if (size == 0)
2796 		size = 1;
2797 
2798 	value->v.octetstring.len = (u_long)size;
2799 	if ((value->v.octetstring.octets = malloc((size_t)size)) == NULL)
2800 		return (SNMP_ERR_RES_UNAVAIL);
2801 	memcpy(value->v.octetstring.octets, ptr, (size_t)size);
2802 	return (SNMP_ERR_NOERROR);
2803 }
2804 
2805 /*
2806  * Calls for adding/updating/freeing/etc of wireless interfaces.
2807  */
2808 static void
2809 wlan_free_interface(struct wlan_iface *wif)
2810 {
2811 	wlan_free_peerlist(wif);
2812 	free(wif->chanlist);
2813 	wlan_scan_free_results(wif);
2814 	wlan_mac_free_maclist(wif);
2815 	wlan_mesh_free_routes(wif);
2816 	free(wif);
2817 }
2818 
2819 static void
2820 wlan_free_iflist(void)
2821 {
2822 	struct wlan_iface *w;
2823 
2824 	while ((w = SLIST_FIRST(&wlan_ifaces)) != NULL) {
2825 		SLIST_REMOVE_HEAD(&wlan_ifaces, w_if);
2826 		wlan_free_interface(w);
2827 	}
2828 }
2829 
2830 static struct wlan_iface *
2831 wlan_find_interface(const char *wname)
2832 {
2833 	struct wlan_iface *wif;
2834 
2835 	SLIST_FOREACH(wif, &wlan_ifaces, w_if)
2836 		if (strcmp(wif->wname, wname) == 0) {
2837 			if (wif->status != RowStatus_active)
2838 				return (NULL);
2839 			break;
2840 		}
2841 
2842 	return (wif);
2843 }
2844 
2845 static struct wlan_iface *
2846 wlan_first_interface(void)
2847 {
2848 	return (SLIST_FIRST(&wlan_ifaces));
2849 }
2850 
2851 static struct wlan_iface *
2852 wlan_next_interface(struct wlan_iface *wif)
2853 {
2854 	if (wif == NULL)
2855 		return (NULL);
2856 
2857 	return (SLIST_NEXT(wif, w_if));
2858 }
2859 
2860 /*
2861  * Add a new interface to the list - sorted by name.
2862  */
2863 static int
2864 wlan_add_wif(struct wlan_iface *wif)
2865 {
2866 	int cmp;
2867 	struct wlan_iface *temp, *prev;
2868 
2869 	if ((prev = SLIST_FIRST(&wlan_ifaces)) == NULL ||
2870 	    strcmp(wif->wname, prev->wname) < 0) {
2871 		SLIST_INSERT_HEAD(&wlan_ifaces, wif, w_if);
2872 		return (0);
2873 	}
2874 
2875 	SLIST_FOREACH(temp, &wlan_ifaces, w_if) {
2876 		if ((cmp = strcmp(wif->wname, temp->wname)) <= 0)
2877 			break;
2878 		prev = temp;
2879 	}
2880 
2881 	if (temp == NULL)
2882 		SLIST_INSERT_AFTER(prev, wif, w_if);
2883 	else if (cmp > 0)
2884 		SLIST_INSERT_AFTER(temp, wif, w_if);
2885 	else {
2886 		syslog(LOG_ERR, "Wlan iface %s already in list", wif->wname);
2887 		return (-1);
2888 	}
2889 
2890 	return (0);
2891 }
2892 
2893 static struct wlan_iface *
2894 wlan_new_wif(char *wname)
2895 {
2896 	struct wlan_iface *wif;
2897 
2898 	/* Make sure it's not in the list. */
2899 	for (wif = wlan_first_interface(); wif != NULL;
2900 	    wif = wlan_next_interface(wif))
2901 		if (strcmp(wname, wif->wname) == 0) {
2902 			wif->internal = 0;
2903 			return (wif);
2904 		}
2905 
2906 	if ((wif = (struct wlan_iface *)malloc(sizeof(*wif))) == NULL)
2907 		return (NULL);
2908 
2909 	memset(wif, 0, sizeof(struct wlan_iface));
2910 	strlcpy(wif->wname, wname, IFNAMSIZ);
2911 	wif->status = RowStatus_notReady;
2912 	wif->state = wlanIfaceState_down;
2913 	wif->mode = WlanIfaceOperatingModeType_station;
2914 
2915 	if (wlan_add_wif(wif) < 0) {
2916 		free(wif);
2917 		return (NULL);
2918 	}
2919 
2920 	return (wif);
2921 }
2922 
2923 static void
2924 wlan_delete_wif(struct wlan_iface *wif)
2925 {
2926 	SLIST_REMOVE(&wlan_ifaces, wif, wlan_iface, w_if);
2927 	wlan_free_interface(wif);
2928 }
2929 
2930 static int
2931 wlan_attach_newif(struct mibif *mif)
2932 {
2933 	struct wlan_iface *wif;
2934 
2935 	if (mif->mib.ifmd_data.ifi_type != IFT_ETHER ||
2936 	    wlan_check_media(mif->name) != IFM_IEEE80211)
2937 		return (0);
2938 
2939 	if ((wif = wlan_new_wif(mif->name)) == NULL)
2940 		return (-1);
2941 
2942 	(void)wlan_get_opmode(wif);
2943 	wif->index = mif->index;
2944 	wif->status = RowStatus_active;
2945 	(void)wlan_update_interface(wif);
2946 
2947 	return (0);
2948 }
2949 
2950 static int
2951 wlan_iface_create(struct wlan_iface *wif)
2952 {
2953 	int rc;
2954 
2955 	if ((rc = wlan_clone_create(wif)) == SNMP_ERR_NOERROR) {
2956 		/*
2957 		 * The rest of the info will be updated once the
2958 		 * snmp_mibII module notifies us of the interface.
2959 		 */
2960 		wif->status = RowStatus_active;
2961 		if (wif->state == wlanIfaceState_up)
2962 			(void)wlan_config_state(wif, 1);
2963 	}
2964 
2965 	return (rc);
2966 }
2967 
2968 static int
2969 wlan_iface_destroy(struct wlan_iface *wif)
2970 {
2971 	int rc = SNMP_ERR_NOERROR;
2972 
2973 	if (wif->internal == 0)
2974 		rc = wlan_clone_destroy(wif);
2975 
2976 	if (rc == SNMP_ERR_NOERROR)
2977 		wlan_delete_wif(wif);
2978 
2979 	return (rc);
2980 }
2981 
2982 static int
2983 wlan_update_interface(struct wlan_iface *wif)
2984 {
2985 	int i;
2986 
2987 	(void)wlan_config_state(wif, 0);
2988 	(void)wlan_get_driver_caps(wif);
2989 	for (i = LEAF_wlanIfacePacketBurst;
2990 	    i <= LEAF_wlanIfaceTdmaBeaconInterval; i++)
2991 		(void)wlan_config_get_ioctl(wif, i);
2992 	(void)wlan_get_stats(wif);
2993 	/*
2994 	 * XXX: wlan_get_channel_list() not needed -
2995 	 * fetched with wlan_get_driver_caps()
2996 	 */
2997 	(void)wlan_get_channel_list(wif);
2998 	(void)wlan_get_roam_params(wif);
2999 	(void)wlan_get_tx_params(wif);
3000 	(void)wlan_get_scan_results(wif);
3001 	(void)wlan_get_wepmode(wif);
3002 	(void)wlan_get_weptxkey(wif);
3003 	(void)wlan_get_mac_policy(wif);
3004 	(void)wlan_get_mac_acl_macs(wif);
3005 	(void)wlan_get_peerinfo(wif);
3006 
3007 	if (wif->mode == WlanIfaceOperatingModeType_meshPoint) {
3008 		for (i = LEAF_wlanMeshTTL; i <= LEAF_wlanMeshPath; i++)
3009 			(void)wlan_mesh_config_get(wif, i);
3010 		(void)wlan_mesh_get_routelist(wif);
3011 		for (i = LEAF_wlanHWMPRootMode; i <= LEAF_wlanHWMPMaxHops; i++)
3012 			(void)wlan_hwmp_config_get(wif, i);
3013 	}
3014 
3015 	return (0);
3016 }
3017 
3018 static void
3019 wlan_update_interface_list(void)
3020 {
3021 	struct wlan_iface *wif, *twif;
3022 
3023 	if ((time(NULL) - wlan_iflist_age) <= WLAN_LIST_MAXAGE)
3024 		return;
3025 
3026 	/*
3027 	 * The snmp_mibII module would have notified us for new interfaces,
3028 	 * so only check if any have been deleted.
3029 	 */
3030 	SLIST_FOREACH_SAFE(wif, &wlan_ifaces, w_if, twif)
3031 		if (wif->status == RowStatus_active && wlan_get_opmode(wif) < 0)
3032 			wlan_delete_wif(wif);
3033 
3034 	wlan_iflist_age = time(NULL);
3035 }
3036 
3037 static void
3038 wlan_append_ifindex(struct asn_oid *oid, uint sub, const struct wlan_iface *w)
3039 {
3040 	uint32_t i;
3041 
3042 	oid->len = sub + strlen(w->wname) + 1;
3043 	oid->subs[sub] = strlen(w->wname);
3044 	for (i = 1; i <= strlen(w->wname); i++)
3045 		oid->subs[sub + i] = w->wname[i - 1];
3046 }
3047 
3048 static uint8_t *
3049 wlan_get_ifname(const struct asn_oid *oid, uint sub, uint8_t *wname)
3050 {
3051 	uint32_t i;
3052 
3053 	memset(wname, 0, IFNAMSIZ);
3054 
3055 	if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
3056 		return (NULL);
3057 
3058 	for (i = 0; i < oid->subs[sub]; i++)
3059 		wname[i] = oid->subs[sub + i + 1];
3060 	wname[i] = '\0';
3061 
3062 	return (wname);
3063 }
3064 
3065 static struct wlan_iface *
3066 wlan_get_interface(const struct asn_oid *oid, uint sub)
3067 {
3068 	uint8_t wname[IFNAMSIZ];
3069 
3070 	if (wlan_get_ifname(oid, sub, wname) == NULL)
3071 		return (NULL);
3072 
3073 	return (wlan_find_interface(wname));
3074 }
3075 
3076 static struct wlan_iface *
3077 wlan_get_next_interface(const struct asn_oid *oid, uint sub)
3078 {
3079 	uint32_t i;
3080 	uint8_t wname[IFNAMSIZ];
3081 	struct wlan_iface *wif;
3082 
3083 	if (oid->len - sub == 0) {
3084 		for (wif = wlan_first_interface(); wif != NULL;
3085 		    wif = wlan_next_interface(wif))
3086 			if (wif->status == RowStatus_active)
3087 				break;
3088 		return (wif);
3089 	}
3090 
3091 	if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
3092 		return (NULL);
3093 
3094 	memset(wname, 0, IFNAMSIZ);
3095 	for (i = 0; i < oid->subs[sub]; i++)
3096 		wname[i] = oid->subs[sub + i + 1];
3097 	wname[i] = '\0';
3098 	if ((wif = wlan_find_interface(wname)) == NULL)
3099 		return (NULL);
3100 
3101 	while ((wif = wlan_next_interface(wif)) != NULL)
3102 		if (wif->status == RowStatus_active)
3103 			break;
3104 
3105 	return (wif);
3106 }
3107 
3108 static struct wlan_iface *
3109 wlan_get_snmp_interface(const struct asn_oid *oid, uint sub)
3110 {
3111 	uint8_t wname[IFNAMSIZ];
3112 	struct wlan_iface *wif;
3113 
3114 	if (wlan_get_ifname(oid, sub, wname) == NULL)
3115 		return (NULL);
3116 
3117 	for (wif = wlan_first_interface(); wif != NULL;
3118 	    wif = wlan_next_interface(wif))
3119 		if (strcmp(wif->wname, wname) == 0)
3120 			break;
3121 
3122 	return (wif);
3123 }
3124 
3125 static struct wlan_iface *
3126 wlan_get_next_snmp_interface(const struct asn_oid *oid, uint sub)
3127 {
3128 	uint32_t i;
3129 	uint8_t wname[IFNAMSIZ];
3130 	struct wlan_iface *wif;
3131 
3132 	if (oid->len - sub == 0)
3133 		return (wlan_first_interface());
3134 
3135 	if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
3136 		return (NULL);
3137 
3138 	memset(wname, 0, IFNAMSIZ);
3139 	for (i = 0; i < oid->subs[sub]; i++)
3140 		wname[i] = oid->subs[sub + i + 1];
3141 	wname[i] = '\0';
3142 
3143 	for (wif = wlan_first_interface(); wif != NULL;
3144 	    wif = wlan_next_interface(wif))
3145 		if (strcmp(wif->wname, wname) == 0)
3146 			break;
3147 
3148 	return (wlan_next_interface(wif));
3149 }
3150 
3151 /*
3152  * Decode/Append an index for tables indexed by the wireless interface
3153  * name and a MAC address - ACL MACs and Mesh Routes.
3154  */
3155 static int
3156 wlan_mac_index_decode(const struct asn_oid *oid, uint sub,
3157     char *wname, uint8_t *mac)
3158 {
3159 	uint32_t i;
3160 	int mac_off;
3161 
3162 	if (oid->len - sub != oid->subs[sub] + 2 + IEEE80211_ADDR_LEN
3163 	    || oid->subs[sub] >= IFNAMSIZ)
3164 		return (-1);
3165 
3166 	for (i = 0; i < oid->subs[sub]; i++)
3167 		wname[i] = oid->subs[sub + i + 1];
3168 	wname[i] = '\0';
3169 
3170 	mac_off = sub + oid->subs[sub] + 1;
3171 	if (oid->subs[mac_off] != IEEE80211_ADDR_LEN)
3172 		return (-1);
3173 	for (i = 0; i < IEEE80211_ADDR_LEN; i++)
3174 		mac[i] = oid->subs[mac_off + i + 1];
3175 
3176 	return (0);
3177 }
3178 
3179 static void
3180 wlan_append_mac_index(struct asn_oid *oid, uint sub, char *wname, uint8_t *mac)
3181 {
3182 	uint32_t i;
3183 
3184 	oid->len = sub + strlen(wname) + IEEE80211_ADDR_LEN + 2;
3185 	oid->subs[sub] = strlen(wname);
3186 	for (i = 1; i <= strlen(wname); i++)
3187 		oid->subs[sub + i] = wname[i - 1];
3188 
3189 	sub += strlen(wname) + 1;
3190 	oid->subs[sub] = IEEE80211_ADDR_LEN;
3191 	for (i = 1; i <= IEEE80211_ADDR_LEN; i++)
3192 		oid->subs[sub + i] = mac[i - 1];
3193 }
3194 
3195 /*
3196  * Decode/Append an index for tables indexed by the wireless interface
3197  * name and the PHY mode - Roam and TX params.
3198  */
3199 static int
3200 wlan_phy_index_decode(const struct asn_oid *oid, uint sub, char *wname,
3201     uint32_t *phy)
3202 {
3203 	uint32_t i;
3204 
3205 	if (oid->len - sub != oid->subs[sub] + 2 || oid->subs[sub] >= IFNAMSIZ)
3206 		return (-1);
3207 
3208 	for (i = 0; i < oid->subs[sub]; i++)
3209 		wname[i] = oid->subs[sub + i + 1];
3210 	wname[i] = '\0';
3211 
3212 	*phy = oid->subs[sub + oid->subs[sub] + 1];
3213 	return (0);
3214 }
3215 
3216 static void
3217 wlan_append_phy_index(struct asn_oid *oid, uint sub, char *wname, uint32_t phy)
3218 {
3219 	uint32_t i;
3220 
3221 	oid->len = sub + strlen(wname) + 2;
3222 	oid->subs[sub] = strlen(wname);
3223 	for (i = 1; i <= strlen(wname); i++)
3224 		oid->subs[sub + i] = wname[i - 1];
3225 	oid->subs[sub + strlen(wname) + 1] = phy;
3226 }
3227 
3228 /*
3229  * Calls for manipulating the peerlist of a wireless interface.
3230  */
3231 static void
3232 wlan_free_peerlist(struct wlan_iface *wif)
3233 {
3234 	struct wlan_peer *wip;
3235 
3236 	while ((wip = SLIST_FIRST(&wif->peerlist)) != NULL) {
3237 		SLIST_REMOVE_HEAD(&wif->peerlist, wp);
3238 		free(wip);
3239 	}
3240 
3241 	SLIST_INIT(&wif->peerlist);
3242 }
3243 
3244 static struct wlan_peer *
3245 wlan_find_peer(struct wlan_iface *wif, uint8_t *peermac)
3246 {
3247 	struct wlan_peer *wip;
3248 
3249 	SLIST_FOREACH(wip, &wif->peerlist, wp)
3250 		if (memcmp(wip->pmac, peermac, IEEE80211_ADDR_LEN) == 0)
3251 			break;
3252 
3253 	return (wip);
3254 }
3255 
3256 struct wlan_peer *
3257 wlan_new_peer(const uint8_t *pmac)
3258 {
3259 	struct wlan_peer *wip;
3260 
3261 	if ((wip = (struct wlan_peer *)malloc(sizeof(*wip))) == NULL)
3262 		return (NULL);
3263 
3264 	memset(wip, 0, sizeof(struct wlan_peer));
3265 	memcpy(wip->pmac, pmac, IEEE80211_ADDR_LEN);
3266 
3267 	return (wip);
3268 }
3269 
3270 void
3271 wlan_free_peer(struct wlan_peer *wip)
3272 {
3273 	free(wip);
3274 }
3275 
3276 int
3277 wlan_add_peer(struct wlan_iface *wif, struct wlan_peer *wip)
3278 {
3279 	struct wlan_peer *temp, *prev;
3280 
3281 	SLIST_FOREACH(temp, &wif->peerlist, wp)
3282 		if (memcmp(temp->pmac, wip->pmac, IEEE80211_ADDR_LEN) == 0)
3283 			return (-1);
3284 
3285 	if ((prev = SLIST_FIRST(&wif->peerlist)) == NULL ||
3286 	    memcmp(wip->pmac, prev->pmac, IEEE80211_ADDR_LEN) < 0) {
3287 	    	SLIST_INSERT_HEAD(&wif->peerlist, wip, wp);
3288 	    	return (0);
3289 	}
3290 
3291 	SLIST_FOREACH(temp, &wif->peerlist, wp) {
3292 		if (memcmp(wip->pmac, temp->pmac, IEEE80211_ADDR_LEN) < 0)
3293 			break;
3294 		prev = temp;
3295 	}
3296 
3297 	SLIST_INSERT_AFTER(prev, wip, wp);
3298 	return (0);
3299 }
3300 
3301 static void
3302 wlan_update_peers(void)
3303 {
3304 	struct wlan_iface *wif;
3305 
3306 	if ((time(NULL) - wlan_peerlist_age) <= WLAN_LIST_MAXAGE)
3307 		return;
3308 
3309 	for (wif = wlan_first_interface(); wif != NULL;
3310 	    wif = wlan_next_interface(wif)) {
3311 		if (wif->status != RowStatus_active)
3312 			continue;
3313 		wlan_free_peerlist(wif);
3314 		(void)wlan_get_peerinfo(wif);
3315 	}
3316 	wlan_peerlist_age = time(NULL);
3317 }
3318 
3319 static struct wlan_peer *
3320 wlan_get_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3321 {
3322 	char wname[IFNAMSIZ];
3323 	uint8_t pmac[IEEE80211_ADDR_LEN];
3324 
3325 	if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0)
3326 		return (NULL);
3327 
3328 	if ((*wif = wlan_find_interface(wname)) == NULL)
3329 		return (NULL);
3330 
3331 	return (wlan_find_peer(*wif, pmac));
3332 }
3333 
3334 static struct wlan_peer *
3335 wlan_get_next_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3336 {
3337 	char wname[IFNAMSIZ];
3338 	char pmac[IEEE80211_ADDR_LEN];
3339 	struct wlan_peer *wip;
3340 
3341 	if (oid->len - sub == 0) {
3342 		for (*wif = wlan_first_interface(); *wif != NULL;
3343 		    *wif = wlan_next_interface(*wif)) {
3344 			if ((*wif)->mode ==
3345 			    WlanIfaceOperatingModeType_meshPoint)
3346 				continue;
3347 			wip = SLIST_FIRST(&(*wif)->peerlist);
3348 			if (wip != NULL)
3349 				return (wip);
3350 		}
3351 		return (NULL);
3352 	}
3353 
3354 	if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0 ||
3355 	    (*wif = wlan_find_interface(wname)) == NULL ||
3356 	    (wip = wlan_find_peer(*wif, pmac)) == NULL)
3357 		return (NULL);
3358 
3359 	if ((wip = SLIST_NEXT(wip, wp)) != NULL)
3360 		return (wip);
3361 
3362 	while ((*wif = wlan_next_interface(*wif)) != NULL) {
3363 		if ((*wif)->mode == WlanIfaceOperatingModeType_meshPoint)
3364 			continue;
3365 		if ((wip = SLIST_FIRST(&(*wif)->peerlist)) != NULL)
3366 			break;
3367 	}
3368 
3369 	return (wip);
3370 }
3371 
3372 /*
3373  * Calls for manipulating the active channel list of a wireless interface.
3374  */
3375 static void
3376 wlan_update_channels(void)
3377 {
3378 	struct wlan_iface *wif;
3379 
3380 	if ((time(NULL) - wlan_chanlist_age) <= WLAN_LIST_MAXAGE)
3381 		return;
3382 
3383 	for (wif = wlan_first_interface(); wif != NULL;
3384 	    wif = wlan_next_interface(wif)) {
3385 		if (wif->status != RowStatus_active)
3386 			continue;
3387 		(void)wlan_get_channel_list(wif);
3388 	}
3389 	wlan_chanlist_age = time(NULL);
3390 }
3391 
3392 static int
3393 wlan_channel_index_decode(const struct asn_oid *oid, uint sub, char *wname,
3394     uint32_t *cindex)
3395 {
3396 	uint32_t i;
3397 	if (oid->len - sub != oid->subs[sub] + 2 || oid->subs[sub] >= IFNAMSIZ)
3398 		return (-1);
3399 
3400 	for (i = 0; i < oid->subs[sub]; i++)
3401 		wname[i] = oid->subs[sub + i + 1];
3402 	wname[i] = '\0';
3403 
3404 	*cindex = oid->subs[sub + oid->subs[sub] + 1];
3405 
3406 	return (0);
3407 }
3408 
3409 static void
3410 wlan_append_channel_index(struct asn_oid *oid, uint sub,
3411     const struct wlan_iface *wif, const struct ieee80211_channel *channel)
3412 {
3413 	uint32_t i;
3414 
3415 	oid->len = sub + strlen(wif->wname) + 2;
3416 	oid->subs[sub] = strlen(wif->wname);
3417 	for (i = 1; i <= strlen(wif->wname); i++)
3418 		oid->subs[sub + i] = wif->wname[i - 1];
3419 	oid->subs[sub + strlen(wif->wname) + 1] = (channel - wif->chanlist) + 1;
3420 }
3421 
3422 static int32_t
3423 wlan_get_channel_type(struct ieee80211_channel *c)
3424 {
3425 	if (IEEE80211_IS_CHAN_FHSS(c))
3426 		return (WlanChannelType_fhss);
3427 	if (IEEE80211_IS_CHAN_A(c))
3428 		return (WlanChannelType_dot11a);
3429 	if (IEEE80211_IS_CHAN_B(c))
3430 		return (WlanChannelType_dot11b);
3431 	if (IEEE80211_IS_CHAN_ANYG(c))
3432 		return (WlanChannelType_dot11g);
3433 	if (IEEE80211_IS_CHAN_HALF(c))
3434 		return (WlanChannelType_tenMHz);
3435 	if (IEEE80211_IS_CHAN_QUARTER(c))
3436 		return (WlanChannelType_fiveMHz);
3437 	if (IEEE80211_IS_CHAN_TURBO(c))
3438 		return (WlanChannelType_turbo);
3439 	if (IEEE80211_IS_CHAN_HT(c))
3440 		return (WlanChannelType_ht);
3441 
3442 	return (-1);
3443 }
3444 
3445 static struct ieee80211_channel *
3446 wlan_find_channel(struct wlan_iface *wif, uint32_t cindex)
3447 {
3448 	if (wif->chanlist == NULL || cindex > wif->nchannels)
3449 		return (NULL);
3450 
3451 	return (wif->chanlist + cindex - 1);
3452 }
3453 
3454 static struct ieee80211_channel *
3455 wlan_get_channel(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3456 {
3457 	uint32_t cindex;
3458 	char wname[IFNAMSIZ];
3459 
3460 	if (wlan_channel_index_decode(oid, sub, wname, &cindex) < 0)
3461 		return (NULL);
3462 
3463 	if ((*wif = wlan_find_interface(wname)) == NULL)
3464 		return (NULL);
3465 
3466 	return (wlan_find_channel(*wif, cindex));
3467 }
3468 
3469 static struct ieee80211_channel *
3470 wlan_get_next_channel(const struct asn_oid *oid, uint sub,
3471     struct wlan_iface **wif)
3472 {
3473 	uint32_t cindex;
3474 	char wname[IFNAMSIZ];
3475 
3476 	if (oid->len - sub == 0) {
3477 		for (*wif = wlan_first_interface(); *wif != NULL;
3478 		    *wif = wlan_next_interface(*wif)) {
3479 			if ((*wif)->status != RowStatus_active)
3480 				continue;
3481 			if ((*wif)->nchannels != 0 && (*wif)->chanlist != NULL)
3482 				return ((*wif)->chanlist);
3483 		}
3484 		return (NULL);
3485 	}
3486 
3487 	if (wlan_channel_index_decode(oid, sub, wname, &cindex) < 0)
3488 		return (NULL);
3489 
3490 	if ((*wif = wlan_find_interface(wname)) == NULL)
3491 		return (NULL);
3492 
3493 	if (cindex < (*wif)->nchannels)
3494 		return ((*wif)->chanlist + cindex);
3495 
3496 	while ((*wif = wlan_next_interface(*wif)) != NULL)
3497 		if ((*wif)->status == RowStatus_active)
3498 			if ((*wif)->nchannels != 0 && (*wif)->chanlist != NULL)
3499 				return ((*wif)->chanlist);
3500 
3501 	return (NULL);
3502 }
3503 
3504 /*
3505  * Calls for manipulating the roam params of a wireless interface.
3506  */
3507 static void
3508 wlan_update_roam_params(void)
3509 {
3510 	struct wlan_iface *wif;
3511 
3512 	if ((time(NULL) - wlan_roamlist_age) <= WLAN_LIST_MAXAGE)
3513 		return;
3514 
3515 	for (wif = wlan_first_interface(); wif != NULL;
3516 	    wif = wlan_next_interface(wif)) {
3517 		if (wif->status != RowStatus_active)
3518 			continue;
3519 		(void)wlan_get_roam_params(wif);
3520 	}
3521 	wlan_roamlist_age = time(NULL);
3522 }
3523 
3524 static struct ieee80211_roamparam *
3525 wlan_get_roam_param(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3526 {
3527 	uint32_t phy;
3528 	char wname[IFNAMSIZ];
3529 
3530 	if (wlan_phy_index_decode(oid, sub, wname, &phy) < 0)
3531 		return (NULL);
3532 
3533 	if ((*wif = wlan_find_interface(wname)) == NULL)
3534 		return (NULL);
3535 
3536 	if (phy == 0 || phy > IEEE80211_MODE_MAX)
3537 		return (NULL);
3538 
3539 	return ((*wif)->roamparams.params + phy - 1);
3540 }
3541 
3542 static struct ieee80211_roamparam *
3543 wlan_get_next_roam_param(const struct asn_oid *oid, uint sub,
3544     struct wlan_iface **wif, uint32_t *phy)
3545 {
3546 	char wname[IFNAMSIZ];
3547 
3548 	if (oid->len - sub == 0) {
3549 		for (*wif = wlan_first_interface(); *wif != NULL;
3550 		    *wif = wlan_next_interface(*wif)) {
3551 			if ((*wif)->status != RowStatus_active)
3552 				continue;
3553 			*phy = 1;
3554 			return ((*wif)->roamparams.params);
3555 		}
3556 		return (NULL);
3557 	}
3558 
3559 	if (wlan_phy_index_decode(oid, sub, wname, phy) < 0)
3560 		return (NULL);
3561 
3562 	if (*phy == 0  || (*wif = wlan_find_interface(wname)) == NULL)
3563 		return (NULL);
3564 
3565 	if (++(*phy) <= IEEE80211_MODE_MAX)
3566 		return ((*wif)->roamparams.params + *phy - 1);
3567 
3568 	*phy = 1;
3569 	while ((*wif = wlan_next_interface(*wif)) != NULL)
3570 		if ((*wif)->status == RowStatus_active)
3571 			return ((*wif)->roamparams.params);
3572 
3573 	return (NULL);
3574 }
3575 
3576 /*
3577  * Calls for manipulating the tx params of a wireless interface.
3578  */
3579 static void
3580 wlan_update_tx_params(void)
3581 {
3582 	struct wlan_iface *wif;
3583 
3584 	if ((time(NULL) - wlan_tx_paramlist_age) <= WLAN_LIST_MAXAGE)
3585 		return;
3586 
3587 	for (wif = wlan_first_interface(); wif != NULL;
3588 	    wif = wlan_next_interface(wif)) {
3589 		if (wif->status != RowStatus_active)
3590 			continue;
3591 		(void)wlan_get_tx_params(wif);
3592 	}
3593 
3594 	wlan_tx_paramlist_age = time(NULL);
3595 }
3596 
3597 static struct ieee80211_txparam *
3598 wlan_get_tx_param(const struct asn_oid *oid, uint sub, struct wlan_iface **wif,
3599     uint32_t *phy)
3600 {
3601 	char wname[IFNAMSIZ];
3602 
3603 	if (wlan_phy_index_decode(oid, sub, wname, phy) < 0)
3604 		return (NULL);
3605 
3606 	if ((*wif = wlan_find_interface(wname)) == NULL)
3607 		return (NULL);
3608 
3609 	if (*phy == 0 || *phy > IEEE80211_MODE_MAX)
3610 		return (NULL);
3611 
3612 	return ((*wif)->txparams.params + *phy - 1);
3613 }
3614 
3615 static struct ieee80211_txparam *
3616 wlan_get_next_tx_param(const struct asn_oid *oid, uint sub,
3617     struct wlan_iface **wif, uint32_t *phy)
3618 {
3619 	char wname[IFNAMSIZ];
3620 
3621 	if (oid->len - sub == 0) {
3622 		for (*wif = wlan_first_interface(); *wif != NULL;
3623 		    *wif = wlan_next_interface(*wif)) {
3624 			if ((*wif)->status != RowStatus_active)
3625 				continue;
3626 			*phy = 1;
3627 			return ((*wif)->txparams.params);
3628 		}
3629 		return (NULL);
3630 	}
3631 
3632 	if (wlan_phy_index_decode(oid, sub, wname, phy) < 0)
3633 		return (NULL);
3634 
3635 	if (*phy == 0 || (*wif = wlan_find_interface(wname)) == NULL)
3636 		return (NULL);
3637 
3638 	if (++(*phy) <= IEEE80211_MODE_MAX)
3639 		return ((*wif)->txparams.params + *phy - 1);
3640 
3641 	*phy = 1;
3642 	while ((*wif = wlan_next_interface(*wif)) != NULL)
3643 		if ((*wif)->status == RowStatus_active)
3644 			return ((*wif)->txparams.params);
3645 
3646 	return (NULL);
3647 }
3648 
3649 /*
3650  * Calls for manipulating the scan results for a wireless interface.
3651  */
3652 static void
3653 wlan_scan_free_results(struct wlan_iface *wif)
3654 {
3655 	struct wlan_scan_result *sr;
3656 
3657 	while ((sr = SLIST_FIRST(&wif->scanlist)) != NULL) {
3658 		SLIST_REMOVE_HEAD(&wif->scanlist, wsr);
3659 		free(sr);
3660 	}
3661 
3662 	SLIST_INIT(&wif->scanlist);
3663 }
3664 
3665 static struct wlan_scan_result *
3666 wlan_scan_find_result(struct wlan_iface *wif, uint8_t *ssid, uint8_t *bssid)
3667 {
3668 	struct wlan_scan_result *sr;
3669 
3670 	SLIST_FOREACH(sr, &wif->scanlist, wsr)
3671 		if (strlen(ssid) == strlen(sr->ssid) &&
3672 		    strcmp(sr->ssid, ssid) == 0 &&
3673 		    memcmp(sr->bssid, bssid, IEEE80211_ADDR_LEN) == 0)
3674 			break;
3675 
3676 	return (sr);
3677 }
3678 
3679 struct wlan_scan_result *
3680 wlan_scan_new_result(const uint8_t *ssid, const uint8_t *bssid)
3681 {
3682 	struct wlan_scan_result *sr;
3683 
3684 	sr = (struct wlan_scan_result *)malloc(sizeof(*sr));
3685 	if (sr == NULL)
3686 		return (NULL);
3687 
3688 	memset(sr, 0, sizeof(*sr));
3689 	if (ssid[0] != '\0')
3690 		strlcpy(sr->ssid, ssid, IEEE80211_NWID_LEN + 1);
3691 	memcpy(sr->bssid, bssid, IEEE80211_ADDR_LEN);
3692 
3693 	return (sr);
3694 }
3695 
3696 void
3697 wlan_scan_free_result(struct wlan_scan_result *sr)
3698 {
3699 	free(sr);
3700 }
3701 
3702 static int
3703 wlan_scan_compare_result(struct wlan_scan_result *sr1,
3704     struct wlan_scan_result *sr2)
3705 {
3706 	uint32_t i;
3707 
3708 	if (strlen(sr1->ssid) < strlen(sr2->ssid))
3709 		return (-1);
3710 	if (strlen(sr1->ssid) > strlen(sr2->ssid))
3711 		return (1);
3712 
3713 	for (i = 0; i < strlen(sr1->ssid) && i < strlen(sr2->ssid); i++) {
3714 		if (sr1->ssid[i] < sr2->ssid[i])
3715 			return (-1);
3716 		if (sr1->ssid[i] > sr2->ssid[i])
3717 			return (1);
3718 	}
3719 
3720 	for (i = 0; i < IEEE80211_ADDR_LEN; i++) {
3721 		if (sr1->bssid[i] < sr2->bssid[i])
3722 			return (-1);
3723 		if (sr1->bssid[i] > sr2->bssid[i])
3724 			return (1);
3725 	}
3726 
3727 	return (0);
3728 }
3729 
3730 int
3731 wlan_scan_add_result(struct wlan_iface *wif, struct wlan_scan_result *sr)
3732 {
3733 	struct wlan_scan_result *prev, *temp;
3734 
3735 	SLIST_FOREACH(temp, &wif->scanlist, wsr)
3736 		if (strlen(temp->ssid) == strlen(sr->ssid) &&
3737 		    strcmp(sr->ssid, temp->ssid) == 0 &&
3738 		    memcmp(sr->bssid, temp->bssid, IEEE80211_ADDR_LEN) == 0)
3739 			return (-1);
3740 
3741 	if ((prev = SLIST_FIRST(&wif->scanlist)) == NULL ||
3742 	    wlan_scan_compare_result(sr, prev) < 0) {
3743 	    	SLIST_INSERT_HEAD(&wif->scanlist, sr, wsr);
3744 	    	return (0);
3745 	}
3746 
3747 	SLIST_FOREACH(temp, &wif->scanlist, wsr) {
3748 		if (wlan_scan_compare_result(sr, temp) < 0)
3749 			break;
3750 		prev = temp;
3751 	}
3752 
3753 	SLIST_INSERT_AFTER(prev, sr, wsr);
3754 	return (0);
3755 }
3756 
3757 static void
3758 wlan_scan_update_results(void)
3759 {
3760 	struct wlan_iface *wif;
3761 
3762 	if ((time(NULL) - wlan_scanlist_age) <= WLAN_LIST_MAXAGE)
3763 		return;
3764 
3765 	for (wif = wlan_first_interface(); wif != NULL;
3766 	    wif = wlan_next_interface(wif)) {
3767 		if (wif->status != RowStatus_active)
3768 			continue;
3769 		wlan_scan_free_results(wif);
3770 		(void)wlan_get_scan_results(wif);
3771 	}
3772 	wlan_scanlist_age = time(NULL);
3773 }
3774 
3775 static int
3776 wlan_scanr_index_decode(const struct asn_oid *oid, uint sub,
3777     char *wname, uint8_t *ssid, uint8_t *bssid)
3778 {
3779 	uint32_t i;
3780 	int offset;
3781 
3782 	if (oid->subs[sub] >= IFNAMSIZ)
3783 		return (-1);
3784 	for (i = 0; i < oid->subs[sub]; i++)
3785 		wname[i] = oid->subs[sub + i + 1];
3786 	wname[oid->subs[sub]] = '\0';
3787 
3788 	offset = sub + oid->subs[sub] + 1;
3789 	if (oid->subs[offset] > IEEE80211_NWID_LEN)
3790 		return (-1);
3791 	for (i = 0; i < oid->subs[offset]; i++)
3792 		ssid[i] = oid->subs[offset + i + 1];
3793 	ssid[i] = '\0';
3794 
3795 	offset = sub + oid->subs[sub] + oid->subs[offset] + 2;
3796 	if (oid->subs[offset] != IEEE80211_ADDR_LEN)
3797 		return (-1);
3798 	for (i = 0; i < IEEE80211_ADDR_LEN; i++)
3799 		bssid[i] = oid->subs[offset + i + 1];
3800 
3801 	return (0);
3802 }
3803 
3804 static void
3805 wlan_append_scanr_index(struct asn_oid *oid, uint sub, char *wname,
3806     uint8_t *ssid, uint8_t *bssid)
3807 {
3808 	uint32_t i;
3809 
3810 	oid->len = sub + strlen(wname) + strlen(ssid) + IEEE80211_ADDR_LEN + 3;
3811 	oid->subs[sub] = strlen(wname);
3812 	for (i = 1; i <= strlen(wname); i++)
3813 		oid->subs[sub + i] = wname[i - 1];
3814 
3815 	sub += strlen(wname) + 1;
3816 	oid->subs[sub] = strlen(ssid);
3817 	for (i = 1; i <= strlen(ssid); i++)
3818 		oid->subs[sub + i] = ssid[i - 1];
3819 
3820 	sub += strlen(ssid) + 1;
3821 	oid->subs[sub] = IEEE80211_ADDR_LEN;
3822 	for (i = 1; i <= IEEE80211_ADDR_LEN; i++)
3823 		oid->subs[sub + i] = bssid[i - 1];
3824 }
3825 
3826 static struct wlan_scan_result *
3827 wlan_get_scanr(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3828 {
3829 	char wname[IFNAMSIZ];
3830 	uint8_t ssid[IEEE80211_NWID_LEN + 1];
3831 	uint8_t bssid[IEEE80211_ADDR_LEN];
3832 
3833 	if (wlan_scanr_index_decode(oid, sub, wname, ssid, bssid) < 0)
3834 		return (NULL);
3835 
3836 	if ((*wif = wlan_find_interface(wname)) == NULL)
3837 		return (NULL);
3838 
3839 	return (wlan_scan_find_result(*wif, ssid, bssid));
3840 }
3841 
3842 static struct wlan_scan_result *
3843 wlan_get_next_scanr(const struct asn_oid *oid, uint sub,
3844     struct wlan_iface **wif)
3845 {
3846 	char wname[IFNAMSIZ];
3847 	uint8_t ssid[IEEE80211_NWID_LEN + 1];
3848 	uint8_t bssid[IEEE80211_ADDR_LEN];
3849 	struct wlan_scan_result *sr;
3850 
3851 	if (oid->len - sub == 0) {
3852 		for (*wif = wlan_first_interface(); *wif != NULL;
3853 		    *wif = wlan_next_interface(*wif)) {
3854 			sr = SLIST_FIRST(&(*wif)->scanlist);
3855 			if (sr != NULL)
3856 				return (sr);
3857 		}
3858 		return (NULL);
3859 	}
3860 
3861 	if (wlan_scanr_index_decode(oid, sub, wname, ssid, bssid) < 0 ||
3862 	    (*wif = wlan_find_interface(wname)) == NULL ||
3863 	    (sr = wlan_scan_find_result(*wif, ssid, bssid)) == NULL)
3864 		return (NULL);
3865 
3866 	if ((sr = SLIST_NEXT(sr, wsr)) != NULL)
3867 		return (sr);
3868 
3869 	while ((*wif = wlan_next_interface(*wif)) != NULL)
3870 		if ((sr = SLIST_FIRST(&(*wif)->scanlist)) != NULL)
3871 			break;
3872 
3873 	return (sr);
3874 }
3875 
3876 /*
3877  * MAC Access Control.
3878  */
3879 static void
3880 wlan_mac_free_maclist(struct wlan_iface *wif)
3881 {
3882 	struct wlan_mac_mac *wmm;
3883 
3884 	while ((wmm = SLIST_FIRST(&wif->mac_maclist)) != NULL) {
3885 		SLIST_REMOVE_HEAD(&wif->mac_maclist, wm);
3886 		free(wmm);
3887 	}
3888 
3889 	SLIST_INIT(&wif->mac_maclist);
3890 }
3891 
3892 static struct wlan_mac_mac *
3893 wlan_mac_find_mac(struct wlan_iface *wif, uint8_t *mac)
3894 {
3895 	struct wlan_mac_mac *wmm;
3896 
3897 	SLIST_FOREACH(wmm, &wif->mac_maclist, wm)
3898 		if (memcmp(wmm->mac, mac, IEEE80211_ADDR_LEN) == 0)
3899 			break;
3900 
3901 	return (wmm);
3902 }
3903 
3904 struct wlan_mac_mac *
3905 wlan_mac_new_mac(const uint8_t *mac)
3906 {
3907 	struct wlan_mac_mac *wmm;
3908 
3909 	if ((wmm = (struct wlan_mac_mac *)malloc(sizeof(*wmm))) == NULL)
3910 		return (NULL);
3911 
3912 	memset(wmm, 0, sizeof(*wmm));
3913 	memcpy(wmm->mac, mac, IEEE80211_ADDR_LEN);
3914 	wmm->mac_status = RowStatus_notReady;
3915 
3916 	return (wmm);
3917 }
3918 
3919 void
3920 wlan_mac_free_mac(struct wlan_mac_mac *wmm)
3921 {
3922 	free(wmm);
3923 }
3924 
3925 int
3926 wlan_mac_add_mac(struct wlan_iface *wif, struct wlan_mac_mac *wmm)
3927 {
3928 	struct wlan_mac_mac *temp, *prev;
3929 
3930 	SLIST_FOREACH(temp, &wif->mac_maclist, wm)
3931 		if (memcmp(temp->mac, wmm->mac, IEEE80211_ADDR_LEN) == 0)
3932 			return (-1);
3933 
3934 	if ((prev = SLIST_FIRST(&wif->mac_maclist)) == NULL ||
3935 	    memcmp(wmm->mac, prev->mac,IEEE80211_ADDR_LEN) < 0) {
3936 	    	SLIST_INSERT_HEAD(&wif->mac_maclist, wmm, wm);
3937 	    	return (0);
3938 	}
3939 
3940 	SLIST_FOREACH(temp, &wif->mac_maclist, wm) {
3941 		if (memcmp(wmm->mac, temp->mac, IEEE80211_ADDR_LEN) < 0)
3942 			break;
3943 		prev = temp;
3944 	}
3945 
3946 	SLIST_INSERT_AFTER(prev, wmm, wm);
3947 	return (0);
3948 }
3949 
3950 static int
3951 wlan_mac_delete_mac(struct wlan_iface *wif, struct wlan_mac_mac *wmm)
3952 {
3953 	if (wmm->mac_status == RowStatus_active &&
3954 	    wlan_del_mac_acl_mac(wif, wmm) < 0)
3955 		return (-1);
3956 
3957 	SLIST_REMOVE(&wif->mac_maclist, wmm, wlan_mac_mac, wm);
3958 	free(wmm);
3959 
3960 	return (0);
3961 }
3962 
3963 static void
3964 wlan_mac_update_aclmacs(void)
3965 {
3966 	struct wlan_iface *wif;
3967 	struct wlan_mac_mac *wmm, *twmm;
3968 
3969 	if ((time(NULL) - wlan_maclist_age) <= WLAN_LIST_MAXAGE)
3970 		return;
3971 
3972 	for (wif = wlan_first_interface(); wif != NULL;
3973 	    wif = wlan_next_interface(wif)) {
3974 		if (wif->status != RowStatus_active)
3975 			continue;
3976 		/*
3977 		 * Nuke old entries - XXX - they are likely not to
3978 		 * change often - reconsider.
3979 		 */
3980 		SLIST_FOREACH_SAFE(wmm, &wif->mac_maclist, wm, twmm)
3981 			if (wmm->mac_status == RowStatus_active) {
3982 				SLIST_REMOVE(&wif->mac_maclist, wmm,
3983 				    wlan_mac_mac, wm);
3984 				wlan_mac_free_mac(wmm);
3985 			}
3986 		(void)wlan_get_mac_acl_macs(wif);
3987 	}
3988 	wlan_maclist_age = time(NULL);
3989 }
3990 
3991 static struct wlan_mac_mac *
3992 wlan_get_acl_mac(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3993 {
3994 	char wname[IFNAMSIZ];
3995 	char mac[IEEE80211_ADDR_LEN];
3996 
3997 	if (wlan_mac_index_decode(oid, sub, wname, mac) < 0)
3998 		return (NULL);
3999 
4000 	if ((*wif = wlan_find_interface(wname)) == NULL)
4001 		return (NULL);
4002 
4003 	return (wlan_mac_find_mac(*wif, mac));
4004 }
4005 
4006 static struct wlan_mac_mac *
4007 wlan_get_next_acl_mac(const struct asn_oid *oid, uint sub,
4008     struct wlan_iface **wif)
4009 {
4010 	char wname[IFNAMSIZ];
4011 	char mac[IEEE80211_ADDR_LEN];
4012 	struct wlan_mac_mac *wmm;
4013 
4014 	if (oid->len - sub == 0) {
4015 		for (*wif = wlan_first_interface(); *wif != NULL;
4016 		    *wif = wlan_next_interface(*wif)) {
4017 			wmm = SLIST_FIRST(&(*wif)->mac_maclist);
4018 			if (wmm != NULL)
4019 				return (wmm);
4020 		}
4021 		return (NULL);
4022 	}
4023 
4024 	if (wlan_mac_index_decode(oid, sub, wname, mac) < 0 ||
4025 	    (*wif = wlan_find_interface(wname)) == NULL ||
4026 	    (wmm = wlan_mac_find_mac(*wif, mac)) == NULL)
4027 		return (NULL);
4028 
4029 	if ((wmm = SLIST_NEXT(wmm, wm)) != NULL)
4030 		return (wmm);
4031 
4032 	while ((*wif = wlan_next_interface(*wif)) != NULL)
4033 		if ((wmm = SLIST_FIRST(&(*wif)->mac_maclist)) != NULL)
4034 			break;
4035 
4036 	return (wmm);
4037 }
4038 
4039 static int
4040 wlan_acl_mac_set_status(struct snmp_context *ctx, struct snmp_value *val,
4041     uint sub)
4042 {
4043 	char wname[IFNAMSIZ];
4044 	uint8_t mac[IEEE80211_ADDR_LEN];
4045 	struct wlan_iface *wif;
4046 	struct wlan_mac_mac *macl;
4047 
4048 	if (wlan_mac_index_decode(&val->var, sub, wname, mac) < 0)
4049 		return (SNMP_ERR_GENERR);
4050 	macl = wlan_get_acl_mac(&val->var, sub, &wif);
4051 
4052 	switch (val->v.integer) {
4053 	case RowStatus_createAndGo:
4054 		if (macl != NULL)
4055 			return (SNMP_ERR_INCONS_NAME);
4056 		break;
4057 	case RowStatus_destroy:
4058 		if (macl == NULL)
4059 			return (SNMP_ERR_NOSUCHNAME);
4060 		ctx->scratch->int1 = RowStatus_active;
4061 		return (SNMP_ERR_NOERROR);
4062 	default:
4063 		return (SNMP_ERR_INCONS_VALUE);
4064 	}
4065 
4066 
4067 	if (wif == NULL || !wif->macsupported)
4068 		return (SNMP_ERR_INCONS_VALUE);
4069 
4070 	if ((macl = wlan_mac_new_mac((const uint8_t *)mac)) == NULL)
4071 		return (SNMP_ERR_GENERR);
4072 
4073 	ctx->scratch->int1 = RowStatus_destroy;
4074 
4075 	if (wlan_mac_add_mac(wif, macl) < 0) {
4076 		wlan_mac_free_mac(macl);
4077 		return (SNMP_ERR_GENERR);
4078 	}
4079 
4080 	ctx->scratch->int1 = RowStatus_destroy;
4081 	if (wlan_add_mac_acl_mac(wif, macl) < 0) {
4082 		(void)wlan_mac_delete_mac(wif, macl);
4083 		return (SNMP_ERR_GENERR);
4084 	}
4085 
4086 	return (SNMP_ERR_NOERROR);
4087 }
4088 
4089 /*
4090  * Wireless interfaces operating as mesh points.
4091  */
4092 static struct wlan_iface *
4093 wlan_mesh_first_interface(void)
4094 {
4095 	struct wlan_iface *wif;
4096 
4097 	SLIST_FOREACH(wif, &wlan_ifaces, w_if)
4098 		if (wif->mode == WlanIfaceOperatingModeType_meshPoint &&
4099 		    wif->status == RowStatus_active)
4100 			break;
4101 
4102 	return (wif);
4103 }
4104 
4105 static struct wlan_iface *
4106 wlan_mesh_next_interface(struct wlan_iface *wif)
4107 {
4108 	struct wlan_iface *nwif;
4109 
4110 	while ((nwif = wlan_next_interface(wif)) != NULL) {
4111 		if (nwif->mode == WlanIfaceOperatingModeType_meshPoint &&
4112 		    nwif->status == RowStatus_active)
4113 			break;
4114 		wif = nwif;
4115 	}
4116 
4117 	return (nwif);
4118 }
4119 
4120 static struct wlan_iface *
4121 wlan_mesh_get_iface(const struct asn_oid *oid, uint sub)
4122 {
4123 	struct wlan_iface *wif;
4124 
4125 	if ((wif = wlan_get_interface(oid, sub)) == NULL)
4126 		return (NULL);
4127 
4128 	if (wif->mode != WlanIfaceOperatingModeType_meshPoint)
4129 		return (NULL);
4130 
4131 	return (wif);
4132 }
4133 
4134 static struct wlan_iface *
4135 wlan_mesh_get_next_iface(const struct asn_oid *oid, uint sub)
4136 {
4137 	uint32_t i;
4138 	uint8_t wname[IFNAMSIZ];
4139 	struct wlan_iface *wif;
4140 
4141 	if (oid->len - sub == 0)
4142 		return (wlan_mesh_first_interface());
4143 
4144 	if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
4145 		return (NULL);
4146 
4147 	memset(wname, 0, IFNAMSIZ);
4148 	for (i = 0; i < oid->subs[sub]; i++)
4149 		wname[i] = oid->subs[sub + i + 1];
4150 	wname[i] = '\0';
4151 
4152 	if ((wif = wlan_find_interface(wname)) == NULL)
4153 		return (NULL);
4154 
4155 	return (wlan_mesh_next_interface(wif));
4156 }
4157 
4158 /*
4159  * The neighbors of wireless interfaces operating as mesh points.
4160  */
4161 static struct wlan_peer *
4162 wlan_mesh_get_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
4163 {
4164 	char wname[IFNAMSIZ];
4165 	uint8_t pmac[IEEE80211_ADDR_LEN];
4166 
4167 	if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0)
4168 		return (NULL);
4169 
4170 	if ((*wif = wlan_find_interface(wname)) == NULL ||
4171 	    (*wif)->mode != WlanIfaceOperatingModeType_meshPoint)
4172 		return (NULL);
4173 
4174 	return (wlan_find_peer(*wif, pmac));
4175 }
4176 
4177 static struct wlan_peer *
4178 wlan_mesh_get_next_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
4179 {
4180 	char wname[IFNAMSIZ];
4181 	char pmac[IEEE80211_ADDR_LEN];
4182 	struct wlan_peer *wip;
4183 
4184 	if (oid->len - sub == 0) {
4185 		for (*wif = wlan_mesh_first_interface(); *wif != NULL;
4186 		    *wif = wlan_mesh_next_interface(*wif)) {
4187 			wip = SLIST_FIRST(&(*wif)->peerlist);
4188 			if (wip != NULL)
4189 				return (wip);
4190 		}
4191 		return (NULL);
4192 	}
4193 
4194 	if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0 ||
4195 	    (*wif = wlan_find_interface(wname)) == NULL ||
4196 	    (*wif)->mode != WlanIfaceOperatingModeType_meshPoint ||
4197 	    (wip = wlan_find_peer(*wif, pmac)) == NULL)
4198 		return (NULL);
4199 
4200 	if ((wip = SLIST_NEXT(wip, wp)) != NULL)
4201 		return (wip);
4202 
4203 	while ((*wif = wlan_mesh_next_interface(*wif)) != NULL)
4204 		if ((wip = SLIST_FIRST(&(*wif)->peerlist)) != NULL)
4205 			break;
4206 
4207 	return (wip);
4208 }
4209 
4210 /*
4211  * Mesh routing table.
4212  */
4213 static void
4214 wlan_mesh_free_routes(struct wlan_iface *wif)
4215 {
4216 	struct wlan_mesh_route *wmr;
4217 
4218 	while ((wmr = SLIST_FIRST(&wif->mesh_routelist)) != NULL) {
4219 		SLIST_REMOVE_HEAD(&wif->mesh_routelist, wr);
4220 		free(wmr);
4221 	}
4222 
4223 	SLIST_INIT(&wif->mesh_routelist);
4224 }
4225 
4226 static struct wlan_mesh_route *
4227 wlan_mesh_find_route(struct wlan_iface *wif, uint8_t *dstmac)
4228 {
4229 	struct wlan_mesh_route *wmr;
4230 
4231 	if (wif->mode != WlanIfaceOperatingModeType_meshPoint)
4232 		return (NULL);
4233 
4234 	SLIST_FOREACH(wmr, &wif->mesh_routelist, wr)
4235 		if (memcmp(wmr->imroute.imr_dest, dstmac,
4236 		    IEEE80211_ADDR_LEN) == 0)
4237 			break;
4238 
4239 	return (wmr);
4240 }
4241 
4242 struct wlan_mesh_route *
4243 wlan_mesh_new_route(const uint8_t *dstmac)
4244 {
4245 	struct wlan_mesh_route *wmr;
4246 
4247 	if ((wmr = (struct wlan_mesh_route *)malloc(sizeof(*wmr))) == NULL)
4248 		return (NULL);
4249 
4250 	memset(wmr, 0, sizeof(*wmr));
4251 	memcpy(wmr->imroute.imr_dest, dstmac, IEEE80211_ADDR_LEN);
4252 	wmr->mroute_status = RowStatus_notReady;
4253 
4254 	return (wmr);
4255 }
4256 
4257 void
4258 wlan_mesh_free_route(struct wlan_mesh_route *wmr)
4259 {
4260 	free(wmr);
4261 }
4262 
4263 int
4264 wlan_mesh_add_rtentry(struct wlan_iface *wif, struct wlan_mesh_route *wmr)
4265 {
4266 	struct wlan_mesh_route *temp, *prev;
4267 
4268 	SLIST_FOREACH(temp, &wif->mesh_routelist, wr)
4269 		if (memcmp(temp->imroute.imr_dest, wmr->imroute.imr_dest,
4270 		    IEEE80211_ADDR_LEN) == 0)
4271 			return (-1);
4272 
4273 	if ((prev = SLIST_FIRST(&wif->mesh_routelist)) == NULL ||
4274 	    memcmp(wmr->imroute.imr_dest, prev->imroute.imr_dest,
4275 	    IEEE80211_ADDR_LEN) < 0) {
4276 	    	SLIST_INSERT_HEAD(&wif->mesh_routelist, wmr, wr);
4277 	    	return (0);
4278 	}
4279 
4280 	SLIST_FOREACH(temp, &wif->mesh_routelist, wr) {
4281 		if (memcmp(wmr->imroute.imr_dest, temp->imroute.imr_dest,
4282 		    IEEE80211_ADDR_LEN) < 0)
4283 			break;
4284 		prev = temp;
4285 	}
4286 
4287 	SLIST_INSERT_AFTER(prev, wmr, wr);
4288 	return (0);
4289 }
4290 
4291 static int
4292 wlan_mesh_delete_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr)
4293 {
4294 	if (wmr->mroute_status == RowStatus_active &&
4295 	    wlan_mesh_del_route(wif, wmr) < 0)
4296 		return (-1);
4297 
4298 	SLIST_REMOVE(&wif->mesh_routelist, wmr, wlan_mesh_route, wr);
4299 	free(wmr);
4300 
4301 	return (0);
4302 }
4303 
4304 static void
4305 wlan_mesh_update_routes(void)
4306 {
4307 	struct wlan_iface *wif;
4308 	struct wlan_mesh_route *wmr, *twmr;
4309 
4310 	if ((time(NULL) - wlan_mrlist_age) <= WLAN_LIST_MAXAGE)
4311 		return;
4312 
4313 	for (wif = wlan_mesh_first_interface(); wif != NULL;
4314 	    wif = wlan_mesh_next_interface(wif)) {
4315 		/*
4316 		 * Nuke old entries - XXX - they are likely not to
4317 		 * change often - reconsider.
4318 		 */
4319 		SLIST_FOREACH_SAFE(wmr, &wif->mesh_routelist, wr, twmr)
4320 			if (wmr->mroute_status == RowStatus_active) {
4321 				SLIST_REMOVE(&wif->mesh_routelist, wmr,
4322 				    wlan_mesh_route, wr);
4323 				wlan_mesh_free_route(wmr);
4324 			}
4325 		(void)wlan_mesh_get_routelist(wif);
4326 	}
4327 	wlan_mrlist_age = time(NULL);
4328 }
4329 
4330 static struct wlan_mesh_route *
4331 wlan_mesh_get_route(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
4332 {
4333 	char wname[IFNAMSIZ];
4334 	char dstmac[IEEE80211_ADDR_LEN];
4335 
4336 	if (wlan_mac_index_decode(oid, sub, wname, dstmac) < 0)
4337 		return (NULL);
4338 
4339 	if ((*wif = wlan_find_interface(wname)) == NULL)
4340 		return (NULL);
4341 
4342 	return (wlan_mesh_find_route(*wif, dstmac));
4343 }
4344 
4345 static struct wlan_mesh_route *
4346 wlan_mesh_get_next_route(const struct asn_oid *oid, uint sub,
4347     struct wlan_iface **wif)
4348 {
4349 	char wname[IFNAMSIZ];
4350 	char dstmac[IEEE80211_ADDR_LEN];
4351 	struct wlan_mesh_route *wmr;
4352 
4353 	if (oid->len - sub == 0) {
4354 		for (*wif = wlan_mesh_first_interface(); *wif != NULL;
4355 		    *wif = wlan_mesh_next_interface(*wif)) {
4356 			wmr = SLIST_FIRST(&(*wif)->mesh_routelist);
4357 			if (wmr != NULL)
4358 				return (wmr);
4359 		}
4360 		return (NULL);
4361 	}
4362 
4363 	if (wlan_mac_index_decode(oid, sub, wname, dstmac) < 0 ||
4364 	    (*wif = wlan_find_interface(wname)) == NULL ||
4365 	    (wmr = wlan_mesh_find_route(*wif, dstmac)) == NULL)
4366 		return (NULL);
4367 
4368 	if ((wmr = SLIST_NEXT(wmr, wr)) != NULL)
4369 		return (wmr);
4370 
4371 	while ((*wif = wlan_mesh_next_interface(*wif)) != NULL)
4372 		if ((wmr = SLIST_FIRST(&(*wif)->mesh_routelist)) != NULL)
4373 			break;
4374 
4375 	return (wmr);
4376 }
4377 
4378 static int
4379 wlan_mesh_route_set_status(struct snmp_context *ctx, struct snmp_value *val,
4380     uint sub)
4381 {
4382 	char wname[IFNAMSIZ];
4383 	char mac[IEEE80211_ADDR_LEN];
4384 	struct wlan_mesh_route *wmr;
4385 	struct wlan_iface *wif;
4386 
4387 	if (wlan_mac_index_decode(&val->var, sub, wname, mac) < 0)
4388 		return (SNMP_ERR_GENERR);
4389 	wmr = wlan_mesh_get_route(&val->var, sub, &wif);
4390 
4391 	switch (val->v.integer) {
4392 	case RowStatus_createAndGo:
4393 		if (wmr != NULL)
4394 			return (SNMP_ERR_INCONS_NAME);
4395 		break;
4396 	case RowStatus_destroy:
4397 		if (wmr == NULL)
4398 			return (SNMP_ERR_NOSUCHNAME);
4399 		ctx->scratch->int1 = RowStatus_active;
4400 		return (SNMP_ERR_NOERROR);
4401 	default:
4402 		return (SNMP_ERR_INCONS_VALUE);
4403 	}
4404 
4405 	if ((wif = wlan_find_interface(wname)) == NULL)
4406 		return (SNMP_ERR_INCONS_NAME);
4407 
4408 	if ((wmr = wlan_mesh_new_route(mac)) == NULL)
4409 		return (SNMP_ERR_GENERR);
4410 
4411 	if (wlan_mesh_add_rtentry(wif, wmr) < 0) {
4412 		wlan_mesh_free_route(wmr);
4413 		return (SNMP_ERR_GENERR);
4414 	}
4415 
4416 	ctx->scratch->int1 = RowStatus_destroy;
4417 	if (wlan_mesh_add_route(wif, wmr) < 0) {
4418 		(void)wlan_mesh_delete_route(wif, wmr);
4419 		return (SNMP_ERR_GENERR);
4420 	}
4421 
4422 	return (SNMP_ERR_NOERROR);
4423 }
4424 
4425 /*
4426  * Wlan snmp module initialization hook.
4427  * Returns 0 on success, < 0 on error.
4428  */
4429 static int
4430 wlan_init(struct lmodule * mod __unused, int argc __unused,
4431      char *argv[] __unused)
4432 {
4433 	if (wlan_kmodules_load() < 0)
4434 		return (-1);
4435 
4436 	if (wlan_ioctl_init() < 0)
4437 		return (-1);
4438 
4439 	/* Register for new interface creation notifications. */
4440 	if (mib_register_newif(wlan_attach_newif, wlan_module)) {
4441 		syslog(LOG_ERR, "Cannot register newif function: %s",
4442 		    strerror(errno));
4443 		return (-1);
4444 	}
4445 
4446 	return (0);
4447 }
4448 
4449 /*
4450  * Wlan snmp module finalization hook.
4451  */
4452 static int
4453 wlan_fini(void)
4454 {
4455 	mib_unregister_newif(wlan_module);
4456 	or_unregister(reg_wlan);
4457 
4458 	/* XXX: Cleanup! */
4459 	wlan_free_iflist();
4460 
4461 	return (0);
4462 }
4463 
4464 /*
4465  * Refetch all available data from the kernel.
4466  */
4467 static void
4468 wlan_update_data(void *arg __unused)
4469 {
4470 }
4471 
4472 /*
4473  * Wlan snmp module start operation.
4474  */
4475 static void
4476 wlan_start(void)
4477 {
4478 	struct mibif *ifp;
4479 
4480 	reg_wlan = or_register(&oid_wlan,
4481 	    "The MIB module for managing wireless networking.", wlan_module);
4482 
4483 	 /* Add the existing wlan interfaces. */
4484 	 for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp))
4485 		wlan_attach_newif(ifp);
4486 
4487 	wlan_data_timer = timer_start_repeat(wlan_poll_ticks,
4488 	    wlan_poll_ticks, wlan_update_data, NULL, wlan_module);
4489 }
4490 
4491 /*
4492  * Dump the Wlan snmp module data on SIGUSR1.
4493  */
4494 static void
4495 wlan_dump(void)
4496 {
4497 	/* XXX: Print some debug info to syslog. */
4498 	struct wlan_iface *wif;
4499 
4500 	for (wif = wlan_first_interface(); wif != NULL;
4501 	    wif = wlan_next_interface(wif))
4502 		syslog(LOG_ERR, "wlan iface %s", wif->wname);
4503 }
4504 
4505 const char wlan_comment[] = \
4506 "This module implements the BEGEMOT MIB for wireless networking.";
4507 
4508 const struct snmp_module config = {
4509 	.comment =	wlan_comment,
4510 	.init =		wlan_init,
4511 	.fini =		wlan_fini,
4512 	.start =	wlan_start,
4513 	.tree =		wlan_ctree,
4514 	.dump =		wlan_dump,
4515 	.tree_size =	wlan_CTREE_SIZE,
4516 };
4517