Path: blob/main/usr.sbin/bsnmpd/modules/snmp_wlan/wlan_snmp.c
108394 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2010 The FreeBSD Foundation4*5* This software was developed by Shteryana Sotirova Shopova under6* sponsorship from the FreeBSD Foundation.7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions10* are met:11* 1. Redistributions of source code must retain the above copyright12* notice, this list of conditions and the following disclaimer.13* 2. Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in the15* documentation and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND18* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE21* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT25* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY26* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF27* SUCH DAMAGE.28*/2930#include <sys/queue.h>31#include <sys/socket.h>32#include <sys/types.h>3334#include <net/if.h>35#include <net/if_media.h>36#include <net/if_mib.h>37#include <net/if_types.h>38#include <net80211/ieee80211.h>39#include <net80211/ieee80211_ioctl.h>4041#include <errno.h>42#include <stdarg.h>43#include <stdlib.h>44#include <stdio.h>45#include <string.h>46#include <syslog.h>4748#include <bsnmp/snmpmod.h>49#include <bsnmp/snmp_mibII.h>5051#define SNMPTREE_TYPES52#include "wlan_tree.h"53#include "wlan_snmp.h"54#include "wlan_oid.h"5556static struct lmodule *wlan_module;5758/* For the registration. */59static const struct asn_oid oid_wlan = OIDX_begemotWlan;60/* The registration. */61static uint reg_wlan;6263/* Periodic timer for polling the module's data. */64static void *wlan_data_timer;6566/*67* Poll data from kernel every 15 minutes unless explicitly requested by an68* SNMP client.69* XXX: make that configurable.70*/71static int wlan_poll_ticks = (15 * 60) * 100;7273/* The age of each table. */74#define WLAN_LIST_MAXAGE 57576static time_t wlan_iflist_age;77static time_t wlan_peerlist_age;78static time_t wlan_chanlist_age;79static time_t wlan_roamlist_age;80static time_t wlan_tx_paramlist_age;81static time_t wlan_scanlist_age;82static time_t wlan_maclist_age;83static time_t wlan_mrlist_age;8485/*86* The list of all virtual wireless interfaces - sorted by name.87*/88SLIST_HEAD(wlan_ifaces, wlan_iface);89static struct wlan_ifaces wlan_ifaces = SLIST_HEAD_INITIALIZER(wlan_ifaces);9091static struct wlan_config wlan_config;9293/* Forward declarations */94static int bits_get(struct snmp_value *, const u_char *, ssize_t);9596static int wlan_add_wif(struct wlan_iface *);97static void wlan_delete_wif(struct wlan_iface *);98static int wlan_attach_newif(struct mibif *);99static int wlan_iface_create(struct wlan_iface *);100static int wlan_iface_destroy(struct wlan_iface *);101static struct wlan_iface * wlan_new_wif(char *);102103static void wlan_free_interface(struct wlan_iface *);104static void wlan_free_iflist(void);105static void wlan_free_peerlist(struct wlan_iface *);106static void wlan_scan_free_results(struct wlan_iface *);107static void wlan_mac_free_maclist(struct wlan_iface *);108static void wlan_mesh_free_routes(struct wlan_iface *);109110static int wlan_update_interface(struct wlan_iface *);111static void wlan_update_interface_list(void);112static void wlan_update_peers(void);113static void wlan_update_channels(void);114static void wlan_update_roam_params(void);115static void wlan_update_tx_params(void);116static void wlan_scan_update_results(void);117static void wlan_mac_update_aclmacs(void);118static void wlan_mesh_update_routes(void);119120static struct wlan_iface * wlan_find_interface(const char *);121static struct wlan_peer * wlan_find_peer(struct wlan_iface *, uint8_t *);122static struct ieee80211_channel* wlan_find_channel(struct wlan_iface *,123uint32_t);124static struct wlan_scan_result * wlan_scan_find_result(struct wlan_iface *,125uint8_t *, uint8_t *);126static struct wlan_mac_mac * wlan_mac_find_mac(struct wlan_iface *,127uint8_t *);128static struct wlan_mesh_route * wlan_mesh_find_route(struct wlan_iface *,129uint8_t *);130131static struct wlan_iface * wlan_first_interface(void);132static struct wlan_iface * wlan_next_interface(struct wlan_iface *);133static struct wlan_iface * wlan_mesh_first_interface(void);134static struct wlan_iface * wlan_mesh_next_interface(struct wlan_iface *);135136static struct wlan_iface * wlan_get_interface(const struct asn_oid *, uint);137static struct wlan_iface * wlan_get_snmp_interface(const struct asn_oid *,138uint);139static struct wlan_peer * wlan_get_peer(const struct asn_oid *, uint,140struct wlan_iface **);141static struct ieee80211_channel *wlan_get_channel(const struct asn_oid *, uint,142struct wlan_iface **);143static struct ieee80211_roamparam *wlan_get_roam_param(const struct asn_oid *,144uint, struct wlan_iface **);145static struct ieee80211_txparam *wlan_get_tx_param(const struct asn_oid *,146uint, struct wlan_iface **, uint32_t *);147static struct wlan_scan_result *wlan_get_scanr(const struct asn_oid *, uint,148struct wlan_iface **);149static struct wlan_mac_mac * wlan_get_acl_mac(const struct asn_oid *,150uint, struct wlan_iface **);151static struct wlan_iface * wlan_mesh_get_iface(const struct asn_oid *, uint);152static struct wlan_peer * wlan_mesh_get_peer(const struct asn_oid *, uint,153struct wlan_iface **);154static struct wlan_mesh_route * wlan_mesh_get_route(const struct asn_oid *,155uint, struct wlan_iface **);156157static struct wlan_iface * wlan_get_next_interface(const struct asn_oid *,158uint);159static struct wlan_iface * wlan_get_next_snmp_interface(const struct160asn_oid *, uint);161static struct wlan_peer * wlan_get_next_peer(const struct asn_oid *, uint,162struct wlan_iface **);163static struct ieee80211_channel *wlan_get_next_channel(const struct asn_oid *,164uint, struct wlan_iface **);165static struct ieee80211_roamparam *wlan_get_next_roam_param(const struct166asn_oid *, uint sub, struct wlan_iface **, uint32_t *);167static struct ieee80211_txparam *wlan_get_next_tx_param(const struct asn_oid *,168uint, struct wlan_iface **, uint32_t *);169static struct wlan_scan_result *wlan_get_next_scanr(const struct asn_oid *,170uint , struct wlan_iface **);171static struct wlan_mac_mac * wlan_get_next_acl_mac(const struct asn_oid *,172uint, struct wlan_iface **);173static struct wlan_iface * wlan_mesh_get_next_iface(const struct asn_oid *,174uint);175static struct wlan_peer * wlan_mesh_get_next_peer(const struct asn_oid *,176uint, struct wlan_iface **);177static struct wlan_mesh_route * wlan_mesh_get_next_route(const struct asn_oid *,178uint sub, struct wlan_iface **);179180static uint8_t *wlan_get_ifname(const struct asn_oid *, uint, uint8_t *);181static int wlan_mac_index_decode(const struct asn_oid *, uint, char *,182uint8_t *);183static int wlan_channel_index_decode(const struct asn_oid *, uint,184char *, uint32_t *);185static int wlan_phy_index_decode(const struct asn_oid *, uint, char *,186uint32_t *);187static int wlan_scanr_index_decode(const struct asn_oid *oid, uint sub,188char *wname, uint8_t *ssid, uint8_t *bssid);189190static void wlan_append_ifindex(struct asn_oid *, uint,191const struct wlan_iface *);192static void wlan_append_mac_index(struct asn_oid *, uint, char *, uint8_t *);193static void wlan_append_channel_index(struct asn_oid *, uint,194const struct wlan_iface *, const struct ieee80211_channel *);195static void wlan_append_phy_index(struct asn_oid *, uint, char *, uint32_t);196static void wlan_append_scanr_index(struct asn_oid *, uint, char *,197uint8_t *, uint8_t *);198199static int wlan_acl_mac_set_status(struct snmp_context *,200struct snmp_value *, uint);201static int wlan_mesh_route_set_status(struct snmp_context *,202struct snmp_value *, uint);203204static int32_t wlan_get_channel_type(struct ieee80211_channel *);205static int wlan_scan_compare_result(struct wlan_scan_result *,206struct wlan_scan_result *);207static int wlan_mac_delete_mac(struct wlan_iface *, struct wlan_mac_mac *);208static int wlan_mesh_delete_route(struct wlan_iface *,209struct wlan_mesh_route *);210211/*212* The module's GET/SET data hooks per each table or group of objects as213* required by bsnmpd(1).214*/215int216op_wlan_iface(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,217uint32_t iidx __unused, enum snmp_op op)218{219int rc;220char wname[IFNAMSIZ];221struct wlan_iface *wif;222223wlan_update_interface_list();224225switch (op) {226case SNMP_OP_GET:227if ((wif = wlan_get_snmp_interface(&val->var, sub)) == NULL)228return (SNMP_ERR_NOSUCHNAME);229break;230231case SNMP_OP_GETNEXT:232if ((wif = wlan_get_next_snmp_interface(&val->var, sub)) == NULL)233return (SNMP_ERR_NOSUCHNAME);234wlan_append_ifindex(&val->var, sub, wif);235break;236237case SNMP_OP_SET:238if ((wif = wlan_get_snmp_interface(&val->var, sub)) == NULL) {239if (val->var.subs[sub - 1] != LEAF_wlanIfaceName)240return (SNMP_ERR_NOSUCHNAME);241if (wlan_get_ifname(&val->var, sub, wname) == NULL)242return (SNMP_ERR_INCONS_VALUE);243if ((wif = wlan_new_wif(wname)) == NULL)244return (SNMP_ERR_GENERR);245wif->internal = 1;246}247if (wif->status == RowStatus_active &&248val->var.subs[sub - 1] != LEAF_wlanIfaceStatus &&249val->var.subs[sub - 1] != LEAF_wlanIfaceState)250return (SNMP_ERR_INCONS_VALUE);251252switch (val->var.subs[sub - 1]) {253case LEAF_wlanIfaceIndex:254return (SNMP_ERR_NOT_WRITEABLE);255256case LEAF_wlanIfaceName:257if (val->v.octetstring.len >= IFNAMSIZ)258return (SNMP_ERR_INCONS_VALUE);259if ((ctx->scratch->ptr1 = malloc(IFNAMSIZ)) == NULL)260return (SNMP_ERR_GENERR);261strlcpy(ctx->scratch->ptr1, wif->wname, IFNAMSIZ);262memcpy(wif->wname, val->v.octetstring.octets,263val->v.octetstring.len);264wif->wname[val->v.octetstring.len] = '\0';265return (SNMP_ERR_NOERROR);266267case LEAF_wlanParentIfName:268if (val->v.octetstring.len >= IFNAMSIZ)269return (SNMP_ERR_INCONS_VALUE);270if ((ctx->scratch->ptr1 = malloc(IFNAMSIZ)) == NULL)271return (SNMP_ERR_GENERR);272strlcpy(ctx->scratch->ptr1, wif->pname, IFNAMSIZ);273memcpy(wif->pname, val->v.octetstring.octets,274val->v.octetstring.len);275wif->pname[val->v.octetstring.len] = '\0';276return (SNMP_ERR_NOERROR);277278case LEAF_wlanIfaceOperatingMode:279ctx->scratch->int1 = wif->mode;280wif->mode = val->v.integer;281return (SNMP_ERR_NOERROR);282283case LEAF_wlanIfaceFlags:284if (val->v.octetstring.len > sizeof(wif->flags))285return (SNMP_ERR_INCONS_VALUE);286ctx->scratch->ptr1 = malloc(sizeof(wif->flags));287if (ctx->scratch->ptr1 == NULL)288return (SNMP_ERR_GENERR);289memcpy(ctx->scratch->ptr1, (uint8_t *)&wif->flags,290sizeof(wif->flags));291memcpy((uint8_t *)&wif->flags, val->v.octetstring.octets,292sizeof(wif->flags));293return (SNMP_ERR_NOERROR);294295case LEAF_wlanIfaceBssid:296if (val->v.octetstring.len != IEEE80211_ADDR_LEN)297return (SNMP_ERR_INCONS_VALUE);298ctx->scratch->ptr1 = malloc(IEEE80211_ADDR_LEN);299if (ctx->scratch->ptr1 == NULL)300return (SNMP_ERR_GENERR);301memcpy(ctx->scratch->ptr1, wif->dbssid,302IEEE80211_ADDR_LEN);303memcpy(wif->dbssid, val->v.octetstring.octets,304IEEE80211_ADDR_LEN);305return (SNMP_ERR_NOERROR);306307case LEAF_wlanIfaceLocalAddress:308if (val->v.octetstring.len != IEEE80211_ADDR_LEN)309return (SNMP_ERR_INCONS_VALUE);310ctx->scratch->ptr1 = malloc(IEEE80211_ADDR_LEN);311if (ctx->scratch->ptr1 == NULL)312return (SNMP_ERR_GENERR);313memcpy(ctx->scratch->ptr1, wif->dlmac,314IEEE80211_ADDR_LEN);315memcpy(wif->dlmac, val->v.octetstring.octets,316IEEE80211_ADDR_LEN);317return (SNMP_ERR_NOERROR);318319case LEAF_wlanIfaceStatus:320ctx->scratch->int1 = wif->status;321wif->status = val->v.integer;322if (wif->status == RowStatus_active) {323rc = wlan_iface_create(wif); /* XXX */324if (rc != SNMP_ERR_NOERROR) {325wif->status = ctx->scratch->int1;326return (rc);327}328} else if (wif->status == RowStatus_destroy)329return (wlan_iface_destroy(wif));330else331wif->status = RowStatus_notReady;332return (SNMP_ERR_NOERROR);333334case LEAF_wlanIfaceState:335ctx->scratch->int1 = wif->state;336wif->state = val->v.integer;337if (wif->status == RowStatus_active)338if (wlan_config_state(wif, 1) < 0)339return (SNMP_ERR_GENERR);340return (SNMP_ERR_NOERROR);341}342abort();343344case SNMP_OP_ROLLBACK:345if ((wif = wlan_get_snmp_interface(&val->var, sub)) == NULL)346return (SNMP_ERR_NOSUCHNAME);347switch (val->var.subs[sub - 1]) {348case LEAF_wlanIfaceName:349strlcpy(wif->wname, ctx->scratch->ptr1, IFNAMSIZ);350free(ctx->scratch->ptr1);351break;352353case LEAF_wlanParentIfName:354strlcpy(wif->pname, ctx->scratch->ptr1, IFNAMSIZ);355free(ctx->scratch->ptr1);356break;357358case LEAF_wlanIfaceOperatingMode:359wif->mode = ctx->scratch->int1;360break;361362case LEAF_wlanIfaceFlags:363memcpy((uint8_t *)&wif->flags, ctx->scratch->ptr1,364sizeof(wif->flags));365free(ctx->scratch->ptr1);366break;367368case LEAF_wlanIfaceBssid:369memcpy(wif->dbssid, ctx->scratch->ptr1,370IEEE80211_ADDR_LEN);371free(ctx->scratch->ptr1);372break;373374case LEAF_wlanIfaceLocalAddress:375memcpy(wif->dlmac, ctx->scratch->ptr1,376IEEE80211_ADDR_LEN);377free(ctx->scratch->ptr1);378break;379380case LEAF_wlanIfaceStatus:381wif->status = ctx->scratch->int1;382if (ctx->scratch->int1 == RowStatus_active)383return (SNMP_ERR_GENERR); /* XXX: FIXME */384else if (wif->internal != 0)385return (wlan_iface_destroy(wif));386break;387388case LEAF_wlanIfaceState:389wif->state = ctx->scratch->int1;390if (wif->status == RowStatus_active)391if (wlan_config_state(wif, 1) < 0)392return (SNMP_ERR_GENERR);393break;394}395return (SNMP_ERR_NOERROR);396397case SNMP_OP_COMMIT:398switch (val->var.subs[sub - 1]) {399case LEAF_wlanIfaceName:400case LEAF_wlanParentIfName:401case LEAF_wlanIfaceFlags:402case LEAF_wlanIfaceBssid:403case LEAF_wlanIfaceLocalAddress:404free(ctx->scratch->ptr1);405/* FALLTHROUGH */406default:407return (SNMP_ERR_NOERROR);408}409default:410abort();411}412413switch (val->var.subs[sub - 1]) {414case LEAF_wlanIfaceIndex:415val->v.integer = wif->index;416return (SNMP_ERR_NOERROR);417case LEAF_wlanIfaceName:418return (string_get(val, wif->wname, -1));419case LEAF_wlanParentIfName:420return (string_get(val, wif->pname, -1));421case LEAF_wlanIfaceOperatingMode:422val->v.integer = wif->mode;423return (SNMP_ERR_NOERROR);424case LEAF_wlanIfaceFlags:425return (bits_get(val, (uint8_t *)&wif->flags,426sizeof(wif->flags)));427case LEAF_wlanIfaceBssid:428return (string_get(val, wif->dbssid, IEEE80211_ADDR_LEN));429case LEAF_wlanIfaceLocalAddress:430return (string_get(val, wif->dlmac, IEEE80211_ADDR_LEN));431case LEAF_wlanIfaceStatus:432val->v.integer = wif->status;433return (SNMP_ERR_NOERROR);434case LEAF_wlanIfaceState:435val->v.integer = wif->state;436return (SNMP_ERR_NOERROR);437}438439abort();440}441442int443op_wlan_if_parent(struct snmp_context *ctx __unused, struct snmp_value *val,444uint32_t sub, uint32_t iidx __unused, enum snmp_op op)445{446struct wlan_iface *wif;447448wlan_update_interface_list();449450switch (op) {451case SNMP_OP_GET:452if ((wif = wlan_get_interface(&val->var, sub)) == NULL)453return (SNMP_ERR_NOSUCHNAME);454break;455case SNMP_OP_GETNEXT:456if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)457return (SNMP_ERR_NOSUCHNAME);458wlan_append_ifindex(&val->var, sub, wif);459break;460case SNMP_OP_SET:461return (SNMP_ERR_NOT_WRITEABLE);462case SNMP_OP_COMMIT:463/* FALLTHROUGH */464case SNMP_OP_ROLLBACK:465/* FALLTHROUGH */466default:467abort();468}469470switch (val->var.subs[sub - 1]) {471case LEAF_wlanIfParentDriverCapabilities:472return (bits_get(val, (uint8_t *)&wif->drivercaps,473sizeof(wif->drivercaps)));474case LEAF_wlanIfParentCryptoCapabilities:475return (bits_get(val, (uint8_t *)&wif->cryptocaps,476sizeof(wif->cryptocaps)));477case LEAF_wlanIfParentHTCapabilities:478return (bits_get(val, (uint8_t *)&wif->htcaps,479sizeof(wif->htcaps)));480}481482abort();483}484485int486op_wlan_iface_config(struct snmp_context *ctx, struct snmp_value *val,487uint32_t sub, uint32_t iidx __unused, enum snmp_op op)488{489int intval, vlen, rc;490char *strval;491struct wlan_iface *wif;492493wlan_update_interface_list();494495switch (op) {496case SNMP_OP_GET:497if ((wif = wlan_get_interface(&val->var, sub)) == NULL)498return (SNMP_ERR_NOSUCHNAME);499goto get_config;500501case SNMP_OP_GETNEXT:502if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)503return (SNMP_ERR_NOSUCHNAME);504wlan_append_ifindex(&val->var, sub, wif);505goto get_config;506507case SNMP_OP_SET:508if ((wif = wlan_get_interface(&val->var, sub)) == NULL)509return (SNMP_ERR_NOSUCHNAME);510511intval = val->v.integer;512strval = NULL;513vlen = 0;514515/* Simple sanity checks & save old data. */516switch (val->var.subs[sub - 1]) {517case LEAF_wlanIfaceCountryCode:518if (val->v.octetstring.len != WLAN_COUNTRY_CODE_SIZE)519return (SNMP_ERR_INCONS_VALUE);520break;521case LEAF_wlanIfaceDesiredSsid:522if (val->v.octetstring.len > IEEE80211_NWID_LEN)523return (SNMP_ERR_INCONS_VALUE);524break;525case LEAF_wlanIfaceDesiredBssid:526if (val->v.octetstring.len != IEEE80211_ADDR_LEN)527return (SNMP_ERR_INCONS_VALUE);528break;529case LEAF_wlanIfacePacketBurst:530ctx->scratch->int1 = wif->packet_burst;531break;532case LEAF_wlanIfaceRegDomain:533ctx->scratch->int1 = wif->reg_domain;534break;535case LEAF_wlanIfaceDesiredChannel:536ctx->scratch->int1 = wif->desired_channel;537break;538case LEAF_wlanIfaceDynamicFreqSelection:539ctx->scratch->int1 = wif->dyn_frequency;540break;541case LEAF_wlanIfaceFastFrames:542ctx->scratch->int1 = wif->fast_frames;543break;544case LEAF_wlanIfaceDturbo:545ctx->scratch->int1 = wif->dturbo;546break;547case LEAF_wlanIfaceTxPower:548ctx->scratch->int1 = wif->tx_power;549break;550case LEAF_wlanIfaceFragmentThreshold:551ctx->scratch->int1 = wif->frag_threshold;552break;553case LEAF_wlanIfaceRTSThreshold:554ctx->scratch->int1 = wif->rts_threshold;555break;556case LEAF_wlanIfaceWlanPrivacySubscribe:557ctx->scratch->int1 = wif->priv_subscribe;558break;559case LEAF_wlanIfaceBgScan:560ctx->scratch->int1 = wif->bg_scan;561break;562case LEAF_wlanIfaceBgScanIdle:563ctx->scratch->int1 = wif->bg_scan_idle;564break;565case LEAF_wlanIfaceBgScanInterval:566ctx->scratch->int1 = wif->bg_scan_interval;567break;568case LEAF_wlanIfaceBeaconMissedThreshold:569ctx->scratch->int1 = wif->beacons_missed;570break;571case LEAF_wlanIfaceRoamingMode:572ctx->scratch->int1 = wif->roam_mode;573break;574case LEAF_wlanIfaceDot11d:575ctx->scratch->int1 = wif->dot11d;576break;577case LEAF_wlanIfaceDot11h:578ctx->scratch->int1 = wif->dot11h;579break;580case LEAF_wlanIfaceDynamicWds:581ctx->scratch->int1 = wif->dynamic_wds;582break;583case LEAF_wlanIfacePowerSave:584ctx->scratch->int1 = wif->power_save;585break;586case LEAF_wlanIfaceApBridge:587ctx->scratch->int1 = wif->ap_bridge;588break;589case LEAF_wlanIfaceBeaconInterval:590ctx->scratch->int1 = wif->beacon_interval;591break;592case LEAF_wlanIfaceDtimPeriod:593ctx->scratch->int1 = wif->dtim_period;594break;595case LEAF_wlanIfaceHideSsid:596ctx->scratch->int1 = wif->hide_ssid;597break;598case LEAF_wlanIfaceInactivityProccess:599ctx->scratch->int1 = wif->inact_process;600break;601case LEAF_wlanIfaceDot11gProtMode:602ctx->scratch->int1 = wif->do11g_protect;603break;604case LEAF_wlanIfaceDot11gPureMode:605ctx->scratch->int1 = wif->dot11g_pure;606break;607case LEAF_wlanIfaceDot11nPureMode:608ctx->scratch->int1 = wif->dot11n_pure;609break;610case LEAF_wlanIfaceDot11nAmpdu:611ctx->scratch->int1 = wif->ampdu;612break;613case LEAF_wlanIfaceDot11nAmpduDensity:614ctx->scratch->int1 = wif->ampdu_density;615break;616case LEAF_wlanIfaceDot11nAmpduLimit:617ctx->scratch->int1 = wif->ampdu_limit;618break;619case LEAF_wlanIfaceDot11nAmsdu:620ctx->scratch->int1 = wif->amsdu;621break;622case LEAF_wlanIfaceDot11nAmsduLimit:623ctx->scratch->int1 = wif->amsdu_limit;624break;625case LEAF_wlanIfaceDot11nHighThroughput:626ctx->scratch->int1 = wif->ht_enabled;627break;628case LEAF_wlanIfaceDot11nHTCompatible:629ctx->scratch->int1 = wif->ht_compatible;630break;631case LEAF_wlanIfaceDot11nHTProtMode:632ctx->scratch->int1 = wif->ht_prot_mode;633break;634case LEAF_wlanIfaceDot11nRIFS:635ctx->scratch->int1 = wif->rifs;636break;637case LEAF_wlanIfaceDot11nShortGI:638ctx->scratch->int1 = wif->short_gi;639break;640case LEAF_wlanIfaceDot11nSMPSMode:641ctx->scratch->int1 = wif->smps_mode;642break;643case LEAF_wlanIfaceTdmaSlot:644ctx->scratch->int1 = wif->tdma_slot;645break;646case LEAF_wlanIfaceTdmaSlotCount:647ctx->scratch->int1 = wif->tdma_slot_count;648break;649case LEAF_wlanIfaceTdmaSlotLength:650ctx->scratch->int1 = wif->tdma_slot_length;651break;652case LEAF_wlanIfaceTdmaBeaconInterval:653ctx->scratch->int1 = wif->tdma_binterval;654break;655default:656abort();657}658659if (val->syntax != SNMP_SYNTAX_OCTETSTRING)660goto set_config;661662ctx->scratch->int1 = val->v.octetstring.len;663ctx->scratch->ptr1 = malloc(val->v.octetstring.len + 1);664if (ctx->scratch->ptr1 == NULL)665return (SNMP_ERR_GENERR); /* XXX */666if (val->var.subs[sub - 1] == LEAF_wlanIfaceDesiredSsid)667strlcpy(ctx->scratch->ptr1, val->v.octetstring.octets,668val->v.octetstring.len + 1);669else670memcpy(ctx->scratch->ptr1, val->v.octetstring.octets,671val->v.octetstring.len);672strval = val->v.octetstring.octets;673vlen = val->v.octetstring.len;674goto set_config;675676case SNMP_OP_ROLLBACK:677intval = ctx->scratch->int1;678strval = NULL;679vlen = 0;680681if ((wif = wlan_get_interface(&val->var, sub)) == NULL)682return (SNMP_ERR_NOSUCHNAME);683switch (val->var.subs[sub - 1]) {684case LEAF_wlanIfaceCountryCode:685case LEAF_wlanIfaceDesiredSsid:686case LEAF_wlanIfaceDesiredBssid:687strval = ctx->scratch->ptr1;688vlen = ctx->scratch->int1;689break;690default:691break;692}693goto set_config;694695case SNMP_OP_COMMIT:696switch (val->var.subs[sub - 1]) {697case LEAF_wlanIfaceCountryCode:698case LEAF_wlanIfaceDesiredSsid:699case LEAF_wlanIfaceDesiredBssid:700free(ctx->scratch->ptr1);701/* FALLTHROUGH */702default:703return (SNMP_ERR_NOERROR);704}705}706abort();707708get_config:709710if (wlan_config_get_ioctl(wif, val->var.subs[sub - 1]) < 0)711return (SNMP_ERR_GENERR);712713switch (val->var.subs[sub - 1]) {714case LEAF_wlanIfacePacketBurst:715val->v.integer = wif->packet_burst;716break;717case LEAF_wlanIfaceCountryCode:718return (string_get(val, wif->country_code,719WLAN_COUNTRY_CODE_SIZE));720case LEAF_wlanIfaceRegDomain:721val->v.integer = wif->reg_domain;722break;723case LEAF_wlanIfaceDesiredSsid:724return (string_get(val, wif->desired_ssid, -1));725case LEAF_wlanIfaceDesiredChannel:726val->v.integer = wif->desired_channel;727break;728case LEAF_wlanIfaceDynamicFreqSelection:729val->v.integer = wif->dyn_frequency;730break;731case LEAF_wlanIfaceFastFrames:732val->v.integer = wif->fast_frames;733break;734case LEAF_wlanIfaceDturbo:735val->v.integer = wif->dturbo;736break;737case LEAF_wlanIfaceTxPower:738val->v.integer = wif->tx_power;739break;740case LEAF_wlanIfaceFragmentThreshold:741val->v.integer = wif->frag_threshold;742break;743case LEAF_wlanIfaceRTSThreshold:744val->v.integer = wif->rts_threshold;745break;746case LEAF_wlanIfaceWlanPrivacySubscribe:747val->v.integer = wif->priv_subscribe;748break;749case LEAF_wlanIfaceBgScan:750val->v.integer = wif->bg_scan;751break;752case LEAF_wlanIfaceBgScanIdle:753val->v.integer = wif->bg_scan_idle;754break;755case LEAF_wlanIfaceBgScanInterval:756val->v.integer = wif->bg_scan_interval;757break;758case LEAF_wlanIfaceBeaconMissedThreshold:759val->v.integer = wif->beacons_missed;760break;761case LEAF_wlanIfaceDesiredBssid:762return (string_get(val, wif->desired_bssid,763IEEE80211_ADDR_LEN));764case LEAF_wlanIfaceRoamingMode:765val->v.integer = wif->roam_mode;766break;767case LEAF_wlanIfaceDot11d:768val->v.integer = wif->dot11d;769break;770case LEAF_wlanIfaceDot11h:771val->v.integer = wif->dot11h;772break;773case LEAF_wlanIfaceDynamicWds:774val->v.integer = wif->dynamic_wds;775break;776case LEAF_wlanIfacePowerSave:777val->v.integer = wif->power_save;778break;779case LEAF_wlanIfaceApBridge:780val->v.integer = wif->ap_bridge;781break;782case LEAF_wlanIfaceBeaconInterval:783val->v.integer = wif->beacon_interval;784break;785case LEAF_wlanIfaceDtimPeriod:786val->v.integer = wif->dtim_period;787break;788case LEAF_wlanIfaceHideSsid:789val->v.integer = wif->hide_ssid;790break;791case LEAF_wlanIfaceInactivityProccess:792val->v.integer = wif->inact_process;793break;794case LEAF_wlanIfaceDot11gProtMode:795val->v.integer = wif->do11g_protect;796break;797case LEAF_wlanIfaceDot11gPureMode:798val->v.integer = wif->dot11g_pure;799break;800case LEAF_wlanIfaceDot11nPureMode:801val->v.integer = wif->dot11n_pure;802break;803case LEAF_wlanIfaceDot11nAmpdu:804val->v.integer = wif->ampdu;805break;806case LEAF_wlanIfaceDot11nAmpduDensity:807val->v.integer = wif->ampdu_density;808break;809case LEAF_wlanIfaceDot11nAmpduLimit:810val->v.integer = wif->ampdu_limit;811break;812case LEAF_wlanIfaceDot11nAmsdu:813val->v.integer = wif->amsdu;814break;815case LEAF_wlanIfaceDot11nAmsduLimit:816val->v.integer = wif->amsdu_limit;817break;818case LEAF_wlanIfaceDot11nHighThroughput:819val->v.integer = wif->ht_enabled;820break;821case LEAF_wlanIfaceDot11nHTCompatible:822val->v.integer = wif->ht_compatible;823break;824case LEAF_wlanIfaceDot11nHTProtMode:825val->v.integer = wif->ht_prot_mode;826break;827case LEAF_wlanIfaceDot11nRIFS:828val->v.integer = wif->rifs;829break;830case LEAF_wlanIfaceDot11nShortGI:831val->v.integer = wif->short_gi;832break;833case LEAF_wlanIfaceDot11nSMPSMode:834val->v.integer = wif->smps_mode;835break;836case LEAF_wlanIfaceTdmaSlot:837val->v.integer = wif->tdma_slot;838break;839case LEAF_wlanIfaceTdmaSlotCount:840val->v.integer = wif->tdma_slot_count;841break;842case LEAF_wlanIfaceTdmaSlotLength:843val->v.integer = wif->tdma_slot_length;844break;845case LEAF_wlanIfaceTdmaBeaconInterval:846val->v.integer = wif->tdma_binterval;847break;848}849850return (SNMP_ERR_NOERROR);851852set_config:853rc = wlan_config_set_ioctl(wif, val->var.subs[sub - 1], intval,854strval, vlen);855856if (op == SNMP_OP_ROLLBACK) {857switch (val->var.subs[sub - 1]) {858case LEAF_wlanIfaceCountryCode:859case LEAF_wlanIfaceDesiredSsid:860case LEAF_wlanIfaceDesiredBssid:861free(ctx->scratch->ptr1);862/* FALLTHROUGH */863default:864break;865}866}867868if (rc < 0)869return (SNMP_ERR_GENERR);870871return (SNMP_ERR_NOERROR);872}873874int875op_wlan_if_peer(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,876uint32_t iidx __unused, enum snmp_op op)877{878struct wlan_peer *wip;879struct wlan_iface *wif;880881wlan_update_interface_list();882wlan_update_peers();883884switch (op) {885case SNMP_OP_GET:886if ((wip = wlan_get_peer(&val->var, sub, &wif)) == NULL)887return (SNMP_ERR_NOSUCHNAME);888break;889case SNMP_OP_GETNEXT:890if ((wip = wlan_get_next_peer(&val->var, sub, &wif)) == NULL)891return (SNMP_ERR_NOSUCHNAME);892wlan_append_mac_index(&val->var, sub, wif->wname, wip->pmac);893break;894case SNMP_OP_SET:895if ((wip = wlan_get_peer(&val->var, sub, &wif)) == NULL)896return (SNMP_ERR_NOSUCHNAME);897if (val->var.subs[sub - 1] != LEAF_wlanIfacePeerVlanTag)898return (SNMP_ERR_GENERR);899ctx->scratch->int1 = wip->vlan;900if (wlan_peer_set_vlan(wif, wip, val->v.integer) < 0)901return (SNMP_ERR_GENERR);902return (SNMP_ERR_NOERROR);903case SNMP_OP_COMMIT:904return (SNMP_ERR_NOERROR);905case SNMP_OP_ROLLBACK:906if ((wip = wlan_get_peer(&val->var, sub, &wif)) == NULL)907return (SNMP_ERR_NOSUCHNAME);908if (val->var.subs[sub - 1] != LEAF_wlanIfacePeerVlanTag)909return (SNMP_ERR_GENERR);910if (wlan_peer_set_vlan(wif, wip, ctx->scratch->int1) < 0)911return (SNMP_ERR_GENERR);912return (SNMP_ERR_NOERROR);913default:914abort();915}916917switch (val->var.subs[sub - 1]) {918case LEAF_wlanIfacePeerAddress:919return (string_get(val, wip->pmac, IEEE80211_ADDR_LEN));920case LEAF_wlanIfacePeerAssociationId:921val->v.integer = wip->associd;922break;923case LEAF_wlanIfacePeerVlanTag:924val->v.integer = wip->vlan;925break;926case LEAF_wlanIfacePeerFrequency:927val->v.integer = wip->frequency;928break;929case LEAF_wlanIfacePeerCurrentTXRate:930val->v.integer = wip->txrate;931break;932case LEAF_wlanIfacePeerRxSignalStrength:933val->v.integer = wip->rssi;934break;935case LEAF_wlanIfacePeerIdleTimer:936val->v.integer = wip->idle;937break;938case LEAF_wlanIfacePeerTxSequenceNo:939val->v.integer = wip->txseqs;940break;941case LEAF_wlanIfacePeerRxSequenceNo:942val->v.integer = wip->rxseqs;943break;944case LEAF_wlanIfacePeerTxPower:945val->v.integer = wip->txpower;946break;947case LEAF_wlanIfacePeerCapabilities:948return (bits_get(val, (uint8_t *)&wip->capinfo,949sizeof(wip->capinfo)));950case LEAF_wlanIfacePeerFlags:951return (bits_get(val, (uint8_t *)&wip->state,952sizeof(wip->state)));953default:954abort();955}956957return (SNMP_ERR_NOERROR);958}959960int961op_wlan_channels(struct snmp_context *ctx __unused, struct snmp_value *val,962uint32_t sub, uint32_t iidx __unused, enum snmp_op op)963{964int32_t bits;965struct ieee80211_channel *channel;966struct wlan_iface *wif;967968wlan_update_interface_list();969wlan_update_channels();970971switch (op) {972case SNMP_OP_GET:973if ((channel = wlan_get_channel(&val->var, sub, &wif)) == NULL)974return (SNMP_ERR_NOSUCHNAME);975break;976case SNMP_OP_GETNEXT:977channel = wlan_get_next_channel(&val->var, sub, &wif);978if (channel == NULL || wif == NULL)979return (SNMP_ERR_NOSUCHNAME);980wlan_append_channel_index(&val->var, sub, wif, channel);981break;982case SNMP_OP_SET:983return (SNMP_ERR_NOT_WRITEABLE);984case SNMP_OP_COMMIT:985/* FALLTHROUGH */986case SNMP_OP_ROLLBACK:987/* FALLTHROUGH */988default:989abort();990}991992switch (val->var.subs[sub - 1]) {993case LEAF_wlanIfaceChannelIeeeId:994val->v.integer = channel->ic_ieee;995break;996case LEAF_wlanIfaceChannelType:997val->v.integer = wlan_get_channel_type(channel);998break;999case LEAF_wlanIfaceChannelFlags:1000bits = wlan_channel_flags_to_snmp(channel->ic_flags);1001return (bits_get(val, (uint8_t *)&bits, sizeof(bits)));1002case LEAF_wlanIfaceChannelFrequency:1003val->v.integer = channel->ic_freq;1004break;1005case LEAF_wlanIfaceChannelMaxRegPower:1006val->v.integer = channel->ic_maxregpower;1007break;1008case LEAF_wlanIfaceChannelMaxTxPower:1009val->v.integer = channel->ic_maxpower;1010break;1011case LEAF_wlanIfaceChannelMinTxPower:1012val->v.integer = channel->ic_minpower;1013break;1014case LEAF_wlanIfaceChannelState:1015bits = wlan_channel_state_to_snmp(channel->ic_state);1016return (bits_get(val, (uint8_t *)&bits, sizeof(bits)));1017case LEAF_wlanIfaceChannelHTExtension:1018val->v.integer = channel->ic_extieee;1019break;1020case LEAF_wlanIfaceChannelMaxAntennaGain:1021val->v.integer = channel->ic_maxantgain;1022break;1023}10241025return (SNMP_ERR_NOERROR);1026}10271028int1029op_wlan_roam_params(struct snmp_context *ctx __unused, struct snmp_value *val,1030uint32_t sub, uint32_t iidx __unused, enum snmp_op op)1031{1032uint32_t phy;1033struct ieee80211_roamparam *rparam;1034struct wlan_iface *wif;10351036wlan_update_interface_list();1037wlan_update_roam_params();10381039switch (op) {1040case SNMP_OP_GET:1041rparam = wlan_get_roam_param(&val->var, sub, &wif);1042if (rparam == NULL)1043return (SNMP_ERR_NOSUCHNAME);1044break;1045case SNMP_OP_GETNEXT:1046rparam = wlan_get_next_roam_param(&val->var, sub, &wif, &phy);1047if (rparam == NULL || wif == NULL)1048return (SNMP_ERR_NOSUCHNAME);1049wlan_append_phy_index(&val->var, sub, wif->wname, phy);1050break;1051case SNMP_OP_SET:1052return (SNMP_ERR_NOT_WRITEABLE);1053case SNMP_OP_COMMIT:1054/* FALLTHROUGH */1055case SNMP_OP_ROLLBACK:1056/* FALLTHROUGH */1057default:1058abort();1059}10601061switch (val->var.subs[sub - 1]) {1062case LEAF_wlanIfRoamRxSignalStrength:1063val->v.integer = rparam->rssi/2;1064break;1065case LEAF_wlanIfRoamTxRateThreshold:1066val->v.integer = rparam->rate/2;1067break;1068default:1069abort();1070}10711072return (SNMP_ERR_NOERROR);1073}10741075int1076op_wlan_tx_params(struct snmp_context *ctx, struct snmp_value *val,1077uint32_t sub, uint32_t iidx __unused, enum snmp_op op)1078{1079uint32_t phy;1080struct ieee80211_txparam *txparam;1081struct wlan_iface *wif;10821083wlan_update_interface_list();1084wlan_update_tx_params();10851086switch (op) {1087case SNMP_OP_GET:1088txparam = wlan_get_tx_param(&val->var, sub, &wif, &phy);1089if (txparam == NULL)1090return (SNMP_ERR_NOSUCHNAME);1091goto get_txparams;10921093case SNMP_OP_GETNEXT:1094txparam = wlan_get_next_tx_param(&val->var, sub, &wif, &phy);1095if (txparam == NULL || wif == NULL)1096return (SNMP_ERR_NOSUCHNAME);1097wlan_append_phy_index(&val->var, sub, wif->wname, phy);1098goto get_txparams;10991100case SNMP_OP_SET:1101txparam = wlan_get_tx_param(&val->var, sub, &wif, &phy);1102if (txparam == NULL || wif == NULL)1103return (SNMP_ERR_NOSUCHNAME);1104switch (val->var.subs[sub - 1]) {1105case LEAF_wlanIfTxUnicastRate:1106ctx->scratch->int1 = txparam->ucastrate;1107txparam->ucastrate = val->v.integer * 2;1108break;1109case LEAF_wlanIfTxMcastRate:1110ctx->scratch->int1 = txparam->mcastrate;1111txparam->mcastrate = val->v.integer * 2;1112break;1113case LEAF_wlanIfTxMgmtRate:1114ctx->scratch->int1 = txparam->mgmtrate;1115txparam->mgmtrate = val->v.integer * 2;1116break;1117case LEAF_wlanIfTxMaxRetryCount:1118ctx->scratch->int1 = txparam->maxretry;1119txparam->maxretry = val->v.integer;1120break;1121default:1122abort();1123}1124if (wlan_set_tx_params(wif, phy) < 0)1125return (SNMP_ERR_GENERR);1126return (SNMP_ERR_NOERROR);11271128case SNMP_OP_COMMIT:1129return (SNMP_ERR_NOERROR);11301131case SNMP_OP_ROLLBACK:1132txparam = wlan_get_tx_param(&val->var, sub, &wif, &phy);1133if (txparam == NULL || wif == NULL)1134return (SNMP_ERR_NOSUCHNAME);1135switch (val->var.subs[sub - 1]) {1136case LEAF_wlanIfTxUnicastRate:1137txparam->ucastrate = ctx->scratch->int1;1138break;1139case LEAF_wlanIfTxMcastRate:1140txparam->mcastrate = ctx->scratch->int1;1141break;1142case LEAF_wlanIfTxMgmtRate:1143txparam->mgmtrate = ctx->scratch->int1;1144break;1145case LEAF_wlanIfTxMaxRetryCount:1146txparam->maxretry = ctx->scratch->int1;1147break;1148default:1149abort();1150}1151if (wlan_set_tx_params(wif, phy) < 0)1152return (SNMP_ERR_GENERR);1153return (SNMP_ERR_NOERROR);1154default:1155abort();1156}11571158get_txparams:1159switch (val->var.subs[sub - 1]) {1160case LEAF_wlanIfTxUnicastRate:1161val->v.integer = txparam->ucastrate / 2;1162break;1163case LEAF_wlanIfTxMcastRate:1164val->v.integer = txparam->mcastrate / 2;1165break;1166case LEAF_wlanIfTxMgmtRate:1167val->v.integer = txparam->mgmtrate / 2;1168break;1169case LEAF_wlanIfTxMaxRetryCount:1170val->v.integer = txparam->maxretry;1171break;1172default:1173abort();1174}11751176return (SNMP_ERR_NOERROR);1177}11781179int1180op_wlan_scan_config(struct snmp_context *ctx, struct snmp_value *val,1181uint32_t sub, uint32_t iidx __unused, enum snmp_op op)1182{1183struct wlan_iface *wif;11841185wlan_update_interface_list();11861187switch (op) {1188case SNMP_OP_GET:1189if ((wif = wlan_get_interface(&val->var, sub)) == NULL)1190return (SNMP_ERR_NOSUCHNAME);1191break;11921193case SNMP_OP_GETNEXT:1194if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)1195return (SNMP_ERR_NOSUCHNAME);1196wlan_append_ifindex(&val->var, sub, wif);1197break;11981199case SNMP_OP_SET:1200if ((wif = wlan_get_interface(&val->var, sub)) == NULL)1201return (SNMP_ERR_NOSUCHNAME);1202if (wif->scan_status == wlanScanConfigStatus_running1203&& val->var.subs[sub - 1] != LEAF_wlanScanConfigStatus)1204return (SNMP_ERR_INCONS_VALUE);1205switch (val->var.subs[sub - 1]) {1206case LEAF_wlanScanFlags:1207ctx->scratch->int1 = wif->scan_flags;1208wif->scan_flags = val->v.integer;1209break;1210case LEAF_wlanScanDuration:1211ctx->scratch->int1 = wif->scan_duration;1212wif->scan_duration = val->v.integer;1213break;1214case LEAF_wlanScanMinChannelDwellTime:1215ctx->scratch->int1 = wif->scan_mindwell;1216wif->scan_mindwell = val->v.integer;1217break;1218case LEAF_wlanScanMaxChannelDwellTime:1219ctx->scratch->int1 = wif->scan_maxdwell;1220wif->scan_maxdwell = val->v.integer;1221break;1222case LEAF_wlanScanConfigStatus:1223if (val->v.integer == wlanScanConfigStatus_running ||1224val->v.integer == wlanScanConfigStatus_cancel) {1225ctx->scratch->int1 = wif->scan_status;1226wif->scan_status = val->v.integer;1227break;1228}1229return (SNMP_ERR_INCONS_VALUE);1230}1231return (SNMP_ERR_NOERROR);12321233case SNMP_OP_COMMIT:1234if ((wif = wlan_get_interface(&val->var, sub)) == NULL)1235return (SNMP_ERR_NOSUCHNAME);1236if (val->var.subs[sub - 1] == LEAF_wlanScanConfigStatus)1237if (wif->scan_status == wlanScanConfigStatus_running)1238(void)wlan_set_scan_config(wif); /* XXX */1239return (SNMP_ERR_NOERROR);12401241case SNMP_OP_ROLLBACK:1242if ((wif = wlan_get_interface(&val->var, sub)) == NULL)1243return (SNMP_ERR_NOSUCHNAME);1244switch (val->var.subs[sub - 1]) {1245case LEAF_wlanScanFlags:1246wif->scan_flags = ctx->scratch->int1;1247break;1248case LEAF_wlanScanDuration:1249wif->scan_duration = ctx->scratch->int1;1250break;1251case LEAF_wlanScanMinChannelDwellTime:1252wif->scan_mindwell = ctx->scratch->int1;1253break;1254case LEAF_wlanScanMaxChannelDwellTime:1255wif->scan_maxdwell = ctx->scratch->int1;1256break;1257case LEAF_wlanScanConfigStatus:1258wif->scan_status = ctx->scratch->int1;1259break;1260}1261return (SNMP_ERR_NOERROR);1262default:1263abort();1264}12651266switch (val->var.subs[sub - 1]) {1267case LEAF_wlanScanFlags:1268val->v.integer = wif->scan_flags;1269break;1270case LEAF_wlanScanDuration:1271val->v.integer = wif->scan_duration;1272break;1273case LEAF_wlanScanMinChannelDwellTime:1274val->v.integer = wif->scan_mindwell;1275break;1276case LEAF_wlanScanMaxChannelDwellTime:1277val->v.integer = wif->scan_maxdwell;1278break;1279case LEAF_wlanScanConfigStatus:1280val->v.integer = wif->scan_status;1281break;1282}12831284return (SNMP_ERR_NOERROR);1285}12861287int1288op_wlan_scan_results(struct snmp_context *ctx __unused, struct snmp_value *val,1289uint32_t sub, uint32_t iidx __unused, enum snmp_op op)1290{1291struct wlan_scan_result *sr;1292struct wlan_iface *wif;12931294wlan_update_interface_list();1295wlan_scan_update_results();12961297switch (op) {1298case SNMP_OP_GET:1299if ((sr = wlan_get_scanr(&val->var, sub, &wif)) == NULL)1300return (SNMP_ERR_NOSUCHNAME);1301break;13021303case SNMP_OP_GETNEXT:1304if ((sr = wlan_get_next_scanr(&val->var, sub, &wif)) == NULL)1305return (SNMP_ERR_NOSUCHNAME);1306wlan_append_scanr_index(&val->var, sub, wif->wname, sr->ssid,1307sr->bssid);1308break;13091310case SNMP_OP_SET:1311return (SNMP_ERR_NOT_WRITEABLE);1312case SNMP_OP_COMMIT:1313/* FALLTHROUGH */1314case SNMP_OP_ROLLBACK:1315/* FALLTHROUGH */1316default:1317abort();1318}13191320switch (val->var.subs[sub - 1]) {1321case LEAF_wlanScanResultID:1322return (string_get(val, sr->ssid, -1));1323case LEAF_wlanScanResultBssid:1324return (string_get(val, sr->bssid, IEEE80211_ADDR_LEN));1325case LEAF_wlanScanResultChannel:1326val->v.integer = sr->opchannel; /* XXX */1327break;1328case LEAF_wlanScanResultRate:1329val->v.integer = sr->rssi;1330break;1331case LEAF_wlanScanResultNoise:1332val->v.integer = sr->noise;1333break;1334case LEAF_wlanScanResultBeaconInterval:1335val->v.integer = sr->bintval;1336break;1337case LEAF_wlanScanResultCapabilities:1338return (bits_get(val, &sr->capinfo, sizeof(sr->capinfo)));1339default:1340abort();1341}13421343return (SNMP_ERR_NOERROR);1344}13451346int1347op_wlan_iface_stats(struct snmp_context *ctx __unused, struct snmp_value *val,1348uint32_t sub, uint32_t iidx __unused, enum snmp_op op)1349{1350struct wlan_iface *wif;13511352wlan_update_interface_list();13531354switch (op) {1355case SNMP_OP_GET:1356if ((wif = wlan_get_interface(&val->var, sub)) == NULL)1357return (SNMP_ERR_NOSUCHNAME);1358break;1359case SNMP_OP_GETNEXT:1360if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)1361return (SNMP_ERR_NOSUCHNAME);1362wlan_append_ifindex(&val->var, sub, wif);1363break;1364case SNMP_OP_SET:1365/* XXX: LEAF_wlanStatsReset */1366return (SNMP_ERR_NOT_WRITEABLE);1367case SNMP_OP_COMMIT:1368/* FALLTHROUGH */1369case SNMP_OP_ROLLBACK:1370/* FALLTHROUGH */1371default:1372abort();1373}13741375if (wlan_get_stats(wif) < 0)1376return (SNMP_ERR_GENERR);13771378switch (val->var.subs[sub - 1]) {1379case LEAF_wlanStatsRxBadVersion:1380val->v.uint32 = wif->stats.is_rx_badversion;1381break;1382case LEAF_wlanStatsRxTooShort:1383val->v.uint32 = wif->stats.is_rx_tooshort;1384break;1385case LEAF_wlanStatsRxWrongBssid:1386val->v.uint32 = wif->stats.is_rx_wrongbss;1387break;1388case LEAF_wlanStatsRxDiscardedDups:1389val->v.uint32 = wif->stats.is_rx_dup;1390break;1391case LEAF_wlanStatsRxWrongDir:1392val->v.uint32 = wif->stats.is_rx_wrongdir;1393break;1394case LEAF_wlanStatsRxDiscardMcastEcho:1395val->v.uint32 = wif->stats.is_rx_mcastecho;1396break;1397case LEAF_wlanStatsRxDiscardNoAssoc:1398val->v.uint32 = wif->stats.is_rx_notassoc;1399break;1400case LEAF_wlanStatsRxWepNoPrivacy:1401val->v.uint32 = wif->stats.is_rx_noprivacy;1402break;1403case LEAF_wlanStatsRxWepUnencrypted:1404val->v.uint32 = wif->stats.is_rx_unencrypted;1405break;1406case LEAF_wlanStatsRxWepFailed:1407val->v.uint32 = wif->stats.is_rx_wepfail;1408break;1409case LEAF_wlanStatsRxDecapsulationFailed:1410val->v.uint32 = wif->stats.is_rx_decap;1411break;1412case LEAF_wlanStatsRxDiscardMgmt:1413val->v.uint32 = wif->stats.is_rx_mgtdiscard;1414break;1415case LEAF_wlanStatsRxControl:1416val->v.uint32 = wif->stats.is_rx_ctl;1417break;1418case LEAF_wlanStatsRxBeacon:1419val->v.uint32 = wif->stats.is_rx_beacon;1420break;1421case LEAF_wlanStatsRxRateSetTooBig:1422val->v.uint32 = wif->stats.is_rx_rstoobig;1423break;1424case LEAF_wlanStatsRxElemMissing:1425val->v.uint32 = wif->stats.is_rx_elem_missing;1426break;1427case LEAF_wlanStatsRxElemTooBig:1428val->v.uint32 = wif->stats.is_rx_elem_toobig;1429break;1430case LEAF_wlanStatsRxElemTooSmall:1431val->v.uint32 = wif->stats.is_rx_elem_toosmall;1432break;1433case LEAF_wlanStatsRxElemUnknown:1434val->v.uint32 = wif->stats.is_rx_elem_unknown;1435break;1436case LEAF_wlanStatsRxChannelMismatch:1437val->v.uint32 = wif->stats.is_rx_chanmismatch;1438break;1439case LEAF_wlanStatsRxDropped:1440val->v.uint32 = wif->stats.is_rx_nodealloc;1441break;1442case LEAF_wlanStatsRxSsidMismatch:1443val->v.uint32 = wif->stats.is_rx_ssidmismatch;1444break;1445case LEAF_wlanStatsRxAuthNotSupported:1446val->v.uint32 = wif->stats.is_rx_auth_unsupported;1447break;1448case LEAF_wlanStatsRxAuthFailed:1449val->v.uint32 = wif->stats.is_rx_auth_fail;1450break;1451case LEAF_wlanStatsRxAuthCM:1452val->v.uint32 = wif->stats.is_rx_auth_countermeasures;1453break;1454case LEAF_wlanStatsRxAssocWrongBssid:1455val->v.uint32 = wif->stats.is_rx_assoc_bss;1456break;1457case LEAF_wlanStatsRxAssocNoAuth:1458val->v.uint32 = wif->stats.is_rx_assoc_notauth;1459break;1460case LEAF_wlanStatsRxAssocCapMismatch:1461val->v.uint32 = wif->stats.is_rx_assoc_capmismatch;1462break;1463case LEAF_wlanStatsRxAssocNoRateMatch:1464val->v.uint32 = wif->stats.is_rx_assoc_norate;1465break;1466case LEAF_wlanStatsRxBadWpaIE:1467val->v.uint32 = wif->stats.is_rx_assoc_badwpaie;1468break;1469case LEAF_wlanStatsRxDeauthenticate:1470val->v.uint32 = wif->stats.is_rx_deauth;1471break;1472case LEAF_wlanStatsRxDisassociate:1473val->v.uint32 = wif->stats.is_rx_disassoc;1474break;1475case LEAF_wlanStatsRxUnknownSubtype:1476val->v.uint32 = wif->stats.is_rx_badsubtype;1477break;1478case LEAF_wlanStatsRxFailedNoBuf:1479val->v.uint32 = wif->stats.is_rx_nobuf;1480break;1481case LEAF_wlanStatsRxBadAuthRequest:1482val->v.uint32 = wif->stats.is_rx_bad_auth;1483break;1484case LEAF_wlanStatsRxUnAuthorized:1485val->v.uint32 = wif->stats.is_rx_unauth;1486break;1487case LEAF_wlanStatsRxBadKeyId:1488val->v.uint32 = wif->stats.is_rx_badkeyid;1489break;1490case LEAF_wlanStatsRxCCMPSeqViolation:1491val->v.uint32 = wif->stats.is_rx_ccmpreplay;1492break;1493case LEAF_wlanStatsRxCCMPBadFormat:1494val->v.uint32 = wif->stats.is_rx_ccmpformat;1495break;1496case LEAF_wlanStatsRxCCMPFailedMIC:1497val->v.uint32 = wif->stats.is_rx_ccmpmic;1498break;1499case LEAF_wlanStatsRxTKIPSeqViolation:1500val->v.uint32 = wif->stats.is_rx_tkipreplay;1501break;1502case LEAF_wlanStatsRxTKIPBadFormat:1503val->v.uint32 = wif->stats.is_rx_tkipformat;1504break;1505case LEAF_wlanStatsRxTKIPFailedMIC:1506val->v.uint32 = wif->stats.is_rx_tkipmic;1507break;1508case LEAF_wlanStatsRxTKIPFailedICV:1509val->v.uint32 = wif->stats.is_rx_tkipicv;1510break;1511case LEAF_wlanStatsRxDiscardACL:1512val->v.uint32 = wif->stats.is_rx_acl;1513break;1514case LEAF_wlanStatsTxFailedNoBuf:1515val->v.uint32 = wif->stats.is_tx_nobuf;1516break;1517case LEAF_wlanStatsTxFailedNoNode:1518val->v.uint32 = wif->stats.is_tx_nonode;1519break;1520case LEAF_wlanStatsTxUnknownMgmt:1521val->v.uint32 = wif->stats.is_tx_unknownmgt;1522break;1523case LEAF_wlanStatsTxBadCipher:1524val->v.uint32 = wif->stats.is_tx_badcipher;1525break;1526case LEAF_wlanStatsTxNoDefKey:1527val->v.uint32 = wif->stats.is_tx_nodefkey;1528break;1529case LEAF_wlanStatsTxFragmented:1530val->v.uint32 = wif->stats.is_tx_fragframes;1531break;1532case LEAF_wlanStatsTxFragmentsCreated:1533val->v.uint32 = wif->stats.is_tx_frags;1534break;1535case LEAF_wlanStatsActiveScans:1536val->v.uint32 = wif->stats.is_scan_active;1537break;1538case LEAF_wlanStatsPassiveScans:1539val->v.uint32 = wif->stats.is_scan_passive;1540break;1541case LEAF_wlanStatsTimeoutInactivity:1542val->v.uint32 = wif->stats.is_node_timeout;1543break;1544case LEAF_wlanStatsCryptoNoMem:1545val->v.uint32 = wif->stats.is_crypto_nomem;1546break;1547case LEAF_wlanStatsSwCryptoTKIP:1548val->v.uint32 = wif->stats.is_crypto_tkip;1549break;1550case LEAF_wlanStatsSwCryptoTKIPEnMIC:1551val->v.uint32 = wif->stats.is_crypto_tkipenmic;1552break;1553case LEAF_wlanStatsSwCryptoTKIPDeMIC:1554val->v.uint32 = wif->stats.is_crypto_tkipdemic;1555break;1556case LEAF_wlanStatsCryptoTKIPCM:1557val->v.uint32 = wif->stats.is_crypto_tkipcm;1558break;1559case LEAF_wlanStatsSwCryptoCCMP:1560val->v.uint32 = wif->stats.is_crypto_ccmp;1561break;1562case LEAF_wlanStatsSwCryptoWEP:1563val->v.uint32 = wif->stats.is_crypto_wep;1564break;1565case LEAF_wlanStatsCryptoCipherKeyRejected:1566val->v.uint32 = wif->stats.is_crypto_setkey_cipher;1567break;1568case LEAF_wlanStatsCryptoNoKey:1569val->v.uint32 = wif->stats.is_crypto_setkey_nokey;1570break;1571case LEAF_wlanStatsCryptoDeleteKeyFailed:1572val->v.uint32 = wif->stats.is_crypto_delkey;1573break;1574case LEAF_wlanStatsCryptoUnknownCipher:1575val->v.uint32 = wif->stats.is_crypto_badcipher;1576break;1577case LEAF_wlanStatsCryptoAttachFailed:1578val->v.uint32 = wif->stats.is_crypto_attachfail;1579break;1580case LEAF_wlanStatsCryptoKeyFailed:1581val->v.uint32 = wif->stats.is_crypto_keyfail;1582break;1583case LEAF_wlanStatsCryptoEnMICFailed:1584val->v.uint32 = wif->stats.is_crypto_enmicfail;1585break;1586case LEAF_wlanStatsIBSSCapMismatch:1587val->v.uint32 = wif->stats.is_ibss_capmismatch;1588break;1589case LEAF_wlanStatsUnassocStaPSPoll:1590val->v.uint32 = wif->stats.is_ps_unassoc;1591break;1592case LEAF_wlanStatsBadAidPSPoll:1593val->v.uint32 = wif->stats.is_ps_badaid;1594break;1595case LEAF_wlanStatsEmptyPSPoll:1596val->v.uint32 = wif->stats.is_ps_qempty;1597break;1598case LEAF_wlanStatsRxFFBadHdr:1599val->v.uint32 = wif->stats.is_ff_badhdr;1600break;1601case LEAF_wlanStatsRxFFTooShort:1602val->v.uint32 = wif->stats.is_ff_tooshort;1603break;1604case LEAF_wlanStatsRxFFSplitError:1605val->v.uint32 = wif->stats.is_ff_split;1606break;1607case LEAF_wlanStatsRxFFDecap:1608val->v.uint32 = wif->stats.is_ff_decap;1609break;1610case LEAF_wlanStatsTxFFEncap:1611val->v.uint32 = wif->stats.is_ff_encap;1612break;1613case LEAF_wlanStatsRxBadBintval:1614val->v.uint32 = wif->stats.is_rx_badbintval;1615break;1616case LEAF_wlanStatsRxDemicFailed:1617val->v.uint32 = wif->stats.is_rx_demicfail;1618break;1619case LEAF_wlanStatsRxDefragFailed:1620val->v.uint32 = wif->stats.is_rx_defrag;1621break;1622case LEAF_wlanStatsRxMgmt:1623val->v.uint32 = wif->stats.is_rx_mgmt;1624break;1625case LEAF_wlanStatsRxActionMgmt:1626val->v.uint32 = wif->stats.is_rx_action;1627break;1628case LEAF_wlanStatsRxAMSDUTooShort:1629val->v.uint32 = wif->stats.is_amsdu_tooshort;1630break;1631case LEAF_wlanStatsRxAMSDUSplitError:1632val->v.uint32 = wif->stats.is_amsdu_split;1633break;1634case LEAF_wlanStatsRxAMSDUDecap:1635val->v.uint32 = wif->stats.is_amsdu_decap;1636break;1637case LEAF_wlanStatsTxAMSDUEncap:1638val->v.uint32 = wif->stats.is_amsdu_encap;1639break;1640case LEAF_wlanStatsAMPDUBadBAR:1641val->v.uint32 = wif->stats.is_ampdu_bar_bad;1642break;1643case LEAF_wlanStatsAMPDUOowBar:1644val->v.uint32 = wif->stats.is_ampdu_bar_oow;1645break;1646case LEAF_wlanStatsAMPDUMovedBAR:1647val->v.uint32 = wif->stats.is_ampdu_bar_move;1648break;1649case LEAF_wlanStatsAMPDURxBAR:1650val->v.uint32 = wif->stats.is_ampdu_bar_rx;1651break;1652case LEAF_wlanStatsAMPDURxOor:1653val->v.uint32 = wif->stats.is_ampdu_rx_oor;1654break;1655case LEAF_wlanStatsAMPDURxCopied:1656val->v.uint32 = wif->stats.is_ampdu_rx_copy;1657break;1658case LEAF_wlanStatsAMPDURxDropped:1659val->v.uint32 = wif->stats.is_ampdu_rx_drop;1660break;1661case LEAF_wlanStatsTxDiscardBadState:1662val->v.uint32 = wif->stats.is_tx_badstate;1663break;1664case LEAF_wlanStatsTxFailedNoAssoc:1665val->v.uint32 = wif->stats.is_tx_notassoc;1666break;1667case LEAF_wlanStatsTxClassifyFailed:1668val->v.uint32 = wif->stats.is_tx_classify;1669break;1670case LEAF_wlanStatsDwdsMcastDiscard:1671val->v.uint32 = wif->stats.is_dwds_mcast;1672break;1673case LEAF_wlanStatsHTAssocRejectNoHT:1674val->v.uint32 = wif->stats.is_ht_assoc_nohtcap;1675break;1676case LEAF_wlanStatsHTAssocDowngrade:1677val->v.uint32 = wif->stats.is_ht_assoc_downgrade;1678break;1679case LEAF_wlanStatsHTAssocRateMismatch:1680val->v.uint32 = wif->stats.is_ht_assoc_norate;1681break;1682case LEAF_wlanStatsAMPDURxAge:1683val->v.uint32 = wif->stats.is_ampdu_rx_age;1684break;1685case LEAF_wlanStatsAMPDUMoved:1686val->v.uint32 = wif->stats.is_ampdu_rx_move;1687break;1688case LEAF_wlanStatsADDBADisabledReject:1689val->v.uint32 = wif->stats.is_addba_reject;1690break;1691case LEAF_wlanStatsADDBANoRequest:1692val->v.uint32 = wif->stats.is_addba_norequest;1693break;1694case LEAF_wlanStatsADDBABadToken:1695val->v.uint32 = wif->stats.is_addba_badtoken;1696break;1697case LEAF_wlanStatsADDBABadPolicy:1698val->v.uint32 = wif->stats.is_addba_badpolicy;1699break;1700case LEAF_wlanStatsAMPDUStopped:1701val->v.uint32 = wif->stats.is_ampdu_stop;1702break;1703case LEAF_wlanStatsAMPDUStopFailed:1704val->v.uint32 = wif->stats.is_ampdu_stop_failed;1705break;1706case LEAF_wlanStatsAMPDURxReorder:1707val->v.uint32 = wif->stats.is_ampdu_rx_reorder;1708break;1709case LEAF_wlanStatsScansBackground:1710val->v.uint32 = wif->stats.is_scan_bg;1711break;1712case LEAF_wlanLastDeauthReason:1713val->v.uint32 = wif->stats.is_rx_deauth_code;1714break;1715case LEAF_wlanLastDissasocReason:1716val->v.uint32 = wif->stats.is_rx_disassoc_code;1717break;1718case LEAF_wlanLastAuthFailReason:1719val->v.uint32 = wif->stats.is_rx_authfail_code;1720break;1721case LEAF_wlanStatsBeaconMissedEvents:1722val->v.uint32 = wif->stats.is_beacon_miss;1723break;1724case LEAF_wlanStatsRxDiscardBadStates:1725val->v.uint32 = wif->stats.is_rx_badstate;1726break;1727case LEAF_wlanStatsFFFlushed:1728val->v.uint32 = wif->stats.is_ff_flush;1729break;1730case LEAF_wlanStatsTxControlFrames:1731val->v.uint32 = wif->stats.is_tx_ctl;1732break;1733case LEAF_wlanStatsAMPDURexmt:1734val->v.uint32 = wif->stats.is_ampdu_rexmt;1735break;1736case LEAF_wlanStatsAMPDURexmtFailed:1737val->v.uint32 = wif->stats.is_ampdu_rexmt_fail;1738break;1739case LEAF_wlanStatsReset:1740val->v.uint32 = wlanStatsReset_no_op;1741break;1742default:1743abort();1744}17451746return (SNMP_ERR_NOERROR);1747}17481749int1750op_wlan_wep_iface(struct snmp_context *ctx, struct snmp_value *val,1751uint32_t sub, uint32_t iidx __unused, enum snmp_op op)1752{1753struct wlan_iface *wif;17541755wlan_update_interface_list();17561757switch (op) {1758case SNMP_OP_GET:1759if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||1760!wif->wepsupported)1761return (SNMP_ERR_NOSUCHNAME);1762break;17631764case SNMP_OP_GETNEXT:1765/* XXX: filter wif->wepsupported */1766if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)1767return (SNMP_ERR_NOSUCHNAME);1768wlan_append_ifindex(&val->var, sub, wif);1769break;17701771case SNMP_OP_SET:1772if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||1773!wif->wepsupported)1774return (SNMP_ERR_NOSUCHNAME);1775switch (val->var.subs[sub - 1]) {1776case LEAF_wlanWepMode:1777if (val->v.integer < wlanWepMode_off ||1778val->v.integer > wlanWepMode_mixed)1779return (SNMP_ERR_INCONS_VALUE);1780ctx->scratch->int1 = wif->wepmode;1781wif->wepmode = val->v.integer;1782if (wlan_set_wepmode(wif) < 0) {1783wif->wepmode = ctx->scratch->int1;1784return (SNMP_ERR_GENERR);1785}1786break;1787case LEAF_wlanWepDefTxKey:1788if (val->v.integer < 0 ||1789val->v.integer > IEEE80211_WEP_NKID)1790return (SNMP_ERR_INCONS_VALUE);1791ctx->scratch->int1 = wif->weptxkey;1792wif->weptxkey = val->v.integer;1793if (wlan_set_weptxkey(wif) < 0) {1794wif->weptxkey = ctx->scratch->int1;1795return (SNMP_ERR_GENERR);1796}1797break;1798default:1799abort();1800}1801return (SNMP_ERR_NOERROR);18021803case SNMP_OP_COMMIT:1804return (SNMP_ERR_NOERROR);18051806case SNMP_OP_ROLLBACK:1807if ((wif = wlan_get_interface(&val->var, sub)) == NULL)1808return (SNMP_ERR_NOSUCHNAME);1809switch (val->var.subs[sub - 1]) {1810case LEAF_wlanWepMode:1811wif->wepmode = ctx->scratch->int1;1812if (wlan_set_wepmode(wif) < 0)1813return (SNMP_ERR_GENERR);1814break;1815case LEAF_wlanWepDefTxKey:1816wif->weptxkey = ctx->scratch->int1;1817if (wlan_set_weptxkey(wif) < 0)1818return (SNMP_ERR_GENERR);1819break;1820default:1821abort();1822}1823return (SNMP_ERR_NOERROR);18241825default:1826abort();1827}18281829switch (val->var.subs[sub - 1]) {1830case LEAF_wlanWepMode:1831if (wlan_get_wepmode(wif) < 0)1832return (SNMP_ERR_GENERR);1833val->v.integer = wif->wepmode;1834break;1835case LEAF_wlanWepDefTxKey:1836if (wlan_get_weptxkey(wif) < 0)1837return (SNMP_ERR_GENERR);1838val->v.integer = wif->weptxkey;1839break;1840default:1841abort();1842}18431844return (SNMP_ERR_NOERROR);1845}18461847int1848op_wlan_wep_key(struct snmp_context *ctx __unused,1849struct snmp_value *val __unused, uint32_t sub __unused,1850uint32_t iidx __unused, enum snmp_op op __unused)1851{1852return (SNMP_ERR_NOSUCHNAME);1853}18541855int1856op_wlan_mac_access_control(struct snmp_context *ctx, struct snmp_value *val,1857uint32_t sub, uint32_t iidx __unused, enum snmp_op op)1858{1859struct wlan_iface *wif;18601861wlan_update_interface_list();18621863switch (op) {1864case SNMP_OP_GET:1865if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||1866!wif->macsupported)1867return (SNMP_ERR_NOSUCHNAME);1868break;18691870case SNMP_OP_GETNEXT:1871/* XXX: filter wif->macsupported */1872if ((wif = wlan_get_next_interface(&val->var, sub)) == NULL)1873return (SNMP_ERR_NOSUCHNAME);1874wlan_append_ifindex(&val->var, sub, wif);1875break;18761877case SNMP_OP_SET:1878if ((wif = wlan_get_interface(&val->var, sub)) == NULL ||1879!wif->macsupported)1880return (SNMP_ERR_NOSUCHNAME);1881switch (val->var.subs[sub - 1]) {1882case LEAF_wlanMACAccessControlPolicy:1883ctx->scratch->int1 = wif->mac_policy;1884wif->mac_policy = val->v.integer;1885break;1886case LEAF_wlanMACAccessControlNacl:1887return (SNMP_ERR_NOT_WRITEABLE);1888case LEAF_wlanMACAccessControlFlush:1889break;1890default:1891abort();1892}1893return (SNMP_ERR_NOERROR);18941895case SNMP_OP_COMMIT:1896if ((wif = wlan_get_interface(&val->var, sub)) == NULL)1897return (SNMP_ERR_NOSUCHNAME);1898switch (val->var.subs[sub - 1]) {1899case LEAF_wlanMACAccessControlPolicy:1900if (wlan_set_mac_policy(wif) < 0) {1901wif->mac_policy = ctx->scratch->int1;1902return (SNMP_ERR_GENERR);1903}1904break;1905case LEAF_wlanMACAccessControlFlush:1906if (wlan_flush_mac_mac(wif) < 0)1907return (SNMP_ERR_GENERR);1908break;1909default:1910abort();1911}1912return (SNMP_ERR_NOERROR);19131914case SNMP_OP_ROLLBACK:1915if ((wif = wlan_get_interface(&val->var, sub)) == NULL)1916return (SNMP_ERR_NOSUCHNAME);1917if (val->var.subs[sub - 1] == LEAF_wlanMACAccessControlPolicy)1918wif->mac_policy = ctx->scratch->int1;1919return (SNMP_ERR_NOERROR);19201921default:1922abort();1923}19241925if (wlan_get_mac_policy(wif) < 0)1926return (SNMP_ERR_GENERR);19271928switch (val->var.subs[sub - 1]) {1929case LEAF_wlanMACAccessControlPolicy:1930val->v.integer = wif->mac_policy;1931break;1932case LEAF_wlanMACAccessControlNacl:1933val->v.integer = wif->mac_nacls;1934break;1935case LEAF_wlanMACAccessControlFlush:1936val->v.integer = wlanMACAccessControlFlush_no_op;1937break;1938default:1939abort();1940}19411942return (SNMP_ERR_NOERROR);1943}19441945int1946op_wlan_mac_acl_mac(struct snmp_context *ctx, struct snmp_value *val,1947uint32_t sub, uint32_t iidx __unused, enum snmp_op op)1948{1949struct wlan_iface *wif;1950struct wlan_mac_mac *macl;19511952wlan_update_interface_list();1953wlan_mac_update_aclmacs();19541955switch (op) {1956case SNMP_OP_GET:1957if ((macl = wlan_get_acl_mac(&val->var, sub, &wif)) == NULL)1958return (SNMP_ERR_NOSUCHNAME);1959break;19601961case SNMP_OP_GETNEXT:1962if ((macl = wlan_get_next_acl_mac(&val->var, sub, &wif))1963== NULL)1964return (SNMP_ERR_NOSUCHNAME);1965wlan_append_mac_index(&val->var, sub, wif->wname, macl->mac);1966break;19671968case SNMP_OP_SET:1969switch (val->var.subs[sub - 1]) {1970case LEAF_wlanMACAccessControlMAC:1971return (SNMP_ERR_INCONS_NAME);1972case LEAF_wlanMACAccessControlMACStatus:1973return(wlan_acl_mac_set_status(ctx, val, sub));1974default:1975abort();1976}19771978case SNMP_OP_COMMIT:1979if ((macl = wlan_get_acl_mac(&val->var, sub, &wif)) == NULL)1980return (SNMP_ERR_NOSUCHNAME);1981if (val->v.integer == RowStatus_destroy &&1982wlan_mac_delete_mac(wif, macl) < 0)1983return (SNMP_ERR_GENERR);1984return (SNMP_ERR_NOERROR);19851986case SNMP_OP_ROLLBACK:1987if ((macl = wlan_get_acl_mac(&val->var, sub, &wif)) == NULL)1988return (SNMP_ERR_NOSUCHNAME);1989if (ctx->scratch->int1 == RowStatus_destroy &&1990wlan_mac_delete_mac(wif, macl) < 0)1991return (SNMP_ERR_GENERR);1992return (SNMP_ERR_NOERROR);19931994default:1995abort();1996}19971998switch (val->var.subs[sub - 1]) {1999case LEAF_wlanMACAccessControlMAC:2000return (string_get(val, macl->mac, IEEE80211_ADDR_LEN));2001case LEAF_wlanMACAccessControlMACStatus:2002val->v.integer = macl->mac_status;2003break;2004default:2005abort();2006}20072008return (SNMP_ERR_NOERROR);2009}20102011int2012op_wlan_mesh_config(struct snmp_context *ctx, struct snmp_value *val,2013uint32_t sub, uint32_t iidx __unused, enum snmp_op op)2014{2015int which;20162017switch (val->var.subs[sub - 1]) {2018case LEAF_wlanMeshMaxRetries:2019which = WLAN_MESH_MAX_RETRIES;2020break;2021case LEAF_wlanMeshHoldingTimeout:2022which = WLAN_MESH_HOLDING_TO;2023break;2024case LEAF_wlanMeshConfirmTimeout:2025which = WLAN_MESH_CONFIRM_TO;2026break;2027case LEAF_wlanMeshRetryTimeout:2028which = WLAN_MESH_RETRY_TO;2029break;2030default:2031abort();2032}20332034switch (op) {2035case SNMP_OP_GET:2036if (wlan_do_sysctl(&wlan_config, which, 0) < 0)2037return (SNMP_ERR_GENERR);2038break;20392040case SNMP_OP_GETNEXT:2041abort();20422043case SNMP_OP_SET:2044switch (val->var.subs[sub - 1]) {2045case LEAF_wlanMeshRetryTimeout :2046ctx->scratch->int1 = wlan_config.mesh_retryto;2047wlan_config.mesh_retryto = val->v.integer;2048break;2049case LEAF_wlanMeshHoldingTimeout:2050ctx->scratch->int1 = wlan_config.mesh_holdingto;2051wlan_config.mesh_holdingto = val->v.integer;2052break;2053case LEAF_wlanMeshConfirmTimeout:2054ctx->scratch->int1 = wlan_config.mesh_confirmto;2055wlan_config.mesh_confirmto = val->v.integer;2056break;2057case LEAF_wlanMeshMaxRetries:2058ctx->scratch->int1 = wlan_config.mesh_maxretries;2059wlan_config.mesh_maxretries = val->v.integer;2060break;2061}2062if (wlan_do_sysctl(&wlan_config, which, 1) < 0)2063return (SNMP_ERR_GENERR);2064return (SNMP_ERR_NOERROR);20652066case SNMP_OP_COMMIT:2067return (SNMP_ERR_NOERROR);20682069case SNMP_OP_ROLLBACK:2070switch (val->var.subs[sub - 1]) {2071case LEAF_wlanMeshRetryTimeout:2072wlan_config.mesh_retryto = ctx->scratch->int1;2073break;2074case LEAF_wlanMeshConfirmTimeout:2075wlan_config.mesh_confirmto = ctx->scratch->int1;2076break;2077case LEAF_wlanMeshHoldingTimeout:2078wlan_config.mesh_holdingto= ctx->scratch->int1;2079break;2080case LEAF_wlanMeshMaxRetries:2081wlan_config.mesh_maxretries = ctx->scratch->int1;2082break;2083}2084if (wlan_do_sysctl(&wlan_config, which, 1) < 0)2085return (SNMP_ERR_GENERR);2086return (SNMP_ERR_NOERROR);20872088default:2089abort();2090}20912092switch (val->var.subs[sub - 1]) {2093case LEAF_wlanMeshRetryTimeout:2094val->v.integer = wlan_config.mesh_retryto;2095break;2096case LEAF_wlanMeshHoldingTimeout:2097val->v.integer = wlan_config.mesh_holdingto;2098break;2099case LEAF_wlanMeshConfirmTimeout:2100val->v.integer = wlan_config.mesh_confirmto;2101break;2102case LEAF_wlanMeshMaxRetries:2103val->v.integer = wlan_config.mesh_maxretries;2104break;2105}21062107return (SNMP_ERR_NOERROR);2108}21092110int2111op_wlan_mesh_iface(struct snmp_context *ctx, struct snmp_value *val,2112uint32_t sub, uint32_t iidx __unused, enum snmp_op op)2113{2114int rc;2115struct wlan_iface *wif;21162117wlan_update_interface_list();21182119switch (op) {2120case SNMP_OP_GET:2121if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)2122return (SNMP_ERR_NOSUCHNAME);2123break;21242125case SNMP_OP_GETNEXT:2126if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)2127return (SNMP_ERR_NOSUCHNAME);2128wlan_append_ifindex(&val->var, sub, wif);2129break;21302131case SNMP_OP_SET:2132if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)2133return (SNMP_ERR_NOSUCHNAME);2134switch (val->var.subs[sub - 1]) {2135case LEAF_wlanMeshId:2136if (val->v.octetstring.len > IEEE80211_NWID_LEN)2137return (SNMP_ERR_INCONS_VALUE);2138ctx->scratch->ptr1 = malloc(val->v.octetstring.len + 1);2139if (ctx->scratch->ptr1 == NULL)2140return (SNMP_ERR_GENERR);2141strlcpy(ctx->scratch->ptr1, wif->desired_ssid,2142val->v.octetstring.len + 1);2143ctx->scratch->int1 = strlen(wif->desired_ssid);2144memcpy(wif->desired_ssid, val->v.octetstring.octets,2145val->v.octetstring.len);2146wif->desired_ssid[val->v.octetstring.len] = '\0';2147break;2148case LEAF_wlanMeshTTL:2149ctx->scratch->int1 = wif->mesh_ttl;2150wif->mesh_ttl = val->v.integer;2151break;2152case LEAF_wlanMeshPeeringEnabled:2153ctx->scratch->int1 = wif->mesh_peering;2154wif->mesh_peering = val->v.integer;2155break;2156case LEAF_wlanMeshForwardingEnabled:2157ctx->scratch->int1 = wif->mesh_forwarding;2158wif->mesh_forwarding = val->v.integer;2159break;2160case LEAF_wlanMeshMetric:2161ctx->scratch->int1 = wif->mesh_metric;2162wif->mesh_metric = val->v.integer;2163break;2164case LEAF_wlanMeshPath:2165ctx->scratch->int1 = wif->mesh_path;2166wif->mesh_path = val->v.integer;2167break;2168case LEAF_wlanMeshRoutesFlush:2169if (val->v.integer != wlanMeshRoutesFlush_flush)2170return (SNMP_ERR_INCONS_VALUE);2171return (SNMP_ERR_NOERROR);2172default:2173abort();2174}2175if (val->var.subs[sub - 1] == LEAF_wlanMeshId)2176rc = wlan_config_set_dssid(wif,2177val->v.octetstring.octets, val->v.octetstring.len);2178else2179rc = wlan_mesh_config_set(wif, val->var.subs[sub - 1]);2180if (rc < 0)2181return (SNMP_ERR_GENERR);2182return (SNMP_ERR_NOERROR);21832184case SNMP_OP_COMMIT:2185if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)2186return (SNMP_ERR_NOSUCHNAME);2187if (val->var.subs[sub - 1] == LEAF_wlanMeshRoutesFlush &&2188wlan_mesh_flush_routes(wif) < 0)2189return (SNMP_ERR_GENERR);2190if (val->var.subs[sub - 1] == LEAF_wlanMeshId)2191free(ctx->scratch->ptr1);2192return (SNMP_ERR_NOERROR);21932194case SNMP_OP_ROLLBACK:2195if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)2196return (SNMP_ERR_NOSUCHNAME);2197switch (val->var.subs[sub - 1]) {2198case LEAF_wlanMeshId:2199strlcpy(wif->desired_ssid, ctx->scratch->ptr1,2200IEEE80211_NWID_LEN);2201free(ctx->scratch->ptr1);2202break;2203case LEAF_wlanMeshTTL:2204wif->mesh_ttl = ctx->scratch->int1;2205break;2206case LEAF_wlanMeshPeeringEnabled:2207wif->mesh_peering = ctx->scratch->int1;2208break;2209case LEAF_wlanMeshForwardingEnabled:2210wif->mesh_forwarding = ctx->scratch->int1;2211break;2212case LEAF_wlanMeshMetric:2213wif->mesh_metric = ctx->scratch->int1;2214break;2215case LEAF_wlanMeshPath:2216wif->mesh_path = ctx->scratch->int1;2217break;2218case LEAF_wlanMeshRoutesFlush:2219return (SNMP_ERR_NOERROR);2220default:2221abort();2222}2223if (val->var.subs[sub - 1] == LEAF_wlanMeshId)2224rc = wlan_config_set_dssid(wif, wif->desired_ssid,2225strlen(wif->desired_ssid));2226else2227rc = wlan_mesh_config_set(wif, val->var.subs[sub - 1]);2228if (rc < 0)2229return (SNMP_ERR_GENERR);2230return (SNMP_ERR_NOERROR);22312232default:2233abort();2234}22352236if (val->var.subs[sub - 1] == LEAF_wlanMeshId)2237rc = wlan_config_get_dssid(wif);2238else2239rc = wlan_mesh_config_get(wif, val->var.subs[sub - 1]);2240if (rc < 0)2241return (SNMP_ERR_GENERR);22422243switch (val->var.subs[sub - 1]) {2244case LEAF_wlanMeshId:2245return (string_get(val, wif->desired_ssid, -1));2246case LEAF_wlanMeshTTL:2247val->v.integer = wif->mesh_ttl;2248break;2249case LEAF_wlanMeshPeeringEnabled:2250val->v.integer = wif->mesh_peering;2251break;2252case LEAF_wlanMeshForwardingEnabled:2253val->v.integer = wif->mesh_forwarding;2254break;2255case LEAF_wlanMeshMetric:2256val->v.integer = wif->mesh_metric;2257break;2258case LEAF_wlanMeshPath:2259val->v.integer = wif->mesh_path;2260break;2261case LEAF_wlanMeshRoutesFlush:2262val->v.integer = wlanMeshRoutesFlush_no_op;2263break;2264default:2265abort();2266}22672268return (SNMP_ERR_NOERROR);2269}22702271int2272op_wlan_mesh_neighbor(struct snmp_context *ctx __unused, struct snmp_value *val,2273uint32_t sub, uint32_t iidx __unused, enum snmp_op op)2274{2275struct wlan_peer *wip;2276struct wlan_iface *wif;22772278wlan_update_interface_list();2279wlan_update_peers();22802281switch (op) {2282case SNMP_OP_GET:2283if ((wip = wlan_mesh_get_peer(&val->var, sub, &wif)) == NULL)2284return (SNMP_ERR_NOSUCHNAME);2285break;2286case SNMP_OP_GETNEXT:2287wip = wlan_mesh_get_next_peer(&val->var, sub, &wif);2288if (wip == NULL)2289return (SNMP_ERR_NOSUCHNAME);2290wlan_append_mac_index(&val->var, sub, wif->wname,2291wip->pmac);2292break;2293case SNMP_OP_SET:2294return (SNMP_ERR_NOT_WRITEABLE);2295case SNMP_OP_COMMIT:2296/* FALLTHROUGH */2297case SNMP_OP_ROLLBACK:2298/* FALLTHROUGH */2299default:2300abort();2301}23022303switch (val->var.subs[sub - 1]) {2304case LEAF_wlanMeshNeighborAddress:2305return (string_get(val, wip->pmac, IEEE80211_ADDR_LEN));2306case LEAF_wlanMeshNeighborFrequency:2307val->v.integer = wip->frequency;2308break;2309case LEAF_wlanMeshNeighborLocalId:2310val->v.integer = wip->local_id;2311break;2312case LEAF_wlanMeshNeighborPeerId:2313val->v.integer = wip->peer_id;2314break;2315case LEAF_wlanMeshNeighborPeerState:2316return (bits_get(val, (uint8_t *)&wip->state,2317sizeof(wip->state)));2318case LEAF_wlanMeshNeighborCurrentTXRate:2319val->v.integer = wip->txrate;2320break;2321case LEAF_wlanMeshNeighborRxSignalStrength:2322val->v.integer = wip->rssi;2323break;2324case LEAF_wlanMeshNeighborIdleTimer:2325val->v.integer = wip->idle;2326break;2327case LEAF_wlanMeshNeighborTxSequenceNo:2328val->v.integer = wip->txseqs;2329break;2330case LEAF_wlanMeshNeighborRxSequenceNo:2331val->v.integer = wip->rxseqs;2332break;2333default:2334abort();2335}23362337return (SNMP_ERR_NOERROR);2338}23392340int2341op_wlan_mesh_route(struct snmp_context *ctx, struct snmp_value *val,2342uint32_t sub, uint32_t iidx __unused, enum snmp_op op)2343{2344struct wlan_mesh_route *wmr;2345struct wlan_iface *wif;23462347wlan_update_interface_list();2348wlan_mesh_update_routes();23492350switch (op) {2351case SNMP_OP_GET:2352if ((wmr = wlan_mesh_get_route(&val->var, sub, &wif)) == NULL)2353return (SNMP_ERR_NOSUCHNAME);2354break;23552356case SNMP_OP_GETNEXT:2357wmr = wlan_mesh_get_next_route(&val->var, sub, &wif);2358if (wmr == NULL)2359return (SNMP_ERR_NOSUCHNAME);2360wlan_append_mac_index(&val->var, sub, wif->wname,2361wmr->imroute.imr_dest);2362break;23632364case SNMP_OP_SET:2365switch (val->var.subs[sub - 1]) {2366case LEAF_wlanMeshRouteDestination:2367return (SNMP_ERR_INCONS_NAME);2368case LEAF_wlanMeshRouteStatus:2369return(wlan_mesh_route_set_status(ctx, val, sub));2370default:2371return (SNMP_ERR_NOT_WRITEABLE);2372}2373abort();23742375case SNMP_OP_COMMIT:2376if ((wmr = wlan_mesh_get_route(&val->var, sub, &wif)) == NULL)2377return (SNMP_ERR_NOSUCHNAME);2378if (val->v.integer == RowStatus_destroy &&2379wlan_mesh_delete_route(wif, wmr) < 0)2380return (SNMP_ERR_GENERR);2381return (SNMP_ERR_NOERROR);23822383case SNMP_OP_ROLLBACK:2384if ((wmr = wlan_mesh_get_route(&val->var, sub, &wif)) == NULL)2385return (SNMP_ERR_NOSUCHNAME);2386if (ctx->scratch->int1 == RowStatus_destroy &&2387wlan_mesh_delete_route(wif, wmr) < 0)2388return (SNMP_ERR_GENERR);2389return (SNMP_ERR_NOERROR);23902391default:2392abort();2393}23942395switch (val->var.subs[sub - 1]) {2396case LEAF_wlanMeshRouteDestination:2397return (string_get(val, wmr->imroute.imr_dest,2398IEEE80211_ADDR_LEN));2399case LEAF_wlanMeshRouteNextHop:2400return (string_get(val, wmr->imroute.imr_nexthop,2401IEEE80211_ADDR_LEN));2402case LEAF_wlanMeshRouteHops:2403val->v.integer = wmr->imroute.imr_nhops;2404break;2405case LEAF_wlanMeshRouteMetric:2406val->v.integer = wmr->imroute.imr_metric;2407break;2408case LEAF_wlanMeshRouteLifeTime:2409val->v.integer = wmr->imroute.imr_lifetime;2410break;2411case LEAF_wlanMeshRouteLastMseq:2412val->v.integer = wmr->imroute.imr_lastmseq;2413break;2414case LEAF_wlanMeshRouteFlags:2415val->v.integer = 0;2416if ((wmr->imroute.imr_flags &2417IEEE80211_MESHRT_FLAGS_VALID) != 0)2418val->v.integer |= (0x1 << wlanMeshRouteFlags_valid);2419if ((wmr->imroute.imr_flags &2420IEEE80211_MESHRT_FLAGS_PROXY) != 0)2421val->v.integer |= (0x1 << wlanMeshRouteFlags_proxy);2422return (bits_get(val, (uint8_t *)&val->v.integer,2423sizeof(val->v.integer)));2424case LEAF_wlanMeshRouteStatus:2425val->v.integer = wmr->mroute_status;2426break;2427}24282429return (SNMP_ERR_NOERROR);2430}24312432int2433op_wlan_mesh_stats(struct snmp_context *ctx __unused, struct snmp_value *val,2434uint32_t sub, uint32_t iidx __unused, enum snmp_op op)2435{2436struct wlan_iface *wif;24372438wlan_update_interface_list();24392440switch (op) {2441case SNMP_OP_GET:2442if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)2443return (SNMP_ERR_NOSUCHNAME);2444break;2445case SNMP_OP_GETNEXT:2446if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)2447return (SNMP_ERR_NOSUCHNAME);2448wlan_append_ifindex(&val->var, sub, wif);2449break;2450case SNMP_OP_SET:2451return (SNMP_ERR_NOT_WRITEABLE);2452case SNMP_OP_COMMIT:2453/* FALLTHROUGH */2454case SNMP_OP_ROLLBACK:2455/* FALLTHROUGH */2456default:2457abort();2458}24592460if (wlan_get_stats(wif) < 0)2461return (SNMP_ERR_GENERR);24622463switch (val->var.subs[sub - 1]) {2464case LEAF_wlanMeshDroppedBadSta:2465val->v.uint32 = wif->stats.is_mesh_wrongmesh;2466break;2467case LEAF_wlanMeshDroppedNoLink:2468val->v.uint32 = wif->stats.is_mesh_nolink;2469break;2470case LEAF_wlanMeshNoFwdTtl:2471val->v.uint32 = wif->stats.is_mesh_fwd_ttl;2472break;2473case LEAF_wlanMeshNoFwdBuf:2474val->v.uint32 = wif->stats.is_mesh_fwd_nobuf;2475break;2476case LEAF_wlanMeshNoFwdTooShort:2477val->v.uint32 = wif->stats.is_mesh_fwd_tooshort;2478break;2479case LEAF_wlanMeshNoFwdDisabled:2480val->v.uint32 = wif->stats.is_mesh_fwd_disabled;2481break;2482case LEAF_wlanMeshNoFwdPathUnknown:2483val->v.uint32 = wif->stats.is_mesh_fwd_nopath;2484break;2485case LEAF_wlanMeshDroppedBadAE:2486val->v.uint32 = wif->stats.is_mesh_badae;2487break;2488case LEAF_wlanMeshRouteAddFailed:2489val->v.uint32 = wif->stats.is_mesh_rtaddfailed;2490break;2491case LEAF_wlanMeshDroppedNoProxy:2492val->v.uint32 = wif->stats.is_mesh_notproxy;2493break;2494case LEAF_wlanMeshDroppedMisaligned:2495val->v.uint32 = wif->stats.is_rx_badalign;2496break;2497default:2498abort();2499}25002501return (SNMP_ERR_NOERROR);2502}25032504int2505op_wlan_hwmp_config(struct snmp_context *ctx, struct snmp_value *val,2506uint32_t sub, uint32_t iidx __unused, enum snmp_op op)2507{2508int which;25092510switch (val->var.subs[sub - 1]) {2511case LEAF_wlanHWMPRouteInactiveTimeout:2512which = WLAN_HWMP_INACTIVITY_TO;2513break;2514case LEAF_wlanHWMPRootAnnounceInterval:2515which = WLAN_HWMP_RANN_INT;2516break;2517case LEAF_wlanHWMPRootInterval:2518which = WLAN_HWMP_ROOT_INT;2519break;2520case LEAF_wlanHWMPRootTimeout:2521which = WLAN_HWMP_ROOT_TO;2522break;2523case LEAF_wlanHWMPPathLifetime:2524which = WLAN_HWMP_PATH_LIFETIME;2525break;2526case LEAF_wlanHWMPReplyForwardBit:2527which = WLAN_HWMP_REPLY_FORWARD;2528break;2529case LEAF_wlanHWMPTargetOnlyBit:2530which = WLAN_HWMP_TARGET_ONLY;2531break;2532default:2533abort();2534}25352536switch (op) {2537case SNMP_OP_GET:2538if (wlan_do_sysctl(&wlan_config, which, 0) < 0)2539return (SNMP_ERR_GENERR);2540break;25412542case SNMP_OP_GETNEXT:2543abort();25442545case SNMP_OP_SET:2546switch (val->var.subs[sub - 1]) {2547case LEAF_wlanHWMPRouteInactiveTimeout:2548ctx->scratch->int1 = wlan_config.hwmp_inact;2549wlan_config.hwmp_inact = val->v.integer;2550break;2551case LEAF_wlanHWMPRootAnnounceInterval:2552ctx->scratch->int1 = wlan_config.hwmp_rannint;2553wlan_config.hwmp_rannint = val->v.integer;2554break;2555case LEAF_wlanHWMPRootInterval:2556ctx->scratch->int1 = wlan_config.hwmp_rootint;2557wlan_config.hwmp_rootint = val->v.integer;2558break;2559case LEAF_wlanHWMPRootTimeout:2560ctx->scratch->int1 = wlan_config.hwmp_roottimeout;2561wlan_config.hwmp_roottimeout = val->v.integer;2562break;2563case LEAF_wlanHWMPPathLifetime:2564ctx->scratch->int1 = wlan_config.hwmp_pathlifetime;2565wlan_config.hwmp_pathlifetime = val->v.integer;2566break;2567case LEAF_wlanHWMPReplyForwardBit:2568ctx->scratch->int1 = wlan_config.hwmp_replyforward;2569wlan_config.hwmp_replyforward = val->v.integer;2570break;2571case LEAF_wlanHWMPTargetOnlyBit:2572ctx->scratch->int1 = wlan_config.hwmp_targetonly;2573wlan_config.hwmp_targetonly = val->v.integer;2574break;2575}2576if (wlan_do_sysctl(&wlan_config, which, 1) < 0)2577return (SNMP_ERR_GENERR);2578return (SNMP_ERR_NOERROR);25792580case SNMP_OP_COMMIT:2581return (SNMP_ERR_NOERROR);25822583case SNMP_OP_ROLLBACK:2584switch (val->var.subs[sub - 1]) {2585case LEAF_wlanHWMPRouteInactiveTimeout:2586wlan_config.hwmp_inact = ctx->scratch->int1;2587break;2588case LEAF_wlanHWMPRootAnnounceInterval:2589wlan_config.hwmp_rannint = ctx->scratch->int1;2590break;2591case LEAF_wlanHWMPRootInterval:2592wlan_config.hwmp_rootint = ctx->scratch->int1;2593break;2594case LEAF_wlanHWMPRootTimeout:2595wlan_config.hwmp_roottimeout = ctx->scratch->int1;2596break;2597case LEAF_wlanHWMPPathLifetime:2598wlan_config.hwmp_pathlifetime = ctx->scratch->int1;2599break;2600case LEAF_wlanHWMPReplyForwardBit:2601wlan_config.hwmp_replyforward = ctx->scratch->int1;2602break;2603case LEAF_wlanHWMPTargetOnlyBit:2604wlan_config.hwmp_targetonly = ctx->scratch->int1;2605break;2606}2607if (wlan_do_sysctl(&wlan_config, which, 1) < 0)2608return (SNMP_ERR_GENERR);2609return (SNMP_ERR_NOERROR);26102611default:2612abort();2613}26142615switch (val->var.subs[sub - 1]) {2616case LEAF_wlanHWMPRouteInactiveTimeout:2617val->v.integer = wlan_config.hwmp_inact;2618break;2619case LEAF_wlanHWMPRootAnnounceInterval:2620val->v.integer = wlan_config.hwmp_rannint;2621break;2622case LEAF_wlanHWMPRootInterval:2623val->v.integer = wlan_config.hwmp_rootint;2624break;2625case LEAF_wlanHWMPRootTimeout:2626val->v.integer = wlan_config.hwmp_roottimeout;2627break;2628case LEAF_wlanHWMPPathLifetime:2629val->v.integer = wlan_config.hwmp_pathlifetime;2630break;2631case LEAF_wlanHWMPReplyForwardBit:2632val->v.integer = wlan_config.hwmp_replyforward;2633break;2634case LEAF_wlanHWMPTargetOnlyBit:2635val->v.integer = wlan_config.hwmp_targetonly;2636break;2637}26382639return (SNMP_ERR_NOERROR);2640}26412642int2643op_wlan_hwmp_iface(struct snmp_context *ctx, struct snmp_value *val,2644uint32_t sub, uint32_t iidx __unused, enum snmp_op op)2645{2646struct wlan_iface *wif;26472648wlan_update_interface_list();26492650switch (op) {2651case SNMP_OP_GET:2652if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)2653return (SNMP_ERR_NOSUCHNAME);2654break;26552656case SNMP_OP_GETNEXT:2657if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)2658return (SNMP_ERR_NOSUCHNAME);2659wlan_append_ifindex(&val->var, sub, wif);2660break;26612662case SNMP_OP_SET:2663if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)2664return (SNMP_ERR_NOSUCHNAME);2665switch (val->var.subs[sub - 1]) {2666case LEAF_wlanHWMPRootMode:2667ctx->scratch->int1 = wif->hwmp_root_mode;2668wif->hwmp_root_mode = val->v.integer;2669break;2670case LEAF_wlanHWMPMaxHops:2671ctx->scratch->int1 = wif->hwmp_max_hops;2672wif->hwmp_max_hops = val->v.integer;2673break;2674default:2675abort();2676}2677if (wlan_hwmp_config_set(wif, val->var.subs[sub - 1]) < 0)2678return (SNMP_ERR_GENERR);2679return (SNMP_ERR_NOERROR);26802681case SNMP_OP_COMMIT:2682return (SNMP_ERR_NOERROR);26832684case SNMP_OP_ROLLBACK:2685if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)2686return (SNMP_ERR_NOSUCHNAME);2687switch (val->var.subs[sub - 1]) {2688case LEAF_wlanHWMPRootMode:2689wif->hwmp_root_mode = ctx->scratch->int1;2690break;2691case LEAF_wlanHWMPMaxHops:2692wif->hwmp_max_hops = ctx->scratch->int1;2693break;2694default:2695abort();2696}2697if (wlan_hwmp_config_set(wif, val->var.subs[sub - 1]) < 0)2698return (SNMP_ERR_GENERR);2699return (SNMP_ERR_NOERROR);27002701default:2702abort();2703}27042705if (wlan_hwmp_config_get(wif, val->var.subs[sub - 1]) < 0)2706return (SNMP_ERR_GENERR);27072708switch (val->var.subs[sub - 1]) {2709case LEAF_wlanHWMPRootMode:2710val->v.integer = wif->hwmp_root_mode;2711break;2712case LEAF_wlanHWMPMaxHops:2713val->v.integer = wif->hwmp_max_hops;2714break;2715default:2716abort();2717}27182719return (SNMP_ERR_NOERROR);2720}27212722int2723op_wlan_hwmp_stats(struct snmp_context *ctx __unused, struct snmp_value *val,2724uint32_t sub, uint32_t iidx __unused, enum snmp_op op)2725{2726struct wlan_iface *wif;27272728wlan_update_interface_list();27292730switch (op) {2731case SNMP_OP_GET:2732if ((wif = wlan_mesh_get_iface(&val->var, sub)) == NULL)2733return (SNMP_ERR_NOSUCHNAME);2734break;2735case SNMP_OP_GETNEXT:2736if ((wif = wlan_mesh_get_next_iface(&val->var, sub)) == NULL)2737return (SNMP_ERR_NOSUCHNAME);2738wlan_append_ifindex(&val->var, sub, wif);2739break;2740case SNMP_OP_SET:2741return (SNMP_ERR_NOT_WRITEABLE);2742case SNMP_OP_COMMIT:2743/* FALLTHROUGH */2744case SNMP_OP_ROLLBACK:2745/* FALLTHROUGH */2746default:2747abort();2748}27492750if (wlan_get_stats(wif) < 0)2751return (SNMP_ERR_GENERR);27522753switch (val->var.subs[sub - 1]) {2754case LEAF_wlanMeshHWMPWrongSeqNo:2755val->v.uint32 = wif->stats.is_hwmp_wrongseq;2756break;2757case LEAF_wlanMeshHWMPTxRootPREQ:2758val->v.uint32 = wif->stats.is_hwmp_rootreqs;2759break;2760case LEAF_wlanMeshHWMPTxRootRANN:2761val->v.uint32 = wif->stats.is_hwmp_rootrann;2762break;2763case LEAF_wlanMeshHWMPProxy:2764val->v.uint32 = wif->stats.is_hwmp_proxy;2765break;2766default:2767abort();2768}27692770return (SNMP_ERR_NOERROR);2771}27722773/*2774* Encode BITS type for a response packet - XXX: this belongs to the snmp lib.2775*/2776static int2777bits_get(struct snmp_value *value, const u_char *ptr, ssize_t len)2778{2779int size;27802781if (ptr == NULL) {2782value->v.octetstring.len = 0;2783value->v.octetstring.octets = NULL;2784return (SNMP_ERR_NOERROR);2785}27862787/* Determine length - up to 8 octets supported so far. */2788for (size = len; size > 0; size--)2789if (ptr[size - 1] != 0)2790break;2791if (size == 0)2792size = 1;27932794value->v.octetstring.len = (u_long)size;2795if ((value->v.octetstring.octets = malloc((size_t)size)) == NULL)2796return (SNMP_ERR_RES_UNAVAIL);2797memcpy(value->v.octetstring.octets, ptr, (size_t)size);2798return (SNMP_ERR_NOERROR);2799}28002801/*2802* Calls for adding/updating/freeing/etc of wireless interfaces.2803*/2804static void2805wlan_free_interface(struct wlan_iface *wif)2806{2807wlan_free_peerlist(wif);2808free(wif->chanlist);2809wlan_scan_free_results(wif);2810wlan_mac_free_maclist(wif);2811wlan_mesh_free_routes(wif);2812free(wif);2813}28142815static void2816wlan_free_iflist(void)2817{2818struct wlan_iface *w;28192820while ((w = SLIST_FIRST(&wlan_ifaces)) != NULL) {2821SLIST_REMOVE_HEAD(&wlan_ifaces, w_if);2822wlan_free_interface(w);2823}2824}28252826static struct wlan_iface *2827wlan_find_interface(const char *wname)2828{2829struct wlan_iface *wif;28302831SLIST_FOREACH(wif, &wlan_ifaces, w_if)2832if (strcmp(wif->wname, wname) == 0) {2833if (wif->status != RowStatus_active)2834return (NULL);2835break;2836}28372838return (wif);2839}28402841static struct wlan_iface *2842wlan_first_interface(void)2843{2844return (SLIST_FIRST(&wlan_ifaces));2845}28462847static struct wlan_iface *2848wlan_next_interface(struct wlan_iface *wif)2849{2850if (wif == NULL)2851return (NULL);28522853return (SLIST_NEXT(wif, w_if));2854}28552856/*2857* Add a new interface to the list - sorted by name.2858*/2859static int2860wlan_add_wif(struct wlan_iface *wif)2861{2862int cmp;2863struct wlan_iface *temp, *prev;28642865if ((prev = SLIST_FIRST(&wlan_ifaces)) == NULL ||2866strcmp(wif->wname, prev->wname) < 0) {2867SLIST_INSERT_HEAD(&wlan_ifaces, wif, w_if);2868return (0);2869}28702871SLIST_FOREACH(temp, &wlan_ifaces, w_if) {2872if ((cmp = strcmp(wif->wname, temp->wname)) <= 0)2873break;2874prev = temp;2875}28762877if (temp == NULL)2878SLIST_INSERT_AFTER(prev, wif, w_if);2879else if (cmp > 0)2880SLIST_INSERT_AFTER(temp, wif, w_if);2881else {2882syslog(LOG_ERR, "Wlan iface %s already in list", wif->wname);2883return (-1);2884}28852886return (0);2887}28882889static struct wlan_iface *2890wlan_new_wif(char *wname)2891{2892struct wlan_iface *wif;28932894/* Make sure it's not in the list. */2895for (wif = wlan_first_interface(); wif != NULL;2896wif = wlan_next_interface(wif))2897if (strcmp(wname, wif->wname) == 0) {2898wif->internal = 0;2899return (wif);2900}29012902if ((wif = (struct wlan_iface *)malloc(sizeof(*wif))) == NULL)2903return (NULL);29042905memset(wif, 0, sizeof(struct wlan_iface));2906strlcpy(wif->wname, wname, IFNAMSIZ);2907wif->status = RowStatus_notReady;2908wif->state = wlanIfaceState_down;2909wif->mode = WlanIfaceOperatingModeType_station;29102911if (wlan_add_wif(wif) < 0) {2912free(wif);2913return (NULL);2914}29152916return (wif);2917}29182919static void2920wlan_delete_wif(struct wlan_iface *wif)2921{2922SLIST_REMOVE(&wlan_ifaces, wif, wlan_iface, w_if);2923wlan_free_interface(wif);2924}29252926static int2927wlan_attach_newif(struct mibif *mif)2928{2929struct wlan_iface *wif;29302931if (mif->mib.ifmd_data.ifi_type != IFT_ETHER ||2932wlan_check_media(mif->name) != IFM_IEEE80211)2933return (0);29342935if ((wif = wlan_new_wif(mif->name)) == NULL)2936return (-1);29372938(void)wlan_get_opmode(wif);2939wif->index = mif->index;2940wif->status = RowStatus_active;2941(void)wlan_update_interface(wif);29422943return (0);2944}29452946static int2947wlan_iface_create(struct wlan_iface *wif)2948{2949int rc;29502951if ((rc = wlan_clone_create(wif)) == SNMP_ERR_NOERROR) {2952/*2953* The rest of the info will be updated once the2954* snmp_mibII module notifies us of the interface.2955*/2956wif->status = RowStatus_active;2957if (wif->state == wlanIfaceState_up)2958(void)wlan_config_state(wif, 1);2959}29602961return (rc);2962}29632964static int2965wlan_iface_destroy(struct wlan_iface *wif)2966{2967int rc = SNMP_ERR_NOERROR;29682969if (wif->internal == 0)2970rc = wlan_clone_destroy(wif);29712972if (rc == SNMP_ERR_NOERROR)2973wlan_delete_wif(wif);29742975return (rc);2976}29772978static int2979wlan_update_interface(struct wlan_iface *wif)2980{2981int i;29822983(void)wlan_config_state(wif, 0);2984(void)wlan_get_driver_caps(wif);2985for (i = LEAF_wlanIfacePacketBurst;2986i <= LEAF_wlanIfaceTdmaBeaconInterval; i++)2987(void)wlan_config_get_ioctl(wif, i);2988(void)wlan_get_stats(wif);2989/*2990* XXX: wlan_get_channel_list() not needed -2991* fetched with wlan_get_driver_caps()2992*/2993(void)wlan_get_channel_list(wif);2994(void)wlan_get_roam_params(wif);2995(void)wlan_get_tx_params(wif);2996(void)wlan_get_scan_results(wif);2997(void)wlan_get_wepmode(wif);2998(void)wlan_get_weptxkey(wif);2999(void)wlan_get_mac_policy(wif);3000(void)wlan_get_mac_acl_macs(wif);3001(void)wlan_get_peerinfo(wif);30023003if (wif->mode == WlanIfaceOperatingModeType_meshPoint) {3004for (i = LEAF_wlanMeshTTL; i <= LEAF_wlanMeshPath; i++)3005(void)wlan_mesh_config_get(wif, i);3006(void)wlan_mesh_get_routelist(wif);3007for (i = LEAF_wlanHWMPRootMode; i <= LEAF_wlanHWMPMaxHops; i++)3008(void)wlan_hwmp_config_get(wif, i);3009}30103011return (0);3012}30133014static void3015wlan_update_interface_list(void)3016{3017struct wlan_iface *wif, *twif;30183019if ((time(NULL) - wlan_iflist_age) <= WLAN_LIST_MAXAGE)3020return;30213022/*3023* The snmp_mibII module would have notified us for new interfaces,3024* so only check if any have been deleted.3025*/3026SLIST_FOREACH_SAFE(wif, &wlan_ifaces, w_if, twif)3027if (wif->status == RowStatus_active && wlan_get_opmode(wif) < 0)3028wlan_delete_wif(wif);30293030wlan_iflist_age = time(NULL);3031}30323033static void3034wlan_append_ifindex(struct asn_oid *oid, uint sub, const struct wlan_iface *w)3035{3036uint32_t i;30373038oid->len = sub + strlen(w->wname) + 1;3039oid->subs[sub] = strlen(w->wname);3040for (i = 1; i <= strlen(w->wname); i++)3041oid->subs[sub + i] = w->wname[i - 1];3042}30433044static uint8_t *3045wlan_get_ifname(const struct asn_oid *oid, uint sub, uint8_t *wname)3046{3047uint32_t i;30483049memset(wname, 0, IFNAMSIZ);30503051if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)3052return (NULL);30533054for (i = 0; i < oid->subs[sub]; i++)3055wname[i] = oid->subs[sub + i + 1];3056wname[i] = '\0';30573058return (wname);3059}30603061static struct wlan_iface *3062wlan_get_interface(const struct asn_oid *oid, uint sub)3063{3064uint8_t wname[IFNAMSIZ];30653066if (wlan_get_ifname(oid, sub, wname) == NULL)3067return (NULL);30683069return (wlan_find_interface(wname));3070}30713072static struct wlan_iface *3073wlan_get_next_interface(const struct asn_oid *oid, uint sub)3074{3075uint32_t i;3076uint8_t wname[IFNAMSIZ];3077struct wlan_iface *wif;30783079if (oid->len - sub == 0) {3080for (wif = wlan_first_interface(); wif != NULL;3081wif = wlan_next_interface(wif))3082if (wif->status == RowStatus_active)3083break;3084return (wif);3085}30863087if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)3088return (NULL);30893090memset(wname, 0, IFNAMSIZ);3091for (i = 0; i < oid->subs[sub]; i++)3092wname[i] = oid->subs[sub + i + 1];3093wname[i] = '\0';3094if ((wif = wlan_find_interface(wname)) == NULL)3095return (NULL);30963097while ((wif = wlan_next_interface(wif)) != NULL)3098if (wif->status == RowStatus_active)3099break;31003101return (wif);3102}31033104static struct wlan_iface *3105wlan_get_snmp_interface(const struct asn_oid *oid, uint sub)3106{3107uint8_t wname[IFNAMSIZ];3108struct wlan_iface *wif;31093110if (wlan_get_ifname(oid, sub, wname) == NULL)3111return (NULL);31123113for (wif = wlan_first_interface(); wif != NULL;3114wif = wlan_next_interface(wif))3115if (strcmp(wif->wname, wname) == 0)3116break;31173118return (wif);3119}31203121static struct wlan_iface *3122wlan_get_next_snmp_interface(const struct asn_oid *oid, uint sub)3123{3124uint32_t i;3125uint8_t wname[IFNAMSIZ];3126struct wlan_iface *wif;31273128if (oid->len - sub == 0)3129return (wlan_first_interface());31303131if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)3132return (NULL);31333134memset(wname, 0, IFNAMSIZ);3135for (i = 0; i < oid->subs[sub]; i++)3136wname[i] = oid->subs[sub + i + 1];3137wname[i] = '\0';31383139for (wif = wlan_first_interface(); wif != NULL;3140wif = wlan_next_interface(wif))3141if (strcmp(wif->wname, wname) == 0)3142break;31433144return (wlan_next_interface(wif));3145}31463147/*3148* Decode/Append an index for tables indexed by the wireless interface3149* name and a MAC address - ACL MACs and Mesh Routes.3150*/3151static int3152wlan_mac_index_decode(const struct asn_oid *oid, uint sub,3153char *wname, uint8_t *mac)3154{3155uint32_t i;3156int mac_off;31573158if (oid->len - sub != oid->subs[sub] + 2 + IEEE80211_ADDR_LEN3159|| oid->subs[sub] >= IFNAMSIZ)3160return (-1);31613162for (i = 0; i < oid->subs[sub]; i++)3163wname[i] = oid->subs[sub + i + 1];3164wname[i] = '\0';31653166mac_off = sub + oid->subs[sub] + 1;3167if (oid->subs[mac_off] != IEEE80211_ADDR_LEN)3168return (-1);3169for (i = 0; i < IEEE80211_ADDR_LEN; i++)3170mac[i] = oid->subs[mac_off + i + 1];31713172return (0);3173}31743175static void3176wlan_append_mac_index(struct asn_oid *oid, uint sub, char *wname, uint8_t *mac)3177{3178uint32_t i;31793180oid->len = sub + strlen(wname) + IEEE80211_ADDR_LEN + 2;3181oid->subs[sub] = strlen(wname);3182for (i = 1; i <= strlen(wname); i++)3183oid->subs[sub + i] = wname[i - 1];31843185sub += strlen(wname) + 1;3186oid->subs[sub] = IEEE80211_ADDR_LEN;3187for (i = 1; i <= IEEE80211_ADDR_LEN; i++)3188oid->subs[sub + i] = mac[i - 1];3189}31903191/*3192* Decode/Append an index for tables indexed by the wireless interface3193* name and the PHY mode - Roam and TX params.3194*/3195static int3196wlan_phy_index_decode(const struct asn_oid *oid, uint sub, char *wname,3197uint32_t *phy)3198{3199uint32_t i;32003201if (oid->len - sub != oid->subs[sub] + 2 || oid->subs[sub] >= IFNAMSIZ)3202return (-1);32033204for (i = 0; i < oid->subs[sub]; i++)3205wname[i] = oid->subs[sub + i + 1];3206wname[i] = '\0';32073208*phy = oid->subs[sub + oid->subs[sub] + 1];3209return (0);3210}32113212static void3213wlan_append_phy_index(struct asn_oid *oid, uint sub, char *wname, uint32_t phy)3214{3215uint32_t i;32163217oid->len = sub + strlen(wname) + 2;3218oid->subs[sub] = strlen(wname);3219for (i = 1; i <= strlen(wname); i++)3220oid->subs[sub + i] = wname[i - 1];3221oid->subs[sub + strlen(wname) + 1] = phy;3222}32233224/*3225* Calls for manipulating the peerlist of a wireless interface.3226*/3227static void3228wlan_free_peerlist(struct wlan_iface *wif)3229{3230struct wlan_peer *wip;32313232while ((wip = SLIST_FIRST(&wif->peerlist)) != NULL) {3233SLIST_REMOVE_HEAD(&wif->peerlist, wp);3234free(wip);3235}32363237SLIST_INIT(&wif->peerlist);3238}32393240static struct wlan_peer *3241wlan_find_peer(struct wlan_iface *wif, uint8_t *peermac)3242{3243struct wlan_peer *wip;32443245SLIST_FOREACH(wip, &wif->peerlist, wp)3246if (memcmp(wip->pmac, peermac, IEEE80211_ADDR_LEN) == 0)3247break;32483249return (wip);3250}32513252struct wlan_peer *3253wlan_new_peer(const uint8_t *pmac)3254{3255struct wlan_peer *wip;32563257if ((wip = (struct wlan_peer *)malloc(sizeof(*wip))) == NULL)3258return (NULL);32593260memset(wip, 0, sizeof(struct wlan_peer));3261memcpy(wip->pmac, pmac, IEEE80211_ADDR_LEN);32623263return (wip);3264}32653266void3267wlan_free_peer(struct wlan_peer *wip)3268{3269free(wip);3270}32713272int3273wlan_add_peer(struct wlan_iface *wif, struct wlan_peer *wip)3274{3275struct wlan_peer *temp, *prev;32763277SLIST_FOREACH(temp, &wif->peerlist, wp)3278if (memcmp(temp->pmac, wip->pmac, IEEE80211_ADDR_LEN) == 0)3279return (-1);32803281if ((prev = SLIST_FIRST(&wif->peerlist)) == NULL ||3282memcmp(wip->pmac, prev->pmac, IEEE80211_ADDR_LEN) < 0) {3283SLIST_INSERT_HEAD(&wif->peerlist, wip, wp);3284return (0);3285}32863287SLIST_FOREACH(temp, &wif->peerlist, wp) {3288if (memcmp(wip->pmac, temp->pmac, IEEE80211_ADDR_LEN) < 0)3289break;3290prev = temp;3291}32923293SLIST_INSERT_AFTER(prev, wip, wp);3294return (0);3295}32963297static void3298wlan_update_peers(void)3299{3300struct wlan_iface *wif;33013302if ((time(NULL) - wlan_peerlist_age) <= WLAN_LIST_MAXAGE)3303return;33043305for (wif = wlan_first_interface(); wif != NULL;3306wif = wlan_next_interface(wif)) {3307if (wif->status != RowStatus_active)3308continue;3309wlan_free_peerlist(wif);3310(void)wlan_get_peerinfo(wif);3311}3312wlan_peerlist_age = time(NULL);3313}33143315static struct wlan_peer *3316wlan_get_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)3317{3318char wname[IFNAMSIZ];3319uint8_t pmac[IEEE80211_ADDR_LEN];33203321if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0)3322return (NULL);33233324if ((*wif = wlan_find_interface(wname)) == NULL)3325return (NULL);33263327return (wlan_find_peer(*wif, pmac));3328}33293330static struct wlan_peer *3331wlan_get_next_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)3332{3333char wname[IFNAMSIZ];3334char pmac[IEEE80211_ADDR_LEN];3335struct wlan_peer *wip;33363337if (oid->len - sub == 0) {3338for (*wif = wlan_first_interface(); *wif != NULL;3339*wif = wlan_next_interface(*wif)) {3340if ((*wif)->mode ==3341WlanIfaceOperatingModeType_meshPoint)3342continue;3343wip = SLIST_FIRST(&(*wif)->peerlist);3344if (wip != NULL)3345return (wip);3346}3347return (NULL);3348}33493350if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0 ||3351(*wif = wlan_find_interface(wname)) == NULL ||3352(wip = wlan_find_peer(*wif, pmac)) == NULL)3353return (NULL);33543355if ((wip = SLIST_NEXT(wip, wp)) != NULL)3356return (wip);33573358while ((*wif = wlan_next_interface(*wif)) != NULL) {3359if ((*wif)->mode == WlanIfaceOperatingModeType_meshPoint)3360continue;3361if ((wip = SLIST_FIRST(&(*wif)->peerlist)) != NULL)3362break;3363}33643365return (wip);3366}33673368/*3369* Calls for manipulating the active channel list of a wireless interface.3370*/3371static void3372wlan_update_channels(void)3373{3374struct wlan_iface *wif;33753376if ((time(NULL) - wlan_chanlist_age) <= WLAN_LIST_MAXAGE)3377return;33783379for (wif = wlan_first_interface(); wif != NULL;3380wif = wlan_next_interface(wif)) {3381if (wif->status != RowStatus_active)3382continue;3383(void)wlan_get_channel_list(wif);3384}3385wlan_chanlist_age = time(NULL);3386}33873388static int3389wlan_channel_index_decode(const struct asn_oid *oid, uint sub, char *wname,3390uint32_t *cindex)3391{3392uint32_t i;3393if (oid->len - sub != oid->subs[sub] + 2 || oid->subs[sub] >= IFNAMSIZ)3394return (-1);33953396for (i = 0; i < oid->subs[sub]; i++)3397wname[i] = oid->subs[sub + i + 1];3398wname[i] = '\0';33993400*cindex = oid->subs[sub + oid->subs[sub] + 1];34013402return (0);3403}34043405static void3406wlan_append_channel_index(struct asn_oid *oid, uint sub,3407const struct wlan_iface *wif, const struct ieee80211_channel *channel)3408{3409uint32_t i;34103411oid->len = sub + strlen(wif->wname) + 2;3412oid->subs[sub] = strlen(wif->wname);3413for (i = 1; i <= strlen(wif->wname); i++)3414oid->subs[sub + i] = wif->wname[i - 1];3415oid->subs[sub + strlen(wif->wname) + 1] = (channel - wif->chanlist) + 1;3416}34173418static int32_t3419wlan_get_channel_type(struct ieee80211_channel *c)3420{3421if (IEEE80211_IS_CHAN_FHSS(c))3422return (WlanChannelType_fhss);3423if (IEEE80211_IS_CHAN_A(c))3424return (WlanChannelType_dot11a);3425if (IEEE80211_IS_CHAN_B(c))3426return (WlanChannelType_dot11b);3427if (IEEE80211_IS_CHAN_ANYG(c))3428return (WlanChannelType_dot11g);3429if (IEEE80211_IS_CHAN_HALF(c))3430return (WlanChannelType_tenMHz);3431if (IEEE80211_IS_CHAN_QUARTER(c))3432return (WlanChannelType_fiveMHz);3433if (IEEE80211_IS_CHAN_TURBO(c))3434return (WlanChannelType_turbo);3435if (IEEE80211_IS_CHAN_HT(c))3436return (WlanChannelType_ht);34373438return (-1);3439}34403441static struct ieee80211_channel *3442wlan_find_channel(struct wlan_iface *wif, uint32_t cindex)3443{3444if (wif->chanlist == NULL || cindex > wif->nchannels)3445return (NULL);34463447return (wif->chanlist + cindex - 1);3448}34493450static struct ieee80211_channel *3451wlan_get_channel(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)3452{3453uint32_t cindex;3454char wname[IFNAMSIZ];34553456if (wlan_channel_index_decode(oid, sub, wname, &cindex) < 0)3457return (NULL);34583459if ((*wif = wlan_find_interface(wname)) == NULL)3460return (NULL);34613462return (wlan_find_channel(*wif, cindex));3463}34643465static struct ieee80211_channel *3466wlan_get_next_channel(const struct asn_oid *oid, uint sub,3467struct wlan_iface **wif)3468{3469uint32_t cindex;3470char wname[IFNAMSIZ];34713472if (oid->len - sub == 0) {3473for (*wif = wlan_first_interface(); *wif != NULL;3474*wif = wlan_next_interface(*wif)) {3475if ((*wif)->status != RowStatus_active)3476continue;3477if ((*wif)->nchannels != 0 && (*wif)->chanlist != NULL)3478return ((*wif)->chanlist);3479}3480return (NULL);3481}34823483if (wlan_channel_index_decode(oid, sub, wname, &cindex) < 0)3484return (NULL);34853486if ((*wif = wlan_find_interface(wname)) == NULL)3487return (NULL);34883489if (cindex < (*wif)->nchannels)3490return ((*wif)->chanlist + cindex);34913492while ((*wif = wlan_next_interface(*wif)) != NULL)3493if ((*wif)->status == RowStatus_active)3494if ((*wif)->nchannels != 0 && (*wif)->chanlist != NULL)3495return ((*wif)->chanlist);34963497return (NULL);3498}34993500/*3501* Calls for manipulating the roam params of a wireless interface.3502*/3503static void3504wlan_update_roam_params(void)3505{3506struct wlan_iface *wif;35073508if ((time(NULL) - wlan_roamlist_age) <= WLAN_LIST_MAXAGE)3509return;35103511for (wif = wlan_first_interface(); wif != NULL;3512wif = wlan_next_interface(wif)) {3513if (wif->status != RowStatus_active)3514continue;3515(void)wlan_get_roam_params(wif);3516}3517wlan_roamlist_age = time(NULL);3518}35193520static struct ieee80211_roamparam *3521wlan_get_roam_param(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)3522{3523uint32_t phy;3524char wname[IFNAMSIZ];35253526if (wlan_phy_index_decode(oid, sub, wname, &phy) < 0)3527return (NULL);35283529if ((*wif = wlan_find_interface(wname)) == NULL)3530return (NULL);35313532if (phy == 0 || phy > IEEE80211_MODE_MAX)3533return (NULL);35343535return ((*wif)->roamparams.params + phy - 1);3536}35373538static struct ieee80211_roamparam *3539wlan_get_next_roam_param(const struct asn_oid *oid, uint sub,3540struct wlan_iface **wif, uint32_t *phy)3541{3542char wname[IFNAMSIZ];35433544if (oid->len - sub == 0) {3545for (*wif = wlan_first_interface(); *wif != NULL;3546*wif = wlan_next_interface(*wif)) {3547if ((*wif)->status != RowStatus_active)3548continue;3549*phy = 1;3550return ((*wif)->roamparams.params);3551}3552return (NULL);3553}35543555if (wlan_phy_index_decode(oid, sub, wname, phy) < 0)3556return (NULL);35573558if (*phy == 0 || (*wif = wlan_find_interface(wname)) == NULL)3559return (NULL);35603561if (++(*phy) <= IEEE80211_MODE_MAX)3562return ((*wif)->roamparams.params + *phy - 1);35633564*phy = 1;3565while ((*wif = wlan_next_interface(*wif)) != NULL)3566if ((*wif)->status == RowStatus_active)3567return ((*wif)->roamparams.params);35683569return (NULL);3570}35713572/*3573* Calls for manipulating the tx params of a wireless interface.3574*/3575static void3576wlan_update_tx_params(void)3577{3578struct wlan_iface *wif;35793580if ((time(NULL) - wlan_tx_paramlist_age) <= WLAN_LIST_MAXAGE)3581return;35823583for (wif = wlan_first_interface(); wif != NULL;3584wif = wlan_next_interface(wif)) {3585if (wif->status != RowStatus_active)3586continue;3587(void)wlan_get_tx_params(wif);3588}35893590wlan_tx_paramlist_age = time(NULL);3591}35923593static struct ieee80211_txparam *3594wlan_get_tx_param(const struct asn_oid *oid, uint sub, struct wlan_iface **wif,3595uint32_t *phy)3596{3597char wname[IFNAMSIZ];35983599if (wlan_phy_index_decode(oid, sub, wname, phy) < 0)3600return (NULL);36013602if ((*wif = wlan_find_interface(wname)) == NULL)3603return (NULL);36043605if (*phy == 0 || *phy > IEEE80211_MODE_MAX)3606return (NULL);36073608return ((*wif)->txparams.params + *phy - 1);3609}36103611static struct ieee80211_txparam *3612wlan_get_next_tx_param(const struct asn_oid *oid, uint sub,3613struct wlan_iface **wif, uint32_t *phy)3614{3615char wname[IFNAMSIZ];36163617if (oid->len - sub == 0) {3618for (*wif = wlan_first_interface(); *wif != NULL;3619*wif = wlan_next_interface(*wif)) {3620if ((*wif)->status != RowStatus_active)3621continue;3622*phy = 1;3623return ((*wif)->txparams.params);3624}3625return (NULL);3626}36273628if (wlan_phy_index_decode(oid, sub, wname, phy) < 0)3629return (NULL);36303631if (*phy == 0 || (*wif = wlan_find_interface(wname)) == NULL)3632return (NULL);36333634if (++(*phy) <= IEEE80211_MODE_MAX)3635return ((*wif)->txparams.params + *phy - 1);36363637*phy = 1;3638while ((*wif = wlan_next_interface(*wif)) != NULL)3639if ((*wif)->status == RowStatus_active)3640return ((*wif)->txparams.params);36413642return (NULL);3643}36443645/*3646* Calls for manipulating the scan results for a wireless interface.3647*/3648static void3649wlan_scan_free_results(struct wlan_iface *wif)3650{3651struct wlan_scan_result *sr;36523653while ((sr = SLIST_FIRST(&wif->scanlist)) != NULL) {3654SLIST_REMOVE_HEAD(&wif->scanlist, wsr);3655free(sr);3656}36573658SLIST_INIT(&wif->scanlist);3659}36603661static struct wlan_scan_result *3662wlan_scan_find_result(struct wlan_iface *wif, uint8_t *ssid, uint8_t *bssid)3663{3664struct wlan_scan_result *sr;36653666SLIST_FOREACH(sr, &wif->scanlist, wsr)3667if (strlen(ssid) == strlen(sr->ssid) &&3668strcmp(sr->ssid, ssid) == 0 &&3669memcmp(sr->bssid, bssid, IEEE80211_ADDR_LEN) == 0)3670break;36713672return (sr);3673}36743675struct wlan_scan_result *3676wlan_scan_new_result(const uint8_t *ssid, const uint8_t *bssid)3677{3678struct wlan_scan_result *sr;36793680sr = (struct wlan_scan_result *)malloc(sizeof(*sr));3681if (sr == NULL)3682return (NULL);36833684memset(sr, 0, sizeof(*sr));3685if (ssid[0] != '\0')3686strlcpy(sr->ssid, ssid, IEEE80211_NWID_LEN + 1);3687memcpy(sr->bssid, bssid, IEEE80211_ADDR_LEN);36883689return (sr);3690}36913692void3693wlan_scan_free_result(struct wlan_scan_result *sr)3694{3695free(sr);3696}36973698static int3699wlan_scan_compare_result(struct wlan_scan_result *sr1,3700struct wlan_scan_result *sr2)3701{3702uint32_t i;37033704if (strlen(sr1->ssid) < strlen(sr2->ssid))3705return (-1);3706if (strlen(sr1->ssid) > strlen(sr2->ssid))3707return (1);37083709for (i = 0; i < strlen(sr1->ssid) && i < strlen(sr2->ssid); i++) {3710if (sr1->ssid[i] < sr2->ssid[i])3711return (-1);3712if (sr1->ssid[i] > sr2->ssid[i])3713return (1);3714}37153716for (i = 0; i < IEEE80211_ADDR_LEN; i++) {3717if (sr1->bssid[i] < sr2->bssid[i])3718return (-1);3719if (sr1->bssid[i] > sr2->bssid[i])3720return (1);3721}37223723return (0);3724}37253726int3727wlan_scan_add_result(struct wlan_iface *wif, struct wlan_scan_result *sr)3728{3729struct wlan_scan_result *prev, *temp;37303731SLIST_FOREACH(temp, &wif->scanlist, wsr)3732if (strlen(temp->ssid) == strlen(sr->ssid) &&3733strcmp(sr->ssid, temp->ssid) == 0 &&3734memcmp(sr->bssid, temp->bssid, IEEE80211_ADDR_LEN) == 0)3735return (-1);37363737if ((prev = SLIST_FIRST(&wif->scanlist)) == NULL ||3738wlan_scan_compare_result(sr, prev) < 0) {3739SLIST_INSERT_HEAD(&wif->scanlist, sr, wsr);3740return (0);3741}37423743SLIST_FOREACH(temp, &wif->scanlist, wsr) {3744if (wlan_scan_compare_result(sr, temp) < 0)3745break;3746prev = temp;3747}37483749SLIST_INSERT_AFTER(prev, sr, wsr);3750return (0);3751}37523753static void3754wlan_scan_update_results(void)3755{3756struct wlan_iface *wif;37573758if ((time(NULL) - wlan_scanlist_age) <= WLAN_LIST_MAXAGE)3759return;37603761for (wif = wlan_first_interface(); wif != NULL;3762wif = wlan_next_interface(wif)) {3763if (wif->status != RowStatus_active)3764continue;3765wlan_scan_free_results(wif);3766(void)wlan_get_scan_results(wif);3767}3768wlan_scanlist_age = time(NULL);3769}37703771static int3772wlan_scanr_index_decode(const struct asn_oid *oid, uint sub,3773char *wname, uint8_t *ssid, uint8_t *bssid)3774{3775uint32_t i;3776int offset;37773778if (oid->subs[sub] >= IFNAMSIZ)3779return (-1);3780for (i = 0; i < oid->subs[sub]; i++)3781wname[i] = oid->subs[sub + i + 1];3782wname[oid->subs[sub]] = '\0';37833784offset = sub + oid->subs[sub] + 1;3785if (oid->subs[offset] > IEEE80211_NWID_LEN)3786return (-1);3787for (i = 0; i < oid->subs[offset]; i++)3788ssid[i] = oid->subs[offset + i + 1];3789ssid[i] = '\0';37903791offset = sub + oid->subs[sub] + oid->subs[offset] + 2;3792if (oid->subs[offset] != IEEE80211_ADDR_LEN)3793return (-1);3794for (i = 0; i < IEEE80211_ADDR_LEN; i++)3795bssid[i] = oid->subs[offset + i + 1];37963797return (0);3798}37993800static void3801wlan_append_scanr_index(struct asn_oid *oid, uint sub, char *wname,3802uint8_t *ssid, uint8_t *bssid)3803{3804uint32_t i;38053806oid->len = sub + strlen(wname) + strlen(ssid) + IEEE80211_ADDR_LEN + 3;3807oid->subs[sub] = strlen(wname);3808for (i = 1; i <= strlen(wname); i++)3809oid->subs[sub + i] = wname[i - 1];38103811sub += strlen(wname) + 1;3812oid->subs[sub] = strlen(ssid);3813for (i = 1; i <= strlen(ssid); i++)3814oid->subs[sub + i] = ssid[i - 1];38153816sub += strlen(ssid) + 1;3817oid->subs[sub] = IEEE80211_ADDR_LEN;3818for (i = 1; i <= IEEE80211_ADDR_LEN; i++)3819oid->subs[sub + i] = bssid[i - 1];3820}38213822static struct wlan_scan_result *3823wlan_get_scanr(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)3824{3825char wname[IFNAMSIZ];3826uint8_t ssid[IEEE80211_NWID_LEN + 1];3827uint8_t bssid[IEEE80211_ADDR_LEN];38283829if (wlan_scanr_index_decode(oid, sub, wname, ssid, bssid) < 0)3830return (NULL);38313832if ((*wif = wlan_find_interface(wname)) == NULL)3833return (NULL);38343835return (wlan_scan_find_result(*wif, ssid, bssid));3836}38373838static struct wlan_scan_result *3839wlan_get_next_scanr(const struct asn_oid *oid, uint sub,3840struct wlan_iface **wif)3841{3842char wname[IFNAMSIZ];3843uint8_t ssid[IEEE80211_NWID_LEN + 1];3844uint8_t bssid[IEEE80211_ADDR_LEN];3845struct wlan_scan_result *sr;38463847if (oid->len - sub == 0) {3848for (*wif = wlan_first_interface(); *wif != NULL;3849*wif = wlan_next_interface(*wif)) {3850sr = SLIST_FIRST(&(*wif)->scanlist);3851if (sr != NULL)3852return (sr);3853}3854return (NULL);3855}38563857if (wlan_scanr_index_decode(oid, sub, wname, ssid, bssid) < 0 ||3858(*wif = wlan_find_interface(wname)) == NULL ||3859(sr = wlan_scan_find_result(*wif, ssid, bssid)) == NULL)3860return (NULL);38613862if ((sr = SLIST_NEXT(sr, wsr)) != NULL)3863return (sr);38643865while ((*wif = wlan_next_interface(*wif)) != NULL)3866if ((sr = SLIST_FIRST(&(*wif)->scanlist)) != NULL)3867break;38683869return (sr);3870}38713872/*3873* MAC Access Control.3874*/3875static void3876wlan_mac_free_maclist(struct wlan_iface *wif)3877{3878struct wlan_mac_mac *wmm;38793880while ((wmm = SLIST_FIRST(&wif->mac_maclist)) != NULL) {3881SLIST_REMOVE_HEAD(&wif->mac_maclist, wm);3882free(wmm);3883}38843885SLIST_INIT(&wif->mac_maclist);3886}38873888static struct wlan_mac_mac *3889wlan_mac_find_mac(struct wlan_iface *wif, uint8_t *mac)3890{3891struct wlan_mac_mac *wmm;38923893SLIST_FOREACH(wmm, &wif->mac_maclist, wm)3894if (memcmp(wmm->mac, mac, IEEE80211_ADDR_LEN) == 0)3895break;38963897return (wmm);3898}38993900struct wlan_mac_mac *3901wlan_mac_new_mac(const uint8_t *mac)3902{3903struct wlan_mac_mac *wmm;39043905if ((wmm = (struct wlan_mac_mac *)malloc(sizeof(*wmm))) == NULL)3906return (NULL);39073908memset(wmm, 0, sizeof(*wmm));3909memcpy(wmm->mac, mac, IEEE80211_ADDR_LEN);3910wmm->mac_status = RowStatus_notReady;39113912return (wmm);3913}39143915void3916wlan_mac_free_mac(struct wlan_mac_mac *wmm)3917{3918free(wmm);3919}39203921int3922wlan_mac_add_mac(struct wlan_iface *wif, struct wlan_mac_mac *wmm)3923{3924struct wlan_mac_mac *temp, *prev;39253926SLIST_FOREACH(temp, &wif->mac_maclist, wm)3927if (memcmp(temp->mac, wmm->mac, IEEE80211_ADDR_LEN) == 0)3928return (-1);39293930if ((prev = SLIST_FIRST(&wif->mac_maclist)) == NULL ||3931memcmp(wmm->mac, prev->mac,IEEE80211_ADDR_LEN) < 0) {3932SLIST_INSERT_HEAD(&wif->mac_maclist, wmm, wm);3933return (0);3934}39353936SLIST_FOREACH(temp, &wif->mac_maclist, wm) {3937if (memcmp(wmm->mac, temp->mac, IEEE80211_ADDR_LEN) < 0)3938break;3939prev = temp;3940}39413942SLIST_INSERT_AFTER(prev, wmm, wm);3943return (0);3944}39453946static int3947wlan_mac_delete_mac(struct wlan_iface *wif, struct wlan_mac_mac *wmm)3948{3949if (wmm->mac_status == RowStatus_active &&3950wlan_del_mac_acl_mac(wif, wmm) < 0)3951return (-1);39523953SLIST_REMOVE(&wif->mac_maclist, wmm, wlan_mac_mac, wm);3954free(wmm);39553956return (0);3957}39583959static void3960wlan_mac_update_aclmacs(void)3961{3962struct wlan_iface *wif;3963struct wlan_mac_mac *wmm, *twmm;39643965if ((time(NULL) - wlan_maclist_age) <= WLAN_LIST_MAXAGE)3966return;39673968for (wif = wlan_first_interface(); wif != NULL;3969wif = wlan_next_interface(wif)) {3970if (wif->status != RowStatus_active)3971continue;3972/*3973* Nuke old entries - XXX - they are likely not to3974* change often - reconsider.3975*/3976SLIST_FOREACH_SAFE(wmm, &wif->mac_maclist, wm, twmm)3977if (wmm->mac_status == RowStatus_active) {3978SLIST_REMOVE(&wif->mac_maclist, wmm,3979wlan_mac_mac, wm);3980wlan_mac_free_mac(wmm);3981}3982(void)wlan_get_mac_acl_macs(wif);3983}3984wlan_maclist_age = time(NULL);3985}39863987static struct wlan_mac_mac *3988wlan_get_acl_mac(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)3989{3990char wname[IFNAMSIZ];3991char mac[IEEE80211_ADDR_LEN];39923993if (wlan_mac_index_decode(oid, sub, wname, mac) < 0)3994return (NULL);39953996if ((*wif = wlan_find_interface(wname)) == NULL)3997return (NULL);39983999return (wlan_mac_find_mac(*wif, mac));4000}40014002static struct wlan_mac_mac *4003wlan_get_next_acl_mac(const struct asn_oid *oid, uint sub,4004struct wlan_iface **wif)4005{4006char wname[IFNAMSIZ];4007char mac[IEEE80211_ADDR_LEN];4008struct wlan_mac_mac *wmm;40094010if (oid->len - sub == 0) {4011for (*wif = wlan_first_interface(); *wif != NULL;4012*wif = wlan_next_interface(*wif)) {4013wmm = SLIST_FIRST(&(*wif)->mac_maclist);4014if (wmm != NULL)4015return (wmm);4016}4017return (NULL);4018}40194020if (wlan_mac_index_decode(oid, sub, wname, mac) < 0 ||4021(*wif = wlan_find_interface(wname)) == NULL ||4022(wmm = wlan_mac_find_mac(*wif, mac)) == NULL)4023return (NULL);40244025if ((wmm = SLIST_NEXT(wmm, wm)) != NULL)4026return (wmm);40274028while ((*wif = wlan_next_interface(*wif)) != NULL)4029if ((wmm = SLIST_FIRST(&(*wif)->mac_maclist)) != NULL)4030break;40314032return (wmm);4033}40344035static int4036wlan_acl_mac_set_status(struct snmp_context *ctx, struct snmp_value *val,4037uint sub)4038{4039char wname[IFNAMSIZ];4040uint8_t mac[IEEE80211_ADDR_LEN];4041struct wlan_iface *wif;4042struct wlan_mac_mac *macl;40434044if (wlan_mac_index_decode(&val->var, sub, wname, mac) < 0)4045return (SNMP_ERR_GENERR);4046macl = wlan_get_acl_mac(&val->var, sub, &wif);40474048switch (val->v.integer) {4049case RowStatus_createAndGo:4050if (macl != NULL)4051return (SNMP_ERR_INCONS_NAME);4052break;4053case RowStatus_destroy:4054if (macl == NULL)4055return (SNMP_ERR_NOSUCHNAME);4056ctx->scratch->int1 = RowStatus_active;4057return (SNMP_ERR_NOERROR);4058default:4059return (SNMP_ERR_INCONS_VALUE);4060}406140624063if (wif == NULL || !wif->macsupported)4064return (SNMP_ERR_INCONS_VALUE);40654066if ((macl = wlan_mac_new_mac((const uint8_t *)mac)) == NULL)4067return (SNMP_ERR_GENERR);40684069ctx->scratch->int1 = RowStatus_destroy;40704071if (wlan_mac_add_mac(wif, macl) < 0) {4072wlan_mac_free_mac(macl);4073return (SNMP_ERR_GENERR);4074}40754076ctx->scratch->int1 = RowStatus_destroy;4077if (wlan_add_mac_acl_mac(wif, macl) < 0) {4078(void)wlan_mac_delete_mac(wif, macl);4079return (SNMP_ERR_GENERR);4080}40814082return (SNMP_ERR_NOERROR);4083}40844085/*4086* Wireless interfaces operating as mesh points.4087*/4088static struct wlan_iface *4089wlan_mesh_first_interface(void)4090{4091struct wlan_iface *wif;40924093SLIST_FOREACH(wif, &wlan_ifaces, w_if)4094if (wif->mode == WlanIfaceOperatingModeType_meshPoint &&4095wif->status == RowStatus_active)4096break;40974098return (wif);4099}41004101static struct wlan_iface *4102wlan_mesh_next_interface(struct wlan_iface *wif)4103{4104struct wlan_iface *nwif;41054106while ((nwif = wlan_next_interface(wif)) != NULL) {4107if (nwif->mode == WlanIfaceOperatingModeType_meshPoint &&4108nwif->status == RowStatus_active)4109break;4110wif = nwif;4111}41124113return (nwif);4114}41154116static struct wlan_iface *4117wlan_mesh_get_iface(const struct asn_oid *oid, uint sub)4118{4119struct wlan_iface *wif;41204121if ((wif = wlan_get_interface(oid, sub)) == NULL)4122return (NULL);41234124if (wif->mode != WlanIfaceOperatingModeType_meshPoint)4125return (NULL);41264127return (wif);4128}41294130static struct wlan_iface *4131wlan_mesh_get_next_iface(const struct asn_oid *oid, uint sub)4132{4133uint32_t i;4134uint8_t wname[IFNAMSIZ];4135struct wlan_iface *wif;41364137if (oid->len - sub == 0)4138return (wlan_mesh_first_interface());41394140if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)4141return (NULL);41424143memset(wname, 0, IFNAMSIZ);4144for (i = 0; i < oid->subs[sub]; i++)4145wname[i] = oid->subs[sub + i + 1];4146wname[i] = '\0';41474148if ((wif = wlan_find_interface(wname)) == NULL)4149return (NULL);41504151return (wlan_mesh_next_interface(wif));4152}41534154/*4155* The neighbors of wireless interfaces operating as mesh points.4156*/4157static struct wlan_peer *4158wlan_mesh_get_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)4159{4160char wname[IFNAMSIZ];4161uint8_t pmac[IEEE80211_ADDR_LEN];41624163if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0)4164return (NULL);41654166if ((*wif = wlan_find_interface(wname)) == NULL ||4167(*wif)->mode != WlanIfaceOperatingModeType_meshPoint)4168return (NULL);41694170return (wlan_find_peer(*wif, pmac));4171}41724173static struct wlan_peer *4174wlan_mesh_get_next_peer(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)4175{4176char wname[IFNAMSIZ];4177char pmac[IEEE80211_ADDR_LEN];4178struct wlan_peer *wip;41794180if (oid->len - sub == 0) {4181for (*wif = wlan_mesh_first_interface(); *wif != NULL;4182*wif = wlan_mesh_next_interface(*wif)) {4183wip = SLIST_FIRST(&(*wif)->peerlist);4184if (wip != NULL)4185return (wip);4186}4187return (NULL);4188}41894190if (wlan_mac_index_decode(oid, sub, wname, pmac) < 0 ||4191(*wif = wlan_find_interface(wname)) == NULL ||4192(*wif)->mode != WlanIfaceOperatingModeType_meshPoint ||4193(wip = wlan_find_peer(*wif, pmac)) == NULL)4194return (NULL);41954196if ((wip = SLIST_NEXT(wip, wp)) != NULL)4197return (wip);41984199while ((*wif = wlan_mesh_next_interface(*wif)) != NULL)4200if ((wip = SLIST_FIRST(&(*wif)->peerlist)) != NULL)4201break;42024203return (wip);4204}42054206/*4207* Mesh routing table.4208*/4209static void4210wlan_mesh_free_routes(struct wlan_iface *wif)4211{4212struct wlan_mesh_route *wmr;42134214while ((wmr = SLIST_FIRST(&wif->mesh_routelist)) != NULL) {4215SLIST_REMOVE_HEAD(&wif->mesh_routelist, wr);4216free(wmr);4217}42184219SLIST_INIT(&wif->mesh_routelist);4220}42214222static struct wlan_mesh_route *4223wlan_mesh_find_route(struct wlan_iface *wif, uint8_t *dstmac)4224{4225struct wlan_mesh_route *wmr;42264227if (wif->mode != WlanIfaceOperatingModeType_meshPoint)4228return (NULL);42294230SLIST_FOREACH(wmr, &wif->mesh_routelist, wr)4231if (memcmp(wmr->imroute.imr_dest, dstmac,4232IEEE80211_ADDR_LEN) == 0)4233break;42344235return (wmr);4236}42374238struct wlan_mesh_route *4239wlan_mesh_new_route(const uint8_t *dstmac)4240{4241struct wlan_mesh_route *wmr;42424243if ((wmr = (struct wlan_mesh_route *)malloc(sizeof(*wmr))) == NULL)4244return (NULL);42454246memset(wmr, 0, sizeof(*wmr));4247memcpy(wmr->imroute.imr_dest, dstmac, IEEE80211_ADDR_LEN);4248wmr->mroute_status = RowStatus_notReady;42494250return (wmr);4251}42524253void4254wlan_mesh_free_route(struct wlan_mesh_route *wmr)4255{4256free(wmr);4257}42584259int4260wlan_mesh_add_rtentry(struct wlan_iface *wif, struct wlan_mesh_route *wmr)4261{4262struct wlan_mesh_route *temp, *prev;42634264SLIST_FOREACH(temp, &wif->mesh_routelist, wr)4265if (memcmp(temp->imroute.imr_dest, wmr->imroute.imr_dest,4266IEEE80211_ADDR_LEN) == 0)4267return (-1);42684269if ((prev = SLIST_FIRST(&wif->mesh_routelist)) == NULL ||4270memcmp(wmr->imroute.imr_dest, prev->imroute.imr_dest,4271IEEE80211_ADDR_LEN) < 0) {4272SLIST_INSERT_HEAD(&wif->mesh_routelist, wmr, wr);4273return (0);4274}42754276SLIST_FOREACH(temp, &wif->mesh_routelist, wr) {4277if (memcmp(wmr->imroute.imr_dest, temp->imroute.imr_dest,4278IEEE80211_ADDR_LEN) < 0)4279break;4280prev = temp;4281}42824283SLIST_INSERT_AFTER(prev, wmr, wr);4284return (0);4285}42864287static int4288wlan_mesh_delete_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr)4289{4290if (wmr->mroute_status == RowStatus_active &&4291wlan_mesh_del_route(wif, wmr) < 0)4292return (-1);42934294SLIST_REMOVE(&wif->mesh_routelist, wmr, wlan_mesh_route, wr);4295free(wmr);42964297return (0);4298}42994300static void4301wlan_mesh_update_routes(void)4302{4303struct wlan_iface *wif;4304struct wlan_mesh_route *wmr, *twmr;43054306if ((time(NULL) - wlan_mrlist_age) <= WLAN_LIST_MAXAGE)4307return;43084309for (wif = wlan_mesh_first_interface(); wif != NULL;4310wif = wlan_mesh_next_interface(wif)) {4311/*4312* Nuke old entries - XXX - they are likely not to4313* change often - reconsider.4314*/4315SLIST_FOREACH_SAFE(wmr, &wif->mesh_routelist, wr, twmr)4316if (wmr->mroute_status == RowStatus_active) {4317SLIST_REMOVE(&wif->mesh_routelist, wmr,4318wlan_mesh_route, wr);4319wlan_mesh_free_route(wmr);4320}4321(void)wlan_mesh_get_routelist(wif);4322}4323wlan_mrlist_age = time(NULL);4324}43254326static struct wlan_mesh_route *4327wlan_mesh_get_route(const struct asn_oid *oid, uint sub, struct wlan_iface **wif)4328{4329char wname[IFNAMSIZ];4330char dstmac[IEEE80211_ADDR_LEN];43314332if (wlan_mac_index_decode(oid, sub, wname, dstmac) < 0)4333return (NULL);43344335if ((*wif = wlan_find_interface(wname)) == NULL)4336return (NULL);43374338return (wlan_mesh_find_route(*wif, dstmac));4339}43404341static struct wlan_mesh_route *4342wlan_mesh_get_next_route(const struct asn_oid *oid, uint sub,4343struct wlan_iface **wif)4344{4345char wname[IFNAMSIZ];4346char dstmac[IEEE80211_ADDR_LEN];4347struct wlan_mesh_route *wmr;43484349if (oid->len - sub == 0) {4350for (*wif = wlan_mesh_first_interface(); *wif != NULL;4351*wif = wlan_mesh_next_interface(*wif)) {4352wmr = SLIST_FIRST(&(*wif)->mesh_routelist);4353if (wmr != NULL)4354return (wmr);4355}4356return (NULL);4357}43584359if (wlan_mac_index_decode(oid, sub, wname, dstmac) < 0 ||4360(*wif = wlan_find_interface(wname)) == NULL ||4361(wmr = wlan_mesh_find_route(*wif, dstmac)) == NULL)4362return (NULL);43634364if ((wmr = SLIST_NEXT(wmr, wr)) != NULL)4365return (wmr);43664367while ((*wif = wlan_mesh_next_interface(*wif)) != NULL)4368if ((wmr = SLIST_FIRST(&(*wif)->mesh_routelist)) != NULL)4369break;43704371return (wmr);4372}43734374static int4375wlan_mesh_route_set_status(struct snmp_context *ctx, struct snmp_value *val,4376uint sub)4377{4378char wname[IFNAMSIZ];4379char mac[IEEE80211_ADDR_LEN];4380struct wlan_mesh_route *wmr;4381struct wlan_iface *wif;43824383if (wlan_mac_index_decode(&val->var, sub, wname, mac) < 0)4384return (SNMP_ERR_GENERR);4385wmr = wlan_mesh_get_route(&val->var, sub, &wif);43864387switch (val->v.integer) {4388case RowStatus_createAndGo:4389if (wmr != NULL)4390return (SNMP_ERR_INCONS_NAME);4391break;4392case RowStatus_destroy:4393if (wmr == NULL)4394return (SNMP_ERR_NOSUCHNAME);4395ctx->scratch->int1 = RowStatus_active;4396return (SNMP_ERR_NOERROR);4397default:4398return (SNMP_ERR_INCONS_VALUE);4399}44004401if ((wif = wlan_find_interface(wname)) == NULL)4402return (SNMP_ERR_INCONS_NAME);44034404if ((wmr = wlan_mesh_new_route(mac)) == NULL)4405return (SNMP_ERR_GENERR);44064407if (wlan_mesh_add_rtentry(wif, wmr) < 0) {4408wlan_mesh_free_route(wmr);4409return (SNMP_ERR_GENERR);4410}44114412ctx->scratch->int1 = RowStatus_destroy;4413if (wlan_mesh_add_route(wif, wmr) < 0) {4414(void)wlan_mesh_delete_route(wif, wmr);4415return (SNMP_ERR_GENERR);4416}44174418return (SNMP_ERR_NOERROR);4419}44204421/*4422* Wlan snmp module initialization hook.4423* Returns 0 on success, < 0 on error.4424*/4425static int4426wlan_init(struct lmodule * mod __unused, int argc __unused,4427char *argv[] __unused)4428{4429if (wlan_kmodules_load() < 0)4430return (-1);44314432if (wlan_ioctl_init() < 0)4433return (-1);44344435/* Register for new interface creation notifications. */4436if (mib_register_newif(wlan_attach_newif, wlan_module)) {4437syslog(LOG_ERR, "Cannot register newif function: %s",4438strerror(errno));4439return (-1);4440}44414442return (0);4443}44444445/*4446* Wlan snmp module finalization hook.4447*/4448static int4449wlan_fini(void)4450{4451mib_unregister_newif(wlan_module);4452or_unregister(reg_wlan);44534454/* XXX: Cleanup! */4455wlan_free_iflist();44564457return (0);4458}44594460/*4461* Refetch all available data from the kernel.4462*/4463static void4464wlan_update_data(void *arg __unused)4465{4466}44674468/*4469* Wlan snmp module start operation.4470*/4471static void4472wlan_start(void)4473{4474struct mibif *ifp;44754476reg_wlan = or_register(&oid_wlan,4477"The MIB module for managing wireless networking.", wlan_module);44784479/* Add the existing wlan interfaces. */4480for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp))4481wlan_attach_newif(ifp);44824483wlan_data_timer = timer_start_repeat(wlan_poll_ticks,4484wlan_poll_ticks, wlan_update_data, NULL, wlan_module);4485}44864487/*4488* Dump the Wlan snmp module data on SIGUSR1.4489*/4490static void4491wlan_dump(void)4492{4493/* XXX: Print some debug info to syslog. */4494struct wlan_iface *wif;44954496for (wif = wlan_first_interface(); wif != NULL;4497wif = wlan_next_interface(wif))4498syslog(LOG_ERR, "wlan iface %s", wif->wname);4499}45004501const char wlan_comment[] = \4502"This module implements the BEGEMOT MIB for wireless networking.";45034504const struct snmp_module config = {4505.comment = wlan_comment,4506.init = wlan_init,4507.fini = wlan_fini,4508.start = wlan_start,4509.tree = wlan_ctree,4510.dump = wlan_dump,4511.tree_size = wlan_CTREE_SIZE,4512};451345144515