]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/bsnmpd/modules/snmp_wlan/wlan_snmp.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / bsnmpd / modules / snmp_wlan / wlan_snmp.c
1 /*-
2  * Copyright (c) 2010 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Shteryana Sotirova Shopova under
6  * sponsorship from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31
32 #include <sys/queue.h>
33 #include <sys/socket.h>
34 #include <sys/types.h>
35
36 #include <net/if.h>
37 #include <net/if_media.h>
38 #include <net/if_mib.h>
39 #include <net/if_types.h>
40 #include <net80211/ieee80211.h>
41 #include <net80211/ieee80211_ioctl.h>
42
43 #include <errno.h>
44 #include <stdarg.h>
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <syslog.h>
49
50 #include <bsnmp/snmpmod.h>
51 #include <bsnmp/snmp_mibII.h>
52
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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 *
2843 wlan_first_interface(void)
2844 {
2845         return (SLIST_FIRST(&wlan_ifaces));
2846 }
2847
2848 static struct wlan_iface *
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
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 *
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
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
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
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
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
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
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
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 *
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 *
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 *
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 *
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 *
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
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
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
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
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
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 *
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 *
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
3268 wlan_free_peer(struct wlan_peer *wip)
3269 {
3270         free(wip);
3271 }
3272
3273 int
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
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 *
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 *
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
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
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
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
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 *
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 *
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 *
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
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 *
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 *
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
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 *
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 *
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
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 *
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 *
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
3694 wlan_scan_free_result(struct wlan_scan_result *sr)
3695 {
3696         free(sr);
3697 }
3698
3699 static int
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
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
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
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
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 *
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 *
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
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 *
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 *
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
3917 wlan_mac_free_mac(struct wlan_mac_mac *wmm)
3918 {
3919         free(wmm);
3920 }
3921
3922 int
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
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
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 *
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 *
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
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 *
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 *
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 *
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 *
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 *
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 *
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
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 *
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 *
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
4255 wlan_mesh_free_route(struct wlan_mesh_route *wmr)
4256 {
4257         free(wmr);
4258 }
4259
4260 int
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
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
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 *
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 *
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
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
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
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
4465 wlan_update_data(void *arg __unused)
4466 {
4467 }
4468
4469 /*
4470  * Wlan snmp module start operation.
4471  */
4472 static 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
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 };