1210502Ssyrinx/*-
2210502Ssyrinx * Copyright (c) 2010 The FreeBSD Foundation
3210502Ssyrinx * All rights reserved.
4210502Ssyrinx *
5210502Ssyrinx * This software was developed by Shteryana Sotirova Shopova under
6210502Ssyrinx * sponsorship from the FreeBSD Foundation.
7210502Ssyrinx *
8210502Ssyrinx * Redistribution and use in source and binary forms, with or without
9210502Ssyrinx * modification, are permitted provided that the following conditions
10210502Ssyrinx * are met:
11210502Ssyrinx * 1. Redistributions of source code must retain the above copyright
12210502Ssyrinx *    notice, this list of conditions and the following disclaimer.
13210502Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright
14210502Ssyrinx *    notice, this list of conditions and the following disclaimer in the
15210502Ssyrinx *    documentation and/or other materials provided with the distribution.
16210502Ssyrinx *
17210502Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18210502Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19210502Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20210502Ssyrinx * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21210502Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22210502Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23210502Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24210502Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25210502Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26210502Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27210502Ssyrinx * SUCH DAMAGE.
28210502Ssyrinx *
29210502Ssyrinx * $FreeBSD$
30210502Ssyrinx */
31210502Ssyrinx
32210502Ssyrinx#include <sys/queue.h>
33210502Ssyrinx#include <sys/socket.h>
34210502Ssyrinx#include <sys/types.h>
35210502Ssyrinx
36210502Ssyrinx#include <net/if.h>
37210502Ssyrinx#include <net/if_media.h>
38210502Ssyrinx#include <net/if_mib.h>
39210502Ssyrinx#include <net/if_types.h>
40210502Ssyrinx#include <net80211/ieee80211.h>
41210502Ssyrinx#include <net80211/ieee80211_ioctl.h>
42210502Ssyrinx
43210502Ssyrinx#include <errno.h>
44210502Ssyrinx#include <stdarg.h>
45210502Ssyrinx#include <stdlib.h>
46210502Ssyrinx#include <stdio.h>
47210502Ssyrinx#include <string.h>
48210502Ssyrinx#include <syslog.h>
49210502Ssyrinx
50210502Ssyrinx#include <bsnmp/snmpmod.h>
51210502Ssyrinx#include <bsnmp/snmp_mibII.h>
52210502Ssyrinx
53210502Ssyrinx#include "wlan_tree.h"
54210502Ssyrinx#include "wlan_snmp.h"
55210502Ssyrinx#include "wlan_oid.h"
56210502Ssyrinx
57210502Ssyrinxstatic struct lmodule *wlan_module;
58210502Ssyrinx
59210502Ssyrinx/* For the registration. */
60210502Ssyrinxstatic const struct asn_oid oid_wlan = OIDX_begemotWlan;
61210502Ssyrinx/* The registration. */
62210502Ssyrinxstatic uint reg_wlan;
63210502Ssyrinx
64210502Ssyrinx/* Periodic timer for polling the module's data. */
65210502Ssyrinxstatic void *wlan_data_timer;
66210502Ssyrinx
67210502Ssyrinx/*
68210502Ssyrinx * Poll data from kernel every 15 minutes unless explicitly requested by an
69210502Ssyrinx * SNMP client.
70210502Ssyrinx * XXX: make that configurable.
71210502Ssyrinx */
72210502Ssyrinxstatic int wlan_poll_ticks = (15 * 60) * 100;
73210502Ssyrinx
74210502Ssyrinx/* The age of each table. */
75210502Ssyrinx#define	WLAN_LIST_MAXAGE	5
76210502Ssyrinx
77210502Ssyrinxstatic time_t wlan_iflist_age;
78210502Ssyrinxstatic time_t wlan_peerlist_age;
79210502Ssyrinxstatic time_t wlan_chanlist_age;
80210502Ssyrinxstatic time_t wlan_roamlist_age;
81210502Ssyrinxstatic time_t wlan_tx_paramlist_age;
82210502Ssyrinxstatic time_t wlan_scanlist_age;
83210502Ssyrinxstatic time_t wlan_maclist_age;
84210502Ssyrinxstatic time_t wlan_mrlist_age;
85210502Ssyrinx
86210502Ssyrinx/*
87210502Ssyrinx * The list of all virtual wireless interfaces - sorted by name.
88210502Ssyrinx */
89210502SsyrinxSLIST_HEAD(wlan_ifaces, wlan_iface);
90210502Ssyrinxstatic struct wlan_ifaces wlan_ifaces = SLIST_HEAD_INITIALIZER(wlan_ifaces);
91210502Ssyrinx
92210502Ssyrinxstatic struct wlan_config wlan_config;
93210502Ssyrinx
94210502Ssyrinx/* Forward declarations */
95210502Ssyrinxstatic int	bits_get(struct snmp_value *, const u_char *, ssize_t);
96210502Ssyrinx
97210502Ssyrinxstatic int	wlan_add_wif(struct wlan_iface *);
98210502Ssyrinxstatic void	wlan_delete_wif(struct wlan_iface *);
99210502Ssyrinxstatic int	wlan_attach_newif(struct mibif *);
100210502Ssyrinxstatic int	wlan_iface_create(struct wlan_iface *);
101210502Ssyrinxstatic int	wlan_iface_destroy(struct wlan_iface *);
102210502Ssyrinxstatic struct wlan_iface *	wlan_new_wif(char *);
103210502Ssyrinx
104210502Ssyrinxstatic void	wlan_free_interface(struct wlan_iface *);
105210502Ssyrinxstatic void	wlan_free_iflist(void);
106210502Ssyrinxstatic void	wlan_free_peerlist(struct wlan_iface *);
107210502Ssyrinxstatic void	wlan_scan_free_results(struct wlan_iface *);
108210502Ssyrinxstatic void	wlan_mac_free_maclist(struct wlan_iface *);
109210502Ssyrinxstatic void	wlan_mesh_free_routes(struct wlan_iface *);
110210502Ssyrinx
111210502Ssyrinxstatic int	wlan_update_interface(struct wlan_iface *);
112210502Ssyrinxstatic void	wlan_update_interface_list(void);
113210502Ssyrinxstatic void	wlan_update_peers(void);
114210502Ssyrinxstatic void	wlan_update_channels(void);
115210502Ssyrinxstatic void	wlan_update_roam_params(void);
116210502Ssyrinxstatic void	wlan_update_tx_params(void);
117210502Ssyrinxstatic void	wlan_scan_update_results(void);
118210502Ssyrinxstatic void	wlan_mac_update_aclmacs(void);
119210502Ssyrinxstatic void	wlan_mesh_update_routes(void);
120210502Ssyrinx
121210502Ssyrinxstatic struct wlan_iface *	wlan_find_interface(const char *);
122210502Ssyrinxstatic struct wlan_peer *	wlan_find_peer(struct wlan_iface *, uint8_t *);
123210502Ssyrinxstatic struct ieee80211_channel*	wlan_find_channel(struct wlan_iface *,
124210502Ssyrinx    uint32_t);
125210502Ssyrinxstatic struct wlan_scan_result *	wlan_scan_find_result(struct wlan_iface *,
126210502Ssyrinx    uint8_t *, uint8_t *);
127210502Ssyrinxstatic struct wlan_mac_mac *		wlan_mac_find_mac(struct wlan_iface *,
128210502Ssyrinx    uint8_t *);
129210502Ssyrinxstatic struct wlan_mesh_route *		wlan_mesh_find_route(struct wlan_iface *,
130210502Ssyrinx    uint8_t *);
131210502Ssyrinx
132210502Ssyrinxstatic struct wlan_iface *	wlan_first_interface(void);
133210502Ssyrinxstatic struct wlan_iface *	wlan_next_interface(struct wlan_iface *);
134210502Ssyrinxstatic struct wlan_iface *	wlan_mesh_first_interface(void);
135210502Ssyrinxstatic struct wlan_iface *	wlan_mesh_next_interface(struct wlan_iface *);
136210502Ssyrinx
137210502Ssyrinxstatic struct wlan_iface *	wlan_get_interface(const struct asn_oid *, uint);
138210502Ssyrinxstatic struct wlan_iface *	wlan_get_snmp_interface(const struct asn_oid *,
139210502Ssyrinx    uint);
140210502Ssyrinxstatic struct wlan_peer *	wlan_get_peer(const struct asn_oid *, uint,
141210502Ssyrinx    struct wlan_iface **);
142210502Ssyrinxstatic struct ieee80211_channel *wlan_get_channel(const struct asn_oid *, uint,
143210502Ssyrinx    struct wlan_iface **);
144210502Ssyrinxstatic struct ieee80211_roamparam *wlan_get_roam_param(const struct asn_oid *,
145210502Ssyrinx    uint, struct wlan_iface **);
146210502Ssyrinxstatic struct ieee80211_txparam *wlan_get_tx_param(const struct asn_oid *,
147210502Ssyrinx    uint, struct wlan_iface **, uint32_t *);
148210502Ssyrinxstatic struct wlan_scan_result *wlan_get_scanr(const struct asn_oid *, uint,
149210502Ssyrinx    struct wlan_iface **);
150210502Ssyrinxstatic struct wlan_mac_mac *	wlan_get_acl_mac(const struct asn_oid *,
151210502Ssyrinx    uint, struct wlan_iface **);
152210502Ssyrinxstatic struct wlan_iface *	wlan_mesh_get_iface(const struct asn_oid *, uint);
153210502Ssyrinxstatic struct wlan_peer *	wlan_mesh_get_peer(const struct asn_oid *, uint,
154210502Ssyrinx    struct wlan_iface **);
155210502Ssyrinxstatic struct wlan_mesh_route *	wlan_mesh_get_route(const struct asn_oid *,
156210502Ssyrinx    uint, struct wlan_iface **);
157210502Ssyrinx
158210502Ssyrinxstatic struct wlan_iface *	wlan_get_next_interface(const struct asn_oid *,
159210502Ssyrinx    uint);
160210502Ssyrinxstatic struct wlan_iface *	wlan_get_next_snmp_interface(const struct
161210502Ssyrinx    asn_oid *, uint);
162210502Ssyrinxstatic struct wlan_peer *	wlan_get_next_peer(const struct asn_oid *, uint,
163210502Ssyrinx    struct wlan_iface **);
164210502Ssyrinxstatic struct ieee80211_channel *wlan_get_next_channel(const struct asn_oid *,
165210502Ssyrinx    uint, struct wlan_iface **);
166210502Ssyrinxstatic struct ieee80211_roamparam *wlan_get_next_roam_param(const struct
167210502Ssyrinx    asn_oid *, uint sub, struct wlan_iface **, uint32_t *);
168210502Ssyrinxstatic struct ieee80211_txparam *wlan_get_next_tx_param(const struct asn_oid *,
169210502Ssyrinx    uint, struct wlan_iface **, uint32_t *);
170210502Ssyrinxstatic struct wlan_scan_result *wlan_get_next_scanr(const struct asn_oid *,
171210502Ssyrinx    uint , struct wlan_iface **);
172210502Ssyrinxstatic struct wlan_mac_mac *	wlan_get_next_acl_mac(const struct asn_oid *,
173210502Ssyrinx    uint, struct wlan_iface **);
174210502Ssyrinxstatic struct wlan_iface *	wlan_mesh_get_next_iface(const struct asn_oid *,
175210502Ssyrinx    uint);
176210502Ssyrinxstatic struct wlan_peer *	wlan_mesh_get_next_peer(const struct asn_oid *,
177210502Ssyrinx    uint, struct wlan_iface **);
178210502Ssyrinxstatic struct wlan_mesh_route *	wlan_mesh_get_next_route(const struct asn_oid *,
179210502Ssyrinx    uint sub, struct wlan_iface **);
180210502Ssyrinx
181210502Ssyrinxstatic uint8_t *wlan_get_ifname(const struct asn_oid *, uint, uint8_t *);
182210502Ssyrinxstatic int	wlan_mac_index_decode(const struct asn_oid *, uint, char *,
183210502Ssyrinx    uint8_t *);
184210502Ssyrinxstatic int	wlan_channel_index_decode(const struct asn_oid *, uint,
185210502Ssyrinx    char *, uint32_t *);
186210502Ssyrinxstatic int	wlan_phy_index_decode(const struct asn_oid *, uint, char *,
187210502Ssyrinx    uint32_t *);
188210502Ssyrinxstatic int wlan_scanr_index_decode(const struct asn_oid *oid, uint sub,
189210502Ssyrinx    char *wname, uint8_t *ssid, uint8_t *bssid);
190210502Ssyrinx
191210502Ssyrinxstatic void	wlan_append_ifindex(struct asn_oid *, uint,
192210502Ssyrinx    const struct wlan_iface *);
193210502Ssyrinxstatic void	wlan_append_mac_index(struct asn_oid *, uint, char *, uint8_t *);
194210502Ssyrinxstatic void	wlan_append_channel_index(struct asn_oid *, uint,
195210502Ssyrinx    const struct wlan_iface *, const struct ieee80211_channel *);
196210502Ssyrinxstatic void	wlan_append_phy_index(struct asn_oid *, uint, char *, uint32_t);
197210502Ssyrinxstatic void	wlan_append_scanr_index(struct asn_oid *, uint, char *,
198210502Ssyrinx    uint8_t *, uint8_t *);
199210502Ssyrinx
200210502Ssyrinxstatic int	wlan_acl_mac_set_status(struct snmp_context *,
201210502Ssyrinx    struct snmp_value *, uint);
202210502Ssyrinxstatic int	wlan_mesh_route_set_status(struct snmp_context *,
203210502Ssyrinx    struct snmp_value *, uint);
204210502Ssyrinx
205210502Ssyrinxstatic int32_t	wlan_get_channel_type(struct ieee80211_channel *);
206210502Ssyrinxstatic int	wlan_scan_compare_result(struct wlan_scan_result *,
207210502Ssyrinx    struct wlan_scan_result *);
208210502Ssyrinxstatic int	wlan_mac_delete_mac(struct wlan_iface *, struct wlan_mac_mac *);
209210502Ssyrinxstatic int	wlan_mesh_delete_route(struct wlan_iface *,
210210502Ssyrinx    struct wlan_mesh_route *);
211210502Ssyrinx
212210502Ssyrinx/*
213210502Ssyrinx * The module's GET/SET data hooks per each table or group of objects as
214210502Ssyrinx * required by bsnmpd(1).
215210502Ssyrinx */
216210502Ssyrinxint
217210502Ssyrinxop_wlan_iface(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
218210502Ssyrinx    uint32_t iidx __unused, enum snmp_op op)
219210502Ssyrinx{
220210502Ssyrinx	int rc;
221210502Ssyrinx	char wname[IFNAMSIZ];
222210502Ssyrinx	struct wlan_iface *wif;
223210502Ssyrinx
224210502Ssyrinx	wlan_update_interface_list();
225210502Ssyrinx
226210502Ssyrinx	switch (op) {
227210502Ssyrinx	case SNMP_OP_GET:
228210502Ssyrinx		if ((wif = wlan_get_snmp_interface(&val->var, sub)) == NULL)
229210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
230210502Ssyrinx		break;
231210502Ssyrinx
232210502Ssyrinx	case SNMP_OP_GETNEXT:
233210502Ssyrinx		if ((wif = wlan_get_next_snmp_interface(&val->var, sub)) == NULL)
234210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
235210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
236210502Ssyrinx		break;
237210502Ssyrinx
238210502Ssyrinx	case SNMP_OP_SET:
239210502Ssyrinx		if ((wif = wlan_get_snmp_interface(&val->var, sub)) == NULL) {
240210502Ssyrinx			if (val->var.subs[sub - 1] != LEAF_wlanIfaceName)
241210502Ssyrinx				return (SNMP_ERR_NOSUCHNAME);
242210502Ssyrinx			if (wlan_get_ifname(&val->var, sub, wname) == NULL)
243210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
244210502Ssyrinx			if ((wif = wlan_new_wif(wname)) == NULL)
245210502Ssyrinx				return (SNMP_ERR_GENERR);
246210502Ssyrinx			wif->internal = 1;
247210502Ssyrinx		}
248210502Ssyrinx		if (wif->status == RowStatus_active &&
249210502Ssyrinx		    val->var.subs[sub - 1] != LEAF_wlanIfaceStatus &&
250210502Ssyrinx		    val->var.subs[sub - 1] != LEAF_wlanIfaceState)
251210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
252210502Ssyrinx
253210502Ssyrinx		switch (val->var.subs[sub - 1]) {
254210502Ssyrinx		case LEAF_wlanIfaceIndex:
255210502Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
256210502Ssyrinx
257210502Ssyrinx		case LEAF_wlanIfaceName:
258210502Ssyrinx			if (val->v.octetstring.len >= IFNAMSIZ)
259210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
260210502Ssyrinx			if ((ctx->scratch->ptr1 = malloc(IFNAMSIZ)) == NULL)
261210502Ssyrinx				return (SNMP_ERR_GENERR);
262210502Ssyrinx			strlcpy(ctx->scratch->ptr1, wif->wname, IFNAMSIZ);
263210502Ssyrinx			memcpy(wif->wname, val->v.octetstring.octets,
264210502Ssyrinx			    val->v.octetstring.len);
265210502Ssyrinx			wif->wname[val->v.octetstring.len] = '\0';
266210502Ssyrinx			return (SNMP_ERR_NOERROR);
267210502Ssyrinx
268210502Ssyrinx		case LEAF_wlanParentIfName:
269210502Ssyrinx			if (val->v.octetstring.len >= IFNAMSIZ)
270210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
271210502Ssyrinx			if ((ctx->scratch->ptr1 = malloc(IFNAMSIZ)) == NULL)
272210502Ssyrinx				return (SNMP_ERR_GENERR);
273210502Ssyrinx			strlcpy(ctx->scratch->ptr1, wif->pname, IFNAMSIZ);
274210502Ssyrinx			memcpy(wif->pname, val->v.octetstring.octets,
275210502Ssyrinx			    val->v.octetstring.len);
276210502Ssyrinx			wif->pname[val->v.octetstring.len] = '\0';
277210502Ssyrinx			return (SNMP_ERR_NOERROR);
278210502Ssyrinx
279210502Ssyrinx		case LEAF_wlanIfaceOperatingMode:
280210502Ssyrinx			ctx->scratch->int1 = wif->mode;
281210502Ssyrinx			wif->mode = val->v.integer;
282210502Ssyrinx			return (SNMP_ERR_NOERROR);
283210502Ssyrinx
284210502Ssyrinx		case LEAF_wlanIfaceFlags:
285210502Ssyrinx			if (val->v.octetstring.len > sizeof(wif->flags))
286210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
287210502Ssyrinx			ctx->scratch->ptr1 = malloc(sizeof(wif->flags));
288210502Ssyrinx			if (ctx->scratch->ptr1 == NULL)
289210502Ssyrinx				return (SNMP_ERR_GENERR);
290210502Ssyrinx			memcpy(ctx->scratch->ptr1, (uint8_t *)&wif->flags,
291210502Ssyrinx			    sizeof(wif->flags));
292210502Ssyrinx			memcpy((uint8_t *)&wif->flags, val->v.octetstring.octets,
293210502Ssyrinx			    sizeof(wif->flags));
294210502Ssyrinx			return (SNMP_ERR_NOERROR);
295210502Ssyrinx
296210502Ssyrinx		case LEAF_wlanIfaceBssid:
297210502Ssyrinx			if (val->v.octetstring.len != IEEE80211_ADDR_LEN)
298210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
299210502Ssyrinx			ctx->scratch->ptr1 = malloc(IEEE80211_ADDR_LEN);
300210502Ssyrinx			if (ctx->scratch->ptr1 == NULL)
301210502Ssyrinx				return (SNMP_ERR_GENERR);
302210502Ssyrinx			memcpy(ctx->scratch->ptr1, wif->dbssid,
303210502Ssyrinx			    IEEE80211_ADDR_LEN);
304210502Ssyrinx			memcpy(wif->dbssid, val->v.octetstring.octets,
305210502Ssyrinx			    IEEE80211_ADDR_LEN);
306210502Ssyrinx			return (SNMP_ERR_NOERROR);
307210502Ssyrinx
308210502Ssyrinx		case LEAF_wlanIfaceLocalAddress:
309210502Ssyrinx			if (val->v.octetstring.len != IEEE80211_ADDR_LEN)
310210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
311210502Ssyrinx			ctx->scratch->ptr1 = malloc(IEEE80211_ADDR_LEN);
312210502Ssyrinx			if (ctx->scratch->ptr1 == NULL)
313210502Ssyrinx				return (SNMP_ERR_GENERR);
314210502Ssyrinx			memcpy(ctx->scratch->ptr1, wif->dlmac,
315210502Ssyrinx			    IEEE80211_ADDR_LEN);
316210502Ssyrinx			memcpy(wif->dlmac, val->v.octetstring.octets,
317210502Ssyrinx			    IEEE80211_ADDR_LEN);
318210502Ssyrinx			return (SNMP_ERR_NOERROR);
319210502Ssyrinx
320210502Ssyrinx		case LEAF_wlanIfaceStatus:
321210502Ssyrinx			ctx->scratch->int1 = wif->status;
322210502Ssyrinx			wif->status = val->v.integer;
323210502Ssyrinx			if (wif->status == RowStatus_active) {
324210502Ssyrinx				rc = wlan_iface_create(wif); /* XXX */
325210502Ssyrinx				if (rc != SNMP_ERR_NOERROR) {
326210502Ssyrinx					wif->status = ctx->scratch->int1;
327210502Ssyrinx					return (rc);
328210502Ssyrinx				}
329210502Ssyrinx			} else if (wif->status == RowStatus_destroy)
330210502Ssyrinx				return (wlan_iface_destroy(wif));
331210502Ssyrinx			else
332210502Ssyrinx				wif->status = RowStatus_notReady;
333210502Ssyrinx			return (SNMP_ERR_NOERROR);
334210502Ssyrinx
335210502Ssyrinx		case LEAF_wlanIfaceState:
336210502Ssyrinx			ctx->scratch->int1 = wif->state;
337210502Ssyrinx			wif->state = val->v.integer;
338210502Ssyrinx			if (wif->status == RowStatus_active)
339210502Ssyrinx				if (wlan_config_state(wif, 1) < 0)
340210502Ssyrinx					return (SNMP_ERR_GENERR);
341210502Ssyrinx			return (SNMP_ERR_NOERROR);
342210502Ssyrinx		}
343210502Ssyrinx		abort();
344210502Ssyrinx
345210502Ssyrinx	case SNMP_OP_ROLLBACK:
346210502Ssyrinx		if ((wif = wlan_get_snmp_interface(&val->var, sub)) == NULL)
347210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
348210502Ssyrinx		switch (val->var.subs[sub - 1]) {
349210502Ssyrinx		case LEAF_wlanIfaceName:
350210502Ssyrinx			strlcpy(wif->wname, ctx->scratch->ptr1, IFNAMSIZ);
351210502Ssyrinx			free(ctx->scratch->ptr1);
352210502Ssyrinx			break;
353210502Ssyrinx
354210502Ssyrinx		case LEAF_wlanParentIfName:
355210502Ssyrinx			strlcpy(wif->pname, ctx->scratch->ptr1, IFNAMSIZ);
356210502Ssyrinx			free(ctx->scratch->ptr1);
357210502Ssyrinx			break;
358210502Ssyrinx
359210502Ssyrinx		case LEAF_wlanIfaceOperatingMode:
360210502Ssyrinx			wif->mode = ctx->scratch->int1;
361210502Ssyrinx			break;
362210502Ssyrinx
363210502Ssyrinx		case LEAF_wlanIfaceFlags:
364210502Ssyrinx			memcpy((uint8_t *)&wif->flags, ctx->scratch->ptr1,
365210502Ssyrinx			    sizeof(wif->flags));
366210502Ssyrinx			free(ctx->scratch->ptr1);
367210502Ssyrinx			break;
368210502Ssyrinx
369210502Ssyrinx		case LEAF_wlanIfaceBssid:
370210502Ssyrinx			memcpy(wif->dbssid, ctx->scratch->ptr1,
371210502Ssyrinx			    IEEE80211_ADDR_LEN);
372210502Ssyrinx			free(ctx->scratch->ptr1);
373210502Ssyrinx			break;
374210502Ssyrinx
375210502Ssyrinx		case LEAF_wlanIfaceLocalAddress:
376210502Ssyrinx			memcpy(wif->dlmac, ctx->scratch->ptr1,
377210502Ssyrinx			    IEEE80211_ADDR_LEN);
378210502Ssyrinx			free(ctx->scratch->ptr1);
379210502Ssyrinx			break;
380210502Ssyrinx
381210502Ssyrinx		case LEAF_wlanIfaceStatus:
382210502Ssyrinx			wif->status = ctx->scratch->int1;
383210502Ssyrinx			if (ctx->scratch->int1 == RowStatus_active)
384210502Ssyrinx				return (SNMP_ERR_GENERR); /* XXX: FIXME */
385210502Ssyrinx			else if (wif->internal != 0)
386210502Ssyrinx				return (wlan_iface_destroy(wif));
387210502Ssyrinx			break;
388210502Ssyrinx
389210502Ssyrinx		case LEAF_wlanIfaceState:
390210502Ssyrinx			wif->state = ctx->scratch->int1;
391210502Ssyrinx			if (wif->status == RowStatus_active)
392210502Ssyrinx				if (wlan_config_state(wif, 1) < 0)
393210502Ssyrinx					return (SNMP_ERR_GENERR);
394210502Ssyrinx			break;
395210502Ssyrinx		}
396210502Ssyrinx		return (SNMP_ERR_NOERROR);
397210502Ssyrinx
398210502Ssyrinx	case SNMP_OP_COMMIT:
399210502Ssyrinx		switch (val->var.subs[sub - 1]) {
400210502Ssyrinx		case LEAF_wlanIfaceName:
401210502Ssyrinx		case LEAF_wlanParentIfName:
402210502Ssyrinx		case LEAF_wlanIfaceFlags:
403210502Ssyrinx		case LEAF_wlanIfaceBssid:
404210502Ssyrinx		case LEAF_wlanIfaceLocalAddress:
405210502Ssyrinx			free(ctx->scratch->ptr1);
406210502Ssyrinx			/* FALLTHROUGH */
407210502Ssyrinx		default:
408210502Ssyrinx			return (SNMP_ERR_NOERROR);
409210502Ssyrinx		}
410210502Ssyrinx	default:
411210502Ssyrinx		abort();
412210502Ssyrinx	}
413210502Ssyrinx
414210502Ssyrinx	switch (val->var.subs[sub - 1]) {
415210502Ssyrinx	case LEAF_wlanIfaceIndex:
416210502Ssyrinx		val->v.integer = wif->index;
417210502Ssyrinx		return (SNMP_ERR_NOERROR);
418210502Ssyrinx	case LEAF_wlanIfaceName:
419210502Ssyrinx		return (string_get(val, wif->wname, -1));
420210502Ssyrinx	case LEAF_wlanParentIfName:
421210502Ssyrinx		return (string_get(val, wif->pname, -1));
422210502Ssyrinx	case LEAF_wlanIfaceOperatingMode:
423210502Ssyrinx		val->v.integer = wif->mode;
424210502Ssyrinx		return (SNMP_ERR_NOERROR);
425210502Ssyrinx	case LEAF_wlanIfaceFlags:
426210502Ssyrinx		return (bits_get(val, (uint8_t *)&wif->flags,
427210502Ssyrinx		    sizeof(wif->flags)));
428210502Ssyrinx	case LEAF_wlanIfaceBssid:
429210502Ssyrinx		return (string_get(val, wif->dbssid, IEEE80211_ADDR_LEN));
430210502Ssyrinx	case LEAF_wlanIfaceLocalAddress:
431210502Ssyrinx		return (string_get(val, wif->dlmac, IEEE80211_ADDR_LEN));
432210502Ssyrinx	case LEAF_wlanIfaceStatus:
433210502Ssyrinx		val->v.integer = wif->status;
434210502Ssyrinx		return (SNMP_ERR_NOERROR);
435210502Ssyrinx	case LEAF_wlanIfaceState:
436210502Ssyrinx		val->v.integer = wif->state;
437210502Ssyrinx		return (SNMP_ERR_NOERROR);
438210502Ssyrinx	}
439210502Ssyrinx
440210502Ssyrinx	abort();
441210502Ssyrinx}
442210502Ssyrinx
443210502Ssyrinxint
444210502Ssyrinxop_wlan_if_parent(struct snmp_context *ctx __unused, struct snmp_value *val,
445210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
446210502Ssyrinx{
447210502Ssyrinx	struct wlan_iface *wif;
448210502Ssyrinx
449210502Ssyrinx	wlan_update_interface_list();
450210502Ssyrinx
451210502Ssyrinx	switch (op) {
452210502Ssyrinx	case SNMP_OP_GET:
453210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
454210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
455210502Ssyrinx		break;
456210502Ssyrinx	case SNMP_OP_GETNEXT:
457210502Ssyrinx		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
458210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
459210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
460210502Ssyrinx		break;
461210502Ssyrinx	case SNMP_OP_SET:
462210502Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
463210502Ssyrinx	case SNMP_OP_COMMIT:
464210502Ssyrinx		/* FALLTHROUGH */
465210502Ssyrinx	case SNMP_OP_ROLLBACK:
466210502Ssyrinx		/* FALLTHROUGH */
467210502Ssyrinx	default:
468210502Ssyrinx		abort();
469210502Ssyrinx	}
470210502Ssyrinx
471210502Ssyrinx	switch (val->var.subs[sub - 1]) {
472210502Ssyrinx	case LEAF_wlanIfParentDriverCapabilities:
473210502Ssyrinx		return (bits_get(val, (uint8_t *)&wif->drivercaps,
474210502Ssyrinx		    sizeof(wif->drivercaps)));
475210502Ssyrinx	case LEAF_wlanIfParentCryptoCapabilities:
476210502Ssyrinx		return (bits_get(val, (uint8_t *)&wif->cryptocaps,
477210502Ssyrinx		    sizeof(wif->cryptocaps)));
478210502Ssyrinx	case LEAF_wlanIfParentHTCapabilities:
479210502Ssyrinx		return (bits_get(val, (uint8_t *)&wif->htcaps,
480210502Ssyrinx		    sizeof(wif->htcaps)));
481210502Ssyrinx	}
482210502Ssyrinx
483210502Ssyrinx	abort();
484210502Ssyrinx}
485210502Ssyrinx
486210502Ssyrinxint
487210502Ssyrinxop_wlan_iface_config(struct snmp_context *ctx, struct snmp_value *val,
488210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
489210502Ssyrinx{
490210502Ssyrinx	int intval, vlen, rc;
491210502Ssyrinx	char *strval;
492210502Ssyrinx	struct wlan_iface *wif;
493210502Ssyrinx
494210502Ssyrinx	wlan_update_interface_list();
495210502Ssyrinx
496210502Ssyrinx	switch (op) {
497210502Ssyrinx	case SNMP_OP_GET:
498210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
499210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
500210502Ssyrinx		goto get_config;
501210502Ssyrinx
502210502Ssyrinx	case SNMP_OP_GETNEXT:
503210502Ssyrinx		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
504210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
505210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
506210502Ssyrinx		goto get_config;
507210502Ssyrinx
508210502Ssyrinx	case SNMP_OP_SET:
509210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
510210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
511210502Ssyrinx
512210502Ssyrinx		intval = val->v.integer;
513210502Ssyrinx		strval = NULL;
514210502Ssyrinx		vlen = 0;
515210502Ssyrinx
516210502Ssyrinx		/* Simple sanity checks & save old data. */
517210502Ssyrinx		switch (val->var.subs[sub - 1]) {
518210502Ssyrinx		case LEAF_wlanIfaceCountryCode:
519210502Ssyrinx			if (val->v.octetstring.len != WLAN_COUNTRY_CODE_SIZE)
520210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
521210502Ssyrinx			break;
522210502Ssyrinx		case LEAF_wlanIfaceDesiredSsid:
523210502Ssyrinx			if (val->v.octetstring.len > IEEE80211_NWID_LEN)
524210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
525210502Ssyrinx			break;
526210502Ssyrinx		case LEAF_wlanIfaceDesiredBssid:
527210502Ssyrinx			if (val->v.octetstring.len != IEEE80211_ADDR_LEN)
528210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
529210502Ssyrinx			break;
530210502Ssyrinx		case LEAF_wlanIfacePacketBurst:
531210502Ssyrinx			ctx->scratch->int1 = wif->packet_burst;
532210502Ssyrinx			break;
533210502Ssyrinx		case LEAF_wlanIfaceRegDomain:
534210502Ssyrinx			ctx->scratch->int1 = wif->reg_domain;
535210502Ssyrinx			break;
536210502Ssyrinx		case LEAF_wlanIfaceDesiredChannel:
537210502Ssyrinx			ctx->scratch->int1 = wif->desired_channel;
538210502Ssyrinx			break;
539210502Ssyrinx		case LEAF_wlanIfaceDynamicFreqSelection:
540210502Ssyrinx			ctx->scratch->int1 = wif->dyn_frequency;
541210502Ssyrinx			break;
542210502Ssyrinx		case LEAF_wlanIfaceFastFrames:
543210502Ssyrinx			ctx->scratch->int1 = wif->fast_frames;
544210502Ssyrinx			break;
545210502Ssyrinx		case LEAF_wlanIfaceDturbo:
546210502Ssyrinx			ctx->scratch->int1 = wif->dturbo;
547210502Ssyrinx			break;
548210502Ssyrinx		case LEAF_wlanIfaceTxPower:
549210502Ssyrinx			ctx->scratch->int1 = wif->tx_power;
550210502Ssyrinx			break;
551210502Ssyrinx		case LEAF_wlanIfaceFragmentThreshold:
552210502Ssyrinx			ctx->scratch->int1 = wif->frag_threshold;
553210502Ssyrinx			break;
554210502Ssyrinx		case LEAF_wlanIfaceRTSThreshold:
555210502Ssyrinx			ctx->scratch->int1 = wif->rts_threshold;
556210502Ssyrinx			break;
557210502Ssyrinx		case LEAF_wlanIfaceWlanPrivacySubscribe:
558210502Ssyrinx			ctx->scratch->int1 = wif->priv_subscribe;
559210502Ssyrinx			break;
560210502Ssyrinx		case LEAF_wlanIfaceBgScan:
561210502Ssyrinx			ctx->scratch->int1 = wif->bg_scan;
562210502Ssyrinx			break;
563210502Ssyrinx		case LEAF_wlanIfaceBgScanIdle:
564210502Ssyrinx			ctx->scratch->int1 = wif->bg_scan_idle;
565210502Ssyrinx			break;
566210502Ssyrinx		case LEAF_wlanIfaceBgScanInterval:
567210502Ssyrinx			ctx->scratch->int1 = wif->bg_scan_interval;
568210502Ssyrinx			break;
569210502Ssyrinx		case LEAF_wlanIfaceBeaconMissedThreshold:
570210502Ssyrinx			ctx->scratch->int1 = wif->beacons_missed;
571210502Ssyrinx			break;
572210502Ssyrinx		case LEAF_wlanIfaceRoamingMode:
573210502Ssyrinx			ctx->scratch->int1 = wif->roam_mode;
574210502Ssyrinx			break;
575210502Ssyrinx		case LEAF_wlanIfaceDot11d:
576210502Ssyrinx			ctx->scratch->int1 = wif->dot11d;
577210502Ssyrinx			break;
578210502Ssyrinx		case LEAF_wlanIfaceDot11h:
579210502Ssyrinx			ctx->scratch->int1 = wif->dot11h;
580210502Ssyrinx			break;
581210502Ssyrinx		case LEAF_wlanIfaceDynamicWds:
582210502Ssyrinx			ctx->scratch->int1 = wif->dynamic_wds;
583210502Ssyrinx			break;
584210502Ssyrinx		case LEAF_wlanIfacePowerSave:
585210502Ssyrinx			ctx->scratch->int1 = wif->power_save;
586210502Ssyrinx			break;
587210502Ssyrinx		case LEAF_wlanIfaceApBridge:
588210502Ssyrinx			ctx->scratch->int1 = wif->ap_bridge;
589210502Ssyrinx			break;
590210502Ssyrinx		case LEAF_wlanIfaceBeaconInterval:
591210502Ssyrinx			ctx->scratch->int1 = wif->beacon_interval;
592210502Ssyrinx			break;
593210502Ssyrinx		case LEAF_wlanIfaceDtimPeriod:
594210502Ssyrinx			ctx->scratch->int1 = wif->dtim_period;
595210502Ssyrinx			break;
596210502Ssyrinx		case LEAF_wlanIfaceHideSsid:
597210502Ssyrinx			ctx->scratch->int1 = wif->hide_ssid;
598210502Ssyrinx			break;
599210502Ssyrinx		case LEAF_wlanIfaceInactivityProccess:
600210502Ssyrinx			ctx->scratch->int1 = wif->inact_process;
601210502Ssyrinx			break;
602210502Ssyrinx		case LEAF_wlanIfaceDot11gProtMode:
603210502Ssyrinx			ctx->scratch->int1 = wif->do11g_protect;
604210502Ssyrinx			break;
605210502Ssyrinx		case LEAF_wlanIfaceDot11gPureMode:
606210502Ssyrinx			ctx->scratch->int1 = wif->dot11g_pure;
607210502Ssyrinx			break;
608210502Ssyrinx		case LEAF_wlanIfaceDot11nPureMode:
609210502Ssyrinx			ctx->scratch->int1 = wif->dot11n_pure;
610210502Ssyrinx			break;
611210502Ssyrinx		case LEAF_wlanIfaceDot11nAmpdu:
612210502Ssyrinx			ctx->scratch->int1 = wif->ampdu;
613210502Ssyrinx			break;
614210502Ssyrinx		case LEAF_wlanIfaceDot11nAmpduDensity:
615210502Ssyrinx			ctx->scratch->int1 = wif->ampdu_density;
616210502Ssyrinx			break;
617210502Ssyrinx		case LEAF_wlanIfaceDot11nAmpduLimit:
618210502Ssyrinx			ctx->scratch->int1 = wif->ampdu_limit;
619210502Ssyrinx			break;
620210502Ssyrinx		case LEAF_wlanIfaceDot11nAmsdu:
621210502Ssyrinx			ctx->scratch->int1 = wif->amsdu;
622210502Ssyrinx			break;
623210502Ssyrinx		case LEAF_wlanIfaceDot11nAmsduLimit:
624210502Ssyrinx			ctx->scratch->int1 = wif->amsdu_limit;
625210502Ssyrinx			break;
626210502Ssyrinx		case LEAF_wlanIfaceDot11nHighThroughput:
627210502Ssyrinx			ctx->scratch->int1 = wif->ht_enabled;
628210502Ssyrinx			break;
629210502Ssyrinx		case LEAF_wlanIfaceDot11nHTCompatible:
630210502Ssyrinx			ctx->scratch->int1 = wif->ht_compatible;
631210502Ssyrinx			break;
632210502Ssyrinx		case LEAF_wlanIfaceDot11nHTProtMode:
633210502Ssyrinx			ctx->scratch->int1 = wif->ht_prot_mode;
634210502Ssyrinx			break;
635210502Ssyrinx		case LEAF_wlanIfaceDot11nRIFS:
636210502Ssyrinx			ctx->scratch->int1 = wif->rifs;
637210502Ssyrinx			break;
638210502Ssyrinx		case LEAF_wlanIfaceDot11nShortGI:
639210502Ssyrinx			ctx->scratch->int1 = wif->short_gi;
640210502Ssyrinx			break;
641210502Ssyrinx		case LEAF_wlanIfaceDot11nSMPSMode:
642210502Ssyrinx			ctx->scratch->int1 = wif->smps_mode;
643210502Ssyrinx			break;
644210502Ssyrinx		case LEAF_wlanIfaceTdmaSlot:
645210502Ssyrinx			ctx->scratch->int1 = wif->tdma_slot;
646210502Ssyrinx			break;
647210502Ssyrinx		case LEAF_wlanIfaceTdmaSlotCount:
648210502Ssyrinx			ctx->scratch->int1 = wif->tdma_slot_count;
649210502Ssyrinx			break;
650210502Ssyrinx		case LEAF_wlanIfaceTdmaSlotLength:
651210502Ssyrinx			ctx->scratch->int1 = wif->tdma_slot_length;
652210502Ssyrinx			break;
653210502Ssyrinx		case LEAF_wlanIfaceTdmaBeaconInterval:
654210502Ssyrinx			ctx->scratch->int1 = wif->tdma_binterval;
655210502Ssyrinx			break;
656210502Ssyrinx		default:
657210502Ssyrinx			abort();
658210502Ssyrinx		}
659210502Ssyrinx
660210502Ssyrinx		if (val->syntax != SNMP_SYNTAX_OCTETSTRING)
661210502Ssyrinx			goto set_config;
662210502Ssyrinx
663210502Ssyrinx		ctx->scratch->int1 = val->v.octetstring.len;
664210502Ssyrinx		ctx->scratch->ptr1 = malloc(val->v.octetstring.len + 1);
665210502Ssyrinx		if (ctx->scratch->ptr1 == NULL)
666210502Ssyrinx			return (SNMP_ERR_GENERR); /* XXX */
667210502Ssyrinx		if (val->var.subs[sub - 1] == LEAF_wlanIfaceDesiredSsid)
668210502Ssyrinx			strlcpy(ctx->scratch->ptr1, val->v.octetstring.octets,
669210502Ssyrinx			    val->v.octetstring.len + 1);
670210502Ssyrinx		else
671210502Ssyrinx			memcpy(ctx->scratch->ptr1, val->v.octetstring.octets,
672210502Ssyrinx			    val->v.octetstring.len);
673210502Ssyrinx		strval = val->v.octetstring.octets;
674210502Ssyrinx		vlen = val->v.octetstring.len;
675210502Ssyrinx		goto set_config;
676210502Ssyrinx
677210502Ssyrinx	case SNMP_OP_ROLLBACK:
678210502Ssyrinx		intval = ctx->scratch->int1;
679210502Ssyrinx		strval = NULL;
680210502Ssyrinx		vlen = 0;
681210502Ssyrinx
682210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
683210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
684210502Ssyrinx		switch (val->var.subs[sub - 1]) {
685210502Ssyrinx		case LEAF_wlanIfaceCountryCode:
686210502Ssyrinx		case LEAF_wlanIfaceDesiredSsid:
687210502Ssyrinx		case LEAF_wlanIfaceDesiredBssid:
688210502Ssyrinx			strval = ctx->scratch->ptr1;
689210502Ssyrinx			vlen = ctx->scratch->int1;
690210502Ssyrinx			break;
691210502Ssyrinx		default:
692210502Ssyrinx			break;
693210502Ssyrinx		}
694210502Ssyrinx		goto set_config;
695210502Ssyrinx
696210502Ssyrinx	case SNMP_OP_COMMIT:
697210502Ssyrinx		switch (val->var.subs[sub - 1]) {
698210502Ssyrinx		case LEAF_wlanIfaceCountryCode:
699210502Ssyrinx		case LEAF_wlanIfaceDesiredSsid:
700210502Ssyrinx		case LEAF_wlanIfaceDesiredBssid:
701210502Ssyrinx			free(ctx->scratch->ptr1);
702210502Ssyrinx			/* FALLTHROUGH */
703210502Ssyrinx		default:
704210502Ssyrinx			return (SNMP_ERR_NOERROR);
705210502Ssyrinx		}
706210502Ssyrinx	}
707210502Ssyrinx	abort();
708210502Ssyrinx
709210502Ssyrinxget_config:
710210502Ssyrinx
711210502Ssyrinx	if (wlan_config_get_ioctl(wif, val->var.subs[sub - 1]) < 0)
712210502Ssyrinx		return (SNMP_ERR_GENERR);
713210502Ssyrinx
714210502Ssyrinx	switch (val->var.subs[sub - 1]) {
715210502Ssyrinx	case LEAF_wlanIfacePacketBurst:
716210502Ssyrinx		val->v.integer = wif->packet_burst;
717210502Ssyrinx		break;
718210502Ssyrinx	case LEAF_wlanIfaceCountryCode:
719210502Ssyrinx		return (string_get(val, wif->country_code,
720210502Ssyrinx		    WLAN_COUNTRY_CODE_SIZE));
721210502Ssyrinx	case LEAF_wlanIfaceRegDomain:
722210502Ssyrinx		val->v.integer = wif->reg_domain;
723210502Ssyrinx		break;
724210502Ssyrinx	case LEAF_wlanIfaceDesiredSsid:
725210502Ssyrinx		return (string_get(val, wif->desired_ssid, -1));
726210502Ssyrinx	case LEAF_wlanIfaceDesiredChannel:
727210502Ssyrinx		val->v.integer = wif->desired_channel;
728210502Ssyrinx		break;
729210502Ssyrinx	case LEAF_wlanIfaceDynamicFreqSelection:
730210502Ssyrinx		val->v.integer = wif->dyn_frequency;
731210502Ssyrinx		break;
732210502Ssyrinx	case LEAF_wlanIfaceFastFrames:
733210502Ssyrinx		val->v.integer = wif->fast_frames;
734210502Ssyrinx		break;
735210502Ssyrinx	case LEAF_wlanIfaceDturbo:
736210502Ssyrinx		val->v.integer = wif->dturbo;
737210502Ssyrinx		break;
738210502Ssyrinx	case LEAF_wlanIfaceTxPower:
739210502Ssyrinx		val->v.integer = wif->tx_power;
740210502Ssyrinx		break;
741210502Ssyrinx	case LEAF_wlanIfaceFragmentThreshold:
742210502Ssyrinx		val->v.integer = wif->frag_threshold;
743210502Ssyrinx		break;
744210502Ssyrinx	case LEAF_wlanIfaceRTSThreshold:
745210502Ssyrinx		val->v.integer = wif->rts_threshold;
746210502Ssyrinx		break;
747210502Ssyrinx	case LEAF_wlanIfaceWlanPrivacySubscribe:
748210502Ssyrinx		val->v.integer = wif->priv_subscribe;
749210502Ssyrinx		break;
750210502Ssyrinx	case LEAF_wlanIfaceBgScan:
751210502Ssyrinx		val->v.integer = wif->bg_scan;
752210502Ssyrinx		break;
753210502Ssyrinx	case LEAF_wlanIfaceBgScanIdle:
754210502Ssyrinx		val->v.integer = wif->bg_scan_idle;
755210502Ssyrinx		break;
756210502Ssyrinx	case LEAF_wlanIfaceBgScanInterval:
757210502Ssyrinx		val->v.integer = wif->bg_scan_interval;
758210502Ssyrinx		break;
759210502Ssyrinx	case LEAF_wlanIfaceBeaconMissedThreshold:
760210502Ssyrinx		val->v.integer = wif->beacons_missed;
761210502Ssyrinx		break;
762210502Ssyrinx	case LEAF_wlanIfaceDesiredBssid:
763210502Ssyrinx		return (string_get(val, wif->desired_bssid,
764210502Ssyrinx		    IEEE80211_ADDR_LEN));
765210502Ssyrinx	case LEAF_wlanIfaceRoamingMode:
766210502Ssyrinx		val->v.integer = wif->roam_mode;
767210502Ssyrinx		break;
768210502Ssyrinx	case LEAF_wlanIfaceDot11d:
769210502Ssyrinx		val->v.integer = wif->dot11d;
770210502Ssyrinx		break;
771210502Ssyrinx	case LEAF_wlanIfaceDot11h:
772210502Ssyrinx		val->v.integer = wif->dot11h;
773210502Ssyrinx		break;
774210502Ssyrinx	case LEAF_wlanIfaceDynamicWds:
775210502Ssyrinx		val->v.integer = wif->dynamic_wds;
776210502Ssyrinx		break;
777210502Ssyrinx	case LEAF_wlanIfacePowerSave:
778210502Ssyrinx		val->v.integer = wif->power_save;
779210502Ssyrinx		break;
780210502Ssyrinx	case LEAF_wlanIfaceApBridge:
781210502Ssyrinx		val->v.integer = wif->ap_bridge;
782210502Ssyrinx		break;
783210502Ssyrinx	case LEAF_wlanIfaceBeaconInterval:
784210502Ssyrinx		val->v.integer = wif->beacon_interval;
785210502Ssyrinx		break;
786210502Ssyrinx	case LEAF_wlanIfaceDtimPeriod:
787210502Ssyrinx		val->v.integer = wif->dtim_period;
788210502Ssyrinx		break;
789210502Ssyrinx	case LEAF_wlanIfaceHideSsid:
790210502Ssyrinx		val->v.integer = wif->hide_ssid;
791210502Ssyrinx		break;
792210502Ssyrinx	case LEAF_wlanIfaceInactivityProccess:
793210502Ssyrinx		val->v.integer = wif->inact_process;
794210502Ssyrinx		break;
795210502Ssyrinx	case LEAF_wlanIfaceDot11gProtMode:
796210502Ssyrinx		val->v.integer = wif->do11g_protect;
797210502Ssyrinx		break;
798210502Ssyrinx	case LEAF_wlanIfaceDot11gPureMode:
799210502Ssyrinx		val->v.integer = wif->dot11g_pure;
800210502Ssyrinx		break;
801210502Ssyrinx	case LEAF_wlanIfaceDot11nPureMode:
802210502Ssyrinx		val->v.integer = wif->dot11n_pure;
803210502Ssyrinx		break;
804210502Ssyrinx	case LEAF_wlanIfaceDot11nAmpdu:
805210502Ssyrinx		val->v.integer = wif->ampdu;
806210502Ssyrinx		break;
807210502Ssyrinx	case LEAF_wlanIfaceDot11nAmpduDensity:
808210502Ssyrinx		val->v.integer = wif->ampdu_density;
809210502Ssyrinx		break;
810210502Ssyrinx	case LEAF_wlanIfaceDot11nAmpduLimit:
811210502Ssyrinx		val->v.integer = wif->ampdu_limit;
812210502Ssyrinx		break;
813210502Ssyrinx	case LEAF_wlanIfaceDot11nAmsdu:
814210502Ssyrinx		val->v.integer = wif->amsdu;
815210502Ssyrinx		break;
816210502Ssyrinx	case LEAF_wlanIfaceDot11nAmsduLimit:
817210502Ssyrinx		val->v.integer = wif->amsdu_limit;
818210502Ssyrinx		break;
819210502Ssyrinx	case LEAF_wlanIfaceDot11nHighThroughput:
820210502Ssyrinx		val->v.integer = wif->ht_enabled;
821210502Ssyrinx		break;
822210502Ssyrinx	case LEAF_wlanIfaceDot11nHTCompatible:
823210502Ssyrinx		val->v.integer = wif->ht_compatible;
824210502Ssyrinx		break;
825210502Ssyrinx	case LEAF_wlanIfaceDot11nHTProtMode:
826210502Ssyrinx		val->v.integer = wif->ht_prot_mode;
827210502Ssyrinx		break;
828210502Ssyrinx	case LEAF_wlanIfaceDot11nRIFS:
829210502Ssyrinx		val->v.integer = wif->rifs;
830210502Ssyrinx		break;
831210502Ssyrinx	case LEAF_wlanIfaceDot11nShortGI:
832210502Ssyrinx		val->v.integer = wif->short_gi;
833210502Ssyrinx		break;
834210502Ssyrinx	case LEAF_wlanIfaceDot11nSMPSMode:
835210502Ssyrinx		val->v.integer = wif->smps_mode;
836210502Ssyrinx		break;
837210502Ssyrinx	case LEAF_wlanIfaceTdmaSlot:
838210502Ssyrinx		val->v.integer = wif->tdma_slot;
839210502Ssyrinx		break;
840210502Ssyrinx	case LEAF_wlanIfaceTdmaSlotCount:
841210502Ssyrinx		val->v.integer = wif->tdma_slot_count;
842210502Ssyrinx		break;
843210502Ssyrinx	case LEAF_wlanIfaceTdmaSlotLength:
844210502Ssyrinx		val->v.integer = wif->tdma_slot_length;
845210502Ssyrinx		break;
846210502Ssyrinx	case LEAF_wlanIfaceTdmaBeaconInterval:
847210502Ssyrinx		val->v.integer = wif->tdma_binterval;
848210502Ssyrinx		break;
849210502Ssyrinx	}
850210502Ssyrinx
851210502Ssyrinx	return (SNMP_ERR_NOERROR);
852210502Ssyrinx
853210502Ssyrinxset_config:
854210502Ssyrinx	rc = wlan_config_set_ioctl(wif, val->var.subs[sub - 1], intval,
855210502Ssyrinx	    strval, vlen);
856210502Ssyrinx
857210502Ssyrinx	if (op == SNMP_OP_ROLLBACK) {
858210502Ssyrinx		switch (val->var.subs[sub - 1]) {
859210502Ssyrinx		case LEAF_wlanIfaceCountryCode:
860210502Ssyrinx		case LEAF_wlanIfaceDesiredSsid:
861210502Ssyrinx		case LEAF_wlanIfaceDesiredBssid:
862210502Ssyrinx			free(ctx->scratch->ptr1);
863210502Ssyrinx			/* FALLTHROUGH */
864210502Ssyrinx		default:
865210502Ssyrinx			break;
866210502Ssyrinx		}
867210502Ssyrinx	}
868210502Ssyrinx
869210502Ssyrinx	if (rc < 0)
870210502Ssyrinx		return (SNMP_ERR_GENERR);
871210502Ssyrinx
872210502Ssyrinx	return (SNMP_ERR_NOERROR);
873210502Ssyrinx}
874210502Ssyrinx
875210502Ssyrinxint
876210502Ssyrinxop_wlan_if_peer(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
877210502Ssyrinx    uint32_t iidx __unused, enum snmp_op op)
878210502Ssyrinx{
879210502Ssyrinx	struct wlan_peer *wip;
880210502Ssyrinx	struct wlan_iface *wif;
881210502Ssyrinx
882210502Ssyrinx	wlan_update_interface_list();
883210502Ssyrinx	wlan_update_peers();
884210502Ssyrinx
885210502Ssyrinx	switch (op) {
886210502Ssyrinx	case SNMP_OP_GET:
887210502Ssyrinx		if ((wip = wlan_get_peer(&val->var, sub, &wif)) == NULL)
888210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
889210502Ssyrinx		break;
890210502Ssyrinx	case SNMP_OP_GETNEXT:
891210502Ssyrinx		if ((wip = wlan_get_next_peer(&val->var, sub, &wif)) == NULL)
892210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
893210502Ssyrinx		wlan_append_mac_index(&val->var, sub, wif->wname, wip->pmac);
894210502Ssyrinx		break;
895210502Ssyrinx	case SNMP_OP_SET:
896210502Ssyrinx		if ((wip = wlan_get_peer(&val->var, sub, &wif)) == NULL)
897210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
898210502Ssyrinx		if (val->var.subs[sub - 1] != LEAF_wlanIfacePeerVlanTag)
899210502Ssyrinx			return (SNMP_ERR_GENERR);
900210502Ssyrinx		ctx->scratch->int1 = wip->vlan;
901210502Ssyrinx		if (wlan_peer_set_vlan(wif, wip, val->v.integer) < 0)
902210502Ssyrinx			return (SNMP_ERR_GENERR);
903210502Ssyrinx		return (SNMP_ERR_NOERROR);
904210502Ssyrinx	case SNMP_OP_COMMIT:
905210502Ssyrinx		return (SNMP_ERR_NOERROR);
906210502Ssyrinx	case SNMP_OP_ROLLBACK:
907210502Ssyrinx		if ((wip = wlan_get_peer(&val->var, sub, &wif)) == NULL)
908210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
909210502Ssyrinx		if (val->var.subs[sub - 1] != LEAF_wlanIfacePeerVlanTag)
910210502Ssyrinx			return (SNMP_ERR_GENERR);
911210502Ssyrinx		if (wlan_peer_set_vlan(wif, wip, ctx->scratch->int1) < 0)
912210502Ssyrinx			return (SNMP_ERR_GENERR);
913210502Ssyrinx		return (SNMP_ERR_NOERROR);
914210502Ssyrinx	default:
915210502Ssyrinx		abort();
916210502Ssyrinx	}
917210502Ssyrinx
918210502Ssyrinx	switch (val->var.subs[sub - 1]) {
919210502Ssyrinx	case LEAF_wlanIfacePeerAddress:
920210502Ssyrinx		return (string_get(val, wip->pmac, IEEE80211_ADDR_LEN));
921210502Ssyrinx	case LEAF_wlanIfacePeerAssociationId:
922210502Ssyrinx		val->v.integer = wip->associd;
923210502Ssyrinx		break;
924210502Ssyrinx	case LEAF_wlanIfacePeerVlanTag:
925210502Ssyrinx		val->v.integer = wip->vlan;
926210502Ssyrinx		break;
927210502Ssyrinx	case LEAF_wlanIfacePeerFrequency:
928210502Ssyrinx		val->v.integer = wip->frequency;
929210502Ssyrinx		break;
930210502Ssyrinx	case LEAF_wlanIfacePeerCurrentTXRate:
931210502Ssyrinx		val->v.integer = wip->txrate;
932210502Ssyrinx		break;
933210502Ssyrinx	case LEAF_wlanIfacePeerRxSignalStrength:
934210502Ssyrinx		val->v.integer = wip->rssi;
935210502Ssyrinx		break;
936210502Ssyrinx	case LEAF_wlanIfacePeerIdleTimer:
937210502Ssyrinx		val->v.integer = wip->idle;
938210502Ssyrinx		break;
939210502Ssyrinx	case LEAF_wlanIfacePeerTxSequenceNo:
940210502Ssyrinx		val->v.integer = wip->txseqs;
941210502Ssyrinx		break;
942210502Ssyrinx	case LEAF_wlanIfacePeerRxSequenceNo:
943210502Ssyrinx		val->v.integer = wip->rxseqs;
944210502Ssyrinx		break;
945210502Ssyrinx	case LEAF_wlanIfacePeerTxPower:
946210502Ssyrinx		val->v.integer = wip->txpower;
947210502Ssyrinx		break;
948210502Ssyrinx	case LEAF_wlanIfacePeerCapabilities:
949210502Ssyrinx		return (bits_get(val, (uint8_t *)&wip->capinfo,
950210502Ssyrinx		    sizeof(wip->capinfo)));
951210502Ssyrinx	case LEAF_wlanIfacePeerFlags:
952210502Ssyrinx		return (bits_get(val, (uint8_t *)&wip->state,
953210502Ssyrinx		    sizeof(wip->state)));
954210502Ssyrinx	default:
955210502Ssyrinx		abort();
956210502Ssyrinx	}
957210502Ssyrinx
958210502Ssyrinx	return (SNMP_ERR_NOERROR);
959210502Ssyrinx}
960210502Ssyrinx
961210502Ssyrinxint
962210502Ssyrinxop_wlan_channels(struct snmp_context *ctx __unused, struct snmp_value *val,
963210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
964210502Ssyrinx{
965210502Ssyrinx	int32_t bits;
966210502Ssyrinx	struct ieee80211_channel *channel;
967210502Ssyrinx	struct wlan_iface *wif;
968210502Ssyrinx
969210502Ssyrinx	wlan_update_interface_list();
970210502Ssyrinx	wlan_update_channels();
971210502Ssyrinx
972210502Ssyrinx	switch (op) {
973210502Ssyrinx	case SNMP_OP_GET:
974210502Ssyrinx		if ((channel = wlan_get_channel(&val->var, sub, &wif)) == NULL)
975210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
976210502Ssyrinx		break;
977210502Ssyrinx	case SNMP_OP_GETNEXT:
978210502Ssyrinx		channel = wlan_get_next_channel(&val->var, sub, &wif);
979210502Ssyrinx		if (channel == NULL || wif == NULL)
980210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
981210502Ssyrinx		wlan_append_channel_index(&val->var, sub, wif, channel);
982210502Ssyrinx		break;
983210502Ssyrinx	case SNMP_OP_SET:
984210502Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
985210502Ssyrinx	case SNMP_OP_COMMIT:
986210502Ssyrinx		/* FALLTHROUGH */
987210502Ssyrinx	case SNMP_OP_ROLLBACK:
988210502Ssyrinx		/* FALLTHROUGH */
989210502Ssyrinx	default:
990210502Ssyrinx		abort();
991210502Ssyrinx	}
992210502Ssyrinx
993210502Ssyrinx	switch (val->var.subs[sub - 1]) {
994210502Ssyrinx	case LEAF_wlanIfaceChannelIeeeId:
995210502Ssyrinx		val->v.integer = channel->ic_ieee;
996210502Ssyrinx		break;
997210502Ssyrinx	case LEAF_wlanIfaceChannelType:
998210502Ssyrinx		val->v.integer = wlan_get_channel_type(channel);
999210502Ssyrinx		break;
1000210502Ssyrinx	case LEAF_wlanIfaceChannelFlags:
1001210502Ssyrinx		bits = wlan_channel_flags_to_snmp(channel->ic_flags);
1002210502Ssyrinx		return (bits_get(val, (uint8_t *)&bits, sizeof(bits)));
1003210502Ssyrinx	case LEAF_wlanIfaceChannelFrequency:
1004210502Ssyrinx		val->v.integer = channel->ic_freq;
1005210502Ssyrinx		break;
1006210502Ssyrinx	case LEAF_wlanIfaceChannelMaxRegPower:
1007210502Ssyrinx		val->v.integer = channel->ic_maxregpower;
1008210502Ssyrinx		break;
1009210502Ssyrinx	case LEAF_wlanIfaceChannelMaxTxPower:
1010210502Ssyrinx		val->v.integer = channel->ic_maxpower;
1011210502Ssyrinx		break;
1012210502Ssyrinx	case LEAF_wlanIfaceChannelMinTxPower:
1013210502Ssyrinx		val->v.integer = channel->ic_minpower;
1014210502Ssyrinx		break;
1015210502Ssyrinx	case LEAF_wlanIfaceChannelState:
1016210502Ssyrinx		bits = wlan_channel_state_to_snmp(channel->ic_state);
1017210502Ssyrinx		return (bits_get(val, (uint8_t *)&bits, sizeof(bits)));
1018210502Ssyrinx	case LEAF_wlanIfaceChannelHTExtension:
1019210502Ssyrinx		val->v.integer = channel->ic_extieee;
1020210502Ssyrinx		break;
1021210502Ssyrinx	case LEAF_wlanIfaceChannelMaxAntennaGain:
1022210502Ssyrinx		val->v.integer = channel->ic_maxantgain;
1023210502Ssyrinx		break;
1024210502Ssyrinx	}
1025210502Ssyrinx
1026210502Ssyrinx	return (SNMP_ERR_NOERROR);
1027210502Ssyrinx}
1028210502Ssyrinx
1029210502Ssyrinxint
1030210502Ssyrinxop_wlan_roam_params(struct snmp_context *ctx __unused, struct snmp_value *val,
1031210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1032210502Ssyrinx{
1033210502Ssyrinx	uint32_t phy;
1034210502Ssyrinx	struct ieee80211_roamparam *rparam;
1035210502Ssyrinx	struct wlan_iface *wif;
1036210502Ssyrinx
1037210502Ssyrinx	wlan_update_interface_list();
1038210502Ssyrinx	wlan_update_roam_params();
1039210502Ssyrinx
1040210502Ssyrinx	switch (op) {
1041210502Ssyrinx	case SNMP_OP_GET:
1042210502Ssyrinx		rparam = wlan_get_roam_param(&val->var, sub, &wif);
1043210502Ssyrinx		if (rparam == NULL)
1044210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1045210502Ssyrinx		break;
1046210502Ssyrinx	case SNMP_OP_GETNEXT:
1047210502Ssyrinx		rparam = wlan_get_next_roam_param(&val->var, sub, &wif, &phy);
1048210502Ssyrinx		if (rparam == NULL || wif == NULL)
1049210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1050210502Ssyrinx		wlan_append_phy_index(&val->var, sub, wif->wname, phy);
1051210502Ssyrinx		break;
1052210502Ssyrinx	case SNMP_OP_SET:
1053210502Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
1054210502Ssyrinx	case SNMP_OP_COMMIT:
1055210502Ssyrinx		/* FALLTHROUGH */
1056210502Ssyrinx	case SNMP_OP_ROLLBACK:
1057210502Ssyrinx		/* FALLTHROUGH */
1058210502Ssyrinx	default:
1059210502Ssyrinx		abort();
1060210502Ssyrinx	}
1061210502Ssyrinx
1062210502Ssyrinx	switch (val->var.subs[sub - 1]) {
1063210502Ssyrinx	case LEAF_wlanIfRoamRxSignalStrength:
1064210502Ssyrinx		val->v.integer = rparam->rssi/2;
1065210502Ssyrinx		break;
1066210502Ssyrinx	case LEAF_wlanIfRoamTxRateThreshold:
1067210502Ssyrinx		val->v.integer = rparam->rate/2;
1068210502Ssyrinx		break;
1069210502Ssyrinx	default:
1070210502Ssyrinx		abort();
1071210502Ssyrinx	}
1072210502Ssyrinx
1073210502Ssyrinx	return (SNMP_ERR_NOERROR);
1074210502Ssyrinx}
1075210502Ssyrinx
1076210502Ssyrinxint
1077210502Ssyrinxop_wlan_tx_params(struct snmp_context *ctx, struct snmp_value *val,
1078210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1079210502Ssyrinx{
1080210502Ssyrinx	uint32_t phy;
1081210502Ssyrinx	struct ieee80211_txparam *txparam;
1082210502Ssyrinx	struct wlan_iface *wif;
1083210502Ssyrinx
1084210502Ssyrinx	wlan_update_interface_list();
1085210502Ssyrinx	wlan_update_tx_params();
1086210502Ssyrinx
1087210502Ssyrinx	switch (op) {
1088210502Ssyrinx	case SNMP_OP_GET:
1089210502Ssyrinx		txparam = wlan_get_tx_param(&val->var, sub, &wif, &phy);
1090210502Ssyrinx		if (txparam == NULL)
1091210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1092210502Ssyrinx		goto get_txparams;
1093210502Ssyrinx
1094210502Ssyrinx	case SNMP_OP_GETNEXT:
1095210502Ssyrinx		txparam = wlan_get_next_tx_param(&val->var, sub, &wif, &phy);
1096210502Ssyrinx		if (txparam == NULL || wif == NULL)
1097210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1098210502Ssyrinx		wlan_append_phy_index(&val->var, sub, wif->wname, phy);
1099210502Ssyrinx		goto get_txparams;
1100210502Ssyrinx
1101210502Ssyrinx	case SNMP_OP_SET:
1102210502Ssyrinx		txparam = wlan_get_tx_param(&val->var, sub, &wif, &phy);
1103210502Ssyrinx		if (txparam == NULL || wif == NULL)
1104210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1105210502Ssyrinx		switch (val->var.subs[sub - 1]) {
1106210502Ssyrinx		case LEAF_wlanIfTxUnicastRate:
1107210502Ssyrinx			ctx->scratch->int1 = txparam->ucastrate;
1108210502Ssyrinx			txparam->ucastrate = val->v.integer * 2;
1109210502Ssyrinx			break;
1110210502Ssyrinx		case LEAF_wlanIfTxMcastRate:
1111210502Ssyrinx			ctx->scratch->int1 = txparam->mcastrate;
1112210502Ssyrinx			txparam->mcastrate = val->v.integer * 2;
1113210502Ssyrinx			break;
1114210502Ssyrinx		case LEAF_wlanIfTxMgmtRate:
1115210502Ssyrinx			ctx->scratch->int1 = txparam->mgmtrate;
1116210502Ssyrinx			txparam->mgmtrate = val->v.integer * 2;
1117210502Ssyrinx			break;
1118210502Ssyrinx		case LEAF_wlanIfTxMaxRetryCount:
1119210502Ssyrinx			ctx->scratch->int1 = txparam->maxretry;
1120210502Ssyrinx			txparam->maxretry = val->v.integer;
1121210502Ssyrinx			break;
1122210502Ssyrinx		default:
1123210502Ssyrinx			abort();
1124210502Ssyrinx		}
1125210502Ssyrinx		if (wlan_set_tx_params(wif, phy) < 0)
1126210502Ssyrinx			return (SNMP_ERR_GENERR);
1127210502Ssyrinx		return (SNMP_ERR_NOERROR);
1128210502Ssyrinx
1129210502Ssyrinx	case SNMP_OP_COMMIT:
1130210502Ssyrinx		return (SNMP_ERR_NOERROR);
1131210502Ssyrinx
1132210502Ssyrinx	case SNMP_OP_ROLLBACK:
1133210502Ssyrinx		txparam = wlan_get_tx_param(&val->var, sub, &wif, &phy);
1134210502Ssyrinx		if (txparam == NULL || wif == NULL)
1135210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1136210502Ssyrinx		switch (val->var.subs[sub - 1]) {
1137210502Ssyrinx		case LEAF_wlanIfTxUnicastRate:
1138210502Ssyrinx			txparam->ucastrate = ctx->scratch->int1;
1139210502Ssyrinx			break;
1140210502Ssyrinx		case LEAF_wlanIfTxMcastRate:
1141210502Ssyrinx			txparam->mcastrate = ctx->scratch->int1;
1142210502Ssyrinx			break;
1143210502Ssyrinx		case LEAF_wlanIfTxMgmtRate:
1144210502Ssyrinx			txparam->mgmtrate = ctx->scratch->int1;
1145210502Ssyrinx			break;
1146210502Ssyrinx		case LEAF_wlanIfTxMaxRetryCount:
1147210502Ssyrinx			txparam->maxretry = ctx->scratch->int1;
1148210502Ssyrinx			break;
1149210502Ssyrinx		default:
1150210502Ssyrinx			abort();
1151210502Ssyrinx		}
1152210502Ssyrinx		if (wlan_set_tx_params(wif, phy) < 0)
1153210502Ssyrinx			return (SNMP_ERR_GENERR);
1154210502Ssyrinx		return (SNMP_ERR_NOERROR);
1155210502Ssyrinx	default:
1156210502Ssyrinx		abort();
1157210502Ssyrinx	}
1158210502Ssyrinx
1159210502Ssyrinxget_txparams:
1160210502Ssyrinx	switch (val->var.subs[sub - 1]) {
1161210502Ssyrinx	case LEAF_wlanIfTxUnicastRate:
1162210502Ssyrinx		val->v.integer = txparam->ucastrate / 2;
1163210502Ssyrinx		break;
1164210502Ssyrinx	case LEAF_wlanIfTxMcastRate:
1165210502Ssyrinx		val->v.integer = txparam->mcastrate / 2;
1166210502Ssyrinx		break;
1167210502Ssyrinx	case LEAF_wlanIfTxMgmtRate:
1168210502Ssyrinx		val->v.integer = txparam->mgmtrate / 2;
1169210502Ssyrinx		break;
1170210502Ssyrinx	case LEAF_wlanIfTxMaxRetryCount:
1171210502Ssyrinx		val->v.integer = txparam->maxretry;
1172210502Ssyrinx		break;
1173210502Ssyrinx	default:
1174210502Ssyrinx		abort();
1175210502Ssyrinx	}
1176210502Ssyrinx
1177210502Ssyrinx	return (SNMP_ERR_NOERROR);
1178210502Ssyrinx}
1179210502Ssyrinx
1180210502Ssyrinxint
1181210502Ssyrinxop_wlan_scan_config(struct snmp_context *ctx, struct snmp_value *val,
1182210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1183210502Ssyrinx{
1184210502Ssyrinx	struct wlan_iface *wif;
1185210502Ssyrinx
1186210502Ssyrinx	wlan_update_interface_list();
1187210502Ssyrinx
1188210502Ssyrinx	switch (op) {
1189210502Ssyrinx	case SNMP_OP_GET:
1190210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1191210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1192210502Ssyrinx		break;
1193210502Ssyrinx
1194210502Ssyrinx	case SNMP_OP_GETNEXT:
1195210502Ssyrinx		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
1196210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1197210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
1198210502Ssyrinx		break;
1199210502Ssyrinx
1200210502Ssyrinx	case SNMP_OP_SET:
1201210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1202210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1203210502Ssyrinx		if (wif->scan_status ==  wlanScanConfigStatus_running
1204210502Ssyrinx		    && val->var.subs[sub - 1] != LEAF_wlanScanConfigStatus)
1205210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1206210502Ssyrinx		switch (val->var.subs[sub - 1]) {
1207210502Ssyrinx		case LEAF_wlanScanFlags:
1208210502Ssyrinx			ctx->scratch->int1 = wif->scan_flags;
1209210502Ssyrinx			wif->scan_flags = val->v.integer;
1210210502Ssyrinx			break;
1211210502Ssyrinx		case LEAF_wlanScanDuration:
1212210502Ssyrinx			ctx->scratch->int1 = wif->scan_duration;
1213210502Ssyrinx			wif->scan_duration = val->v.integer;
1214210502Ssyrinx			break;
1215210502Ssyrinx		case LEAF_wlanScanMinChannelDwellTime:
1216210502Ssyrinx			ctx->scratch->int1 = wif->scan_mindwell;
1217210502Ssyrinx			wif->scan_mindwell = val->v.integer;
1218210502Ssyrinx			break;
1219210502Ssyrinx		case LEAF_wlanScanMaxChannelDwellTime:
1220210502Ssyrinx			ctx->scratch->int1 = wif->scan_maxdwell;
1221210502Ssyrinx			wif->scan_maxdwell = val->v.integer;
1222210502Ssyrinx			break;
1223210502Ssyrinx		case LEAF_wlanScanConfigStatus:
1224210502Ssyrinx			if (val->v.integer == wlanScanConfigStatus_running ||
1225210502Ssyrinx			    val->v.integer == wlanScanConfigStatus_cancel) {
1226210502Ssyrinx				ctx->scratch->int1 = wif->scan_status;
1227210502Ssyrinx				wif->scan_status = val->v.integer;
1228210502Ssyrinx				break;
1229210502Ssyrinx			}
1230210502Ssyrinx			return (SNMP_ERR_INCONS_VALUE);
1231210502Ssyrinx		}
1232210502Ssyrinx		return (SNMP_ERR_NOERROR);
1233210502Ssyrinx
1234210502Ssyrinx	case SNMP_OP_COMMIT:
1235210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1236210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1237210502Ssyrinx		if (val->var.subs[sub - 1] == LEAF_wlanScanConfigStatus)
1238210502Ssyrinx			if (wif->scan_status == wlanScanConfigStatus_running)
1239210502Ssyrinx				(void)wlan_set_scan_config(wif); /* XXX */
1240210502Ssyrinx		return (SNMP_ERR_NOERROR);
1241210502Ssyrinx
1242210502Ssyrinx	case SNMP_OP_ROLLBACK:
1243210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1244210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1245210502Ssyrinx		switch (val->var.subs[sub - 1]) {
1246210502Ssyrinx		case LEAF_wlanScanFlags:
1247210502Ssyrinx			wif->scan_flags = ctx->scratch->int1;
1248210502Ssyrinx			break;
1249210502Ssyrinx		case LEAF_wlanScanDuration:
1250210502Ssyrinx			wif->scan_duration = ctx->scratch->int1;
1251210502Ssyrinx			break;
1252210502Ssyrinx		case LEAF_wlanScanMinChannelDwellTime:
1253210502Ssyrinx			wif->scan_mindwell = ctx->scratch->int1;
1254210502Ssyrinx			break;
1255210502Ssyrinx		case LEAF_wlanScanMaxChannelDwellTime:
1256210502Ssyrinx			wif->scan_maxdwell = ctx->scratch->int1;
1257210502Ssyrinx			break;
1258210502Ssyrinx		case LEAF_wlanScanConfigStatus:
1259210502Ssyrinx			wif->scan_status = ctx->scratch->int1;
1260210502Ssyrinx			break;
1261210502Ssyrinx		}
1262210502Ssyrinx		return (SNMP_ERR_NOERROR);
1263210502Ssyrinx	default:
1264210502Ssyrinx		abort();
1265210502Ssyrinx	}
1266210502Ssyrinx
1267210502Ssyrinx	switch (val->var.subs[sub - 1]) {
1268210502Ssyrinx	case LEAF_wlanScanFlags:
1269210502Ssyrinx		val->v.integer = wif->scan_flags;
1270210502Ssyrinx		break;
1271210502Ssyrinx	case LEAF_wlanScanDuration:
1272210502Ssyrinx		val->v.integer = wif->scan_duration;
1273210502Ssyrinx		break;
1274210502Ssyrinx	case LEAF_wlanScanMinChannelDwellTime:
1275210502Ssyrinx		val->v.integer = wif->scan_mindwell;
1276210502Ssyrinx		break;
1277210502Ssyrinx	case LEAF_wlanScanMaxChannelDwellTime:
1278210502Ssyrinx		val->v.integer = wif->scan_maxdwell;
1279210502Ssyrinx		break;
1280210502Ssyrinx	case LEAF_wlanScanConfigStatus:
1281210502Ssyrinx		val->v.integer = wif->scan_status;
1282210502Ssyrinx		break;
1283210502Ssyrinx	}
1284210502Ssyrinx
1285210502Ssyrinx	return (SNMP_ERR_NOERROR);
1286210502Ssyrinx}
1287210502Ssyrinx
1288210502Ssyrinxint
1289210502Ssyrinxop_wlan_scan_results(struct snmp_context *ctx __unused, struct snmp_value *val,
1290210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1291210502Ssyrinx{
1292210502Ssyrinx	struct wlan_scan_result *sr;
1293210502Ssyrinx	struct wlan_iface *wif;
1294210502Ssyrinx
1295210502Ssyrinx	wlan_update_interface_list();
1296210502Ssyrinx	wlan_scan_update_results();
1297210502Ssyrinx
1298210502Ssyrinx	switch (op) {
1299210502Ssyrinx	case SNMP_OP_GET:
1300210502Ssyrinx		if ((sr = wlan_get_scanr(&val->var, sub, &wif)) == NULL)
1301210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1302210502Ssyrinx		break;
1303210502Ssyrinx
1304210502Ssyrinx	case SNMP_OP_GETNEXT:
1305210502Ssyrinx		if ((sr = wlan_get_next_scanr(&val->var, sub, &wif)) == NULL)
1306210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1307210502Ssyrinx		wlan_append_scanr_index(&val->var, sub, wif->wname, sr->ssid,
1308210502Ssyrinx		    sr->bssid);
1309210502Ssyrinx		break;
1310210502Ssyrinx
1311210502Ssyrinx	case SNMP_OP_SET:
1312210502Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
1313210502Ssyrinx	case SNMP_OP_COMMIT:
1314210502Ssyrinx		/* FALLTHROUGH */
1315210502Ssyrinx	case SNMP_OP_ROLLBACK:
1316210502Ssyrinx		/* FALLTHROUGH */
1317210502Ssyrinx	default:
1318210502Ssyrinx		abort();
1319210502Ssyrinx	}
1320210502Ssyrinx
1321210502Ssyrinx	switch (val->var.subs[sub - 1]) {
1322210502Ssyrinx	case LEAF_wlanScanResultID:
1323210502Ssyrinx		return (string_get(val, sr->ssid, -1));
1324210502Ssyrinx	case LEAF_wlanScanResultBssid:
1325210502Ssyrinx		return (string_get(val, sr->bssid, IEEE80211_ADDR_LEN));
1326210502Ssyrinx	case LEAF_wlanScanResultChannel:
1327210502Ssyrinx		val->v.integer = sr->opchannel; /* XXX */
1328210502Ssyrinx		break;
1329210502Ssyrinx	case LEAF_wlanScanResultRate:
1330210502Ssyrinx		val->v.integer = sr->rssi;
1331210502Ssyrinx		break;
1332210502Ssyrinx	case LEAF_wlanScanResultNoise:
1333210502Ssyrinx		val->v.integer = sr->noise;
1334210502Ssyrinx		break;
1335210502Ssyrinx	case LEAF_wlanScanResultBeaconInterval:
1336210502Ssyrinx		val->v.integer = sr->bintval;
1337210502Ssyrinx		break;
1338210502Ssyrinx	case LEAF_wlanScanResultCapabilities:
1339210502Ssyrinx		return (bits_get(val, &sr->capinfo, sizeof(sr->capinfo)));
1340210502Ssyrinx	default:
1341210502Ssyrinx		abort();
1342210502Ssyrinx	}
1343210502Ssyrinx
1344210502Ssyrinx	return (SNMP_ERR_NOERROR);
1345210502Ssyrinx}
1346210502Ssyrinx
1347210502Ssyrinxint
1348210502Ssyrinxop_wlan_iface_stats(struct snmp_context *ctx __unused, struct snmp_value *val,
1349210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1350210502Ssyrinx{
1351210502Ssyrinx	struct wlan_iface *wif;
1352210502Ssyrinx
1353210502Ssyrinx	wlan_update_interface_list();
1354210502Ssyrinx
1355210502Ssyrinx	switch (op) {
1356210502Ssyrinx	case SNMP_OP_GET:
1357210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1358210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1359210502Ssyrinx		break;
1360210502Ssyrinx	case SNMP_OP_GETNEXT:
1361210502Ssyrinx		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
1362210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1363210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
1364210502Ssyrinx		break;
1365210502Ssyrinx	case SNMP_OP_SET:
1366210502Ssyrinx		/* XXX: LEAF_wlanStatsReset */
1367210502Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
1368210502Ssyrinx	case SNMP_OP_COMMIT:
1369210502Ssyrinx		/* FALLTHROUGH */
1370210502Ssyrinx	case SNMP_OP_ROLLBACK:
1371210502Ssyrinx		/* FALLTHROUGH */
1372210502Ssyrinx	default:
1373210502Ssyrinx		abort();
1374210502Ssyrinx	}
1375210502Ssyrinx
1376210502Ssyrinx	if (wlan_get_stats(wif) < 0)
1377210502Ssyrinx		return (SNMP_ERR_GENERR);
1378210502Ssyrinx
1379210502Ssyrinx	switch (val->var.subs[sub - 1]) {
1380210502Ssyrinx	case LEAF_wlanStatsRxBadVersion:
1381210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_badversion;
1382210502Ssyrinx		break;
1383210502Ssyrinx	case LEAF_wlanStatsRxTooShort:
1384210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_tooshort;
1385210502Ssyrinx		break;
1386210502Ssyrinx	case LEAF_wlanStatsRxWrongBssid:
1387210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_wrongbss;
1388210502Ssyrinx		break;
1389210502Ssyrinx	case LEAF_wlanStatsRxDiscardedDups:
1390210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_dup;
1391210502Ssyrinx		break;
1392210502Ssyrinx	case LEAF_wlanStatsRxWrongDir:
1393210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_wrongdir;
1394210502Ssyrinx		break;
1395210502Ssyrinx	case LEAF_wlanStatsRxDiscardMcastEcho:
1396210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_mcastecho;
1397210502Ssyrinx		break;
1398210502Ssyrinx	case LEAF_wlanStatsRxDiscardNoAssoc:
1399210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_notassoc;
1400210502Ssyrinx		break;
1401210502Ssyrinx	case LEAF_wlanStatsRxWepNoPrivacy:
1402210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_noprivacy;
1403210502Ssyrinx		break;
1404210502Ssyrinx	case LEAF_wlanStatsRxWepUnencrypted:
1405210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_unencrypted;
1406210502Ssyrinx		break;
1407210502Ssyrinx	case LEAF_wlanStatsRxWepFailed:
1408210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_wepfail;
1409210502Ssyrinx		break;
1410210502Ssyrinx	case LEAF_wlanStatsRxDecapsulationFailed:
1411210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_decap;
1412210502Ssyrinx		break;
1413210502Ssyrinx	case LEAF_wlanStatsRxDiscardMgmt:
1414210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_mgtdiscard;
1415210502Ssyrinx		break;
1416210502Ssyrinx	case LEAF_wlanStatsRxControl:
1417210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_ctl;
1418210502Ssyrinx		break;
1419210502Ssyrinx	case LEAF_wlanStatsRxBeacon:
1420210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_beacon;
1421210502Ssyrinx		break;
1422210502Ssyrinx	case LEAF_wlanStatsRxRateSetTooBig:
1423210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_rstoobig;
1424210502Ssyrinx		break;
1425210502Ssyrinx	case LEAF_wlanStatsRxElemMissing:
1426210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_elem_missing;
1427210502Ssyrinx		break;
1428210502Ssyrinx	case LEAF_wlanStatsRxElemTooBig:
1429210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_elem_toobig;
1430210502Ssyrinx		break;
1431210502Ssyrinx	case LEAF_wlanStatsRxElemTooSmall:
1432210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_elem_toosmall;
1433210502Ssyrinx		break;
1434210502Ssyrinx	case LEAF_wlanStatsRxElemUnknown:
1435210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_elem_unknown;
1436210502Ssyrinx		break;
1437210502Ssyrinx	case LEAF_wlanStatsRxChannelMismatch:
1438210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_chanmismatch;
1439210502Ssyrinx		break;
1440210502Ssyrinx	case LEAF_wlanStatsRxDropped:
1441210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_nodealloc;
1442210502Ssyrinx		break;
1443210502Ssyrinx	case LEAF_wlanStatsRxSsidMismatch:
1444210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_ssidmismatch;
1445210502Ssyrinx		break;
1446210502Ssyrinx	case LEAF_wlanStatsRxAuthNotSupported:
1447210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_auth_unsupported;
1448210502Ssyrinx		break;
1449210502Ssyrinx	case LEAF_wlanStatsRxAuthFailed:
1450210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_auth_fail;
1451210502Ssyrinx		break;
1452210502Ssyrinx	case LEAF_wlanStatsRxAuthCM:
1453210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_auth_countermeasures;
1454210502Ssyrinx		break;
1455210502Ssyrinx	case LEAF_wlanStatsRxAssocWrongBssid:
1456210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_assoc_bss;
1457210502Ssyrinx		break;
1458210502Ssyrinx	case LEAF_wlanStatsRxAssocNoAuth:
1459210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_assoc_notauth;
1460210502Ssyrinx		break;
1461210502Ssyrinx	case LEAF_wlanStatsRxAssocCapMismatch:
1462210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_assoc_capmismatch;
1463210502Ssyrinx		break;
1464210502Ssyrinx	case LEAF_wlanStatsRxAssocNoRateMatch:
1465210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_assoc_norate;
1466210502Ssyrinx		break;
1467210502Ssyrinx	case LEAF_wlanStatsRxBadWpaIE:
1468210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_assoc_badwpaie;
1469210502Ssyrinx		break;
1470210502Ssyrinx	case LEAF_wlanStatsRxDeauthenticate:
1471210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_deauth;
1472210502Ssyrinx		break;
1473210502Ssyrinx	case LEAF_wlanStatsRxDisassociate:
1474210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_disassoc;
1475210502Ssyrinx		break;
1476210502Ssyrinx	case LEAF_wlanStatsRxUnknownSubtype:
1477210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_badsubtype;
1478210502Ssyrinx		break;
1479210502Ssyrinx	case LEAF_wlanStatsRxFailedNoBuf:
1480210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_nobuf;
1481210502Ssyrinx		break;
1482210502Ssyrinx	case LEAF_wlanStatsRxBadAuthRequest:
1483210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_bad_auth;
1484210502Ssyrinx		break;
1485210502Ssyrinx	case LEAF_wlanStatsRxUnAuthorized:
1486210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_unauth;
1487210502Ssyrinx		break;
1488210502Ssyrinx	case LEAF_wlanStatsRxBadKeyId:
1489210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_badkeyid;
1490210502Ssyrinx		break;
1491210502Ssyrinx	case LEAF_wlanStatsRxCCMPSeqViolation:
1492210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_ccmpreplay;
1493210502Ssyrinx		break;
1494210502Ssyrinx	case LEAF_wlanStatsRxCCMPBadFormat:
1495210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_ccmpformat;
1496210502Ssyrinx		break;
1497210502Ssyrinx	case LEAF_wlanStatsRxCCMPFailedMIC:
1498210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_ccmpmic;
1499210502Ssyrinx		break;
1500210502Ssyrinx	case LEAF_wlanStatsRxTKIPSeqViolation:
1501210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_tkipreplay;
1502210502Ssyrinx		break;
1503210502Ssyrinx	case LEAF_wlanStatsRxTKIPBadFormat:
1504210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_tkipformat;
1505210502Ssyrinx		break;
1506210502Ssyrinx	case LEAF_wlanStatsRxTKIPFailedMIC:
1507210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_tkipmic;
1508210502Ssyrinx		break;
1509210502Ssyrinx	case LEAF_wlanStatsRxTKIPFailedICV:
1510210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_tkipicv;
1511210502Ssyrinx		break;
1512210502Ssyrinx	case LEAF_wlanStatsRxDiscardACL:
1513210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_acl;
1514210502Ssyrinx		break;
1515210502Ssyrinx	case LEAF_wlanStatsTxFailedNoBuf:
1516210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_nobuf;
1517210502Ssyrinx		break;
1518210502Ssyrinx	case LEAF_wlanStatsTxFailedNoNode:
1519210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_nonode;
1520210502Ssyrinx		break;
1521210502Ssyrinx	case LEAF_wlanStatsTxUnknownMgmt:
1522210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_unknownmgt;
1523210502Ssyrinx		break;
1524210502Ssyrinx	case LEAF_wlanStatsTxBadCipher:
1525210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_badcipher;
1526210502Ssyrinx		break;
1527210502Ssyrinx	case LEAF_wlanStatsTxNoDefKey:
1528210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_nodefkey;
1529210502Ssyrinx		break;
1530210502Ssyrinx	case LEAF_wlanStatsTxFragmented:
1531210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_fragframes;
1532210502Ssyrinx		break;
1533210502Ssyrinx	case LEAF_wlanStatsTxFragmentsCreated:
1534210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_frags;
1535210502Ssyrinx		break;
1536210502Ssyrinx	case LEAF_wlanStatsActiveScans:
1537210502Ssyrinx		val->v.uint32 = wif->stats.is_scan_active;
1538210502Ssyrinx		break;
1539210502Ssyrinx	case LEAF_wlanStatsPassiveScans:
1540210502Ssyrinx		val->v.uint32 = wif->stats.is_scan_passive;
1541210502Ssyrinx		break;
1542210502Ssyrinx	case LEAF_wlanStatsTimeoutInactivity:
1543210502Ssyrinx		val->v.uint32 = wif->stats.is_node_timeout;
1544210502Ssyrinx		break;
1545210502Ssyrinx	case LEAF_wlanStatsCryptoNoMem:
1546210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_nomem;
1547210502Ssyrinx		break;
1548210502Ssyrinx	case LEAF_wlanStatsSwCryptoTKIP:
1549210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_tkip;
1550210502Ssyrinx		break;
1551210502Ssyrinx	case LEAF_wlanStatsSwCryptoTKIPEnMIC:
1552210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_tkipenmic;
1553210502Ssyrinx		break;
1554210502Ssyrinx	case LEAF_wlanStatsSwCryptoTKIPDeMIC:
1555210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_tkipdemic;
1556210502Ssyrinx		break;
1557210502Ssyrinx	case LEAF_wlanStatsCryptoTKIPCM:
1558210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_tkipcm;
1559210502Ssyrinx		break;
1560210502Ssyrinx	case LEAF_wlanStatsSwCryptoCCMP:
1561210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_ccmp;
1562210502Ssyrinx		break;
1563210502Ssyrinx	case LEAF_wlanStatsSwCryptoWEP:
1564210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_wep;
1565210502Ssyrinx		break;
1566210502Ssyrinx	case LEAF_wlanStatsCryptoCipherKeyRejected:
1567210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_setkey_cipher;
1568210502Ssyrinx		break;
1569210502Ssyrinx	case LEAF_wlanStatsCryptoNoKey:
1570210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_setkey_nokey;
1571210502Ssyrinx		break;
1572210502Ssyrinx	case LEAF_wlanStatsCryptoDeleteKeyFailed:
1573210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_delkey;
1574210502Ssyrinx		break;
1575210502Ssyrinx	case LEAF_wlanStatsCryptoUnknownCipher:
1576210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_badcipher;
1577210502Ssyrinx		break;
1578210502Ssyrinx	case LEAF_wlanStatsCryptoAttachFailed:
1579210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_attachfail;
1580210502Ssyrinx		break;
1581210502Ssyrinx	case LEAF_wlanStatsCryptoKeyFailed:
1582210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_keyfail;
1583210502Ssyrinx		break;
1584210502Ssyrinx	case LEAF_wlanStatsCryptoEnMICFailed:
1585210502Ssyrinx		val->v.uint32 = wif->stats.is_crypto_enmicfail;
1586210502Ssyrinx		break;
1587210502Ssyrinx	case LEAF_wlanStatsIBSSCapMismatch:
1588210502Ssyrinx		val->v.uint32 = wif->stats.is_ibss_capmismatch;
1589210502Ssyrinx		break;
1590210502Ssyrinx	case LEAF_wlanStatsUnassocStaPSPoll:
1591210502Ssyrinx		val->v.uint32 = wif->stats.is_ps_unassoc;
1592210502Ssyrinx		break;
1593210502Ssyrinx	case LEAF_wlanStatsBadAidPSPoll:
1594210502Ssyrinx		val->v.uint32 = wif->stats.is_ps_badaid;
1595210502Ssyrinx		break;
1596210502Ssyrinx	case LEAF_wlanStatsEmptyPSPoll:
1597210502Ssyrinx		val->v.uint32 = wif->stats.is_ps_qempty;
1598210502Ssyrinx		break;
1599210502Ssyrinx	case LEAF_wlanStatsRxFFBadHdr:
1600210502Ssyrinx		val->v.uint32 = wif->stats.is_ff_badhdr;
1601210502Ssyrinx		break;
1602210502Ssyrinx	case LEAF_wlanStatsRxFFTooShort:
1603210502Ssyrinx		val->v.uint32 = wif->stats.is_ff_tooshort;
1604210502Ssyrinx		break;
1605210502Ssyrinx	case LEAF_wlanStatsRxFFSplitError:
1606210502Ssyrinx		val->v.uint32 = wif->stats.is_ff_split;
1607210502Ssyrinx		break;
1608210502Ssyrinx	case LEAF_wlanStatsRxFFDecap:
1609210502Ssyrinx		val->v.uint32 = wif->stats.is_ff_decap;
1610210502Ssyrinx		break;
1611210502Ssyrinx	case LEAF_wlanStatsTxFFEncap:
1612210502Ssyrinx		val->v.uint32 = wif->stats.is_ff_encap;
1613210502Ssyrinx		break;
1614210502Ssyrinx	case LEAF_wlanStatsRxBadBintval:
1615210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_badbintval;
1616210502Ssyrinx		break;
1617210502Ssyrinx	case LEAF_wlanStatsRxDemicFailed:
1618210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_demicfail;
1619210502Ssyrinx		break;
1620210502Ssyrinx	case LEAF_wlanStatsRxDefragFailed:
1621210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_defrag;
1622210502Ssyrinx		break;
1623210502Ssyrinx	case LEAF_wlanStatsRxMgmt:
1624210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_mgmt;
1625210502Ssyrinx		break;
1626210502Ssyrinx	case LEAF_wlanStatsRxActionMgmt:
1627210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_action;
1628210502Ssyrinx		break;
1629210502Ssyrinx	case LEAF_wlanStatsRxAMSDUTooShort:
1630210502Ssyrinx		val->v.uint32 = wif->stats.is_amsdu_tooshort;
1631210502Ssyrinx		break;
1632210502Ssyrinx	case LEAF_wlanStatsRxAMSDUSplitError:
1633210502Ssyrinx		val->v.uint32 = wif->stats.is_amsdu_split;
1634210502Ssyrinx		break;
1635210502Ssyrinx	case LEAF_wlanStatsRxAMSDUDecap:
1636210502Ssyrinx		val->v.uint32 = wif->stats.is_amsdu_decap;
1637210502Ssyrinx		break;
1638210502Ssyrinx	case LEAF_wlanStatsTxAMSDUEncap:
1639210502Ssyrinx		val->v.uint32 = wif->stats.is_amsdu_encap;
1640210502Ssyrinx		break;
1641210502Ssyrinx	case LEAF_wlanStatsAMPDUBadBAR:
1642210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_bar_bad;
1643210502Ssyrinx		break;
1644210502Ssyrinx	case LEAF_wlanStatsAMPDUOowBar:
1645210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_bar_oow;
1646210502Ssyrinx		break;
1647210502Ssyrinx	case LEAF_wlanStatsAMPDUMovedBAR:
1648210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_bar_move;
1649210502Ssyrinx		break;
1650210502Ssyrinx	case LEAF_wlanStatsAMPDURxBAR:
1651210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_bar_rx;
1652210502Ssyrinx		break;
1653210502Ssyrinx	case LEAF_wlanStatsAMPDURxOor:
1654210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_rx_oor;
1655210502Ssyrinx		break;
1656210502Ssyrinx	case LEAF_wlanStatsAMPDURxCopied:
1657210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_rx_copy;
1658210502Ssyrinx		break;
1659210502Ssyrinx	case LEAF_wlanStatsAMPDURxDropped:
1660210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_rx_drop;
1661210502Ssyrinx		break;
1662210502Ssyrinx	case LEAF_wlanStatsTxDiscardBadState:
1663210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_badstate;
1664210502Ssyrinx		break;
1665210502Ssyrinx	case LEAF_wlanStatsTxFailedNoAssoc:
1666210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_notassoc;
1667210502Ssyrinx		break;
1668210502Ssyrinx	case LEAF_wlanStatsTxClassifyFailed:
1669210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_classify;
1670210502Ssyrinx		break;
1671210502Ssyrinx	case LEAF_wlanStatsDwdsMcastDiscard:
1672210502Ssyrinx		val->v.uint32 = wif->stats.is_dwds_mcast;
1673210502Ssyrinx		break;
1674210502Ssyrinx	case LEAF_wlanStatsHTAssocRejectNoHT:
1675210502Ssyrinx		val->v.uint32 = wif->stats.is_ht_assoc_nohtcap;
1676210502Ssyrinx		break;
1677210502Ssyrinx	case LEAF_wlanStatsHTAssocDowngrade:
1678210502Ssyrinx		val->v.uint32 = wif->stats.is_ht_assoc_downgrade;
1679210502Ssyrinx		break;
1680210502Ssyrinx	case LEAF_wlanStatsHTAssocRateMismatch:
1681210502Ssyrinx		val->v.uint32 = wif->stats.is_ht_assoc_norate;
1682210502Ssyrinx		break;
1683210502Ssyrinx	case LEAF_wlanStatsAMPDURxAge:
1684210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_rx_age;
1685210502Ssyrinx		break;
1686210502Ssyrinx	case LEAF_wlanStatsAMPDUMoved:
1687210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_rx_move;
1688210502Ssyrinx		break;
1689210502Ssyrinx	case LEAF_wlanStatsADDBADisabledReject:
1690210502Ssyrinx		val->v.uint32 = wif->stats.is_addba_reject;
1691210502Ssyrinx		break;
1692210502Ssyrinx	case LEAF_wlanStatsADDBANoRequest:
1693210502Ssyrinx		val->v.uint32 = wif->stats.is_addba_norequest;
1694210502Ssyrinx		break;
1695210502Ssyrinx	case LEAF_wlanStatsADDBABadToken:
1696210502Ssyrinx		val->v.uint32 = wif->stats.is_addba_badtoken;
1697210502Ssyrinx		break;
1698210502Ssyrinx	case LEAF_wlanStatsADDBABadPolicy:
1699210502Ssyrinx		val->v.uint32 = wif->stats.is_addba_badpolicy;
1700210502Ssyrinx		break;
1701210502Ssyrinx	case LEAF_wlanStatsAMPDUStopped:
1702210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_stop;
1703210502Ssyrinx		break;
1704210502Ssyrinx	case LEAF_wlanStatsAMPDUStopFailed:
1705210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_stop_failed;
1706210502Ssyrinx		break;
1707210502Ssyrinx	case LEAF_wlanStatsAMPDURxReorder:
1708210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_rx_reorder;
1709210502Ssyrinx		break;
1710210502Ssyrinx	case LEAF_wlanStatsScansBackground:
1711210502Ssyrinx		val->v.uint32 = wif->stats.is_scan_bg;
1712210502Ssyrinx		break;
1713210502Ssyrinx	case LEAF_wlanLastDeauthReason:
1714210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_deauth_code;
1715210502Ssyrinx		break;
1716210502Ssyrinx	case LEAF_wlanLastDissasocReason:
1717210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_disassoc_code;
1718210502Ssyrinx		break;
1719210502Ssyrinx	case LEAF_wlanLastAuthFailReason:
1720210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_authfail_code;
1721210502Ssyrinx		break;
1722210502Ssyrinx	case LEAF_wlanStatsBeaconMissedEvents:
1723210502Ssyrinx		val->v.uint32 = wif->stats.is_beacon_miss;
1724210502Ssyrinx		break;
1725210502Ssyrinx	case LEAF_wlanStatsRxDiscardBadStates:
1726210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_badstate;
1727210502Ssyrinx		break;
1728210502Ssyrinx	case LEAF_wlanStatsFFFlushed:
1729210502Ssyrinx		val->v.uint32 = wif->stats.is_ff_flush;
1730210502Ssyrinx		break;
1731210502Ssyrinx	case LEAF_wlanStatsTxControlFrames:
1732210502Ssyrinx		val->v.uint32 = wif->stats.is_tx_ctl;
1733210502Ssyrinx		break;
1734210502Ssyrinx	case LEAF_wlanStatsAMPDURexmt:
1735210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_rexmt;
1736210502Ssyrinx		break;
1737210502Ssyrinx	case LEAF_wlanStatsAMPDURexmtFailed:
1738210502Ssyrinx		val->v.uint32 = wif->stats.is_ampdu_rexmt_fail;
1739210502Ssyrinx		break;
1740210502Ssyrinx	case LEAF_wlanStatsReset:
1741210502Ssyrinx		val->v.uint32 = wlanStatsReset_no_op;
1742210502Ssyrinx		break;
1743210502Ssyrinx	default:
1744210502Ssyrinx		abort();
1745210502Ssyrinx	}
1746210502Ssyrinx
1747210502Ssyrinx	return (SNMP_ERR_NOERROR);
1748210502Ssyrinx}
1749210502Ssyrinx
1750210502Ssyrinxint
1751210502Ssyrinxop_wlan_wep_iface(struct snmp_context *ctx, struct snmp_value *val,
1752210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1753210502Ssyrinx{
1754210502Ssyrinx	struct wlan_iface *wif;
1755210502Ssyrinx
1756210502Ssyrinx	wlan_update_interface_list();
1757210502Ssyrinx
1758210502Ssyrinx	switch (op) {
1759210502Ssyrinx	case SNMP_OP_GET:
1760210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||
1761210502Ssyrinx		    !wif->wepsupported)
1762210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1763210502Ssyrinx		break;
1764210502Ssyrinx
1765210502Ssyrinx	case SNMP_OP_GETNEXT:
1766210502Ssyrinx		/* XXX: filter wif->wepsupported */
1767210502Ssyrinx		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
1768210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1769210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
1770210502Ssyrinx		break;
1771210502Ssyrinx
1772210502Ssyrinx	case SNMP_OP_SET:
1773210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||
1774210502Ssyrinx		    !wif->wepsupported)
1775210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1776210502Ssyrinx		switch (val->var.subs[sub - 1]) {
1777210502Ssyrinx		case LEAF_wlanWepMode:
1778210502Ssyrinx			if (val->v.integer < wlanWepMode_off ||
1779210502Ssyrinx			    val->v.integer > wlanWepMode_mixed)
1780210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
1781210502Ssyrinx			ctx->scratch->int1 = wif->wepmode;
1782210502Ssyrinx			wif->wepmode = val->v.integer;
1783210502Ssyrinx			if (wlan_set_wepmode(wif) < 0) {
1784210502Ssyrinx				wif->wepmode = ctx->scratch->int1;
1785210502Ssyrinx				return (SNMP_ERR_GENERR);
1786210502Ssyrinx			}
1787210502Ssyrinx			break;
1788210502Ssyrinx		case LEAF_wlanWepDefTxKey:
1789210502Ssyrinx			if (val->v.integer < 0 ||
1790210502Ssyrinx			    val->v.integer > IEEE80211_WEP_NKID)
1791210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
1792210502Ssyrinx			ctx->scratch->int1 = wif->weptxkey;
1793210502Ssyrinx			wif->weptxkey = val->v.integer;
1794210502Ssyrinx			if (wlan_set_weptxkey(wif) < 0) {
1795210502Ssyrinx				wif->weptxkey = ctx->scratch->int1;
1796210502Ssyrinx				return (SNMP_ERR_GENERR);
1797210502Ssyrinx			}
1798210502Ssyrinx			break;
1799210502Ssyrinx		default:
1800210502Ssyrinx			abort();
1801210502Ssyrinx		}
1802210502Ssyrinx		return (SNMP_ERR_NOERROR);
1803210502Ssyrinx
1804210502Ssyrinx	case SNMP_OP_COMMIT:
1805210502Ssyrinx		return (SNMP_ERR_NOERROR);
1806210502Ssyrinx
1807210502Ssyrinx	case SNMP_OP_ROLLBACK:
1808210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1809210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1810210502Ssyrinx		switch (val->var.subs[sub - 1]) {
1811210502Ssyrinx		case LEAF_wlanWepMode:
1812210502Ssyrinx			wif->wepmode = ctx->scratch->int1;
1813210502Ssyrinx			if (wlan_set_wepmode(wif) < 0)
1814210502Ssyrinx				return (SNMP_ERR_GENERR);
1815210502Ssyrinx			break;
1816210502Ssyrinx		case LEAF_wlanWepDefTxKey:
1817210502Ssyrinx			wif->weptxkey = ctx->scratch->int1;
1818210502Ssyrinx			if (wlan_set_weptxkey(wif) < 0)
1819210502Ssyrinx				return (SNMP_ERR_GENERR);
1820210502Ssyrinx			break;
1821210502Ssyrinx		default:
1822210502Ssyrinx			abort();
1823210502Ssyrinx		}
1824210502Ssyrinx		return (SNMP_ERR_NOERROR);
1825210502Ssyrinx
1826210502Ssyrinx	default:
1827210502Ssyrinx		abort();
1828210502Ssyrinx	}
1829210502Ssyrinx
1830210502Ssyrinx	switch (val->var.subs[sub - 1]) {
1831210502Ssyrinx	case LEAF_wlanWepMode:
1832210502Ssyrinx		if (wlan_get_wepmode(wif) < 0)
1833210502Ssyrinx			return (SNMP_ERR_GENERR);
1834210502Ssyrinx		val->v.integer = wif->wepmode;
1835210502Ssyrinx		break;
1836210502Ssyrinx	case LEAF_wlanWepDefTxKey:
1837210502Ssyrinx		if (wlan_get_weptxkey(wif) < 0)
1838210502Ssyrinx			return (SNMP_ERR_GENERR);
1839210502Ssyrinx		val->v.integer = wif->weptxkey;
1840210502Ssyrinx		break;
1841210502Ssyrinx	default:
1842210502Ssyrinx		abort();
1843210502Ssyrinx	}
1844210502Ssyrinx
1845210502Ssyrinx	return (SNMP_ERR_NOERROR);
1846210502Ssyrinx}
1847210502Ssyrinx
1848210502Ssyrinxint
1849210502Ssyrinxop_wlan_wep_key(struct snmp_context *ctx __unused,
1850210502Ssyrinx    struct snmp_value *val __unused, uint32_t sub __unused,
1851210502Ssyrinx    uint32_t iidx __unused, enum snmp_op op __unused)
1852210502Ssyrinx{
1853210502Ssyrinx	return (SNMP_ERR_NOSUCHNAME);
1854210502Ssyrinx}
1855210502Ssyrinx
1856210502Ssyrinxint
1857210502Ssyrinxop_wlan_mac_access_control(struct snmp_context *ctx, struct snmp_value *val,
1858210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1859210502Ssyrinx{
1860210502Ssyrinx	struct wlan_iface *wif;
1861210502Ssyrinx
1862210502Ssyrinx	wlan_update_interface_list();
1863210502Ssyrinx
1864210502Ssyrinx	switch (op) {
1865210502Ssyrinx	case SNMP_OP_GET:
1866210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||
1867210502Ssyrinx		    !wif->macsupported)
1868210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1869210502Ssyrinx		break;
1870210502Ssyrinx
1871210502Ssyrinx	case SNMP_OP_GETNEXT:
1872210502Ssyrinx		/* XXX: filter wif->macsupported */
1873210502Ssyrinx		if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)
1874210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1875210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
1876210502Ssyrinx		break;
1877210502Ssyrinx
1878210502Ssyrinx	case SNMP_OP_SET:
1879210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||
1880210502Ssyrinx		    !wif->macsupported)
1881210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1882210502Ssyrinx		switch (val->var.subs[sub - 1]) {
1883210502Ssyrinx		case LEAF_wlanMACAccessControlPolicy:
1884210502Ssyrinx			ctx->scratch->int1 = wif->mac_policy;
1885210502Ssyrinx			wif->mac_policy = val->v.integer;
1886210502Ssyrinx			break;
1887210502Ssyrinx		case LEAF_wlanMACAccessControlNacl:
1888210502Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
1889210502Ssyrinx		case LEAF_wlanMACAccessControlFlush:
1890210502Ssyrinx			break;
1891210502Ssyrinx		default:
1892210502Ssyrinx			abort();
1893210502Ssyrinx		}
1894210502Ssyrinx		return (SNMP_ERR_NOERROR);
1895210502Ssyrinx
1896210502Ssyrinx	case SNMP_OP_COMMIT:
1897210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1898210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1899210502Ssyrinx		switch (val->var.subs[sub - 1]) {
1900210502Ssyrinx		case LEAF_wlanMACAccessControlPolicy:
1901210502Ssyrinx			if (wlan_set_mac_policy(wif) < 0) {
1902210502Ssyrinx				wif->mac_policy = ctx->scratch->int1;
1903210502Ssyrinx				return (SNMP_ERR_GENERR);
1904210502Ssyrinx			}
1905210502Ssyrinx			break;
1906210502Ssyrinx		case LEAF_wlanMACAccessControlFlush:
1907210502Ssyrinx			if (wlan_flush_mac_mac(wif) < 0)
1908210502Ssyrinx				return (SNMP_ERR_GENERR);
1909210502Ssyrinx			break;
1910210502Ssyrinx		default:
1911210502Ssyrinx			abort();
1912210502Ssyrinx		}
1913210502Ssyrinx		return (SNMP_ERR_NOERROR);
1914210502Ssyrinx
1915210502Ssyrinx	case SNMP_OP_ROLLBACK:
1916210502Ssyrinx		if ((wif = wlan_get_interface(&val->var, sub)) == NULL)
1917210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1918210502Ssyrinx		if (val->var.subs[sub - 1] == LEAF_wlanMACAccessControlPolicy)
1919210502Ssyrinx			wif->mac_policy = ctx->scratch->int1;
1920210502Ssyrinx		return (SNMP_ERR_NOERROR);
1921210502Ssyrinx
1922210502Ssyrinx	default:
1923210502Ssyrinx		abort();
1924210502Ssyrinx	}
1925210502Ssyrinx
1926210502Ssyrinx	if (wlan_get_mac_policy(wif) < 0)
1927210502Ssyrinx		return (SNMP_ERR_GENERR);
1928210502Ssyrinx
1929210502Ssyrinx	switch (val->var.subs[sub - 1]) {
1930210502Ssyrinx	case LEAF_wlanMACAccessControlPolicy:
1931210502Ssyrinx		val->v.integer = wif->mac_policy;
1932210502Ssyrinx		break;
1933210502Ssyrinx	case LEAF_wlanMACAccessControlNacl:
1934210502Ssyrinx		val->v.integer = wif->mac_nacls;
1935210502Ssyrinx		break;
1936210502Ssyrinx	case LEAF_wlanMACAccessControlFlush:
1937210502Ssyrinx		val->v.integer = wlanMACAccessControlFlush_no_op;
1938210502Ssyrinx		break;
1939210502Ssyrinx	default:
1940210502Ssyrinx		abort();
1941210502Ssyrinx	}
1942210502Ssyrinx
1943210502Ssyrinx	return (SNMP_ERR_NOERROR);
1944210502Ssyrinx}
1945210502Ssyrinx
1946210502Ssyrinxint
1947210502Ssyrinxop_wlan_mac_acl_mac(struct snmp_context *ctx, struct snmp_value *val,
1948210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
1949210502Ssyrinx{
1950210502Ssyrinx	struct wlan_iface *wif;
1951210502Ssyrinx	struct wlan_mac_mac *macl;
1952210502Ssyrinx
1953210502Ssyrinx	wlan_update_interface_list();
1954210502Ssyrinx	wlan_mac_update_aclmacs();
1955210502Ssyrinx
1956210502Ssyrinx	switch (op) {
1957210502Ssyrinx	case SNMP_OP_GET:
1958210502Ssyrinx		if ((macl = wlan_get_acl_mac(&val->var, sub, &wif)) == NULL)
1959210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1960210502Ssyrinx		break;
1961210502Ssyrinx
1962210502Ssyrinx	case SNMP_OP_GETNEXT:
1963210502Ssyrinx		if ((macl = wlan_get_next_acl_mac(&val->var, sub, &wif))
1964210502Ssyrinx		    == NULL)
1965210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1966210502Ssyrinx		wlan_append_mac_index(&val->var, sub, wif->wname, macl->mac);
1967210502Ssyrinx		break;
1968210502Ssyrinx
1969210502Ssyrinx	case SNMP_OP_SET:
1970210502Ssyrinx		switch (val->var.subs[sub - 1]) {
1971210502Ssyrinx		case LEAF_wlanMACAccessControlMAC:
1972210502Ssyrinx			return (SNMP_ERR_INCONS_NAME);
1973210502Ssyrinx		case LEAF_wlanMACAccessControlMACStatus:
1974210502Ssyrinx			return(wlan_acl_mac_set_status(ctx, val, sub));
1975210502Ssyrinx		default:
1976210502Ssyrinx			abort();
1977210502Ssyrinx		}
1978210502Ssyrinx
1979210502Ssyrinx	case SNMP_OP_COMMIT:
1980210502Ssyrinx		if ((macl = wlan_get_acl_mac(&val->var, sub, &wif)) == NULL)
1981210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1982210502Ssyrinx		if (val->v.integer == RowStatus_destroy &&
1983210502Ssyrinx		    wlan_mac_delete_mac(wif, macl) < 0)
1984210502Ssyrinx			return (SNMP_ERR_GENERR);
1985210502Ssyrinx		return (SNMP_ERR_NOERROR);
1986210502Ssyrinx
1987210502Ssyrinx	case SNMP_OP_ROLLBACK:
1988210502Ssyrinx		if ((macl = wlan_get_acl_mac(&val->var, sub, &wif)) == NULL)
1989210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
1990210502Ssyrinx		if (ctx->scratch->int1 == RowStatus_destroy &&
1991210502Ssyrinx		    wlan_mac_delete_mac(wif, macl) < 0)
1992210502Ssyrinx			return (SNMP_ERR_GENERR);
1993210502Ssyrinx		return (SNMP_ERR_NOERROR);
1994210502Ssyrinx
1995210502Ssyrinx	default:
1996210502Ssyrinx		abort();
1997210502Ssyrinx	}
1998210502Ssyrinx
1999210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2000210502Ssyrinx	case LEAF_wlanMACAccessControlMAC:
2001210502Ssyrinx		return (string_get(val, macl->mac, IEEE80211_ADDR_LEN));
2002210502Ssyrinx	case LEAF_wlanMACAccessControlMACStatus:
2003210502Ssyrinx		val->v.integer = macl->mac_status;
2004210502Ssyrinx		break;
2005210502Ssyrinx	default:
2006210502Ssyrinx		abort();
2007210502Ssyrinx	}
2008210502Ssyrinx
2009210502Ssyrinx	return (SNMP_ERR_NOERROR);
2010210502Ssyrinx}
2011210502Ssyrinx
2012210502Ssyrinxint
2013210502Ssyrinxop_wlan_mesh_config(struct snmp_context *ctx, struct snmp_value *val,
2014210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2015210502Ssyrinx{
2016210502Ssyrinx	int which;
2017210502Ssyrinx
2018210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2019210502Ssyrinx	case LEAF_wlanMeshMaxRetries:
2020210502Ssyrinx		which = WLAN_MESH_MAX_RETRIES;
2021210502Ssyrinx		break;
2022210502Ssyrinx	case LEAF_wlanMeshHoldingTimeout:
2023210502Ssyrinx		which = WLAN_MESH_HOLDING_TO;
2024210502Ssyrinx		break;
2025210502Ssyrinx	case LEAF_wlanMeshConfirmTimeout:
2026210502Ssyrinx		which = WLAN_MESH_CONFIRM_TO;
2027210502Ssyrinx		break;
2028210502Ssyrinx	case LEAF_wlanMeshRetryTimeout:
2029210502Ssyrinx		which = WLAN_MESH_RETRY_TO;
2030210502Ssyrinx		break;
2031210502Ssyrinx	default:
2032210502Ssyrinx		abort();
2033210502Ssyrinx	}
2034210502Ssyrinx
2035210502Ssyrinx	switch (op) {
2036210502Ssyrinx	case SNMP_OP_GET:
2037210502Ssyrinx		if (wlan_do_sysctl(&wlan_config, which, 0) < 0)
2038210502Ssyrinx			return (SNMP_ERR_GENERR);
2039210502Ssyrinx		break;
2040210502Ssyrinx
2041210502Ssyrinx	case SNMP_OP_GETNEXT:
2042210502Ssyrinx		abort();
2043210502Ssyrinx
2044210502Ssyrinx	case SNMP_OP_SET:
2045210502Ssyrinx		switch (val->var.subs[sub - 1]) {
2046210502Ssyrinx		case LEAF_wlanMeshRetryTimeout :
2047210502Ssyrinx			ctx->scratch->int1 = wlan_config.mesh_retryto;
2048210502Ssyrinx			wlan_config.mesh_retryto = val->v.integer;
2049210502Ssyrinx			break;
2050210502Ssyrinx		case LEAF_wlanMeshHoldingTimeout:
2051210502Ssyrinx			ctx->scratch->int1 = wlan_config.mesh_holdingto;
2052210502Ssyrinx			wlan_config.mesh_holdingto = val->v.integer;
2053210502Ssyrinx			break;
2054210502Ssyrinx		case LEAF_wlanMeshConfirmTimeout:
2055210502Ssyrinx			ctx->scratch->int1 = wlan_config.mesh_confirmto;
2056210502Ssyrinx			wlan_config.mesh_confirmto = val->v.integer;
2057210502Ssyrinx			break;
2058210502Ssyrinx		case LEAF_wlanMeshMaxRetries:
2059210502Ssyrinx			ctx->scratch->int1 = wlan_config.mesh_maxretries;
2060210502Ssyrinx			wlan_config.mesh_maxretries = val->v.integer;
2061210502Ssyrinx			break;
2062210502Ssyrinx		}
2063210502Ssyrinx		if (wlan_do_sysctl(&wlan_config, which, 1) < 0)
2064210502Ssyrinx			return (SNMP_ERR_GENERR);
2065210502Ssyrinx		return (SNMP_ERR_NOERROR);
2066210502Ssyrinx
2067210502Ssyrinx	case SNMP_OP_COMMIT:
2068210502Ssyrinx		return (SNMP_ERR_NOERROR);
2069210502Ssyrinx
2070210502Ssyrinx	case SNMP_OP_ROLLBACK:
2071210502Ssyrinx		switch (val->var.subs[sub - 1]) {
2072210502Ssyrinx		case LEAF_wlanMeshRetryTimeout:
2073210502Ssyrinx			wlan_config.mesh_retryto = ctx->scratch->int1;
2074210502Ssyrinx			break;
2075210502Ssyrinx		case LEAF_wlanMeshConfirmTimeout:
2076210502Ssyrinx			wlan_config.mesh_confirmto = ctx->scratch->int1;
2077210502Ssyrinx			break;
2078210502Ssyrinx		case LEAF_wlanMeshHoldingTimeout:
2079210502Ssyrinx			wlan_config.mesh_holdingto= ctx->scratch->int1;
2080210502Ssyrinx			break;
2081210502Ssyrinx		case LEAF_wlanMeshMaxRetries:
2082210502Ssyrinx			wlan_config.mesh_maxretries = ctx->scratch->int1;
2083210502Ssyrinx			break;
2084210502Ssyrinx		}
2085210502Ssyrinx		if (wlan_do_sysctl(&wlan_config, which, 1) < 0)
2086210502Ssyrinx			return (SNMP_ERR_GENERR);
2087210502Ssyrinx		return (SNMP_ERR_NOERROR);
2088210502Ssyrinx
2089210502Ssyrinx	default:
2090210502Ssyrinx		abort();
2091210502Ssyrinx	}
2092210502Ssyrinx
2093210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2094210502Ssyrinx	case LEAF_wlanMeshRetryTimeout:
2095210502Ssyrinx		val->v.integer = wlan_config.mesh_retryto;
2096210502Ssyrinx		break;
2097210502Ssyrinx	case LEAF_wlanMeshHoldingTimeout:
2098210502Ssyrinx		val->v.integer = wlan_config.mesh_holdingto;
2099210502Ssyrinx		break;
2100210502Ssyrinx	case LEAF_wlanMeshConfirmTimeout:
2101210502Ssyrinx		val->v.integer = wlan_config.mesh_confirmto;
2102210502Ssyrinx		break;
2103210502Ssyrinx	case LEAF_wlanMeshMaxRetries:
2104210502Ssyrinx		val->v.integer = wlan_config.mesh_maxretries;
2105210502Ssyrinx		break;
2106210502Ssyrinx	}
2107210502Ssyrinx
2108210502Ssyrinx	return (SNMP_ERR_NOERROR);
2109210502Ssyrinx}
2110210502Ssyrinx
2111210502Ssyrinxint
2112210502Ssyrinxop_wlan_mesh_iface(struct snmp_context *ctx, struct snmp_value *val,
2113210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2114210502Ssyrinx{
2115210502Ssyrinx	int rc;
2116210502Ssyrinx	struct wlan_iface *wif;
2117210502Ssyrinx
2118210502Ssyrinx	wlan_update_interface_list();
2119210502Ssyrinx
2120210502Ssyrinx	switch (op) {
2121210502Ssyrinx	case SNMP_OP_GET:
2122210502Ssyrinx		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2123210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2124210502Ssyrinx		break;
2125210502Ssyrinx
2126210502Ssyrinx	case SNMP_OP_GETNEXT:
2127210502Ssyrinx		if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)
2128210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2129210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
2130210502Ssyrinx		break;
2131210502Ssyrinx
2132210502Ssyrinx	case SNMP_OP_SET:
2133210502Ssyrinx		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2134210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2135210502Ssyrinx		switch (val->var.subs[sub - 1]) {
2136210502Ssyrinx		case LEAF_wlanMeshId:
2137210502Ssyrinx			if (val->v.octetstring.len > IEEE80211_NWID_LEN)
2138210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
2139210502Ssyrinx			ctx->scratch->ptr1 = malloc(val->v.octetstring.len + 1);
2140210502Ssyrinx			if (ctx->scratch->ptr1 == NULL)
2141210502Ssyrinx				return (SNMP_ERR_GENERR);
2142210502Ssyrinx			strlcpy(ctx->scratch->ptr1, wif->desired_ssid,
2143210502Ssyrinx			    val->v.octetstring.len + 1);
2144210502Ssyrinx			ctx->scratch->int1 = strlen(wif->desired_ssid);
2145210502Ssyrinx			memcpy(wif->desired_ssid, val->v.octetstring.octets,
2146210502Ssyrinx			    val->v.octetstring.len);
2147210502Ssyrinx			wif->desired_ssid[val->v.octetstring.len] = '\0';
2148210502Ssyrinx			break;
2149210502Ssyrinx		case LEAF_wlanMeshTTL:
2150210502Ssyrinx			ctx->scratch->int1 = wif->mesh_ttl;
2151210502Ssyrinx			wif->mesh_ttl = val->v.integer;
2152210502Ssyrinx			break;
2153210502Ssyrinx		case LEAF_wlanMeshPeeringEnabled:
2154210502Ssyrinx			ctx->scratch->int1 = wif->mesh_peering;
2155210502Ssyrinx			wif->mesh_peering = val->v.integer;
2156210502Ssyrinx			break;
2157210502Ssyrinx		case LEAF_wlanMeshForwardingEnabled:
2158210502Ssyrinx			ctx->scratch->int1 = wif->mesh_forwarding;
2159210502Ssyrinx			wif->mesh_forwarding = val->v.integer;
2160210502Ssyrinx			break;
2161210502Ssyrinx		case LEAF_wlanMeshMetric:
2162210502Ssyrinx			ctx->scratch->int1 = wif->mesh_metric;
2163210502Ssyrinx			wif->mesh_metric = val->v.integer;
2164210502Ssyrinx			break;
2165210502Ssyrinx		case LEAF_wlanMeshPath:
2166210502Ssyrinx			ctx->scratch->int1 = wif->mesh_path;
2167210502Ssyrinx			wif->mesh_path = val->v.integer;
2168210502Ssyrinx			break;
2169210502Ssyrinx		case LEAF_wlanMeshRoutesFlush:
2170210502Ssyrinx			if (val->v.integer != wlanMeshRoutesFlush_flush)
2171210502Ssyrinx				return (SNMP_ERR_INCONS_VALUE);
2172210502Ssyrinx			return (SNMP_ERR_NOERROR);
2173210502Ssyrinx		default:
2174210502Ssyrinx			abort();
2175210502Ssyrinx		}
2176210502Ssyrinx		if (val->var.subs[sub - 1] == LEAF_wlanMeshId)
2177210502Ssyrinx			rc = wlan_config_set_dssid(wif,
2178210502Ssyrinx			    val->v.octetstring.octets, val->v.octetstring.len);
2179210502Ssyrinx		else
2180210502Ssyrinx			rc = wlan_mesh_config_set(wif, val->var.subs[sub - 1]);
2181210502Ssyrinx		if (rc < 0)
2182210502Ssyrinx			return (SNMP_ERR_GENERR);
2183210502Ssyrinx		return (SNMP_ERR_NOERROR);
2184210502Ssyrinx
2185210502Ssyrinx	case SNMP_OP_COMMIT:
2186210502Ssyrinx		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2187210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2188210502Ssyrinx		if (val->var.subs[sub - 1] == LEAF_wlanMeshRoutesFlush &&
2189210502Ssyrinx		    wlan_mesh_flush_routes(wif) < 0)
2190210502Ssyrinx			return (SNMP_ERR_GENERR);
2191210502Ssyrinx		if (val->var.subs[sub - 1] == LEAF_wlanMeshId)
2192210502Ssyrinx			free(ctx->scratch->ptr1);
2193210502Ssyrinx		return (SNMP_ERR_NOERROR);
2194210502Ssyrinx
2195210502Ssyrinx	case SNMP_OP_ROLLBACK:
2196210502Ssyrinx		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2197210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2198210502Ssyrinx		switch (val->var.subs[sub - 1]) {
2199210502Ssyrinx		case LEAF_wlanMeshId:
2200210502Ssyrinx			strlcpy(wif->desired_ssid, ctx->scratch->ptr1,
2201210502Ssyrinx			    IEEE80211_NWID_LEN);
2202210502Ssyrinx			free(ctx->scratch->ptr1);
2203210502Ssyrinx			break;
2204210502Ssyrinx		case LEAF_wlanMeshTTL:
2205210502Ssyrinx			wif->mesh_ttl = ctx->scratch->int1;
2206210502Ssyrinx			break;
2207210502Ssyrinx		case LEAF_wlanMeshPeeringEnabled:
2208210502Ssyrinx			wif->mesh_peering = ctx->scratch->int1;
2209210502Ssyrinx			break;
2210210502Ssyrinx		case LEAF_wlanMeshForwardingEnabled:
2211210502Ssyrinx			wif->mesh_forwarding = ctx->scratch->int1;
2212210502Ssyrinx			break;
2213210502Ssyrinx		case LEAF_wlanMeshMetric:
2214210502Ssyrinx			wif->mesh_metric = ctx->scratch->int1;
2215210502Ssyrinx			break;
2216210502Ssyrinx		case LEAF_wlanMeshPath:
2217210502Ssyrinx			wif->mesh_path = ctx->scratch->int1;
2218210502Ssyrinx			break;
2219210502Ssyrinx		case LEAF_wlanMeshRoutesFlush:
2220210502Ssyrinx			return (SNMP_ERR_NOERROR);
2221210502Ssyrinx		default:
2222210502Ssyrinx			abort();
2223210502Ssyrinx		}
2224210502Ssyrinx		if (val->var.subs[sub - 1] == LEAF_wlanMeshId)
2225210502Ssyrinx			rc = wlan_config_set_dssid(wif, wif->desired_ssid,
2226210502Ssyrinx			    strlen(wif->desired_ssid));
2227210502Ssyrinx		else
2228210502Ssyrinx			rc = wlan_mesh_config_set(wif, val->var.subs[sub - 1]);
2229210502Ssyrinx		if (rc < 0)
2230210502Ssyrinx			return (SNMP_ERR_GENERR);
2231210502Ssyrinx		return (SNMP_ERR_NOERROR);
2232210502Ssyrinx
2233210502Ssyrinx	default:
2234210502Ssyrinx		abort();
2235210502Ssyrinx	}
2236210502Ssyrinx
2237210502Ssyrinx	if (val->var.subs[sub - 1] == LEAF_wlanMeshId)
2238210502Ssyrinx		rc = wlan_config_get_dssid(wif);
2239210502Ssyrinx	else
2240210502Ssyrinx		rc = wlan_mesh_config_get(wif, val->var.subs[sub - 1]);
2241210502Ssyrinx	if (rc < 0)
2242210502Ssyrinx		return (SNMP_ERR_GENERR);
2243210502Ssyrinx
2244210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2245210502Ssyrinx	case LEAF_wlanMeshId:
2246210502Ssyrinx		return (string_get(val, wif->desired_ssid, -1));
2247210502Ssyrinx	case LEAF_wlanMeshTTL:
2248210502Ssyrinx		val->v.integer = wif->mesh_ttl;
2249210502Ssyrinx		break;
2250210502Ssyrinx	case LEAF_wlanMeshPeeringEnabled:
2251210502Ssyrinx		val->v.integer = wif->mesh_peering;
2252210502Ssyrinx		break;
2253210502Ssyrinx	case LEAF_wlanMeshForwardingEnabled:
2254210502Ssyrinx		val->v.integer = wif->mesh_forwarding;
2255210502Ssyrinx		break;
2256210502Ssyrinx	case LEAF_wlanMeshMetric:
2257210502Ssyrinx		val->v.integer = wif->mesh_metric;
2258210502Ssyrinx		break;
2259210502Ssyrinx	case LEAF_wlanMeshPath:
2260210502Ssyrinx		val->v.integer = wif->mesh_path;
2261210502Ssyrinx		break;
2262210502Ssyrinx	case LEAF_wlanMeshRoutesFlush:
2263210502Ssyrinx		val->v.integer = wlanMeshRoutesFlush_no_op;
2264210502Ssyrinx		break;
2265210502Ssyrinx	default:
2266210502Ssyrinx		abort();
2267210502Ssyrinx	}
2268210502Ssyrinx
2269210502Ssyrinx	return (SNMP_ERR_NOERROR);
2270210502Ssyrinx}
2271210502Ssyrinx
2272210502Ssyrinxint
2273210502Ssyrinxop_wlan_mesh_neighbor(struct snmp_context *ctx __unused, struct snmp_value *val,
2274210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2275210502Ssyrinx{
2276210502Ssyrinx	struct wlan_peer *wip;
2277210502Ssyrinx	struct wlan_iface *wif;
2278210502Ssyrinx
2279210502Ssyrinx	wlan_update_interface_list();
2280210502Ssyrinx	wlan_update_peers();
2281210502Ssyrinx
2282210502Ssyrinx	switch (op) {
2283210502Ssyrinx	case SNMP_OP_GET:
2284210502Ssyrinx		if ((wip = wlan_mesh_get_peer(&val->var, sub, &wif)) == NULL)
2285210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2286210502Ssyrinx		break;
2287210502Ssyrinx	case SNMP_OP_GETNEXT:
2288210502Ssyrinx		wip = wlan_mesh_get_next_peer(&val->var, sub, &wif);
2289210502Ssyrinx		if (wip == NULL)
2290210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2291210502Ssyrinx		wlan_append_mac_index(&val->var, sub, wif->wname,
2292210502Ssyrinx		    wip->pmac);
2293210502Ssyrinx		break;
2294210502Ssyrinx	case SNMP_OP_SET:
2295210502Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
2296210502Ssyrinx	case SNMP_OP_COMMIT:
2297210502Ssyrinx		/* FALLTHROUGH */
2298210502Ssyrinx	case SNMP_OP_ROLLBACK:
2299210502Ssyrinx		/* FALLTHROUGH */
2300210502Ssyrinx	default:
2301210502Ssyrinx		abort();
2302210502Ssyrinx	}
2303210502Ssyrinx
2304210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2305210502Ssyrinx	case LEAF_wlanMeshNeighborAddress:
2306210502Ssyrinx		return (string_get(val, wip->pmac, IEEE80211_ADDR_LEN));
2307210502Ssyrinx	case LEAF_wlanMeshNeighborFrequency:
2308210502Ssyrinx		val->v.integer = wip->frequency;
2309210502Ssyrinx		break;
2310210502Ssyrinx	case LEAF_wlanMeshNeighborLocalId:
2311210502Ssyrinx		val->v.integer = wip->local_id;
2312210502Ssyrinx		break;
2313210502Ssyrinx	case LEAF_wlanMeshNeighborPeerId:
2314210502Ssyrinx		val->v.integer = wip->peer_id;
2315210502Ssyrinx		break;
2316210502Ssyrinx	case LEAF_wlanMeshNeighborPeerState:
2317210502Ssyrinx		return (bits_get(val, (uint8_t *)&wip->state,
2318210502Ssyrinx		    sizeof(wip->state)));
2319210502Ssyrinx	case LEAF_wlanMeshNeighborCurrentTXRate:
2320210502Ssyrinx		val->v.integer = wip->txrate;
2321210502Ssyrinx		break;
2322210502Ssyrinx	case LEAF_wlanMeshNeighborRxSignalStrength:
2323210502Ssyrinx		val->v.integer = wip->rssi;
2324210502Ssyrinx		break;
2325210502Ssyrinx	case LEAF_wlanMeshNeighborIdleTimer:
2326210502Ssyrinx		val->v.integer = wip->idle;
2327210502Ssyrinx		break;
2328210502Ssyrinx	case LEAF_wlanMeshNeighborTxSequenceNo:
2329210502Ssyrinx		val->v.integer = wip->txseqs;
2330210502Ssyrinx		break;
2331210502Ssyrinx	case LEAF_wlanMeshNeighborRxSequenceNo:
2332210502Ssyrinx		val->v.integer = wip->rxseqs;
2333210502Ssyrinx		break;
2334210502Ssyrinx	default:
2335210502Ssyrinx		abort();
2336210502Ssyrinx	}
2337210502Ssyrinx
2338210502Ssyrinx	return (SNMP_ERR_NOERROR);
2339210502Ssyrinx}
2340210502Ssyrinx
2341210502Ssyrinxint
2342210502Ssyrinxop_wlan_mesh_route(struct snmp_context *ctx, struct snmp_value *val,
2343210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2344210502Ssyrinx{
2345210502Ssyrinx	struct wlan_mesh_route *wmr;
2346210502Ssyrinx	struct wlan_iface *wif;
2347210502Ssyrinx
2348210502Ssyrinx	wlan_update_interface_list();
2349210502Ssyrinx	wlan_mesh_update_routes();
2350210502Ssyrinx
2351210502Ssyrinx	switch (op) {
2352210502Ssyrinx	case SNMP_OP_GET:
2353210502Ssyrinx		if ((wmr = wlan_mesh_get_route(&val->var, sub, &wif)) == NULL)
2354210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2355210502Ssyrinx		break;
2356210502Ssyrinx
2357210502Ssyrinx	case SNMP_OP_GETNEXT:
2358210502Ssyrinx		wmr = wlan_mesh_get_next_route(&val->var, sub, &wif);
2359210502Ssyrinx		if (wmr == NULL)
2360210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2361210502Ssyrinx		wlan_append_mac_index(&val->var, sub, wif->wname,
2362210502Ssyrinx		    wmr->imroute.imr_dest);
2363210502Ssyrinx		break;
2364210502Ssyrinx
2365210502Ssyrinx	case SNMP_OP_SET:
2366210502Ssyrinx		switch (val->var.subs[sub - 1]) {
2367210502Ssyrinx		case LEAF_wlanMeshRouteDestination:
2368210502Ssyrinx			return (SNMP_ERR_INCONS_NAME);
2369210502Ssyrinx		case LEAF_wlanMeshRouteStatus:
2370210502Ssyrinx			return(wlan_mesh_route_set_status(ctx, val, sub));
2371210502Ssyrinx		default:
2372210502Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
2373210502Ssyrinx		}
2374210502Ssyrinx		abort();
2375210502Ssyrinx
2376210502Ssyrinx	case SNMP_OP_COMMIT:
2377210502Ssyrinx		if ((wmr = wlan_mesh_get_route(&val->var, sub, &wif)) == NULL)
2378210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2379210502Ssyrinx		if (val->v.integer == RowStatus_destroy &&
2380210502Ssyrinx		    wlan_mesh_delete_route(wif, wmr) < 0)
2381210502Ssyrinx			return (SNMP_ERR_GENERR);
2382210502Ssyrinx		return (SNMP_ERR_NOERROR);
2383210502Ssyrinx
2384210502Ssyrinx	case SNMP_OP_ROLLBACK:
2385210502Ssyrinx		if ((wmr = wlan_mesh_get_route(&val->var, sub, &wif)) == NULL)
2386210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2387210502Ssyrinx		if (ctx->scratch->int1 == RowStatus_destroy &&
2388210502Ssyrinx		    wlan_mesh_delete_route(wif, wmr) < 0)
2389210502Ssyrinx			return (SNMP_ERR_GENERR);
2390210502Ssyrinx		return (SNMP_ERR_NOERROR);
2391210502Ssyrinx
2392210502Ssyrinx	default:
2393210502Ssyrinx		abort();
2394210502Ssyrinx	}
2395210502Ssyrinx
2396210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2397210502Ssyrinx	case LEAF_wlanMeshRouteDestination:
2398210502Ssyrinx		return (string_get(val, wmr->imroute.imr_dest,
2399210502Ssyrinx		    IEEE80211_ADDR_LEN));
2400210502Ssyrinx	case LEAF_wlanMeshRouteNextHop:
2401210502Ssyrinx		return (string_get(val, wmr->imroute.imr_nexthop,
2402210502Ssyrinx		    IEEE80211_ADDR_LEN));
2403210502Ssyrinx	case LEAF_wlanMeshRouteHops:
2404210502Ssyrinx		val->v.integer = wmr->imroute.imr_nhops;
2405210502Ssyrinx		break;
2406210502Ssyrinx	case LEAF_wlanMeshRouteMetric:
2407210502Ssyrinx		val->v.integer = wmr->imroute.imr_metric;
2408210502Ssyrinx		break;
2409210502Ssyrinx	case LEAF_wlanMeshRouteLifeTime:
2410210502Ssyrinx		val->v.integer = wmr->imroute.imr_lifetime;
2411210502Ssyrinx		break;
2412210502Ssyrinx	case LEAF_wlanMeshRouteLastMseq:
2413210502Ssyrinx		val->v.integer = wmr->imroute.imr_lastmseq;
2414210502Ssyrinx		break;
2415210502Ssyrinx	case LEAF_wlanMeshRouteFlags:
2416210502Ssyrinx		val->v.integer = 0;
2417210502Ssyrinx		if ((wmr->imroute.imr_flags &
2418210502Ssyrinx		    IEEE80211_MESHRT_FLAGS_VALID) != 0)
2419210502Ssyrinx			val->v.integer |= (0x1 << wlanMeshRouteFlags_valid);
2420210502Ssyrinx		if ((wmr->imroute.imr_flags &
2421210502Ssyrinx		    IEEE80211_MESHRT_FLAGS_PROXY) != 0)
2422210502Ssyrinx			val->v.integer |= (0x1 << wlanMeshRouteFlags_proxy);
2423210502Ssyrinx		return (bits_get(val, (uint8_t *)&val->v.integer,
2424210502Ssyrinx		    sizeof(val->v.integer)));
2425210502Ssyrinx	case LEAF_wlanMeshRouteStatus:
2426210502Ssyrinx		val->v.integer = wmr->mroute_status;
2427210502Ssyrinx		break;
2428210502Ssyrinx	}
2429210502Ssyrinx
2430210502Ssyrinx	return (SNMP_ERR_NOERROR);
2431210502Ssyrinx}
2432210502Ssyrinx
2433210502Ssyrinxint
2434210502Ssyrinxop_wlan_mesh_stats(struct snmp_context *ctx __unused, struct snmp_value *val,
2435210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2436210502Ssyrinx{
2437210502Ssyrinx	struct wlan_iface *wif;
2438210502Ssyrinx
2439210502Ssyrinx	wlan_update_interface_list();
2440210502Ssyrinx
2441210502Ssyrinx	switch (op) {
2442210502Ssyrinx	case SNMP_OP_GET:
2443210502Ssyrinx		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2444210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2445210502Ssyrinx		break;
2446210502Ssyrinx	case SNMP_OP_GETNEXT:
2447210502Ssyrinx		if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)
2448210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2449210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
2450210502Ssyrinx		break;
2451210502Ssyrinx	case SNMP_OP_SET:
2452210502Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
2453210502Ssyrinx	case SNMP_OP_COMMIT:
2454210502Ssyrinx		/* FALLTHROUGH */
2455210502Ssyrinx	case SNMP_OP_ROLLBACK:
2456210502Ssyrinx		/* FALLTHROUGH */
2457210502Ssyrinx	default:
2458210502Ssyrinx		abort();
2459210502Ssyrinx	}
2460210502Ssyrinx
2461210502Ssyrinx	if (wlan_get_stats(wif) < 0)
2462210502Ssyrinx		return (SNMP_ERR_GENERR);
2463210502Ssyrinx
2464210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2465210502Ssyrinx	case LEAF_wlanMeshDroppedBadSta:
2466210502Ssyrinx		val->v.uint32 = wif->stats.is_mesh_wrongmesh;
2467210502Ssyrinx		break;
2468210502Ssyrinx	case LEAF_wlanMeshDroppedNoLink:
2469210502Ssyrinx		val->v.uint32 = wif->stats.is_mesh_nolink;
2470210502Ssyrinx		break;
2471210502Ssyrinx	case LEAF_wlanMeshNoFwdTtl:
2472210502Ssyrinx		val->v.uint32 = wif->stats.is_mesh_fwd_ttl;
2473210502Ssyrinx		break;
2474210502Ssyrinx	case LEAF_wlanMeshNoFwdBuf:
2475210502Ssyrinx		val->v.uint32 = wif->stats.is_mesh_fwd_nobuf;
2476210502Ssyrinx		break;
2477210502Ssyrinx	case LEAF_wlanMeshNoFwdTooShort:
2478210502Ssyrinx		val->v.uint32 = wif->stats.is_mesh_fwd_tooshort;
2479210502Ssyrinx		break;
2480210502Ssyrinx	case LEAF_wlanMeshNoFwdDisabled:
2481210502Ssyrinx		val->v.uint32 = wif->stats.is_mesh_fwd_disabled;
2482210502Ssyrinx		break;
2483210502Ssyrinx	case LEAF_wlanMeshNoFwdPathUnknown:
2484210502Ssyrinx		val->v.uint32 = wif->stats.is_mesh_fwd_nopath;
2485210502Ssyrinx		break;
2486210502Ssyrinx	case LEAF_wlanMeshDroppedBadAE:
2487210502Ssyrinx		val->v.uint32 = wif->stats.is_mesh_badae;
2488210502Ssyrinx		break;
2489210502Ssyrinx	case LEAF_wlanMeshRouteAddFailed:
2490210502Ssyrinx		val->v.uint32 = wif->stats.is_mesh_rtaddfailed;
2491210502Ssyrinx		break;
2492210502Ssyrinx	case LEAF_wlanMeshDroppedNoProxy:
2493210502Ssyrinx		val->v.uint32 = wif->stats.is_mesh_notproxy;
2494210502Ssyrinx		break;
2495210502Ssyrinx	case LEAF_wlanMeshDroppedMisaligned:
2496210502Ssyrinx		val->v.uint32 = wif->stats.is_rx_badalign;
2497210502Ssyrinx		break;
2498210502Ssyrinx	default:
2499210502Ssyrinx		abort();
2500210502Ssyrinx	}
2501210502Ssyrinx
2502210502Ssyrinx	return (SNMP_ERR_NOERROR);
2503210502Ssyrinx}
2504210502Ssyrinx
2505210502Ssyrinxint
2506210502Ssyrinxop_wlan_hwmp_config(struct snmp_context *ctx, struct snmp_value *val,
2507210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2508210502Ssyrinx{
2509210502Ssyrinx	int which;
2510210502Ssyrinx
2511210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2512210502Ssyrinx	case LEAF_wlanHWMPRouteInactiveTimeout:
2513210502Ssyrinx		which = WLAN_HWMP_INACTIVITY_TO;
2514210502Ssyrinx		break;
2515210502Ssyrinx	case LEAF_wlanHWMPRootAnnounceInterval:
2516210502Ssyrinx		which = WLAN_HWMP_RANN_INT;
2517210502Ssyrinx		break;
2518210502Ssyrinx	case LEAF_wlanHWMPRootInterval:
2519210502Ssyrinx		which = WLAN_HWMP_ROOT_INT;
2520210502Ssyrinx		break;
2521210502Ssyrinx	case LEAF_wlanHWMPRootTimeout:
2522210502Ssyrinx		which = WLAN_HWMP_ROOT_TO;
2523210502Ssyrinx		break;
2524210502Ssyrinx	case LEAF_wlanHWMPPathLifetime:
2525210502Ssyrinx		which = WLAN_HWMP_PATH_LIFETIME;
2526210502Ssyrinx		break;
2527210502Ssyrinx	case LEAF_wlanHWMPReplyForwardBit:
2528210502Ssyrinx		which = WLAN_HWMP_REPLY_FORWARD;
2529210502Ssyrinx		break;
2530210502Ssyrinx	case LEAF_wlanHWMPTargetOnlyBit:
2531210502Ssyrinx		which = WLAN_HWMP_TARGET_ONLY;
2532210502Ssyrinx		break;
2533210502Ssyrinx	default:
2534210502Ssyrinx		abort();
2535210502Ssyrinx	}
2536210502Ssyrinx
2537210502Ssyrinx	switch (op) {
2538210502Ssyrinx	case SNMP_OP_GET:
2539210502Ssyrinx		if (wlan_do_sysctl(&wlan_config, which, 0) < 0)
2540210502Ssyrinx			return (SNMP_ERR_GENERR);
2541210502Ssyrinx		break;
2542210502Ssyrinx
2543210502Ssyrinx	case SNMP_OP_GETNEXT:
2544210502Ssyrinx		abort();
2545210502Ssyrinx
2546210502Ssyrinx	case SNMP_OP_SET:
2547210502Ssyrinx		switch (val->var.subs[sub - 1]) {
2548210502Ssyrinx		case LEAF_wlanHWMPRouteInactiveTimeout:
2549210502Ssyrinx			ctx->scratch->int1 = wlan_config.hwmp_inact;
2550210502Ssyrinx			wlan_config.hwmp_inact = val->v.integer;
2551210502Ssyrinx			break;
2552210502Ssyrinx		case LEAF_wlanHWMPRootAnnounceInterval:
2553210502Ssyrinx			ctx->scratch->int1 = wlan_config.hwmp_rannint;
2554210502Ssyrinx			wlan_config.hwmp_rannint = val->v.integer;
2555210502Ssyrinx			break;
2556210502Ssyrinx		case LEAF_wlanHWMPRootInterval:
2557210502Ssyrinx			ctx->scratch->int1 = wlan_config.hwmp_rootint;
2558210502Ssyrinx			wlan_config.hwmp_rootint = val->v.integer;
2559210502Ssyrinx			break;
2560210502Ssyrinx		case LEAF_wlanHWMPRootTimeout:
2561210502Ssyrinx			ctx->scratch->int1 = wlan_config.hwmp_roottimeout;
2562210502Ssyrinx			wlan_config.hwmp_roottimeout = val->v.integer;
2563210502Ssyrinx			break;
2564210502Ssyrinx		case LEAF_wlanHWMPPathLifetime:
2565210502Ssyrinx			ctx->scratch->int1 = wlan_config.hwmp_pathlifetime;
2566210502Ssyrinx			wlan_config.hwmp_pathlifetime = val->v.integer;
2567210502Ssyrinx			break;
2568210502Ssyrinx		case LEAF_wlanHWMPReplyForwardBit:
2569210502Ssyrinx			ctx->scratch->int1 = wlan_config.hwmp_replyforward;
2570210502Ssyrinx			wlan_config.hwmp_replyforward = val->v.integer;
2571210502Ssyrinx			break;
2572210502Ssyrinx		case LEAF_wlanHWMPTargetOnlyBit:
2573210502Ssyrinx			ctx->scratch->int1 = wlan_config.hwmp_targetonly;
2574210502Ssyrinx			wlan_config.hwmp_targetonly = val->v.integer;
2575210502Ssyrinx			break;
2576210502Ssyrinx		}
2577210502Ssyrinx		if (wlan_do_sysctl(&wlan_config, which, 1) < 0)
2578210502Ssyrinx			return (SNMP_ERR_GENERR);
2579210502Ssyrinx		return (SNMP_ERR_NOERROR);
2580210502Ssyrinx
2581210502Ssyrinx	case SNMP_OP_COMMIT:
2582210502Ssyrinx		return (SNMP_ERR_NOERROR);
2583210502Ssyrinx
2584210502Ssyrinx	case SNMP_OP_ROLLBACK:
2585210502Ssyrinx		switch (val->var.subs[sub - 1]) {
2586210502Ssyrinx		case LEAF_wlanHWMPRouteInactiveTimeout:
2587210502Ssyrinx			wlan_config.hwmp_inact = ctx->scratch->int1;
2588210502Ssyrinx			break;
2589210502Ssyrinx		case LEAF_wlanHWMPRootAnnounceInterval:
2590210502Ssyrinx			wlan_config.hwmp_rannint = ctx->scratch->int1;
2591210502Ssyrinx			break;
2592210502Ssyrinx		case LEAF_wlanHWMPRootInterval:
2593210502Ssyrinx			wlan_config.hwmp_rootint = ctx->scratch->int1;
2594210502Ssyrinx			break;
2595210502Ssyrinx		case LEAF_wlanHWMPRootTimeout:
2596210502Ssyrinx			wlan_config.hwmp_roottimeout = ctx->scratch->int1;
2597210502Ssyrinx			break;
2598210502Ssyrinx		case LEAF_wlanHWMPPathLifetime:
2599210502Ssyrinx			wlan_config.hwmp_pathlifetime = ctx->scratch->int1;
2600210502Ssyrinx			break;
2601210502Ssyrinx		case LEAF_wlanHWMPReplyForwardBit:
2602210502Ssyrinx			wlan_config.hwmp_replyforward = ctx->scratch->int1;
2603210502Ssyrinx			break;
2604210502Ssyrinx		case LEAF_wlanHWMPTargetOnlyBit:
2605210502Ssyrinx			wlan_config.hwmp_targetonly = ctx->scratch->int1;
2606210502Ssyrinx			break;
2607210502Ssyrinx		}
2608210502Ssyrinx		if (wlan_do_sysctl(&wlan_config, which, 1) < 0)
2609210502Ssyrinx			return (SNMP_ERR_GENERR);
2610210502Ssyrinx		return (SNMP_ERR_NOERROR);
2611210502Ssyrinx
2612210502Ssyrinx	default:
2613210502Ssyrinx		abort();
2614210502Ssyrinx	}
2615210502Ssyrinx
2616210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2617210502Ssyrinx	case LEAF_wlanHWMPRouteInactiveTimeout:
2618210502Ssyrinx		val->v.integer = wlan_config.hwmp_inact;
2619210502Ssyrinx		break;
2620210502Ssyrinx	case LEAF_wlanHWMPRootAnnounceInterval:
2621210502Ssyrinx		val->v.integer = wlan_config.hwmp_rannint;
2622210502Ssyrinx		break;
2623210502Ssyrinx	case LEAF_wlanHWMPRootInterval:
2624210502Ssyrinx		val->v.integer = wlan_config.hwmp_rootint;
2625210502Ssyrinx		break;
2626210502Ssyrinx	case LEAF_wlanHWMPRootTimeout:
2627210502Ssyrinx		val->v.integer = wlan_config.hwmp_roottimeout;
2628210502Ssyrinx		break;
2629210502Ssyrinx	case LEAF_wlanHWMPPathLifetime:
2630210502Ssyrinx		val->v.integer = wlan_config.hwmp_pathlifetime;
2631210502Ssyrinx		break;
2632210502Ssyrinx	case LEAF_wlanHWMPReplyForwardBit:
2633210502Ssyrinx		val->v.integer = wlan_config.hwmp_replyforward;
2634210502Ssyrinx		break;
2635210502Ssyrinx	case LEAF_wlanHWMPTargetOnlyBit:
2636210502Ssyrinx		val->v.integer = wlan_config.hwmp_targetonly;
2637210502Ssyrinx		break;
2638210502Ssyrinx	}
2639210502Ssyrinx
2640210502Ssyrinx	return (SNMP_ERR_NOERROR);
2641210502Ssyrinx}
2642210502Ssyrinx
2643210502Ssyrinxint
2644210502Ssyrinxop_wlan_hwmp_iface(struct snmp_context *ctx, struct snmp_value *val,
2645210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2646210502Ssyrinx{
2647210502Ssyrinx	struct wlan_iface *wif;
2648210502Ssyrinx
2649210502Ssyrinx	wlan_update_interface_list();
2650210502Ssyrinx
2651210502Ssyrinx	switch (op) {
2652210502Ssyrinx	case SNMP_OP_GET:
2653210502Ssyrinx		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2654210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2655210502Ssyrinx		break;
2656210502Ssyrinx
2657210502Ssyrinx	case SNMP_OP_GETNEXT:
2658210502Ssyrinx		if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)
2659210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2660210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
2661210502Ssyrinx		break;
2662210502Ssyrinx
2663210502Ssyrinx	case SNMP_OP_SET:
2664210502Ssyrinx		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2665210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2666210502Ssyrinx		switch (val->var.subs[sub - 1]) {
2667210502Ssyrinx		case LEAF_wlanHWMPRootMode:
2668210502Ssyrinx			ctx->scratch->int1 = wif->hwmp_root_mode;
2669210502Ssyrinx			wif->hwmp_root_mode = val->v.integer;
2670210502Ssyrinx			break;
2671210502Ssyrinx		case LEAF_wlanHWMPMaxHops:
2672210502Ssyrinx			ctx->scratch->int1 = wif->hwmp_max_hops;
2673210502Ssyrinx			wif->hwmp_max_hops = val->v.integer;
2674210502Ssyrinx			break;
2675210502Ssyrinx		default:
2676210502Ssyrinx			abort();
2677210502Ssyrinx		}
2678210502Ssyrinx		if (wlan_hwmp_config_set(wif, val->var.subs[sub - 1]) < 0)
2679210502Ssyrinx			return (SNMP_ERR_GENERR);
2680210502Ssyrinx		return (SNMP_ERR_NOERROR);
2681210502Ssyrinx
2682210502Ssyrinx	case SNMP_OP_COMMIT:
2683210502Ssyrinx		return (SNMP_ERR_NOERROR);
2684210502Ssyrinx
2685210502Ssyrinx	case SNMP_OP_ROLLBACK:
2686210502Ssyrinx		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2687210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2688210502Ssyrinx		switch (val->var.subs[sub - 1]) {
2689210502Ssyrinx		case LEAF_wlanHWMPRootMode:
2690210502Ssyrinx			wif->hwmp_root_mode = ctx->scratch->int1;
2691210502Ssyrinx			break;
2692210502Ssyrinx		case LEAF_wlanHWMPMaxHops:
2693210502Ssyrinx			wif->hwmp_max_hops = ctx->scratch->int1;
2694210502Ssyrinx			break;
2695210502Ssyrinx		default:
2696210502Ssyrinx			abort();
2697210502Ssyrinx		}
2698210502Ssyrinx		if (wlan_hwmp_config_set(wif, val->var.subs[sub - 1]) < 0)
2699210502Ssyrinx			return (SNMP_ERR_GENERR);
2700210502Ssyrinx		return (SNMP_ERR_NOERROR);
2701210502Ssyrinx
2702210502Ssyrinx	default:
2703210502Ssyrinx		abort();
2704210502Ssyrinx	}
2705210502Ssyrinx
2706210502Ssyrinx	if (wlan_hwmp_config_get(wif, val->var.subs[sub - 1]) < 0)
2707210502Ssyrinx		return (SNMP_ERR_GENERR);
2708210502Ssyrinx
2709210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2710210502Ssyrinx	case LEAF_wlanHWMPRootMode:
2711210502Ssyrinx		val->v.integer = wif->hwmp_root_mode;
2712210502Ssyrinx		break;
2713210502Ssyrinx	case LEAF_wlanHWMPMaxHops:
2714210502Ssyrinx		val->v.integer = wif->hwmp_max_hops;
2715210502Ssyrinx		break;
2716210502Ssyrinx	default:
2717210502Ssyrinx		abort();
2718210502Ssyrinx	}
2719210502Ssyrinx
2720210502Ssyrinx	return (SNMP_ERR_NOERROR);
2721210502Ssyrinx}
2722210502Ssyrinx
2723210502Ssyrinxint
2724210502Ssyrinxop_wlan_hwmp_stats(struct snmp_context *ctx __unused, struct snmp_value *val,
2725210502Ssyrinx    uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
2726210502Ssyrinx{
2727210502Ssyrinx	struct wlan_iface *wif;
2728210502Ssyrinx
2729210502Ssyrinx	wlan_update_interface_list();
2730210502Ssyrinx
2731210502Ssyrinx	switch (op) {
2732210502Ssyrinx	case SNMP_OP_GET:
2733210502Ssyrinx		if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)
2734210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2735210502Ssyrinx		break;
2736210502Ssyrinx	case SNMP_OP_GETNEXT:
2737210502Ssyrinx		if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)
2738210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
2739210502Ssyrinx		wlan_append_ifindex(&val->var, sub, wif);
2740210502Ssyrinx		break;
2741210502Ssyrinx	case SNMP_OP_SET:
2742210502Ssyrinx		return (SNMP_ERR_NOT_WRITEABLE);
2743210502Ssyrinx	case SNMP_OP_COMMIT:
2744210502Ssyrinx		/* FALLTHROUGH */
2745210502Ssyrinx	case SNMP_OP_ROLLBACK:
2746210502Ssyrinx		/* FALLTHROUGH */
2747210502Ssyrinx	default:
2748210502Ssyrinx		abort();
2749210502Ssyrinx	}
2750210502Ssyrinx
2751210502Ssyrinx	if (wlan_get_stats(wif) < 0)
2752210502Ssyrinx		return (SNMP_ERR_GENERR);
2753210502Ssyrinx
2754210502Ssyrinx	switch (val->var.subs[sub - 1]) {
2755210502Ssyrinx	case LEAF_wlanMeshHWMPWrongSeqNo:
2756210502Ssyrinx		val->v.uint32 = wif->stats.is_hwmp_wrongseq;
2757210502Ssyrinx		break;
2758210502Ssyrinx	case LEAF_wlanMeshHWMPTxRootPREQ:
2759210502Ssyrinx		val->v.uint32 = wif->stats.is_hwmp_rootreqs;
2760210502Ssyrinx		break;
2761210502Ssyrinx	case LEAF_wlanMeshHWMPTxRootRANN:
2762210502Ssyrinx		val->v.uint32 = wif->stats.is_hwmp_rootrann;
2763210502Ssyrinx		break;
2764210502Ssyrinx	case LEAF_wlanMeshHWMPProxy:
2765210502Ssyrinx		val->v.uint32 = wif->stats.is_hwmp_proxy;
2766210502Ssyrinx		break;
2767210502Ssyrinx	default:
2768210502Ssyrinx		abort();
2769210502Ssyrinx	}
2770210502Ssyrinx
2771210502Ssyrinx	return (SNMP_ERR_NOERROR);
2772210502Ssyrinx}
2773210502Ssyrinx
2774210502Ssyrinx/*
2775210502Ssyrinx * Encode BITS type for a response packet - XXX: this belongs to the snmp lib.
2776210502Ssyrinx */
2777210502Ssyrinxstatic int
2778210502Ssyrinxbits_get(struct snmp_value *value, const u_char *ptr, ssize_t len)
2779210502Ssyrinx{
2780210502Ssyrinx	int size;
2781210502Ssyrinx
2782210502Ssyrinx	if (ptr == NULL) {
2783210502Ssyrinx		value->v.octetstring.len = 0;
2784210502Ssyrinx		value->v.octetstring.octets = NULL;
2785210502Ssyrinx		return (SNMP_ERR_NOERROR);
2786210502Ssyrinx	}
2787210502Ssyrinx
2788210502Ssyrinx	/* Determine length - up to 8 octets supported so far. */
2789210502Ssyrinx	for (size = len; size > 0; size--)
2790210502Ssyrinx		if (ptr[size - 1] != 0)
2791210502Ssyrinx			break;
2792210502Ssyrinx	if (size == 0)
2793210502Ssyrinx		size = 1;
2794210502Ssyrinx
2795210502Ssyrinx	value->v.octetstring.len = (u_long)size;
2796210502Ssyrinx	if ((value->v.octetstring.octets = malloc((size_t)size)) == NULL)
2797210502Ssyrinx		return (SNMP_ERR_RES_UNAVAIL);
2798210502Ssyrinx	memcpy(value->v.octetstring.octets, ptr, (size_t)size);
2799210502Ssyrinx	return (SNMP_ERR_NOERROR);
2800210502Ssyrinx}
2801210502Ssyrinx
2802210502Ssyrinx/*
2803210502Ssyrinx * Calls for adding/updating/freeing/etc of wireless interfaces.
2804210502Ssyrinx */
2805210502Ssyrinxstatic void
2806210502Ssyrinxwlan_free_interface(struct wlan_iface *wif)
2807210502Ssyrinx{
2808210502Ssyrinx	wlan_free_peerlist(wif);
2809210502Ssyrinx	free(wif->chanlist);
2810210502Ssyrinx	wlan_scan_free_results(wif);
2811210502Ssyrinx	wlan_mac_free_maclist(wif);
2812210502Ssyrinx	wlan_mesh_free_routes(wif);
2813210502Ssyrinx	free(wif);
2814210502Ssyrinx}
2815210502Ssyrinx
2816210502Ssyrinxstatic void
2817210502Ssyrinxwlan_free_iflist(void)
2818210502Ssyrinx{
2819210502Ssyrinx	struct wlan_iface *w;
2820210502Ssyrinx
2821210502Ssyrinx	while ((w = SLIST_FIRST(&wlan_ifaces)) != NULL) {
2822210502Ssyrinx		SLIST_REMOVE_HEAD(&wlan_ifaces, w_if);
2823210502Ssyrinx		wlan_free_interface(w);
2824210502Ssyrinx	}
2825210502Ssyrinx}
2826210502Ssyrinx
2827210502Ssyrinxstatic struct wlan_iface *
2828210502Ssyrinxwlan_find_interface(const char *wname)
2829210502Ssyrinx{
2830210502Ssyrinx	struct wlan_iface *wif;
2831210502Ssyrinx
2832210502Ssyrinx	SLIST_FOREACH(wif, &wlan_ifaces, w_if)
2833210502Ssyrinx		if (strcmp(wif->wname, wname) == 0) {
2834210502Ssyrinx			if (wif->status != RowStatus_active)
2835210502Ssyrinx				return (NULL);
2836210502Ssyrinx			break;
2837210502Ssyrinx		}
2838210502Ssyrinx
2839210502Ssyrinx	return (wif);
2840210502Ssyrinx}
2841210502Ssyrinx
2842210502Ssyrinxstatic struct wlan_iface *
2843210502Ssyrinxwlan_first_interface(void)
2844210502Ssyrinx{
2845210502Ssyrinx	return (SLIST_FIRST(&wlan_ifaces));
2846210502Ssyrinx}
2847210502Ssyrinx
2848210502Ssyrinxstatic struct wlan_iface *
2849210502Ssyrinxwlan_next_interface(struct wlan_iface *wif)
2850210502Ssyrinx{
2851210502Ssyrinx	if (wif == NULL)
2852210502Ssyrinx		return (NULL);
2853210502Ssyrinx
2854210502Ssyrinx	return (SLIST_NEXT(wif, w_if));
2855210502Ssyrinx}
2856210502Ssyrinx
2857210502Ssyrinx/*
2858210502Ssyrinx * Add a new interface to the list - sorted by name.
2859210502Ssyrinx */
2860210502Ssyrinxstatic int
2861210502Ssyrinxwlan_add_wif(struct wlan_iface *wif)
2862210502Ssyrinx{
2863210502Ssyrinx	int cmp;
2864210502Ssyrinx	struct wlan_iface *temp, *prev;
2865210502Ssyrinx
2866210502Ssyrinx	if ((prev = SLIST_FIRST(&wlan_ifaces)) == NULL ||
2867210502Ssyrinx	    strcmp(wif->wname, prev->wname) < 0) {
2868210502Ssyrinx		SLIST_INSERT_HEAD(&wlan_ifaces, wif, w_if);
2869210502Ssyrinx		return (0);
2870210502Ssyrinx	}
2871210502Ssyrinx
2872210502Ssyrinx	SLIST_FOREACH(temp, &wlan_ifaces, w_if) {
2873210502Ssyrinx		if ((cmp = strcmp(wif->wname, temp->wname)) <= 0)
2874210502Ssyrinx			break;
2875210502Ssyrinx		prev = temp;
2876210502Ssyrinx	}
2877210502Ssyrinx
2878210502Ssyrinx	if (temp == NULL)
2879210502Ssyrinx		SLIST_INSERT_AFTER(prev, wif, w_if);
2880210502Ssyrinx	else if (cmp > 0)
2881210502Ssyrinx		SLIST_INSERT_AFTER(temp, wif, w_if);
2882210502Ssyrinx	else {
2883210502Ssyrinx		syslog(LOG_ERR, "Wlan iface %s already in list", wif->wname);
2884210502Ssyrinx		return (-1);
2885210502Ssyrinx	}
2886210502Ssyrinx
2887210502Ssyrinx	return (0);
2888210502Ssyrinx}
2889210502Ssyrinx
2890210502Ssyrinxstatic struct wlan_iface *
2891210502Ssyrinxwlan_new_wif(char *wname)
2892210502Ssyrinx{
2893210502Ssyrinx	struct wlan_iface *wif;
2894210502Ssyrinx
2895210502Ssyrinx	/* Make sure it's not in the list. */
2896210502Ssyrinx	for (wif = wlan_first_interface(); wif != NULL;
2897210502Ssyrinx	    wif = wlan_next_interface(wif))
2898210502Ssyrinx		if (strcmp(wname, wif->wname) == 0) {
2899210502Ssyrinx			wif->internal = 0;
2900210502Ssyrinx			return (wif);
2901210502Ssyrinx		}
2902210502Ssyrinx
2903210502Ssyrinx	if ((wif = (struct wlan_iface *)malloc(sizeof(*wif))) == NULL)
2904210502Ssyrinx		return (NULL);
2905210502Ssyrinx
2906210502Ssyrinx	memset(wif, 0, sizeof(struct wlan_iface));
2907210502Ssyrinx	strlcpy(wif->wname, wname, IFNAMSIZ);
2908210502Ssyrinx	wif->status = RowStatus_notReady;
2909210502Ssyrinx	wif->state = wlanIfaceState_down;
2910210502Ssyrinx	wif->mode = WlanIfaceOperatingModeType_station;
2911210502Ssyrinx
2912210502Ssyrinx	if (wlan_add_wif(wif) < 0) {
2913210502Ssyrinx		free(wif);
2914210502Ssyrinx		return (NULL);
2915210502Ssyrinx	}
2916210502Ssyrinx
2917210502Ssyrinx	return (wif);
2918210502Ssyrinx}
2919210502Ssyrinx
2920210502Ssyrinxstatic void
2921210502Ssyrinxwlan_delete_wif(struct wlan_iface *wif)
2922210502Ssyrinx{
2923210502Ssyrinx	SLIST_REMOVE(&wlan_ifaces, wif, wlan_iface, w_if);
2924210502Ssyrinx	wlan_free_interface(wif);
2925210502Ssyrinx}
2926210502Ssyrinx
2927210502Ssyrinxstatic int
2928210502Ssyrinxwlan_attach_newif(struct mibif *mif)
2929210502Ssyrinx{
2930210502Ssyrinx	struct wlan_iface *wif;
2931210502Ssyrinx
2932210502Ssyrinx	if (mif->mib.ifmd_data.ifi_type != IFT_ETHER ||
2933210502Ssyrinx	    wlan_check_media(mif->name) != IFM_IEEE80211)
2934210502Ssyrinx		return (0);
2935210502Ssyrinx
2936210502Ssyrinx	if ((wif = wlan_new_wif(mif->name)) == NULL)
2937210502Ssyrinx		return (-1);
2938210502Ssyrinx
2939210502Ssyrinx	(void)wlan_get_opmode(wif);
2940210502Ssyrinx	wif->index = mif->index;
2941210502Ssyrinx	wif->status = RowStatus_active;
2942210502Ssyrinx	(void)wlan_update_interface(wif);
2943210502Ssyrinx
2944210502Ssyrinx	return (0);
2945210502Ssyrinx}
2946210502Ssyrinx
2947210502Ssyrinxstatic int
2948210502Ssyrinxwlan_iface_create(struct wlan_iface *wif)
2949210502Ssyrinx{
2950210502Ssyrinx	int rc;
2951210502Ssyrinx
2952210502Ssyrinx	if ((rc = wlan_clone_create(wif)) == SNMP_ERR_NOERROR) {
2953210502Ssyrinx		/*
2954210502Ssyrinx		 * The rest of the info will be updated once the
2955210502Ssyrinx		 * snmp_mibII module notifies us of the interface.
2956210502Ssyrinx		 */
2957210502Ssyrinx		wif->status = RowStatus_active;
2958210502Ssyrinx		if (wif->state == wlanIfaceState_up)
2959210502Ssyrinx			(void)wlan_config_state(wif, 1);
2960210502Ssyrinx	}
2961210502Ssyrinx
2962210502Ssyrinx	return (rc);
2963210502Ssyrinx}
2964210502Ssyrinx
2965210502Ssyrinxstatic int
2966210502Ssyrinxwlan_iface_destroy(struct wlan_iface *wif)
2967210502Ssyrinx{
2968210502Ssyrinx	int rc = SNMP_ERR_NOERROR;
2969210502Ssyrinx
2970210502Ssyrinx	if (wif->internal == 0)
2971210502Ssyrinx		rc = wlan_clone_destroy(wif);
2972210502Ssyrinx
2973210502Ssyrinx	if (rc == SNMP_ERR_NOERROR)
2974210502Ssyrinx		wlan_delete_wif(wif);
2975210502Ssyrinx
2976210502Ssyrinx	return (rc);
2977210502Ssyrinx}
2978210502Ssyrinx
2979210502Ssyrinxstatic int
2980210502Ssyrinxwlan_update_interface(struct wlan_iface *wif)
2981210502Ssyrinx{
2982210502Ssyrinx	int i;
2983210502Ssyrinx
2984210502Ssyrinx	(void)wlan_config_state(wif, 0);
2985210502Ssyrinx	(void)wlan_get_driver_caps(wif);
2986210502Ssyrinx	for (i = LEAF_wlanIfacePacketBurst;
2987210502Ssyrinx	    i <= LEAF_wlanIfaceTdmaBeaconInterval; i++)
2988210502Ssyrinx		(void)wlan_config_get_ioctl(wif, i);
2989210502Ssyrinx	(void)wlan_get_stats(wif);
2990210502Ssyrinx	/*
2991210502Ssyrinx	 * XXX: wlan_get_channel_list() not needed -
2992210502Ssyrinx	 * fetched with wlan_get_driver_caps()
2993210502Ssyrinx	 */
2994210502Ssyrinx	(void)wlan_get_channel_list(wif);
2995210502Ssyrinx	(void)wlan_get_roam_params(wif);
2996210502Ssyrinx	(void)wlan_get_tx_params(wif);
2997210502Ssyrinx	(void)wlan_get_scan_results(wif);
2998210502Ssyrinx	(void)wlan_get_wepmode(wif);
2999210502Ssyrinx	(void)wlan_get_weptxkey(wif);
3000210502Ssyrinx	(void)wlan_get_mac_policy(wif);
3001210502Ssyrinx	(void)wlan_get_mac_acl_macs(wif);
3002210502Ssyrinx	(void)wlan_get_peerinfo(wif);
3003210502Ssyrinx
3004210502Ssyrinx	if (wif->mode == WlanIfaceOperatingModeType_meshPoint) {
3005210502Ssyrinx		for (i = LEAF_wlanMeshTTL; i <= LEAF_wlanMeshPath; i++)
3006210502Ssyrinx			(void)wlan_mesh_config_get(wif, i);
3007210502Ssyrinx		(void)wlan_mesh_get_routelist(wif);
3008210502Ssyrinx		for (i = LEAF_wlanHWMPRootMode; i <= LEAF_wlanHWMPMaxHops; i++)
3009210502Ssyrinx			(void)wlan_hwmp_config_get(wif, i);
3010210502Ssyrinx	}
3011210502Ssyrinx
3012210502Ssyrinx	return (0);
3013210502Ssyrinx}
3014210502Ssyrinx
3015210502Ssyrinxstatic void
3016210502Ssyrinxwlan_update_interface_list(void)
3017210502Ssyrinx{
3018210502Ssyrinx	struct wlan_iface *wif, *twif;
3019210502Ssyrinx
3020210502Ssyrinx	if ((time(NULL) - wlan_iflist_age) <= WLAN_LIST_MAXAGE)
3021210502Ssyrinx		return;
3022210502Ssyrinx
3023210502Ssyrinx	/*
3024210502Ssyrinx	 * The snmp_mibII module would have notified us for new interfaces,
3025210502Ssyrinx	 * so only check if any have been deleted.
3026210502Ssyrinx	 */
3027210502Ssyrinx	SLIST_FOREACH_SAFE(wif, &wlan_ifaces, w_if, twif)
3028210502Ssyrinx		if (wif->status == RowStatus_active && wlan_get_opmode(wif) < 0)
3029210502Ssyrinx			wlan_delete_wif(wif);
3030210502Ssyrinx
3031210502Ssyrinx	wlan_iflist_age = time(NULL);
3032210502Ssyrinx}
3033210502Ssyrinx
3034210502Ssyrinxstatic void
3035210502Ssyrinxwlan_append_ifindex(struct asn_oid *oid, uint sub, const struct wlan_iface *w)
3036210502Ssyrinx{
3037210502Ssyrinx	uint32_t i;
3038210502Ssyrinx
3039210502Ssyrinx	oid->len = sub + strlen(w->wname) + 1;
3040210502Ssyrinx	oid->subs[sub] = strlen(w->wname);
3041210502Ssyrinx	for (i = 1; i <= strlen(w->wname); i++)
3042210502Ssyrinx		oid->subs[sub + i] = w->wname[i - 1];
3043210502Ssyrinx}
3044210502Ssyrinx
3045210502Ssyrinxstatic uint8_t *
3046210502Ssyrinxwlan_get_ifname(const struct asn_oid *oid, uint sub, uint8_t *wname)
3047210502Ssyrinx{
3048210502Ssyrinx	uint32_t i;
3049210502Ssyrinx
3050210502Ssyrinx	memset(wname, 0, IFNAMSIZ);
3051210502Ssyrinx
3052210502Ssyrinx	if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
3053210502Ssyrinx		return (NULL);
3054210502Ssyrinx
3055210502Ssyrinx	for (i = 0; i < oid->subs[sub]; i++)
3056210502Ssyrinx		wname[i] = oid->subs[sub + i + 1];
3057210502Ssyrinx	wname[i] = '\0';
3058210502Ssyrinx
3059210502Ssyrinx	return (wname);
3060210502Ssyrinx}
3061210502Ssyrinx
3062210502Ssyrinxstatic struct wlan_iface *
3063210502Ssyrinxwlan_get_interface(const struct asn_oid *oid, uint sub)
3064210502Ssyrinx{
3065210502Ssyrinx	uint8_t wname[IFNAMSIZ];
3066210502Ssyrinx
3067210502Ssyrinx	if (wlan_get_ifname(oid, sub, wname) == NULL)
3068210502Ssyrinx		return (NULL);
3069210502Ssyrinx
3070210502Ssyrinx	return (wlan_find_interface(wname));
3071210502Ssyrinx}
3072210502Ssyrinx
3073210502Ssyrinxstatic struct wlan_iface *
3074210502Ssyrinxwlan_get_next_interface(const struct asn_oid *oid, uint sub)
3075210502Ssyrinx{
3076210502Ssyrinx	uint32_t i;
3077210502Ssyrinx	uint8_t wname[IFNAMSIZ];
3078210502Ssyrinx	struct wlan_iface *wif;
3079210502Ssyrinx
3080210502Ssyrinx	if (oid->len - sub == 0) {
3081210502Ssyrinx		for (wif = wlan_first_interface(); wif != NULL;
3082210502Ssyrinx		    wif = wlan_next_interface(wif))
3083210502Ssyrinx			if (wif->status == RowStatus_active)
3084210502Ssyrinx				break;
3085210502Ssyrinx		return (wif);
3086210502Ssyrinx	}
3087210502Ssyrinx
3088210502Ssyrinx	if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
3089210502Ssyrinx		return (NULL);
3090210502Ssyrinx
3091210502Ssyrinx	memset(wname, 0, IFNAMSIZ);
3092210502Ssyrinx	for (i = 0; i < oid->subs[sub]; i++)
3093210502Ssyrinx		wname[i] = oid->subs[sub + i + 1];
3094210502Ssyrinx	wname[i] = '\0';
3095210502Ssyrinx	if ((wif = wlan_find_interface(wname)) == NULL)
3096210502Ssyrinx		return (NULL);
3097210502Ssyrinx
3098210502Ssyrinx	while ((wif = wlan_next_interface(wif)) != NULL)
3099210502Ssyrinx		if (wif->status == RowStatus_active)
3100210502Ssyrinx			break;
3101210502Ssyrinx
3102210502Ssyrinx	return (wif);
3103210502Ssyrinx}
3104210502Ssyrinx
3105210502Ssyrinxstatic struct wlan_iface *
3106210502Ssyrinxwlan_get_snmp_interface(const struct asn_oid *oid, uint sub)
3107210502Ssyrinx{
3108210502Ssyrinx	uint8_t wname[IFNAMSIZ];
3109210502Ssyrinx	struct wlan_iface *wif;
3110210502Ssyrinx
3111210502Ssyrinx	if (wlan_get_ifname(oid, sub, wname) == NULL)
3112210502Ssyrinx		return (NULL);
3113210502Ssyrinx
3114210502Ssyrinx	for (wif = wlan_first_interface(); wif != NULL;
3115210502Ssyrinx	    wif = wlan_next_interface(wif))
3116210502Ssyrinx		if (strcmp(wif->wname, wname) == 0)
3117210502Ssyrinx			break;
3118210502Ssyrinx
3119210502Ssyrinx	return (wif);
3120210502Ssyrinx}
3121210502Ssyrinx
3122210502Ssyrinxstatic struct wlan_iface *
3123210502Ssyrinxwlan_get_next_snmp_interface(const struct asn_oid *oid, uint sub)
3124210502Ssyrinx{
3125210502Ssyrinx	uint32_t i;
3126210502Ssyrinx	uint8_t wname[IFNAMSIZ];
3127210502Ssyrinx	struct wlan_iface *wif;
3128210502Ssyrinx
3129210502Ssyrinx	if (oid->len - sub == 0)
3130210502Ssyrinx		return (wlan_first_interface());
3131210502Ssyrinx
3132210502Ssyrinx	if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
3133210502Ssyrinx		return (NULL);
3134210502Ssyrinx
3135210502Ssyrinx	memset(wname, 0, IFNAMSIZ);
3136210502Ssyrinx	for (i = 0; i < oid->subs[sub]; i++)
3137210502Ssyrinx		wname[i] = oid->subs[sub + i + 1];
3138210502Ssyrinx	wname[i] = '\0';
3139210502Ssyrinx
3140210502Ssyrinx	for (wif = wlan_first_interface(); wif != NULL;
3141210502Ssyrinx	    wif = wlan_next_interface(wif))
3142210502Ssyrinx		if (strcmp(wif->wname, wname) == 0)
3143210502Ssyrinx			break;
3144210502Ssyrinx
3145210502Ssyrinx	return (wlan_next_interface(wif));
3146210502Ssyrinx}
3147210502Ssyrinx
3148210502Ssyrinx/*
3149210502Ssyrinx * Decode/Append an index for tables indexed by the wireless interface
3150210502Ssyrinx * name and a MAC address - ACL MACs and Mesh Routes.
3151210502Ssyrinx */
3152210502Ssyrinxstatic int
3153210502Ssyrinxwlan_mac_index_decode(const struct asn_oid *oid, uint sub,
3154210502Ssyrinx    char *wname, uint8_t *mac)
3155210502Ssyrinx{
3156210502Ssyrinx	uint32_t i;
3157210502Ssyrinx	int mac_off;
3158210502Ssyrinx
3159210502Ssyrinx	if (oid->len - sub != oid->subs[sub] + 2 + IEEE80211_ADDR_LEN
3160210502Ssyrinx	    || oid->subs[sub] >= IFNAMSIZ)
3161210502Ssyrinx		return (-1);
3162210502Ssyrinx
3163210502Ssyrinx	for (i = 0; i < oid->subs[sub]; i++)
3164210502Ssyrinx		wname[i] = oid->subs[sub + i + 1];
3165210502Ssyrinx	wname[i] = '\0';
3166210502Ssyrinx
3167210502Ssyrinx	mac_off = sub + oid->subs[sub] + 1;
3168210502Ssyrinx	if (oid->subs[mac_off] != IEEE80211_ADDR_LEN)
3169210502Ssyrinx		return (-1);
3170210502Ssyrinx	for (i = 0; i < IEEE80211_ADDR_LEN; i++)
3171210502Ssyrinx		mac[i] = oid->subs[mac_off + i + 1];
3172210502Ssyrinx
3173210502Ssyrinx	return (0);
3174210502Ssyrinx}
3175210502Ssyrinx
3176210502Ssyrinxstatic void
3177210502Ssyrinxwlan_append_mac_index(struct asn_oid *oid, uint sub, char *wname, uint8_t *mac)
3178210502Ssyrinx{
3179210502Ssyrinx	uint32_t i;
3180210502Ssyrinx
3181210502Ssyrinx	oid->len = sub + strlen(wname) + IEEE80211_ADDR_LEN + 2;
3182210502Ssyrinx	oid->subs[sub] = strlen(wname);
3183210502Ssyrinx	for (i = 1; i <= strlen(wname); i++)
3184210502Ssyrinx		oid->subs[sub + i] = wname[i - 1];
3185210502Ssyrinx
3186210502Ssyrinx	sub += strlen(wname) + 1;
3187210502Ssyrinx	oid->subs[sub] = IEEE80211_ADDR_LEN;
3188210502Ssyrinx	for (i = 1; i <= IEEE80211_ADDR_LEN; i++)
3189210502Ssyrinx		oid->subs[sub + i] = mac[i - 1];
3190210502Ssyrinx}
3191210502Ssyrinx
3192210502Ssyrinx/*
3193210502Ssyrinx * Decode/Append an index for tables indexed by the wireless interface
3194210502Ssyrinx * name and the PHY mode - Roam and TX params.
3195210502Ssyrinx */
3196210502Ssyrinxstatic int
3197210502Ssyrinxwlan_phy_index_decode(const struct asn_oid *oid, uint sub, char *wname,
3198210502Ssyrinx    uint32_t *phy)
3199210502Ssyrinx{
3200210502Ssyrinx	uint32_t i;
3201210502Ssyrinx
3202210502Ssyrinx	if (oid->len - sub != oid->subs[sub] + 2 || oid->subs[sub] >= IFNAMSIZ)
3203210502Ssyrinx		return (-1);
3204210502Ssyrinx
3205210502Ssyrinx	for (i = 0; i < oid->subs[sub]; i++)
3206210502Ssyrinx		wname[i] = oid->subs[sub + i + 1];
3207210502Ssyrinx	wname[i] = '\0';
3208210502Ssyrinx
3209210502Ssyrinx	*phy = oid->subs[sub + oid->subs[sub] + 1];
3210210502Ssyrinx	return (0);
3211210502Ssyrinx}
3212210502Ssyrinx
3213210502Ssyrinxstatic void
3214210502Ssyrinxwlan_append_phy_index(struct asn_oid *oid, uint sub, char *wname, uint32_t phy)
3215210502Ssyrinx{
3216210502Ssyrinx	uint32_t i;
3217210502Ssyrinx
3218210502Ssyrinx	oid->len = sub + strlen(wname) + 2;
3219210502Ssyrinx	oid->subs[sub] = strlen(wname);
3220210502Ssyrinx	for (i = 1; i <= strlen(wname); i++)
3221210502Ssyrinx		oid->subs[sub + i] = wname[i - 1];
3222210502Ssyrinx	oid->subs[sub + strlen(wname) + 1] = phy;
3223210502Ssyrinx}
3224210502Ssyrinx
3225210502Ssyrinx/*
3226210502Ssyrinx * Calls for manipulating the peerlist of a wireless interface.
3227210502Ssyrinx */
3228210502Ssyrinxstatic void
3229210502Ssyrinxwlan_free_peerlist(struct wlan_iface *wif)
3230210502Ssyrinx{
3231210502Ssyrinx	struct wlan_peer *wip;
3232210502Ssyrinx
3233210502Ssyrinx	while ((wip = SLIST_FIRST(&wif->peerlist)) != NULL) {
3234210502Ssyrinx		SLIST_REMOVE_HEAD(&wif->peerlist, wp);
3235210502Ssyrinx		free(wip);
3236210502Ssyrinx	}
3237210502Ssyrinx
3238210502Ssyrinx	SLIST_INIT(&wif->peerlist);
3239210502Ssyrinx}
3240210502Ssyrinx
3241210502Ssyrinxstatic struct wlan_peer *
3242210502Ssyrinxwlan_find_peer(struct wlan_iface *wif, uint8_t *peermac)
3243210502Ssyrinx{
3244210502Ssyrinx	struct wlan_peer *wip;
3245210502Ssyrinx
3246210502Ssyrinx	SLIST_FOREACH(wip, &wif->peerlist, wp)
3247210502Ssyrinx		if (memcmp(wip->pmac, peermac, IEEE80211_ADDR_LEN) == 0)
3248210502Ssyrinx			break;
3249210502Ssyrinx
3250210502Ssyrinx	return (wip);
3251210502Ssyrinx}
3252210502Ssyrinx
3253210502Ssyrinxstruct wlan_peer *
3254210502Ssyrinxwlan_new_peer(const uint8_t *pmac)
3255210502Ssyrinx{
3256210502Ssyrinx	struct wlan_peer *wip;
3257210502Ssyrinx
3258210502Ssyrinx	if ((wip = (struct wlan_peer *)malloc(sizeof(*wip))) == NULL)
3259210502Ssyrinx		return (NULL);
3260210502Ssyrinx
3261210502Ssyrinx	memset(wip, 0, sizeof(struct wlan_peer));
3262210502Ssyrinx	memcpy(wip->pmac, pmac, IEEE80211_ADDR_LEN);
3263210502Ssyrinx
3264210502Ssyrinx	return (wip);
3265210502Ssyrinx}
3266210502Ssyrinx
3267210502Ssyrinxvoid
3268210502Ssyrinxwlan_free_peer(struct wlan_peer *wip)
3269210502Ssyrinx{
3270210502Ssyrinx	free(wip);
3271210502Ssyrinx}
3272210502Ssyrinx
3273210502Ssyrinxint
3274210502Ssyrinxwlan_add_peer(struct wlan_iface *wif, struct wlan_peer *wip)
3275210502Ssyrinx{
3276210502Ssyrinx	struct wlan_peer *temp, *prev;
3277210502Ssyrinx
3278210502Ssyrinx	SLIST_FOREACH(temp, &wif->peerlist, wp)
3279210502Ssyrinx		if (memcmp(temp->pmac, wip->pmac, IEEE80211_ADDR_LEN) == 0)
3280210502Ssyrinx			return (-1);
3281210502Ssyrinx
3282210502Ssyrinx	if ((prev = SLIST_FIRST(&wif->peerlist)) == NULL ||
3283210502Ssyrinx	    memcmp(wip->pmac, prev->pmac, IEEE80211_ADDR_LEN) < 0) {
3284210502Ssyrinx	    	SLIST_INSERT_HEAD(&wif->peerlist, wip, wp);
3285210502Ssyrinx	    	return (0);
3286210502Ssyrinx	}
3287210502Ssyrinx
3288210502Ssyrinx	SLIST_FOREACH(temp, &wif->peerlist, wp) {
3289210502Ssyrinx		if (memcmp(wip->pmac, temp->pmac, IEEE80211_ADDR_LEN) < 0)
3290210502Ssyrinx			break;
3291210502Ssyrinx		prev = temp;
3292210502Ssyrinx	}
3293210502Ssyrinx
3294210502Ssyrinx	SLIST_INSERT_AFTER(prev, wip, wp);
3295210502Ssyrinx	return (0);
3296210502Ssyrinx}
3297210502Ssyrinx
3298210502Ssyrinxstatic void
3299210502Ssyrinxwlan_update_peers(void)
3300210502Ssyrinx{
3301210502Ssyrinx	struct wlan_iface *wif;
3302210502Ssyrinx
3303210502Ssyrinx	if ((time(NULL) - wlan_peerlist_age) <= WLAN_LIST_MAXAGE)
3304210502Ssyrinx		return;
3305210502Ssyrinx
3306210502Ssyrinx	for (wif = wlan_first_interface(); wif != NULL;
3307210502Ssyrinx	    wif = wlan_next_interface(wif)) {
3308210502Ssyrinx		if (wif->status != RowStatus_active)
3309210502Ssyrinx			continue;
3310210502Ssyrinx		wlan_free_peerlist(wif);
3311210502Ssyrinx		(void)wlan_get_peerinfo(wif);
3312210502Ssyrinx	}
3313210502Ssyrinx	wlan_peerlist_age = time(NULL);
3314210502Ssyrinx}
3315210502Ssyrinx
3316210502Ssyrinxstatic struct wlan_peer *
3317210502Ssyrinxwlan_get_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3318210502Ssyrinx{
3319210502Ssyrinx	char wname[IFNAMSIZ];
3320210502Ssyrinx	uint8_t pmac[IEEE80211_ADDR_LEN];
3321210502Ssyrinx
3322210502Ssyrinx	if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0)
3323210502Ssyrinx		return (NULL);
3324210502Ssyrinx
3325210502Ssyrinx	if ((*wif = wlan_find_interface(wname)) == NULL)
3326210502Ssyrinx		return (NULL);
3327210502Ssyrinx
3328210502Ssyrinx	return (wlan_find_peer(*wif, pmac));
3329210502Ssyrinx}
3330210502Ssyrinx
3331210502Ssyrinxstatic struct wlan_peer *
3332210502Ssyrinxwlan_get_next_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3333210502Ssyrinx{
3334210502Ssyrinx	char wname[IFNAMSIZ];
3335210502Ssyrinx	char pmac[IEEE80211_ADDR_LEN];
3336210502Ssyrinx	struct wlan_peer *wip;
3337210502Ssyrinx
3338210502Ssyrinx	if (oid->len - sub == 0) {
3339210502Ssyrinx		for (*wif = wlan_first_interface(); *wif != NULL;
3340210502Ssyrinx		    *wif = wlan_next_interface(*wif)) {
3341210502Ssyrinx			if ((*wif)->mode ==
3342210502Ssyrinx			    WlanIfaceOperatingModeType_meshPoint)
3343210502Ssyrinx				continue;
3344210502Ssyrinx			wip = SLIST_FIRST(&(*wif)->peerlist);
3345210502Ssyrinx			if (wip != NULL)
3346210502Ssyrinx				return (wip);
3347210502Ssyrinx		}
3348210502Ssyrinx		return (NULL);
3349210502Ssyrinx	}
3350210502Ssyrinx
3351210502Ssyrinx	if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0 ||
3352210502Ssyrinx	    (*wif = wlan_find_interface(wname)) == NULL ||
3353210502Ssyrinx	    (wip = wlan_find_peer(*wif, pmac)) == NULL)
3354210502Ssyrinx		return (NULL);
3355210502Ssyrinx
3356210502Ssyrinx	if ((wip = SLIST_NEXT(wip, wp)) != NULL)
3357210502Ssyrinx		return (wip);
3358210502Ssyrinx
3359210502Ssyrinx	while ((*wif = wlan_next_interface(*wif)) != NULL) {
3360210502Ssyrinx		if ((*wif)->mode == WlanIfaceOperatingModeType_meshPoint)
3361210502Ssyrinx			continue;
3362210502Ssyrinx		if ((wip = SLIST_FIRST(&(*wif)->peerlist)) != NULL)
3363210502Ssyrinx			break;
3364210502Ssyrinx	}
3365210502Ssyrinx
3366210502Ssyrinx	return (wip);
3367210502Ssyrinx}
3368210502Ssyrinx
3369210502Ssyrinx/*
3370210502Ssyrinx * Calls for manipulating the active channel list of a wireless interface.
3371210502Ssyrinx */
3372210502Ssyrinxstatic void
3373210502Ssyrinxwlan_update_channels(void)
3374210502Ssyrinx{
3375210502Ssyrinx	struct wlan_iface *wif;
3376210502Ssyrinx
3377210502Ssyrinx	if ((time(NULL) - wlan_chanlist_age) <= WLAN_LIST_MAXAGE)
3378210502Ssyrinx		return;
3379210502Ssyrinx
3380210502Ssyrinx	for (wif = wlan_first_interface(); wif != NULL;
3381210502Ssyrinx	    wif = wlan_next_interface(wif)) {
3382210502Ssyrinx		if (wif->status != RowStatus_active)
3383210502Ssyrinx			continue;
3384210502Ssyrinx		(void)wlan_get_channel_list(wif);
3385210502Ssyrinx	}
3386210502Ssyrinx	wlan_chanlist_age = time(NULL);
3387210502Ssyrinx}
3388210502Ssyrinx
3389210502Ssyrinxstatic int
3390210502Ssyrinxwlan_channel_index_decode(const struct asn_oid *oid, uint sub, char *wname,
3391210502Ssyrinx    uint32_t *cindex)
3392210502Ssyrinx{
3393210502Ssyrinx	uint32_t i;
3394210502Ssyrinx	if (oid->len - sub != oid->subs[sub] + 2 || oid->subs[sub] >= IFNAMSIZ)
3395210502Ssyrinx		return (-1);
3396210502Ssyrinx
3397210502Ssyrinx	for (i = 0; i < oid->subs[sub]; i++)
3398210502Ssyrinx		wname[i] = oid->subs[sub + i + 1];
3399210502Ssyrinx	wname[i] = '\0';
3400210502Ssyrinx
3401210502Ssyrinx	*cindex = oid->subs[sub + oid->subs[sub] + 1];
3402210502Ssyrinx
3403210502Ssyrinx	return (0);
3404210502Ssyrinx}
3405210502Ssyrinx
3406210502Ssyrinxstatic void
3407210502Ssyrinxwlan_append_channel_index(struct asn_oid *oid, uint sub,
3408210502Ssyrinx    const struct wlan_iface *wif, const struct ieee80211_channel *channel)
3409210502Ssyrinx{
3410210502Ssyrinx	uint32_t i;
3411210502Ssyrinx
3412210502Ssyrinx	oid->len = sub + strlen(wif->wname) + 2;
3413210502Ssyrinx	oid->subs[sub] = strlen(wif->wname);
3414210502Ssyrinx	for (i = 1; i <= strlen(wif->wname); i++)
3415210502Ssyrinx		oid->subs[sub + i] = wif->wname[i - 1];
3416210502Ssyrinx	oid->subs[sub + strlen(wif->wname) + 1] = (channel - wif->chanlist) + 1;
3417210502Ssyrinx}
3418210502Ssyrinx
3419210502Ssyrinxstatic int32_t
3420210502Ssyrinxwlan_get_channel_type(struct ieee80211_channel *c)
3421210502Ssyrinx{
3422210502Ssyrinx	if (IEEE80211_IS_CHAN_FHSS(c))
3423210502Ssyrinx		return (WlanChannelType_fhss);
3424210502Ssyrinx	if (IEEE80211_IS_CHAN_A(c))
3425210502Ssyrinx		return (WlanChannelType_dot11a);
3426210502Ssyrinx	if (IEEE80211_IS_CHAN_B(c))
3427210502Ssyrinx		return (WlanChannelType_dot11b);
3428210502Ssyrinx	if (IEEE80211_IS_CHAN_ANYG(c))
3429210502Ssyrinx		return (WlanChannelType_dot11g);
3430210502Ssyrinx	if (IEEE80211_IS_CHAN_HALF(c))
3431210502Ssyrinx		return (WlanChannelType_tenMHz);
3432210502Ssyrinx	if (IEEE80211_IS_CHAN_QUARTER(c))
3433210502Ssyrinx		return (WlanChannelType_fiveMHz);
3434210502Ssyrinx	if (IEEE80211_IS_CHAN_TURBO(c))
3435210502Ssyrinx		return (WlanChannelType_turbo);
3436210502Ssyrinx	if (IEEE80211_IS_CHAN_HT(c))
3437210502Ssyrinx		return (WlanChannelType_ht);
3438210502Ssyrinx
3439210502Ssyrinx	return (-1);
3440210502Ssyrinx}
3441210502Ssyrinx
3442210502Ssyrinxstatic struct ieee80211_channel *
3443210502Ssyrinxwlan_find_channel(struct wlan_iface *wif, uint32_t cindex)
3444210502Ssyrinx{
3445210502Ssyrinx	if (wif->chanlist == NULL || cindex > wif->nchannels)
3446210502Ssyrinx		return (NULL);
3447210502Ssyrinx
3448210502Ssyrinx	return (wif->chanlist + cindex - 1);
3449210502Ssyrinx}
3450210502Ssyrinx
3451210502Ssyrinxstatic struct ieee80211_channel *
3452210502Ssyrinxwlan_get_channel(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3453210502Ssyrinx{
3454210502Ssyrinx	uint32_t cindex;
3455210502Ssyrinx	char wname[IFNAMSIZ];
3456210502Ssyrinx
3457210502Ssyrinx	if (wlan_channel_index_decode(oid, sub, wname, &cindex) < 0)
3458210502Ssyrinx		return (NULL);
3459210502Ssyrinx
3460210502Ssyrinx	if ((*wif = wlan_find_interface(wname)) == NULL)
3461210502Ssyrinx		return (NULL);
3462210502Ssyrinx
3463210502Ssyrinx	return (wlan_find_channel(*wif, cindex));
3464210502Ssyrinx}
3465210502Ssyrinx
3466210502Ssyrinxstatic struct ieee80211_channel *
3467210502Ssyrinxwlan_get_next_channel(const struct asn_oid *oid, uint sub,
3468210502Ssyrinx    struct wlan_iface **wif)
3469210502Ssyrinx{
3470210502Ssyrinx	uint32_t cindex;
3471210502Ssyrinx	char wname[IFNAMSIZ];
3472210502Ssyrinx
3473210502Ssyrinx	if (oid->len - sub == 0) {
3474210502Ssyrinx		for (*wif = wlan_first_interface(); *wif != NULL;
3475210502Ssyrinx		    *wif = wlan_next_interface(*wif)) {
3476210502Ssyrinx			if ((*wif)->status != RowStatus_active)
3477210502Ssyrinx				continue;
3478210502Ssyrinx			if ((*wif)->nchannels != 0 && (*wif)->chanlist != NULL)
3479210502Ssyrinx				return ((*wif)->chanlist);
3480210502Ssyrinx		}
3481210502Ssyrinx		return (NULL);
3482210502Ssyrinx	}
3483210502Ssyrinx
3484210502Ssyrinx	if (wlan_channel_index_decode(oid, sub, wname, &cindex) < 0)
3485210502Ssyrinx		return (NULL);
3486210502Ssyrinx
3487210502Ssyrinx	if ((*wif = wlan_find_interface(wname)) == NULL)
3488210502Ssyrinx		return (NULL);
3489210502Ssyrinx
3490210502Ssyrinx	if (cindex < (*wif)->nchannels)
3491210502Ssyrinx		return ((*wif)->chanlist + cindex);
3492210502Ssyrinx
3493210502Ssyrinx	while ((*wif = wlan_next_interface(*wif)) != NULL)
3494210502Ssyrinx		if ((*wif)->status == RowStatus_active)
3495210502Ssyrinx			if ((*wif)->nchannels != 0 && (*wif)->chanlist != NULL)
3496210502Ssyrinx				return ((*wif)->chanlist);
3497210502Ssyrinx
3498210502Ssyrinx	return (NULL);
3499210502Ssyrinx}
3500210502Ssyrinx
3501210502Ssyrinx/*
3502210502Ssyrinx * Calls for manipulating the roam params of a wireless interface.
3503210502Ssyrinx */
3504210502Ssyrinxstatic void
3505210502Ssyrinxwlan_update_roam_params(void)
3506210502Ssyrinx{
3507210502Ssyrinx	struct wlan_iface *wif;
3508210502Ssyrinx
3509210502Ssyrinx	if ((time(NULL) - wlan_roamlist_age) <= WLAN_LIST_MAXAGE)
3510210502Ssyrinx		return;
3511210502Ssyrinx
3512210502Ssyrinx	for (wif = wlan_first_interface(); wif != NULL;
3513210502Ssyrinx	    wif = wlan_next_interface(wif)) {
3514210502Ssyrinx		if (wif->status != RowStatus_active)
3515210502Ssyrinx			continue;
3516210502Ssyrinx		(void)wlan_get_roam_params(wif);
3517210502Ssyrinx	}
3518210502Ssyrinx	wlan_roamlist_age = time(NULL);
3519210502Ssyrinx}
3520210502Ssyrinx
3521210502Ssyrinxstatic struct ieee80211_roamparam *
3522210502Ssyrinxwlan_get_roam_param(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3523210502Ssyrinx{
3524210502Ssyrinx	uint32_t phy;
3525210502Ssyrinx	char wname[IFNAMSIZ];
3526210502Ssyrinx
3527210502Ssyrinx	if (wlan_phy_index_decode(oid, sub, wname, &phy) < 0)
3528210502Ssyrinx		return (NULL);
3529210502Ssyrinx
3530210502Ssyrinx	if ((*wif = wlan_find_interface(wname)) == NULL)
3531210502Ssyrinx		return (NULL);
3532210502Ssyrinx
3533210502Ssyrinx	if (phy == 0 || phy > IEEE80211_MODE_MAX)
3534210502Ssyrinx		return (NULL);
3535210502Ssyrinx
3536210502Ssyrinx	return ((*wif)->roamparams.params + phy - 1);
3537210502Ssyrinx}
3538210502Ssyrinx
3539210502Ssyrinxstatic struct ieee80211_roamparam *
3540210502Ssyrinxwlan_get_next_roam_param(const struct asn_oid *oid, uint sub,
3541210502Ssyrinx    struct wlan_iface **wif, uint32_t *phy)
3542210502Ssyrinx{
3543210502Ssyrinx	char wname[IFNAMSIZ];
3544210502Ssyrinx
3545210502Ssyrinx	if (oid->len - sub == 0) {
3546210502Ssyrinx		for (*wif = wlan_first_interface(); *wif != NULL;
3547210502Ssyrinx		    *wif = wlan_next_interface(*wif)) {
3548210502Ssyrinx			if ((*wif)->status != RowStatus_active)
3549210502Ssyrinx				continue;
3550210502Ssyrinx			*phy = 1;
3551210502Ssyrinx			return ((*wif)->roamparams.params);
3552210502Ssyrinx		}
3553210502Ssyrinx		return (NULL);
3554210502Ssyrinx	}
3555210502Ssyrinx
3556210502Ssyrinx	if (wlan_phy_index_decode(oid, sub, wname, phy) < 0)
3557210502Ssyrinx		return (NULL);
3558210502Ssyrinx
3559210502Ssyrinx	if (*phy == 0  || (*wif = wlan_find_interface(wname)) == NULL)
3560210502Ssyrinx		return (NULL);
3561210502Ssyrinx
3562210502Ssyrinx	if (++(*phy) <= IEEE80211_MODE_MAX)
3563210502Ssyrinx		return ((*wif)->roamparams.params + *phy - 1);
3564210502Ssyrinx
3565210502Ssyrinx	*phy = 1;
3566210502Ssyrinx	while ((*wif = wlan_next_interface(*wif)) != NULL)
3567210502Ssyrinx		if ((*wif)->status == RowStatus_active)
3568210502Ssyrinx			return ((*wif)->roamparams.params);
3569210502Ssyrinx
3570210502Ssyrinx	return (NULL);
3571210502Ssyrinx}
3572210502Ssyrinx
3573210502Ssyrinx/*
3574210502Ssyrinx * Calls for manipulating the tx params of a wireless interface.
3575210502Ssyrinx */
3576210502Ssyrinxstatic void
3577210502Ssyrinxwlan_update_tx_params(void)
3578210502Ssyrinx{
3579210502Ssyrinx	struct wlan_iface *wif;
3580210502Ssyrinx
3581210502Ssyrinx	if ((time(NULL) - wlan_tx_paramlist_age) <= WLAN_LIST_MAXAGE)
3582210502Ssyrinx		return;
3583210502Ssyrinx
3584210502Ssyrinx	for (wif = wlan_first_interface(); wif != NULL;
3585210502Ssyrinx	    wif = wlan_next_interface(wif)) {
3586210502Ssyrinx		if (wif->status != RowStatus_active)
3587210502Ssyrinx			continue;
3588210502Ssyrinx		(void)wlan_get_tx_params(wif);
3589210502Ssyrinx	}
3590210502Ssyrinx
3591210502Ssyrinx	wlan_tx_paramlist_age = time(NULL);
3592210502Ssyrinx}
3593210502Ssyrinx
3594210502Ssyrinxstatic struct ieee80211_txparam *
3595210502Ssyrinxwlan_get_tx_param(const struct asn_oid *oid, uint sub, struct wlan_iface **wif,
3596210502Ssyrinx    uint32_t *phy)
3597210502Ssyrinx{
3598210502Ssyrinx	char wname[IFNAMSIZ];
3599210502Ssyrinx
3600210502Ssyrinx	if (wlan_phy_index_decode(oid, sub, wname, phy) < 0)
3601210502Ssyrinx		return (NULL);
3602210502Ssyrinx
3603210502Ssyrinx	if ((*wif = wlan_find_interface(wname)) == NULL)
3604210502Ssyrinx		return (NULL);
3605210502Ssyrinx
3606210502Ssyrinx	if (*phy == 0 || *phy > IEEE80211_MODE_MAX)
3607210502Ssyrinx		return (NULL);
3608210502Ssyrinx
3609210502Ssyrinx	return ((*wif)->txparams.params + *phy - 1);
3610210502Ssyrinx}
3611210502Ssyrinx
3612210502Ssyrinxstatic struct ieee80211_txparam *
3613210502Ssyrinxwlan_get_next_tx_param(const struct asn_oid *oid, uint sub,
3614210502Ssyrinx    struct wlan_iface **wif, uint32_t *phy)
3615210502Ssyrinx{
3616210502Ssyrinx	char wname[IFNAMSIZ];
3617210502Ssyrinx
3618210502Ssyrinx	if (oid->len - sub == 0) {
3619210502Ssyrinx		for (*wif = wlan_first_interface(); *wif != NULL;
3620210502Ssyrinx		    *wif = wlan_next_interface(*wif)) {
3621210502Ssyrinx			if ((*wif)->status != RowStatus_active)
3622210502Ssyrinx				continue;
3623210502Ssyrinx			*phy = 1;
3624210502Ssyrinx			return ((*wif)->txparams.params);
3625210502Ssyrinx		}
3626210502Ssyrinx		return (NULL);
3627210502Ssyrinx	}
3628210502Ssyrinx
3629210502Ssyrinx	if (wlan_phy_index_decode(oid, sub, wname, phy) < 0)
3630210502Ssyrinx		return (NULL);
3631210502Ssyrinx
3632210502Ssyrinx	if (*phy == 0 || (*wif = wlan_find_interface(wname)) == NULL)
3633210502Ssyrinx		return (NULL);
3634210502Ssyrinx
3635210502Ssyrinx	if (++(*phy) <= IEEE80211_MODE_MAX)
3636210502Ssyrinx		return ((*wif)->txparams.params + *phy - 1);
3637210502Ssyrinx
3638210502Ssyrinx	*phy = 1;
3639210502Ssyrinx	while ((*wif = wlan_next_interface(*wif)) != NULL)
3640210502Ssyrinx		if ((*wif)->status == RowStatus_active)
3641210502Ssyrinx			return ((*wif)->txparams.params);
3642210502Ssyrinx
3643210502Ssyrinx	return (NULL);
3644210502Ssyrinx}
3645210502Ssyrinx
3646210502Ssyrinx/*
3647210502Ssyrinx * Calls for manipulating the scan results for a wireless interface.
3648210502Ssyrinx */
3649210502Ssyrinxstatic void
3650210502Ssyrinxwlan_scan_free_results(struct wlan_iface *wif)
3651210502Ssyrinx{
3652210502Ssyrinx	struct wlan_scan_result *sr;
3653210502Ssyrinx
3654210502Ssyrinx	while ((sr = SLIST_FIRST(&wif->scanlist)) != NULL) {
3655210502Ssyrinx		SLIST_REMOVE_HEAD(&wif->scanlist, wsr);
3656210502Ssyrinx		free(sr);
3657210502Ssyrinx	}
3658210502Ssyrinx
3659210502Ssyrinx	SLIST_INIT(&wif->scanlist);
3660210502Ssyrinx}
3661210502Ssyrinx
3662210502Ssyrinxstatic struct wlan_scan_result *
3663210502Ssyrinxwlan_scan_find_result(struct wlan_iface *wif, uint8_t *ssid, uint8_t *bssid)
3664210502Ssyrinx{
3665210502Ssyrinx	struct wlan_scan_result *sr;
3666210502Ssyrinx
3667210502Ssyrinx	SLIST_FOREACH(sr, &wif->scanlist, wsr)
3668210502Ssyrinx		if (strlen(ssid) == strlen(sr->ssid) &&
3669210502Ssyrinx		    strcmp(sr->ssid, ssid) == 0 &&
3670210502Ssyrinx		    memcmp(sr->bssid, bssid, IEEE80211_ADDR_LEN) == 0)
3671210502Ssyrinx			break;
3672210502Ssyrinx
3673210502Ssyrinx	return (sr);
3674210502Ssyrinx}
3675210502Ssyrinx
3676210502Ssyrinxstruct wlan_scan_result *
3677210502Ssyrinxwlan_scan_new_result(const uint8_t *ssid, const uint8_t *bssid)
3678210502Ssyrinx{
3679210502Ssyrinx	struct wlan_scan_result *sr;
3680210502Ssyrinx
3681210502Ssyrinx	sr = (struct wlan_scan_result *)malloc(sizeof(*sr));
3682210502Ssyrinx	if (sr == NULL)
3683210502Ssyrinx		return (NULL);
3684210502Ssyrinx
3685210502Ssyrinx	memset(sr, 0, sizeof(*sr));
3686210502Ssyrinx	if (ssid[0] != '\0')
3687210502Ssyrinx		strlcpy(sr->ssid, ssid, IEEE80211_NWID_LEN + 1);
3688210502Ssyrinx	memcpy(sr->bssid, bssid, IEEE80211_ADDR_LEN);
3689210502Ssyrinx
3690210502Ssyrinx	return (sr);
3691210502Ssyrinx}
3692210502Ssyrinx
3693210502Ssyrinxvoid
3694210502Ssyrinxwlan_scan_free_result(struct wlan_scan_result *sr)
3695210502Ssyrinx{
3696210502Ssyrinx	free(sr);
3697210502Ssyrinx}
3698210502Ssyrinx
3699210502Ssyrinxstatic int
3700210502Ssyrinxwlan_scan_compare_result(struct wlan_scan_result *sr1,
3701210502Ssyrinx    struct wlan_scan_result *sr2)
3702210502Ssyrinx{
3703210502Ssyrinx	uint32_t i;
3704210502Ssyrinx
3705210502Ssyrinx	if (strlen(sr1->ssid) < strlen(sr2->ssid))
3706210502Ssyrinx		return (-1);
3707210502Ssyrinx	if (strlen(sr1->ssid) > strlen(sr2->ssid))
3708210502Ssyrinx		return (1);
3709210502Ssyrinx
3710210502Ssyrinx	for (i = 0; i < strlen(sr1->ssid) && i < strlen(sr2->ssid); i++) {
3711210502Ssyrinx		if (sr1->ssid[i] < sr2->ssid[i])
3712210502Ssyrinx			return (-1);
3713210502Ssyrinx		if (sr1->ssid[i] > sr2->ssid[i])
3714210502Ssyrinx			return (1);
3715210502Ssyrinx	}
3716210502Ssyrinx
3717210502Ssyrinx	for (i = 0; i < IEEE80211_ADDR_LEN; i++) {
3718210502Ssyrinx		if (sr1->bssid[i] < sr2->bssid[i])
3719210502Ssyrinx			return (-1);
3720210502Ssyrinx		if (sr1->bssid[i] > sr2->bssid[i])
3721210502Ssyrinx			return (1);
3722210502Ssyrinx	}
3723210502Ssyrinx
3724210502Ssyrinx	return (0);
3725210502Ssyrinx}
3726210502Ssyrinx
3727210502Ssyrinxint
3728210502Ssyrinxwlan_scan_add_result(struct wlan_iface *wif, struct wlan_scan_result *sr)
3729210502Ssyrinx{
3730210502Ssyrinx	struct wlan_scan_result *prev, *temp;
3731210502Ssyrinx
3732210502Ssyrinx	SLIST_FOREACH(temp, &wif->scanlist, wsr)
3733210502Ssyrinx		if (strlen(temp->ssid) == strlen(sr->ssid) &&
3734210502Ssyrinx		    strcmp(sr->ssid, temp->ssid) == 0 &&
3735210502Ssyrinx		    memcmp(sr->bssid, temp->bssid, IEEE80211_ADDR_LEN) == 0)
3736210502Ssyrinx			return (-1);
3737210502Ssyrinx
3738210502Ssyrinx	if ((prev = SLIST_FIRST(&wif->scanlist)) == NULL ||
3739210502Ssyrinx	    wlan_scan_compare_result(sr, prev) < 0) {
3740210502Ssyrinx	    	SLIST_INSERT_HEAD(&wif->scanlist, sr, wsr);
3741210502Ssyrinx	    	return (0);
3742210502Ssyrinx	}
3743210502Ssyrinx
3744210502Ssyrinx	SLIST_FOREACH(temp, &wif->scanlist, wsr) {
3745210502Ssyrinx		if (wlan_scan_compare_result(sr, temp) < 0)
3746210502Ssyrinx			break;
3747210502Ssyrinx		prev = temp;
3748210502Ssyrinx	}
3749210502Ssyrinx
3750210502Ssyrinx	SLIST_INSERT_AFTER(prev, sr, wsr);
3751210502Ssyrinx	return (0);
3752210502Ssyrinx}
3753210502Ssyrinx
3754210502Ssyrinxstatic void
3755210502Ssyrinxwlan_scan_update_results(void)
3756210502Ssyrinx{
3757210502Ssyrinx	struct wlan_iface *wif;
3758210502Ssyrinx
3759210502Ssyrinx	if ((time(NULL) - wlan_scanlist_age) <= WLAN_LIST_MAXAGE)
3760210502Ssyrinx		return;
3761210502Ssyrinx
3762210502Ssyrinx	for (wif = wlan_first_interface(); wif != NULL;
3763210502Ssyrinx	    wif = wlan_next_interface(wif)) {
3764210502Ssyrinx		if (wif->status != RowStatus_active)
3765210502Ssyrinx			continue;
3766210502Ssyrinx		wlan_scan_free_results(wif);
3767210502Ssyrinx		(void)wlan_get_scan_results(wif);
3768210502Ssyrinx	}
3769210502Ssyrinx	wlan_scanlist_age = time(NULL);
3770210502Ssyrinx}
3771210502Ssyrinx
3772210502Ssyrinxstatic int
3773210502Ssyrinxwlan_scanr_index_decode(const struct asn_oid *oid, uint sub,
3774210502Ssyrinx    char *wname, uint8_t *ssid, uint8_t *bssid)
3775210502Ssyrinx{
3776210502Ssyrinx	uint32_t i;
3777210502Ssyrinx	int offset;
3778210502Ssyrinx
3779210502Ssyrinx	if (oid->subs[sub] >= IFNAMSIZ)
3780210502Ssyrinx		return (-1);
3781210502Ssyrinx	for (i = 0; i < oid->subs[sub]; i++)
3782210502Ssyrinx		wname[i] = oid->subs[sub + i + 1];
3783210502Ssyrinx	wname[oid->subs[sub]] = '\0';
3784210502Ssyrinx
3785210502Ssyrinx	offset = sub + oid->subs[sub] + 1;
3786210502Ssyrinx	if (oid->subs[offset] > IEEE80211_NWID_LEN)
3787210502Ssyrinx		return (-1);
3788210502Ssyrinx	for (i = 0; i < oid->subs[offset]; i++)
3789210502Ssyrinx		ssid[i] = oid->subs[offset + i + 1];
3790210502Ssyrinx	ssid[i] = '\0';
3791210502Ssyrinx
3792210502Ssyrinx	offset = sub + oid->subs[sub] + oid->subs[offset] + 2;
3793210502Ssyrinx	if (oid->subs[offset] != IEEE80211_ADDR_LEN)
3794210502Ssyrinx		return (-1);
3795210502Ssyrinx	for (i = 0; i < IEEE80211_ADDR_LEN; i++)
3796210502Ssyrinx		bssid[i] = oid->subs[offset + i + 1];
3797210502Ssyrinx
3798210502Ssyrinx	return (0);
3799210502Ssyrinx}
3800210502Ssyrinx
3801210502Ssyrinxstatic void
3802210502Ssyrinxwlan_append_scanr_index(struct asn_oid *oid, uint sub, char *wname,
3803210502Ssyrinx    uint8_t *ssid, uint8_t *bssid)
3804210502Ssyrinx{
3805210502Ssyrinx	uint32_t i;
3806210502Ssyrinx
3807210502Ssyrinx	oid->len = sub + strlen(wname) + strlen(ssid) + IEEE80211_ADDR_LEN + 3;
3808210502Ssyrinx	oid->subs[sub] = strlen(wname);
3809210502Ssyrinx	for (i = 1; i <= strlen(wname); i++)
3810210502Ssyrinx		oid->subs[sub + i] = wname[i - 1];
3811210502Ssyrinx
3812210502Ssyrinx	sub += strlen(wname) + 1;
3813210502Ssyrinx	oid->subs[sub] = strlen(ssid);
3814210502Ssyrinx	for (i = 1; i <= strlen(ssid); i++)
3815210502Ssyrinx		oid->subs[sub + i] = ssid[i - 1];
3816210502Ssyrinx
3817210502Ssyrinx	sub += strlen(ssid) + 1;
3818210502Ssyrinx	oid->subs[sub] = IEEE80211_ADDR_LEN;
3819210502Ssyrinx	for (i = 1; i <= IEEE80211_ADDR_LEN; i++)
3820210502Ssyrinx		oid->subs[sub + i] = bssid[i - 1];
3821210502Ssyrinx}
3822210502Ssyrinx
3823210502Ssyrinxstatic struct wlan_scan_result *
3824210502Ssyrinxwlan_get_scanr(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3825210502Ssyrinx{
3826210502Ssyrinx	char wname[IFNAMSIZ];
3827210502Ssyrinx	uint8_t ssid[IEEE80211_NWID_LEN + 1];
3828210502Ssyrinx	uint8_t bssid[IEEE80211_ADDR_LEN];
3829210502Ssyrinx
3830210502Ssyrinx	if (wlan_scanr_index_decode(oid, sub, wname, ssid, bssid) < 0)
3831210502Ssyrinx		return (NULL);
3832210502Ssyrinx
3833210502Ssyrinx	if ((*wif = wlan_find_interface(wname)) == NULL)
3834210502Ssyrinx		return (NULL);
3835210502Ssyrinx
3836210502Ssyrinx	return (wlan_scan_find_result(*wif, ssid, bssid));
3837210502Ssyrinx}
3838210502Ssyrinx
3839210502Ssyrinxstatic struct wlan_scan_result *
3840210502Ssyrinxwlan_get_next_scanr(const struct asn_oid *oid, uint sub,
3841210502Ssyrinx    struct wlan_iface **wif)
3842210502Ssyrinx{
3843210502Ssyrinx	char wname[IFNAMSIZ];
3844210502Ssyrinx	uint8_t ssid[IEEE80211_NWID_LEN + 1];
3845210502Ssyrinx	uint8_t bssid[IEEE80211_ADDR_LEN];
3846210502Ssyrinx	struct wlan_scan_result *sr;
3847210502Ssyrinx
3848210502Ssyrinx	if (oid->len - sub == 0) {
3849210502Ssyrinx		for (*wif = wlan_first_interface(); *wif != NULL;
3850210502Ssyrinx		    *wif = wlan_next_interface(*wif)) {
3851210502Ssyrinx			sr = SLIST_FIRST(&(*wif)->scanlist);
3852210502Ssyrinx			if (sr != NULL)
3853210502Ssyrinx				return (sr);
3854210502Ssyrinx		}
3855210502Ssyrinx		return (NULL);
3856210502Ssyrinx	}
3857210502Ssyrinx
3858210502Ssyrinx	if (wlan_scanr_index_decode(oid, sub, wname, ssid, bssid) < 0 ||
3859210502Ssyrinx	    (*wif = wlan_find_interface(wname)) == NULL ||
3860210502Ssyrinx	    (sr = wlan_scan_find_result(*wif, ssid, bssid)) == NULL)
3861210502Ssyrinx		return (NULL);
3862210502Ssyrinx
3863210502Ssyrinx	if ((sr = SLIST_NEXT(sr, wsr)) != NULL)
3864210502Ssyrinx		return (sr);
3865210502Ssyrinx
3866210502Ssyrinx	while ((*wif = wlan_next_interface(*wif)) != NULL)
3867210502Ssyrinx		if ((sr = SLIST_FIRST(&(*wif)->scanlist)) != NULL)
3868210502Ssyrinx			break;
3869210502Ssyrinx
3870210502Ssyrinx	return (sr);
3871210502Ssyrinx}
3872210502Ssyrinx
3873210502Ssyrinx/*
3874210502Ssyrinx * MAC Access Control.
3875210502Ssyrinx */
3876210502Ssyrinxstatic void
3877210502Ssyrinxwlan_mac_free_maclist(struct wlan_iface *wif)
3878210502Ssyrinx{
3879210502Ssyrinx	struct wlan_mac_mac *wmm;
3880210502Ssyrinx
3881210502Ssyrinx	while ((wmm = SLIST_FIRST(&wif->mac_maclist)) != NULL) {
3882210502Ssyrinx		SLIST_REMOVE_HEAD(&wif->mac_maclist, wm);
3883210502Ssyrinx		free(wmm);
3884210502Ssyrinx	}
3885210502Ssyrinx
3886210502Ssyrinx	SLIST_INIT(&wif->mac_maclist);
3887210502Ssyrinx}
3888210502Ssyrinx
3889210502Ssyrinxstatic struct wlan_mac_mac *
3890210502Ssyrinxwlan_mac_find_mac(struct wlan_iface *wif, uint8_t *mac)
3891210502Ssyrinx{
3892210502Ssyrinx	struct wlan_mac_mac *wmm;
3893210502Ssyrinx
3894210502Ssyrinx	SLIST_FOREACH(wmm, &wif->mac_maclist, wm)
3895210502Ssyrinx		if (memcmp(wmm->mac, mac, IEEE80211_ADDR_LEN) == 0)
3896210502Ssyrinx			break;
3897210502Ssyrinx
3898210502Ssyrinx	return (wmm);
3899210502Ssyrinx}
3900210502Ssyrinx
3901210502Ssyrinxstruct wlan_mac_mac *
3902210502Ssyrinxwlan_mac_new_mac(const uint8_t *mac)
3903210502Ssyrinx{
3904210502Ssyrinx	struct wlan_mac_mac *wmm;
3905210502Ssyrinx
3906210502Ssyrinx	if ((wmm = (struct wlan_mac_mac *)malloc(sizeof(*wmm))) == NULL)
3907210502Ssyrinx		return (NULL);
3908210502Ssyrinx
3909210502Ssyrinx	memset(wmm, 0, sizeof(*wmm));
3910210502Ssyrinx	memcpy(wmm->mac, mac, IEEE80211_ADDR_LEN);
3911210502Ssyrinx	wmm->mac_status = RowStatus_notReady;
3912210502Ssyrinx
3913210502Ssyrinx	return (wmm);
3914210502Ssyrinx}
3915210502Ssyrinx
3916210502Ssyrinxvoid
3917210502Ssyrinxwlan_mac_free_mac(struct wlan_mac_mac *wmm)
3918210502Ssyrinx{
3919210502Ssyrinx	free(wmm);
3920210502Ssyrinx}
3921210502Ssyrinx
3922210502Ssyrinxint
3923210502Ssyrinxwlan_mac_add_mac(struct wlan_iface *wif, struct wlan_mac_mac *wmm)
3924210502Ssyrinx{
3925210502Ssyrinx	struct wlan_mac_mac *temp, *prev;
3926210502Ssyrinx
3927210502Ssyrinx	SLIST_FOREACH(temp, &wif->mac_maclist, wm)
3928210502Ssyrinx		if (memcmp(temp->mac, wmm->mac, IEEE80211_ADDR_LEN) == 0)
3929210502Ssyrinx			return (-1);
3930210502Ssyrinx
3931210502Ssyrinx	if ((prev = SLIST_FIRST(&wif->mac_maclist)) == NULL ||
3932210502Ssyrinx	    memcmp(wmm->mac, prev->mac,IEEE80211_ADDR_LEN) < 0) {
3933210502Ssyrinx	    	SLIST_INSERT_HEAD(&wif->mac_maclist, wmm, wm);
3934210502Ssyrinx	    	return (0);
3935210502Ssyrinx	}
3936210502Ssyrinx
3937210502Ssyrinx	SLIST_FOREACH(temp, &wif->mac_maclist, wm) {
3938210502Ssyrinx		if (memcmp(wmm->mac, temp->mac, IEEE80211_ADDR_LEN) < 0)
3939210502Ssyrinx			break;
3940210502Ssyrinx		prev = temp;
3941210502Ssyrinx	}
3942210502Ssyrinx
3943210502Ssyrinx	SLIST_INSERT_AFTER(prev, wmm, wm);
3944210502Ssyrinx	return (0);
3945210502Ssyrinx}
3946210502Ssyrinx
3947210502Ssyrinxstatic int
3948210502Ssyrinxwlan_mac_delete_mac(struct wlan_iface *wif, struct wlan_mac_mac *wmm)
3949210502Ssyrinx{
3950210502Ssyrinx	if (wmm->mac_status == RowStatus_active &&
3951210502Ssyrinx	    wlan_del_mac_acl_mac(wif, wmm) < 0)
3952210502Ssyrinx		return (-1);
3953210502Ssyrinx
3954210502Ssyrinx	SLIST_REMOVE(&wif->mac_maclist, wmm, wlan_mac_mac, wm);
3955210502Ssyrinx	free(wmm);
3956210502Ssyrinx
3957210502Ssyrinx	return (0);
3958210502Ssyrinx}
3959210502Ssyrinx
3960210502Ssyrinxstatic void
3961210502Ssyrinxwlan_mac_update_aclmacs(void)
3962210502Ssyrinx{
3963210502Ssyrinx	struct wlan_iface *wif;
3964210502Ssyrinx	struct wlan_mac_mac *wmm, *twmm;
3965210502Ssyrinx
3966210502Ssyrinx	if ((time(NULL) - wlan_maclist_age) <= WLAN_LIST_MAXAGE)
3967210502Ssyrinx		return;
3968210502Ssyrinx
3969210502Ssyrinx	for (wif = wlan_first_interface(); wif != NULL;
3970210502Ssyrinx	    wif = wlan_next_interface(wif)) {
3971210502Ssyrinx		if (wif->status != RowStatus_active)
3972210502Ssyrinx			continue;
3973210502Ssyrinx		/*
3974210502Ssyrinx		 * Nuke old entries - XXX - they are likely not to
3975210502Ssyrinx		 * change often - reconsider.
3976210502Ssyrinx		 */
3977210502Ssyrinx		SLIST_FOREACH_SAFE(wmm, &wif->mac_maclist, wm, twmm)
3978210502Ssyrinx			if (wmm->mac_status == RowStatus_active) {
3979210502Ssyrinx				SLIST_REMOVE(&wif->mac_maclist, wmm,
3980210502Ssyrinx				    wlan_mac_mac, wm);
3981210502Ssyrinx				wlan_mac_free_mac(wmm);
3982210502Ssyrinx			}
3983210502Ssyrinx		(void)wlan_get_mac_acl_macs(wif);
3984210502Ssyrinx	}
3985210502Ssyrinx	wlan_maclist_age = time(NULL);
3986210502Ssyrinx}
3987210502Ssyrinx
3988210502Ssyrinxstatic struct wlan_mac_mac *
3989210502Ssyrinxwlan_get_acl_mac(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
3990210502Ssyrinx{
3991210502Ssyrinx	char wname[IFNAMSIZ];
3992210502Ssyrinx	char mac[IEEE80211_ADDR_LEN];
3993210502Ssyrinx
3994210502Ssyrinx	if (wlan_mac_index_decode(oid, sub, wname, mac) < 0)
3995210502Ssyrinx		return (NULL);
3996210502Ssyrinx
3997210502Ssyrinx	if ((*wif = wlan_find_interface(wname)) == NULL)
3998210502Ssyrinx		return (NULL);
3999210502Ssyrinx
4000210502Ssyrinx	return (wlan_mac_find_mac(*wif, mac));
4001210502Ssyrinx}
4002210502Ssyrinx
4003210502Ssyrinxstatic struct wlan_mac_mac *
4004210502Ssyrinxwlan_get_next_acl_mac(const struct asn_oid *oid, uint sub,
4005210502Ssyrinx    struct wlan_iface **wif)
4006210502Ssyrinx{
4007210502Ssyrinx	char wname[IFNAMSIZ];
4008210502Ssyrinx	char mac[IEEE80211_ADDR_LEN];
4009210502Ssyrinx	struct wlan_mac_mac *wmm;
4010210502Ssyrinx
4011210502Ssyrinx	if (oid->len - sub == 0) {
4012210502Ssyrinx		for (*wif = wlan_first_interface(); *wif != NULL;
4013210502Ssyrinx		    *wif = wlan_next_interface(*wif)) {
4014210502Ssyrinx			wmm = SLIST_FIRST(&(*wif)->mac_maclist);
4015210502Ssyrinx			if (wmm != NULL)
4016210502Ssyrinx				return (wmm);
4017210502Ssyrinx		}
4018210502Ssyrinx		return (NULL);
4019210502Ssyrinx	}
4020210502Ssyrinx
4021210502Ssyrinx	if (wlan_mac_index_decode(oid, sub, wname, mac) < 0 ||
4022210502Ssyrinx	    (*wif = wlan_find_interface(wname)) == NULL ||
4023210502Ssyrinx	    (wmm = wlan_mac_find_mac(*wif, mac)) == NULL)
4024210502Ssyrinx		return (NULL);
4025210502Ssyrinx
4026210502Ssyrinx	if ((wmm = SLIST_NEXT(wmm, wm)) != NULL)
4027210502Ssyrinx		return (wmm);
4028210502Ssyrinx
4029210502Ssyrinx	while ((*wif = wlan_next_interface(*wif)) != NULL)
4030210502Ssyrinx		if ((wmm = SLIST_FIRST(&(*wif)->mac_maclist)) != NULL)
4031210502Ssyrinx			break;
4032210502Ssyrinx
4033210502Ssyrinx	return (wmm);
4034210502Ssyrinx}
4035210502Ssyrinx
4036210502Ssyrinxstatic int
4037210502Ssyrinxwlan_acl_mac_set_status(struct snmp_context *ctx, struct snmp_value *val,
4038210502Ssyrinx    uint sub)
4039210502Ssyrinx{
4040210502Ssyrinx	char wname[IFNAMSIZ];
4041210502Ssyrinx	uint8_t mac[IEEE80211_ADDR_LEN];
4042210502Ssyrinx	struct wlan_iface *wif;
4043210502Ssyrinx	struct wlan_mac_mac *macl;
4044210502Ssyrinx
4045210502Ssyrinx	if (wlan_mac_index_decode(&val->var, sub, wname, mac) < 0)
4046210502Ssyrinx		return (SNMP_ERR_GENERR);
4047210502Ssyrinx	macl = wlan_get_acl_mac(&val->var, sub, &wif);
4048210502Ssyrinx
4049210502Ssyrinx	switch (val->v.integer) {
4050210502Ssyrinx	case RowStatus_createAndGo:
4051210502Ssyrinx		if (macl != NULL)
4052210502Ssyrinx			return (SNMP_ERR_INCONS_NAME);
4053210502Ssyrinx		break;
4054210502Ssyrinx	case RowStatus_destroy:
4055210502Ssyrinx		if (macl == NULL)
4056210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
4057210502Ssyrinx		ctx->scratch->int1 = RowStatus_active;
4058210502Ssyrinx		return (SNMP_ERR_NOERROR);
4059210502Ssyrinx	default:
4060210502Ssyrinx		return (SNMP_ERR_INCONS_VALUE);
4061210502Ssyrinx	}
4062210502Ssyrinx
4063210502Ssyrinx
4064210502Ssyrinx	if (wif == NULL || !wif->macsupported)
4065210502Ssyrinx		return (SNMP_ERR_INCONS_VALUE);
4066210502Ssyrinx
4067210502Ssyrinx	if ((macl = wlan_mac_new_mac((const uint8_t *)mac)) == NULL)
4068210502Ssyrinx		return (SNMP_ERR_GENERR);
4069210502Ssyrinx
4070210502Ssyrinx	ctx->scratch->int1 = RowStatus_destroy;
4071210502Ssyrinx
4072210502Ssyrinx	if (wlan_mac_add_mac(wif, macl) < 0) {
4073210502Ssyrinx		wlan_mac_free_mac(macl);
4074210502Ssyrinx		return (SNMP_ERR_GENERR);
4075210502Ssyrinx	}
4076210502Ssyrinx
4077210502Ssyrinx	ctx->scratch->int1 = RowStatus_destroy;
4078210502Ssyrinx	if (wlan_add_mac_acl_mac(wif, macl) < 0) {
4079210502Ssyrinx		(void)wlan_mac_delete_mac(wif, macl);
4080210502Ssyrinx		return (SNMP_ERR_GENERR);
4081210502Ssyrinx	}
4082210502Ssyrinx
4083210502Ssyrinx	return (SNMP_ERR_NOERROR);
4084210502Ssyrinx}
4085210502Ssyrinx
4086210502Ssyrinx/*
4087210502Ssyrinx * Wireless interfaces operating as mesh points.
4088210502Ssyrinx */
4089210502Ssyrinxstatic struct wlan_iface *
4090210502Ssyrinxwlan_mesh_first_interface(void)
4091210502Ssyrinx{
4092210502Ssyrinx	struct wlan_iface *wif;
4093210502Ssyrinx
4094210502Ssyrinx	SLIST_FOREACH(wif, &wlan_ifaces, w_if)
4095210502Ssyrinx		if (wif->mode == WlanIfaceOperatingModeType_meshPoint &&
4096210502Ssyrinx		    wif->status == RowStatus_active)
4097210502Ssyrinx			break;
4098210502Ssyrinx
4099210502Ssyrinx	return (wif);
4100210502Ssyrinx}
4101210502Ssyrinx
4102210502Ssyrinxstatic struct wlan_iface *
4103210502Ssyrinxwlan_mesh_next_interface(struct wlan_iface *wif)
4104210502Ssyrinx{
4105210502Ssyrinx	struct wlan_iface *nwif;
4106210502Ssyrinx
4107210502Ssyrinx	while ((nwif = wlan_next_interface(wif)) != NULL) {
4108210502Ssyrinx		if (nwif->mode == WlanIfaceOperatingModeType_meshPoint &&
4109210502Ssyrinx		    nwif->status == RowStatus_active)
4110210502Ssyrinx			break;
4111210502Ssyrinx		wif = nwif;
4112210502Ssyrinx	}
4113210502Ssyrinx
4114210502Ssyrinx	return (nwif);
4115210502Ssyrinx}
4116210502Ssyrinx
4117210502Ssyrinxstatic struct wlan_iface *
4118210502Ssyrinxwlan_mesh_get_iface(const struct asn_oid *oid, uint sub)
4119210502Ssyrinx{
4120210502Ssyrinx	struct wlan_iface *wif;
4121210502Ssyrinx
4122210502Ssyrinx	if ((wif = wlan_get_interface(oid, sub)) == NULL)
4123210502Ssyrinx		return (NULL);
4124210502Ssyrinx
4125210502Ssyrinx	if (wif->mode != WlanIfaceOperatingModeType_meshPoint)
4126210502Ssyrinx		return (NULL);
4127210502Ssyrinx
4128210502Ssyrinx	return (wif);
4129210502Ssyrinx}
4130210502Ssyrinx
4131210502Ssyrinxstatic struct wlan_iface *
4132210502Ssyrinxwlan_mesh_get_next_iface(const struct asn_oid *oid, uint sub)
4133210502Ssyrinx{
4134210502Ssyrinx	uint32_t i;
4135210502Ssyrinx	uint8_t wname[IFNAMSIZ];
4136210502Ssyrinx	struct wlan_iface *wif;
4137210502Ssyrinx
4138210502Ssyrinx	if (oid->len - sub == 0)
4139210502Ssyrinx		return (wlan_mesh_first_interface());
4140210502Ssyrinx
4141210502Ssyrinx	if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
4142210502Ssyrinx		return (NULL);
4143210502Ssyrinx
4144210502Ssyrinx	memset(wname, 0, IFNAMSIZ);
4145210502Ssyrinx	for (i = 0; i < oid->subs[sub]; i++)
4146210502Ssyrinx		wname[i] = oid->subs[sub + i + 1];
4147210502Ssyrinx	wname[i] = '\0';
4148210502Ssyrinx
4149210502Ssyrinx	if ((wif = wlan_find_interface(wname)) == NULL)
4150210502Ssyrinx		return (NULL);
4151210502Ssyrinx
4152210502Ssyrinx	return (wlan_mesh_next_interface(wif));
4153210502Ssyrinx}
4154210502Ssyrinx
4155210502Ssyrinx/*
4156210502Ssyrinx * The neighbors of wireless interfaces operating as mesh points.
4157210502Ssyrinx */
4158210502Ssyrinxstatic struct wlan_peer *
4159210502Ssyrinxwlan_mesh_get_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
4160210502Ssyrinx{
4161210502Ssyrinx	char wname[IFNAMSIZ];
4162210502Ssyrinx	uint8_t pmac[IEEE80211_ADDR_LEN];
4163210502Ssyrinx
4164210502Ssyrinx	if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0)
4165210502Ssyrinx		return (NULL);
4166210502Ssyrinx
4167210502Ssyrinx	if ((*wif = wlan_find_interface(wname)) == NULL ||
4168210502Ssyrinx	    (*wif)->mode != WlanIfaceOperatingModeType_meshPoint)
4169210502Ssyrinx		return (NULL);
4170210502Ssyrinx
4171210502Ssyrinx	return (wlan_find_peer(*wif, pmac));
4172210502Ssyrinx}
4173210502Ssyrinx
4174210502Ssyrinxstatic struct wlan_peer *
4175210502Ssyrinxwlan_mesh_get_next_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
4176210502Ssyrinx{
4177210502Ssyrinx	char wname[IFNAMSIZ];
4178210502Ssyrinx	char pmac[IEEE80211_ADDR_LEN];
4179210502Ssyrinx	struct wlan_peer *wip;
4180210502Ssyrinx
4181210502Ssyrinx	if (oid->len - sub == 0) {
4182210502Ssyrinx		for (*wif = wlan_mesh_first_interface(); *wif != NULL;
4183210502Ssyrinx		    *wif = wlan_mesh_next_interface(*wif)) {
4184210502Ssyrinx			wip = SLIST_FIRST(&(*wif)->peerlist);
4185210502Ssyrinx			if (wip != NULL)
4186210502Ssyrinx				return (wip);
4187210502Ssyrinx		}
4188210502Ssyrinx		return (NULL);
4189210502Ssyrinx	}
4190210502Ssyrinx
4191210502Ssyrinx	if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0 ||
4192210502Ssyrinx	    (*wif = wlan_find_interface(wname)) == NULL ||
4193210502Ssyrinx	    (*wif)->mode != WlanIfaceOperatingModeType_meshPoint ||
4194210502Ssyrinx	    (wip = wlan_find_peer(*wif, pmac)) == NULL)
4195210502Ssyrinx		return (NULL);
4196210502Ssyrinx
4197210502Ssyrinx	if ((wip = SLIST_NEXT(wip, wp)) != NULL)
4198210502Ssyrinx		return (wip);
4199210502Ssyrinx
4200210502Ssyrinx	while ((*wif = wlan_mesh_next_interface(*wif)) != NULL)
4201210502Ssyrinx		if ((wip = SLIST_FIRST(&(*wif)->peerlist)) != NULL)
4202210502Ssyrinx			break;
4203210502Ssyrinx
4204210502Ssyrinx	return (wip);
4205210502Ssyrinx}
4206210502Ssyrinx
4207210502Ssyrinx/*
4208210502Ssyrinx * Mesh routing table.
4209210502Ssyrinx */
4210210502Ssyrinxstatic void
4211210502Ssyrinxwlan_mesh_free_routes(struct wlan_iface *wif)
4212210502Ssyrinx{
4213210502Ssyrinx	struct wlan_mesh_route *wmr;
4214210502Ssyrinx
4215210502Ssyrinx	while ((wmr = SLIST_FIRST(&wif->mesh_routelist)) != NULL) {
4216210502Ssyrinx		SLIST_REMOVE_HEAD(&wif->mesh_routelist, wr);
4217210502Ssyrinx		free(wmr);
4218210502Ssyrinx	}
4219210502Ssyrinx
4220210502Ssyrinx	SLIST_INIT(&wif->mesh_routelist);
4221210502Ssyrinx}
4222210502Ssyrinx
4223210502Ssyrinxstatic struct wlan_mesh_route *
4224210502Ssyrinxwlan_mesh_find_route(struct wlan_iface *wif, uint8_t *dstmac)
4225210502Ssyrinx{
4226210502Ssyrinx	struct wlan_mesh_route *wmr;
4227210502Ssyrinx
4228210502Ssyrinx	if (wif->mode != WlanIfaceOperatingModeType_meshPoint)
4229210502Ssyrinx		return (NULL);
4230210502Ssyrinx
4231210502Ssyrinx	SLIST_FOREACH(wmr, &wif->mesh_routelist, wr)
4232210502Ssyrinx		if (memcmp(wmr->imroute.imr_dest, dstmac,
4233210502Ssyrinx		    IEEE80211_ADDR_LEN) == 0)
4234210502Ssyrinx			break;
4235210502Ssyrinx
4236210502Ssyrinx	return (wmr);
4237210502Ssyrinx}
4238210502Ssyrinx
4239210502Ssyrinxstruct wlan_mesh_route *
4240210502Ssyrinxwlan_mesh_new_route(const uint8_t *dstmac)
4241210502Ssyrinx{
4242210502Ssyrinx	struct wlan_mesh_route *wmr;
4243210502Ssyrinx
4244210502Ssyrinx	if ((wmr = (struct wlan_mesh_route *)malloc(sizeof(*wmr))) == NULL)
4245210502Ssyrinx		return (NULL);
4246210502Ssyrinx
4247210502Ssyrinx	memset(wmr, 0, sizeof(*wmr));
4248210502Ssyrinx	memcpy(wmr->imroute.imr_dest, dstmac, IEEE80211_ADDR_LEN);
4249210502Ssyrinx	wmr->mroute_status = RowStatus_notReady;
4250210502Ssyrinx
4251210502Ssyrinx	return (wmr);
4252210502Ssyrinx}
4253210502Ssyrinx
4254210502Ssyrinxvoid
4255210502Ssyrinxwlan_mesh_free_route(struct wlan_mesh_route *wmr)
4256210502Ssyrinx{
4257210502Ssyrinx	free(wmr);
4258210502Ssyrinx}
4259210502Ssyrinx
4260210502Ssyrinxint
4261210502Ssyrinxwlan_mesh_add_rtentry(struct wlan_iface *wif, struct wlan_mesh_route *wmr)
4262210502Ssyrinx{
4263210502Ssyrinx	struct wlan_mesh_route *temp, *prev;
4264210502Ssyrinx
4265210502Ssyrinx	SLIST_FOREACH(temp, &wif->mesh_routelist, wr)
4266210502Ssyrinx		if (memcmp(temp->imroute.imr_dest, wmr->imroute.imr_dest,
4267210502Ssyrinx		    IEEE80211_ADDR_LEN) == 0)
4268210502Ssyrinx			return (-1);
4269210502Ssyrinx
4270210502Ssyrinx	if ((prev = SLIST_FIRST(&wif->mesh_routelist)) == NULL ||
4271210502Ssyrinx	    memcmp(wmr->imroute.imr_dest, prev->imroute.imr_dest,
4272210502Ssyrinx	    IEEE80211_ADDR_LEN) < 0) {
4273210502Ssyrinx	    	SLIST_INSERT_HEAD(&wif->mesh_routelist, wmr, wr);
4274210502Ssyrinx	    	return (0);
4275210502Ssyrinx	}
4276210502Ssyrinx
4277210502Ssyrinx	SLIST_FOREACH(temp, &wif->mesh_routelist, wr) {
4278210502Ssyrinx		if (memcmp(wmr->imroute.imr_dest, temp->imroute.imr_dest,
4279210502Ssyrinx		    IEEE80211_ADDR_LEN) < 0)
4280210502Ssyrinx			break;
4281210502Ssyrinx		prev = temp;
4282210502Ssyrinx	}
4283210502Ssyrinx
4284210502Ssyrinx	SLIST_INSERT_AFTER(prev, wmr, wr);
4285210502Ssyrinx	return (0);
4286210502Ssyrinx}
4287210502Ssyrinx
4288210502Ssyrinxstatic int
4289210502Ssyrinxwlan_mesh_delete_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr)
4290210502Ssyrinx{
4291210502Ssyrinx	if (wmr->mroute_status == RowStatus_active &&
4292210502Ssyrinx	    wlan_mesh_del_route(wif, wmr) < 0)
4293210502Ssyrinx		return (-1);
4294210502Ssyrinx
4295210502Ssyrinx	SLIST_REMOVE(&wif->mesh_routelist, wmr, wlan_mesh_route, wr);
4296210502Ssyrinx	free(wmr);
4297210502Ssyrinx
4298210502Ssyrinx	return (0);
4299210502Ssyrinx}
4300210502Ssyrinx
4301210502Ssyrinxstatic void
4302210502Ssyrinxwlan_mesh_update_routes(void)
4303210502Ssyrinx{
4304210502Ssyrinx	struct wlan_iface *wif;
4305210502Ssyrinx	struct wlan_mesh_route *wmr, *twmr;
4306210502Ssyrinx
4307210502Ssyrinx	if ((time(NULL) - wlan_mrlist_age) <= WLAN_LIST_MAXAGE)
4308210502Ssyrinx		return;
4309210502Ssyrinx
4310210502Ssyrinx	for (wif = wlan_mesh_first_interface(); wif != NULL;
4311210502Ssyrinx	    wif = wlan_mesh_next_interface(wif)) {
4312210502Ssyrinx		/*
4313210502Ssyrinx		 * Nuke old entries - XXX - they are likely not to
4314210502Ssyrinx		 * change often - reconsider.
4315210502Ssyrinx		 */
4316210502Ssyrinx		SLIST_FOREACH_SAFE(wmr, &wif->mesh_routelist, wr, twmr)
4317210502Ssyrinx			if (wmr->mroute_status == RowStatus_active) {
4318210502Ssyrinx				SLIST_REMOVE(&wif->mesh_routelist, wmr,
4319210502Ssyrinx				    wlan_mesh_route, wr);
4320210502Ssyrinx				wlan_mesh_free_route(wmr);
4321210502Ssyrinx			}
4322210502Ssyrinx		(void)wlan_mesh_get_routelist(wif);
4323210502Ssyrinx	}
4324210502Ssyrinx	wlan_mrlist_age = time(NULL);
4325210502Ssyrinx}
4326210502Ssyrinx
4327210502Ssyrinxstatic struct wlan_mesh_route *
4328210502Ssyrinxwlan_mesh_get_route(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)
4329210502Ssyrinx{
4330210502Ssyrinx	char wname[IFNAMSIZ];
4331210502Ssyrinx	char dstmac[IEEE80211_ADDR_LEN];
4332210502Ssyrinx
4333210502Ssyrinx	if (wlan_mac_index_decode(oid, sub, wname, dstmac) < 0)
4334210502Ssyrinx		return (NULL);
4335210502Ssyrinx
4336210502Ssyrinx	if ((*wif = wlan_find_interface(wname)) == NULL)
4337210502Ssyrinx		return (NULL);
4338210502Ssyrinx
4339210502Ssyrinx	return (wlan_mesh_find_route(*wif, dstmac));
4340210502Ssyrinx}
4341210502Ssyrinx
4342210502Ssyrinxstatic struct wlan_mesh_route *
4343210502Ssyrinxwlan_mesh_get_next_route(const struct asn_oid *oid, uint sub,
4344210502Ssyrinx    struct wlan_iface **wif)
4345210502Ssyrinx{
4346210502Ssyrinx	char wname[IFNAMSIZ];
4347210502Ssyrinx	char dstmac[IEEE80211_ADDR_LEN];
4348210502Ssyrinx	struct wlan_mesh_route *wmr;
4349210502Ssyrinx
4350210502Ssyrinx	if (oid->len - sub == 0) {
4351210502Ssyrinx		for (*wif = wlan_mesh_first_interface(); *wif != NULL;
4352210502Ssyrinx		    *wif = wlan_mesh_next_interface(*wif)) {
4353210502Ssyrinx			wmr = SLIST_FIRST(&(*wif)->mesh_routelist);
4354210502Ssyrinx			if (wmr != NULL)
4355210502Ssyrinx				return (wmr);
4356210502Ssyrinx		}
4357210502Ssyrinx		return (NULL);
4358210502Ssyrinx	}
4359210502Ssyrinx
4360210502Ssyrinx	if (wlan_mac_index_decode(oid, sub, wname, dstmac) < 0 ||
4361210502Ssyrinx	    (*wif = wlan_find_interface(wname)) == NULL ||
4362210502Ssyrinx	    (wmr = wlan_mesh_find_route(*wif, dstmac)) == NULL)
4363210502Ssyrinx		return (NULL);
4364210502Ssyrinx
4365210502Ssyrinx	if ((wmr = SLIST_NEXT(wmr, wr)) != NULL)
4366210502Ssyrinx		return (wmr);
4367210502Ssyrinx
4368210502Ssyrinx	while ((*wif = wlan_mesh_next_interface(*wif)) != NULL)
4369210502Ssyrinx		if ((wmr = SLIST_FIRST(&(*wif)->mesh_routelist)) != NULL)
4370210502Ssyrinx			break;
4371210502Ssyrinx
4372210502Ssyrinx	return (wmr);
4373210502Ssyrinx}
4374210502Ssyrinx
4375210502Ssyrinxstatic int
4376210502Ssyrinxwlan_mesh_route_set_status(struct snmp_context *ctx, struct snmp_value *val,
4377210502Ssyrinx    uint sub)
4378210502Ssyrinx{
4379210502Ssyrinx	char wname[IFNAMSIZ];
4380210502Ssyrinx	char mac[IEEE80211_ADDR_LEN];
4381210502Ssyrinx	struct wlan_mesh_route *wmr;
4382210502Ssyrinx	struct wlan_iface *wif;
4383210502Ssyrinx
4384210502Ssyrinx	if (wlan_mac_index_decode(&val->var, sub, wname, mac) < 0)
4385210502Ssyrinx		return (SNMP_ERR_GENERR);
4386210502Ssyrinx	wmr = wlan_mesh_get_route(&val->var, sub, &wif);
4387210502Ssyrinx
4388210502Ssyrinx	switch (val->v.integer) {
4389210502Ssyrinx	case RowStatus_createAndGo:
4390210502Ssyrinx		if (wmr != NULL)
4391210502Ssyrinx			return (SNMP_ERR_INCONS_NAME);
4392210502Ssyrinx		break;
4393210502Ssyrinx	case RowStatus_destroy:
4394210502Ssyrinx		if (wmr == NULL)
4395210502Ssyrinx			return (SNMP_ERR_NOSUCHNAME);
4396210502Ssyrinx		ctx->scratch->int1 = RowStatus_active;
4397210502Ssyrinx		return (SNMP_ERR_NOERROR);
4398210502Ssyrinx	default:
4399210502Ssyrinx		return (SNMP_ERR_INCONS_VALUE);
4400210502Ssyrinx	}
4401210502Ssyrinx
4402210502Ssyrinx	if ((wif = wlan_find_interface(wname)) == NULL)
4403210502Ssyrinx		return (SNMP_ERR_INCONS_NAME);
4404210502Ssyrinx
4405210502Ssyrinx	if ((wmr = wlan_mesh_new_route(mac)) == NULL)
4406210502Ssyrinx		return (SNMP_ERR_GENERR);
4407210502Ssyrinx
4408210502Ssyrinx	if (wlan_mesh_add_rtentry(wif, wmr) < 0) {
4409210502Ssyrinx		wlan_mesh_free_route(wmr);
4410210502Ssyrinx		return (SNMP_ERR_GENERR);
4411210502Ssyrinx	}
4412210502Ssyrinx
4413210502Ssyrinx	ctx->scratch->int1 = RowStatus_destroy;
4414210502Ssyrinx	if (wlan_mesh_add_route(wif, wmr) < 0) {
4415210502Ssyrinx		(void)wlan_mesh_delete_route(wif, wmr);
4416210502Ssyrinx		return (SNMP_ERR_GENERR);
4417210502Ssyrinx	}
4418210502Ssyrinx
4419210502Ssyrinx	return (SNMP_ERR_NOERROR);
4420210502Ssyrinx}
4421210502Ssyrinx
4422210502Ssyrinx/*
4423210502Ssyrinx * Wlan snmp module initialization hook.
4424210502Ssyrinx * Returns 0 on success, < 0 on error.
4425210502Ssyrinx */
4426210502Ssyrinxstatic int
4427210502Ssyrinxwlan_init(struct lmodule * mod __unused, int argc __unused,
4428210502Ssyrinx     char *argv[] __unused)
4429210502Ssyrinx{
4430210502Ssyrinx	if (wlan_kmodules_load() < 0)
4431210502Ssyrinx		return (-1);
4432210502Ssyrinx
4433210502Ssyrinx	if (wlan_ioctl_init() < 0)
4434210502Ssyrinx		return (-1);
4435210502Ssyrinx
4436210502Ssyrinx	/* Register for new interface creation notifications. */
4437210502Ssyrinx	if (mib_register_newif(wlan_attach_newif, wlan_module)) {
4438210502Ssyrinx		syslog(LOG_ERR, "Cannot register newif function: %s",
4439210502Ssyrinx		    strerror(errno));
4440210502Ssyrinx		return (-1);
4441210502Ssyrinx	}
4442210502Ssyrinx
4443210502Ssyrinx	return (0);
4444210502Ssyrinx}
4445210502Ssyrinx
4446210502Ssyrinx/*
4447210502Ssyrinx * Wlan snmp module finalization hook.
4448210502Ssyrinx */
4449210502Ssyrinxstatic int
4450210502Ssyrinxwlan_fini(void)
4451210502Ssyrinx{
4452210502Ssyrinx	mib_unregister_newif(wlan_module);
4453210502Ssyrinx	or_unregister(reg_wlan);
4454210502Ssyrinx
4455210502Ssyrinx	/* XXX: Cleanup! */
4456210502Ssyrinx	wlan_free_iflist();
4457210502Ssyrinx
4458210502Ssyrinx	return (0);
4459210502Ssyrinx}
4460210502Ssyrinx
4461210502Ssyrinx/*
4462210502Ssyrinx * Refetch all available data from the kernel.
4463210502Ssyrinx */
4464210502Ssyrinxstatic void
4465210502Ssyrinxwlan_update_data(void *arg __unused)
4466210502Ssyrinx{
4467210502Ssyrinx}
4468210502Ssyrinx
4469210502Ssyrinx/*
4470210502Ssyrinx * Wlan snmp module start operation.
4471210502Ssyrinx */
4472210502Ssyrinxstatic void
4473210502Ssyrinxwlan_start(void)
4474210502Ssyrinx{
4475210502Ssyrinx	struct mibif *ifp;
4476210502Ssyrinx
4477210502Ssyrinx	reg_wlan = or_register(&oid_wlan,
4478210502Ssyrinx	    "The MIB module for managing wireless networking.", wlan_module);
4479210502Ssyrinx
4480210502Ssyrinx	 /* Add the existing wlan interfaces. */
4481210502Ssyrinx	 for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp))
4482210502Ssyrinx		wlan_attach_newif(ifp);
4483210502Ssyrinx
4484210502Ssyrinx	wlan_data_timer = timer_start_repeat(wlan_poll_ticks,
4485210502Ssyrinx	    wlan_poll_ticks, wlan_update_data, NULL, wlan_module);
4486210502Ssyrinx}
4487210502Ssyrinx
4488210502Ssyrinx/*
4489210502Ssyrinx * Dump the Wlan snmp module data on SIGUSR1.
4490210502Ssyrinx */
4491210502Ssyrinxstatic void
4492210502Ssyrinxwlan_dump(void)
4493210502Ssyrinx{
4494210502Ssyrinx	/* XXX: Print some debug info to syslog. */
4495210502Ssyrinx	struct wlan_iface *wif;
4496210502Ssyrinx
4497210502Ssyrinx	for (wif = wlan_first_interface(); wif != NULL;
4498210502Ssyrinx	    wif = wlan_next_interface(wif))
4499210502Ssyrinx		syslog(LOG_ERR, "wlan iface %s", wif->wname);
4500210502Ssyrinx}
4501210502Ssyrinx
4502210502Ssyrinxconst char wlan_comment[] = \
4503210502Ssyrinx"This module implements the BEGEMOT MIB for wireless networking.";
4504210502Ssyrinx
4505210502Ssyrinxconst struct snmp_module config = {
4506210502Ssyrinx	.comment =	wlan_comment,
4507210502Ssyrinx	.init =		wlan_init,
4508210502Ssyrinx	.fini =		wlan_fini,
4509210502Ssyrinx	.start =	wlan_start,
4510210502Ssyrinx	.tree =		wlan_ctree,
4511210502Ssyrinx	.dump =		wlan_dump,
4512210502Ssyrinx	.tree_size =	wlan_CTREE_SIZE,
4513210502Ssyrinx};
4514