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