1164410Ssyrinx/*- 2164410Ssyrinx * Copyright (c) 2006 Shteryana Shopova <syrinx@FreeBSD.org> 3164410Ssyrinx * All rights reserved. 4164410Ssyrinx * 5164410Ssyrinx * Redistribution and use in source and binary forms, with or without 6164410Ssyrinx * modification, are permitted provided that the following conditions 7164410Ssyrinx * are met: 8164410Ssyrinx * 1. Redistributions of source code must retain the above copyright 9164410Ssyrinx * notice, this list of conditions and the following disclaimer. 10164410Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright 11164410Ssyrinx * notice, this list of conditions and the following disclaimer in the 12164410Ssyrinx * documentation and/or other materials provided with the distribution. 13164410Ssyrinx * 14164410Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15164410Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16164410Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17164410Ssyrinx * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18164410Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19164410Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20164410Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21164410Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22164410Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23164410Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24164410Ssyrinx * SUCH DAMAGE. 25164410Ssyrinx * 26164410Ssyrinx * Bridge MIB implementation for SNMPd. 27164410Ssyrinx * Bridge ports. 28164410Ssyrinx * 29164410Ssyrinx * $FreeBSD: stable/10/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c 357520 2020-02-04 19:35:40Z dim $ 30164410Ssyrinx */ 31164410Ssyrinx 32164410Ssyrinx#include <sys/queue.h> 33164410Ssyrinx#include <sys/socket.h> 34164410Ssyrinx#include <sys/types.h> 35164410Ssyrinx 36164410Ssyrinx#include <net/ethernet.h> 37164410Ssyrinx#include <net/if.h> 38164410Ssyrinx#include <net/if_mib.h> 39164410Ssyrinx 40164410Ssyrinx#include <assert.h> 41164410Ssyrinx#include <errno.h> 42164410Ssyrinx#include <stdarg.h> 43164410Ssyrinx#include <string.h> 44164410Ssyrinx#include <stdlib.h> 45164410Ssyrinx#include <syslog.h> 46164410Ssyrinx 47164410Ssyrinx#include <bsnmp/snmpmod.h> 48164410Ssyrinx#include <bsnmp/snmp_mibII.h> 49164410Ssyrinx 50164410Ssyrinx#include "bridge_tree.h" 51164410Ssyrinx#include "bridge_snmp.h" 52164410Ssyrinx 53164410SsyrinxTAILQ_HEAD(bridge_ports, bridge_port); 54164410Ssyrinx 55164410Ssyrinx/* 56164410Ssyrinx * Free the bridge base ports list. 57164410Ssyrinx */ 58164410Ssyrinxstatic void 59164410Ssyrinxbridge_ports_free(struct bridge_ports *headp) 60164410Ssyrinx{ 61164410Ssyrinx struct bridge_port *bp; 62164410Ssyrinx 63164410Ssyrinx while ((bp = TAILQ_FIRST(headp)) != NULL) { 64164410Ssyrinx TAILQ_REMOVE(headp, bp, b_p); 65164410Ssyrinx free(bp); 66164410Ssyrinx } 67164410Ssyrinx} 68164410Ssyrinx 69164410Ssyrinx/* 70164410Ssyrinx * Free the bridge base ports from the base ports list, 71164410Ssyrinx * members of a specified bridge interface only. 72164410Ssyrinx */ 73164410Ssyrinxstatic void 74164410Ssyrinxbridge_port_memif_free(struct bridge_ports *headp, 75164410Ssyrinx struct bridge_if *bif) 76164410Ssyrinx{ 77164410Ssyrinx struct bridge_port *bp; 78164410Ssyrinx 79164410Ssyrinx while (bif->f_bp != NULL && bif->sysindex == bif->f_bp->sysindex) { 80164410Ssyrinx bp = TAILQ_NEXT(bif->f_bp, b_p); 81164410Ssyrinx TAILQ_REMOVE(headp, bif->f_bp, b_p); 82164410Ssyrinx free(bif->f_bp); 83164410Ssyrinx bif->f_bp = bp; 84164410Ssyrinx } 85164410Ssyrinx} 86164410Ssyrinx 87164410Ssyrinx/* 88164410Ssyrinx * Insert a port entry in the base port TAILQ starting to search 89164410Ssyrinx * for its place from the position of the first bridge port for the bridge 90228990Suqs * interface. Update the first bridge port if necessary. 91164410Ssyrinx */ 92164410Ssyrinxstatic void 93164410Ssyrinxbridge_port_insert_at(struct bridge_ports *headp, 94164410Ssyrinx struct bridge_port *bp, struct bridge_port **f_bp) 95164410Ssyrinx{ 96164410Ssyrinx struct bridge_port *t1; 97164410Ssyrinx 98164410Ssyrinx assert(f_bp != NULL); 99164410Ssyrinx 100164410Ssyrinx for (t1 = *f_bp; 101164410Ssyrinx t1 != NULL && bp->sysindex == t1->sysindex; 102164410Ssyrinx t1 = TAILQ_NEXT(t1, b_p)) { 103164410Ssyrinx if (bp->if_idx < t1->if_idx) { 104164410Ssyrinx TAILQ_INSERT_BEFORE(t1, bp, b_p); 105164410Ssyrinx if (*f_bp == t1) 106164410Ssyrinx *f_bp = bp; 107164410Ssyrinx return; 108164410Ssyrinx } 109164410Ssyrinx } 110164410Ssyrinx 111164410Ssyrinx /* 112164410Ssyrinx * Handle the case when our first port was actually the 113164410Ssyrinx * last element of the TAILQ. 114164410Ssyrinx */ 115164410Ssyrinx if (t1 == NULL) 116164410Ssyrinx TAILQ_INSERT_TAIL(headp, bp, b_p); 117164410Ssyrinx else 118164410Ssyrinx TAILQ_INSERT_BEFORE(t1, bp, b_p); 119164410Ssyrinx} 120164410Ssyrinx 121164410Ssyrinx/* 122228990Suqs * Find a port entry's position in the ports list according 123164410Ssyrinx * to it's parent bridge interface name. Returns a NULL if 124164410Ssyrinx * we should be at the TAILQ head, otherwise the entry after 125164410Ssyrinx * which we should be inserted. 126164410Ssyrinx */ 127164410Ssyrinxstatic struct bridge_port * 128164410Ssyrinxbridge_port_find_pos(struct bridge_ports *headp, uint32_t b_idx) 129164410Ssyrinx{ 130164410Ssyrinx uint32_t t_idx; 131164410Ssyrinx struct bridge_port *t1; 132164410Ssyrinx 133164410Ssyrinx if ((t1 = TAILQ_FIRST(headp)) == NULL || 134164410Ssyrinx bridge_compare_sysidx(b_idx, t1->sysindex) < 0) 135164410Ssyrinx return (NULL); 136164410Ssyrinx 137164410Ssyrinx t_idx = t1->sysindex; 138164410Ssyrinx 139164410Ssyrinx for (t1 = TAILQ_NEXT(t1, b_p); t1 != NULL; t1 = TAILQ_NEXT(t1, b_p)) { 140164410Ssyrinx if (t1->sysindex != t_idx) { 141164410Ssyrinx if (bridge_compare_sysidx(b_idx, t1->sysindex) < 0) 142164410Ssyrinx return (TAILQ_PREV(t1, bridge_ports, b_p)); 143164410Ssyrinx else 144164410Ssyrinx t_idx = t1->sysindex; 145164410Ssyrinx } 146164410Ssyrinx } 147164410Ssyrinx 148164410Ssyrinx if (t1 == NULL) 149164410Ssyrinx t1 = TAILQ_LAST(headp, bridge_ports); 150164410Ssyrinx 151164410Ssyrinx return (t1); 152164410Ssyrinx} 153164410Ssyrinx 154164410Ssyrinx/* 155164410Ssyrinx * Insert a bridge member interface in the ports TAILQ. 156164410Ssyrinx */ 157164410Ssyrinxstatic void 158164410Ssyrinxbridge_port_memif_insert(struct bridge_ports *headp, 159164410Ssyrinx struct bridge_port *bp, struct bridge_port **f_bp) 160164410Ssyrinx{ 161164410Ssyrinx struct bridge_port *temp; 162164410Ssyrinx 163164410Ssyrinx if (*f_bp != NULL) 164164410Ssyrinx bridge_port_insert_at(headp, bp, f_bp); 165164410Ssyrinx else { 166164410Ssyrinx temp = bridge_port_find_pos(headp, bp->sysindex); 167164410Ssyrinx 168164410Ssyrinx if (temp == NULL) 169164410Ssyrinx TAILQ_INSERT_HEAD(headp, bp, b_p); 170164410Ssyrinx else 171164410Ssyrinx TAILQ_INSERT_AFTER(headp, temp, bp, b_p); 172164410Ssyrinx *f_bp = bp; 173164410Ssyrinx } 174164410Ssyrinx} 175164410Ssyrinx 176164410Ssyrinx/* The global ports list. */ 177164410Ssyrinxstatic struct bridge_ports bridge_ports = TAILQ_HEAD_INITIALIZER(bridge_ports); 178164410Ssyrinxstatic time_t ports_list_age; 179164410Ssyrinx 180164410Ssyrinxvoid 181164410Ssyrinxbridge_ports_update_listage(void) 182164410Ssyrinx{ 183164410Ssyrinx ports_list_age = time(NULL); 184164410Ssyrinx} 185164410Ssyrinx 186164410Ssyrinxvoid 187164410Ssyrinxbridge_ports_fini(void) 188164410Ssyrinx{ 189164410Ssyrinx bridge_ports_free(&bridge_ports); 190164410Ssyrinx} 191164410Ssyrinx 192164410Ssyrinxvoid 193164410Ssyrinxbridge_members_free(struct bridge_if *bif) 194164410Ssyrinx{ 195164410Ssyrinx bridge_port_memif_free(&bridge_ports, bif); 196164410Ssyrinx} 197164410Ssyrinx 198164410Ssyrinx/* 199164410Ssyrinx * Find the first port in the ports list. 200164410Ssyrinx */ 201164410Ssyrinxstatic struct bridge_port * 202164410Ssyrinxbridge_port_first(void) 203164410Ssyrinx{ 204164410Ssyrinx return (TAILQ_FIRST(&bridge_ports)); 205164410Ssyrinx} 206164410Ssyrinx 207164410Ssyrinx/* 208164410Ssyrinx * Find the next port in the ports list. 209164410Ssyrinx */ 210164410Ssyrinxstatic struct bridge_port * 211164410Ssyrinxbridge_port_next(struct bridge_port *bp) 212164410Ssyrinx{ 213164410Ssyrinx return (TAILQ_NEXT(bp, b_p)); 214164410Ssyrinx} 215164410Ssyrinx 216164410Ssyrinx/* 217164410Ssyrinx * Find the first member of the specified bridge interface. 218164410Ssyrinx */ 219164410Ssyrinxstruct bridge_port * 220164410Ssyrinxbridge_port_bif_first(struct bridge_if *bif) 221164410Ssyrinx{ 222164410Ssyrinx return (bif->f_bp); 223164410Ssyrinx} 224164410Ssyrinx 225164410Ssyrinx/* 226164410Ssyrinx * Find the next member of the specified bridge interface. 227164410Ssyrinx */ 228164410Ssyrinxstruct bridge_port * 229164410Ssyrinxbridge_port_bif_next(struct bridge_port *bp) 230164410Ssyrinx{ 231164410Ssyrinx struct bridge_port *bp_next; 232164410Ssyrinx 233164410Ssyrinx if ((bp_next = TAILQ_NEXT(bp, b_p)) == NULL || 234164410Ssyrinx bp_next->sysindex != bp->sysindex) 235164410Ssyrinx return (NULL); 236164410Ssyrinx 237164410Ssyrinx return (bp_next); 238164410Ssyrinx} 239164410Ssyrinx 240164410Ssyrinx/* 241164410Ssyrinx * Remove a bridge port from the ports list. 242164410Ssyrinx */ 243164410Ssyrinxvoid 244164410Ssyrinxbridge_port_remove(struct bridge_port *bp, struct bridge_if *bif) 245164410Ssyrinx{ 246164410Ssyrinx if (bif->f_bp == bp) 247164410Ssyrinx bif->f_bp = bridge_port_bif_next(bp); 248164410Ssyrinx 249164410Ssyrinx TAILQ_REMOVE(&bridge_ports, bp, b_p); 250164410Ssyrinx free(bp); 251164410Ssyrinx} 252164410Ssyrinx 253164410Ssyrinx/* 254164410Ssyrinx * Allocate memory for a new bridge port and insert it 255164410Ssyrinx * in the base ports list. Return a pointer to the port's 256164410Ssyrinx * structure in case we want to do anything else with it. 257164410Ssyrinx */ 258164410Ssyrinxstruct bridge_port * 259164410Ssyrinxbridge_new_port(struct mibif *mif, struct bridge_if *bif) 260164410Ssyrinx{ 261164410Ssyrinx struct bridge_port *bp; 262164410Ssyrinx 263164410Ssyrinx if ((bp = (struct bridge_port *) malloc(sizeof(*bp))) == NULL) { 264164410Ssyrinx syslog(LOG_ERR, "bridge new member: failed: %s", 265164410Ssyrinx strerror(errno)); 266164410Ssyrinx return (NULL); 267164410Ssyrinx } 268164410Ssyrinx 269164410Ssyrinx bzero(bp, sizeof(*bp)); 270164410Ssyrinx 271164410Ssyrinx bp->sysindex = bif->sysindex; 272164410Ssyrinx bp->if_idx = mif->index; 273164410Ssyrinx bp->port_no = mif->sysindex; 274164410Ssyrinx strlcpy(bp->p_name, mif->name, IFNAMSIZ); 275164410Ssyrinx bp->circuit = oid_zeroDotZero; 276164410Ssyrinx 277164997Ssyrinx /* 278164997Ssyrinx * Initialize all rstpMib specific values to false/default. 279164997Ssyrinx * These will be set to their true values later if the bridge 280164997Ssyrinx * supports RSTP. 281164997Ssyrinx */ 282164997Ssyrinx bp->proto_migr = TruthValue_false; 283164997Ssyrinx bp->admin_edge = TruthValue_false; 284164997Ssyrinx bp->oper_edge = TruthValue_false; 285165416Ssyrinx bp->oper_ptp = TruthValue_false; 286165416Ssyrinx bp->admin_ptp = StpPortAdminPointToPointType_auto; 287164997Ssyrinx 288164410Ssyrinx bridge_port_memif_insert(&bridge_ports, bp, &(bif->f_bp)); 289164410Ssyrinx 290164410Ssyrinx return (bp); 291164410Ssyrinx} 292164410Ssyrinx 293164410Ssyrinx/* 294164410Ssyrinx * Update our info from the corresponding mibII interface info. 295164410Ssyrinx */ 296164410Ssyrinxvoid 297164410Ssyrinxbridge_port_getinfo_mibif(struct mibif *m_if, struct bridge_port *bp) 298164410Ssyrinx{ 299164410Ssyrinx bp->max_info = m_if->mib.ifmd_data.ifi_mtu; 300164410Ssyrinx bp->in_frames = m_if->mib.ifmd_data.ifi_ipackets; 301164410Ssyrinx bp->out_frames = m_if->mib.ifmd_data.ifi_opackets; 302164410Ssyrinx bp->in_drops = m_if->mib.ifmd_data.ifi_iqdrops; 303164410Ssyrinx} 304164410Ssyrinx 305164410Ssyrinx/* 306164410Ssyrinx * Find a port, whose SNMP's mibII ifIndex matches one of the ports, 307164410Ssyrinx * members of the specified bridge interface. 308164410Ssyrinx */ 309164410Ssyrinxstruct bridge_port * 310164410Ssyrinxbridge_port_find(int32_t if_idx, struct bridge_if *bif) 311164410Ssyrinx{ 312164410Ssyrinx struct bridge_port *bp; 313164410Ssyrinx 314164410Ssyrinx for (bp = bif->f_bp; bp != NULL; bp = TAILQ_NEXT(bp, b_p)) { 315164410Ssyrinx if (bp->sysindex != bif->sysindex) { 316164410Ssyrinx bp = NULL; 317164410Ssyrinx break; 318164410Ssyrinx } 319164410Ssyrinx 320164410Ssyrinx if (bp->if_idx == if_idx) 321164410Ssyrinx break; 322164410Ssyrinx } 323164410Ssyrinx 324164410Ssyrinx return (bp); 325164410Ssyrinx} 326164410Ssyrinx 327164410Ssyrinxvoid 328164410Ssyrinxbridge_ports_dump(struct bridge_if *bif) 329164410Ssyrinx{ 330164410Ssyrinx struct bridge_port *bp; 331164410Ssyrinx 332164410Ssyrinx for (bp = bridge_port_bif_first(bif); bp != NULL; 333164410Ssyrinx bp = bridge_port_bif_next(bp)) { 334164410Ssyrinx syslog(LOG_ERR, "memif - %s, index - %d", 335164410Ssyrinx bp->p_name, bp->port_no); 336164410Ssyrinx } 337164410Ssyrinx} 338164410Ssyrinx 339164410Ssyrinx/* 340164410Ssyrinx * RFC4188 specifics. 341164410Ssyrinx */ 342164410Ssyrinxint 343164410Ssyrinxop_dot1d_base_port(struct snmp_context *c __unused, struct snmp_value *val, 344164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 345164410Ssyrinx{ 346164410Ssyrinx struct bridge_if *bif; 347164410Ssyrinx struct bridge_port *bp; 348164410Ssyrinx 349164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 350164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 351164410Ssyrinx 352164410Ssyrinx if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 353164410Ssyrinx bridge_update_memif(bif) <= 0) 354164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 355164410Ssyrinx 356164410Ssyrinx switch (op) { 357164410Ssyrinx case SNMP_OP_GET: 358164410Ssyrinx if (val->var.len - sub != 1) 359164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 360164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 361164410Ssyrinx bif)) == NULL) 362164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 363165253Ssyrinx goto get; 364164410Ssyrinx 365164410Ssyrinx case SNMP_OP_GETNEXT: 366164410Ssyrinx if (val->var.len - sub == 0) { 367164410Ssyrinx if ((bp = bridge_port_bif_first(bif)) == NULL) 368164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 369164410Ssyrinx } else { 370164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 371164410Ssyrinx bif)) == NULL || 372164410Ssyrinx (bp = bridge_port_bif_next(bp)) == NULL) 373164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 374164410Ssyrinx } 375164410Ssyrinx val->var.len = sub + 1; 376164410Ssyrinx val->var.subs[sub] = bp->port_no; 377165253Ssyrinx goto get; 378164410Ssyrinx 379164410Ssyrinx case SNMP_OP_SET: 380164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 381164410Ssyrinx 382164410Ssyrinx case SNMP_OP_ROLLBACK: 383164410Ssyrinx case SNMP_OP_COMMIT: 384165253Ssyrinx break; 385164410Ssyrinx } 386165253Ssyrinx abort(); 387164410Ssyrinx 388165253Ssyrinxget: 389164410Ssyrinx switch (val->var.subs[sub - 1]) { 390164410Ssyrinx case LEAF_dot1dBasePort: 391164410Ssyrinx val->v.integer = bp->port_no; 392165253Ssyrinx return (SNMP_ERR_NOERROR); 393165253Ssyrinx 394164410Ssyrinx case LEAF_dot1dBasePortIfIndex: 395164410Ssyrinx val->v.integer = bp->if_idx; 396165253Ssyrinx return (SNMP_ERR_NOERROR); 397165253Ssyrinx 398164410Ssyrinx case LEAF_dot1dBasePortCircuit: 399164410Ssyrinx val->v.oid = bp->circuit; 400165253Ssyrinx return (SNMP_ERR_NOERROR); 401165253Ssyrinx 402164410Ssyrinx case LEAF_dot1dBasePortDelayExceededDiscards: 403164410Ssyrinx val->v.uint32 = bp->dly_ex_drops; 404165253Ssyrinx return (SNMP_ERR_NOERROR); 405165253Ssyrinx 406164410Ssyrinx case LEAF_dot1dBasePortMtuExceededDiscards: 407164410Ssyrinx val->v.uint32 = bp->dly_mtu_drops; 408165253Ssyrinx return (SNMP_ERR_NOERROR); 409164410Ssyrinx } 410164410Ssyrinx 411165253Ssyrinx abort(); 412164410Ssyrinx} 413164410Ssyrinx 414164410Ssyrinxint 415164410Ssyrinxop_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val, 416164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 417164410Ssyrinx{ 418164410Ssyrinx struct bridge_if *bif; 419164410Ssyrinx struct bridge_port *bp; 420164410Ssyrinx 421164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 422164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 423164410Ssyrinx 424164410Ssyrinx if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 425164410Ssyrinx bridge_update_memif(bif) <= 0) 426164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 427164410Ssyrinx 428164410Ssyrinx switch (op) { 429164410Ssyrinx case SNMP_OP_GET: 430164410Ssyrinx if (val->var.len - sub != 1) 431164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 432164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 433164410Ssyrinx bif)) == NULL) 434164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 435165253Ssyrinx goto get; 436164410Ssyrinx 437164410Ssyrinx case SNMP_OP_GETNEXT: 438164410Ssyrinx if (val->var.len - sub == 0) { 439164410Ssyrinx if ((bp = bridge_port_bif_first(bif)) == NULL) 440164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 441164410Ssyrinx } else { 442164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 443164410Ssyrinx bif)) == NULL || 444164410Ssyrinx (bp = bridge_port_bif_next(bp)) == NULL) 445164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 446164410Ssyrinx } 447164410Ssyrinx val->var.len = sub + 1; 448164410Ssyrinx val->var.subs[sub] = bp->port_no; 449165253Ssyrinx goto get; 450164410Ssyrinx 451164410Ssyrinx case SNMP_OP_SET: 452164997Ssyrinx if (val->var.len - sub != 1) 453164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 454164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 455164410Ssyrinx bif)) == NULL) 456164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 457164410Ssyrinx 458164410Ssyrinx switch (val->var.subs[sub - 1]) { 459164410Ssyrinx case LEAF_dot1dStpPortPriority: 460165253Ssyrinx if (val->v.integer < 0 || val->v.integer > 255) 461165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 462165253Ssyrinx 463164410Ssyrinx ctx->scratch->int1 = bp->priority; 464165253Ssyrinx if (bridge_port_set_priority(bif->bif_name, bp, 465165253Ssyrinx val->v.integer) < 0) 466165253Ssyrinx return (SNMP_ERR_GENERR); 467165253Ssyrinx return (SNMP_ERR_NOERROR); 468165253Ssyrinx 469164410Ssyrinx case LEAF_dot1dStpPortEnable: 470165253Ssyrinx if (val->v.integer != dot1dStpPortEnable_enabled && 471165253Ssyrinx val->v.integer != dot1dStpPortEnable_disabled) 472165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 473165253Ssyrinx 474164410Ssyrinx ctx->scratch->int1 = bp->enable; 475165253Ssyrinx if (bridge_port_set_stp_enable(bif->bif_name, 476165253Ssyrinx bp, val->v.integer) < 0) 477165253Ssyrinx return (SNMP_ERR_GENERR); 478165253Ssyrinx return (SNMP_ERR_NOERROR); 479165253Ssyrinx 480164410Ssyrinx case LEAF_dot1dStpPortPathCost: 481165253Ssyrinx if (val->v.integer < SNMP_PORT_MIN_PATHCOST || 482165253Ssyrinx val->v.integer > SNMP_PORT_MAX_PATHCOST) 483165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 484165253Ssyrinx 485164410Ssyrinx ctx->scratch->int1 = bp->path_cost; 486165253Ssyrinx if (bridge_port_set_path_cost(bif->bif_name, bp, 487165253Ssyrinx val->v.integer) < 0) 488165253Ssyrinx return (SNMP_ERR_GENERR); 489165253Ssyrinx return (SNMP_ERR_NOERROR); 490165253Ssyrinx 491164410Ssyrinx case LEAF_dot1dStpPort: 492164410Ssyrinx case LEAF_dot1dStpPortState: 493164410Ssyrinx case LEAF_dot1dStpPortDesignatedRoot: 494164410Ssyrinx case LEAF_dot1dStpPortDesignatedCost: 495164410Ssyrinx case LEAF_dot1dStpPortDesignatedBridge: 496164410Ssyrinx case LEAF_dot1dStpPortDesignatedPort: 497164410Ssyrinx case LEAF_dot1dStpPortForwardTransitions: 498164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 499164410Ssyrinx } 500165253Ssyrinx abort(); 501164410Ssyrinx 502164410Ssyrinx case SNMP_OP_ROLLBACK: 503164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 504164410Ssyrinx bif)) == NULL) 505164410Ssyrinx return (SNMP_ERR_GENERR); 506164410Ssyrinx switch (val->var.subs[sub - 1]) { 507164410Ssyrinx case LEAF_dot1dStpPortPriority: 508164410Ssyrinx bridge_port_set_priority(bif->bif_name, bp, 509164410Ssyrinx ctx->scratch->int1); 510164410Ssyrinx break; 511164410Ssyrinx case LEAF_dot1dStpPortEnable: 512164410Ssyrinx bridge_port_set_stp_enable(bif->bif_name, bp, 513164410Ssyrinx ctx->scratch->int1); 514164410Ssyrinx break; 515164410Ssyrinx case LEAF_dot1dStpPortPathCost: 516164410Ssyrinx bridge_port_set_path_cost(bif->bif_name, bp, 517164410Ssyrinx ctx->scratch->int1); 518164410Ssyrinx break; 519164410Ssyrinx } 520164410Ssyrinx return (SNMP_ERR_NOERROR); 521164410Ssyrinx 522164410Ssyrinx case SNMP_OP_COMMIT: 523164410Ssyrinx return (SNMP_ERR_NOERROR); 524164410Ssyrinx } 525165253Ssyrinx abort(); 526164997Ssyrinx 527165253Ssyrinxget: 528164410Ssyrinx switch (val->var.subs[sub - 1]) { 529164410Ssyrinx case LEAF_dot1dStpPort: 530164410Ssyrinx val->v.integer = bp->port_no; 531165253Ssyrinx return (SNMP_ERR_NOERROR); 532165253Ssyrinx 533164410Ssyrinx case LEAF_dot1dStpPortPriority: 534164410Ssyrinx val->v.integer = bp->priority; 535165253Ssyrinx return (SNMP_ERR_NOERROR); 536165253Ssyrinx 537164410Ssyrinx case LEAF_dot1dStpPortState: 538164410Ssyrinx val->v.integer = bp->state; 539165253Ssyrinx return (SNMP_ERR_NOERROR); 540165253Ssyrinx 541164410Ssyrinx case LEAF_dot1dStpPortEnable: 542164410Ssyrinx val->v.integer = bp->enable; 543165253Ssyrinx return (SNMP_ERR_NOERROR); 544165253Ssyrinx 545164410Ssyrinx case LEAF_dot1dStpPortPathCost: 546164410Ssyrinx val->v.integer = bp->path_cost; 547165253Ssyrinx return (SNMP_ERR_NOERROR); 548165253Ssyrinx 549164410Ssyrinx case LEAF_dot1dStpPortDesignatedRoot: 550165253Ssyrinx return (string_get(val, bp->design_root, 551165253Ssyrinx SNMP_BRIDGE_ID_LEN)); 552165253Ssyrinx 553164410Ssyrinx case LEAF_dot1dStpPortDesignatedCost: 554164410Ssyrinx val->v.integer = bp->design_cost; 555165253Ssyrinx return (SNMP_ERR_NOERROR); 556165253Ssyrinx 557164410Ssyrinx case LEAF_dot1dStpPortDesignatedBridge: 558165253Ssyrinx return (string_get(val, bp->design_bridge, 559165253Ssyrinx SNMP_BRIDGE_ID_LEN)); 560165253Ssyrinx 561164410Ssyrinx case LEAF_dot1dStpPortDesignatedPort: 562165253Ssyrinx return (string_get(val, bp->design_port, 2)); 563165253Ssyrinx 564164410Ssyrinx case LEAF_dot1dStpPortForwardTransitions: 565164410Ssyrinx val->v.uint32 = bp->fwd_trans; 566165253Ssyrinx return (SNMP_ERR_NOERROR); 567164410Ssyrinx } 568164410Ssyrinx 569165253Ssyrinx abort(); 570164410Ssyrinx} 571164410Ssyrinx 572164410Ssyrinxint 573164997Ssyrinxop_dot1d_stp_ext_port(struct snmp_context *ctx, struct snmp_value *val, 574164997Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 575164997Ssyrinx{ 576164997Ssyrinx struct bridge_if *bif; 577164997Ssyrinx struct bridge_port *bp; 578164997Ssyrinx 579164997Ssyrinx if ((bif = bridge_get_default()) == NULL) 580164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 581164997Ssyrinx 582164997Ssyrinx if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 583164997Ssyrinx bridge_update_memif(bif) <= 0) 584164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 585164997Ssyrinx 586164997Ssyrinx switch (op) { 587164997Ssyrinx case SNMP_OP_GET: 588164997Ssyrinx if (val->var.len - sub != 1) 589164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 590164997Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 591164997Ssyrinx bif)) == NULL) 592164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 593165253Ssyrinx goto get; 594164997Ssyrinx 595164997Ssyrinx case SNMP_OP_GETNEXT: 596164997Ssyrinx if (val->var.len - sub == 0) { 597164997Ssyrinx if ((bp = bridge_port_bif_first(bif)) == NULL) 598164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 599164997Ssyrinx } else { 600164997Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 601164997Ssyrinx bif)) == NULL || 602164997Ssyrinx (bp = bridge_port_bif_next(bp)) == NULL) 603164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 604164997Ssyrinx } 605164997Ssyrinx val->var.len = sub + 1; 606164997Ssyrinx val->var.subs[sub] = bp->port_no; 607165253Ssyrinx goto get; 608164997Ssyrinx 609164997Ssyrinx case SNMP_OP_SET: 610164997Ssyrinx if (val->var.len - sub != 1) 611164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 612164997Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 613164997Ssyrinx bif)) == NULL) 614164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 615164997Ssyrinx 616164997Ssyrinx switch (val->var.subs[sub - 1]) { 617164997Ssyrinx case LEAF_dot1dStpPortAdminEdgePort: 618165253Ssyrinx if (val->v.integer != TruthValue_true && 619165253Ssyrinx val->v.integer != TruthValue_false) 620165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 621165253Ssyrinx 622164997Ssyrinx ctx->scratch->int1 = bp->admin_edge; 623165253Ssyrinx if (bridge_port_set_admin_edge(bif->bif_name, bp, 624165253Ssyrinx val->v.integer) < 0) 625165253Ssyrinx return (SNMP_ERR_GENERR); 626165253Ssyrinx return (SNMP_ERR_NOERROR); 627165253Ssyrinx 628164997Ssyrinx case LEAF_dot1dStpPortAdminPointToPoint: 629310903Sngie if (val->v.integer < 0 || val->v.integer > 630165253Ssyrinx StpPortAdminPointToPointType_auto) 631165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 632165253Ssyrinx 633165416Ssyrinx ctx->scratch->int1 = bp->admin_ptp; 634165416Ssyrinx if (bridge_port_set_admin_ptp(bif->bif_name, bp, 635165253Ssyrinx val->v.integer) < 0) 636165253Ssyrinx return (SNMP_ERR_GENERR); 637165253Ssyrinx return (SNMP_ERR_NOERROR); 638165253Ssyrinx 639164997Ssyrinx case LEAF_dot1dStpPortAdminPathCost: 640165253Ssyrinx if (val->v.integer < SNMP_PORT_MIN_PATHCOST || 641165253Ssyrinx val->v.integer > SNMP_PORT_MAX_PATHCOST) 642165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 643165253Ssyrinx 644164997Ssyrinx ctx->scratch->int1 = bp->admin_path_cost; 645165253Ssyrinx if (bridge_port_set_path_cost(bif->bif_name, bp, 646165253Ssyrinx val->v.integer) < 0) 647165253Ssyrinx return (SNMP_ERR_GENERR); 648165253Ssyrinx return (SNMP_ERR_NOERROR); 649165253Ssyrinx 650164997Ssyrinx case LEAF_dot1dStpPortProtocolMigration: 651164997Ssyrinx case LEAF_dot1dStpPortOperEdgePort: 652164997Ssyrinx case LEAF_dot1dStpPortOperPointToPoint: 653164997Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 654164997Ssyrinx } 655165253Ssyrinx abort(); 656164997Ssyrinx 657164997Ssyrinx case SNMP_OP_ROLLBACK: 658164997Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 659164997Ssyrinx bif)) == NULL) 660164997Ssyrinx return (SNMP_ERR_GENERR); 661164997Ssyrinx 662164997Ssyrinx switch (val->var.subs[sub - 1]) { 663164997Ssyrinx case LEAF_dot1dStpPortAdminEdgePort: 664164997Ssyrinx bridge_port_set_admin_edge(bif->bif_name, bp, 665164997Ssyrinx ctx->scratch->int1); 666164997Ssyrinx break; 667164997Ssyrinx case LEAF_dot1dStpPortAdminPointToPoint: 668165416Ssyrinx bridge_port_set_admin_ptp(bif->bif_name, bp, 669164997Ssyrinx ctx->scratch->int1); 670164997Ssyrinx break; 671164997Ssyrinx case LEAF_dot1dStpPortAdminPathCost: 672164997Ssyrinx bridge_port_set_path_cost(bif->bif_name, bp, 673164997Ssyrinx ctx->scratch->int1); 674164997Ssyrinx break; 675164997Ssyrinx } 676164997Ssyrinx return (SNMP_ERR_NOERROR); 677164997Ssyrinx 678164997Ssyrinx case SNMP_OP_COMMIT: 679164997Ssyrinx return (SNMP_ERR_NOERROR); 680164997Ssyrinx } 681165253Ssyrinx abort(); 682164997Ssyrinx 683165253Ssyrinxget: 684164997Ssyrinx switch (val->var.subs[sub - 1]) { 685164997Ssyrinx case LEAF_dot1dStpPortProtocolMigration: 686164997Ssyrinx val->v.integer = bp->proto_migr; 687165253Ssyrinx return (SNMP_ERR_NOERROR); 688165253Ssyrinx 689164997Ssyrinx case LEAF_dot1dStpPortAdminEdgePort: 690164997Ssyrinx val->v.integer = bp->admin_edge; 691165253Ssyrinx return (SNMP_ERR_NOERROR); 692165253Ssyrinx 693164997Ssyrinx case LEAF_dot1dStpPortOperEdgePort: 694164997Ssyrinx val->v.integer = bp->oper_edge; 695165253Ssyrinx return (SNMP_ERR_NOERROR); 696165253Ssyrinx 697164997Ssyrinx case LEAF_dot1dStpPortAdminPointToPoint: 698165416Ssyrinx val->v.integer = bp->admin_ptp; 699165253Ssyrinx return (SNMP_ERR_NOERROR); 700165253Ssyrinx 701164997Ssyrinx case LEAF_dot1dStpPortOperPointToPoint: 702165416Ssyrinx val->v.integer = bp->oper_ptp; 703165253Ssyrinx return (SNMP_ERR_NOERROR); 704165253Ssyrinx 705164997Ssyrinx case LEAF_dot1dStpPortAdminPathCost: 706164997Ssyrinx val->v.integer = bp->admin_path_cost; 707165253Ssyrinx return (SNMP_ERR_NOERROR); 708164997Ssyrinx } 709164997Ssyrinx 710165253Ssyrinx abort(); 711164997Ssyrinx} 712164997Ssyrinx 713164997Ssyrinxint 714164410Ssyrinxop_dot1d_tp_port(struct snmp_context *c __unused, struct snmp_value *val, 715164997Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 716164410Ssyrinx{ 717164410Ssyrinx struct bridge_if *bif; 718164410Ssyrinx struct bridge_port *bp; 719164410Ssyrinx 720164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 721164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 722164410Ssyrinx 723164410Ssyrinx if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 724164410Ssyrinx bridge_update_memif(bif) <= 0) 725164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 726164410Ssyrinx 727164410Ssyrinx switch (op) { 728164410Ssyrinx case SNMP_OP_GET: 729164410Ssyrinx if (val->var.len - sub != 1) 730164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 731164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 732164410Ssyrinx bif)) == NULL) 733164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 734165253Ssyrinx goto get; 735164410Ssyrinx 736164410Ssyrinx case SNMP_OP_GETNEXT: 737164410Ssyrinx if (val->var.len - sub == 0) { 738164410Ssyrinx if ((bp = bridge_port_bif_first(bif)) == NULL) 739164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 740164410Ssyrinx } else { 741164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 742164410Ssyrinx bif)) == NULL || 743164410Ssyrinx (bp = bridge_port_bif_next(bp)) == NULL) 744164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 745164410Ssyrinx } 746164410Ssyrinx val->var.len = sub + 1; 747164410Ssyrinx val->var.subs[sub] = bp->port_no; 748165253Ssyrinx goto get; 749164410Ssyrinx 750164410Ssyrinx case SNMP_OP_SET: 751164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 752164410Ssyrinx 753164410Ssyrinx case SNMP_OP_ROLLBACK: 754164410Ssyrinx case SNMP_OP_COMMIT: 755165253Ssyrinx break; 756164410Ssyrinx } 757165253Ssyrinx abort(); 758164410Ssyrinx 759165253Ssyrinxget: 760164410Ssyrinx switch (val->var.subs[sub - 1]) { 761164410Ssyrinx case LEAF_dot1dTpPort: 762164410Ssyrinx val->v.integer = bp->port_no; 763165253Ssyrinx return (SNMP_ERR_NOERROR); 764165253Ssyrinx 765164410Ssyrinx case LEAF_dot1dTpPortMaxInfo: 766164410Ssyrinx val->v.integer = bp->max_info; 767165253Ssyrinx return (SNMP_ERR_NOERROR); 768165253Ssyrinx 769164410Ssyrinx case LEAF_dot1dTpPortInFrames: 770164410Ssyrinx val->v.uint32 = bp->in_frames; 771165253Ssyrinx return (SNMP_ERR_NOERROR); 772165253Ssyrinx 773164410Ssyrinx case LEAF_dot1dTpPortOutFrames: 774164410Ssyrinx val->v.uint32 = bp->out_frames; 775165253Ssyrinx return (SNMP_ERR_NOERROR); 776165253Ssyrinx 777164410Ssyrinx case LEAF_dot1dTpPortInDiscards: 778164410Ssyrinx val->v.uint32 = bp->in_drops; 779165253Ssyrinx return (SNMP_ERR_NOERROR); 780164410Ssyrinx } 781164410Ssyrinx 782165253Ssyrinx abort(); 783164410Ssyrinx} 784164410Ssyrinx 785164410Ssyrinx/* 786164410Ssyrinx * Private BEGEMOT-BRIDGE-MIB specifics. 787164410Ssyrinx */ 788164410Ssyrinx 789164410Ssyrinx/* 790164410Ssyrinx * Construct a bridge port entry index. 791164410Ssyrinx */ 792164410Ssyrinxstatic int 793164410Ssyrinxbridge_port_index_append(struct asn_oid *oid, uint sub, 794164410Ssyrinx const struct bridge_port *bp) 795164410Ssyrinx{ 796164410Ssyrinx uint i; 797164410Ssyrinx const char *b_name; 798164410Ssyrinx 799164410Ssyrinx if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) 800164410Ssyrinx return (-1); 801164410Ssyrinx 802164410Ssyrinx oid->len = sub + strlen(b_name) + 1 + 1; 803164410Ssyrinx oid->subs[sub] = strlen(b_name); 804164410Ssyrinx 805164410Ssyrinx for (i = 1; i <= strlen(b_name); i++) 806164410Ssyrinx oid->subs[sub + i] = b_name[i - 1]; 807164410Ssyrinx 808164410Ssyrinx oid->subs[sub + i] = bp->port_no; 809164410Ssyrinx 810164410Ssyrinx return (0); 811164410Ssyrinx} 812164410Ssyrinx 813164410Ssyrinx/* 814164410Ssyrinx * Get the port entry from an entry's index. 815164410Ssyrinx */ 816164410Ssyrinxstatic struct bridge_port * 817164410Ssyrinxbridge_port_index_get(const struct asn_oid *oid, uint sub, int8_t status) 818164410Ssyrinx{ 819164410Ssyrinx uint i; 820164410Ssyrinx int32_t port_no; 821164410Ssyrinx char bif_name[IFNAMSIZ]; 822164410Ssyrinx struct bridge_if *bif; 823164410Ssyrinx struct bridge_port *bp; 824164410Ssyrinx 825164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 2 || 826164410Ssyrinx oid->subs[sub] >= IFNAMSIZ) 827164410Ssyrinx return (NULL); 828164410Ssyrinx 829164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 830164410Ssyrinx bif_name[i] = oid->subs[sub + i + 1]; 831164410Ssyrinx bif_name[i] = '\0'; 832164410Ssyrinx 833164410Ssyrinx port_no = oid->subs[sub + i + 1]; 834164410Ssyrinx 835164410Ssyrinx if ((bif = bridge_if_find_ifname(bif_name)) == NULL) 836164410Ssyrinx return (NULL); 837164410Ssyrinx 838164410Ssyrinx if ((bp = bridge_port_find(port_no, bif)) == NULL || 839164410Ssyrinx (status == 0 && bp->status != RowStatus_active)) 840164410Ssyrinx return (NULL); 841164410Ssyrinx 842164410Ssyrinx return (bp); 843164410Ssyrinx} 844164410Ssyrinx 845164410Ssyrinx/* 846164410Ssyrinx * Get the next port entry from an entry's index. 847164410Ssyrinx */ 848164410Ssyrinxstatic struct bridge_port * 849164410Ssyrinxbridge_port_index_getnext(const struct asn_oid *oid, uint sub, int8_t status) 850164410Ssyrinx{ 851164410Ssyrinx uint i; 852164410Ssyrinx int32_t port_no; 853164410Ssyrinx char bif_name[IFNAMSIZ]; 854164410Ssyrinx struct bridge_if *bif; 855164410Ssyrinx struct bridge_port *bp; 856164410Ssyrinx 857164410Ssyrinx if (oid->len - sub == 0) 858164410Ssyrinx bp = bridge_port_first(); 859164410Ssyrinx else { 860164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 2 || 861164410Ssyrinx oid->subs[sub] >= IFNAMSIZ) 862164410Ssyrinx return (NULL); 863164410Ssyrinx 864164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 865164410Ssyrinx bif_name[i] = oid->subs[sub + i + 1]; 866164410Ssyrinx bif_name[i] = '\0'; 867310903Sngie 868164410Ssyrinx port_no = oid->subs[sub + i + 1]; 869164410Ssyrinx 870164410Ssyrinx if ((bif = bridge_if_find_ifname(bif_name)) == NULL || 871164410Ssyrinx (bp = bridge_port_find(port_no, bif)) == NULL) 872164410Ssyrinx return (NULL); 873164410Ssyrinx 874164410Ssyrinx bp = bridge_port_next(bp); 875164410Ssyrinx } 876164410Ssyrinx 877164410Ssyrinx if (status == 1) 878164410Ssyrinx return (bp); 879164410Ssyrinx 880164410Ssyrinx while (bp != NULL) { 881164410Ssyrinx if (bp->status == RowStatus_active) 882164410Ssyrinx break; 883164410Ssyrinx bp = bridge_port_next(bp); 884164410Ssyrinx } 885164410Ssyrinx 886164410Ssyrinx return (bp); 887164410Ssyrinx} 888164410Ssyrinx 889164410Ssyrinx/* 890164410Ssyrinx * Read the bridge name and port index from a ASN OID structure. 891164410Ssyrinx */ 892164410Ssyrinxstatic int 893164410Ssyrinxbridge_port_index_decode(const struct asn_oid *oid, uint sub, 894164410Ssyrinx char *b_name, int32_t *idx) 895164410Ssyrinx{ 896164410Ssyrinx uint i; 897164410Ssyrinx 898164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 2 || 899164410Ssyrinx oid->subs[sub] >= IFNAMSIZ) 900164410Ssyrinx return (-1); 901164410Ssyrinx 902164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 903164410Ssyrinx b_name[i] = oid->subs[sub + i + 1]; 904164410Ssyrinx b_name[i] = '\0'; 905164410Ssyrinx 906164410Ssyrinx *idx = oid->subs[sub + i + 1]; 907164410Ssyrinx return (0); 908164410Ssyrinx} 909164410Ssyrinx 910164410Ssyrinxstatic int 911164410Ssyrinxbridge_port_set_status(struct snmp_context *ctx, 912164410Ssyrinx struct snmp_value *val, uint sub) 913164410Ssyrinx{ 914164410Ssyrinx int32_t if_idx; 915164410Ssyrinx char b_name[IFNAMSIZ]; 916164410Ssyrinx struct bridge_if *bif; 917164410Ssyrinx struct bridge_port *bp; 918164410Ssyrinx struct mibif *mif; 919164410Ssyrinx 920164410Ssyrinx if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 921164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 922164410Ssyrinx 923164410Ssyrinx if ((bif = bridge_if_find_ifname(b_name)) == NULL || 924164410Ssyrinx (mif = mib_find_if(if_idx)) == NULL) 925164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 926164410Ssyrinx 927164410Ssyrinx bp = bridge_port_find(if_idx, bif); 928164410Ssyrinx 929164410Ssyrinx switch (val->v.integer) { 930164410Ssyrinx case RowStatus_active: 931164410Ssyrinx if (bp == NULL) 932164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 933164410Ssyrinx 934164410Ssyrinx if (bp->span_enable == 0) 935164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 936164410Ssyrinx 937164410Ssyrinx ctx->scratch->int1 = bp->status; 938164410Ssyrinx bp->status = RowStatus_active; 939164410Ssyrinx break; 940310903Sngie 941164410Ssyrinx case RowStatus_notInService: 942164410Ssyrinx if (bp == NULL || bp->span_enable == 0 || 943164410Ssyrinx bp->status == RowStatus_active) 944164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 945164410Ssyrinx 946164410Ssyrinx ctx->scratch->int1 = bp->status; 947164410Ssyrinx bp->status = RowStatus_notInService; 948164410Ssyrinx 949164410Ssyrinx case RowStatus_notReady: 950164410Ssyrinx /* FALLTHROUGH */ 951164410Ssyrinx case RowStatus_createAndGo: 952164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 953164410Ssyrinx 954164410Ssyrinx case RowStatus_createAndWait: 955164410Ssyrinx if (bp != NULL) 956164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 957164410Ssyrinx 958164410Ssyrinx if ((bp = bridge_new_port(mif, bif)) == NULL) 959164410Ssyrinx return (SNMP_ERR_GENERR); 960164410Ssyrinx 961164410Ssyrinx ctx->scratch->int1 = RowStatus_destroy; 962164410Ssyrinx bp->status = RowStatus_notReady; 963164410Ssyrinx break; 964164410Ssyrinx 965164410Ssyrinx case RowStatus_destroy: 966164410Ssyrinx if (bp == NULL) 967164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 968164410Ssyrinx 969164410Ssyrinx ctx->scratch->int1 = bp->status; 970164410Ssyrinx bp->status = RowStatus_destroy; 971164410Ssyrinx break; 972164410Ssyrinx } 973164410Ssyrinx 974164410Ssyrinx return (SNMP_ERR_NOERROR); 975164410Ssyrinx} 976164410Ssyrinx 977164410Ssyrinxstatic int 978164410Ssyrinxbridge_port_rollback_status(struct snmp_context *ctx, 979164410Ssyrinx struct snmp_value *val, uint sub) 980164410Ssyrinx{ 981164410Ssyrinx int32_t if_idx; 982164410Ssyrinx char b_name[IFNAMSIZ]; 983164410Ssyrinx struct bridge_if *bif; 984164410Ssyrinx struct bridge_port *bp; 985164410Ssyrinx 986164410Ssyrinx if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 987164410Ssyrinx return (SNMP_ERR_GENERR); 988164410Ssyrinx 989164410Ssyrinx if ((bif = bridge_if_find_ifname(b_name)) == NULL || 990164410Ssyrinx (bp = bridge_port_find(if_idx, bif)) == NULL) 991164410Ssyrinx return (SNMP_ERR_GENERR); 992164410Ssyrinx 993164410Ssyrinx if (ctx->scratch->int1 == RowStatus_destroy) 994164410Ssyrinx bridge_port_remove(bp, bif); 995164410Ssyrinx else 996164410Ssyrinx bp->status = ctx->scratch->int1; 997164410Ssyrinx 998164410Ssyrinx return (SNMP_ERR_NOERROR); 999164410Ssyrinx} 1000164410Ssyrinx 1001164410Ssyrinxstatic int 1002164410Ssyrinxbridge_port_commit_status(struct snmp_value *val, uint sub) 1003164410Ssyrinx{ 1004164410Ssyrinx int32_t if_idx; 1005164410Ssyrinx char b_name[IFNAMSIZ]; 1006164410Ssyrinx struct bridge_if *bif; 1007164410Ssyrinx struct bridge_port *bp; 1008164410Ssyrinx 1009164410Ssyrinx if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 1010164410Ssyrinx return (SNMP_ERR_GENERR); 1011164410Ssyrinx 1012164410Ssyrinx if ((bif = bridge_if_find_ifname(b_name)) == NULL || 1013164410Ssyrinx (bp = bridge_port_find(if_idx, bif)) == NULL) 1014164410Ssyrinx return (SNMP_ERR_GENERR); 1015164410Ssyrinx 1016164410Ssyrinx switch (bp->status) { 1017164410Ssyrinx case RowStatus_active: 1018164410Ssyrinx if (bridge_port_addm(bp, b_name) < 0) 1019164410Ssyrinx return (SNMP_ERR_COMMIT_FAILED); 1020164410Ssyrinx break; 1021164410Ssyrinx 1022164410Ssyrinx case RowStatus_destroy: 1023164410Ssyrinx if (bridge_port_delm(bp, b_name) < 0) 1024164410Ssyrinx return (SNMP_ERR_COMMIT_FAILED); 1025164410Ssyrinx bridge_port_remove(bp, bif); 1026164410Ssyrinx break; 1027164410Ssyrinx } 1028164410Ssyrinx 1029164410Ssyrinx return (SNMP_ERR_NOERROR); 1030164410Ssyrinx} 1031164410Ssyrinx 1032164410Ssyrinxstatic int 1033164410Ssyrinxbridge_port_set_span_enable(struct snmp_context *ctx, 1034164410Ssyrinx struct snmp_value *val, uint sub) 1035164410Ssyrinx{ 1036164410Ssyrinx int32_t if_idx; 1037164410Ssyrinx char b_name[IFNAMSIZ]; 1038164410Ssyrinx struct bridge_if *bif; 1039164410Ssyrinx struct bridge_port *bp; 1040164410Ssyrinx struct mibif *mif; 1041164410Ssyrinx 1042164410Ssyrinx if (val->v.integer != begemotBridgeBaseSpanEnabled_enabled && 1043164410Ssyrinx val->v.integer != begemotBridgeBaseSpanEnabled_disabled) 1044164410Ssyrinx return (SNMP_ERR_BADVALUE); 1045164410Ssyrinx 1046164410Ssyrinx if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 1047164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1048164410Ssyrinx 1049164410Ssyrinx if ((bif = bridge_if_find_ifname(b_name)) == NULL) 1050164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1051164410Ssyrinx 1052164410Ssyrinx if ((bp = bridge_port_find(if_idx, bif)) == NULL) { 1053164410Ssyrinx if ((mif = mib_find_if(if_idx)) == NULL) 1054164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1055164410Ssyrinx 1056164410Ssyrinx if ((bp = bridge_new_port(mif, bif)) == NULL) 1057164410Ssyrinx return (SNMP_ERR_GENERR); 1058164410Ssyrinx 1059164410Ssyrinx ctx->scratch->int1 = RowStatus_destroy; 1060164410Ssyrinx } else if (bp->status == RowStatus_active) { 1061164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1062164410Ssyrinx } else { 1063164410Ssyrinx ctx->scratch->int1 = bp->status; 1064164410Ssyrinx } 1065164410Ssyrinx 1066164410Ssyrinx bp->span_enable = val->v.integer; 1067164410Ssyrinx bp->status = RowStatus_notInService; 1068164410Ssyrinx 1069164410Ssyrinx return (SNMP_ERR_NOERROR); 1070164410Ssyrinx} 1071164410Ssyrinx 1072164410Ssyrinxint 1073164410Ssyrinxop_begemot_base_port(struct snmp_context *ctx, struct snmp_value *val, 1074164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1075164410Ssyrinx{ 1076164410Ssyrinx int8_t status, which; 1077171791Ssyrinx const char *bname; 1078165253Ssyrinx struct bridge_port *bp; 1079164410Ssyrinx 1080164410Ssyrinx if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 1081164410Ssyrinx bridge_update_all_ports(); 1082164410Ssyrinx 1083164410Ssyrinx which = val->var.subs[sub - 1]; 1084164410Ssyrinx status = 0; 1085164410Ssyrinx 1086164410Ssyrinx switch (op) { 1087164410Ssyrinx case SNMP_OP_GET: 1088164410Ssyrinx if (which == LEAF_begemotBridgeBaseSpanEnabled || 1089164410Ssyrinx which == LEAF_begemotBridgeBasePortStatus) 1090164410Ssyrinx status = 1; 1091164410Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 1092164410Ssyrinx status)) == NULL) 1093164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1094165253Ssyrinx goto get; 1095164410Ssyrinx 1096164410Ssyrinx case SNMP_OP_GETNEXT: 1097164410Ssyrinx if (which == LEAF_begemotBridgeBaseSpanEnabled || 1098164410Ssyrinx which == LEAF_begemotBridgeBasePortStatus) 1099164410Ssyrinx status = 1; 1100164410Ssyrinx if ((bp = bridge_port_index_getnext(&val->var, sub, 1101164410Ssyrinx status)) == NULL || 1102164410Ssyrinx bridge_port_index_append(&val->var, sub, bp) < 0) 1103164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1104165253Ssyrinx goto get; 1105164410Ssyrinx 1106164410Ssyrinx case SNMP_OP_SET: 1107164410Ssyrinx switch (which) { 1108164410Ssyrinx case LEAF_begemotBridgeBaseSpanEnabled: 1109164410Ssyrinx return (bridge_port_set_span_enable(ctx, val, sub)); 1110164410Ssyrinx 1111164410Ssyrinx case LEAF_begemotBridgeBasePortStatus: 1112164410Ssyrinx return (bridge_port_set_status(ctx, val, sub)); 1113164410Ssyrinx 1114171791Ssyrinx case LEAF_begemotBridgeBasePortPrivate: 1115171791Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 1116171791Ssyrinx status)) == NULL) 1117171791Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1118171791Ssyrinx if ((bname = bridge_if_find_name(bp->sysindex)) == NULL) 1119171791Ssyrinx return (SNMP_ERR_GENERR); 1120171791Ssyrinx ctx->scratch->int1 = bp->priv_set; 1121171791Ssyrinx return (bridge_port_set_private(bname, bp, 1122171791Ssyrinx val->v.integer)); 1123171791Ssyrinx 1124164410Ssyrinx case LEAF_begemotBridgeBasePort: 1125164410Ssyrinx case LEAF_begemotBridgeBasePortIfIndex: 1126164410Ssyrinx case LEAF_begemotBridgeBasePortDelayExceededDiscards: 1127164410Ssyrinx case LEAF_begemotBridgeBasePortMtuExceededDiscards: 1128164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1129164410Ssyrinx } 1130164410Ssyrinx abort(); 1131164410Ssyrinx 1132164410Ssyrinx case SNMP_OP_ROLLBACK: 1133164410Ssyrinx switch (which) { 1134164410Ssyrinx case LEAF_begemotBridgeBaseSpanEnabled: 1135164410Ssyrinx /* FALLTHROUGH */ 1136164410Ssyrinx case LEAF_begemotBridgeBasePortStatus: 1137164410Ssyrinx return (bridge_port_rollback_status(ctx, val, sub)); 1138171791Ssyrinx case LEAF_begemotBridgeBasePortPrivate: 1139171791Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 1140171791Ssyrinx status)) == NULL) 1141171791Ssyrinx return (SNMP_ERR_GENERR); 1142171791Ssyrinx if ((bname = bridge_if_find_name(bp->sysindex)) == NULL) 1143171791Ssyrinx return (SNMP_ERR_GENERR); 1144171791Ssyrinx return (bridge_port_set_private(bname, bp, 1145171791Ssyrinx ctx->scratch->int1)); 1146164410Ssyrinx } 1147164410Ssyrinx return (SNMP_ERR_NOERROR); 1148164410Ssyrinx 1149164410Ssyrinx case SNMP_OP_COMMIT: 1150164410Ssyrinx if (which == LEAF_begemotBridgeBasePortStatus) 1151164410Ssyrinx return (bridge_port_commit_status(val, sub)); 1152164410Ssyrinx 1153164410Ssyrinx return (SNMP_ERR_NOERROR); 1154164410Ssyrinx } 1155165253Ssyrinx abort(); 1156164410Ssyrinx 1157165253Ssyrinxget: 1158164410Ssyrinx switch (which) { 1159164410Ssyrinx case LEAF_begemotBridgeBasePort: 1160164410Ssyrinx val->v.integer = bp->port_no; 1161165253Ssyrinx return (SNMP_ERR_NOERROR); 1162165253Ssyrinx 1163164410Ssyrinx case LEAF_begemotBridgeBasePortIfIndex: 1164164410Ssyrinx val->v.integer = bp->if_idx; 1165165253Ssyrinx return (SNMP_ERR_NOERROR); 1166165253Ssyrinx 1167164410Ssyrinx case LEAF_begemotBridgeBaseSpanEnabled: 1168164410Ssyrinx val->v.integer = bp->span_enable; 1169165253Ssyrinx return (SNMP_ERR_NOERROR); 1170165253Ssyrinx 1171164410Ssyrinx case LEAF_begemotBridgeBasePortDelayExceededDiscards: 1172164410Ssyrinx val->v.uint32 = bp->dly_ex_drops; 1173165253Ssyrinx return (SNMP_ERR_NOERROR); 1174165253Ssyrinx 1175164410Ssyrinx case LEAF_begemotBridgeBasePortMtuExceededDiscards: 1176164410Ssyrinx val->v.uint32 = bp->dly_mtu_drops; 1177165253Ssyrinx return (SNMP_ERR_NOERROR); 1178165253Ssyrinx 1179164410Ssyrinx case LEAF_begemotBridgeBasePortStatus: 1180164410Ssyrinx val->v.integer = bp->status; 1181165253Ssyrinx return (SNMP_ERR_NOERROR); 1182171791Ssyrinx 1183171791Ssyrinx case LEAF_begemotBridgeBasePortPrivate: 1184171791Ssyrinx val->v.integer = bp->priv_set; 1185171791Ssyrinx return (SNMP_ERR_NOERROR); 1186164410Ssyrinx } 1187164410Ssyrinx 1188165253Ssyrinx abort(); 1189164410Ssyrinx} 1190164410Ssyrinx 1191164410Ssyrinxint 1192164410Ssyrinxop_begemot_stp_port(struct snmp_context *ctx, struct snmp_value *val, 1193164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1194164410Ssyrinx{ 1195165046Ssyrinx struct bridge_port *bp; 1196164410Ssyrinx const char *b_name; 1197164410Ssyrinx 1198164410Ssyrinx if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 1199164410Ssyrinx bridge_update_all_ports(); 1200164410Ssyrinx 1201164410Ssyrinx switch (op) { 1202164410Ssyrinx case SNMP_OP_GET: 1203164410Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1204164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1205165253Ssyrinx goto get; 1206164410Ssyrinx 1207164410Ssyrinx case SNMP_OP_GETNEXT: 1208164410Ssyrinx if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == 1209164410Ssyrinx NULL || bridge_port_index_append(&val->var, sub, bp) < 0) 1210164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1211165253Ssyrinx goto get; 1212164410Ssyrinx 1213164410Ssyrinx case SNMP_OP_SET: 1214164410Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1215164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1216164410Ssyrinx if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) 1217164410Ssyrinx return (SNMP_ERR_GENERR); 1218164410Ssyrinx 1219164410Ssyrinx switch (val->var.subs[sub - 1]) { 1220164410Ssyrinx case LEAF_begemotBridgeStpPortPriority: 1221165253Ssyrinx if (val->v.integer < 0 || val->v.integer > 255) 1222165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1223165253Ssyrinx 1224164410Ssyrinx ctx->scratch->int1 = bp->priority; 1225165253Ssyrinx if (bridge_port_set_priority(b_name, bp, 1226165253Ssyrinx val->v.integer) < 0) 1227165253Ssyrinx return (SNMP_ERR_GENERR); 1228165253Ssyrinx return (SNMP_ERR_NOERROR); 1229165253Ssyrinx 1230164410Ssyrinx case LEAF_begemotBridgeStpPortEnable: 1231165253Ssyrinx if (val->v.integer != 1232357520Sdim (int32_t)begemotBridgeStpPortEnable_enabled || 1233165253Ssyrinx val->v.integer != 1234357520Sdim (int32_t)begemotBridgeStpPortEnable_disabled) 1235165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1236165253Ssyrinx 1237164410Ssyrinx ctx->scratch->int1 = bp->enable; 1238165253Ssyrinx if (bridge_port_set_stp_enable(b_name, bp, 1239165253Ssyrinx val->v.integer) < 0) 1240165253Ssyrinx return (SNMP_ERR_GENERR); 1241165253Ssyrinx return (SNMP_ERR_NOERROR); 1242165253Ssyrinx 1243164410Ssyrinx case LEAF_begemotBridgeStpPortPathCost: 1244165253Ssyrinx if (val->v.integer < SNMP_PORT_MIN_PATHCOST || 1245165253Ssyrinx val->v.integer > SNMP_PORT_MAX_PATHCOST) 1246165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1247165253Ssyrinx 1248164410Ssyrinx ctx->scratch->int1 = bp->path_cost; 1249165253Ssyrinx if (bridge_port_set_path_cost(b_name, bp, 1250165253Ssyrinx val->v.integer) < 0) 1251165253Ssyrinx return (SNMP_ERR_GENERR); 1252165253Ssyrinx return (SNMP_ERR_NOERROR); 1253165253Ssyrinx 1254164410Ssyrinx case LEAF_begemotBridgeStpPort: 1255164410Ssyrinx case LEAF_begemotBridgeStpPortState: 1256164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedRoot: 1257164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedCost: 1258164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedBridge: 1259164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedPort: 1260164410Ssyrinx case LEAF_begemotBridgeStpPortForwardTransitions: 1261164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1262164410Ssyrinx } 1263165253Ssyrinx abort(); 1264164410Ssyrinx 1265164410Ssyrinx case SNMP_OP_ROLLBACK: 1266164410Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL || 1267164410Ssyrinx (b_name = bridge_if_find_name(bp->sysindex)) == NULL) 1268164410Ssyrinx return (SNMP_ERR_GENERR); 1269164410Ssyrinx 1270164410Ssyrinx switch (val->var.subs[sub - 1]) { 1271164410Ssyrinx case LEAF_begemotBridgeStpPortPriority: 1272164410Ssyrinx bridge_port_set_priority(b_name, bp, 1273164410Ssyrinx ctx->scratch->int1); 1274164410Ssyrinx break; 1275164410Ssyrinx case LEAF_begemotBridgeStpPortEnable: 1276164410Ssyrinx bridge_port_set_stp_enable(b_name, bp, 1277164410Ssyrinx ctx->scratch->int1); 1278164410Ssyrinx break; 1279164410Ssyrinx case LEAF_begemotBridgeStpPortPathCost: 1280164410Ssyrinx bridge_port_set_path_cost(b_name, bp, 1281164410Ssyrinx ctx->scratch->int1); 1282164410Ssyrinx break; 1283164410Ssyrinx } 1284164410Ssyrinx return (SNMP_ERR_NOERROR); 1285164410Ssyrinx 1286164410Ssyrinx case SNMP_OP_COMMIT: 1287164410Ssyrinx return (SNMP_ERR_NOERROR); 1288164410Ssyrinx } 1289165253Ssyrinx abort(); 1290164410Ssyrinx 1291165253Ssyrinxget: 1292164410Ssyrinx switch (val->var.subs[sub - 1]) { 1293164410Ssyrinx case LEAF_begemotBridgeStpPort: 1294164410Ssyrinx val->v.integer = bp->port_no; 1295165253Ssyrinx return (SNMP_ERR_NOERROR); 1296165253Ssyrinx 1297164410Ssyrinx case LEAF_begemotBridgeStpPortPriority: 1298164410Ssyrinx val->v.integer = bp->priority; 1299165253Ssyrinx return (SNMP_ERR_NOERROR); 1300165253Ssyrinx 1301164410Ssyrinx case LEAF_begemotBridgeStpPortState: 1302164410Ssyrinx val->v.integer = bp->state; 1303165253Ssyrinx return (SNMP_ERR_NOERROR); 1304165253Ssyrinx 1305164410Ssyrinx case LEAF_begemotBridgeStpPortEnable: 1306164410Ssyrinx val->v.integer = bp->enable; 1307165253Ssyrinx return (SNMP_ERR_NOERROR); 1308165253Ssyrinx 1309164410Ssyrinx case LEAF_begemotBridgeStpPortPathCost: 1310164410Ssyrinx val->v.integer = bp->path_cost; 1311165253Ssyrinx return (SNMP_ERR_NOERROR); 1312165253Ssyrinx 1313164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedRoot: 1314165253Ssyrinx return (string_get(val, bp->design_root, SNMP_BRIDGE_ID_LEN)); 1315165253Ssyrinx 1316164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedCost: 1317164410Ssyrinx val->v.integer = bp->design_cost; 1318165253Ssyrinx return (SNMP_ERR_NOERROR); 1319165253Ssyrinx 1320164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedBridge: 1321165253Ssyrinx return (string_get(val, bp->design_bridge, SNMP_BRIDGE_ID_LEN)); 1322165253Ssyrinx 1323164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedPort: 1324165253Ssyrinx return (string_get(val, bp->design_port, 2)); 1325165253Ssyrinx 1326164410Ssyrinx case LEAF_begemotBridgeStpPortForwardTransitions: 1327164410Ssyrinx val->v.uint32 = bp->fwd_trans; 1328165253Ssyrinx return (SNMP_ERR_NOERROR); 1329164410Ssyrinx } 1330164410Ssyrinx 1331165253Ssyrinx abort(); 1332164410Ssyrinx} 1333164410Ssyrinx 1334164410Ssyrinxint 1335164997Ssyrinxop_begemot_stp_ext_port(struct snmp_context *ctx, struct snmp_value *val, 1336164997Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1337164997Ssyrinx{ 1338165046Ssyrinx struct bridge_port *bp; 1339164997Ssyrinx const char *b_name; 1340164997Ssyrinx 1341164997Ssyrinx if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 1342164997Ssyrinx bridge_update_all_ports(); 1343164997Ssyrinx 1344164997Ssyrinx switch (op) { 1345164997Ssyrinx case SNMP_OP_GET: 1346164997Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1347164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1348165253Ssyrinx goto get; 1349164997Ssyrinx 1350164997Ssyrinx case SNMP_OP_GETNEXT: 1351164997Ssyrinx if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == 1352164997Ssyrinx NULL || bridge_port_index_append(&val->var, sub, bp) < 0) 1353164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1354165253Ssyrinx goto get; 1355164997Ssyrinx 1356164997Ssyrinx case SNMP_OP_SET: 1357164997Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1358164997Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1359164997Ssyrinx if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) 1360164997Ssyrinx return (SNMP_ERR_GENERR); 1361164997Ssyrinx 1362164997Ssyrinx switch (val->var.subs[sub - 1]) { 1363164997Ssyrinx case LEAF_begemotBridgeStpPortAdminEdgePort: 1364165253Ssyrinx if (val->v.integer != TruthValue_true && 1365165253Ssyrinx val->v.integer != TruthValue_false) 1366165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1367165253Ssyrinx 1368164997Ssyrinx ctx->scratch->int1 = bp->admin_edge; 1369165253Ssyrinx if (bridge_port_set_admin_edge(b_name, bp, 1370165253Ssyrinx val->v.integer) < 0) 1371165253Ssyrinx return (SNMP_ERR_GENERR); 1372165253Ssyrinx return (SNMP_ERR_NOERROR); 1373165253Ssyrinx 1374164997Ssyrinx case LEAF_begemotBridgeStpPortAdminPointToPoint: 1375165253Ssyrinx if (val->v.integer < 0 || val->v.integer > 1376165253Ssyrinx StpPortAdminPointToPointType_auto) 1377165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1378165253Ssyrinx 1379165416Ssyrinx ctx->scratch->int1 = bp->admin_ptp; 1380165416Ssyrinx if (bridge_port_set_admin_ptp(b_name, bp, 1381165253Ssyrinx val->v.integer) < 0) 1382165253Ssyrinx return (SNMP_ERR_GENERR); 1383165253Ssyrinx return (SNMP_ERR_NOERROR); 1384165253Ssyrinx 1385164997Ssyrinx case LEAF_begemotBridgeStpPortAdminPathCost: 1386165253Ssyrinx if (val->v.integer < SNMP_PORT_MIN_PATHCOST || 1387165253Ssyrinx val->v.integer > SNMP_PORT_MAX_PATHCOST) 1388165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1389165253Ssyrinx 1390164997Ssyrinx ctx->scratch->int1 = bp->admin_path_cost; 1391165253Ssyrinx if (bridge_port_set_path_cost(b_name, bp, 1392165253Ssyrinx val->v.integer) < 0) 1393165253Ssyrinx return (SNMP_ERR_GENERR); 1394165253Ssyrinx return (SNMP_ERR_NOERROR); 1395165253Ssyrinx 1396164997Ssyrinx case LEAF_begemotBridgeStpPortProtocolMigration: 1397164997Ssyrinx case LEAF_begemotBridgeStpPortOperEdgePort: 1398164997Ssyrinx case LEAF_begemotBridgeStpPortOperPointToPoint: 1399164997Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1400164997Ssyrinx } 1401165253Ssyrinx abort(); 1402164997Ssyrinx 1403164997Ssyrinx case SNMP_OP_ROLLBACK: 1404164997Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL || 1405164997Ssyrinx (b_name = bridge_if_find_name(bp->sysindex)) == NULL) 1406164997Ssyrinx return (SNMP_ERR_GENERR); 1407164997Ssyrinx 1408164997Ssyrinx switch (val->var.subs[sub - 1]) { 1409164997Ssyrinx case LEAF_begemotBridgeStpPortAdminEdgePort: 1410164997Ssyrinx bridge_port_set_admin_edge(b_name, bp, 1411164997Ssyrinx ctx->scratch->int1); 1412164997Ssyrinx break; 1413164997Ssyrinx case LEAF_begemotBridgeStpPortAdminPointToPoint: 1414165416Ssyrinx bridge_port_set_admin_ptp(b_name, bp, 1415164997Ssyrinx ctx->scratch->int1); 1416164997Ssyrinx break; 1417164997Ssyrinx case LEAF_begemotBridgeStpPortAdminPathCost: 1418164997Ssyrinx bridge_port_set_path_cost(b_name, bp, 1419164997Ssyrinx ctx->scratch->int1); 1420164997Ssyrinx break; 1421164997Ssyrinx } 1422164997Ssyrinx return (SNMP_ERR_NOERROR); 1423164997Ssyrinx 1424164997Ssyrinx case SNMP_OP_COMMIT: 1425164997Ssyrinx return (SNMP_ERR_NOERROR); 1426164997Ssyrinx } 1427165253Ssyrinx abort(); 1428164997Ssyrinx 1429165253Ssyrinxget: 1430164997Ssyrinx switch (val->var.subs[sub - 1]) { 1431164997Ssyrinx case LEAF_begemotBridgeStpPortProtocolMigration: 1432164997Ssyrinx val->v.integer = bp->proto_migr; 1433165253Ssyrinx return (SNMP_ERR_NOERROR); 1434165253Ssyrinx 1435164997Ssyrinx case LEAF_begemotBridgeStpPortAdminEdgePort: 1436164997Ssyrinx val->v.integer = bp->admin_edge; 1437165253Ssyrinx return (SNMP_ERR_NOERROR); 1438165253Ssyrinx 1439164997Ssyrinx case LEAF_begemotBridgeStpPortOperEdgePort: 1440164997Ssyrinx val->v.integer = bp->oper_edge; 1441165253Ssyrinx return (SNMP_ERR_NOERROR); 1442165253Ssyrinx 1443164997Ssyrinx case LEAF_begemotBridgeStpPortAdminPointToPoint: 1444165416Ssyrinx val->v.integer = bp->admin_ptp; 1445165253Ssyrinx return (SNMP_ERR_NOERROR); 1446165253Ssyrinx 1447164997Ssyrinx case LEAF_begemotBridgeStpPortOperPointToPoint: 1448165416Ssyrinx val->v.integer = bp->oper_ptp; 1449165253Ssyrinx return (SNMP_ERR_NOERROR); 1450165253Ssyrinx 1451164997Ssyrinx case LEAF_begemotBridgeStpPortAdminPathCost: 1452164997Ssyrinx val->v.integer = bp->admin_path_cost; 1453165253Ssyrinx return (SNMP_ERR_NOERROR); 1454164997Ssyrinx } 1455164997Ssyrinx 1456165253Ssyrinx abort(); 1457164997Ssyrinx} 1458164997Ssyrinx 1459164997Ssyrinxint 1460164410Ssyrinxop_begemot_tp_port(struct snmp_context *c __unused, struct snmp_value *val, 1461164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1462164410Ssyrinx{ 1463165046Ssyrinx struct bridge_port *bp; 1464164410Ssyrinx 1465164410Ssyrinx if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 1466164410Ssyrinx bridge_update_all_ports(); 1467164410Ssyrinx 1468164410Ssyrinx switch (op) { 1469164410Ssyrinx case SNMP_OP_GET: 1470164410Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1471164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1472165253Ssyrinx goto get; 1473164410Ssyrinx 1474164410Ssyrinx case SNMP_OP_GETNEXT: 1475164410Ssyrinx if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == 1476164410Ssyrinx NULL || bridge_port_index_append(&val->var, sub, bp) < 0) 1477164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1478165253Ssyrinx goto get; 1479164410Ssyrinx 1480164410Ssyrinx case SNMP_OP_SET: 1481164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1482164410Ssyrinx 1483164410Ssyrinx case SNMP_OP_ROLLBACK: 1484164410Ssyrinx case SNMP_OP_COMMIT: 1485165253Ssyrinx break; 1486164410Ssyrinx } 1487165253Ssyrinx abort(); 1488164410Ssyrinx 1489165253Ssyrinxget: 1490164410Ssyrinx switch (val->var.subs[sub - 1]) { 1491164410Ssyrinx case LEAF_begemotBridgeTpPort: 1492164410Ssyrinx val->v.integer = bp->port_no; 1493165253Ssyrinx return (SNMP_ERR_NOERROR); 1494165253Ssyrinx 1495164410Ssyrinx case LEAF_begemotBridgeTpPortMaxInfo: 1496164410Ssyrinx val->v.integer = bp->max_info; 1497165253Ssyrinx return (SNMP_ERR_NOERROR); 1498165253Ssyrinx 1499164410Ssyrinx case LEAF_begemotBridgeTpPortInFrames: 1500164410Ssyrinx val->v.uint32 = bp->in_frames; 1501165253Ssyrinx return (SNMP_ERR_NOERROR); 1502165253Ssyrinx 1503164410Ssyrinx case LEAF_begemotBridgeTpPortOutFrames: 1504164410Ssyrinx val->v.uint32 = bp->out_frames; 1505165253Ssyrinx return (SNMP_ERR_NOERROR); 1506165253Ssyrinx 1507164410Ssyrinx case LEAF_begemotBridgeTpPortInDiscards: 1508164410Ssyrinx val->v.uint32 = bp->in_drops; 1509165253Ssyrinx return (SNMP_ERR_NOERROR); 1510164410Ssyrinx } 1511164410Ssyrinx 1512165253Ssyrinx abort(); 1513164410Ssyrinx} 1514