1164410Ssyrinx/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 4164410Ssyrinx * Copyright (c) 2006 Shteryana Shopova <syrinx@FreeBSD.org> 5164410Ssyrinx * All rights reserved. 6164410Ssyrinx * 7164410Ssyrinx * Redistribution and use in source and binary forms, with or without 8164410Ssyrinx * modification, are permitted provided that the following conditions 9164410Ssyrinx * are met: 10164410Ssyrinx * 1. Redistributions of source code must retain the above copyright 11164410Ssyrinx * notice, this list of conditions and the following disclaimer. 12164410Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright 13164410Ssyrinx * notice, this list of conditions and the following disclaimer in the 14164410Ssyrinx * documentation and/or other materials provided with the distribution. 15164410Ssyrinx * 16164410Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17164410Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18164410Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19164410Ssyrinx * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20164410Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21164410Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22164410Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23164410Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24164410Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25164410Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26164410Ssyrinx * SUCH DAMAGE. 27164410Ssyrinx * 28164410Ssyrinx * Bridge MIB implementation for SNMPd. 29164410Ssyrinx * Bridge interface objects. 30164410Ssyrinx * 31164410Ssyrinx * $FreeBSD: stable/11/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c 330449 2018-03-05 07:26:05Z eadler $ 32164410Ssyrinx */ 33164410Ssyrinx 34164410Ssyrinx#include <sys/queue.h> 35164410Ssyrinx#include <sys/socket.h> 36164410Ssyrinx#include <sys/time.h> 37164410Ssyrinx#include <sys/types.h> 38164410Ssyrinx 39164410Ssyrinx#include <net/ethernet.h> 40164410Ssyrinx#include <net/if.h> 41164410Ssyrinx#include <net/if_mib.h> 42164410Ssyrinx#include <net/if_types.h> 43164410Ssyrinx 44164410Ssyrinx#include <errno.h> 45164410Ssyrinx#include <stdarg.h> 46164410Ssyrinx#include <stdlib.h> 47164410Ssyrinx#include <string.h> 48164410Ssyrinx#include <syslog.h> 49164410Ssyrinx 50164410Ssyrinx#include <bsnmp/snmpmod.h> 51164410Ssyrinx#include <bsnmp/snmp_mibII.h> 52164410Ssyrinx 53164410Ssyrinx#include "bridge_tree.h" 54164410Ssyrinx#include "bridge_snmp.h" 55164410Ssyrinx#include "bridge_oid.h" 56164410Ssyrinx 57164410Ssyrinxstatic const struct asn_oid oid_newRoot = OIDX_newRoot; 58164410Ssyrinxstatic const struct asn_oid oid_TopologyChange = OIDX_topologyChange; 59164410Ssyrinxstatic const struct asn_oid oid_begemotBrigeName = \ 60164410Ssyrinx OIDX_begemotBridgeBaseName; 61164410Ssyrinxstatic const struct asn_oid oid_begemotNewRoot = OIDX_begemotBridgeNewRoot; 62164410Ssyrinxstatic const struct asn_oid oid_begemotTopologyChange = \ 63164410Ssyrinx OIDX_begemotBridgeTopologyChange; 64164410Ssyrinx 65164410SsyrinxTAILQ_HEAD(bridge_ifs, bridge_if); 66164410Ssyrinx 67164410Ssyrinx/* 68164410Ssyrinx * Free the bridge interface list. 69164410Ssyrinx */ 70164410Ssyrinxstatic void 71164410Ssyrinxbridge_ifs_free(struct bridge_ifs *headp) 72164410Ssyrinx{ 73164410Ssyrinx struct bridge_if *b; 74164410Ssyrinx 75164410Ssyrinx while ((b = TAILQ_FIRST(headp)) != NULL) { 76164410Ssyrinx TAILQ_REMOVE(headp, b, b_if); 77164410Ssyrinx free(b); 78164410Ssyrinx } 79164410Ssyrinx} 80164410Ssyrinx 81164410Ssyrinx/* 82164410Ssyrinx * Insert an entry in the bridge interface TAILQ. Keep the 83164410Ssyrinx * TAILQ sorted by the bridge's interface name. 84164410Ssyrinx */ 85164410Ssyrinxstatic void 86164410Ssyrinxbridge_ifs_insert(struct bridge_ifs *headp, 87164410Ssyrinx struct bridge_if *b) 88164410Ssyrinx{ 89164410Ssyrinx struct bridge_if *temp; 90164410Ssyrinx 91164410Ssyrinx if ((temp = TAILQ_FIRST(headp)) == NULL || 92164410Ssyrinx strcmp(b->bif_name, temp->bif_name) < 0) { 93164410Ssyrinx TAILQ_INSERT_HEAD(headp, b, b_if); 94164410Ssyrinx return; 95164410Ssyrinx } 96164410Ssyrinx 97164410Ssyrinx TAILQ_FOREACH(temp, headp, b_if) 98164410Ssyrinx if(strcmp(b->bif_name, temp->bif_name) < 0) 99164410Ssyrinx TAILQ_INSERT_BEFORE(temp, b, b_if); 100164410Ssyrinx 101164410Ssyrinx TAILQ_INSERT_TAIL(headp, b, b_if); 102164410Ssyrinx} 103164410Ssyrinx 104164410Ssyrinx/* The global bridge interface list. */ 105164410Ssyrinxstatic struct bridge_ifs bridge_ifs = TAILQ_HEAD_INITIALIZER(bridge_ifs); 106164410Ssyrinxstatic time_t bridge_list_age; 107164410Ssyrinx 108164410Ssyrinx/* 109164410Ssyrinx * Free the global list. 110164410Ssyrinx */ 111164410Ssyrinxvoid 112164410Ssyrinxbridge_ifs_fini(void) 113164410Ssyrinx{ 114164410Ssyrinx bridge_ifs_free(&bridge_ifs); 115164410Ssyrinx} 116164410Ssyrinx 117164410Ssyrinx/* 118164410Ssyrinx * Find a bridge interface entry by the bridge interface system index. 119164410Ssyrinx */ 120164410Ssyrinxstruct bridge_if * 121164410Ssyrinxbridge_if_find_ifs(uint32_t sysindex) 122164410Ssyrinx{ 123164410Ssyrinx struct bridge_if *b; 124164410Ssyrinx 125164410Ssyrinx TAILQ_FOREACH(b, &bridge_ifs, b_if) 126164410Ssyrinx if (b->sysindex == sysindex) 127164410Ssyrinx return (b); 128164410Ssyrinx 129164410Ssyrinx return (NULL); 130164410Ssyrinx} 131164410Ssyrinx 132164410Ssyrinx/* 133164410Ssyrinx * Find a bridge interface entry by the bridge interface name. 134164410Ssyrinx */ 135164410Ssyrinxstruct bridge_if * 136164410Ssyrinxbridge_if_find_ifname(const char *b_name) 137164410Ssyrinx{ 138164410Ssyrinx struct bridge_if *b; 139164410Ssyrinx 140164410Ssyrinx TAILQ_FOREACH(b, &bridge_ifs, b_if) 141164410Ssyrinx if (strcmp(b_name, b->bif_name) == 0) 142164410Ssyrinx return (b); 143164410Ssyrinx 144164410Ssyrinx return (NULL); 145164410Ssyrinx} 146164410Ssyrinx 147164410Ssyrinx/* 148164410Ssyrinx * Find a bridge name by the bridge interface system index. 149164410Ssyrinx */ 150164410Ssyrinxconst char * 151164410Ssyrinxbridge_if_find_name(uint32_t sysindex) 152164410Ssyrinx{ 153164410Ssyrinx struct bridge_if *b; 154164410Ssyrinx 155164410Ssyrinx TAILQ_FOREACH(b, &bridge_ifs, b_if) 156164410Ssyrinx if (b->sysindex == sysindex) 157164410Ssyrinx return (b->bif_name); 158164410Ssyrinx 159164410Ssyrinx return (NULL); 160164410Ssyrinx} 161164410Ssyrinx 162164410Ssyrinx/* 163164410Ssyrinx * Given two bridge interfaces' system indexes, find their 164164410Ssyrinx * corresponding names and return the result of the name 165164410Ssyrinx * comparison. Returns: 166164410Ssyrinx * error : -2 167164410Ssyrinx * i1 < i2 : -1 168164410Ssyrinx * i1 > i2 : +1 169164410Ssyrinx * i1 = i2 : 0 170164410Ssyrinx */ 171164410Ssyrinxint 172164410Ssyrinxbridge_compare_sysidx(uint32_t i1, uint32_t i2) 173164410Ssyrinx{ 174164410Ssyrinx int c; 175164410Ssyrinx const char *b1, *b2; 176164410Ssyrinx 177164410Ssyrinx if (i1 == i2) 178164410Ssyrinx return (0); 179164410Ssyrinx 180164410Ssyrinx if ((b1 = bridge_if_find_name(i1)) == NULL) { 181164410Ssyrinx syslog(LOG_ERR, "Bridge interface %d does not exist", i1); 182164410Ssyrinx return (-2); 183164410Ssyrinx } 184164410Ssyrinx 185164410Ssyrinx if ((b2 = bridge_if_find_name(i2)) == NULL) { 186164410Ssyrinx syslog(LOG_ERR, "Bridge interface %d does not exist", i2); 187164410Ssyrinx return (-2); 188164410Ssyrinx } 189164410Ssyrinx 190164410Ssyrinx if ((c = strcmp(b1, b2)) < 0) 191164410Ssyrinx return (-1); 192164410Ssyrinx else if (c > 0) 193164410Ssyrinx return (1); 194164410Ssyrinx 195164410Ssyrinx return (0); 196164410Ssyrinx} 197164410Ssyrinx 198164410Ssyrinx/* 199164410Ssyrinx * Fetch the first bridge interface from the list. 200164410Ssyrinx */ 201164410Ssyrinxstruct bridge_if * 202164410Ssyrinxbridge_first_bif(void) 203164410Ssyrinx{ 204164410Ssyrinx return (TAILQ_FIRST(&bridge_ifs)); 205164410Ssyrinx} 206164410Ssyrinx 207164410Ssyrinx/* 208164410Ssyrinx * Fetch the next bridge interface from the list. 209164410Ssyrinx */ 210164410Ssyrinxstruct bridge_if * 211164410Ssyrinxbridge_next_bif(struct bridge_if *b_pr) 212164410Ssyrinx{ 213164410Ssyrinx return (TAILQ_NEXT(b_pr, b_if)); 214164410Ssyrinx} 215164410Ssyrinx 216164410Ssyrinx/* 217164410Ssyrinx * Create a new entry for a bridge interface and insert 218164410Ssyrinx * it in the list. 219164410Ssyrinx */ 220164410Ssyrinxstatic struct bridge_if * 221164410Ssyrinxbridge_new_bif(const char *bif_n, uint32_t sysindex, const u_char *physaddr) 222164410Ssyrinx{ 223164410Ssyrinx struct bridge_if *bif; 224164410Ssyrinx 225164410Ssyrinx if ((bif = (struct bridge_if *) malloc(sizeof(*bif)))== NULL) { 226164410Ssyrinx syslog(LOG_ERR, "bridge new interface failed: %s", 227164410Ssyrinx strerror(errno)); 228164410Ssyrinx return (NULL); 229164410Ssyrinx } 230164410Ssyrinx 231164410Ssyrinx bzero(bif, sizeof(struct bridge_if)); 232164410Ssyrinx strlcpy(bif->bif_name, bif_n, IFNAMSIZ); 233164410Ssyrinx bcopy(physaddr, bif->br_addr.octet, ETHER_ADDR_LEN); 234164410Ssyrinx bif->sysindex = sysindex; 235164410Ssyrinx bif->br_type = BaseType_transparent_only; 236164410Ssyrinx /* 1 - all bridges default hold time * 100 - centi-seconds */ 237164410Ssyrinx bif->hold_time = 1 * 100; 238164410Ssyrinx bif->prot_spec = dot1dStpProtocolSpecification_ieee8021d; 239164410Ssyrinx bridge_ifs_insert(&bridge_ifs, bif); 240164410Ssyrinx 241164410Ssyrinx return (bif); 242164410Ssyrinx} 243164410Ssyrinx 244164410Ssyrinx/* 245164410Ssyrinx * Remove a bridge interface from the list, freeing all it's ports 246164410Ssyrinx * and address entries. 247164410Ssyrinx */ 248164410Ssyrinxvoid 249164410Ssyrinxbridge_remove_bif(struct bridge_if *bif) 250164410Ssyrinx{ 251164410Ssyrinx bridge_members_free(bif); 252164410Ssyrinx bridge_addrs_free(bif); 253164410Ssyrinx TAILQ_REMOVE(&bridge_ifs, bif, b_if); 254164410Ssyrinx free(bif); 255164410Ssyrinx} 256164410Ssyrinx 257164410Ssyrinx 258164410Ssyrinx/* 259164410Ssyrinx * Prepare the variable (bridge interface name) for the private 260164410Ssyrinx * begemot notifications. 261164410Ssyrinx */ 262164410Ssyrinxstatic struct snmp_value* 263164410Ssyrinxbridge_basename_var(struct bridge_if *bif, struct snmp_value* b_val) 264164410Ssyrinx{ 265164410Ssyrinx uint i; 266164410Ssyrinx 267164410Ssyrinx b_val->var = oid_begemotBrigeName; 268164410Ssyrinx b_val->var.subs[b_val->var.len++] = strlen(bif->bif_name); 269164410Ssyrinx 270164410Ssyrinx if ((b_val->v.octetstring.octets = (u_char *) 271164410Ssyrinx malloc(strlen(bif->bif_name))) == NULL) 272164410Ssyrinx return (NULL); 273164410Ssyrinx 274164410Ssyrinx for (i = 0; i < strlen(bif->bif_name); i++) 275164410Ssyrinx b_val->var.subs[b_val->var.len++] = bif->bif_name[i]; 276164410Ssyrinx 277164410Ssyrinx b_val->v.octetstring.len = strlen(bif->bif_name); 278164410Ssyrinx bcopy(bif->bif_name, b_val->v.octetstring.octets, 279164410Ssyrinx strlen(bif->bif_name)); 280164410Ssyrinx b_val->syntax = SNMP_SYNTAX_OCTETSTRING; 281164410Ssyrinx 282164410Ssyrinx return (b_val); 283164410Ssyrinx} 284164410Ssyrinx 285164410Ssyrinx/* 286164410Ssyrinx * Compare the values of the old and the new root port and 287164410Ssyrinx * send a new root notification, if they are not matching. 288164410Ssyrinx */ 289164410Ssyrinxstatic void 290164410Ssyrinxbridge_new_root(struct bridge_if *bif) 291164410Ssyrinx{ 292164410Ssyrinx struct snmp_value bif_idx; 293164410Ssyrinx 294164410Ssyrinx if (bridge_get_default() == bif) 295164410Ssyrinx snmp_send_trap(&oid_newRoot, (struct snmp_value *) NULL); 296164410Ssyrinx 297164410Ssyrinx if (bridge_basename_var(bif, &bif_idx) == NULL) 298164410Ssyrinx return; 299164410Ssyrinx 300164410Ssyrinx snmp_send_trap(&oid_begemotTopologyChange, 301164410Ssyrinx &bif_idx, (struct snmp_value *) NULL); 302164410Ssyrinx} 303164410Ssyrinx 304164410Ssyrinx/* 305164410Ssyrinx * Compare the new and old topology change times and send a 306164410Ssyrinx * topology change notification if necessary. 307164410Ssyrinx */ 308164410Ssyrinxstatic void 309164410Ssyrinxbridge_top_change(struct bridge_if *bif) 310164410Ssyrinx{ 311164410Ssyrinx struct snmp_value bif_idx; 312164410Ssyrinx 313164410Ssyrinx if (bridge_get_default() == bif) 314164410Ssyrinx snmp_send_trap(&oid_TopologyChange, 315164410Ssyrinx (struct snmp_value *) NULL); 316164410Ssyrinx 317164410Ssyrinx if (bridge_basename_var(bif, &bif_idx) == NULL) 318164410Ssyrinx return; 319164410Ssyrinx 320164410Ssyrinx snmp_send_trap(&oid_begemotNewRoot, 321164410Ssyrinx &bif_idx, (struct snmp_value *) NULL); 322164410Ssyrinx} 323164410Ssyrinx 324164410Ssyrinxstatic int 325164410Ssyrinxbridge_if_create(const char* b_name, int8_t up) 326164410Ssyrinx{ 327164410Ssyrinx if (bridge_create(b_name) < 0) 328164410Ssyrinx return (-1); 329164410Ssyrinx 330164410Ssyrinx if (up == 1 && (bridge_set_if_up(b_name, 1) < 0)) 331164410Ssyrinx return (-1); 332164410Ssyrinx 333164410Ssyrinx /* 334164410Ssyrinx * Do not create a new bridge entry here - 335164410Ssyrinx * wait until the mibII module notifies us. 336164410Ssyrinx */ 337164410Ssyrinx return (0); 338164410Ssyrinx} 339164410Ssyrinx 340164410Ssyrinxstatic int 341164410Ssyrinxbridge_if_destroy(struct bridge_if *bif) 342164410Ssyrinx{ 343164410Ssyrinx if (bridge_destroy(bif->bif_name) < 0) 344164410Ssyrinx return (-1); 345164410Ssyrinx 346164410Ssyrinx bridge_remove_bif(bif); 347164410Ssyrinx 348164410Ssyrinx return (0); 349164410Ssyrinx} 350164410Ssyrinx 351164410Ssyrinx/* 352164410Ssyrinx * Calculate the timeticks since the last topology change. 353164410Ssyrinx */ 354164410Ssyrinxstatic int 355164410Ssyrinxbridge_get_time_since_tc(struct bridge_if *bif, uint32_t *ticks) 356164410Ssyrinx{ 357164410Ssyrinx struct timeval ct; 358164410Ssyrinx 359164410Ssyrinx if (gettimeofday(&ct, NULL) < 0) { 360164410Ssyrinx syslog(LOG_ERR, "bridge get time since last TC:" 361164410Ssyrinx "getttimeofday failed: %s", strerror(errno)); 362164410Ssyrinx return (-1); 363164410Ssyrinx } 364164410Ssyrinx 365164410Ssyrinx if (ct.tv_usec - bif->last_tc_time.tv_usec < 0) { 366164410Ssyrinx ct.tv_sec -= 1; 367164410Ssyrinx ct.tv_usec += 1000000; 368164410Ssyrinx } 369164410Ssyrinx 370164410Ssyrinx ct.tv_sec -= bif->last_tc_time.tv_sec; 371164410Ssyrinx ct.tv_usec -= bif->last_tc_time.tv_usec; 372164410Ssyrinx 373164410Ssyrinx *ticks = ct.tv_sec * 100 + ct.tv_usec/10000; 374164410Ssyrinx 375164410Ssyrinx return (0); 376164410Ssyrinx} 377164410Ssyrinx 378164410Ssyrinx/* 379164410Ssyrinx * Update the info we have for a single bridge interface. 380164410Ssyrinx * Return: 381164410Ssyrinx * 1, if successful 382164410Ssyrinx * 0, if the interface was deleted 383228990Suqs * -1, error occurred while fetching the info from the kernel. 384164410Ssyrinx */ 385164410Ssyrinxstatic int 386164410Ssyrinxbridge_update_bif(struct bridge_if *bif) 387164410Ssyrinx{ 388164410Ssyrinx struct mibif *ifp; 389164410Ssyrinx 390164410Ssyrinx /* Walk through the mibII interface list. */ 391164410Ssyrinx for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) 392164410Ssyrinx if (strcmp(ifp->name, bif->bif_name) == 0) 393164410Ssyrinx break; 394164410Ssyrinx 395164410Ssyrinx if (ifp == NULL) { 396164410Ssyrinx /* Ops, we do not exist anymore. */ 397164410Ssyrinx bridge_remove_bif(bif); 398164410Ssyrinx return (0); 399164410Ssyrinx } 400164410Ssyrinx 401164410Ssyrinx if (ifp->physaddr != NULL ) 402164410Ssyrinx bcopy(ifp->physaddr, bif->br_addr.octet, ETHER_ADDR_LEN); 403164410Ssyrinx else 404165642Sbz bridge_get_basemac(bif->bif_name, bif->br_addr.octet, 405165642Sbz ETHER_ADDR_LEN); 406164410Ssyrinx 407164410Ssyrinx if (ifp->mib.ifmd_flags & IFF_RUNNING) 408164410Ssyrinx bif->if_status = RowStatus_active; 409164410Ssyrinx else 410164410Ssyrinx bif->if_status = RowStatus_notInService; 411164410Ssyrinx 412164410Ssyrinx switch (bridge_getinfo_bif(bif)) { 413164410Ssyrinx case 2: 414164410Ssyrinx bridge_new_root(bif); 415164410Ssyrinx break; 416164410Ssyrinx case 1: 417164410Ssyrinx bridge_top_change(bif); 418164410Ssyrinx break; 419164410Ssyrinx case -1: 420164410Ssyrinx bridge_remove_bif(bif); 421164410Ssyrinx return (-1); 422164410Ssyrinx default: 423164410Ssyrinx break; 424164410Ssyrinx } 425164410Ssyrinx 426164410Ssyrinx /* 427164410Ssyrinx * The number of ports is accessible via SNMP - 428164410Ssyrinx * update the ports each time the bridge interface data 429164410Ssyrinx * is refreshed too. 430164410Ssyrinx */ 431164410Ssyrinx bif->num_ports = bridge_update_memif(bif); 432164410Ssyrinx bif->entry_age = time(NULL); 433164410Ssyrinx 434164410Ssyrinx return (1); 435164410Ssyrinx} 436164410Ssyrinx 437164410Ssyrinx/* 438310901Sngie * Update all bridge interfaces' ports only - 439164410Ssyrinx * make sure each bridge interface exists first. 440164410Ssyrinx */ 441164410Ssyrinxvoid 442164410Ssyrinxbridge_update_all_ports(void) 443164410Ssyrinx{ 444164410Ssyrinx struct mibif *ifp; 445164410Ssyrinx struct bridge_if *bif, *t_bif; 446164410Ssyrinx 447164410Ssyrinx for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 448164410Ssyrinx t_bif = bridge_next_bif(bif); 449164410Ssyrinx 450164410Ssyrinx for (ifp = mib_first_if(); ifp != NULL; 451164410Ssyrinx ifp = mib_next_if(ifp)) 452164410Ssyrinx if (strcmp(ifp->name, bif->bif_name) == 0) 453164410Ssyrinx break; 454164410Ssyrinx 455164410Ssyrinx if (ifp != NULL) 456164410Ssyrinx bif->num_ports = bridge_update_memif(bif); 457164410Ssyrinx else /* Ops, we do not exist anymore. */ 458164410Ssyrinx bridge_remove_bif(bif); 459164410Ssyrinx } 460164410Ssyrinx 461164410Ssyrinx bridge_ports_update_listage(); 462164410Ssyrinx} 463164410Ssyrinx 464164410Ssyrinx/* 465164410Ssyrinx * Update all addresses only. 466164410Ssyrinx */ 467164410Ssyrinxvoid 468164410Ssyrinxbridge_update_all_addrs(void) 469164410Ssyrinx{ 470164410Ssyrinx struct mibif *ifp; 471164410Ssyrinx struct bridge_if *bif, *t_bif; 472164410Ssyrinx 473164410Ssyrinx for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 474164410Ssyrinx t_bif = bridge_next_bif(bif); 475164410Ssyrinx 476164410Ssyrinx for (ifp = mib_first_if(); ifp != NULL; 477164410Ssyrinx ifp = mib_next_if(ifp)) 478164410Ssyrinx if (strcmp(ifp->name, bif->bif_name) == 0) 479164410Ssyrinx break; 480164410Ssyrinx 481164410Ssyrinx if (ifp != NULL) 482164410Ssyrinx bif->num_addrs = bridge_update_addrs(bif); 483164410Ssyrinx else /* Ops, we don't exist anymore. */ 484164410Ssyrinx bridge_remove_bif(bif); 485164410Ssyrinx } 486164410Ssyrinx 487164410Ssyrinx bridge_addrs_update_listage(); 488164410Ssyrinx} 489164410Ssyrinx 490164410Ssyrinx/* 491164410Ssyrinx * Update only the bridge interfaces' data - skip addresses. 492164410Ssyrinx */ 493164410Ssyrinxvoid 494164410Ssyrinxbridge_update_all_ifs(void) 495164410Ssyrinx{ 496164410Ssyrinx struct bridge_if *bif, *t_bif; 497164410Ssyrinx 498164410Ssyrinx for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 499164410Ssyrinx t_bif = bridge_next_bif(bif); 500164410Ssyrinx bridge_update_bif(bif); 501164410Ssyrinx } 502164410Ssyrinx 503164410Ssyrinx bridge_ports_update_listage(); 504164410Ssyrinx bridge_list_age = time(NULL); 505164410Ssyrinx} 506164410Ssyrinx 507164410Ssyrinx/* 508164410Ssyrinx * Update all info we have for all bridges. 509164410Ssyrinx */ 510164410Ssyrinxvoid 511164410Ssyrinxbridge_update_all(void *arg __unused) 512164410Ssyrinx{ 513164410Ssyrinx struct bridge_if *bif, *t_bif; 514164410Ssyrinx 515164410Ssyrinx for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 516164410Ssyrinx t_bif = bridge_next_bif(bif); 517164410Ssyrinx if (bridge_update_bif(bif) <= 0) 518164410Ssyrinx continue; 519164410Ssyrinx 520164410Ssyrinx /* Update our learnt addresses. */ 521164410Ssyrinx bif->num_addrs = bridge_update_addrs(bif); 522164410Ssyrinx } 523164410Ssyrinx 524164410Ssyrinx bridge_list_age = time(NULL); 525164410Ssyrinx bridge_ports_update_listage(); 526164410Ssyrinx bridge_addrs_update_listage(); 527164410Ssyrinx} 528164410Ssyrinx 529164410Ssyrinx/* 530164410Ssyrinx * Callback for polling our last topology change time - 531164410Ssyrinx * check whether we are root or whether a TC was detected once every 532164410Ssyrinx * 30 seconds, so that we can send the newRoot and TopologyChange traps 533164410Ssyrinx * on time. The rest of the data is polled only once every 5 min. 534164410Ssyrinx */ 535164410Ssyrinxvoid 536164410Ssyrinxbridge_update_tc_time(void *arg __unused) 537164410Ssyrinx{ 538164410Ssyrinx struct bridge_if *bif; 539164410Ssyrinx struct mibif *ifp; 540164410Ssyrinx 541164410Ssyrinx TAILQ_FOREACH(bif, &bridge_ifs, b_if) { 542164410Ssyrinx /* Walk through the mibII interface list. */ 543164410Ssyrinx for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) 544164410Ssyrinx if (strcmp(ifp->name, bif->bif_name) == 0) 545164410Ssyrinx break; 546164410Ssyrinx 547164410Ssyrinx if (ifp == NULL) { 548164410Ssyrinx bridge_remove_bif(bif); 549164410Ssyrinx continue; 550164410Ssyrinx } 551164410Ssyrinx 552164410Ssyrinx switch (bridge_get_op_param(bif)) { 553164410Ssyrinx case 2: 554164410Ssyrinx bridge_new_root(bif); 555164410Ssyrinx break; 556164410Ssyrinx case 1: 557164410Ssyrinx bridge_top_change(bif); 558164410Ssyrinx break; 559164410Ssyrinx } 560164410Ssyrinx } 561164410Ssyrinx} 562164410Ssyrinx 563164410Ssyrinx/* 564164410Ssyrinx * Callback for handling new bridge interface creation. 565164410Ssyrinx */ 566164410Ssyrinxint 567164410Ssyrinxbridge_attach_newif(struct mibif *ifp) 568164410Ssyrinx{ 569165642Sbz u_char mac[ETHER_ADDR_LEN]; 570164410Ssyrinx struct bridge_if *bif; 571164410Ssyrinx 572164410Ssyrinx if (ifp->mib.ifmd_data.ifi_type != IFT_BRIDGE) 573164410Ssyrinx return (0); 574164410Ssyrinx 575164410Ssyrinx /* Make sure it does not exist in our list. */ 576164410Ssyrinx TAILQ_FOREACH(bif, &bridge_ifs, b_if) 577164410Ssyrinx if(strcmp(bif->bif_name, ifp->name) == 0) { 578164410Ssyrinx syslog(LOG_ERR, "bridge interface %s already " 579164410Ssyrinx "in list", bif->bif_name); 580164410Ssyrinx return (-1); 581164410Ssyrinx } 582164410Ssyrinx 583165642Sbz if (ifp->physaddr == NULL) { 584165642Sbz if (bridge_get_basemac(ifp->name, mac, sizeof(mac)) == NULL) { 585165642Sbz syslog(LOG_ERR, "bridge attach new %s failed - " 586165642Sbz "no bridge mac address", ifp->name); 587165642Sbz return (-1); 588165642Sbz } 589165642Sbz } else 590165642Sbz bcopy(ifp->physaddr, &mac, sizeof(mac)); 591164410Ssyrinx 592165642Sbz if ((bif = bridge_new_bif(ifp->name, ifp->sysindex, mac)) == NULL) 593164410Ssyrinx return (-1); 594164410Ssyrinx 595164410Ssyrinx if (ifp->mib.ifmd_flags & IFF_RUNNING) 596164410Ssyrinx bif->if_status = RowStatus_active; 597164410Ssyrinx else 598164410Ssyrinx bif->if_status = RowStatus_notInService; 599164410Ssyrinx 600164410Ssyrinx /* Skip sending notifications if the interface was just created. */ 601164410Ssyrinx if (bridge_getinfo_bif(bif) < 0 || 602164410Ssyrinx (bif->num_ports = bridge_getinfo_bif_ports(bif)) < 0 || 603164410Ssyrinx (bif->num_addrs = bridge_getinfo_bif_addrs(bif)) < 0) { 604164410Ssyrinx bridge_remove_bif(bif); 605164410Ssyrinx return (-1); 606164410Ssyrinx } 607164410Ssyrinx 608164410Ssyrinx /* Check whether we are the default bridge interface. */ 609164410Ssyrinx if (strcmp(ifp->name, bridge_get_default_name()) == 0) 610164410Ssyrinx bridge_set_default(bif); 611164410Ssyrinx 612164410Ssyrinx return (0); 613164410Ssyrinx} 614164410Ssyrinx 615164410Ssyrinxvoid 616164410Ssyrinxbridge_ifs_dump(void) 617164410Ssyrinx{ 618164410Ssyrinx struct bridge_if *bif; 619164410Ssyrinx 620164410Ssyrinx for (bif = bridge_first_bif(); bif != NULL; 621164410Ssyrinx bif = bridge_next_bif(bif)) { 622164410Ssyrinx syslog(LOG_ERR, "Bridge %s, index - %d", bif->bif_name, 623164410Ssyrinx bif->sysindex); 624164410Ssyrinx bridge_ports_dump(bif); 625164410Ssyrinx bridge_addrs_dump(bif); 626164410Ssyrinx } 627164410Ssyrinx} 628164410Ssyrinx 629164410Ssyrinx/* 630164410Ssyrinx * RFC4188 specifics. 631164410Ssyrinx */ 632164410Ssyrinxint 633164410Ssyrinxop_dot1d_base(struct snmp_context *ctx __unused, struct snmp_value *value, 634164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 635164410Ssyrinx{ 636164410Ssyrinx struct bridge_if *bif; 637164410Ssyrinx 638164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 639164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 640164410Ssyrinx 641164410Ssyrinx if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 642164410Ssyrinx bridge_update_bif(bif) <= 0) /* It was just deleted. */ 643164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 644164410Ssyrinx 645164410Ssyrinx switch (op) { 646164410Ssyrinx case SNMP_OP_GET: 647164410Ssyrinx switch (value->var.subs[sub - 1]) { 648164410Ssyrinx case LEAF_dot1dBaseBridgeAddress: 649165253Ssyrinx return (string_get(value, bif->br_addr.octet, 650165253Ssyrinx ETHER_ADDR_LEN)); 651164410Ssyrinx case LEAF_dot1dBaseNumPorts: 652164410Ssyrinx value->v.integer = bif->num_ports; 653165253Ssyrinx return (SNMP_ERR_NOERROR); 654164410Ssyrinx case LEAF_dot1dBaseType: 655164410Ssyrinx value->v.integer = bif->br_type; 656165253Ssyrinx return (SNMP_ERR_NOERROR); 657164410Ssyrinx } 658165253Ssyrinx abort(); 659164410Ssyrinx 660164410Ssyrinx case SNMP_OP_SET: 661165253Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 662164410Ssyrinx 663164410Ssyrinx case SNMP_OP_GETNEXT: 664164410Ssyrinx case SNMP_OP_ROLLBACK: 665164410Ssyrinx case SNMP_OP_COMMIT: 666165253Ssyrinx break; 667164410Ssyrinx } 668164410Ssyrinx 669165253Ssyrinx abort(); 670164410Ssyrinx} 671164410Ssyrinx 672164410Ssyrinxint 673165253Ssyrinxop_dot1d_stp(struct snmp_context *ctx, struct snmp_value *val, uint sub, 674165253Ssyrinx uint iidx __unused, enum snmp_op op) 675164410Ssyrinx{ 676164410Ssyrinx struct bridge_if *bif; 677164410Ssyrinx 678164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 679164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 680164410Ssyrinx 681164410Ssyrinx if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 682164410Ssyrinx bridge_update_bif(bif) <= 0) /* It was just deleted. */ 683164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 684164410Ssyrinx 685164410Ssyrinx switch (op) { 686164410Ssyrinx case SNMP_OP_GET: 687165253Ssyrinx switch (val->var.subs[sub - 1]) { 688164410Ssyrinx case LEAF_dot1dStpProtocolSpecification: 689165253Ssyrinx val->v.integer = bif->prot_spec; 690165253Ssyrinx return (SNMP_ERR_NOERROR); 691164410Ssyrinx 692164410Ssyrinx case LEAF_dot1dStpPriority: 693165253Ssyrinx val->v.integer = bif->priority; 694165253Ssyrinx return (SNMP_ERR_NOERROR); 695164410Ssyrinx 696164410Ssyrinx case LEAF_dot1dStpTimeSinceTopologyChange: 697164410Ssyrinx if (bridge_get_time_since_tc(bif, 698165253Ssyrinx &(val->v.uint32)) < 0) 699164410Ssyrinx return (SNMP_ERR_GENERR); 700165253Ssyrinx return (SNMP_ERR_NOERROR); 701164410Ssyrinx 702164410Ssyrinx case LEAF_dot1dStpTopChanges: 703165253Ssyrinx val->v.uint32 = bif->top_changes; 704165253Ssyrinx return (SNMP_ERR_NOERROR); 705164410Ssyrinx 706164410Ssyrinx case LEAF_dot1dStpDesignatedRoot: 707165253Ssyrinx return (string_get(val, bif->design_root, 708164410Ssyrinx SNMP_BRIDGE_ID_LEN)); 709164410Ssyrinx 710164410Ssyrinx case LEAF_dot1dStpRootCost: 711165253Ssyrinx val->v.integer = bif->root_cost; 712165253Ssyrinx return (SNMP_ERR_NOERROR); 713164410Ssyrinx 714164410Ssyrinx case LEAF_dot1dStpRootPort: 715165253Ssyrinx val->v.integer = bif->root_port; 716165253Ssyrinx return (SNMP_ERR_NOERROR); 717164410Ssyrinx 718164410Ssyrinx case LEAF_dot1dStpMaxAge: 719165253Ssyrinx val->v.integer = bif->max_age; 720165253Ssyrinx return (SNMP_ERR_NOERROR); 721164410Ssyrinx 722164410Ssyrinx case LEAF_dot1dStpHelloTime: 723165253Ssyrinx val->v.integer = bif->hello_time; 724165253Ssyrinx return (SNMP_ERR_NOERROR); 725164410Ssyrinx 726164410Ssyrinx case LEAF_dot1dStpHoldTime: 727165253Ssyrinx val->v.integer = bif->hold_time; 728165253Ssyrinx return (SNMP_ERR_NOERROR); 729164410Ssyrinx 730164410Ssyrinx case LEAF_dot1dStpForwardDelay: 731165253Ssyrinx val->v.integer = bif->fwd_delay; 732165253Ssyrinx return (SNMP_ERR_NOERROR); 733164410Ssyrinx 734164410Ssyrinx case LEAF_dot1dStpBridgeMaxAge: 735165253Ssyrinx val->v.integer = bif->bridge_max_age; 736165253Ssyrinx return (SNMP_ERR_NOERROR); 737164410Ssyrinx 738164410Ssyrinx case LEAF_dot1dStpBridgeHelloTime: 739165253Ssyrinx val->v.integer = bif->bridge_hello_time; 740165253Ssyrinx return (SNMP_ERR_NOERROR); 741164410Ssyrinx 742164410Ssyrinx case LEAF_dot1dStpBridgeForwardDelay: 743165253Ssyrinx val->v.integer = bif->bridge_fwd_delay; 744165253Ssyrinx return (SNMP_ERR_NOERROR); 745165253Ssyrinx 746164997Ssyrinx case LEAF_dot1dStpVersion: 747165253Ssyrinx val->v.integer = bif->stp_version; 748165253Ssyrinx return (SNMP_ERR_NOERROR); 749165253Ssyrinx 750164997Ssyrinx case LEAF_dot1dStpTxHoldCount: 751165253Ssyrinx val->v.integer = bif->tx_hold_count; 752165253Ssyrinx return (SNMP_ERR_NOERROR); 753164410Ssyrinx } 754165253Ssyrinx abort(); 755164410Ssyrinx 756164410Ssyrinx case SNMP_OP_GETNEXT: 757164410Ssyrinx abort(); 758164410Ssyrinx 759164410Ssyrinx case SNMP_OP_SET: 760165253Ssyrinx switch (val->var.subs[sub - 1]) { 761164410Ssyrinx case LEAF_dot1dStpPriority: 762165253Ssyrinx if (val->v.integer > SNMP_BRIDGE_MAX_PRIORITY || 763165253Ssyrinx val->v.integer % 4096 != 0) 764165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 765165253Ssyrinx 766164410Ssyrinx ctx->scratch->int1 = bif->priority; 767165253Ssyrinx if (bridge_set_priority(bif, val->v.integer) < 0) 768165253Ssyrinx return (SNMP_ERR_GENERR); 769165253Ssyrinx return (SNMP_ERR_NOERROR); 770164410Ssyrinx 771164410Ssyrinx case LEAF_dot1dStpBridgeMaxAge: 772165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_MAGE || 773165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_MAGE) 774165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 775165253Ssyrinx 776164410Ssyrinx ctx->scratch->int1 = bif->bridge_max_age; 777165253Ssyrinx if (bridge_set_maxage(bif, val->v.integer) < 0) 778165253Ssyrinx return (SNMP_ERR_GENERR); 779165253Ssyrinx return (SNMP_ERR_NOERROR); 780164410Ssyrinx 781164410Ssyrinx case LEAF_dot1dStpBridgeHelloTime: 782165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_HTIME || 783165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_HTIME) 784165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 785165253Ssyrinx 786164410Ssyrinx ctx->scratch->int1 = bif->bridge_hello_time; 787165253Ssyrinx if (bridge_set_hello_time(bif, val->v.integer) < 0) 788165253Ssyrinx return (SNMP_ERR_GENERR); 789165253Ssyrinx return (SNMP_ERR_NOERROR); 790164410Ssyrinx 791164410Ssyrinx case LEAF_dot1dStpBridgeForwardDelay: 792165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_FDELAY || 793165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_FDELAY) 794165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 795165253Ssyrinx 796164410Ssyrinx ctx->scratch->int1 = bif->bridge_fwd_delay; 797165253Ssyrinx if (bridge_set_forward_delay(bif, val->v.integer) < 0) 798165253Ssyrinx return (SNMP_ERR_GENERR); 799165253Ssyrinx return (SNMP_ERR_NOERROR); 800164410Ssyrinx 801164997Ssyrinx case LEAF_dot1dStpVersion: 802165253Ssyrinx if (val->v.integer != dot1dStpVersion_stpCompatible && 803165253Ssyrinx val->v.integer != dot1dStpVersion_rstp) 804165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 805165253Ssyrinx 806164997Ssyrinx ctx->scratch->int1 = bif->stp_version; 807165253Ssyrinx if (bridge_set_stp_version(bif, val->v.integer) < 0) 808165253Ssyrinx return (SNMP_ERR_GENERR); 809165253Ssyrinx return (SNMP_ERR_NOERROR); 810164997Ssyrinx 811164997Ssyrinx case LEAF_dot1dStpTxHoldCount: 812165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_TXHC || 813165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_TXHC) 814165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 815165253Ssyrinx 816164997Ssyrinx ctx->scratch->int1 = bif->tx_hold_count; 817165253Ssyrinx if (bridge_set_tx_hold_count(bif, val->v.integer) < 0) 818165253Ssyrinx return (SNMP_ERR_GENERR); 819165253Ssyrinx return (SNMP_ERR_NOERROR); 820164997Ssyrinx 821164410Ssyrinx case LEAF_dot1dStpProtocolSpecification: 822164410Ssyrinx case LEAF_dot1dStpTimeSinceTopologyChange: 823164410Ssyrinx case LEAF_dot1dStpTopChanges: 824164410Ssyrinx case LEAF_dot1dStpDesignatedRoot: 825164410Ssyrinx case LEAF_dot1dStpRootCost: 826164410Ssyrinx case LEAF_dot1dStpRootPort: 827164410Ssyrinx case LEAF_dot1dStpMaxAge: 828164410Ssyrinx case LEAF_dot1dStpHelloTime: 829164410Ssyrinx case LEAF_dot1dStpHoldTime: 830164410Ssyrinx case LEAF_dot1dStpForwardDelay: 831164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 832164410Ssyrinx } 833165253Ssyrinx abort(); 834164410Ssyrinx 835164410Ssyrinx case SNMP_OP_ROLLBACK: 836165253Ssyrinx switch (val->var.subs[sub - 1]) { 837164410Ssyrinx case LEAF_dot1dStpPriority: 838164997Ssyrinx bridge_set_priority(bif, ctx->scratch->int1); 839164410Ssyrinx break; 840164410Ssyrinx case LEAF_dot1dStpBridgeMaxAge: 841164997Ssyrinx bridge_set_maxage(bif, ctx->scratch->int1); 842164410Ssyrinx break; 843164410Ssyrinx case LEAF_dot1dStpBridgeHelloTime: 844164997Ssyrinx bridge_set_hello_time(bif, ctx->scratch->int1); 845164410Ssyrinx break; 846164410Ssyrinx case LEAF_dot1dStpBridgeForwardDelay: 847164997Ssyrinx bridge_set_forward_delay(bif, ctx->scratch->int1); 848164410Ssyrinx break; 849164997Ssyrinx case LEAF_dot1dStpVersion: 850164997Ssyrinx bridge_set_stp_version(bif, ctx->scratch->int1); 851164997Ssyrinx break; 852164997Ssyrinx case LEAF_dot1dStpTxHoldCount: 853164997Ssyrinx bridge_set_tx_hold_count(bif, ctx->scratch->int1); 854164997Ssyrinx break; 855164410Ssyrinx } 856164410Ssyrinx return (SNMP_ERR_NOERROR); 857164410Ssyrinx 858164410Ssyrinx case SNMP_OP_COMMIT: 859164410Ssyrinx return (SNMP_ERR_NOERROR); 860164410Ssyrinx } 861164410Ssyrinx 862165253Ssyrinx abort(); 863164410Ssyrinx} 864164410Ssyrinx 865164410Ssyrinxint 866164410Ssyrinxop_dot1d_tp(struct snmp_context *ctx, struct snmp_value *value, 867164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 868164410Ssyrinx{ 869164410Ssyrinx struct bridge_if *bif; 870164410Ssyrinx 871164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 872164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 873164410Ssyrinx 874164410Ssyrinx if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 875164410Ssyrinx bridge_update_bif(bif) <= 0) /* It was just deleted. */ 876164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 877164410Ssyrinx 878164410Ssyrinx switch (op) { 879164410Ssyrinx case SNMP_OP_GET: 880164410Ssyrinx switch (value->var.subs[sub - 1]) { 881164410Ssyrinx case LEAF_dot1dTpLearnedEntryDiscards: 882164410Ssyrinx value->v.uint32 = bif->lrnt_drops; 883165253Ssyrinx return (SNMP_ERR_NOERROR); 884164410Ssyrinx case LEAF_dot1dTpAgingTime: 885164410Ssyrinx value->v.integer = bif->age_time; 886165253Ssyrinx return (SNMP_ERR_NOERROR); 887164410Ssyrinx } 888165253Ssyrinx abort(); 889164410Ssyrinx 890164410Ssyrinx case SNMP_OP_GETNEXT: 891164410Ssyrinx abort(); 892164410Ssyrinx 893164410Ssyrinx case SNMP_OP_SET: 894165253Ssyrinx switch (value->var.subs[sub - 1]) { 895165253Ssyrinx case LEAF_dot1dTpLearnedEntryDiscards: 896165253Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 897165253Ssyrinx 898165253Ssyrinx case LEAF_dot1dTpAgingTime: 899165253Ssyrinx if (value->v.integer < SNMP_BRIDGE_MIN_AGE_TIME || 900165253Ssyrinx value->v.integer > SNMP_BRIDGE_MAX_AGE_TIME) 901165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 902165253Ssyrinx 903165253Ssyrinx ctx->scratch->int1 = bif->age_time; 904165253Ssyrinx if (bridge_set_aging_time(bif, value->v.integer) < 0) 905165253Ssyrinx return (SNMP_ERR_GENERR); 906165253Ssyrinx return (SNMP_ERR_NOERROR); 907164410Ssyrinx } 908165253Ssyrinx abort(); 909164410Ssyrinx 910164410Ssyrinx case SNMP_OP_ROLLBACK: 911164410Ssyrinx if (value->var.subs[sub - 1] == LEAF_dot1dTpAgingTime) 912164997Ssyrinx bridge_set_aging_time(bif, ctx->scratch->int1); 913164410Ssyrinx return (SNMP_ERR_NOERROR); 914164410Ssyrinx 915164410Ssyrinx case SNMP_OP_COMMIT: 916164410Ssyrinx return (SNMP_ERR_NOERROR); 917164410Ssyrinx } 918164410Ssyrinx 919165253Ssyrinx abort(); 920164410Ssyrinx} 921164410Ssyrinx 922164410Ssyrinx/* 923164410Ssyrinx * Private BEGEMOT-BRIDGE-MIB specifics. 924164410Ssyrinx */ 925164410Ssyrinx 926164410Ssyrinx/* 927164410Ssyrinx * Get the bridge name from an OID index. 928164410Ssyrinx */ 929164410Ssyrinxstatic char * 930164410Ssyrinxbridge_name_index_get(const struct asn_oid *oid, uint sub, char *b_name) 931164410Ssyrinx{ 932164410Ssyrinx uint i; 933164410Ssyrinx 934164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 935164410Ssyrinx return (NULL); 936164410Ssyrinx 937164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 938164410Ssyrinx b_name[i] = oid->subs[sub + i + 1]; 939164410Ssyrinx b_name[i] = '\0'; 940164410Ssyrinx 941164410Ssyrinx return (b_name); 942164410Ssyrinx} 943164410Ssyrinx 944164410Ssyrinxstatic void 945164410Ssyrinxbridge_if_index_append(struct asn_oid *oid, uint sub, 946164410Ssyrinx const struct bridge_if *bif) 947164410Ssyrinx{ 948164410Ssyrinx uint i; 949164410Ssyrinx 950164410Ssyrinx oid->len = sub + strlen(bif->bif_name) + 1; 951164410Ssyrinx oid->subs[sub] = strlen(bif->bif_name); 952164410Ssyrinx 953164410Ssyrinx for (i = 1; i <= strlen(bif->bif_name); i++) 954164410Ssyrinx oid->subs[sub + i] = bif->bif_name[i - 1]; 955164410Ssyrinx} 956164410Ssyrinx 957164410Ssyrinxstatic struct bridge_if * 958164410Ssyrinxbridge_if_index_get(const struct asn_oid *oid, uint sub) 959164410Ssyrinx{ 960164410Ssyrinx uint i; 961164410Ssyrinx char bif_name[IFNAMSIZ]; 962164410Ssyrinx 963164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 964164410Ssyrinx return (NULL); 965164410Ssyrinx 966164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 967164410Ssyrinx bif_name[i] = oid->subs[sub + i + 1]; 968164410Ssyrinx bif_name[i] = '\0'; 969164410Ssyrinx 970164410Ssyrinx return (bridge_if_find_ifname(bif_name)); 971164410Ssyrinx} 972164410Ssyrinx 973164410Ssyrinxstatic struct bridge_if * 974164410Ssyrinxbridge_if_index_getnext(const struct asn_oid *oid, uint sub) 975164410Ssyrinx{ 976164410Ssyrinx uint i; 977164410Ssyrinx char bif_name[IFNAMSIZ]; 978164410Ssyrinx struct bridge_if *bif; 979164410Ssyrinx 980164410Ssyrinx if (oid->len - sub == 0) 981164410Ssyrinx return (bridge_first_bif()); 982164410Ssyrinx 983164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 984164410Ssyrinx return (NULL); 985164410Ssyrinx 986164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 987164410Ssyrinx bif_name[i] = oid->subs[sub + i + 1]; 988164410Ssyrinx bif_name[i] = '\0'; 989164410Ssyrinx 990164410Ssyrinx if ((bif = bridge_if_find_ifname(bif_name)) == NULL) 991164410Ssyrinx return (NULL); 992164410Ssyrinx 993164410Ssyrinx return (bridge_next_bif(bif)); 994164410Ssyrinx} 995164410Ssyrinx 996164410Ssyrinxstatic int 997164410Ssyrinxbridge_set_if_status(struct snmp_context *ctx, 998164410Ssyrinx struct snmp_value *val, uint sub) 999164410Ssyrinx{ 1000164410Ssyrinx struct bridge_if *bif; 1001164410Ssyrinx char bif_name[IFNAMSIZ]; 1002164410Ssyrinx 1003164410Ssyrinx bif = bridge_if_index_get(&val->var, sub); 1004164410Ssyrinx 1005164410Ssyrinx switch (val->v.integer) { 1006164410Ssyrinx case RowStatus_active: 1007164410Ssyrinx if (bif == NULL) 1008164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1009164410Ssyrinx 1010164410Ssyrinx ctx->scratch->int1 = bif->if_status; 1011164410Ssyrinx 1012164410Ssyrinx switch (bif->if_status) { 1013164410Ssyrinx case RowStatus_active: 1014164410Ssyrinx return (SNMP_ERR_NOERROR); 1015164410Ssyrinx case RowStatus_notInService: 1016164410Ssyrinx if (bridge_set_if_up(bif->bif_name, 1) < 0) 1017164410Ssyrinx return (SNMP_ERR_GENERR); 1018164410Ssyrinx return (SNMP_ERR_NOERROR); 1019164410Ssyrinx default: 1020164410Ssyrinx break; 1021164410Ssyrinx } 1022164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1023164410Ssyrinx 1024164410Ssyrinx case RowStatus_notInService: 1025164410Ssyrinx if (bif == NULL) 1026164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1027164410Ssyrinx 1028164410Ssyrinx ctx->scratch->int1 = bif->if_status; 1029164410Ssyrinx 1030164410Ssyrinx switch (bif->if_status) { 1031164410Ssyrinx case RowStatus_active: 1032164410Ssyrinx if (bridge_set_if_up(bif->bif_name, 1) < 0) 1033164410Ssyrinx return (SNMP_ERR_GENERR); 1034164410Ssyrinx return (SNMP_ERR_NOERROR); 1035164410Ssyrinx case RowStatus_notInService: 1036164410Ssyrinx return (SNMP_ERR_NOERROR); 1037164410Ssyrinx default: 1038164410Ssyrinx break; 1039164410Ssyrinx } 1040164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1041164410Ssyrinx 1042164410Ssyrinx case RowStatus_notReady: 1043164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1044164410Ssyrinx 1045164410Ssyrinx case RowStatus_createAndGo: 1046164410Ssyrinx if (bif != NULL) 1047164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1048164410Ssyrinx 1049164410Ssyrinx ctx->scratch->int1 = RowStatus_destroy; 1050164410Ssyrinx 1051164410Ssyrinx if (bridge_name_index_get(&val->var, sub, bif_name) == NULL) 1052164410Ssyrinx return (SNMP_ERR_BADVALUE); 1053164410Ssyrinx if (bridge_if_create(bif_name, 1) < 0) 1054164410Ssyrinx return (SNMP_ERR_GENERR); 1055164410Ssyrinx return (SNMP_ERR_NOERROR); 1056164410Ssyrinx 1057164410Ssyrinx case RowStatus_createAndWait: 1058164410Ssyrinx if (bif != NULL) 1059164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1060164410Ssyrinx 1061164410Ssyrinx if (bridge_name_index_get(&val->var, sub, bif_name) == NULL) 1062164410Ssyrinx return (SNMP_ERR_BADVALUE); 1063164410Ssyrinx 1064164410Ssyrinx ctx->scratch->int1 = RowStatus_destroy; 1065164410Ssyrinx 1066164410Ssyrinx if (bridge_if_create(bif_name, 0) < 0) 1067164410Ssyrinx return (SNMP_ERR_GENERR); 1068164410Ssyrinx return (SNMP_ERR_NOERROR); 1069164410Ssyrinx 1070164410Ssyrinx case RowStatus_destroy: 1071164410Ssyrinx if (bif == NULL) 1072164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1073164410Ssyrinx 1074164410Ssyrinx ctx->scratch->int1 = bif->if_status; 1075164410Ssyrinx bif->if_status = RowStatus_destroy; 1076164410Ssyrinx } 1077164410Ssyrinx 1078164410Ssyrinx return (SNMP_ERR_NOERROR); 1079164410Ssyrinx} 1080164410Ssyrinx 1081164410Ssyrinxstatic int 1082164410Ssyrinxbridge_rollback_if_status(struct snmp_context *ctx, 1083164410Ssyrinx struct snmp_value *val, uint sub) 1084164410Ssyrinx{ 1085164410Ssyrinx struct bridge_if *bif; 1086164410Ssyrinx 1087164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1088164410Ssyrinx return (SNMP_ERR_GENERR); 1089164410Ssyrinx 1090164410Ssyrinx switch (ctx->scratch->int1) { 1091164410Ssyrinx case RowStatus_destroy: 1092164410Ssyrinx bridge_if_destroy(bif); 1093164410Ssyrinx return (SNMP_ERR_NOERROR); 1094164410Ssyrinx 1095164410Ssyrinx case RowStatus_notInService: 1096164410Ssyrinx if (bif->if_status != ctx->scratch->int1) 1097164410Ssyrinx bridge_set_if_up(bif->bif_name, 0); 1098164410Ssyrinx bif->if_status = RowStatus_notInService; 1099164410Ssyrinx return (SNMP_ERR_NOERROR); 1100164410Ssyrinx 1101164410Ssyrinx case RowStatus_active: 1102164410Ssyrinx if (bif->if_status != ctx->scratch->int1) 1103164410Ssyrinx bridge_set_if_up(bif->bif_name, 1); 1104164410Ssyrinx bif->if_status = RowStatus_active; 1105164410Ssyrinx return (SNMP_ERR_NOERROR); 1106164410Ssyrinx } 1107164410Ssyrinx 1108164410Ssyrinx abort(); 1109164410Ssyrinx} 1110164410Ssyrinx 1111164410Ssyrinxstatic int 1112164410Ssyrinxbridge_commit_if_status(struct snmp_value *val, uint sub) 1113164410Ssyrinx{ 1114164410Ssyrinx struct bridge_if *bif; 1115164410Ssyrinx 1116164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1117164410Ssyrinx return (SNMP_ERR_GENERR); 1118164410Ssyrinx 1119164410Ssyrinx if (bif->if_status == RowStatus_destroy && 1120164410Ssyrinx bridge_if_destroy(bif) < 0) 1121164410Ssyrinx return (SNMP_ERR_COMMIT_FAILED); 1122164410Ssyrinx 1123164410Ssyrinx return (SNMP_ERR_NOERROR); 1124164410Ssyrinx} 1125164410Ssyrinx 1126164410Ssyrinxint 1127164410Ssyrinxop_begemot_base_bridge(struct snmp_context *ctx, struct snmp_value *val, 1128164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1129164410Ssyrinx{ 1130165046Ssyrinx struct bridge_if *bif; 1131164410Ssyrinx 1132164410Ssyrinx if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1133164410Ssyrinx bridge_update_all_ifs(); 1134164410Ssyrinx 1135164410Ssyrinx switch (op) { 1136164410Ssyrinx case SNMP_OP_GET: 1137164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1138164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1139165253Ssyrinx goto get; 1140164410Ssyrinx 1141164410Ssyrinx case SNMP_OP_GETNEXT: 1142164410Ssyrinx if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1143164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1144164410Ssyrinx bridge_if_index_append(&val->var, sub, bif); 1145165253Ssyrinx goto get; 1146164410Ssyrinx 1147164410Ssyrinx case SNMP_OP_SET: 1148164410Ssyrinx switch (val->var.subs[sub - 1]) { 1149164410Ssyrinx case LEAF_begemotBridgeBaseStatus: 1150164410Ssyrinx return (bridge_set_if_status(ctx, val, sub)); 1151164410Ssyrinx case LEAF_begemotBridgeBaseName: 1152164410Ssyrinx case LEAF_begemotBridgeBaseAddress: 1153164410Ssyrinx case LEAF_begemotBridgeBaseNumPorts: 1154164410Ssyrinx case LEAF_begemotBridgeBaseType: 1155164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1156164410Ssyrinx } 1157164410Ssyrinx abort(); 1158164410Ssyrinx 1159164410Ssyrinx case SNMP_OP_ROLLBACK: 1160164410Ssyrinx return (bridge_rollback_if_status(ctx, val, sub)); 1161165046Ssyrinx 1162164410Ssyrinx case SNMP_OP_COMMIT: 1163164410Ssyrinx return (bridge_commit_if_status(val, sub)); 1164164410Ssyrinx } 1165165253Ssyrinx abort(); 1166164410Ssyrinx 1167165253Ssyrinxget: 1168164410Ssyrinx switch (val->var.subs[sub - 1]) { 1169164410Ssyrinx case LEAF_begemotBridgeBaseName: 1170165253Ssyrinx return (string_get(val, bif->bif_name, -1)); 1171164410Ssyrinx 1172164410Ssyrinx case LEAF_begemotBridgeBaseAddress: 1173165253Ssyrinx return (string_get(val, bif->br_addr.octet, ETHER_ADDR_LEN)); 1174164410Ssyrinx 1175164410Ssyrinx case LEAF_begemotBridgeBaseNumPorts: 1176164410Ssyrinx val->v.integer = bif->num_ports; 1177165253Ssyrinx return (SNMP_ERR_NOERROR); 1178164410Ssyrinx 1179164410Ssyrinx case LEAF_begemotBridgeBaseType: 1180164410Ssyrinx val->v.integer = bif->br_type; 1181165253Ssyrinx return (SNMP_ERR_NOERROR); 1182164410Ssyrinx 1183164410Ssyrinx case LEAF_begemotBridgeBaseStatus: 1184164410Ssyrinx val->v.integer = bif->if_status; 1185165253Ssyrinx return (SNMP_ERR_NOERROR); 1186164410Ssyrinx } 1187164410Ssyrinx 1188165253Ssyrinx abort(); 1189164410Ssyrinx} 1190164410Ssyrinx 1191164410Ssyrinxint 1192164410Ssyrinxop_begemot_stp(struct snmp_context *ctx, struct snmp_value *val, 1193164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1194164410Ssyrinx{ 1195165046Ssyrinx struct bridge_if *bif; 1196164410Ssyrinx 1197164410Ssyrinx if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1198164410Ssyrinx bridge_update_all_ifs(); 1199164410Ssyrinx 1200164410Ssyrinx switch (op) { 1201164410Ssyrinx case SNMP_OP_GET: 1202164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1203164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1204165253Ssyrinx goto get; 1205164410Ssyrinx 1206164410Ssyrinx case SNMP_OP_GETNEXT: 1207164410Ssyrinx if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1208164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1209164410Ssyrinx bridge_if_index_append(&val->var, sub, bif); 1210165253Ssyrinx goto get; 1211164410Ssyrinx 1212164410Ssyrinx case SNMP_OP_SET: 1213164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1214164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1215164410Ssyrinx 1216164410Ssyrinx switch (val->var.subs[sub - 1]) { 1217164410Ssyrinx case LEAF_begemotBridgeStpPriority: 1218165253Ssyrinx if (val->v.integer > SNMP_BRIDGE_MAX_PRIORITY || 1219165253Ssyrinx val->v.integer % 4096 != 0) 1220165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1221165253Ssyrinx 1222164410Ssyrinx ctx->scratch->int1 = bif->priority; 1223165253Ssyrinx if (bridge_set_priority(bif, val->v.integer) < 0) 1224165253Ssyrinx return (SNMP_ERR_GENERR); 1225165253Ssyrinx return (SNMP_ERR_NOERROR); 1226164410Ssyrinx 1227164410Ssyrinx case LEAF_begemotBridgeStpBridgeMaxAge: 1228165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_MAGE || 1229165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_MAGE) 1230165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1231165253Ssyrinx 1232164410Ssyrinx ctx->scratch->int1 = bif->bridge_max_age; 1233165253Ssyrinx if (bridge_set_maxage(bif, val->v.integer) < 0) 1234165253Ssyrinx return (SNMP_ERR_GENERR); 1235165253Ssyrinx return (SNMP_ERR_NOERROR); 1236164410Ssyrinx 1237164410Ssyrinx case LEAF_begemotBridgeStpBridgeHelloTime: 1238165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_HTIME || 1239165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_HTIME) 1240165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1241165253Ssyrinx 1242164410Ssyrinx ctx->scratch->int1 = bif->bridge_hello_time; 1243165253Ssyrinx if (bridge_set_hello_time(bif, val->v.integer) < 0) 1244165253Ssyrinx return (SNMP_ERR_GENERR); 1245165253Ssyrinx return (SNMP_ERR_NOERROR); 1246164410Ssyrinx 1247164410Ssyrinx case LEAF_begemotBridgeStpBridgeForwardDelay: 1248165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_FDELAY || 1249165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_FDELAY) 1250165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1251165253Ssyrinx 1252164410Ssyrinx ctx->scratch->int1 = bif->bridge_fwd_delay; 1253165253Ssyrinx if (bridge_set_forward_delay(bif, val->v.integer) < 0) 1254165253Ssyrinx return (SNMP_ERR_GENERR); 1255165253Ssyrinx return (SNMP_ERR_NOERROR); 1256164410Ssyrinx 1257164997Ssyrinx case LEAF_begemotBridgeStpVersion: 1258165253Ssyrinx if (val->v.integer != 1259165253Ssyrinx begemotBridgeStpVersion_stpCompatible && 1260165253Ssyrinx val->v.integer != begemotBridgeStpVersion_rstp) 1261165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1262165253Ssyrinx 1263164997Ssyrinx ctx->scratch->int1 = bif->stp_version; 1264165253Ssyrinx if (bridge_set_stp_version(bif, val->v.integer) < 0) 1265165253Ssyrinx return (SNMP_ERR_GENERR); 1266165253Ssyrinx return (SNMP_ERR_NOERROR); 1267164997Ssyrinx 1268164997Ssyrinx case LEAF_begemotBridgeStpTxHoldCount: 1269165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_TXHC || 1270165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_TXHC) 1271165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1272165253Ssyrinx 1273164997Ssyrinx ctx->scratch->int1 = bif->tx_hold_count; 1274165253Ssyrinx if (bridge_set_tx_hold_count(bif, val->v.integer) < 0) 1275165253Ssyrinx return (SNMP_ERR_GENERR); 1276165253Ssyrinx return (SNMP_ERR_NOERROR); 1277164997Ssyrinx 1278164410Ssyrinx case LEAF_begemotBridgeStpProtocolSpecification: 1279164410Ssyrinx case LEAF_begemotBridgeStpTimeSinceTopologyChange: 1280164410Ssyrinx case LEAF_begemotBridgeStpTopChanges: 1281164410Ssyrinx case LEAF_begemotBridgeStpDesignatedRoot: 1282164410Ssyrinx case LEAF_begemotBridgeStpRootCost: 1283164410Ssyrinx case LEAF_begemotBridgeStpRootPort: 1284164410Ssyrinx case LEAF_begemotBridgeStpMaxAge: 1285164410Ssyrinx case LEAF_begemotBridgeStpHelloTime: 1286164410Ssyrinx case LEAF_begemotBridgeStpHoldTime: 1287164410Ssyrinx case LEAF_begemotBridgeStpForwardDelay: 1288164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1289164410Ssyrinx } 1290165253Ssyrinx abort(); 1291164410Ssyrinx 1292164410Ssyrinx case SNMP_OP_ROLLBACK: 1293164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1294164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1295164410Ssyrinx 1296164410Ssyrinx switch (val->var.subs[sub - 1]) { 1297164410Ssyrinx case LEAF_begemotBridgeStpPriority: 1298164410Ssyrinx bridge_set_priority(bif, ctx->scratch->int1); 1299164410Ssyrinx break; 1300164410Ssyrinx 1301164410Ssyrinx case LEAF_begemotBridgeStpBridgeMaxAge: 1302164410Ssyrinx bridge_set_maxage(bif, ctx->scratch->int1); 1303164410Ssyrinx break; 1304164410Ssyrinx 1305164410Ssyrinx case LEAF_begemotBridgeStpBridgeHelloTime: 1306164410Ssyrinx bridge_set_hello_time(bif, ctx->scratch->int1); 1307164410Ssyrinx break; 1308164410Ssyrinx 1309164410Ssyrinx case LEAF_begemotBridgeStpBridgeForwardDelay: 1310164410Ssyrinx bridge_set_forward_delay(bif, ctx->scratch->int1); 1311164410Ssyrinx break; 1312164997Ssyrinx 1313164997Ssyrinx case LEAF_begemotBridgeStpVersion: 1314164997Ssyrinx bridge_set_stp_version(bif, ctx->scratch->int1); 1315164997Ssyrinx break; 1316164997Ssyrinx 1317164997Ssyrinx case LEAF_begemotBridgeStpTxHoldCount: 1318164997Ssyrinx bridge_set_tx_hold_count(bif, ctx->scratch->int1); 1319164997Ssyrinx break; 1320164410Ssyrinx } 1321164410Ssyrinx return (SNMP_ERR_NOERROR); 1322164410Ssyrinx 1323164410Ssyrinx case SNMP_OP_COMMIT: 1324164410Ssyrinx return (SNMP_ERR_NOERROR); 1325164410Ssyrinx } 1326165253Ssyrinx abort(); 1327164410Ssyrinx 1328165253Ssyrinxget: 1329164410Ssyrinx switch (val->var.subs[sub - 1]) { 1330164410Ssyrinx case LEAF_begemotBridgeStpProtocolSpecification: 1331164410Ssyrinx val->v.integer = bif->prot_spec; 1332165253Ssyrinx return (SNMP_ERR_NOERROR); 1333164410Ssyrinx 1334164410Ssyrinx case LEAF_begemotBridgeStpPriority: 1335164410Ssyrinx val->v.integer = bif->priority; 1336165253Ssyrinx return (SNMP_ERR_NOERROR); 1337164410Ssyrinx 1338164410Ssyrinx case LEAF_begemotBridgeStpTimeSinceTopologyChange: 1339164410Ssyrinx if (bridge_get_time_since_tc(bif, &(val->v.uint32)) < 0) 1340164410Ssyrinx return (SNMP_ERR_GENERR); 1341165253Ssyrinx return (SNMP_ERR_NOERROR); 1342164410Ssyrinx 1343164410Ssyrinx case LEAF_begemotBridgeStpTopChanges: 1344164410Ssyrinx val->v.uint32 = bif->top_changes; 1345165253Ssyrinx return (SNMP_ERR_NOERROR); 1346164410Ssyrinx 1347164410Ssyrinx case LEAF_begemotBridgeStpDesignatedRoot: 1348165253Ssyrinx return (string_get(val, bif->design_root, SNMP_BRIDGE_ID_LEN)); 1349164410Ssyrinx 1350164410Ssyrinx case LEAF_begemotBridgeStpRootCost: 1351164410Ssyrinx val->v.integer = bif->root_cost; 1352165253Ssyrinx return (SNMP_ERR_NOERROR); 1353164410Ssyrinx 1354164410Ssyrinx case LEAF_begemotBridgeStpRootPort: 1355164410Ssyrinx val->v.integer = bif->root_port; 1356165253Ssyrinx return (SNMP_ERR_NOERROR); 1357164410Ssyrinx 1358164410Ssyrinx case LEAF_begemotBridgeStpMaxAge: 1359164410Ssyrinx val->v.integer = bif->max_age; 1360165253Ssyrinx return (SNMP_ERR_NOERROR); 1361164410Ssyrinx 1362164410Ssyrinx case LEAF_begemotBridgeStpHelloTime: 1363164410Ssyrinx val->v.integer = bif->hello_time; 1364165253Ssyrinx return (SNMP_ERR_NOERROR); 1365164410Ssyrinx 1366164410Ssyrinx case LEAF_begemotBridgeStpHoldTime: 1367164410Ssyrinx val->v.integer = bif->hold_time; 1368165253Ssyrinx return (SNMP_ERR_NOERROR); 1369164410Ssyrinx 1370164410Ssyrinx case LEAF_begemotBridgeStpForwardDelay: 1371164410Ssyrinx val->v.integer = bif->fwd_delay; 1372165253Ssyrinx return (SNMP_ERR_NOERROR); 1373164410Ssyrinx 1374164410Ssyrinx case LEAF_begemotBridgeStpBridgeMaxAge: 1375164410Ssyrinx val->v.integer = bif->bridge_max_age; 1376165253Ssyrinx return (SNMP_ERR_NOERROR); 1377164410Ssyrinx 1378164410Ssyrinx case LEAF_begemotBridgeStpBridgeHelloTime: 1379164410Ssyrinx val->v.integer = bif->bridge_hello_time; 1380165253Ssyrinx return (SNMP_ERR_NOERROR); 1381164410Ssyrinx 1382164410Ssyrinx case LEAF_begemotBridgeStpBridgeForwardDelay: 1383164410Ssyrinx val->v.integer = bif->bridge_fwd_delay; 1384165253Ssyrinx return (SNMP_ERR_NOERROR); 1385164997Ssyrinx 1386164997Ssyrinx case LEAF_begemotBridgeStpVersion: 1387164997Ssyrinx val->v.integer = bif->stp_version; 1388165253Ssyrinx return (SNMP_ERR_NOERROR); 1389164997Ssyrinx 1390164997Ssyrinx case LEAF_begemotBridgeStpTxHoldCount: 1391164997Ssyrinx val->v.integer = bif->tx_hold_count; 1392165253Ssyrinx return (SNMP_ERR_NOERROR); 1393164410Ssyrinx } 1394164410Ssyrinx 1395165253Ssyrinx abort(); 1396164410Ssyrinx} 1397164410Ssyrinx 1398164410Ssyrinxint 1399164410Ssyrinxop_begemot_tp(struct snmp_context *ctx, struct snmp_value *val, 1400164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1401164410Ssyrinx{ 1402165046Ssyrinx struct bridge_if *bif; 1403164410Ssyrinx 1404164410Ssyrinx if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1405164410Ssyrinx bridge_update_all_ifs(); 1406164410Ssyrinx 1407164410Ssyrinx switch (op) { 1408164410Ssyrinx case SNMP_OP_GET: 1409164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1410164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1411165253Ssyrinx goto get; 1412164410Ssyrinx 1413164410Ssyrinx case SNMP_OP_GETNEXT: 1414164410Ssyrinx if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1415164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1416164410Ssyrinx bridge_if_index_append(&val->var, sub, bif); 1417165253Ssyrinx goto get; 1418164410Ssyrinx 1419164410Ssyrinx case SNMP_OP_SET: 1420164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1421164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1422164410Ssyrinx 1423164410Ssyrinx switch (val->var.subs[sub - 1]) { 1424164410Ssyrinx case LEAF_begemotBridgeTpAgingTime: 1425165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_AGE_TIME || 1426165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_AGE_TIME) 1427165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1428165253Ssyrinx 1429164410Ssyrinx ctx->scratch->int1 = bif->age_time; 1430164410Ssyrinx if (bridge_set_aging_time(bif, val->v.integer) < 0) 1431164410Ssyrinx return (SNMP_ERR_GENERR); 1432164410Ssyrinx return (SNMP_ERR_NOERROR); 1433164410Ssyrinx 1434164410Ssyrinx case LEAF_begemotBridgeTpMaxAddresses: 1435164410Ssyrinx ctx->scratch->int1 = bif->max_addrs; 1436164410Ssyrinx if (bridge_set_max_cache(bif, val->v.integer) < 0) 1437164410Ssyrinx return (SNMP_ERR_GENERR); 1438164410Ssyrinx return (SNMP_ERR_NOERROR); 1439164410Ssyrinx 1440164410Ssyrinx case LEAF_begemotBridgeTpLearnedEntryDiscards: 1441164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1442164410Ssyrinx } 1443164410Ssyrinx abort(); 1444164410Ssyrinx 1445164410Ssyrinx case SNMP_OP_ROLLBACK: 1446164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1447164410Ssyrinx return (SNMP_ERR_GENERR); 1448164410Ssyrinx 1449164410Ssyrinx switch (val->var.subs[sub - 1]) { 1450164410Ssyrinx case LEAF_begemotBridgeTpAgingTime: 1451164410Ssyrinx bridge_set_aging_time(bif, ctx->scratch->int1); 1452164410Ssyrinx break; 1453164410Ssyrinx 1454164410Ssyrinx case LEAF_begemotBridgeTpMaxAddresses: 1455164410Ssyrinx bridge_set_max_cache(bif, ctx->scratch->int1); 1456164410Ssyrinx break; 1457164410Ssyrinx } 1458164410Ssyrinx return (SNMP_ERR_NOERROR); 1459164410Ssyrinx 1460164410Ssyrinx case SNMP_OP_COMMIT: 1461164410Ssyrinx return (SNMP_ERR_NOERROR); 1462164410Ssyrinx } 1463165253Ssyrinx abort(); 1464164410Ssyrinx 1465165253Ssyrinxget: 1466164410Ssyrinx switch (val->var.subs[sub - 1]) { 1467164410Ssyrinx case LEAF_begemotBridgeTpLearnedEntryDiscards: 1468164410Ssyrinx val->v.uint32 = bif->lrnt_drops; 1469165253Ssyrinx return (SNMP_ERR_NOERROR); 1470164410Ssyrinx 1471164410Ssyrinx case LEAF_begemotBridgeTpAgingTime: 1472164410Ssyrinx val->v.integer = bif->age_time; 1473165253Ssyrinx return (SNMP_ERR_NOERROR); 1474164410Ssyrinx 1475164410Ssyrinx case LEAF_begemotBridgeTpMaxAddresses: 1476164410Ssyrinx val->v.integer = bif->max_addrs; 1477165253Ssyrinx return (SNMP_ERR_NOERROR); 1478164410Ssyrinx } 1479164410Ssyrinx 1480165253Ssyrinx abort(); 1481164410Ssyrinx} 1482