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 interface objects. 28164410Ssyrinx * 29164410Ssyrinx * $FreeBSD$ 30164410Ssyrinx */ 31164410Ssyrinx 32164410Ssyrinx#include <sys/queue.h> 33164410Ssyrinx#include <sys/socket.h> 34164410Ssyrinx#include <sys/time.h> 35164410Ssyrinx#include <sys/types.h> 36164410Ssyrinx 37164410Ssyrinx#include <net/ethernet.h> 38164410Ssyrinx#include <net/if.h> 39164410Ssyrinx#include <net/if_mib.h> 40164410Ssyrinx#include <net/if_types.h> 41164410Ssyrinx 42164410Ssyrinx#include <errno.h> 43164410Ssyrinx#include <stdarg.h> 44164410Ssyrinx#include <stdlib.h> 45164410Ssyrinx#include <string.h> 46164410Ssyrinx#include <syslog.h> 47164410Ssyrinx 48164410Ssyrinx#include <bsnmp/snmpmod.h> 49164410Ssyrinx#include <bsnmp/snmp_mibII.h> 50164410Ssyrinx 51164410Ssyrinx#include "bridge_tree.h" 52164410Ssyrinx#include "bridge_snmp.h" 53164410Ssyrinx#include "bridge_oid.h" 54164410Ssyrinx 55164410Ssyrinxstatic const struct asn_oid oid_newRoot = OIDX_newRoot; 56164410Ssyrinxstatic const struct asn_oid oid_TopologyChange = OIDX_topologyChange; 57164410Ssyrinxstatic const struct asn_oid oid_begemotBrigeName = \ 58164410Ssyrinx OIDX_begemotBridgeBaseName; 59164410Ssyrinxstatic const struct asn_oid oid_begemotNewRoot = OIDX_begemotBridgeNewRoot; 60164410Ssyrinxstatic const struct asn_oid oid_begemotTopologyChange = \ 61164410Ssyrinx OIDX_begemotBridgeTopologyChange; 62164410Ssyrinx 63164410SsyrinxTAILQ_HEAD(bridge_ifs, bridge_if); 64164410Ssyrinx 65164410Ssyrinx/* 66164410Ssyrinx * Free the bridge interface list. 67164410Ssyrinx */ 68164410Ssyrinxstatic void 69164410Ssyrinxbridge_ifs_free(struct bridge_ifs *headp) 70164410Ssyrinx{ 71164410Ssyrinx struct bridge_if *b; 72164410Ssyrinx 73164410Ssyrinx while ((b = TAILQ_FIRST(headp)) != NULL) { 74164410Ssyrinx TAILQ_REMOVE(headp, b, b_if); 75164410Ssyrinx free(b); 76164410Ssyrinx } 77164410Ssyrinx} 78164410Ssyrinx 79164410Ssyrinx/* 80164410Ssyrinx * Insert an entry in the bridge interface TAILQ. Keep the 81164410Ssyrinx * TAILQ sorted by the bridge's interface name. 82164410Ssyrinx */ 83164410Ssyrinxstatic void 84164410Ssyrinxbridge_ifs_insert(struct bridge_ifs *headp, 85164410Ssyrinx struct bridge_if *b) 86164410Ssyrinx{ 87164410Ssyrinx struct bridge_if *temp; 88164410Ssyrinx 89164410Ssyrinx if ((temp = TAILQ_FIRST(headp)) == NULL || 90164410Ssyrinx strcmp(b->bif_name, temp->bif_name) < 0) { 91164410Ssyrinx TAILQ_INSERT_HEAD(headp, b, b_if); 92164410Ssyrinx return; 93164410Ssyrinx } 94164410Ssyrinx 95164410Ssyrinx TAILQ_FOREACH(temp, headp, b_if) 96164410Ssyrinx if(strcmp(b->bif_name, temp->bif_name) < 0) 97164410Ssyrinx TAILQ_INSERT_BEFORE(temp, b, b_if); 98164410Ssyrinx 99164410Ssyrinx TAILQ_INSERT_TAIL(headp, b, b_if); 100164410Ssyrinx} 101164410Ssyrinx 102164410Ssyrinx/* The global bridge interface list. */ 103164410Ssyrinxstatic struct bridge_ifs bridge_ifs = TAILQ_HEAD_INITIALIZER(bridge_ifs); 104164410Ssyrinxstatic time_t bridge_list_age; 105164410Ssyrinx 106164410Ssyrinx/* 107164410Ssyrinx * Free the global list. 108164410Ssyrinx */ 109164410Ssyrinxvoid 110164410Ssyrinxbridge_ifs_fini(void) 111164410Ssyrinx{ 112164410Ssyrinx bridge_ifs_free(&bridge_ifs); 113164410Ssyrinx} 114164410Ssyrinx 115164410Ssyrinx/* 116164410Ssyrinx * Find a bridge interface entry by the bridge interface system index. 117164410Ssyrinx */ 118164410Ssyrinxstruct bridge_if * 119164410Ssyrinxbridge_if_find_ifs(uint32_t sysindex) 120164410Ssyrinx{ 121164410Ssyrinx struct bridge_if *b; 122164410Ssyrinx 123164410Ssyrinx TAILQ_FOREACH(b, &bridge_ifs, b_if) 124164410Ssyrinx if (b->sysindex == sysindex) 125164410Ssyrinx return (b); 126164410Ssyrinx 127164410Ssyrinx return (NULL); 128164410Ssyrinx} 129164410Ssyrinx 130164410Ssyrinx/* 131164410Ssyrinx * Find a bridge interface entry by the bridge interface name. 132164410Ssyrinx */ 133164410Ssyrinxstruct bridge_if * 134164410Ssyrinxbridge_if_find_ifname(const char *b_name) 135164410Ssyrinx{ 136164410Ssyrinx struct bridge_if *b; 137164410Ssyrinx 138164410Ssyrinx TAILQ_FOREACH(b, &bridge_ifs, b_if) 139164410Ssyrinx if (strcmp(b_name, b->bif_name) == 0) 140164410Ssyrinx return (b); 141164410Ssyrinx 142164410Ssyrinx return (NULL); 143164410Ssyrinx} 144164410Ssyrinx 145164410Ssyrinx/* 146164410Ssyrinx * Find a bridge name by the bridge interface system index. 147164410Ssyrinx */ 148164410Ssyrinxconst char * 149164410Ssyrinxbridge_if_find_name(uint32_t sysindex) 150164410Ssyrinx{ 151164410Ssyrinx struct bridge_if *b; 152164410Ssyrinx 153164410Ssyrinx TAILQ_FOREACH(b, &bridge_ifs, b_if) 154164410Ssyrinx if (b->sysindex == sysindex) 155164410Ssyrinx return (b->bif_name); 156164410Ssyrinx 157164410Ssyrinx return (NULL); 158164410Ssyrinx} 159164410Ssyrinx 160164410Ssyrinx/* 161164410Ssyrinx * Given two bridge interfaces' system indexes, find their 162164410Ssyrinx * corresponding names and return the result of the name 163164410Ssyrinx * comparison. Returns: 164164410Ssyrinx * error : -2 165164410Ssyrinx * i1 < i2 : -1 166164410Ssyrinx * i1 > i2 : +1 167164410Ssyrinx * i1 = i2 : 0 168164410Ssyrinx */ 169164410Ssyrinxint 170164410Ssyrinxbridge_compare_sysidx(uint32_t i1, uint32_t i2) 171164410Ssyrinx{ 172164410Ssyrinx int c; 173164410Ssyrinx const char *b1, *b2; 174164410Ssyrinx 175164410Ssyrinx if (i1 == i2) 176164410Ssyrinx return (0); 177164410Ssyrinx 178164410Ssyrinx if ((b1 = bridge_if_find_name(i1)) == NULL) { 179164410Ssyrinx syslog(LOG_ERR, "Bridge interface %d does not exist", i1); 180164410Ssyrinx return (-2); 181164410Ssyrinx } 182164410Ssyrinx 183164410Ssyrinx if ((b2 = bridge_if_find_name(i2)) == NULL) { 184164410Ssyrinx syslog(LOG_ERR, "Bridge interface %d does not exist", i2); 185164410Ssyrinx return (-2); 186164410Ssyrinx } 187164410Ssyrinx 188164410Ssyrinx if ((c = strcmp(b1, b2)) < 0) 189164410Ssyrinx return (-1); 190164410Ssyrinx else if (c > 0) 191164410Ssyrinx return (1); 192164410Ssyrinx 193164410Ssyrinx return (0); 194164410Ssyrinx} 195164410Ssyrinx 196164410Ssyrinx/* 197164410Ssyrinx * Fetch the first bridge interface from the list. 198164410Ssyrinx */ 199164410Ssyrinxstruct bridge_if * 200164410Ssyrinxbridge_first_bif(void) 201164410Ssyrinx{ 202164410Ssyrinx return (TAILQ_FIRST(&bridge_ifs)); 203164410Ssyrinx} 204164410Ssyrinx 205164410Ssyrinx/* 206164410Ssyrinx * Fetch the next bridge interface from the list. 207164410Ssyrinx */ 208164410Ssyrinxstruct bridge_if * 209164410Ssyrinxbridge_next_bif(struct bridge_if *b_pr) 210164410Ssyrinx{ 211164410Ssyrinx return (TAILQ_NEXT(b_pr, b_if)); 212164410Ssyrinx} 213164410Ssyrinx 214164410Ssyrinx/* 215164410Ssyrinx * Create a new entry for a bridge interface and insert 216164410Ssyrinx * it in the list. 217164410Ssyrinx */ 218164410Ssyrinxstatic struct bridge_if * 219164410Ssyrinxbridge_new_bif(const char *bif_n, uint32_t sysindex, const u_char *physaddr) 220164410Ssyrinx{ 221164410Ssyrinx struct bridge_if *bif; 222164410Ssyrinx 223164410Ssyrinx if ((bif = (struct bridge_if *) malloc(sizeof(*bif)))== NULL) { 224164410Ssyrinx syslog(LOG_ERR, "bridge new interface failed: %s", 225164410Ssyrinx strerror(errno)); 226164410Ssyrinx return (NULL); 227164410Ssyrinx } 228164410Ssyrinx 229164410Ssyrinx bzero(bif, sizeof(struct bridge_if)); 230164410Ssyrinx strlcpy(bif->bif_name, bif_n, IFNAMSIZ); 231164410Ssyrinx bcopy(physaddr, bif->br_addr.octet, ETHER_ADDR_LEN); 232164410Ssyrinx bif->sysindex = sysindex; 233164410Ssyrinx bif->br_type = BaseType_transparent_only; 234164410Ssyrinx /* 1 - all bridges default hold time * 100 - centi-seconds */ 235164410Ssyrinx bif->hold_time = 1 * 100; 236164410Ssyrinx bif->prot_spec = dot1dStpProtocolSpecification_ieee8021d; 237164410Ssyrinx bridge_ifs_insert(&bridge_ifs, bif); 238164410Ssyrinx 239164410Ssyrinx return (bif); 240164410Ssyrinx} 241164410Ssyrinx 242164410Ssyrinx/* 243164410Ssyrinx * Remove a bridge interface from the list, freeing all it's ports 244164410Ssyrinx * and address entries. 245164410Ssyrinx */ 246164410Ssyrinxvoid 247164410Ssyrinxbridge_remove_bif(struct bridge_if *bif) 248164410Ssyrinx{ 249164410Ssyrinx bridge_members_free(bif); 250164410Ssyrinx bridge_addrs_free(bif); 251164410Ssyrinx TAILQ_REMOVE(&bridge_ifs, bif, b_if); 252164410Ssyrinx free(bif); 253164410Ssyrinx} 254164410Ssyrinx 255164410Ssyrinx 256164410Ssyrinx/* 257164410Ssyrinx * Prepare the variable (bridge interface name) for the private 258164410Ssyrinx * begemot notifications. 259164410Ssyrinx */ 260164410Ssyrinxstatic struct snmp_value* 261164410Ssyrinxbridge_basename_var(struct bridge_if *bif, struct snmp_value* b_val) 262164410Ssyrinx{ 263164410Ssyrinx uint i; 264164410Ssyrinx 265164410Ssyrinx b_val->var = oid_begemotBrigeName; 266164410Ssyrinx b_val->var.subs[b_val->var.len++] = strlen(bif->bif_name); 267164410Ssyrinx 268164410Ssyrinx if ((b_val->v.octetstring.octets = (u_char *) 269164410Ssyrinx malloc(strlen(bif->bif_name))) == NULL) 270164410Ssyrinx return (NULL); 271164410Ssyrinx 272164410Ssyrinx for (i = 0; i < strlen(bif->bif_name); i++) 273164410Ssyrinx b_val->var.subs[b_val->var.len++] = bif->bif_name[i]; 274164410Ssyrinx 275164410Ssyrinx b_val->v.octetstring.len = strlen(bif->bif_name); 276164410Ssyrinx bcopy(bif->bif_name, b_val->v.octetstring.octets, 277164410Ssyrinx strlen(bif->bif_name)); 278164410Ssyrinx b_val->syntax = SNMP_SYNTAX_OCTETSTRING; 279164410Ssyrinx 280164410Ssyrinx return (b_val); 281164410Ssyrinx} 282164410Ssyrinx 283164410Ssyrinx/* 284164410Ssyrinx * Compare the values of the old and the new root port and 285164410Ssyrinx * send a new root notification, if they are not matching. 286164410Ssyrinx */ 287164410Ssyrinxstatic void 288164410Ssyrinxbridge_new_root(struct bridge_if *bif) 289164410Ssyrinx{ 290164410Ssyrinx struct snmp_value bif_idx; 291164410Ssyrinx 292164410Ssyrinx if (bridge_get_default() == bif) 293164410Ssyrinx snmp_send_trap(&oid_newRoot, (struct snmp_value *) NULL); 294164410Ssyrinx 295164410Ssyrinx if (bridge_basename_var(bif, &bif_idx) == NULL) 296164410Ssyrinx return; 297164410Ssyrinx 298164410Ssyrinx snmp_send_trap(&oid_begemotTopologyChange, 299164410Ssyrinx &bif_idx, (struct snmp_value *) NULL); 300164410Ssyrinx} 301164410Ssyrinx 302164410Ssyrinx/* 303164410Ssyrinx * Compare the new and old topology change times and send a 304164410Ssyrinx * topology change notification if necessary. 305164410Ssyrinx */ 306164410Ssyrinxstatic void 307164410Ssyrinxbridge_top_change(struct bridge_if *bif) 308164410Ssyrinx{ 309164410Ssyrinx struct snmp_value bif_idx; 310164410Ssyrinx 311164410Ssyrinx if (bridge_get_default() == bif) 312164410Ssyrinx snmp_send_trap(&oid_TopologyChange, 313164410Ssyrinx (struct snmp_value *) NULL); 314164410Ssyrinx 315164410Ssyrinx if (bridge_basename_var(bif, &bif_idx) == NULL) 316164410Ssyrinx return; 317164410Ssyrinx 318164410Ssyrinx snmp_send_trap(&oid_begemotNewRoot, 319164410Ssyrinx &bif_idx, (struct snmp_value *) NULL); 320164410Ssyrinx} 321164410Ssyrinx 322164410Ssyrinxstatic int 323164410Ssyrinxbridge_if_create(const char* b_name, int8_t up) 324164410Ssyrinx{ 325164410Ssyrinx if (bridge_create(b_name) < 0) 326164410Ssyrinx return (-1); 327164410Ssyrinx 328164410Ssyrinx if (up == 1 && (bridge_set_if_up(b_name, 1) < 0)) 329164410Ssyrinx return (-1); 330164410Ssyrinx 331164410Ssyrinx /* 332164410Ssyrinx * Do not create a new bridge entry here - 333164410Ssyrinx * wait until the mibII module notifies us. 334164410Ssyrinx */ 335164410Ssyrinx return (0); 336164410Ssyrinx} 337164410Ssyrinx 338164410Ssyrinxstatic int 339164410Ssyrinxbridge_if_destroy(struct bridge_if *bif) 340164410Ssyrinx{ 341164410Ssyrinx if (bridge_destroy(bif->bif_name) < 0) 342164410Ssyrinx return (-1); 343164410Ssyrinx 344164410Ssyrinx bridge_remove_bif(bif); 345164410Ssyrinx 346164410Ssyrinx return (0); 347164410Ssyrinx} 348164410Ssyrinx 349164410Ssyrinx/* 350164410Ssyrinx * Calculate the timeticks since the last topology change. 351164410Ssyrinx */ 352164410Ssyrinxstatic int 353164410Ssyrinxbridge_get_time_since_tc(struct bridge_if *bif, uint32_t *ticks) 354164410Ssyrinx{ 355164410Ssyrinx struct timeval ct; 356164410Ssyrinx 357164410Ssyrinx if (gettimeofday(&ct, NULL) < 0) { 358164410Ssyrinx syslog(LOG_ERR, "bridge get time since last TC:" 359164410Ssyrinx "getttimeofday failed: %s", strerror(errno)); 360164410Ssyrinx return (-1); 361164410Ssyrinx } 362164410Ssyrinx 363164410Ssyrinx if (ct.tv_usec - bif->last_tc_time.tv_usec < 0) { 364164410Ssyrinx ct.tv_sec -= 1; 365164410Ssyrinx ct.tv_usec += 1000000; 366164410Ssyrinx } 367164410Ssyrinx 368164410Ssyrinx ct.tv_sec -= bif->last_tc_time.tv_sec; 369164410Ssyrinx ct.tv_usec -= bif->last_tc_time.tv_usec; 370164410Ssyrinx 371164410Ssyrinx *ticks = ct.tv_sec * 100 + ct.tv_usec/10000; 372164410Ssyrinx 373164410Ssyrinx return (0); 374164410Ssyrinx} 375164410Ssyrinx 376164410Ssyrinx/* 377164410Ssyrinx * Update the info we have for a single bridge interface. 378164410Ssyrinx * Return: 379164410Ssyrinx * 1, if successful 380164410Ssyrinx * 0, if the interface was deleted 381164410Ssyrinx * -1, error occured while fetching the info from the kernel. 382164410Ssyrinx */ 383164410Ssyrinxstatic int 384164410Ssyrinxbridge_update_bif(struct bridge_if *bif) 385164410Ssyrinx{ 386164410Ssyrinx struct mibif *ifp; 387164410Ssyrinx 388164410Ssyrinx /* Walk through the mibII interface list. */ 389164410Ssyrinx for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) 390164410Ssyrinx if (strcmp(ifp->name, bif->bif_name) == 0) 391164410Ssyrinx break; 392164410Ssyrinx 393164410Ssyrinx if (ifp == NULL) { 394164410Ssyrinx /* Ops, we do not exist anymore. */ 395164410Ssyrinx bridge_remove_bif(bif); 396164410Ssyrinx return (0); 397164410Ssyrinx } 398164410Ssyrinx 399164410Ssyrinx if (ifp->physaddr != NULL ) 400164410Ssyrinx bcopy(ifp->physaddr, bif->br_addr.octet, ETHER_ADDR_LEN); 401164410Ssyrinx else 402165642Sbz bridge_get_basemac(bif->bif_name, bif->br_addr.octet, 403165642Sbz ETHER_ADDR_LEN); 404164410Ssyrinx 405164410Ssyrinx if (ifp->mib.ifmd_flags & IFF_RUNNING) 406164410Ssyrinx bif->if_status = RowStatus_active; 407164410Ssyrinx else 408164410Ssyrinx bif->if_status = RowStatus_notInService; 409164410Ssyrinx 410164410Ssyrinx switch (bridge_getinfo_bif(bif)) { 411164410Ssyrinx case 2: 412164410Ssyrinx bridge_new_root(bif); 413164410Ssyrinx break; 414164410Ssyrinx case 1: 415164410Ssyrinx bridge_top_change(bif); 416164410Ssyrinx break; 417164410Ssyrinx case -1: 418164410Ssyrinx bridge_remove_bif(bif); 419164410Ssyrinx return (-1); 420164410Ssyrinx default: 421164410Ssyrinx break; 422164410Ssyrinx } 423164410Ssyrinx 424164410Ssyrinx /* 425164410Ssyrinx * The number of ports is accessible via SNMP - 426164410Ssyrinx * update the ports each time the bridge interface data 427164410Ssyrinx * is refreshed too. 428164410Ssyrinx */ 429164410Ssyrinx bif->num_ports = bridge_update_memif(bif); 430164410Ssyrinx bif->entry_age = time(NULL); 431164410Ssyrinx 432164410Ssyrinx return (1); 433164410Ssyrinx} 434164410Ssyrinx 435164410Ssyrinx/* 436164410Ssyrinx * Update all bridge interfaces' ports only - 437164410Ssyrinx * make sure each bridge interface exists first. 438164410Ssyrinx */ 439164410Ssyrinxvoid 440164410Ssyrinxbridge_update_all_ports(void) 441164410Ssyrinx{ 442164410Ssyrinx struct mibif *ifp; 443164410Ssyrinx struct bridge_if *bif, *t_bif; 444164410Ssyrinx 445164410Ssyrinx for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 446164410Ssyrinx t_bif = bridge_next_bif(bif); 447164410Ssyrinx 448164410Ssyrinx for (ifp = mib_first_if(); ifp != NULL; 449164410Ssyrinx ifp = mib_next_if(ifp)) 450164410Ssyrinx if (strcmp(ifp->name, bif->bif_name) == 0) 451164410Ssyrinx break; 452164410Ssyrinx 453164410Ssyrinx if (ifp != NULL) 454164410Ssyrinx bif->num_ports = bridge_update_memif(bif); 455164410Ssyrinx else /* Ops, we do not exist anymore. */ 456164410Ssyrinx bridge_remove_bif(bif); 457164410Ssyrinx } 458164410Ssyrinx 459164410Ssyrinx bridge_ports_update_listage(); 460164410Ssyrinx} 461164410Ssyrinx 462164410Ssyrinx/* 463164410Ssyrinx * Update all addresses only. 464164410Ssyrinx */ 465164410Ssyrinxvoid 466164410Ssyrinxbridge_update_all_addrs(void) 467164410Ssyrinx{ 468164410Ssyrinx struct mibif *ifp; 469164410Ssyrinx struct bridge_if *bif, *t_bif; 470164410Ssyrinx 471164410Ssyrinx for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 472164410Ssyrinx t_bif = bridge_next_bif(bif); 473164410Ssyrinx 474164410Ssyrinx for (ifp = mib_first_if(); ifp != NULL; 475164410Ssyrinx ifp = mib_next_if(ifp)) 476164410Ssyrinx if (strcmp(ifp->name, bif->bif_name) == 0) 477164410Ssyrinx break; 478164410Ssyrinx 479164410Ssyrinx if (ifp != NULL) 480164410Ssyrinx bif->num_addrs = bridge_update_addrs(bif); 481164410Ssyrinx else /* Ops, we don't exist anymore. */ 482164410Ssyrinx bridge_remove_bif(bif); 483164410Ssyrinx } 484164410Ssyrinx 485164410Ssyrinx bridge_addrs_update_listage(); 486164410Ssyrinx} 487164410Ssyrinx 488164410Ssyrinx/* 489164410Ssyrinx * Update only the bridge interfaces' data - skip addresses. 490164410Ssyrinx */ 491164410Ssyrinxvoid 492164410Ssyrinxbridge_update_all_ifs(void) 493164410Ssyrinx{ 494164410Ssyrinx struct bridge_if *bif, *t_bif; 495164410Ssyrinx 496164410Ssyrinx for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 497164410Ssyrinx t_bif = bridge_next_bif(bif); 498164410Ssyrinx bridge_update_bif(bif); 499164410Ssyrinx } 500164410Ssyrinx 501164410Ssyrinx bridge_ports_update_listage(); 502164410Ssyrinx bridge_list_age = time(NULL); 503164410Ssyrinx} 504164410Ssyrinx 505164410Ssyrinx/* 506164410Ssyrinx * Update all info we have for all bridges. 507164410Ssyrinx */ 508164410Ssyrinxvoid 509164410Ssyrinxbridge_update_all(void *arg __unused) 510164410Ssyrinx{ 511164410Ssyrinx struct bridge_if *bif, *t_bif; 512164410Ssyrinx 513164410Ssyrinx for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 514164410Ssyrinx t_bif = bridge_next_bif(bif); 515164410Ssyrinx if (bridge_update_bif(bif) <= 0) 516164410Ssyrinx continue; 517164410Ssyrinx 518164410Ssyrinx /* Update our learnt addresses. */ 519164410Ssyrinx bif->num_addrs = bridge_update_addrs(bif); 520164410Ssyrinx } 521164410Ssyrinx 522164410Ssyrinx bridge_list_age = time(NULL); 523164410Ssyrinx bridge_ports_update_listage(); 524164410Ssyrinx bridge_addrs_update_listage(); 525164410Ssyrinx} 526164410Ssyrinx 527164410Ssyrinx/* 528164410Ssyrinx * Callback for polling our last topology change time - 529164410Ssyrinx * check whether we are root or whether a TC was detected once every 530164410Ssyrinx * 30 seconds, so that we can send the newRoot and TopologyChange traps 531164410Ssyrinx * on time. The rest of the data is polled only once every 5 min. 532164410Ssyrinx */ 533164410Ssyrinxvoid 534164410Ssyrinxbridge_update_tc_time(void *arg __unused) 535164410Ssyrinx{ 536164410Ssyrinx struct bridge_if *bif; 537164410Ssyrinx struct mibif *ifp; 538164410Ssyrinx 539164410Ssyrinx TAILQ_FOREACH(bif, &bridge_ifs, b_if) { 540164410Ssyrinx /* Walk through the mibII interface list. */ 541164410Ssyrinx for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) 542164410Ssyrinx if (strcmp(ifp->name, bif->bif_name) == 0) 543164410Ssyrinx break; 544164410Ssyrinx 545164410Ssyrinx if (ifp == NULL) { 546164410Ssyrinx bridge_remove_bif(bif); 547164410Ssyrinx continue; 548164410Ssyrinx } 549164410Ssyrinx 550164410Ssyrinx switch (bridge_get_op_param(bif)) { 551164410Ssyrinx case 2: 552164410Ssyrinx bridge_new_root(bif); 553164410Ssyrinx break; 554164410Ssyrinx case 1: 555164410Ssyrinx bridge_top_change(bif); 556164410Ssyrinx break; 557164410Ssyrinx } 558164410Ssyrinx } 559164410Ssyrinx} 560164410Ssyrinx 561164410Ssyrinx/* 562164410Ssyrinx * Callback for handling new bridge interface creation. 563164410Ssyrinx */ 564164410Ssyrinxint 565164410Ssyrinxbridge_attach_newif(struct mibif *ifp) 566164410Ssyrinx{ 567165642Sbz u_char mac[ETHER_ADDR_LEN]; 568164410Ssyrinx struct bridge_if *bif; 569164410Ssyrinx 570164410Ssyrinx if (ifp->mib.ifmd_data.ifi_type != IFT_BRIDGE) 571164410Ssyrinx return (0); 572164410Ssyrinx 573164410Ssyrinx /* Make sure it does not exist in our list. */ 574164410Ssyrinx TAILQ_FOREACH(bif, &bridge_ifs, b_if) 575164410Ssyrinx if(strcmp(bif->bif_name, ifp->name) == 0) { 576164410Ssyrinx syslog(LOG_ERR, "bridge interface %s already " 577164410Ssyrinx "in list", bif->bif_name); 578164410Ssyrinx return (-1); 579164410Ssyrinx } 580164410Ssyrinx 581165642Sbz if (ifp->physaddr == NULL) { 582165642Sbz if (bridge_get_basemac(ifp->name, mac, sizeof(mac)) == NULL) { 583165642Sbz syslog(LOG_ERR, "bridge attach new %s failed - " 584165642Sbz "no bridge mac address", ifp->name); 585165642Sbz return (-1); 586165642Sbz } 587165642Sbz } else 588165642Sbz bcopy(ifp->physaddr, &mac, sizeof(mac)); 589164410Ssyrinx 590165642Sbz if ((bif = bridge_new_bif(ifp->name, ifp->sysindex, mac)) == NULL) 591164410Ssyrinx return (-1); 592164410Ssyrinx 593164410Ssyrinx if (ifp->mib.ifmd_flags & IFF_RUNNING) 594164410Ssyrinx bif->if_status = RowStatus_active; 595164410Ssyrinx else 596164410Ssyrinx bif->if_status = RowStatus_notInService; 597164410Ssyrinx 598164410Ssyrinx /* Skip sending notifications if the interface was just created. */ 599164410Ssyrinx if (bridge_getinfo_bif(bif) < 0 || 600164410Ssyrinx (bif->num_ports = bridge_getinfo_bif_ports(bif)) < 0 || 601164410Ssyrinx (bif->num_addrs = bridge_getinfo_bif_addrs(bif)) < 0) { 602164410Ssyrinx bridge_remove_bif(bif); 603164410Ssyrinx return (-1); 604164410Ssyrinx } 605164410Ssyrinx 606164410Ssyrinx /* Check whether we are the default bridge interface. */ 607164410Ssyrinx if (strcmp(ifp->name, bridge_get_default_name()) == 0) 608164410Ssyrinx bridge_set_default(bif); 609164410Ssyrinx 610164410Ssyrinx return (0); 611164410Ssyrinx} 612164410Ssyrinx 613164410Ssyrinxvoid 614164410Ssyrinxbridge_ifs_dump(void) 615164410Ssyrinx{ 616164410Ssyrinx struct bridge_if *bif; 617164410Ssyrinx 618164410Ssyrinx for (bif = bridge_first_bif(); bif != NULL; 619164410Ssyrinx bif = bridge_next_bif(bif)) { 620164410Ssyrinx syslog(LOG_ERR, "Bridge %s, index - %d", bif->bif_name, 621164410Ssyrinx bif->sysindex); 622164410Ssyrinx bridge_ports_dump(bif); 623164410Ssyrinx bridge_addrs_dump(bif); 624164410Ssyrinx } 625164410Ssyrinx} 626164410Ssyrinx 627164410Ssyrinx/* 628164410Ssyrinx * RFC4188 specifics. 629164410Ssyrinx */ 630164410Ssyrinxint 631164410Ssyrinxop_dot1d_base(struct snmp_context *ctx __unused, struct snmp_value *value, 632164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 633164410Ssyrinx{ 634164410Ssyrinx struct bridge_if *bif; 635164410Ssyrinx 636164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 637164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 638164410Ssyrinx 639164410Ssyrinx if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 640164410Ssyrinx bridge_update_bif(bif) <= 0) /* It was just deleted. */ 641164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 642164410Ssyrinx 643164410Ssyrinx switch (op) { 644164410Ssyrinx case SNMP_OP_GET: 645164410Ssyrinx switch (value->var.subs[sub - 1]) { 646164410Ssyrinx case LEAF_dot1dBaseBridgeAddress: 647165253Ssyrinx return (string_get(value, bif->br_addr.octet, 648165253Ssyrinx ETHER_ADDR_LEN)); 649164410Ssyrinx case LEAF_dot1dBaseNumPorts: 650164410Ssyrinx value->v.integer = bif->num_ports; 651165253Ssyrinx return (SNMP_ERR_NOERROR); 652164410Ssyrinx case LEAF_dot1dBaseType: 653164410Ssyrinx value->v.integer = bif->br_type; 654165253Ssyrinx return (SNMP_ERR_NOERROR); 655164410Ssyrinx } 656165253Ssyrinx abort(); 657164410Ssyrinx 658164410Ssyrinx case SNMP_OP_SET: 659165253Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 660164410Ssyrinx 661164410Ssyrinx case SNMP_OP_GETNEXT: 662164410Ssyrinx case SNMP_OP_ROLLBACK: 663164410Ssyrinx case SNMP_OP_COMMIT: 664165253Ssyrinx break; 665164410Ssyrinx } 666164410Ssyrinx 667165253Ssyrinx abort(); 668164410Ssyrinx} 669164410Ssyrinx 670164410Ssyrinxint 671165253Ssyrinxop_dot1d_stp(struct snmp_context *ctx, struct snmp_value *val, uint sub, 672165253Ssyrinx uint iidx __unused, enum snmp_op op) 673164410Ssyrinx{ 674164410Ssyrinx struct bridge_if *bif; 675164410Ssyrinx 676164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 677164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 678164410Ssyrinx 679164410Ssyrinx if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 680164410Ssyrinx bridge_update_bif(bif) <= 0) /* It was just deleted. */ 681164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 682164410Ssyrinx 683164410Ssyrinx switch (op) { 684164410Ssyrinx case SNMP_OP_GET: 685165253Ssyrinx switch (val->var.subs[sub - 1]) { 686164410Ssyrinx case LEAF_dot1dStpProtocolSpecification: 687165253Ssyrinx val->v.integer = bif->prot_spec; 688165253Ssyrinx return (SNMP_ERR_NOERROR); 689164410Ssyrinx 690164410Ssyrinx case LEAF_dot1dStpPriority: 691165253Ssyrinx val->v.integer = bif->priority; 692165253Ssyrinx return (SNMP_ERR_NOERROR); 693164410Ssyrinx 694164410Ssyrinx case LEAF_dot1dStpTimeSinceTopologyChange: 695164410Ssyrinx if (bridge_get_time_since_tc(bif, 696165253Ssyrinx &(val->v.uint32)) < 0) 697164410Ssyrinx return (SNMP_ERR_GENERR); 698165253Ssyrinx return (SNMP_ERR_NOERROR); 699164410Ssyrinx 700164410Ssyrinx case LEAF_dot1dStpTopChanges: 701165253Ssyrinx val->v.uint32 = bif->top_changes; 702165253Ssyrinx return (SNMP_ERR_NOERROR); 703164410Ssyrinx 704164410Ssyrinx case LEAF_dot1dStpDesignatedRoot: 705165253Ssyrinx return (string_get(val, bif->design_root, 706164410Ssyrinx SNMP_BRIDGE_ID_LEN)); 707164410Ssyrinx 708164410Ssyrinx case LEAF_dot1dStpRootCost: 709165253Ssyrinx val->v.integer = bif->root_cost; 710165253Ssyrinx return (SNMP_ERR_NOERROR); 711164410Ssyrinx 712164410Ssyrinx case LEAF_dot1dStpRootPort: 713165253Ssyrinx val->v.integer = bif->root_port; 714165253Ssyrinx return (SNMP_ERR_NOERROR); 715164410Ssyrinx 716164410Ssyrinx case LEAF_dot1dStpMaxAge: 717165253Ssyrinx val->v.integer = bif->max_age; 718165253Ssyrinx return (SNMP_ERR_NOERROR); 719164410Ssyrinx 720164410Ssyrinx case LEAF_dot1dStpHelloTime: 721165253Ssyrinx val->v.integer = bif->hello_time; 722165253Ssyrinx return (SNMP_ERR_NOERROR); 723164410Ssyrinx 724164410Ssyrinx case LEAF_dot1dStpHoldTime: 725165253Ssyrinx val->v.integer = bif->hold_time; 726165253Ssyrinx return (SNMP_ERR_NOERROR); 727164410Ssyrinx 728164410Ssyrinx case LEAF_dot1dStpForwardDelay: 729165253Ssyrinx val->v.integer = bif->fwd_delay; 730165253Ssyrinx return (SNMP_ERR_NOERROR); 731164410Ssyrinx 732164410Ssyrinx case LEAF_dot1dStpBridgeMaxAge: 733165253Ssyrinx val->v.integer = bif->bridge_max_age; 734165253Ssyrinx return (SNMP_ERR_NOERROR); 735164410Ssyrinx 736164410Ssyrinx case LEAF_dot1dStpBridgeHelloTime: 737165253Ssyrinx val->v.integer = bif->bridge_hello_time; 738165253Ssyrinx return (SNMP_ERR_NOERROR); 739164410Ssyrinx 740164410Ssyrinx case LEAF_dot1dStpBridgeForwardDelay: 741165253Ssyrinx val->v.integer = bif->bridge_fwd_delay; 742165253Ssyrinx return (SNMP_ERR_NOERROR); 743165253Ssyrinx 744164997Ssyrinx case LEAF_dot1dStpVersion: 745165253Ssyrinx val->v.integer = bif->stp_version; 746165253Ssyrinx return (SNMP_ERR_NOERROR); 747165253Ssyrinx 748164997Ssyrinx case LEAF_dot1dStpTxHoldCount: 749165253Ssyrinx val->v.integer = bif->tx_hold_count; 750165253Ssyrinx return (SNMP_ERR_NOERROR); 751164410Ssyrinx } 752165253Ssyrinx abort(); 753164410Ssyrinx 754164410Ssyrinx case SNMP_OP_GETNEXT: 755164410Ssyrinx abort(); 756164410Ssyrinx 757164410Ssyrinx case SNMP_OP_SET: 758165253Ssyrinx switch (val->var.subs[sub - 1]) { 759164410Ssyrinx case LEAF_dot1dStpPriority: 760165253Ssyrinx if (val->v.integer > SNMP_BRIDGE_MAX_PRIORITY || 761165253Ssyrinx val->v.integer % 4096 != 0) 762165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 763165253Ssyrinx 764164410Ssyrinx ctx->scratch->int1 = bif->priority; 765165253Ssyrinx if (bridge_set_priority(bif, val->v.integer) < 0) 766165253Ssyrinx return (SNMP_ERR_GENERR); 767165253Ssyrinx return (SNMP_ERR_NOERROR); 768164410Ssyrinx 769164410Ssyrinx case LEAF_dot1dStpBridgeMaxAge: 770165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_MAGE || 771165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_MAGE) 772165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 773165253Ssyrinx 774164410Ssyrinx ctx->scratch->int1 = bif->bridge_max_age; 775165253Ssyrinx if (bridge_set_maxage(bif, val->v.integer) < 0) 776165253Ssyrinx return (SNMP_ERR_GENERR); 777165253Ssyrinx return (SNMP_ERR_NOERROR); 778164410Ssyrinx 779164410Ssyrinx case LEAF_dot1dStpBridgeHelloTime: 780165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_HTIME || 781165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_HTIME) 782165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 783165253Ssyrinx 784164410Ssyrinx ctx->scratch->int1 = bif->bridge_hello_time; 785165253Ssyrinx if (bridge_set_hello_time(bif, val->v.integer) < 0) 786165253Ssyrinx return (SNMP_ERR_GENERR); 787165253Ssyrinx return (SNMP_ERR_NOERROR); 788164410Ssyrinx 789164410Ssyrinx case LEAF_dot1dStpBridgeForwardDelay: 790165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_FDELAY || 791165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_FDELAY) 792165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 793165253Ssyrinx 794164410Ssyrinx ctx->scratch->int1 = bif->bridge_fwd_delay; 795165253Ssyrinx if (bridge_set_forward_delay(bif, val->v.integer) < 0) 796165253Ssyrinx return (SNMP_ERR_GENERR); 797165253Ssyrinx return (SNMP_ERR_NOERROR); 798164410Ssyrinx 799164997Ssyrinx case LEAF_dot1dStpVersion: 800165253Ssyrinx if (val->v.integer != dot1dStpVersion_stpCompatible && 801165253Ssyrinx val->v.integer != dot1dStpVersion_rstp) 802165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 803165253Ssyrinx 804164997Ssyrinx ctx->scratch->int1 = bif->stp_version; 805165253Ssyrinx if (bridge_set_stp_version(bif, val->v.integer) < 0) 806165253Ssyrinx return (SNMP_ERR_GENERR); 807165253Ssyrinx return (SNMP_ERR_NOERROR); 808164997Ssyrinx 809164997Ssyrinx case LEAF_dot1dStpTxHoldCount: 810165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_TXHC || 811165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_TXHC) 812165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 813165253Ssyrinx 814164997Ssyrinx ctx->scratch->int1 = bif->tx_hold_count; 815165253Ssyrinx if (bridge_set_tx_hold_count(bif, val->v.integer) < 0) 816165253Ssyrinx return (SNMP_ERR_GENERR); 817165253Ssyrinx return (SNMP_ERR_NOERROR); 818164997Ssyrinx 819164410Ssyrinx case LEAF_dot1dStpProtocolSpecification: 820164410Ssyrinx case LEAF_dot1dStpTimeSinceTopologyChange: 821164410Ssyrinx case LEAF_dot1dStpTopChanges: 822164410Ssyrinx case LEAF_dot1dStpDesignatedRoot: 823164410Ssyrinx case LEAF_dot1dStpRootCost: 824164410Ssyrinx case LEAF_dot1dStpRootPort: 825164410Ssyrinx case LEAF_dot1dStpMaxAge: 826164410Ssyrinx case LEAF_dot1dStpHelloTime: 827164410Ssyrinx case LEAF_dot1dStpHoldTime: 828164410Ssyrinx case LEAF_dot1dStpForwardDelay: 829164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 830164410Ssyrinx } 831165253Ssyrinx abort(); 832164410Ssyrinx 833164410Ssyrinx case SNMP_OP_ROLLBACK: 834165253Ssyrinx switch (val->var.subs[sub - 1]) { 835164410Ssyrinx case LEAF_dot1dStpPriority: 836164997Ssyrinx bridge_set_priority(bif, ctx->scratch->int1); 837164410Ssyrinx break; 838164410Ssyrinx case LEAF_dot1dStpBridgeMaxAge: 839164997Ssyrinx bridge_set_maxage(bif, ctx->scratch->int1); 840164410Ssyrinx break; 841164410Ssyrinx case LEAF_dot1dStpBridgeHelloTime: 842164997Ssyrinx bridge_set_hello_time(bif, ctx->scratch->int1); 843164410Ssyrinx break; 844164410Ssyrinx case LEAF_dot1dStpBridgeForwardDelay: 845164997Ssyrinx bridge_set_forward_delay(bif, ctx->scratch->int1); 846164410Ssyrinx break; 847164997Ssyrinx case LEAF_dot1dStpVersion: 848164997Ssyrinx bridge_set_stp_version(bif, ctx->scratch->int1); 849164997Ssyrinx break; 850164997Ssyrinx case LEAF_dot1dStpTxHoldCount: 851164997Ssyrinx bridge_set_tx_hold_count(bif, ctx->scratch->int1); 852164997Ssyrinx break; 853164410Ssyrinx } 854164410Ssyrinx return (SNMP_ERR_NOERROR); 855164410Ssyrinx 856164410Ssyrinx case SNMP_OP_COMMIT: 857164410Ssyrinx return (SNMP_ERR_NOERROR); 858164410Ssyrinx } 859164410Ssyrinx 860165253Ssyrinx abort(); 861164410Ssyrinx} 862164410Ssyrinx 863164410Ssyrinxint 864164410Ssyrinxop_dot1d_tp(struct snmp_context *ctx, struct snmp_value *value, 865164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 866164410Ssyrinx{ 867164410Ssyrinx struct bridge_if *bif; 868164410Ssyrinx 869164410Ssyrinx if ((bif = bridge_get_default()) == NULL) 870164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 871164410Ssyrinx 872164410Ssyrinx if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 873164410Ssyrinx bridge_update_bif(bif) <= 0) /* It was just deleted. */ 874164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 875164410Ssyrinx 876164410Ssyrinx switch (op) { 877164410Ssyrinx case SNMP_OP_GET: 878164410Ssyrinx switch (value->var.subs[sub - 1]) { 879164410Ssyrinx case LEAF_dot1dTpLearnedEntryDiscards: 880164410Ssyrinx value->v.uint32 = bif->lrnt_drops; 881165253Ssyrinx return (SNMP_ERR_NOERROR); 882164410Ssyrinx case LEAF_dot1dTpAgingTime: 883164410Ssyrinx value->v.integer = bif->age_time; 884165253Ssyrinx return (SNMP_ERR_NOERROR); 885164410Ssyrinx } 886165253Ssyrinx abort(); 887164410Ssyrinx 888164410Ssyrinx case SNMP_OP_GETNEXT: 889164410Ssyrinx abort(); 890164410Ssyrinx 891164410Ssyrinx case SNMP_OP_SET: 892165253Ssyrinx switch (value->var.subs[sub - 1]) { 893165253Ssyrinx case LEAF_dot1dTpLearnedEntryDiscards: 894165253Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 895165253Ssyrinx 896165253Ssyrinx case LEAF_dot1dTpAgingTime: 897165253Ssyrinx if (value->v.integer < SNMP_BRIDGE_MIN_AGE_TIME || 898165253Ssyrinx value->v.integer > SNMP_BRIDGE_MAX_AGE_TIME) 899165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 900165253Ssyrinx 901165253Ssyrinx ctx->scratch->int1 = bif->age_time; 902165253Ssyrinx if (bridge_set_aging_time(bif, value->v.integer) < 0) 903165253Ssyrinx return (SNMP_ERR_GENERR); 904165253Ssyrinx return (SNMP_ERR_NOERROR); 905164410Ssyrinx } 906165253Ssyrinx abort(); 907164410Ssyrinx 908164410Ssyrinx case SNMP_OP_ROLLBACK: 909164410Ssyrinx if (value->var.subs[sub - 1] == LEAF_dot1dTpAgingTime) 910164997Ssyrinx bridge_set_aging_time(bif, ctx->scratch->int1); 911164410Ssyrinx return (SNMP_ERR_NOERROR); 912164410Ssyrinx 913164410Ssyrinx case SNMP_OP_COMMIT: 914164410Ssyrinx return (SNMP_ERR_NOERROR); 915164410Ssyrinx } 916164410Ssyrinx 917165253Ssyrinx abort(); 918164410Ssyrinx} 919164410Ssyrinx 920164410Ssyrinx/* 921164410Ssyrinx * Private BEGEMOT-BRIDGE-MIB specifics. 922164410Ssyrinx */ 923164410Ssyrinx 924164410Ssyrinx/* 925164410Ssyrinx * Get the bridge name from an OID index. 926164410Ssyrinx */ 927164410Ssyrinxstatic char * 928164410Ssyrinxbridge_name_index_get(const struct asn_oid *oid, uint sub, char *b_name) 929164410Ssyrinx{ 930164410Ssyrinx uint i; 931164410Ssyrinx 932164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 933164410Ssyrinx return (NULL); 934164410Ssyrinx 935164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 936164410Ssyrinx b_name[i] = oid->subs[sub + i + 1]; 937164410Ssyrinx b_name[i] = '\0'; 938164410Ssyrinx 939164410Ssyrinx return (b_name); 940164410Ssyrinx} 941164410Ssyrinx 942164410Ssyrinxstatic void 943164410Ssyrinxbridge_if_index_append(struct asn_oid *oid, uint sub, 944164410Ssyrinx const struct bridge_if *bif) 945164410Ssyrinx{ 946164410Ssyrinx uint i; 947164410Ssyrinx 948164410Ssyrinx oid->len = sub + strlen(bif->bif_name) + 1; 949164410Ssyrinx oid->subs[sub] = strlen(bif->bif_name); 950164410Ssyrinx 951164410Ssyrinx for (i = 1; i <= strlen(bif->bif_name); i++) 952164410Ssyrinx oid->subs[sub + i] = bif->bif_name[i - 1]; 953164410Ssyrinx} 954164410Ssyrinx 955164410Ssyrinxstatic struct bridge_if * 956164410Ssyrinxbridge_if_index_get(const struct asn_oid *oid, uint sub) 957164410Ssyrinx{ 958164410Ssyrinx uint i; 959164410Ssyrinx char bif_name[IFNAMSIZ]; 960164410Ssyrinx 961164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 962164410Ssyrinx return (NULL); 963164410Ssyrinx 964164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 965164410Ssyrinx bif_name[i] = oid->subs[sub + i + 1]; 966164410Ssyrinx bif_name[i] = '\0'; 967164410Ssyrinx 968164410Ssyrinx return (bridge_if_find_ifname(bif_name)); 969164410Ssyrinx} 970164410Ssyrinx 971164410Ssyrinxstatic struct bridge_if * 972164410Ssyrinxbridge_if_index_getnext(const struct asn_oid *oid, uint sub) 973164410Ssyrinx{ 974164410Ssyrinx uint i; 975164410Ssyrinx char bif_name[IFNAMSIZ]; 976164410Ssyrinx struct bridge_if *bif; 977164410Ssyrinx 978164410Ssyrinx if (oid->len - sub == 0) 979164410Ssyrinx return (bridge_first_bif()); 980164410Ssyrinx 981164410Ssyrinx if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 982164410Ssyrinx return (NULL); 983164410Ssyrinx 984164410Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 985164410Ssyrinx bif_name[i] = oid->subs[sub + i + 1]; 986164410Ssyrinx bif_name[i] = '\0'; 987164410Ssyrinx 988164410Ssyrinx if ((bif = bridge_if_find_ifname(bif_name)) == NULL) 989164410Ssyrinx return (NULL); 990164410Ssyrinx 991164410Ssyrinx return (bridge_next_bif(bif)); 992164410Ssyrinx} 993164410Ssyrinx 994164410Ssyrinxstatic int 995164410Ssyrinxbridge_set_if_status(struct snmp_context *ctx, 996164410Ssyrinx struct snmp_value *val, uint sub) 997164410Ssyrinx{ 998164410Ssyrinx struct bridge_if *bif; 999164410Ssyrinx char bif_name[IFNAMSIZ]; 1000164410Ssyrinx 1001164410Ssyrinx bif = bridge_if_index_get(&val->var, sub); 1002164410Ssyrinx 1003164410Ssyrinx switch (val->v.integer) { 1004164410Ssyrinx case RowStatus_active: 1005164410Ssyrinx if (bif == NULL) 1006164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1007164410Ssyrinx 1008164410Ssyrinx ctx->scratch->int1 = bif->if_status; 1009164410Ssyrinx 1010164410Ssyrinx switch (bif->if_status) { 1011164410Ssyrinx case RowStatus_active: 1012164410Ssyrinx return (SNMP_ERR_NOERROR); 1013164410Ssyrinx case RowStatus_notInService: 1014164410Ssyrinx if (bridge_set_if_up(bif->bif_name, 1) < 0) 1015164410Ssyrinx return (SNMP_ERR_GENERR); 1016164410Ssyrinx return (SNMP_ERR_NOERROR); 1017164410Ssyrinx default: 1018164410Ssyrinx break; 1019164410Ssyrinx } 1020164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1021164410Ssyrinx 1022164410Ssyrinx case RowStatus_notInService: 1023164410Ssyrinx if (bif == NULL) 1024164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1025164410Ssyrinx 1026164410Ssyrinx ctx->scratch->int1 = bif->if_status; 1027164410Ssyrinx 1028164410Ssyrinx switch (bif->if_status) { 1029164410Ssyrinx case RowStatus_active: 1030164410Ssyrinx if (bridge_set_if_up(bif->bif_name, 1) < 0) 1031164410Ssyrinx return (SNMP_ERR_GENERR); 1032164410Ssyrinx return (SNMP_ERR_NOERROR); 1033164410Ssyrinx case RowStatus_notInService: 1034164410Ssyrinx return (SNMP_ERR_NOERROR); 1035164410Ssyrinx default: 1036164410Ssyrinx break; 1037164410Ssyrinx } 1038164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1039164410Ssyrinx 1040164410Ssyrinx case RowStatus_notReady: 1041164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1042164410Ssyrinx 1043164410Ssyrinx case RowStatus_createAndGo: 1044164410Ssyrinx if (bif != NULL) 1045164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1046164410Ssyrinx 1047164410Ssyrinx ctx->scratch->int1 = RowStatus_destroy; 1048164410Ssyrinx 1049164410Ssyrinx if (bridge_name_index_get(&val->var, sub, bif_name) == NULL) 1050164410Ssyrinx return (SNMP_ERR_BADVALUE); 1051164410Ssyrinx if (bridge_if_create(bif_name, 1) < 0) 1052164410Ssyrinx return (SNMP_ERR_GENERR); 1053164410Ssyrinx return (SNMP_ERR_NOERROR); 1054164410Ssyrinx 1055164410Ssyrinx case RowStatus_createAndWait: 1056164410Ssyrinx if (bif != NULL) 1057164410Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1058164410Ssyrinx 1059164410Ssyrinx if (bridge_name_index_get(&val->var, sub, bif_name) == NULL) 1060164410Ssyrinx return (SNMP_ERR_BADVALUE); 1061164410Ssyrinx 1062164410Ssyrinx ctx->scratch->int1 = RowStatus_destroy; 1063164410Ssyrinx 1064164410Ssyrinx if (bridge_if_create(bif_name, 0) < 0) 1065164410Ssyrinx return (SNMP_ERR_GENERR); 1066164410Ssyrinx return (SNMP_ERR_NOERROR); 1067164410Ssyrinx 1068164410Ssyrinx case RowStatus_destroy: 1069164410Ssyrinx if (bif == NULL) 1070164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1071164410Ssyrinx 1072164410Ssyrinx ctx->scratch->int1 = bif->if_status; 1073164410Ssyrinx bif->if_status = RowStatus_destroy; 1074164410Ssyrinx } 1075164410Ssyrinx 1076164410Ssyrinx return (SNMP_ERR_NOERROR); 1077164410Ssyrinx} 1078164410Ssyrinx 1079164410Ssyrinxstatic int 1080164410Ssyrinxbridge_rollback_if_status(struct snmp_context *ctx, 1081164410Ssyrinx struct snmp_value *val, uint sub) 1082164410Ssyrinx{ 1083164410Ssyrinx struct bridge_if *bif; 1084164410Ssyrinx 1085164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1086164410Ssyrinx return (SNMP_ERR_GENERR); 1087164410Ssyrinx 1088164410Ssyrinx switch (ctx->scratch->int1) { 1089164410Ssyrinx case RowStatus_destroy: 1090164410Ssyrinx bridge_if_destroy(bif); 1091164410Ssyrinx return (SNMP_ERR_NOERROR); 1092164410Ssyrinx 1093164410Ssyrinx case RowStatus_notInService: 1094164410Ssyrinx if (bif->if_status != ctx->scratch->int1) 1095164410Ssyrinx bridge_set_if_up(bif->bif_name, 0); 1096164410Ssyrinx bif->if_status = RowStatus_notInService; 1097164410Ssyrinx return (SNMP_ERR_NOERROR); 1098164410Ssyrinx 1099164410Ssyrinx case RowStatus_active: 1100164410Ssyrinx if (bif->if_status != ctx->scratch->int1) 1101164410Ssyrinx bridge_set_if_up(bif->bif_name, 1); 1102164410Ssyrinx bif->if_status = RowStatus_active; 1103164410Ssyrinx return (SNMP_ERR_NOERROR); 1104164410Ssyrinx } 1105164410Ssyrinx 1106164410Ssyrinx abort(); 1107164410Ssyrinx} 1108164410Ssyrinx 1109164410Ssyrinxstatic int 1110164410Ssyrinxbridge_commit_if_status(struct snmp_value *val, uint sub) 1111164410Ssyrinx{ 1112164410Ssyrinx struct bridge_if *bif; 1113164410Ssyrinx 1114164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1115164410Ssyrinx return (SNMP_ERR_GENERR); 1116164410Ssyrinx 1117164410Ssyrinx if (bif->if_status == RowStatus_destroy && 1118164410Ssyrinx bridge_if_destroy(bif) < 0) 1119164410Ssyrinx return (SNMP_ERR_COMMIT_FAILED); 1120164410Ssyrinx 1121164410Ssyrinx return (SNMP_ERR_NOERROR); 1122164410Ssyrinx} 1123164410Ssyrinx 1124164410Ssyrinxint 1125164410Ssyrinxop_begemot_base_bridge(struct snmp_context *ctx, struct snmp_value *val, 1126164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1127164410Ssyrinx{ 1128165046Ssyrinx struct bridge_if *bif; 1129164410Ssyrinx 1130164410Ssyrinx if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1131164410Ssyrinx bridge_update_all_ifs(); 1132164410Ssyrinx 1133164410Ssyrinx switch (op) { 1134164410Ssyrinx case SNMP_OP_GET: 1135164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1136164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1137165253Ssyrinx goto get; 1138164410Ssyrinx 1139164410Ssyrinx case SNMP_OP_GETNEXT: 1140164410Ssyrinx if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1141164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1142164410Ssyrinx bridge_if_index_append(&val->var, sub, bif); 1143165253Ssyrinx goto get; 1144164410Ssyrinx 1145164410Ssyrinx case SNMP_OP_SET: 1146164410Ssyrinx switch (val->var.subs[sub - 1]) { 1147164410Ssyrinx case LEAF_begemotBridgeBaseStatus: 1148164410Ssyrinx return (bridge_set_if_status(ctx, val, sub)); 1149164410Ssyrinx case LEAF_begemotBridgeBaseName: 1150164410Ssyrinx case LEAF_begemotBridgeBaseAddress: 1151164410Ssyrinx case LEAF_begemotBridgeBaseNumPorts: 1152164410Ssyrinx case LEAF_begemotBridgeBaseType: 1153164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1154164410Ssyrinx } 1155164410Ssyrinx abort(); 1156164410Ssyrinx 1157164410Ssyrinx case SNMP_OP_ROLLBACK: 1158164410Ssyrinx return (bridge_rollback_if_status(ctx, val, sub)); 1159165046Ssyrinx 1160164410Ssyrinx case SNMP_OP_COMMIT: 1161164410Ssyrinx return (bridge_commit_if_status(val, sub)); 1162164410Ssyrinx } 1163165253Ssyrinx abort(); 1164164410Ssyrinx 1165165253Ssyrinxget: 1166164410Ssyrinx switch (val->var.subs[sub - 1]) { 1167164410Ssyrinx case LEAF_begemotBridgeBaseName: 1168165253Ssyrinx return (string_get(val, bif->bif_name, -1)); 1169164410Ssyrinx 1170164410Ssyrinx case LEAF_begemotBridgeBaseAddress: 1171165253Ssyrinx return (string_get(val, bif->br_addr.octet, ETHER_ADDR_LEN)); 1172164410Ssyrinx 1173164410Ssyrinx case LEAF_begemotBridgeBaseNumPorts: 1174164410Ssyrinx val->v.integer = bif->num_ports; 1175165253Ssyrinx return (SNMP_ERR_NOERROR); 1176164410Ssyrinx 1177164410Ssyrinx case LEAF_begemotBridgeBaseType: 1178164410Ssyrinx val->v.integer = bif->br_type; 1179165253Ssyrinx return (SNMP_ERR_NOERROR); 1180164410Ssyrinx 1181164410Ssyrinx case LEAF_begemotBridgeBaseStatus: 1182164410Ssyrinx val->v.integer = bif->if_status; 1183165253Ssyrinx return (SNMP_ERR_NOERROR); 1184164410Ssyrinx } 1185164410Ssyrinx 1186165253Ssyrinx abort(); 1187164410Ssyrinx} 1188164410Ssyrinx 1189164410Ssyrinxint 1190164410Ssyrinxop_begemot_stp(struct snmp_context *ctx, struct snmp_value *val, 1191164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1192164410Ssyrinx{ 1193165046Ssyrinx struct bridge_if *bif; 1194164410Ssyrinx 1195164410Ssyrinx if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1196164410Ssyrinx bridge_update_all_ifs(); 1197164410Ssyrinx 1198164410Ssyrinx switch (op) { 1199164410Ssyrinx case SNMP_OP_GET: 1200164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1201164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1202165253Ssyrinx goto get; 1203164410Ssyrinx 1204164410Ssyrinx case SNMP_OP_GETNEXT: 1205164410Ssyrinx if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1206164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1207164410Ssyrinx bridge_if_index_append(&val->var, sub, bif); 1208165253Ssyrinx goto get; 1209164410Ssyrinx 1210164410Ssyrinx case SNMP_OP_SET: 1211164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1212164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1213164410Ssyrinx 1214164410Ssyrinx switch (val->var.subs[sub - 1]) { 1215164410Ssyrinx case LEAF_begemotBridgeStpPriority: 1216165253Ssyrinx if (val->v.integer > SNMP_BRIDGE_MAX_PRIORITY || 1217165253Ssyrinx val->v.integer % 4096 != 0) 1218165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1219165253Ssyrinx 1220164410Ssyrinx ctx->scratch->int1 = bif->priority; 1221165253Ssyrinx if (bridge_set_priority(bif, val->v.integer) < 0) 1222165253Ssyrinx return (SNMP_ERR_GENERR); 1223165253Ssyrinx return (SNMP_ERR_NOERROR); 1224164410Ssyrinx 1225164410Ssyrinx case LEAF_begemotBridgeStpBridgeMaxAge: 1226165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_MAGE || 1227165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_MAGE) 1228165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1229165253Ssyrinx 1230164410Ssyrinx ctx->scratch->int1 = bif->bridge_max_age; 1231165253Ssyrinx if (bridge_set_maxage(bif, val->v.integer) < 0) 1232165253Ssyrinx return (SNMP_ERR_GENERR); 1233165253Ssyrinx return (SNMP_ERR_NOERROR); 1234164410Ssyrinx 1235164410Ssyrinx case LEAF_begemotBridgeStpBridgeHelloTime: 1236165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_HTIME || 1237165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_HTIME) 1238165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1239165253Ssyrinx 1240164410Ssyrinx ctx->scratch->int1 = bif->bridge_hello_time; 1241165253Ssyrinx if (bridge_set_hello_time(bif, val->v.integer) < 0) 1242165253Ssyrinx return (SNMP_ERR_GENERR); 1243165253Ssyrinx return (SNMP_ERR_NOERROR); 1244164410Ssyrinx 1245164410Ssyrinx case LEAF_begemotBridgeStpBridgeForwardDelay: 1246165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_FDELAY || 1247165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_FDELAY) 1248165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1249165253Ssyrinx 1250164410Ssyrinx ctx->scratch->int1 = bif->bridge_fwd_delay; 1251165253Ssyrinx if (bridge_set_forward_delay(bif, val->v.integer) < 0) 1252165253Ssyrinx return (SNMP_ERR_GENERR); 1253165253Ssyrinx return (SNMP_ERR_NOERROR); 1254164410Ssyrinx 1255164997Ssyrinx case LEAF_begemotBridgeStpVersion: 1256165253Ssyrinx if (val->v.integer != 1257165253Ssyrinx begemotBridgeStpVersion_stpCompatible && 1258165253Ssyrinx val->v.integer != begemotBridgeStpVersion_rstp) 1259165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1260165253Ssyrinx 1261164997Ssyrinx ctx->scratch->int1 = bif->stp_version; 1262165253Ssyrinx if (bridge_set_stp_version(bif, val->v.integer) < 0) 1263165253Ssyrinx return (SNMP_ERR_GENERR); 1264165253Ssyrinx return (SNMP_ERR_NOERROR); 1265164997Ssyrinx 1266164997Ssyrinx case LEAF_begemotBridgeStpTxHoldCount: 1267165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_TXHC || 1268165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_TXHC) 1269165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1270165253Ssyrinx 1271164997Ssyrinx ctx->scratch->int1 = bif->tx_hold_count; 1272165253Ssyrinx if (bridge_set_tx_hold_count(bif, val->v.integer) < 0) 1273165253Ssyrinx return (SNMP_ERR_GENERR); 1274165253Ssyrinx return (SNMP_ERR_NOERROR); 1275164997Ssyrinx 1276164410Ssyrinx case LEAF_begemotBridgeStpProtocolSpecification: 1277164410Ssyrinx case LEAF_begemotBridgeStpTimeSinceTopologyChange: 1278164410Ssyrinx case LEAF_begemotBridgeStpTopChanges: 1279164410Ssyrinx case LEAF_begemotBridgeStpDesignatedRoot: 1280164410Ssyrinx case LEAF_begemotBridgeStpRootCost: 1281164410Ssyrinx case LEAF_begemotBridgeStpRootPort: 1282164410Ssyrinx case LEAF_begemotBridgeStpMaxAge: 1283164410Ssyrinx case LEAF_begemotBridgeStpHelloTime: 1284164410Ssyrinx case LEAF_begemotBridgeStpHoldTime: 1285164410Ssyrinx case LEAF_begemotBridgeStpForwardDelay: 1286164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1287164410Ssyrinx } 1288165253Ssyrinx abort(); 1289164410Ssyrinx 1290164410Ssyrinx case SNMP_OP_ROLLBACK: 1291164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1292164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1293164410Ssyrinx 1294164410Ssyrinx switch (val->var.subs[sub - 1]) { 1295164410Ssyrinx case LEAF_begemotBridgeStpPriority: 1296164410Ssyrinx bridge_set_priority(bif, ctx->scratch->int1); 1297164410Ssyrinx break; 1298164410Ssyrinx 1299164410Ssyrinx case LEAF_begemotBridgeStpBridgeMaxAge: 1300164410Ssyrinx bridge_set_maxage(bif, ctx->scratch->int1); 1301164410Ssyrinx break; 1302164410Ssyrinx 1303164410Ssyrinx case LEAF_begemotBridgeStpBridgeHelloTime: 1304164410Ssyrinx bridge_set_hello_time(bif, ctx->scratch->int1); 1305164410Ssyrinx break; 1306164410Ssyrinx 1307164410Ssyrinx case LEAF_begemotBridgeStpBridgeForwardDelay: 1308164410Ssyrinx bridge_set_forward_delay(bif, ctx->scratch->int1); 1309164410Ssyrinx break; 1310164997Ssyrinx 1311164997Ssyrinx case LEAF_begemotBridgeStpVersion: 1312164997Ssyrinx bridge_set_stp_version(bif, ctx->scratch->int1); 1313164997Ssyrinx break; 1314164997Ssyrinx 1315164997Ssyrinx case LEAF_begemotBridgeStpTxHoldCount: 1316164997Ssyrinx bridge_set_tx_hold_count(bif, ctx->scratch->int1); 1317164997Ssyrinx break; 1318164410Ssyrinx } 1319164410Ssyrinx return (SNMP_ERR_NOERROR); 1320164410Ssyrinx 1321164410Ssyrinx case SNMP_OP_COMMIT: 1322164410Ssyrinx return (SNMP_ERR_NOERROR); 1323164410Ssyrinx } 1324165253Ssyrinx abort(); 1325164410Ssyrinx 1326165253Ssyrinxget: 1327164410Ssyrinx switch (val->var.subs[sub - 1]) { 1328164410Ssyrinx case LEAF_begemotBridgeStpProtocolSpecification: 1329164410Ssyrinx val->v.integer = bif->prot_spec; 1330165253Ssyrinx return (SNMP_ERR_NOERROR); 1331164410Ssyrinx 1332164410Ssyrinx case LEAF_begemotBridgeStpPriority: 1333164410Ssyrinx val->v.integer = bif->priority; 1334165253Ssyrinx return (SNMP_ERR_NOERROR); 1335164410Ssyrinx 1336164410Ssyrinx case LEAF_begemotBridgeStpTimeSinceTopologyChange: 1337164410Ssyrinx if (bridge_get_time_since_tc(bif, &(val->v.uint32)) < 0) 1338164410Ssyrinx return (SNMP_ERR_GENERR); 1339165253Ssyrinx return (SNMP_ERR_NOERROR); 1340164410Ssyrinx 1341164410Ssyrinx case LEAF_begemotBridgeStpTopChanges: 1342164410Ssyrinx val->v.uint32 = bif->top_changes; 1343165253Ssyrinx return (SNMP_ERR_NOERROR); 1344164410Ssyrinx 1345164410Ssyrinx case LEAF_begemotBridgeStpDesignatedRoot: 1346165253Ssyrinx return (string_get(val, bif->design_root, SNMP_BRIDGE_ID_LEN)); 1347164410Ssyrinx 1348164410Ssyrinx case LEAF_begemotBridgeStpRootCost: 1349164410Ssyrinx val->v.integer = bif->root_cost; 1350165253Ssyrinx return (SNMP_ERR_NOERROR); 1351164410Ssyrinx 1352164410Ssyrinx case LEAF_begemotBridgeStpRootPort: 1353164410Ssyrinx val->v.integer = bif->root_port; 1354165253Ssyrinx return (SNMP_ERR_NOERROR); 1355164410Ssyrinx 1356164410Ssyrinx case LEAF_begemotBridgeStpMaxAge: 1357164410Ssyrinx val->v.integer = bif->max_age; 1358165253Ssyrinx return (SNMP_ERR_NOERROR); 1359164410Ssyrinx 1360164410Ssyrinx case LEAF_begemotBridgeStpHelloTime: 1361164410Ssyrinx val->v.integer = bif->hello_time; 1362165253Ssyrinx return (SNMP_ERR_NOERROR); 1363164410Ssyrinx 1364164410Ssyrinx case LEAF_begemotBridgeStpHoldTime: 1365164410Ssyrinx val->v.integer = bif->hold_time; 1366165253Ssyrinx return (SNMP_ERR_NOERROR); 1367164410Ssyrinx 1368164410Ssyrinx case LEAF_begemotBridgeStpForwardDelay: 1369164410Ssyrinx val->v.integer = bif->fwd_delay; 1370165253Ssyrinx return (SNMP_ERR_NOERROR); 1371164410Ssyrinx 1372164410Ssyrinx case LEAF_begemotBridgeStpBridgeMaxAge: 1373164410Ssyrinx val->v.integer = bif->bridge_max_age; 1374165253Ssyrinx return (SNMP_ERR_NOERROR); 1375164410Ssyrinx 1376164410Ssyrinx case LEAF_begemotBridgeStpBridgeHelloTime: 1377164410Ssyrinx val->v.integer = bif->bridge_hello_time; 1378165253Ssyrinx return (SNMP_ERR_NOERROR); 1379164410Ssyrinx 1380164410Ssyrinx case LEAF_begemotBridgeStpBridgeForwardDelay: 1381164410Ssyrinx val->v.integer = bif->bridge_fwd_delay; 1382165253Ssyrinx return (SNMP_ERR_NOERROR); 1383164997Ssyrinx 1384164997Ssyrinx case LEAF_begemotBridgeStpVersion: 1385164997Ssyrinx val->v.integer = bif->stp_version; 1386165253Ssyrinx return (SNMP_ERR_NOERROR); 1387164997Ssyrinx 1388164997Ssyrinx case LEAF_begemotBridgeStpTxHoldCount: 1389164997Ssyrinx val->v.integer = bif->tx_hold_count; 1390165253Ssyrinx return (SNMP_ERR_NOERROR); 1391164410Ssyrinx } 1392164410Ssyrinx 1393165253Ssyrinx abort(); 1394164410Ssyrinx} 1395164410Ssyrinx 1396164410Ssyrinxint 1397164410Ssyrinxop_begemot_tp(struct snmp_context *ctx, struct snmp_value *val, 1398164410Ssyrinx uint sub, uint iidx __unused, enum snmp_op op) 1399164410Ssyrinx{ 1400165046Ssyrinx struct bridge_if *bif; 1401164410Ssyrinx 1402164410Ssyrinx if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1403164410Ssyrinx bridge_update_all_ifs(); 1404164410Ssyrinx 1405164410Ssyrinx switch (op) { 1406164410Ssyrinx case SNMP_OP_GET: 1407164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1408164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1409165253Ssyrinx goto get; 1410164410Ssyrinx 1411164410Ssyrinx case SNMP_OP_GETNEXT: 1412164410Ssyrinx if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1413164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1414164410Ssyrinx bridge_if_index_append(&val->var, sub, bif); 1415165253Ssyrinx goto get; 1416164410Ssyrinx 1417164410Ssyrinx case SNMP_OP_SET: 1418164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1419164410Ssyrinx return (SNMP_ERR_NOSUCHNAME); 1420164410Ssyrinx 1421164410Ssyrinx switch (val->var.subs[sub - 1]) { 1422164410Ssyrinx case LEAF_begemotBridgeTpAgingTime: 1423165253Ssyrinx if (val->v.integer < SNMP_BRIDGE_MIN_AGE_TIME || 1424165253Ssyrinx val->v.integer > SNMP_BRIDGE_MAX_AGE_TIME) 1425165253Ssyrinx return (SNMP_ERR_WRONG_VALUE); 1426165253Ssyrinx 1427164410Ssyrinx ctx->scratch->int1 = bif->age_time; 1428164410Ssyrinx if (bridge_set_aging_time(bif, val->v.integer) < 0) 1429164410Ssyrinx return (SNMP_ERR_GENERR); 1430164410Ssyrinx return (SNMP_ERR_NOERROR); 1431164410Ssyrinx 1432164410Ssyrinx case LEAF_begemotBridgeTpMaxAddresses: 1433164410Ssyrinx ctx->scratch->int1 = bif->max_addrs; 1434164410Ssyrinx if (bridge_set_max_cache(bif, val->v.integer) < 0) 1435164410Ssyrinx return (SNMP_ERR_GENERR); 1436164410Ssyrinx return (SNMP_ERR_NOERROR); 1437164410Ssyrinx 1438164410Ssyrinx case LEAF_begemotBridgeTpLearnedEntryDiscards: 1439164410Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 1440164410Ssyrinx } 1441164410Ssyrinx abort(); 1442164410Ssyrinx 1443164410Ssyrinx case SNMP_OP_ROLLBACK: 1444164410Ssyrinx if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1445164410Ssyrinx return (SNMP_ERR_GENERR); 1446164410Ssyrinx 1447164410Ssyrinx switch (val->var.subs[sub - 1]) { 1448164410Ssyrinx case LEAF_begemotBridgeTpAgingTime: 1449164410Ssyrinx bridge_set_aging_time(bif, ctx->scratch->int1); 1450164410Ssyrinx break; 1451164410Ssyrinx 1452164410Ssyrinx case LEAF_begemotBridgeTpMaxAddresses: 1453164410Ssyrinx bridge_set_max_cache(bif, ctx->scratch->int1); 1454164410Ssyrinx break; 1455164410Ssyrinx } 1456164410Ssyrinx return (SNMP_ERR_NOERROR); 1457164410Ssyrinx 1458164410Ssyrinx case SNMP_OP_COMMIT: 1459164410Ssyrinx return (SNMP_ERR_NOERROR); 1460164410Ssyrinx } 1461165253Ssyrinx abort(); 1462164410Ssyrinx 1463165253Ssyrinxget: 1464164410Ssyrinx switch (val->var.subs[sub - 1]) { 1465164410Ssyrinx case LEAF_begemotBridgeTpLearnedEntryDiscards: 1466164410Ssyrinx val->v.uint32 = bif->lrnt_drops; 1467165253Ssyrinx return (SNMP_ERR_NOERROR); 1468164410Ssyrinx 1469164410Ssyrinx case LEAF_begemotBridgeTpAgingTime: 1470164410Ssyrinx val->v.integer = bif->age_time; 1471165253Ssyrinx return (SNMP_ERR_NOERROR); 1472164410Ssyrinx 1473164410Ssyrinx case LEAF_begemotBridgeTpMaxAddresses: 1474164410Ssyrinx val->v.integer = bif->max_addrs; 1475165253Ssyrinx return (SNMP_ERR_NOERROR); 1476164410Ssyrinx } 1477164410Ssyrinx 1478165253Ssyrinx abort(); 1479164410Ssyrinx} 1480