bridge_port.c revision 164410
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: head/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c 164410 2006-11-19 15:42:48Z syrinx $ 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 90164410Ssyrinx * interface. Update the first bridge port if neccessary. 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/* 122164410Ssyrinx * Find a port entry's possition 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 277164410Ssyrinx bridge_port_memif_insert(&bridge_ports, bp, &(bif->f_bp)); 278164410Ssyrinx 279164410Ssyrinx return (bp); 280164410Ssyrinx} 281164410Ssyrinx 282164410Ssyrinx/* 283164410Ssyrinx * Update our info from the corresponding mibII interface info. 284164410Ssyrinx */ 285164410Ssyrinxvoid 286164410Ssyrinxbridge_port_getinfo_mibif(struct mibif *m_if, struct bridge_port *bp) 287164410Ssyrinx{ 288164410Ssyrinx bp->max_info = m_if->mib.ifmd_data.ifi_mtu; 289164410Ssyrinx bp->in_frames = m_if->mib.ifmd_data.ifi_ipackets; 290164410Ssyrinx bp->out_frames = m_if->mib.ifmd_data.ifi_opackets; 291164410Ssyrinx bp->in_drops = m_if->mib.ifmd_data.ifi_iqdrops; 292164410Ssyrinx} 293164410Ssyrinx 294164410Ssyrinx/* 295164410Ssyrinx * Find a port, whose SNMP's mibII ifIndex matches one of the ports, 296164410Ssyrinx * members of the specified bridge interface. 297164410Ssyrinx */ 298164410Ssyrinxstruct bridge_port * 299164410Ssyrinxbridge_port_find(int32_t if_idx, struct bridge_if *bif) 300164410Ssyrinx{ 301164410Ssyrinx struct bridge_port *bp; 302164410Ssyrinx 303164410Ssyrinx for (bp = bif->f_bp; bp != NULL; bp = TAILQ_NEXT(bp, b_p)) { 304164410Ssyrinx if (bp->sysindex != bif->sysindex) { 305164410Ssyrinx bp = NULL; 306164410Ssyrinx break; 307164410Ssyrinx } 308164410Ssyrinx 309164410Ssyrinx if (bp->if_idx == if_idx) 310164410Ssyrinx break; 311164410Ssyrinx } 312164410Ssyrinx 313164410Ssyrinx return (bp); 314164410Ssyrinx} 315164410Ssyrinx 316164410Ssyrinxvoid 317164410Ssyrinxbridge_ports_dump(struct bridge_if *bif) 318164410Ssyrinx{ 319164410Ssyrinx struct bridge_port *bp; 320164410Ssyrinx 321164410Ssyrinx for (bp = bridge_port_bif_first(bif); bp != NULL; 322164410Ssyrinx bp = bridge_port_bif_next(bp)) { 323164410Ssyrinx syslog(LOG_ERR, "memif - %s, index - %d", 324164410Ssyrinx bp->p_name, bp->port_no); 325164410Ssyrinx } 326164410Ssyrinx} 327164410Ssyrinx 328164410Ssyrinx/* 329164410Ssyrinx * RFC4188 specifics. 330164410Ssyrinx */ 331164410Ssyrinxint 332164410Ssyrinxop_dot1d_base_port(struct snmp_context *c __unused, struct snmp_value *val, 333164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 334164410Ssyrinx{ 335164410Ssyrinx struct bridge_if *bif; 336164410Ssyrinx struct bridge_port *bp; 337164410Ssyrinx 338164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 339164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 340164410Ssyrinx 341164410Ssyrinx if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 342164410Ssyrinx bridge_update_memif(bif) <= 0) 343164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 344164410Ssyrinx 345164410Ssyrinx bp = NULL; /* Make the compiler happy. */ 346164410Ssyrinx switch (op) { 347164410Ssyrinx case SNMP_OP_GET: 348164410Ssyrinx if (val->var.len - sub != 1) 349164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 350164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 351164410Ssyrinx bif)) == NULL) 352164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 353164410Ssyrinx break; 354164410Ssyrinx 355164410Ssyrinx case SNMP_OP_GETNEXT: 356164410Ssyrinx if (val->var.len - sub == 0) { 357164410Ssyrinx if ((bp = bridge_port_bif_first(bif)) == NULL) 358164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 359164410Ssyrinx } else { 360164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 361164410Ssyrinx bif)) == NULL || 362164410Ssyrinx (bp = bridge_port_bif_next(bp)) == NULL) 363164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 364164410Ssyrinx } 365164410Ssyrinx val->var.len = sub + 1; 366164410Ssyrinx val->var.subs[sub] = bp->port_no; 367164410Ssyrinx break; 368164410Ssyrinx 369164410Ssyrinx case SNMP_OP_SET: 370164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 371164410Ssyrinx 372164410Ssyrinx case SNMP_OP_ROLLBACK: 373164410Ssyrinx case SNMP_OP_COMMIT: 374164410Ssyrinx abort(); 375164410Ssyrinx } 376164410Ssyrinx 377164410Ssyrinx switch (val->var.subs[sub - 1]) { 378164410Ssyrinx case LEAF_dot1dBasePort: 379164410Ssyrinx val->v.integer = bp->port_no; 380164410Ssyrinx break; 381164410Ssyrinx case LEAF_dot1dBasePortIfIndex: 382164410Ssyrinx val->v.integer = bp->if_idx; 383164410Ssyrinx break; 384164410Ssyrinx case LEAF_dot1dBasePortCircuit: 385164410Ssyrinx val->v.oid = bp->circuit; 386164410Ssyrinx break; 387164410Ssyrinx case LEAF_dot1dBasePortDelayExceededDiscards: 388164410Ssyrinx val->v.uint32 = bp->dly_ex_drops; 389164410Ssyrinx break; 390164410Ssyrinx case LEAF_dot1dBasePortMtuExceededDiscards: 391164410Ssyrinx val->v.uint32 = bp->dly_mtu_drops; 392164410Ssyrinx break; 393164410Ssyrinx } 394164410Ssyrinx 395164410Ssyrinx return (SNMP_ERR_NOERROR); 396164410Ssyrinx} 397164410Ssyrinx 398164410Ssyrinxint 399164410Ssyrinxop_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val, 400164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 401164410Ssyrinx{ 402164410Ssyrinx int ret; 403164410Ssyrinx struct bridge_if *bif; 404164410Ssyrinx struct bridge_port *bp; 405164410Ssyrinx 406164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 407164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 408164410Ssyrinx 409164410Ssyrinx if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 410164410Ssyrinx bridge_update_memif(bif) <= 0) 411164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 412164410Ssyrinx 413164410Ssyrinx bp = NULL; /* Make the compiler happy. */ 414164410Ssyrinx ret = SNMP_ERR_NOERROR; 415164410Ssyrinx 416164410Ssyrinx switch (op) { 417164410Ssyrinx case SNMP_OP_GET: 418164410Ssyrinx if (val->var.len - sub != 1) 419164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 420164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 421164410Ssyrinx bif)) == NULL) 422164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 423164410Ssyrinx break; 424164410Ssyrinx 425164410Ssyrinx case SNMP_OP_GETNEXT: 426164410Ssyrinx if (val->var.len - sub == 0) { 427164410Ssyrinx if ((bp = bridge_port_bif_first(bif)) == NULL) 428164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 429164410Ssyrinx } else { 430164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 431164410Ssyrinx bif)) == NULL || 432164410Ssyrinx (bp = bridge_port_bif_next(bp)) == NULL) 433164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 434164410Ssyrinx } 435164410Ssyrinx val->var.len = sub + 1; 436164410Ssyrinx val->var.subs[sub] = bp->port_no; 437164410Ssyrinx break; 438164410Ssyrinx 439164410Ssyrinx case SNMP_OP_SET: 440164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 441164410Ssyrinx bif)) == NULL) 442164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 443164410Ssyrinx 444164410Ssyrinx switch (val->var.subs[sub - 1]) { 445164410Ssyrinx case LEAF_dot1dStpPortPriority: 446164410Ssyrinx ctx->scratch->int1 = bp->priority; 447164410Ssyrinx ret = bridge_port_set_priority(bif->bif_name, bp, 448164410Ssyrinx val->v.integer); 449164410Ssyrinx break; 450164410Ssyrinx case LEAF_dot1dStpPortEnable: 451164410Ssyrinx ctx->scratch->int1 = bp->enable; 452164410Ssyrinx ret = bridge_port_set_stp_enable(bif->bif_name, 453164410Ssyrinx bp, val->v.integer); 454164410Ssyrinx break; 455164410Ssyrinx case LEAF_dot1dStpPortPathCost: 456164410Ssyrinx ctx->scratch->int1 = bp->path_cost; 457164410Ssyrinx ret = bridge_port_set_path_cost(bif->bif_name, bp, 458164410Ssyrinx val->v.integer); 459164410Ssyrinx break; 460164410Ssyrinx case LEAF_dot1dStpPort: 461164410Ssyrinx case LEAF_dot1dStpPortState: 462164410Ssyrinx case LEAF_dot1dStpPortDesignatedRoot: 463164410Ssyrinx case LEAF_dot1dStpPortDesignatedCost: 464164410Ssyrinx case LEAF_dot1dStpPortDesignatedBridge: 465164410Ssyrinx case LEAF_dot1dStpPortDesignatedPort: 466164410Ssyrinx case LEAF_dot1dStpPortForwardTransitions: 467164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 468164410Ssyrinx } 469164410Ssyrinx if (ret == 0) 470164410Ssyrinx return (SNMP_ERR_NOERROR); 471164410Ssyrinx else if (ret == -2) 472164410Ssyrinx return (SNMP_ERR_WRONG_VALUE); 473164410Ssyrinx return (SNMP_ERR_GENERR); 474164410Ssyrinx 475164410Ssyrinx case SNMP_OP_ROLLBACK: 476164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 477164410Ssyrinx bif)) == NULL) 478164410Ssyrinx return (SNMP_ERR_GENERR); 479164410Ssyrinx switch (val->var.subs[sub - 1]) { 480164410Ssyrinx case LEAF_dot1dStpPortPriority: 481164410Ssyrinx bridge_port_set_priority(bif->bif_name, bp, 482164410Ssyrinx ctx->scratch->int1); 483164410Ssyrinx break; 484164410Ssyrinx case LEAF_dot1dStpPortEnable: 485164410Ssyrinx bridge_port_set_stp_enable(bif->bif_name, bp, 486164410Ssyrinx ctx->scratch->int1); 487164410Ssyrinx break; 488164410Ssyrinx case LEAF_dot1dStpPortPathCost: 489164410Ssyrinx bridge_port_set_path_cost(bif->bif_name, bp, 490164410Ssyrinx ctx->scratch->int1); 491164410Ssyrinx break; 492164410Ssyrinx } 493164410Ssyrinx return (SNMP_ERR_NOERROR); 494164410Ssyrinx 495164410Ssyrinx case SNMP_OP_COMMIT: 496164410Ssyrinx return (SNMP_ERR_NOERROR); 497164410Ssyrinx } 498164410Ssyrinx 499164410Ssyrinx switch (val->var.subs[sub - 1]) { 500164410Ssyrinx case LEAF_dot1dStpPort: 501164410Ssyrinx val->v.integer = bp->port_no; 502164410Ssyrinx break; 503164410Ssyrinx case LEAF_dot1dStpPortPriority: 504164410Ssyrinx val->v.integer = bp->priority; 505164410Ssyrinx break; 506164410Ssyrinx case LEAF_dot1dStpPortState: 507164410Ssyrinx val->v.integer = bp->state; 508164410Ssyrinx break; 509164410Ssyrinx case LEAF_dot1dStpPortEnable: 510164410Ssyrinx val->v.integer = bp->enable; 511164410Ssyrinx break; 512164410Ssyrinx case LEAF_dot1dStpPortPathCost: 513164410Ssyrinx val->v.integer = bp->path_cost; 514164410Ssyrinx break; 515164410Ssyrinx case LEAF_dot1dStpPortDesignatedRoot: 516164410Ssyrinx ret = string_get(val, bp->design_root, 517164410Ssyrinx SNMP_BRIDGE_ID_LEN); 518164410Ssyrinx break; 519164410Ssyrinx case LEAF_dot1dStpPortDesignatedCost: 520164410Ssyrinx val->v.integer = bp->design_cost; 521164410Ssyrinx break; 522164410Ssyrinx case LEAF_dot1dStpPortDesignatedBridge: 523164410Ssyrinx ret = string_get(val, bp->design_bridge, 524164410Ssyrinx SNMP_BRIDGE_ID_LEN); 525164410Ssyrinx break; 526164410Ssyrinx case LEAF_dot1dStpPortDesignatedPort: 527164410Ssyrinx ret = string_get(val, bp->design_port, 2); 528164410Ssyrinx break; 529164410Ssyrinx case LEAF_dot1dStpPortForwardTransitions: 530164410Ssyrinx val->v.uint32 = bp->fwd_trans; 531164410Ssyrinx break; 532164410Ssyrinx } 533164410Ssyrinx 534164410Ssyrinx return (ret); 535164410Ssyrinx} 536164410Ssyrinx 537164410Ssyrinxint 538164410Ssyrinxop_dot1d_tp_port(struct snmp_context *c __unused, struct snmp_value *val, 539164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 540164410Ssyrinx{ 541164410Ssyrinx struct bridge_if *bif; 542164410Ssyrinx struct bridge_port *bp; 543164410Ssyrinx 544164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 545164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 546164410Ssyrinx 547164410Ssyrinx if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 548164410Ssyrinx bridge_update_memif(bif) <= 0) 549164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 550164410Ssyrinx 551164410Ssyrinx bp = NULL; /* Make the compiler happy. */ 552164410Ssyrinx switch (op) { 553164410Ssyrinx case SNMP_OP_GET: 554164410Ssyrinx if (val->var.len - sub != 1) 555164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 556164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 557164410Ssyrinx bif)) == NULL) 558164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 559164410Ssyrinx break; 560164410Ssyrinx 561164410Ssyrinx case SNMP_OP_GETNEXT: 562164410Ssyrinx if (val->var.len - sub == 0) { 563164410Ssyrinx if ((bp = bridge_port_bif_first(bif)) == NULL) 564164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 565164410Ssyrinx } else { 566164410Ssyrinx if ((bp = bridge_port_find(val->var.subs[sub], 567164410Ssyrinx bif)) == NULL || 568164410Ssyrinx (bp = bridge_port_bif_next(bp)) == NULL) 569164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 570164410Ssyrinx } 571164410Ssyrinx val->var.len = sub + 1; 572164410Ssyrinx val->var.subs[sub] = bp->port_no; 573164410Ssyrinx break; 574164410Ssyrinx 575164410Ssyrinx case SNMP_OP_SET: 576164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 577164410Ssyrinx 578164410Ssyrinx case SNMP_OP_ROLLBACK: 579164410Ssyrinx case SNMP_OP_COMMIT: 580164410Ssyrinx abort(); 581164410Ssyrinx } 582164410Ssyrinx 583164410Ssyrinx switch (val->var.subs[sub - 1]) { 584164410Ssyrinx case LEAF_dot1dTpPort: 585164410Ssyrinx val->v.integer = bp->port_no; 586164410Ssyrinx break; 587164410Ssyrinx case LEAF_dot1dTpPortMaxInfo: 588164410Ssyrinx val->v.integer = bp->max_info; 589164410Ssyrinx break; 590164410Ssyrinx case LEAF_dot1dTpPortInFrames: 591164410Ssyrinx val->v.uint32 = bp->in_frames; 592164410Ssyrinx break; 593164410Ssyrinx case LEAF_dot1dTpPortOutFrames: 594164410Ssyrinx val->v.uint32 = bp->out_frames; 595164410Ssyrinx break; 596164410Ssyrinx case LEAF_dot1dTpPortInDiscards: 597164410Ssyrinx val->v.uint32 = bp->in_drops; 598164410Ssyrinx break; 599164410Ssyrinx } 600164410Ssyrinx 601164410Ssyrinx return (SNMP_ERR_NOERROR); 602164410Ssyrinx} 603164410Ssyrinx 604164410Ssyrinx/* 605164410Ssyrinx * Private BEGEMOT-BRIDGE-MIB specifics. 606164410Ssyrinx */ 607164410Ssyrinx 608164410Ssyrinx/* 609164410Ssyrinx * Construct a bridge port entry index. 610164410Ssyrinx */ 611164410Ssyrinxstatic int 612164410Ssyrinxbridge_port_index_append(struct asn_oid *oid, uint sub, 613164410Ssyrinx const struct bridge_port *bp) 614164410Ssyrinx{ 615164410Ssyrinx uint i; 616164410Ssyrinx const char *b_name; 617164410Ssyrinx 618164410Ssyrinx if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) 619164410Ssyrinx return (-1); 620164410Ssyrinx 621164410Ssyrinx oid->len = sub + strlen(b_name) + 1 + 1; 622164410Ssyrinx oid->subs[sub] = strlen(b_name); 623164410Ssyrinx 624164410Ssyrinx for (i = 1; i <= strlen(b_name); i++) 625164410Ssyrinx oid->subs[sub + i] = b_name[i - 1]; 626164410Ssyrinx 627164410Ssyrinx oid->subs[sub + i] = bp->port_no; 628164410Ssyrinx 629164410Ssyrinx return (0); 630164410Ssyrinx} 631164410Ssyrinx 632164410Ssyrinx/* 633164410Ssyrinx * Get the port entry from an entry's index. 634164410Ssyrinx */ 635164410Ssyrinxstatic struct bridge_port * 636164410Ssyrinxbridge_port_index_get(const struct asn_oid *oid, uint sub, int8_t status) 637164410Ssyrinx{ 638164410Ssyrinx uint i; 639164410Ssyrinx int32_t port_no; 640164410Ssyrinx char bif_name[IFNAMSIZ]; 641164410Ssyrinx struct bridge_if *bif; 642164410Ssyrinx struct bridge_port *bp; 643164410Ssyrinx 644164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 2 || 645164410Ssyrinx oid->subs[sub] >= IFNAMSIZ) 646164410Ssyrinx return (NULL); 647164410Ssyrinx 648164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 649164410Ssyrinx bif_name[i] = oid->subs[sub + i + 1]; 650164410Ssyrinx bif_name[i] = '\0'; 651164410Ssyrinx 652164410Ssyrinx port_no = oid->subs[sub + i + 1]; 653164410Ssyrinx 654164410Ssyrinx if ((bif = bridge_if_find_ifname(bif_name)) == NULL) 655164410Ssyrinx return (NULL); 656164410Ssyrinx 657164410Ssyrinx if ((bp = bridge_port_find(port_no, bif)) == NULL || 658164410Ssyrinx (status == 0 && bp->status != RowStatus_active)) 659164410Ssyrinx return (NULL); 660164410Ssyrinx 661164410Ssyrinx return (bp); 662164410Ssyrinx} 663164410Ssyrinx 664164410Ssyrinx/* 665164410Ssyrinx * Get the next port entry from an entry's index. 666164410Ssyrinx */ 667164410Ssyrinxstatic struct bridge_port * 668164410Ssyrinxbridge_port_index_getnext(const struct asn_oid *oid, uint sub, int8_t status) 669164410Ssyrinx{ 670164410Ssyrinx uint i; 671164410Ssyrinx int32_t port_no; 672164410Ssyrinx char bif_name[IFNAMSIZ]; 673164410Ssyrinx struct bridge_if *bif; 674164410Ssyrinx struct bridge_port *bp; 675164410Ssyrinx 676164410Ssyrinx if (oid->len - sub == 0) 677164410Ssyrinx bp = bridge_port_first(); 678164410Ssyrinx else { 679164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 2 || 680164410Ssyrinx oid->subs[sub] >= IFNAMSIZ) 681164410Ssyrinx return (NULL); 682164410Ssyrinx 683164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 684164410Ssyrinx bif_name[i] = oid->subs[sub + i + 1]; 685164410Ssyrinx bif_name[i] = '\0'; 686164410Ssyrinx 687164410Ssyrinx port_no = oid->subs[sub + i + 1]; 688164410Ssyrinx 689164410Ssyrinx if ((bif = bridge_if_find_ifname(bif_name)) == NULL || 690164410Ssyrinx (bp = bridge_port_find(port_no, bif)) == NULL) 691164410Ssyrinx return (NULL); 692164410Ssyrinx 693164410Ssyrinx bp = bridge_port_next(bp); 694164410Ssyrinx } 695164410Ssyrinx 696164410Ssyrinx if (status == 1) 697164410Ssyrinx return (bp); 698164410Ssyrinx 699164410Ssyrinx while (bp != NULL) { 700164410Ssyrinx if (bp->status == RowStatus_active) 701164410Ssyrinx break; 702164410Ssyrinx bp = bridge_port_next(bp); 703164410Ssyrinx } 704164410Ssyrinx 705164410Ssyrinx return (bp); 706164410Ssyrinx} 707164410Ssyrinx 708164410Ssyrinx/* 709164410Ssyrinx * Read the bridge name and port index from a ASN OID structure. 710164410Ssyrinx */ 711164410Ssyrinxstatic int 712164410Ssyrinxbridge_port_index_decode(const struct asn_oid *oid, uint sub, 713164410Ssyrinx char *b_name, int32_t *idx) 714164410Ssyrinx{ 715164410Ssyrinx uint i; 716164410Ssyrinx 717164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 2 || 718164410Ssyrinx oid->subs[sub] >= IFNAMSIZ) 719164410Ssyrinx return (-1); 720164410Ssyrinx 721164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 722164410Ssyrinx b_name[i] = oid->subs[sub + i + 1]; 723164410Ssyrinx b_name[i] = '\0'; 724164410Ssyrinx 725164410Ssyrinx *idx = oid->subs[sub + i + 1]; 726164410Ssyrinx return (0); 727164410Ssyrinx} 728164410Ssyrinx 729164410Ssyrinxstatic int 730164410Ssyrinxbridge_port_set_status(struct snmp_context *ctx, 731164410Ssyrinx struct snmp_value *val, uint sub) 732164410Ssyrinx{ 733164410Ssyrinx int32_t if_idx; 734164410Ssyrinx char b_name[IFNAMSIZ]; 735164410Ssyrinx struct bridge_if *bif; 736164410Ssyrinx struct bridge_port *bp; 737164410Ssyrinx struct mibif *mif; 738164410Ssyrinx 739164410Ssyrinx if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 740164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 741164410Ssyrinx 742164410Ssyrinx if ((bif = bridge_if_find_ifname(b_name)) == NULL || 743164410Ssyrinx (mif = mib_find_if(if_idx)) == NULL) 744164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 745164410Ssyrinx 746164410Ssyrinx bp = bridge_port_find(if_idx, bif); 747164410Ssyrinx 748164410Ssyrinx switch (val->v.integer) { 749164410Ssyrinx case RowStatus_active: 750164410Ssyrinx if (bp == NULL) 751164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 752164410Ssyrinx 753164410Ssyrinx if (bp->span_enable == 0) 754164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 755164410Ssyrinx 756164410Ssyrinx ctx->scratch->int1 = bp->status; 757164410Ssyrinx bp->status = RowStatus_active; 758164410Ssyrinx break; 759164410Ssyrinx 760164410Ssyrinx case RowStatus_notInService: 761164410Ssyrinx if (bp == NULL || bp->span_enable == 0 || 762164410Ssyrinx bp->status == RowStatus_active) 763164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 764164410Ssyrinx 765164410Ssyrinx ctx->scratch->int1 = bp->status; 766164410Ssyrinx bp->status = RowStatus_notInService; 767164410Ssyrinx 768164410Ssyrinx case RowStatus_notReady: 769164410Ssyrinx /* FALLTHROUGH */ 770164410Ssyrinx case RowStatus_createAndGo: 771164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 772164410Ssyrinx 773164410Ssyrinx case RowStatus_createAndWait: 774164410Ssyrinx if (bp != NULL) 775164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 776164410Ssyrinx 777164410Ssyrinx if ((bp = bridge_new_port(mif, bif)) == NULL) 778164410Ssyrinx return (SNMP_ERR_GENERR); 779164410Ssyrinx 780164410Ssyrinx ctx->scratch->int1 = RowStatus_destroy; 781164410Ssyrinx bp->status = RowStatus_notReady; 782164410Ssyrinx break; 783164410Ssyrinx 784164410Ssyrinx case RowStatus_destroy: 785164410Ssyrinx if (bp == NULL) 786164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 787164410Ssyrinx 788164410Ssyrinx ctx->scratch->int1 = bp->status; 789164410Ssyrinx bp->status = RowStatus_destroy; 790164410Ssyrinx break; 791164410Ssyrinx } 792164410Ssyrinx 793164410Ssyrinx return (SNMP_ERR_NOERROR); 794164410Ssyrinx} 795164410Ssyrinx 796164410Ssyrinxstatic int 797164410Ssyrinxbridge_port_rollback_status(struct snmp_context *ctx, 798164410Ssyrinx struct snmp_value *val, uint sub) 799164410Ssyrinx{ 800164410Ssyrinx int32_t if_idx; 801164410Ssyrinx char b_name[IFNAMSIZ]; 802164410Ssyrinx struct bridge_if *bif; 803164410Ssyrinx struct bridge_port *bp; 804164410Ssyrinx 805164410Ssyrinx if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 806164410Ssyrinx return (SNMP_ERR_GENERR); 807164410Ssyrinx 808164410Ssyrinx if ((bif = bridge_if_find_ifname(b_name)) == NULL || 809164410Ssyrinx (bp = bridge_port_find(if_idx, bif)) == NULL) 810164410Ssyrinx return (SNMP_ERR_GENERR); 811164410Ssyrinx 812164410Ssyrinx if (ctx->scratch->int1 == RowStatus_destroy) 813164410Ssyrinx bridge_port_remove(bp, bif); 814164410Ssyrinx else 815164410Ssyrinx bp->status = ctx->scratch->int1; 816164410Ssyrinx 817164410Ssyrinx return (SNMP_ERR_NOERROR); 818164410Ssyrinx} 819164410Ssyrinx 820164410Ssyrinxstatic int 821164410Ssyrinxbridge_port_commit_status(struct snmp_value *val, uint sub) 822164410Ssyrinx{ 823164410Ssyrinx int32_t if_idx; 824164410Ssyrinx char b_name[IFNAMSIZ]; 825164410Ssyrinx struct bridge_if *bif; 826164410Ssyrinx struct bridge_port *bp; 827164410Ssyrinx 828164410Ssyrinx if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 829164410Ssyrinx return (SNMP_ERR_GENERR); 830164410Ssyrinx 831164410Ssyrinx if ((bif = bridge_if_find_ifname(b_name)) == NULL || 832164410Ssyrinx (bp = bridge_port_find(if_idx, bif)) == NULL) 833164410Ssyrinx return (SNMP_ERR_GENERR); 834164410Ssyrinx 835164410Ssyrinx switch (bp->status) { 836164410Ssyrinx case RowStatus_active: 837164410Ssyrinx if (bridge_port_addm(bp, b_name) < 0) 838164410Ssyrinx return (SNMP_ERR_COMMIT_FAILED); 839164410Ssyrinx break; 840164410Ssyrinx 841164410Ssyrinx case RowStatus_destroy: 842164410Ssyrinx if (bridge_port_delm(bp, b_name) < 0) 843164410Ssyrinx return (SNMP_ERR_COMMIT_FAILED); 844164410Ssyrinx bridge_port_remove(bp, bif); 845164410Ssyrinx break; 846164410Ssyrinx } 847164410Ssyrinx 848164410Ssyrinx return (SNMP_ERR_NOERROR); 849164410Ssyrinx} 850164410Ssyrinx 851164410Ssyrinxstatic int 852164410Ssyrinxbridge_port_set_span_enable(struct snmp_context *ctx, 853164410Ssyrinx struct snmp_value *val, uint sub) 854164410Ssyrinx{ 855164410Ssyrinx int32_t if_idx; 856164410Ssyrinx char b_name[IFNAMSIZ]; 857164410Ssyrinx struct bridge_if *bif; 858164410Ssyrinx struct bridge_port *bp; 859164410Ssyrinx struct mibif *mif; 860164410Ssyrinx 861164410Ssyrinx if (val->v.integer != begemotBridgeBaseSpanEnabled_enabled && 862164410Ssyrinx val->v.integer != begemotBridgeBaseSpanEnabled_disabled) 863164410Ssyrinx return (SNMP_ERR_BADVALUE); 864164410Ssyrinx 865164410Ssyrinx if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 866164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 867164410Ssyrinx 868164410Ssyrinx if ((bif = bridge_if_find_ifname(b_name)) == NULL) 869164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 870164410Ssyrinx 871164410Ssyrinx if ((bp = bridge_port_find(if_idx, bif)) == NULL) { 872164410Ssyrinx if ((mif = mib_find_if(if_idx)) == NULL) 873164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 874164410Ssyrinx 875164410Ssyrinx if ((bp = bridge_new_port(mif, bif)) == NULL) 876164410Ssyrinx return (SNMP_ERR_GENERR); 877164410Ssyrinx 878164410Ssyrinx ctx->scratch->int1 = RowStatus_destroy; 879164410Ssyrinx } else if (bp->status == RowStatus_active) { 880164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 881164410Ssyrinx } else { 882164410Ssyrinx ctx->scratch->int1 = bp->status; 883164410Ssyrinx } 884164410Ssyrinx 885164410Ssyrinx bp->span_enable = val->v.integer; 886164410Ssyrinx bp->status = RowStatus_notInService; 887164410Ssyrinx 888164410Ssyrinx return (SNMP_ERR_NOERROR); 889164410Ssyrinx} 890164410Ssyrinx 891164410Ssyrinxint 892164410Ssyrinxop_begemot_base_port(struct snmp_context *ctx, struct snmp_value *val, 893164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 894164410Ssyrinx{ 895164410Ssyrinx int8_t status, which; 896164410Ssyrinx struct bridge_port *bp = NULL; 897164410Ssyrinx 898164410Ssyrinx if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 899164410Ssyrinx bridge_update_all_ports(); 900164410Ssyrinx 901164410Ssyrinx which = val->var.subs[sub - 1]; 902164410Ssyrinx status = 0; 903164410Ssyrinx 904164410Ssyrinx switch (op) { 905164410Ssyrinx case SNMP_OP_GET: 906164410Ssyrinx if (which == LEAF_begemotBridgeBaseSpanEnabled || 907164410Ssyrinx which == LEAF_begemotBridgeBasePortStatus) 908164410Ssyrinx status = 1; 909164410Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 910164410Ssyrinx status)) == NULL) 911164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 912164410Ssyrinx break; 913164410Ssyrinx 914164410Ssyrinx case SNMP_OP_GETNEXT: 915164410Ssyrinx if (which == LEAF_begemotBridgeBaseSpanEnabled || 916164410Ssyrinx which == LEAF_begemotBridgeBasePortStatus) 917164410Ssyrinx status = 1; 918164410Ssyrinx if ((bp = bridge_port_index_getnext(&val->var, sub, 919164410Ssyrinx status)) == NULL || 920164410Ssyrinx bridge_port_index_append(&val->var, sub, bp) < 0) 921164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 922164410Ssyrinx break; 923164410Ssyrinx 924164410Ssyrinx case SNMP_OP_SET: 925164410Ssyrinx switch (which) { 926164410Ssyrinx case LEAF_begemotBridgeBaseSpanEnabled: 927164410Ssyrinx return (bridge_port_set_span_enable(ctx, val, sub)); 928164410Ssyrinx 929164410Ssyrinx case LEAF_begemotBridgeBasePortStatus: 930164410Ssyrinx return (bridge_port_set_status(ctx, val, sub)); 931164410Ssyrinx 932164410Ssyrinx case LEAF_begemotBridgeBasePort: 933164410Ssyrinx case LEAF_begemotBridgeBasePortIfIndex: 934164410Ssyrinx case LEAF_begemotBridgeBasePortDelayExceededDiscards: 935164410Ssyrinx case LEAF_begemotBridgeBasePortMtuExceededDiscards: 936164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 937164410Ssyrinx } 938164410Ssyrinx abort(); 939164410Ssyrinx 940164410Ssyrinx case SNMP_OP_ROLLBACK: 941164410Ssyrinx switch (which) { 942164410Ssyrinx case LEAF_begemotBridgeBaseSpanEnabled: 943164410Ssyrinx /* FALLTHROUGH */ 944164410Ssyrinx case LEAF_begemotBridgeBasePortStatus: 945164410Ssyrinx return (bridge_port_rollback_status(ctx, val, sub)); 946164410Ssyrinx } 947164410Ssyrinx return (SNMP_ERR_NOERROR); 948164410Ssyrinx 949164410Ssyrinx case SNMP_OP_COMMIT: 950164410Ssyrinx if (which == LEAF_begemotBridgeBasePortStatus) 951164410Ssyrinx return (bridge_port_commit_status(val, sub)); 952164410Ssyrinx 953164410Ssyrinx return (SNMP_ERR_NOERROR); 954164410Ssyrinx } 955164410Ssyrinx 956164410Ssyrinx switch (which) { 957164410Ssyrinx case LEAF_begemotBridgeBasePort: 958164410Ssyrinx val->v.integer = bp->port_no; 959164410Ssyrinx break; 960164410Ssyrinx case LEAF_begemotBridgeBasePortIfIndex: 961164410Ssyrinx val->v.integer = bp->if_idx; 962164410Ssyrinx break; 963164410Ssyrinx case LEAF_begemotBridgeBaseSpanEnabled: 964164410Ssyrinx val->v.integer = bp->span_enable; 965164410Ssyrinx break; 966164410Ssyrinx case LEAF_begemotBridgeBasePortDelayExceededDiscards: 967164410Ssyrinx val->v.uint32 = bp->dly_ex_drops; 968164410Ssyrinx break; 969164410Ssyrinx case LEAF_begemotBridgeBasePortMtuExceededDiscards: 970164410Ssyrinx val->v.uint32 = bp->dly_mtu_drops; 971164410Ssyrinx break; 972164410Ssyrinx case LEAF_begemotBridgeBasePortStatus: 973164410Ssyrinx val->v.integer = bp->status; 974164410Ssyrinx break; 975164410Ssyrinx } 976164410Ssyrinx 977164410Ssyrinx return (SNMP_ERR_NOERROR); 978164410Ssyrinx} 979164410Ssyrinx 980164410Ssyrinxint 981164410Ssyrinxop_begemot_stp_port(struct snmp_context *ctx, struct snmp_value *val, 982164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 983164410Ssyrinx{ 984164410Ssyrinx int ret; 985164410Ssyrinx struct bridge_port *bp = NULL; 986164410Ssyrinx const char *b_name; 987164410Ssyrinx 988164410Ssyrinx if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 989164410Ssyrinx bridge_update_all_ports(); 990164410Ssyrinx 991164410Ssyrinx switch (op) { 992164410Ssyrinx case SNMP_OP_GET: 993164410Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 994164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 995164410Ssyrinx break; 996164410Ssyrinx 997164410Ssyrinx case SNMP_OP_GETNEXT: 998164410Ssyrinx if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == 999164410Ssyrinx NULL || bridge_port_index_append(&val->var, sub, bp) < 0) 1000164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1001164410Ssyrinx break; 1002164410Ssyrinx 1003164410Ssyrinx case SNMP_OP_SET: 1004164410Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1005164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1006164410Ssyrinx if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) 1007164410Ssyrinx return (SNMP_ERR_GENERR); 1008164410Ssyrinx 1009164410Ssyrinx ret = SNMP_ERR_NOERROR; 1010164410Ssyrinx switch (val->var.subs[sub - 1]) { 1011164410Ssyrinx case LEAF_begemotBridgeStpPortPriority: 1012164410Ssyrinx ctx->scratch->int1 = bp->priority; 1013164410Ssyrinx ret = bridge_port_set_priority(b_name, bp, 1014164410Ssyrinx val->v.integer); 1015164410Ssyrinx break; 1016164410Ssyrinx case LEAF_begemotBridgeStpPortEnable: 1017164410Ssyrinx ctx->scratch->int1 = bp->enable; 1018164410Ssyrinx ret = bridge_port_set_stp_enable(b_name, bp, 1019164410Ssyrinx val->v.integer); 1020164410Ssyrinx break; 1021164410Ssyrinx case LEAF_begemotBridgeStpPortPathCost: 1022164410Ssyrinx ctx->scratch->int1 = bp->path_cost; 1023164410Ssyrinx ret = bridge_port_set_path_cost(b_name, bp, 1024164410Ssyrinx val->v.integer); 1025164410Ssyrinx break; 1026164410Ssyrinx case LEAF_begemotBridgeStpPort: 1027164410Ssyrinx case LEAF_begemotBridgeStpPortState: 1028164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedRoot: 1029164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedCost: 1030164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedBridge: 1031164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedPort: 1032164410Ssyrinx case LEAF_begemotBridgeStpPortForwardTransitions: 1033164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1034164410Ssyrinx } 1035164410Ssyrinx if (ret == 0) 1036164410Ssyrinx return (SNMP_ERR_NOERROR); 1037164410Ssyrinx else if (ret == -2) 1038164410Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1039164410Ssyrinx return (SNMP_ERR_GENERR); 1040164410Ssyrinx 1041164410Ssyrinx case SNMP_OP_ROLLBACK: 1042164410Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL || 1043164410Ssyrinx (b_name = bridge_if_find_name(bp->sysindex)) == NULL) 1044164410Ssyrinx return (SNMP_ERR_GENERR); 1045164410Ssyrinx 1046164410Ssyrinx switch (val->var.subs[sub - 1]) { 1047164410Ssyrinx case LEAF_begemotBridgeStpPortPriority: 1048164410Ssyrinx bridge_port_set_priority(b_name, bp, 1049164410Ssyrinx ctx->scratch->int1); 1050164410Ssyrinx break; 1051164410Ssyrinx case LEAF_begemotBridgeStpPortEnable: 1052164410Ssyrinx bridge_port_set_stp_enable(b_name, bp, 1053164410Ssyrinx ctx->scratch->int1); 1054164410Ssyrinx break; 1055164410Ssyrinx case LEAF_begemotBridgeStpPortPathCost: 1056164410Ssyrinx bridge_port_set_path_cost(b_name, bp, 1057164410Ssyrinx ctx->scratch->int1); 1058164410Ssyrinx break; 1059164410Ssyrinx } 1060164410Ssyrinx return (SNMP_ERR_NOERROR); 1061164410Ssyrinx 1062164410Ssyrinx case SNMP_OP_COMMIT: 1063164410Ssyrinx return (SNMP_ERR_NOERROR); 1064164410Ssyrinx } 1065164410Ssyrinx 1066164410Ssyrinx ret = SNMP_ERR_NOERROR; 1067164410Ssyrinx 1068164410Ssyrinx switch (val->var.subs[sub - 1]) { 1069164410Ssyrinx case LEAF_begemotBridgeStpPort: 1070164410Ssyrinx val->v.integer = bp->port_no; 1071164410Ssyrinx break; 1072164410Ssyrinx case LEAF_begemotBridgeStpPortPriority: 1073164410Ssyrinx val->v.integer = bp->priority; 1074164410Ssyrinx break; 1075164410Ssyrinx case LEAF_begemotBridgeStpPortState: 1076164410Ssyrinx val->v.integer = bp->state; 1077164410Ssyrinx break; 1078164410Ssyrinx case LEAF_begemotBridgeStpPortEnable: 1079164410Ssyrinx val->v.integer = bp->enable; 1080164410Ssyrinx break; 1081164410Ssyrinx case LEAF_begemotBridgeStpPortPathCost: 1082164410Ssyrinx val->v.integer = bp->path_cost; 1083164410Ssyrinx break; 1084164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedRoot: 1085164410Ssyrinx ret = string_get(val, bp->design_root, SNMP_BRIDGE_ID_LEN); 1086164410Ssyrinx break; 1087164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedCost: 1088164410Ssyrinx val->v.integer = bp->design_cost; 1089164410Ssyrinx break; 1090164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedBridge: 1091164410Ssyrinx ret = string_get(val, bp->design_bridge, SNMP_BRIDGE_ID_LEN); 1092164410Ssyrinx break; 1093164410Ssyrinx case LEAF_begemotBridgeStpPortDesignatedPort: 1094164410Ssyrinx ret = string_get(val, bp->design_port, 2); 1095164410Ssyrinx break; 1096164410Ssyrinx case LEAF_begemotBridgeStpPortForwardTransitions: 1097164410Ssyrinx val->v.uint32 = bp->fwd_trans; 1098164410Ssyrinx break; 1099164410Ssyrinx } 1100164410Ssyrinx 1101164410Ssyrinx return (ret); 1102164410Ssyrinx} 1103164410Ssyrinx 1104164410Ssyrinxint 1105164410Ssyrinxop_begemot_tp_port(struct snmp_context *c __unused, struct snmp_value *val, 1106164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1107164410Ssyrinx{ 1108164410Ssyrinx struct bridge_port *bp = NULL; 1109164410Ssyrinx 1110164410Ssyrinx if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 1111164410Ssyrinx bridge_update_all_ports(); 1112164410Ssyrinx 1113164410Ssyrinx switch (op) { 1114164410Ssyrinx case SNMP_OP_GET: 1115164410Ssyrinx if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1116164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1117164410Ssyrinx break; 1118164410Ssyrinx 1119164410Ssyrinx case SNMP_OP_GETNEXT: 1120164410Ssyrinx if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == 1121164410Ssyrinx NULL || bridge_port_index_append(&val->var, sub, bp) < 0) 1122164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1123164410Ssyrinx break; 1124164410Ssyrinx 1125164410Ssyrinx case SNMP_OP_SET: 1126164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1127164410Ssyrinx 1128164410Ssyrinx case SNMP_OP_ROLLBACK: 1129164410Ssyrinx case SNMP_OP_COMMIT: 1130164410Ssyrinx return (SNMP_ERR_NOERROR); 1131164410Ssyrinx } 1132164410Ssyrinx 1133164410Ssyrinx switch (val->var.subs[sub - 1]) { 1134164410Ssyrinx case LEAF_begemotBridgeTpPort: 1135164410Ssyrinx val->v.integer = bp->port_no; 1136164410Ssyrinx break; 1137164410Ssyrinx case LEAF_begemotBridgeTpPortMaxInfo: 1138164410Ssyrinx val->v.integer = bp->max_info; 1139164410Ssyrinx break; 1140164410Ssyrinx case LEAF_begemotBridgeTpPortInFrames: 1141164410Ssyrinx val->v.uint32 = bp->in_frames; 1142164410Ssyrinx break; 1143164410Ssyrinx case LEAF_begemotBridgeTpPortOutFrames: 1144164410Ssyrinx val->v.uint32 = bp->out_frames; 1145164410Ssyrinx break; 1146164410Ssyrinx case LEAF_begemotBridgeTpPortInDiscards: 1147164410Ssyrinx val->v.uint32 = bp->in_drops; 1148164410Ssyrinx break; 1149164410Ssyrinx } 1150164410Ssyrinx 1151164410Ssyrinx return (SNMP_ERR_NOERROR); 1152164410Ssyrinx} 1153