1/*- 2 * Copyright (c) 2006 Shteryana Shopova <syrinx@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * Bridge MIB implementation for SNMPd. 27 * Bridge interface objects. 28 *
| 1/*- 2 * Copyright (c) 2006 Shteryana Shopova <syrinx@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * Bridge MIB implementation for SNMPd. 27 * Bridge interface objects. 28 *
|
29 * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c 164410 2006-11-19 15:42:48Z syrinx $
| 29 * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c 164997 2006-12-07 22:36:17Z syrinx $
|
30 */ 31 32#include <sys/queue.h> 33#include <sys/socket.h> 34#include <sys/time.h> 35#include <sys/types.h> 36 37#include <net/ethernet.h> 38#include <net/if.h> 39#include <net/if_mib.h> 40#include <net/if_types.h> 41 42#include <errno.h> 43#include <stdarg.h> 44#include <stdlib.h> 45#include <string.h> 46#include <syslog.h> 47 48#include <bsnmp/snmpmod.h> 49#include <bsnmp/snmp_mibII.h> 50 51#include "bridge_tree.h" 52#include "bridge_snmp.h" 53#include "bridge_oid.h" 54 55static const struct asn_oid oid_newRoot = OIDX_newRoot; 56static const struct asn_oid oid_TopologyChange = OIDX_topologyChange; 57static const struct asn_oid oid_begemotBrigeName = \ 58 OIDX_begemotBridgeBaseName; 59static const struct asn_oid oid_begemotNewRoot = OIDX_begemotBridgeNewRoot; 60static const struct asn_oid oid_begemotTopologyChange = \ 61 OIDX_begemotBridgeTopologyChange; 62 63TAILQ_HEAD(bridge_ifs, bridge_if); 64 65/* 66 * Free the bridge interface list. 67 */ 68static void 69bridge_ifs_free(struct bridge_ifs *headp) 70{ 71 struct bridge_if *b; 72 73 while ((b = TAILQ_FIRST(headp)) != NULL) { 74 TAILQ_REMOVE(headp, b, b_if); 75 free(b); 76 } 77} 78 79/* 80 * Insert an entry in the bridge interface TAILQ. Keep the 81 * TAILQ sorted by the bridge's interface name. 82 */ 83static void 84bridge_ifs_insert(struct bridge_ifs *headp, 85 struct bridge_if *b) 86{ 87 struct bridge_if *temp; 88 89 if ((temp = TAILQ_FIRST(headp)) == NULL || 90 strcmp(b->bif_name, temp->bif_name) < 0) { 91 TAILQ_INSERT_HEAD(headp, b, b_if); 92 return; 93 } 94 95 TAILQ_FOREACH(temp, headp, b_if) 96 if(strcmp(b->bif_name, temp->bif_name) < 0) 97 TAILQ_INSERT_BEFORE(temp, b, b_if); 98 99 TAILQ_INSERT_TAIL(headp, b, b_if); 100} 101 102/* The global bridge interface list. */ 103static struct bridge_ifs bridge_ifs = TAILQ_HEAD_INITIALIZER(bridge_ifs); 104static time_t bridge_list_age; 105 106/* 107 * Free the global list. 108 */ 109void 110bridge_ifs_fini(void) 111{ 112 bridge_ifs_free(&bridge_ifs); 113} 114 115/* 116 * Find a bridge interface entry by the bridge interface system index. 117 */ 118struct bridge_if * 119bridge_if_find_ifs(uint32_t sysindex) 120{ 121 struct bridge_if *b; 122 123 TAILQ_FOREACH(b, &bridge_ifs, b_if) 124 if (b->sysindex == sysindex) 125 return (b); 126 127 return (NULL); 128} 129 130/* 131 * Find a bridge interface entry by the bridge interface name. 132 */ 133struct bridge_if * 134bridge_if_find_ifname(const char *b_name) 135{ 136 struct bridge_if *b; 137 138 TAILQ_FOREACH(b, &bridge_ifs, b_if) 139 if (strcmp(b_name, b->bif_name) == 0) 140 return (b); 141 142 return (NULL); 143} 144 145/* 146 * Find a bridge name by the bridge interface system index. 147 */ 148const char * 149bridge_if_find_name(uint32_t sysindex) 150{ 151 struct bridge_if *b; 152 153 TAILQ_FOREACH(b, &bridge_ifs, b_if) 154 if (b->sysindex == sysindex) 155 return (b->bif_name); 156 157 return (NULL); 158} 159 160/* 161 * Given two bridge interfaces' system indexes, find their 162 * corresponding names and return the result of the name 163 * comparison. Returns: 164 * error : -2 165 * i1 < i2 : -1 166 * i1 > i2 : +1 167 * i1 = i2 : 0 168 */ 169int 170bridge_compare_sysidx(uint32_t i1, uint32_t i2) 171{ 172 int c; 173 const char *b1, *b2; 174 175 if (i1 == i2) 176 return (0); 177 178 if ((b1 = bridge_if_find_name(i1)) == NULL) { 179 syslog(LOG_ERR, "Bridge interface %d does not exist", i1); 180 return (-2); 181 } 182 183 if ((b2 = bridge_if_find_name(i2)) == NULL) { 184 syslog(LOG_ERR, "Bridge interface %d does not exist", i2); 185 return (-2); 186 } 187 188 if ((c = strcmp(b1, b2)) < 0) 189 return (-1); 190 else if (c > 0) 191 return (1); 192 193 return (0); 194} 195 196/* 197 * Fetch the first bridge interface from the list. 198 */ 199struct bridge_if * 200bridge_first_bif(void) 201{ 202 return (TAILQ_FIRST(&bridge_ifs)); 203} 204 205/* 206 * Fetch the next bridge interface from the list. 207 */ 208struct bridge_if * 209bridge_next_bif(struct bridge_if *b_pr) 210{ 211 return (TAILQ_NEXT(b_pr, b_if)); 212} 213 214/* 215 * Create a new entry for a bridge interface and insert 216 * it in the list. 217 */ 218static struct bridge_if * 219bridge_new_bif(const char *bif_n, uint32_t sysindex, const u_char *physaddr) 220{ 221 struct bridge_if *bif; 222 223 if ((bif = (struct bridge_if *) malloc(sizeof(*bif)))== NULL) { 224 syslog(LOG_ERR, "bridge new interface failed: %s", 225 strerror(errno)); 226 return (NULL); 227 } 228 229 bzero(bif, sizeof(struct bridge_if)); 230 strlcpy(bif->bif_name, bif_n, IFNAMSIZ); 231 bcopy(physaddr, bif->br_addr.octet, ETHER_ADDR_LEN); 232 bif->sysindex = sysindex; 233 bif->br_type = BaseType_transparent_only; 234 /* 1 - all bridges default hold time * 100 - centi-seconds */ 235 bif->hold_time = 1 * 100; 236 bif->prot_spec = dot1dStpProtocolSpecification_ieee8021d; 237 bridge_ifs_insert(&bridge_ifs, bif); 238 239 return (bif); 240} 241 242/* 243 * Remove a bridge interface from the list, freeing all it's ports 244 * and address entries. 245 */ 246void 247bridge_remove_bif(struct bridge_if *bif) 248{ 249 bridge_members_free(bif); 250 bridge_addrs_free(bif); 251 TAILQ_REMOVE(&bridge_ifs, bif, b_if); 252 free(bif); 253} 254 255 256/* 257 * Prepare the variable (bridge interface name) for the private 258 * begemot notifications. 259 */ 260static struct snmp_value* 261bridge_basename_var(struct bridge_if *bif, struct snmp_value* b_val) 262{ 263 uint i; 264 265 b_val->var = oid_begemotBrigeName; 266 b_val->var.subs[b_val->var.len++] = strlen(bif->bif_name); 267 268 if ((b_val->v.octetstring.octets = (u_char *) 269 malloc(strlen(bif->bif_name))) == NULL) 270 return (NULL); 271 272 for (i = 0; i < strlen(bif->bif_name); i++) 273 b_val->var.subs[b_val->var.len++] = bif->bif_name[i]; 274 275 b_val->v.octetstring.len = strlen(bif->bif_name); 276 bcopy(bif->bif_name, b_val->v.octetstring.octets, 277 strlen(bif->bif_name)); 278 b_val->syntax = SNMP_SYNTAX_OCTETSTRING; 279 280 return (b_val); 281} 282 283/* 284 * Compare the values of the old and the new root port and 285 * send a new root notification, if they are not matching. 286 */ 287static void 288bridge_new_root(struct bridge_if *bif) 289{ 290 struct snmp_value bif_idx; 291 292 if (bridge_get_default() == bif) 293 snmp_send_trap(&oid_newRoot, (struct snmp_value *) NULL); 294 295 if (bridge_basename_var(bif, &bif_idx) == NULL) 296 return; 297 298 snmp_send_trap(&oid_begemotTopologyChange, 299 &bif_idx, (struct snmp_value *) NULL); 300} 301 302/* 303 * Compare the new and old topology change times and send a 304 * topology change notification if necessary. 305 */ 306static void 307bridge_top_change(struct bridge_if *bif) 308{ 309 struct snmp_value bif_idx; 310 311 if (bridge_get_default() == bif) 312 snmp_send_trap(&oid_TopologyChange, 313 (struct snmp_value *) NULL); 314 315 if (bridge_basename_var(bif, &bif_idx) == NULL) 316 return; 317 318 snmp_send_trap(&oid_begemotNewRoot, 319 &bif_idx, (struct snmp_value *) NULL); 320} 321 322static int 323bridge_if_create(const char* b_name, int8_t up) 324{ 325 if (bridge_create(b_name) < 0) 326 return (-1); 327 328 if (up == 1 && (bridge_set_if_up(b_name, 1) < 0)) 329 return (-1); 330 331 /* 332 * Do not create a new bridge entry here - 333 * wait until the mibII module notifies us. 334 */ 335 return (0); 336} 337 338static int 339bridge_if_destroy(struct bridge_if *bif) 340{ 341 if (bridge_destroy(bif->bif_name) < 0) 342 return (-1); 343 344 bridge_remove_bif(bif); 345 346 return (0); 347} 348 349/* 350 * Calculate the timeticks since the last topology change. 351 */ 352static int 353bridge_get_time_since_tc(struct bridge_if *bif, uint32_t *ticks) 354{ 355 struct timeval ct; 356 357 if (gettimeofday(&ct, NULL) < 0) { 358 syslog(LOG_ERR, "bridge get time since last TC:" 359 "getttimeofday failed: %s", strerror(errno)); 360 return (-1); 361 } 362 363 if (ct.tv_usec - bif->last_tc_time.tv_usec < 0) { 364 ct.tv_sec -= 1; 365 ct.tv_usec += 1000000; 366 } 367 368 ct.tv_sec -= bif->last_tc_time.tv_sec; 369 ct.tv_usec -= bif->last_tc_time.tv_usec; 370 371 *ticks = ct.tv_sec * 100 + ct.tv_usec/10000; 372 373 return (0); 374} 375 376/* 377 * Update the info we have for a single bridge interface. 378 * Return: 379 * 1, if successful 380 * 0, if the interface was deleted 381 * -1, error occured while fetching the info from the kernel. 382 */ 383static int 384bridge_update_bif(struct bridge_if *bif) 385{ 386 struct mibif *ifp; 387 388 /* Walk through the mibII interface list. */ 389 for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) 390 if (strcmp(ifp->name, bif->bif_name) == 0) 391 break; 392 393 if (ifp == NULL) { 394 /* Ops, we do not exist anymore. */ 395 bridge_remove_bif(bif); 396 return (0); 397 } 398 399 if (ifp->physaddr != NULL ) 400 bcopy(ifp->physaddr, bif->br_addr.octet, ETHER_ADDR_LEN); 401 else 402 bridge_get_basemac(bif->bif_name, bif->br_addr.octet); 403 404 if (ifp->mib.ifmd_flags & IFF_RUNNING) 405 bif->if_status = RowStatus_active; 406 else 407 bif->if_status = RowStatus_notInService; 408 409 switch (bridge_getinfo_bif(bif)) { 410 case 2: 411 bridge_new_root(bif); 412 break; 413 case 1: 414 bridge_top_change(bif); 415 break; 416 case -1: 417 bridge_remove_bif(bif); 418 return (-1); 419 default: 420 break; 421 } 422 423 /* 424 * The number of ports is accessible via SNMP - 425 * update the ports each time the bridge interface data 426 * is refreshed too. 427 */ 428 bif->num_ports = bridge_update_memif(bif); 429 bif->entry_age = time(NULL); 430 431 return (1); 432} 433 434/* 435 * Update all bridge interfaces' ports only - 436 * make sure each bridge interface exists first. 437 */ 438void 439bridge_update_all_ports(void) 440{ 441 struct mibif *ifp; 442 struct bridge_if *bif, *t_bif; 443 444 for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 445 t_bif = bridge_next_bif(bif); 446 447 for (ifp = mib_first_if(); ifp != NULL; 448 ifp = mib_next_if(ifp)) 449 if (strcmp(ifp->name, bif->bif_name) == 0) 450 break; 451 452 if (ifp != NULL) 453 bif->num_ports = bridge_update_memif(bif); 454 else /* Ops, we do not exist anymore. */ 455 bridge_remove_bif(bif); 456 } 457 458 bridge_ports_update_listage(); 459} 460 461/* 462 * Update all addresses only. 463 */ 464void 465bridge_update_all_addrs(void) 466{ 467 struct mibif *ifp; 468 struct bridge_if *bif, *t_bif; 469 470 for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 471 t_bif = bridge_next_bif(bif); 472 473 for (ifp = mib_first_if(); ifp != NULL; 474 ifp = mib_next_if(ifp)) 475 if (strcmp(ifp->name, bif->bif_name) == 0) 476 break; 477 478 if (ifp != NULL) 479 bif->num_addrs = bridge_update_addrs(bif); 480 else /* Ops, we don't exist anymore. */ 481 bridge_remove_bif(bif); 482 } 483 484 bridge_addrs_update_listage(); 485} 486 487/* 488 * Update only the bridge interfaces' data - skip addresses. 489 */ 490void 491bridge_update_all_ifs(void) 492{ 493 struct bridge_if *bif, *t_bif; 494 495 for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 496 t_bif = bridge_next_bif(bif); 497 bridge_update_bif(bif); 498 } 499 500 bridge_ports_update_listage(); 501 bridge_list_age = time(NULL); 502} 503 504/* 505 * Update all info we have for all bridges. 506 */ 507void 508bridge_update_all(void *arg __unused) 509{ 510 struct bridge_if *bif, *t_bif; 511 512 for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 513 t_bif = bridge_next_bif(bif); 514 if (bridge_update_bif(bif) <= 0) 515 continue; 516 517 /* Update our learnt addresses. */ 518 bif->num_addrs = bridge_update_addrs(bif); 519 } 520 521 bridge_list_age = time(NULL); 522 bridge_ports_update_listage(); 523 bridge_addrs_update_listage(); 524} 525 526/* 527 * Callback for polling our last topology change time - 528 * check whether we are root or whether a TC was detected once every 529 * 30 seconds, so that we can send the newRoot and TopologyChange traps 530 * on time. The rest of the data is polled only once every 5 min. 531 */ 532void 533bridge_update_tc_time(void *arg __unused) 534{ 535 struct bridge_if *bif; 536 struct mibif *ifp; 537 538 TAILQ_FOREACH(bif, &bridge_ifs, b_if) { 539 /* Walk through the mibII interface list. */ 540 for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) 541 if (strcmp(ifp->name, bif->bif_name) == 0) 542 break; 543 544 if (ifp == NULL) { 545 bridge_remove_bif(bif); 546 continue; 547 } 548 549 switch (bridge_get_op_param(bif)) { 550 case 2: 551 bridge_new_root(bif); 552 break; 553 case 1: 554 bridge_top_change(bif); 555 break; 556 } 557 } 558} 559 560/* 561 * Callback for handling new bridge interface creation. 562 */ 563int 564bridge_attach_newif(struct mibif *ifp) 565{ 566 u_char *p_mac, mac[ETHER_ADDR_LEN]; 567 struct bridge_if *bif; 568 569 if (ifp->mib.ifmd_data.ifi_type != IFT_BRIDGE) 570 return (0); 571 572 /* Make sure it does not exist in our list. */ 573 TAILQ_FOREACH(bif, &bridge_ifs, b_if) 574 if(strcmp(bif->bif_name, ifp->name) == 0) { 575 syslog(LOG_ERR, "bridge interface %s already " 576 "in list", bif->bif_name); 577 return (-1); 578 } 579 580 if ((p_mac = ifp->physaddr) == NULL && 581 (p_mac = bridge_get_basemac(ifp->name, mac)) == NULL) { 582 syslog(LOG_ERR, "bridge attach new %s failed - " 583 "no bridge mac address", ifp->name); 584 return (-1); 585 } 586 587 if ((bif = bridge_new_bif(ifp->name, ifp->sysindex, p_mac)) == NULL) 588 return (-1); 589 590 if (ifp->mib.ifmd_flags & IFF_RUNNING) 591 bif->if_status = RowStatus_active; 592 else 593 bif->if_status = RowStatus_notInService; 594 595 /* Skip sending notifications if the interface was just created. */ 596 if (bridge_getinfo_bif(bif) < 0 || 597 (bif->num_ports = bridge_getinfo_bif_ports(bif)) < 0 || 598 (bif->num_addrs = bridge_getinfo_bif_addrs(bif)) < 0) { 599 bridge_remove_bif(bif); 600 return (-1); 601 } 602 603 /* Check whether we are the default bridge interface. */ 604 if (strcmp(ifp->name, bridge_get_default_name()) == 0) 605 bridge_set_default(bif); 606 607 return (0); 608} 609 610void 611bridge_ifs_dump(void) 612{ 613 struct bridge_if *bif; 614 615 for (bif = bridge_first_bif(); bif != NULL; 616 bif = bridge_next_bif(bif)) { 617 syslog(LOG_ERR, "Bridge %s, index - %d", bif->bif_name, 618 bif->sysindex); 619 bridge_ports_dump(bif); 620 bridge_addrs_dump(bif); 621 } 622} 623 624/* 625 * RFC4188 specifics. 626 */ 627int 628op_dot1d_base(struct snmp_context *ctx __unused, struct snmp_value *value, 629 uint sub, uint iidx __unused, enum snmp_op op) 630{ 631 int ret; 632 struct bridge_if *bif; 633 634 if ((bif = bridge_get_default()) == NULL) 635 return (SNMP_ERR_NOSUCHNAME); 636 637 if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 638 bridge_update_bif(bif) <= 0) /* It was just deleted. */ 639 return (SNMP_ERR_NOSUCHNAME); 640 641 ret = SNMP_ERR_NOERROR; 642 643 switch (op) { 644 case SNMP_OP_GET: 645 switch (value->var.subs[sub - 1]) { 646 case LEAF_dot1dBaseBridgeAddress: 647 ret = string_get(value, bif->br_addr.octet, 648 ETHER_ADDR_LEN); 649 break; 650 case LEAF_dot1dBaseNumPorts: 651 value->v.integer = bif->num_ports; 652 break; 653 case LEAF_dot1dBaseType: 654 value->v.integer = bif->br_type; 655 break; 656 abort(); 657 } 658 break; 659 660 case SNMP_OP_SET: 661 ret = SNMP_ERR_NOT_WRITEABLE; 662 break; 663 664 case SNMP_OP_GETNEXT: 665 case SNMP_OP_ROLLBACK: 666 case SNMP_OP_COMMIT: 667 abort(); 668 } 669 670 return (ret); 671} 672 673int 674op_dot1d_stp(struct snmp_context *ctx, struct snmp_value *value, 675 uint sub, uint iidx __unused, enum snmp_op op) 676{
| 30 */ 31 32#include <sys/queue.h> 33#include <sys/socket.h> 34#include <sys/time.h> 35#include <sys/types.h> 36 37#include <net/ethernet.h> 38#include <net/if.h> 39#include <net/if_mib.h> 40#include <net/if_types.h> 41 42#include <errno.h> 43#include <stdarg.h> 44#include <stdlib.h> 45#include <string.h> 46#include <syslog.h> 47 48#include <bsnmp/snmpmod.h> 49#include <bsnmp/snmp_mibII.h> 50 51#include "bridge_tree.h" 52#include "bridge_snmp.h" 53#include "bridge_oid.h" 54 55static const struct asn_oid oid_newRoot = OIDX_newRoot; 56static const struct asn_oid oid_TopologyChange = OIDX_topologyChange; 57static const struct asn_oid oid_begemotBrigeName = \ 58 OIDX_begemotBridgeBaseName; 59static const struct asn_oid oid_begemotNewRoot = OIDX_begemotBridgeNewRoot; 60static const struct asn_oid oid_begemotTopologyChange = \ 61 OIDX_begemotBridgeTopologyChange; 62 63TAILQ_HEAD(bridge_ifs, bridge_if); 64 65/* 66 * Free the bridge interface list. 67 */ 68static void 69bridge_ifs_free(struct bridge_ifs *headp) 70{ 71 struct bridge_if *b; 72 73 while ((b = TAILQ_FIRST(headp)) != NULL) { 74 TAILQ_REMOVE(headp, b, b_if); 75 free(b); 76 } 77} 78 79/* 80 * Insert an entry in the bridge interface TAILQ. Keep the 81 * TAILQ sorted by the bridge's interface name. 82 */ 83static void 84bridge_ifs_insert(struct bridge_ifs *headp, 85 struct bridge_if *b) 86{ 87 struct bridge_if *temp; 88 89 if ((temp = TAILQ_FIRST(headp)) == NULL || 90 strcmp(b->bif_name, temp->bif_name) < 0) { 91 TAILQ_INSERT_HEAD(headp, b, b_if); 92 return; 93 } 94 95 TAILQ_FOREACH(temp, headp, b_if) 96 if(strcmp(b->bif_name, temp->bif_name) < 0) 97 TAILQ_INSERT_BEFORE(temp, b, b_if); 98 99 TAILQ_INSERT_TAIL(headp, b, b_if); 100} 101 102/* The global bridge interface list. */ 103static struct bridge_ifs bridge_ifs = TAILQ_HEAD_INITIALIZER(bridge_ifs); 104static time_t bridge_list_age; 105 106/* 107 * Free the global list. 108 */ 109void 110bridge_ifs_fini(void) 111{ 112 bridge_ifs_free(&bridge_ifs); 113} 114 115/* 116 * Find a bridge interface entry by the bridge interface system index. 117 */ 118struct bridge_if * 119bridge_if_find_ifs(uint32_t sysindex) 120{ 121 struct bridge_if *b; 122 123 TAILQ_FOREACH(b, &bridge_ifs, b_if) 124 if (b->sysindex == sysindex) 125 return (b); 126 127 return (NULL); 128} 129 130/* 131 * Find a bridge interface entry by the bridge interface name. 132 */ 133struct bridge_if * 134bridge_if_find_ifname(const char *b_name) 135{ 136 struct bridge_if *b; 137 138 TAILQ_FOREACH(b, &bridge_ifs, b_if) 139 if (strcmp(b_name, b->bif_name) == 0) 140 return (b); 141 142 return (NULL); 143} 144 145/* 146 * Find a bridge name by the bridge interface system index. 147 */ 148const char * 149bridge_if_find_name(uint32_t sysindex) 150{ 151 struct bridge_if *b; 152 153 TAILQ_FOREACH(b, &bridge_ifs, b_if) 154 if (b->sysindex == sysindex) 155 return (b->bif_name); 156 157 return (NULL); 158} 159 160/* 161 * Given two bridge interfaces' system indexes, find their 162 * corresponding names and return the result of the name 163 * comparison. Returns: 164 * error : -2 165 * i1 < i2 : -1 166 * i1 > i2 : +1 167 * i1 = i2 : 0 168 */ 169int 170bridge_compare_sysidx(uint32_t i1, uint32_t i2) 171{ 172 int c; 173 const char *b1, *b2; 174 175 if (i1 == i2) 176 return (0); 177 178 if ((b1 = bridge_if_find_name(i1)) == NULL) { 179 syslog(LOG_ERR, "Bridge interface %d does not exist", i1); 180 return (-2); 181 } 182 183 if ((b2 = bridge_if_find_name(i2)) == NULL) { 184 syslog(LOG_ERR, "Bridge interface %d does not exist", i2); 185 return (-2); 186 } 187 188 if ((c = strcmp(b1, b2)) < 0) 189 return (-1); 190 else if (c > 0) 191 return (1); 192 193 return (0); 194} 195 196/* 197 * Fetch the first bridge interface from the list. 198 */ 199struct bridge_if * 200bridge_first_bif(void) 201{ 202 return (TAILQ_FIRST(&bridge_ifs)); 203} 204 205/* 206 * Fetch the next bridge interface from the list. 207 */ 208struct bridge_if * 209bridge_next_bif(struct bridge_if *b_pr) 210{ 211 return (TAILQ_NEXT(b_pr, b_if)); 212} 213 214/* 215 * Create a new entry for a bridge interface and insert 216 * it in the list. 217 */ 218static struct bridge_if * 219bridge_new_bif(const char *bif_n, uint32_t sysindex, const u_char *physaddr) 220{ 221 struct bridge_if *bif; 222 223 if ((bif = (struct bridge_if *) malloc(sizeof(*bif)))== NULL) { 224 syslog(LOG_ERR, "bridge new interface failed: %s", 225 strerror(errno)); 226 return (NULL); 227 } 228 229 bzero(bif, sizeof(struct bridge_if)); 230 strlcpy(bif->bif_name, bif_n, IFNAMSIZ); 231 bcopy(physaddr, bif->br_addr.octet, ETHER_ADDR_LEN); 232 bif->sysindex = sysindex; 233 bif->br_type = BaseType_transparent_only; 234 /* 1 - all bridges default hold time * 100 - centi-seconds */ 235 bif->hold_time = 1 * 100; 236 bif->prot_spec = dot1dStpProtocolSpecification_ieee8021d; 237 bridge_ifs_insert(&bridge_ifs, bif); 238 239 return (bif); 240} 241 242/* 243 * Remove a bridge interface from the list, freeing all it's ports 244 * and address entries. 245 */ 246void 247bridge_remove_bif(struct bridge_if *bif) 248{ 249 bridge_members_free(bif); 250 bridge_addrs_free(bif); 251 TAILQ_REMOVE(&bridge_ifs, bif, b_if); 252 free(bif); 253} 254 255 256/* 257 * Prepare the variable (bridge interface name) for the private 258 * begemot notifications. 259 */ 260static struct snmp_value* 261bridge_basename_var(struct bridge_if *bif, struct snmp_value* b_val) 262{ 263 uint i; 264 265 b_val->var = oid_begemotBrigeName; 266 b_val->var.subs[b_val->var.len++] = strlen(bif->bif_name); 267 268 if ((b_val->v.octetstring.octets = (u_char *) 269 malloc(strlen(bif->bif_name))) == NULL) 270 return (NULL); 271 272 for (i = 0; i < strlen(bif->bif_name); i++) 273 b_val->var.subs[b_val->var.len++] = bif->bif_name[i]; 274 275 b_val->v.octetstring.len = strlen(bif->bif_name); 276 bcopy(bif->bif_name, b_val->v.octetstring.octets, 277 strlen(bif->bif_name)); 278 b_val->syntax = SNMP_SYNTAX_OCTETSTRING; 279 280 return (b_val); 281} 282 283/* 284 * Compare the values of the old and the new root port and 285 * send a new root notification, if they are not matching. 286 */ 287static void 288bridge_new_root(struct bridge_if *bif) 289{ 290 struct snmp_value bif_idx; 291 292 if (bridge_get_default() == bif) 293 snmp_send_trap(&oid_newRoot, (struct snmp_value *) NULL); 294 295 if (bridge_basename_var(bif, &bif_idx) == NULL) 296 return; 297 298 snmp_send_trap(&oid_begemotTopologyChange, 299 &bif_idx, (struct snmp_value *) NULL); 300} 301 302/* 303 * Compare the new and old topology change times and send a 304 * topology change notification if necessary. 305 */ 306static void 307bridge_top_change(struct bridge_if *bif) 308{ 309 struct snmp_value bif_idx; 310 311 if (bridge_get_default() == bif) 312 snmp_send_trap(&oid_TopologyChange, 313 (struct snmp_value *) NULL); 314 315 if (bridge_basename_var(bif, &bif_idx) == NULL) 316 return; 317 318 snmp_send_trap(&oid_begemotNewRoot, 319 &bif_idx, (struct snmp_value *) NULL); 320} 321 322static int 323bridge_if_create(const char* b_name, int8_t up) 324{ 325 if (bridge_create(b_name) < 0) 326 return (-1); 327 328 if (up == 1 && (bridge_set_if_up(b_name, 1) < 0)) 329 return (-1); 330 331 /* 332 * Do not create a new bridge entry here - 333 * wait until the mibII module notifies us. 334 */ 335 return (0); 336} 337 338static int 339bridge_if_destroy(struct bridge_if *bif) 340{ 341 if (bridge_destroy(bif->bif_name) < 0) 342 return (-1); 343 344 bridge_remove_bif(bif); 345 346 return (0); 347} 348 349/* 350 * Calculate the timeticks since the last topology change. 351 */ 352static int 353bridge_get_time_since_tc(struct bridge_if *bif, uint32_t *ticks) 354{ 355 struct timeval ct; 356 357 if (gettimeofday(&ct, NULL) < 0) { 358 syslog(LOG_ERR, "bridge get time since last TC:" 359 "getttimeofday failed: %s", strerror(errno)); 360 return (-1); 361 } 362 363 if (ct.tv_usec - bif->last_tc_time.tv_usec < 0) { 364 ct.tv_sec -= 1; 365 ct.tv_usec += 1000000; 366 } 367 368 ct.tv_sec -= bif->last_tc_time.tv_sec; 369 ct.tv_usec -= bif->last_tc_time.tv_usec; 370 371 *ticks = ct.tv_sec * 100 + ct.tv_usec/10000; 372 373 return (0); 374} 375 376/* 377 * Update the info we have for a single bridge interface. 378 * Return: 379 * 1, if successful 380 * 0, if the interface was deleted 381 * -1, error occured while fetching the info from the kernel. 382 */ 383static int 384bridge_update_bif(struct bridge_if *bif) 385{ 386 struct mibif *ifp; 387 388 /* Walk through the mibII interface list. */ 389 for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) 390 if (strcmp(ifp->name, bif->bif_name) == 0) 391 break; 392 393 if (ifp == NULL) { 394 /* Ops, we do not exist anymore. */ 395 bridge_remove_bif(bif); 396 return (0); 397 } 398 399 if (ifp->physaddr != NULL ) 400 bcopy(ifp->physaddr, bif->br_addr.octet, ETHER_ADDR_LEN); 401 else 402 bridge_get_basemac(bif->bif_name, bif->br_addr.octet); 403 404 if (ifp->mib.ifmd_flags & IFF_RUNNING) 405 bif->if_status = RowStatus_active; 406 else 407 bif->if_status = RowStatus_notInService; 408 409 switch (bridge_getinfo_bif(bif)) { 410 case 2: 411 bridge_new_root(bif); 412 break; 413 case 1: 414 bridge_top_change(bif); 415 break; 416 case -1: 417 bridge_remove_bif(bif); 418 return (-1); 419 default: 420 break; 421 } 422 423 /* 424 * The number of ports is accessible via SNMP - 425 * update the ports each time the bridge interface data 426 * is refreshed too. 427 */ 428 bif->num_ports = bridge_update_memif(bif); 429 bif->entry_age = time(NULL); 430 431 return (1); 432} 433 434/* 435 * Update all bridge interfaces' ports only - 436 * make sure each bridge interface exists first. 437 */ 438void 439bridge_update_all_ports(void) 440{ 441 struct mibif *ifp; 442 struct bridge_if *bif, *t_bif; 443 444 for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 445 t_bif = bridge_next_bif(bif); 446 447 for (ifp = mib_first_if(); ifp != NULL; 448 ifp = mib_next_if(ifp)) 449 if (strcmp(ifp->name, bif->bif_name) == 0) 450 break; 451 452 if (ifp != NULL) 453 bif->num_ports = bridge_update_memif(bif); 454 else /* Ops, we do not exist anymore. */ 455 bridge_remove_bif(bif); 456 } 457 458 bridge_ports_update_listage(); 459} 460 461/* 462 * Update all addresses only. 463 */ 464void 465bridge_update_all_addrs(void) 466{ 467 struct mibif *ifp; 468 struct bridge_if *bif, *t_bif; 469 470 for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 471 t_bif = bridge_next_bif(bif); 472 473 for (ifp = mib_first_if(); ifp != NULL; 474 ifp = mib_next_if(ifp)) 475 if (strcmp(ifp->name, bif->bif_name) == 0) 476 break; 477 478 if (ifp != NULL) 479 bif->num_addrs = bridge_update_addrs(bif); 480 else /* Ops, we don't exist anymore. */ 481 bridge_remove_bif(bif); 482 } 483 484 bridge_addrs_update_listage(); 485} 486 487/* 488 * Update only the bridge interfaces' data - skip addresses. 489 */ 490void 491bridge_update_all_ifs(void) 492{ 493 struct bridge_if *bif, *t_bif; 494 495 for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 496 t_bif = bridge_next_bif(bif); 497 bridge_update_bif(bif); 498 } 499 500 bridge_ports_update_listage(); 501 bridge_list_age = time(NULL); 502} 503 504/* 505 * Update all info we have for all bridges. 506 */ 507void 508bridge_update_all(void *arg __unused) 509{ 510 struct bridge_if *bif, *t_bif; 511 512 for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { 513 t_bif = bridge_next_bif(bif); 514 if (bridge_update_bif(bif) <= 0) 515 continue; 516 517 /* Update our learnt addresses. */ 518 bif->num_addrs = bridge_update_addrs(bif); 519 } 520 521 bridge_list_age = time(NULL); 522 bridge_ports_update_listage(); 523 bridge_addrs_update_listage(); 524} 525 526/* 527 * Callback for polling our last topology change time - 528 * check whether we are root or whether a TC was detected once every 529 * 30 seconds, so that we can send the newRoot and TopologyChange traps 530 * on time. The rest of the data is polled only once every 5 min. 531 */ 532void 533bridge_update_tc_time(void *arg __unused) 534{ 535 struct bridge_if *bif; 536 struct mibif *ifp; 537 538 TAILQ_FOREACH(bif, &bridge_ifs, b_if) { 539 /* Walk through the mibII interface list. */ 540 for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) 541 if (strcmp(ifp->name, bif->bif_name) == 0) 542 break; 543 544 if (ifp == NULL) { 545 bridge_remove_bif(bif); 546 continue; 547 } 548 549 switch (bridge_get_op_param(bif)) { 550 case 2: 551 bridge_new_root(bif); 552 break; 553 case 1: 554 bridge_top_change(bif); 555 break; 556 } 557 } 558} 559 560/* 561 * Callback for handling new bridge interface creation. 562 */ 563int 564bridge_attach_newif(struct mibif *ifp) 565{ 566 u_char *p_mac, mac[ETHER_ADDR_LEN]; 567 struct bridge_if *bif; 568 569 if (ifp->mib.ifmd_data.ifi_type != IFT_BRIDGE) 570 return (0); 571 572 /* Make sure it does not exist in our list. */ 573 TAILQ_FOREACH(bif, &bridge_ifs, b_if) 574 if(strcmp(bif->bif_name, ifp->name) == 0) { 575 syslog(LOG_ERR, "bridge interface %s already " 576 "in list", bif->bif_name); 577 return (-1); 578 } 579 580 if ((p_mac = ifp->physaddr) == NULL && 581 (p_mac = bridge_get_basemac(ifp->name, mac)) == NULL) { 582 syslog(LOG_ERR, "bridge attach new %s failed - " 583 "no bridge mac address", ifp->name); 584 return (-1); 585 } 586 587 if ((bif = bridge_new_bif(ifp->name, ifp->sysindex, p_mac)) == NULL) 588 return (-1); 589 590 if (ifp->mib.ifmd_flags & IFF_RUNNING) 591 bif->if_status = RowStatus_active; 592 else 593 bif->if_status = RowStatus_notInService; 594 595 /* Skip sending notifications if the interface was just created. */ 596 if (bridge_getinfo_bif(bif) < 0 || 597 (bif->num_ports = bridge_getinfo_bif_ports(bif)) < 0 || 598 (bif->num_addrs = bridge_getinfo_bif_addrs(bif)) < 0) { 599 bridge_remove_bif(bif); 600 return (-1); 601 } 602 603 /* Check whether we are the default bridge interface. */ 604 if (strcmp(ifp->name, bridge_get_default_name()) == 0) 605 bridge_set_default(bif); 606 607 return (0); 608} 609 610void 611bridge_ifs_dump(void) 612{ 613 struct bridge_if *bif; 614 615 for (bif = bridge_first_bif(); bif != NULL; 616 bif = bridge_next_bif(bif)) { 617 syslog(LOG_ERR, "Bridge %s, index - %d", bif->bif_name, 618 bif->sysindex); 619 bridge_ports_dump(bif); 620 bridge_addrs_dump(bif); 621 } 622} 623 624/* 625 * RFC4188 specifics. 626 */ 627int 628op_dot1d_base(struct snmp_context *ctx __unused, struct snmp_value *value, 629 uint sub, uint iidx __unused, enum snmp_op op) 630{ 631 int ret; 632 struct bridge_if *bif; 633 634 if ((bif = bridge_get_default()) == NULL) 635 return (SNMP_ERR_NOSUCHNAME); 636 637 if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 638 bridge_update_bif(bif) <= 0) /* It was just deleted. */ 639 return (SNMP_ERR_NOSUCHNAME); 640 641 ret = SNMP_ERR_NOERROR; 642 643 switch (op) { 644 case SNMP_OP_GET: 645 switch (value->var.subs[sub - 1]) { 646 case LEAF_dot1dBaseBridgeAddress: 647 ret = string_get(value, bif->br_addr.octet, 648 ETHER_ADDR_LEN); 649 break; 650 case LEAF_dot1dBaseNumPorts: 651 value->v.integer = bif->num_ports; 652 break; 653 case LEAF_dot1dBaseType: 654 value->v.integer = bif->br_type; 655 break; 656 abort(); 657 } 658 break; 659 660 case SNMP_OP_SET: 661 ret = SNMP_ERR_NOT_WRITEABLE; 662 break; 663 664 case SNMP_OP_GETNEXT: 665 case SNMP_OP_ROLLBACK: 666 case SNMP_OP_COMMIT: 667 abort(); 668 } 669 670 return (ret); 671} 672 673int 674op_dot1d_stp(struct snmp_context *ctx, struct snmp_value *value, 675 uint sub, uint iidx __unused, enum snmp_op op) 676{
|
| 677 int ret;
|
677 struct bridge_if *bif; 678 679 if ((bif = bridge_get_default()) == NULL) 680 return (SNMP_ERR_NOSUCHNAME); 681 682 if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 683 bridge_update_bif(bif) <= 0) /* It was just deleted. */ 684 return (SNMP_ERR_NOSUCHNAME); 685 686 switch (op) { 687 case SNMP_OP_GET: 688 switch (value->var.subs[sub - 1]) { 689 case LEAF_dot1dStpProtocolSpecification: 690 value->v.integer = bif->prot_spec; 691 break; 692 693 case LEAF_dot1dStpPriority: 694 value->v.integer = bif->priority; 695 break; 696 697 case LEAF_dot1dStpTimeSinceTopologyChange: 698 if (bridge_get_time_since_tc(bif, 699 &(value->v.uint32)) < 0) 700 return (SNMP_ERR_GENERR); 701 break; 702 703 case LEAF_dot1dStpTopChanges: 704 value->v.uint32 = bif->top_changes; 705 break; 706 707 case LEAF_dot1dStpDesignatedRoot: 708 return (string_get(value, bif->design_root, 709 SNMP_BRIDGE_ID_LEN)); 710 711 case LEAF_dot1dStpRootCost: 712 value->v.integer = bif->root_cost; 713 break; 714 715 case LEAF_dot1dStpRootPort: 716 value->v.integer = bif->root_port; 717 break; 718 719 case LEAF_dot1dStpMaxAge: 720 value->v.integer = bif->max_age; 721 break; 722 723 case LEAF_dot1dStpHelloTime: 724 value->v.integer = bif->hello_time; 725 break; 726 727 case LEAF_dot1dStpHoldTime: 728 value->v.integer = bif->hold_time; 729 break; 730 731 case LEAF_dot1dStpForwardDelay: 732 value->v.integer = bif->fwd_delay; 733 break; 734 735 case LEAF_dot1dStpBridgeMaxAge: 736 value->v.integer = bif->bridge_max_age; 737 break; 738 739 case LEAF_dot1dStpBridgeHelloTime: 740 value->v.integer = bif->bridge_hello_time; 741 break; 742 743 case LEAF_dot1dStpBridgeForwardDelay: 744 value->v.integer = bif->bridge_fwd_delay; 745 break;
| 678 struct bridge_if *bif; 679 680 if ((bif = bridge_get_default()) == NULL) 681 return (SNMP_ERR_NOSUCHNAME); 682 683 if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 684 bridge_update_bif(bif) <= 0) /* It was just deleted. */ 685 return (SNMP_ERR_NOSUCHNAME); 686 687 switch (op) { 688 case SNMP_OP_GET: 689 switch (value->var.subs[sub - 1]) { 690 case LEAF_dot1dStpProtocolSpecification: 691 value->v.integer = bif->prot_spec; 692 break; 693 694 case LEAF_dot1dStpPriority: 695 value->v.integer = bif->priority; 696 break; 697 698 case LEAF_dot1dStpTimeSinceTopologyChange: 699 if (bridge_get_time_since_tc(bif, 700 &(value->v.uint32)) < 0) 701 return (SNMP_ERR_GENERR); 702 break; 703 704 case LEAF_dot1dStpTopChanges: 705 value->v.uint32 = bif->top_changes; 706 break; 707 708 case LEAF_dot1dStpDesignatedRoot: 709 return (string_get(value, bif->design_root, 710 SNMP_BRIDGE_ID_LEN)); 711 712 case LEAF_dot1dStpRootCost: 713 value->v.integer = bif->root_cost; 714 break; 715 716 case LEAF_dot1dStpRootPort: 717 value->v.integer = bif->root_port; 718 break; 719 720 case LEAF_dot1dStpMaxAge: 721 value->v.integer = bif->max_age; 722 break; 723 724 case LEAF_dot1dStpHelloTime: 725 value->v.integer = bif->hello_time; 726 break; 727 728 case LEAF_dot1dStpHoldTime: 729 value->v.integer = bif->hold_time; 730 break; 731 732 case LEAF_dot1dStpForwardDelay: 733 value->v.integer = bif->fwd_delay; 734 break; 735 736 case LEAF_dot1dStpBridgeMaxAge: 737 value->v.integer = bif->bridge_max_age; 738 break; 739 740 case LEAF_dot1dStpBridgeHelloTime: 741 value->v.integer = bif->bridge_hello_time; 742 break; 743 744 case LEAF_dot1dStpBridgeForwardDelay: 745 value->v.integer = bif->bridge_fwd_delay; 746 break;
|
| 747 case LEAF_dot1dStpVersion: 748 value->v.integer = bif->stp_version; 749 break; 750 case LEAF_dot1dStpTxHoldCount: 751 value->v.integer = bif->tx_hold_count;
|
746 } 747 748 return (SNMP_ERR_NOERROR); 749 750 case SNMP_OP_GETNEXT: 751 abort(); 752 753 case SNMP_OP_SET: 754 switch (value->var.subs[sub - 1]) { 755 case LEAF_dot1dStpPriority: 756 ctx->scratch->int1 = bif->priority;
| 752 } 753 754 return (SNMP_ERR_NOERROR); 755 756 case SNMP_OP_GETNEXT: 757 abort(); 758 759 case SNMP_OP_SET: 760 switch (value->var.subs[sub - 1]) { 761 case LEAF_dot1dStpPriority: 762 ctx->scratch->int1 = bif->priority;
|
757 if (bridge_set_priority(bif, value->v.integer) < 0) 758 return (SNMP_ERR_GENERR);
| 763 ret = bridge_set_priority(bif, value->v.integer);
|
759 break; 760 761 case LEAF_dot1dStpBridgeMaxAge: 762 ctx->scratch->int1 = bif->bridge_max_age;
| 764 break; 765 766 case LEAF_dot1dStpBridgeMaxAge: 767 ctx->scratch->int1 = bif->bridge_max_age;
|
763 if (bridge_set_maxage(bif, value->v.integer) < 0) 764 return (SNMP_ERR_GENERR);
| 768 ret = bridge_set_maxage(bif, value->v.integer);
|
765 break; 766 767 case LEAF_dot1dStpBridgeHelloTime: 768 ctx->scratch->int1 = bif->bridge_hello_time;
| 769 break; 770 771 case LEAF_dot1dStpBridgeHelloTime: 772 ctx->scratch->int1 = bif->bridge_hello_time;
|
769 if (bridge_set_hello_time(bif, value->v.integer) < 0) 770 return (SNMP_ERR_GENERR);
| 773 ret = bridge_set_hello_time(bif, value->v.integer);
|
771 break; 772 773 case LEAF_dot1dStpBridgeForwardDelay: 774 ctx->scratch->int1 = bif->bridge_fwd_delay;
| 774 break; 775 776 case LEAF_dot1dStpBridgeForwardDelay: 777 ctx->scratch->int1 = bif->bridge_fwd_delay;
|
775 if (bridge_set_forward_delay(bif, value->v.integer) < 0) 776 return (SNMP_ERR_GENERR);
| 778 ret = bridge_set_forward_delay(bif, value->v.integer);
|
777 break; 778
| 779 break; 780
|
| 781 case LEAF_dot1dStpVersion: 782 ctx->scratch->int1 = bif->stp_version; 783 ret = bridge_set_stp_version(bif, value->v.integer); 784 break; 785 786 case LEAF_dot1dStpTxHoldCount: 787 ctx->scratch->int1 = bif->tx_hold_count; 788 ret = bridge_set_tx_hold_count(bif, value->v.integer); 789 break; 790
|
779 case LEAF_dot1dStpProtocolSpecification: 780 case LEAF_dot1dStpTimeSinceTopologyChange: 781 case LEAF_dot1dStpTopChanges: 782 case LEAF_dot1dStpDesignatedRoot: 783 case LEAF_dot1dStpRootCost: 784 case LEAF_dot1dStpRootPort: 785 case LEAF_dot1dStpMaxAge: 786 case LEAF_dot1dStpHelloTime: 787 case LEAF_dot1dStpHoldTime: 788 case LEAF_dot1dStpForwardDelay: 789 return (SNMP_ERR_NOT_WRITEABLE);
| 791 case LEAF_dot1dStpProtocolSpecification: 792 case LEAF_dot1dStpTimeSinceTopologyChange: 793 case LEAF_dot1dStpTopChanges: 794 case LEAF_dot1dStpDesignatedRoot: 795 case LEAF_dot1dStpRootCost: 796 case LEAF_dot1dStpRootPort: 797 case LEAF_dot1dStpMaxAge: 798 case LEAF_dot1dStpHelloTime: 799 case LEAF_dot1dStpHoldTime: 800 case LEAF_dot1dStpForwardDelay: 801 return (SNMP_ERR_NOT_WRITEABLE);
|
| 802 default: 803 return (SNMP_ERR_NOSUCHNAME);
|
790 } 791
| 804 } 805
|
| 806 if (ret == -2) 807 return (SNMP_ERR_WRONG_VALUE); 808 else if (ret < 0) 809 return (SNMP_ERR_GENERR);
|
792 return (SNMP_ERR_NOERROR); 793 794 case SNMP_OP_ROLLBACK: 795 switch (value->var.subs[sub - 1]) { 796 case LEAF_dot1dStpPriority:
| 810 return (SNMP_ERR_NOERROR); 811 812 case SNMP_OP_ROLLBACK: 813 switch (value->var.subs[sub - 1]) { 814 case LEAF_dot1dStpPriority:
|
797 (void) bridge_set_priority(bif, ctx->scratch->int1);
| 815 bridge_set_priority(bif, ctx->scratch->int1);
|
798 break; 799 case LEAF_dot1dStpBridgeMaxAge:
| 816 break; 817 case LEAF_dot1dStpBridgeMaxAge:
|
800 (void) bridge_set_maxage(bif, ctx->scratch->int1);
| 818 bridge_set_maxage(bif, ctx->scratch->int1);
|
801 break; 802 case LEAF_dot1dStpBridgeHelloTime:
| 819 break; 820 case LEAF_dot1dStpBridgeHelloTime:
|
803 (void) bridge_set_hello_time(bif, ctx->scratch->int1);
| 821 bridge_set_hello_time(bif, ctx->scratch->int1);
|
804 break; 805 case LEAF_dot1dStpBridgeForwardDelay:
| 822 break; 823 case LEAF_dot1dStpBridgeForwardDelay:
|
806 (void) bridge_set_forward_delay(bif, 807 ctx->scratch->int1);
| 824 bridge_set_forward_delay(bif, ctx->scratch->int1);
|
808 break;
| 825 break;
|
| 826 case LEAF_dot1dStpVersion: 827 bridge_set_stp_version(bif, ctx->scratch->int1); 828 break; 829 case LEAF_dot1dStpTxHoldCount: 830 bridge_set_tx_hold_count(bif, ctx->scratch->int1); 831 break;
|
809 } 810 return (SNMP_ERR_NOERROR); 811 812 case SNMP_OP_COMMIT: 813 return (SNMP_ERR_NOERROR); 814 } 815 816 return (SNMP_ERR_NOERROR); 817} 818 819int 820op_dot1d_tp(struct snmp_context *ctx, struct snmp_value *value, 821 uint sub, uint iidx __unused, enum snmp_op op) 822{ 823 struct bridge_if *bif; 824 825 if ((bif = bridge_get_default()) == NULL) 826 return (SNMP_ERR_NOSUCHNAME); 827 828 if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 829 bridge_update_bif(bif) <= 0) /* It was just deleted. */ 830 return (SNMP_ERR_NOSUCHNAME); 831 832 switch (op) { 833 case SNMP_OP_GET: 834 switch (value->var.subs[sub - 1]) { 835 case LEAF_dot1dTpLearnedEntryDiscards: 836 value->v.uint32 = bif->lrnt_drops; 837 break; 838 case LEAF_dot1dTpAgingTime: 839 value->v.integer = bif->age_time; 840 break; 841 } 842 return (SNMP_ERR_NOERROR); 843 844 case SNMP_OP_GETNEXT: 845 abort(); 846 847 case SNMP_OP_SET: 848 if (value->var.subs[sub - 1] == LEAF_dot1dTpAgingTime) { 849 ctx->scratch->int1 = bif->age_time; 850 if (bridge_set_aging_time(bif, value->v.integer) < 0) 851 return (SNMP_ERR_GENERR); 852 } 853 return (SNMP_ERR_NOERROR); 854 855 case SNMP_OP_ROLLBACK: 856 if (value->var.subs[sub - 1] == LEAF_dot1dTpAgingTime)
| 832 } 833 return (SNMP_ERR_NOERROR); 834 835 case SNMP_OP_COMMIT: 836 return (SNMP_ERR_NOERROR); 837 } 838 839 return (SNMP_ERR_NOERROR); 840} 841 842int 843op_dot1d_tp(struct snmp_context *ctx, struct snmp_value *value, 844 uint sub, uint iidx __unused, enum snmp_op op) 845{ 846 struct bridge_if *bif; 847 848 if ((bif = bridge_get_default()) == NULL) 849 return (SNMP_ERR_NOSUCHNAME); 850 851 if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && 852 bridge_update_bif(bif) <= 0) /* It was just deleted. */ 853 return (SNMP_ERR_NOSUCHNAME); 854 855 switch (op) { 856 case SNMP_OP_GET: 857 switch (value->var.subs[sub - 1]) { 858 case LEAF_dot1dTpLearnedEntryDiscards: 859 value->v.uint32 = bif->lrnt_drops; 860 break; 861 case LEAF_dot1dTpAgingTime: 862 value->v.integer = bif->age_time; 863 break; 864 } 865 return (SNMP_ERR_NOERROR); 866 867 case SNMP_OP_GETNEXT: 868 abort(); 869 870 case SNMP_OP_SET: 871 if (value->var.subs[sub - 1] == LEAF_dot1dTpAgingTime) { 872 ctx->scratch->int1 = bif->age_time; 873 if (bridge_set_aging_time(bif, value->v.integer) < 0) 874 return (SNMP_ERR_GENERR); 875 } 876 return (SNMP_ERR_NOERROR); 877 878 case SNMP_OP_ROLLBACK: 879 if (value->var.subs[sub - 1] == LEAF_dot1dTpAgingTime)
|
857 (void) bridge_set_aging_time(bif, ctx->scratch->int1);
| 880 bridge_set_aging_time(bif, ctx->scratch->int1);
|
858 return (SNMP_ERR_NOERROR); 859 860 case SNMP_OP_COMMIT: 861 return (SNMP_ERR_NOERROR); 862 } 863 864 return (SNMP_ERR_NOERROR); 865} 866 867/* 868 * Private BEGEMOT-BRIDGE-MIB specifics. 869 */ 870 871/* 872 * Get the bridge name from an OID index. 873 */ 874static char * 875bridge_name_index_get(const struct asn_oid *oid, uint sub, char *b_name) 876{ 877 uint i; 878 879 if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 880 return (NULL); 881 882 for (i = 0; i < oid->subs[sub]; i++) 883 b_name[i] = oid->subs[sub + i + 1]; 884 b_name[i] = '\0'; 885 886 return (b_name); 887} 888 889static void 890bridge_if_index_append(struct asn_oid *oid, uint sub, 891 const struct bridge_if *bif) 892{ 893 uint i; 894 895 oid->len = sub + strlen(bif->bif_name) + 1; 896 oid->subs[sub] = strlen(bif->bif_name); 897 898 for (i = 1; i <= strlen(bif->bif_name); i++) 899 oid->subs[sub + i] = bif->bif_name[i - 1]; 900} 901 902static struct bridge_if * 903bridge_if_index_get(const struct asn_oid *oid, uint sub) 904{ 905 uint i; 906 char bif_name[IFNAMSIZ]; 907 908 if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 909 return (NULL); 910 911 for (i = 0; i < oid->subs[sub]; i++) 912 bif_name[i] = oid->subs[sub + i + 1]; 913 bif_name[i] = '\0'; 914 915 return (bridge_if_find_ifname(bif_name)); 916} 917 918static struct bridge_if * 919bridge_if_index_getnext(const struct asn_oid *oid, uint sub) 920{ 921 uint i; 922 char bif_name[IFNAMSIZ]; 923 struct bridge_if *bif; 924 925 if (oid->len - sub == 0) 926 return (bridge_first_bif()); 927 928 if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 929 return (NULL); 930 931 for (i = 0; i < oid->subs[sub]; i++) 932 bif_name[i] = oid->subs[sub + i + 1]; 933 bif_name[i] = '\0'; 934 935 if ((bif = bridge_if_find_ifname(bif_name)) == NULL) 936 return (NULL); 937 938 return (bridge_next_bif(bif)); 939} 940 941static int 942bridge_set_if_status(struct snmp_context *ctx, 943 struct snmp_value *val, uint sub) 944{ 945 struct bridge_if *bif; 946 char bif_name[IFNAMSIZ]; 947 948 bif = bridge_if_index_get(&val->var, sub); 949 950 switch (val->v.integer) { 951 case RowStatus_active: 952 if (bif == NULL) 953 return (SNMP_ERR_INCONS_VALUE); 954 955 ctx->scratch->int1 = bif->if_status; 956 957 switch (bif->if_status) { 958 case RowStatus_active: 959 return (SNMP_ERR_NOERROR); 960 case RowStatus_notInService: 961 if (bridge_set_if_up(bif->bif_name, 1) < 0) 962 return (SNMP_ERR_GENERR); 963 return (SNMP_ERR_NOERROR); 964 default: 965 break; 966 } 967 return (SNMP_ERR_INCONS_VALUE); 968 969 case RowStatus_notInService: 970 if (bif == NULL) 971 return (SNMP_ERR_INCONS_VALUE); 972 973 ctx->scratch->int1 = bif->if_status; 974 975 switch (bif->if_status) { 976 case RowStatus_active: 977 if (bridge_set_if_up(bif->bif_name, 1) < 0) 978 return (SNMP_ERR_GENERR); 979 return (SNMP_ERR_NOERROR); 980 case RowStatus_notInService: 981 return (SNMP_ERR_NOERROR); 982 default: 983 break; 984 } 985 return (SNMP_ERR_INCONS_VALUE); 986 987 case RowStatus_notReady: 988 return (SNMP_ERR_INCONS_VALUE); 989 990 case RowStatus_createAndGo: 991 if (bif != NULL) 992 return (SNMP_ERR_INCONS_VALUE); 993 994 ctx->scratch->int1 = RowStatus_destroy; 995 996 if (bridge_name_index_get(&val->var, sub, bif_name) == NULL) 997 return (SNMP_ERR_BADVALUE); 998 if (bridge_if_create(bif_name, 1) < 0) 999 return (SNMP_ERR_GENERR); 1000 return (SNMP_ERR_NOERROR); 1001 1002 case RowStatus_createAndWait: 1003 if (bif != NULL) 1004 return (SNMP_ERR_INCONS_VALUE); 1005 1006 if (bridge_name_index_get(&val->var, sub, bif_name) == NULL) 1007 return (SNMP_ERR_BADVALUE); 1008 1009 ctx->scratch->int1 = RowStatus_destroy; 1010 1011 if (bridge_if_create(bif_name, 0) < 0) 1012 return (SNMP_ERR_GENERR); 1013 return (SNMP_ERR_NOERROR); 1014 1015 case RowStatus_destroy: 1016 if (bif == NULL) 1017 return (SNMP_ERR_NOSUCHNAME); 1018 1019 ctx->scratch->int1 = bif->if_status; 1020 bif->if_status = RowStatus_destroy; 1021 } 1022 1023 return (SNMP_ERR_NOERROR); 1024} 1025 1026static int 1027bridge_rollback_if_status(struct snmp_context *ctx, 1028 struct snmp_value *val, uint sub) 1029{ 1030 struct bridge_if *bif; 1031 1032 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1033 return (SNMP_ERR_GENERR); 1034 1035 switch (ctx->scratch->int1) { 1036 case RowStatus_destroy: 1037 bridge_if_destroy(bif); 1038 return (SNMP_ERR_NOERROR); 1039 1040 case RowStatus_notInService: 1041 if (bif->if_status != ctx->scratch->int1) 1042 bridge_set_if_up(bif->bif_name, 0); 1043 bif->if_status = RowStatus_notInService; 1044 return (SNMP_ERR_NOERROR); 1045 1046 case RowStatus_active: 1047 if (bif->if_status != ctx->scratch->int1) 1048 bridge_set_if_up(bif->bif_name, 1); 1049 bif->if_status = RowStatus_active; 1050 return (SNMP_ERR_NOERROR); 1051 } 1052 1053 abort(); 1054} 1055 1056static int 1057bridge_commit_if_status(struct snmp_value *val, uint sub) 1058{ 1059 struct bridge_if *bif; 1060 1061 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1062 return (SNMP_ERR_GENERR); 1063 1064 if (bif->if_status == RowStatus_destroy && 1065 bridge_if_destroy(bif) < 0) 1066 return (SNMP_ERR_COMMIT_FAILED); 1067 1068 return (SNMP_ERR_NOERROR); 1069} 1070 1071int 1072op_begemot_base_bridge(struct snmp_context *ctx, struct snmp_value *val, 1073 uint sub, uint iidx __unused, enum snmp_op op) 1074{ 1075 int ret; 1076 struct bridge_if *bif = NULL; 1077 1078 if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1079 bridge_update_all_ifs(); 1080 1081 switch (op) { 1082 case SNMP_OP_GET: 1083 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1084 return (SNMP_ERR_NOSUCHNAME); 1085 break; 1086 1087 case SNMP_OP_GETNEXT: 1088 if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1089 return (SNMP_ERR_NOSUCHNAME); 1090 bridge_if_index_append(&val->var, sub, bif); 1091 break; 1092 1093 case SNMP_OP_SET: 1094 switch (val->var.subs[sub - 1]) { 1095 case LEAF_begemotBridgeBaseStatus: 1096 return (bridge_set_if_status(ctx, val, sub)); 1097 case LEAF_begemotBridgeBaseName: 1098 case LEAF_begemotBridgeBaseAddress: 1099 case LEAF_begemotBridgeBaseNumPorts: 1100 case LEAF_begemotBridgeBaseType: 1101 return (SNMP_ERR_NOT_WRITEABLE); 1102 } 1103 abort(); 1104 1105 case SNMP_OP_ROLLBACK: 1106 return (bridge_rollback_if_status(ctx, val, sub)); 1107 case SNMP_OP_COMMIT: 1108 return (bridge_commit_if_status(val, sub)); 1109 } 1110 1111 ret = SNMP_ERR_NOERROR; 1112 switch (val->var.subs[sub - 1]) { 1113 case LEAF_begemotBridgeBaseName: 1114 ret = string_get(val, bif->bif_name, -1); 1115 break; 1116 1117 case LEAF_begemotBridgeBaseAddress: 1118 ret = string_get(val, bif->br_addr.octet, ETHER_ADDR_LEN); 1119 break; 1120 1121 case LEAF_begemotBridgeBaseNumPorts: 1122 val->v.integer = bif->num_ports; 1123 break; 1124 1125 case LEAF_begemotBridgeBaseType: 1126 val->v.integer = bif->br_type; 1127 break; 1128 1129 case LEAF_begemotBridgeBaseStatus: 1130 val->v.integer = bif->if_status; 1131 break; 1132 } 1133 1134 return (ret); 1135} 1136 1137int 1138op_begemot_stp(struct snmp_context *ctx, struct snmp_value *val, 1139 uint sub, uint iidx __unused, enum snmp_op op) 1140{ 1141 int ret = SNMP_ERR_NOERROR; /* Make the compiler happy. */ 1142 struct bridge_if *bif = NULL; 1143 1144 if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1145 bridge_update_all_ifs(); 1146 1147 switch (op) { 1148 case SNMP_OP_GET: 1149 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1150 return (SNMP_ERR_NOSUCHNAME); 1151 break; 1152 1153 case SNMP_OP_GETNEXT: 1154 if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1155 return (SNMP_ERR_NOSUCHNAME); 1156 bridge_if_index_append(&val->var, sub, bif); 1157 break; 1158 1159 case SNMP_OP_SET: 1160 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1161 return (SNMP_ERR_NOSUCHNAME); 1162 1163 switch (val->var.subs[sub - 1]) { 1164 case LEAF_begemotBridgeStpPriority: 1165 ctx->scratch->int1 = bif->priority; 1166 ret = bridge_set_priority(bif, val->v.integer); 1167 break; 1168 1169 case LEAF_begemotBridgeStpBridgeMaxAge: 1170 ctx->scratch->int1 = bif->bridge_max_age; 1171 ret = bridge_set_maxage(bif, val->v.integer); 1172 break; 1173 1174 case LEAF_begemotBridgeStpBridgeHelloTime: 1175 ctx->scratch->int1 = bif->bridge_hello_time; 1176 ret = bridge_set_hello_time(bif, val->v.integer); 1177 break; 1178 1179 case LEAF_begemotBridgeStpBridgeForwardDelay: 1180 ctx->scratch->int1 = bif->bridge_fwd_delay; 1181 ret = bridge_set_forward_delay(bif, val->v.integer); 1182 break; 1183
| 881 return (SNMP_ERR_NOERROR); 882 883 case SNMP_OP_COMMIT: 884 return (SNMP_ERR_NOERROR); 885 } 886 887 return (SNMP_ERR_NOERROR); 888} 889 890/* 891 * Private BEGEMOT-BRIDGE-MIB specifics. 892 */ 893 894/* 895 * Get the bridge name from an OID index. 896 */ 897static char * 898bridge_name_index_get(const struct asn_oid *oid, uint sub, char *b_name) 899{ 900 uint i; 901 902 if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 903 return (NULL); 904 905 for (i = 0; i < oid->subs[sub]; i++) 906 b_name[i] = oid->subs[sub + i + 1]; 907 b_name[i] = '\0'; 908 909 return (b_name); 910} 911 912static void 913bridge_if_index_append(struct asn_oid *oid, uint sub, 914 const struct bridge_if *bif) 915{ 916 uint i; 917 918 oid->len = sub + strlen(bif->bif_name) + 1; 919 oid->subs[sub] = strlen(bif->bif_name); 920 921 for (i = 1; i <= strlen(bif->bif_name); i++) 922 oid->subs[sub + i] = bif->bif_name[i - 1]; 923} 924 925static struct bridge_if * 926bridge_if_index_get(const struct asn_oid *oid, uint sub) 927{ 928 uint i; 929 char bif_name[IFNAMSIZ]; 930 931 if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 932 return (NULL); 933 934 for (i = 0; i < oid->subs[sub]; i++) 935 bif_name[i] = oid->subs[sub + i + 1]; 936 bif_name[i] = '\0'; 937 938 return (bridge_if_find_ifname(bif_name)); 939} 940 941static struct bridge_if * 942bridge_if_index_getnext(const struct asn_oid *oid, uint sub) 943{ 944 uint i; 945 char bif_name[IFNAMSIZ]; 946 struct bridge_if *bif; 947 948 if (oid->len - sub == 0) 949 return (bridge_first_bif()); 950 951 if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) 952 return (NULL); 953 954 for (i = 0; i < oid->subs[sub]; i++) 955 bif_name[i] = oid->subs[sub + i + 1]; 956 bif_name[i] = '\0'; 957 958 if ((bif = bridge_if_find_ifname(bif_name)) == NULL) 959 return (NULL); 960 961 return (bridge_next_bif(bif)); 962} 963 964static int 965bridge_set_if_status(struct snmp_context *ctx, 966 struct snmp_value *val, uint sub) 967{ 968 struct bridge_if *bif; 969 char bif_name[IFNAMSIZ]; 970 971 bif = bridge_if_index_get(&val->var, sub); 972 973 switch (val->v.integer) { 974 case RowStatus_active: 975 if (bif == NULL) 976 return (SNMP_ERR_INCONS_VALUE); 977 978 ctx->scratch->int1 = bif->if_status; 979 980 switch (bif->if_status) { 981 case RowStatus_active: 982 return (SNMP_ERR_NOERROR); 983 case RowStatus_notInService: 984 if (bridge_set_if_up(bif->bif_name, 1) < 0) 985 return (SNMP_ERR_GENERR); 986 return (SNMP_ERR_NOERROR); 987 default: 988 break; 989 } 990 return (SNMP_ERR_INCONS_VALUE); 991 992 case RowStatus_notInService: 993 if (bif == NULL) 994 return (SNMP_ERR_INCONS_VALUE); 995 996 ctx->scratch->int1 = bif->if_status; 997 998 switch (bif->if_status) { 999 case RowStatus_active: 1000 if (bridge_set_if_up(bif->bif_name, 1) < 0) 1001 return (SNMP_ERR_GENERR); 1002 return (SNMP_ERR_NOERROR); 1003 case RowStatus_notInService: 1004 return (SNMP_ERR_NOERROR); 1005 default: 1006 break; 1007 } 1008 return (SNMP_ERR_INCONS_VALUE); 1009 1010 case RowStatus_notReady: 1011 return (SNMP_ERR_INCONS_VALUE); 1012 1013 case RowStatus_createAndGo: 1014 if (bif != NULL) 1015 return (SNMP_ERR_INCONS_VALUE); 1016 1017 ctx->scratch->int1 = RowStatus_destroy; 1018 1019 if (bridge_name_index_get(&val->var, sub, bif_name) == NULL) 1020 return (SNMP_ERR_BADVALUE); 1021 if (bridge_if_create(bif_name, 1) < 0) 1022 return (SNMP_ERR_GENERR); 1023 return (SNMP_ERR_NOERROR); 1024 1025 case RowStatus_createAndWait: 1026 if (bif != NULL) 1027 return (SNMP_ERR_INCONS_VALUE); 1028 1029 if (bridge_name_index_get(&val->var, sub, bif_name) == NULL) 1030 return (SNMP_ERR_BADVALUE); 1031 1032 ctx->scratch->int1 = RowStatus_destroy; 1033 1034 if (bridge_if_create(bif_name, 0) < 0) 1035 return (SNMP_ERR_GENERR); 1036 return (SNMP_ERR_NOERROR); 1037 1038 case RowStatus_destroy: 1039 if (bif == NULL) 1040 return (SNMP_ERR_NOSUCHNAME); 1041 1042 ctx->scratch->int1 = bif->if_status; 1043 bif->if_status = RowStatus_destroy; 1044 } 1045 1046 return (SNMP_ERR_NOERROR); 1047} 1048 1049static int 1050bridge_rollback_if_status(struct snmp_context *ctx, 1051 struct snmp_value *val, uint sub) 1052{ 1053 struct bridge_if *bif; 1054 1055 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1056 return (SNMP_ERR_GENERR); 1057 1058 switch (ctx->scratch->int1) { 1059 case RowStatus_destroy: 1060 bridge_if_destroy(bif); 1061 return (SNMP_ERR_NOERROR); 1062 1063 case RowStatus_notInService: 1064 if (bif->if_status != ctx->scratch->int1) 1065 bridge_set_if_up(bif->bif_name, 0); 1066 bif->if_status = RowStatus_notInService; 1067 return (SNMP_ERR_NOERROR); 1068 1069 case RowStatus_active: 1070 if (bif->if_status != ctx->scratch->int1) 1071 bridge_set_if_up(bif->bif_name, 1); 1072 bif->if_status = RowStatus_active; 1073 return (SNMP_ERR_NOERROR); 1074 } 1075 1076 abort(); 1077} 1078 1079static int 1080bridge_commit_if_status(struct snmp_value *val, uint sub) 1081{ 1082 struct bridge_if *bif; 1083 1084 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1085 return (SNMP_ERR_GENERR); 1086 1087 if (bif->if_status == RowStatus_destroy && 1088 bridge_if_destroy(bif) < 0) 1089 return (SNMP_ERR_COMMIT_FAILED); 1090 1091 return (SNMP_ERR_NOERROR); 1092} 1093 1094int 1095op_begemot_base_bridge(struct snmp_context *ctx, struct snmp_value *val, 1096 uint sub, uint iidx __unused, enum snmp_op op) 1097{ 1098 int ret; 1099 struct bridge_if *bif = NULL; 1100 1101 if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1102 bridge_update_all_ifs(); 1103 1104 switch (op) { 1105 case SNMP_OP_GET: 1106 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1107 return (SNMP_ERR_NOSUCHNAME); 1108 break; 1109 1110 case SNMP_OP_GETNEXT: 1111 if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1112 return (SNMP_ERR_NOSUCHNAME); 1113 bridge_if_index_append(&val->var, sub, bif); 1114 break; 1115 1116 case SNMP_OP_SET: 1117 switch (val->var.subs[sub - 1]) { 1118 case LEAF_begemotBridgeBaseStatus: 1119 return (bridge_set_if_status(ctx, val, sub)); 1120 case LEAF_begemotBridgeBaseName: 1121 case LEAF_begemotBridgeBaseAddress: 1122 case LEAF_begemotBridgeBaseNumPorts: 1123 case LEAF_begemotBridgeBaseType: 1124 return (SNMP_ERR_NOT_WRITEABLE); 1125 } 1126 abort(); 1127 1128 case SNMP_OP_ROLLBACK: 1129 return (bridge_rollback_if_status(ctx, val, sub)); 1130 case SNMP_OP_COMMIT: 1131 return (bridge_commit_if_status(val, sub)); 1132 } 1133 1134 ret = SNMP_ERR_NOERROR; 1135 switch (val->var.subs[sub - 1]) { 1136 case LEAF_begemotBridgeBaseName: 1137 ret = string_get(val, bif->bif_name, -1); 1138 break; 1139 1140 case LEAF_begemotBridgeBaseAddress: 1141 ret = string_get(val, bif->br_addr.octet, ETHER_ADDR_LEN); 1142 break; 1143 1144 case LEAF_begemotBridgeBaseNumPorts: 1145 val->v.integer = bif->num_ports; 1146 break; 1147 1148 case LEAF_begemotBridgeBaseType: 1149 val->v.integer = bif->br_type; 1150 break; 1151 1152 case LEAF_begemotBridgeBaseStatus: 1153 val->v.integer = bif->if_status; 1154 break; 1155 } 1156 1157 return (ret); 1158} 1159 1160int 1161op_begemot_stp(struct snmp_context *ctx, struct snmp_value *val, 1162 uint sub, uint iidx __unused, enum snmp_op op) 1163{ 1164 int ret = SNMP_ERR_NOERROR; /* Make the compiler happy. */ 1165 struct bridge_if *bif = NULL; 1166 1167 if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1168 bridge_update_all_ifs(); 1169 1170 switch (op) { 1171 case SNMP_OP_GET: 1172 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1173 return (SNMP_ERR_NOSUCHNAME); 1174 break; 1175 1176 case SNMP_OP_GETNEXT: 1177 if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1178 return (SNMP_ERR_NOSUCHNAME); 1179 bridge_if_index_append(&val->var, sub, bif); 1180 break; 1181 1182 case SNMP_OP_SET: 1183 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1184 return (SNMP_ERR_NOSUCHNAME); 1185 1186 switch (val->var.subs[sub - 1]) { 1187 case LEAF_begemotBridgeStpPriority: 1188 ctx->scratch->int1 = bif->priority; 1189 ret = bridge_set_priority(bif, val->v.integer); 1190 break; 1191 1192 case LEAF_begemotBridgeStpBridgeMaxAge: 1193 ctx->scratch->int1 = bif->bridge_max_age; 1194 ret = bridge_set_maxage(bif, val->v.integer); 1195 break; 1196 1197 case LEAF_begemotBridgeStpBridgeHelloTime: 1198 ctx->scratch->int1 = bif->bridge_hello_time; 1199 ret = bridge_set_hello_time(bif, val->v.integer); 1200 break; 1201 1202 case LEAF_begemotBridgeStpBridgeForwardDelay: 1203 ctx->scratch->int1 = bif->bridge_fwd_delay; 1204 ret = bridge_set_forward_delay(bif, val->v.integer); 1205 break; 1206
|
| 1207 case LEAF_begemotBridgeStpVersion: 1208 ctx->scratch->int1 = bif->stp_version; 1209 ret = bridge_set_stp_version(bif, val->v.integer); 1210 break; 1211 1212 case LEAF_begemotBridgeStpTxHoldCount: 1213 ctx->scratch->int1 = bif->tx_hold_count; 1214 ret = bridge_set_tx_hold_count(bif, val->v.integer); 1215 break; 1216
|
1184 case LEAF_begemotBridgeStpProtocolSpecification: 1185 case LEAF_begemotBridgeStpTimeSinceTopologyChange: 1186 case LEAF_begemotBridgeStpTopChanges: 1187 case LEAF_begemotBridgeStpDesignatedRoot: 1188 case LEAF_begemotBridgeStpRootCost: 1189 case LEAF_begemotBridgeStpRootPort: 1190 case LEAF_begemotBridgeStpMaxAge: 1191 case LEAF_begemotBridgeStpHelloTime: 1192 case LEAF_begemotBridgeStpHoldTime: 1193 case LEAF_begemotBridgeStpForwardDelay: 1194 return (SNMP_ERR_NOT_WRITEABLE); 1195 } 1196 1197 if (ret == 0) 1198 return (SNMP_ERR_NOERROR); 1199 else if (ret == -2) 1200 return (SNMP_ERR_WRONG_VALUE); 1201 return (SNMP_ERR_GENERR); 1202 1203 case SNMP_OP_ROLLBACK: 1204 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1205 return (SNMP_ERR_NOSUCHNAME); 1206 1207 switch (val->var.subs[sub - 1]) { 1208 case LEAF_begemotBridgeStpPriority: 1209 bridge_set_priority(bif, ctx->scratch->int1); 1210 break; 1211 1212 case LEAF_begemotBridgeStpBridgeMaxAge: 1213 bridge_set_maxage(bif, ctx->scratch->int1); 1214 break; 1215 1216 case LEAF_begemotBridgeStpBridgeHelloTime: 1217 bridge_set_hello_time(bif, ctx->scratch->int1); 1218 break; 1219 1220 case LEAF_begemotBridgeStpBridgeForwardDelay: 1221 bridge_set_forward_delay(bif, ctx->scratch->int1); 1222 break;
| 1217 case LEAF_begemotBridgeStpProtocolSpecification: 1218 case LEAF_begemotBridgeStpTimeSinceTopologyChange: 1219 case LEAF_begemotBridgeStpTopChanges: 1220 case LEAF_begemotBridgeStpDesignatedRoot: 1221 case LEAF_begemotBridgeStpRootCost: 1222 case LEAF_begemotBridgeStpRootPort: 1223 case LEAF_begemotBridgeStpMaxAge: 1224 case LEAF_begemotBridgeStpHelloTime: 1225 case LEAF_begemotBridgeStpHoldTime: 1226 case LEAF_begemotBridgeStpForwardDelay: 1227 return (SNMP_ERR_NOT_WRITEABLE); 1228 } 1229 1230 if (ret == 0) 1231 return (SNMP_ERR_NOERROR); 1232 else if (ret == -2) 1233 return (SNMP_ERR_WRONG_VALUE); 1234 return (SNMP_ERR_GENERR); 1235 1236 case SNMP_OP_ROLLBACK: 1237 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1238 return (SNMP_ERR_NOSUCHNAME); 1239 1240 switch (val->var.subs[sub - 1]) { 1241 case LEAF_begemotBridgeStpPriority: 1242 bridge_set_priority(bif, ctx->scratch->int1); 1243 break; 1244 1245 case LEAF_begemotBridgeStpBridgeMaxAge: 1246 bridge_set_maxage(bif, ctx->scratch->int1); 1247 break; 1248 1249 case LEAF_begemotBridgeStpBridgeHelloTime: 1250 bridge_set_hello_time(bif, ctx->scratch->int1); 1251 break; 1252 1253 case LEAF_begemotBridgeStpBridgeForwardDelay: 1254 bridge_set_forward_delay(bif, ctx->scratch->int1); 1255 break;
|
| 1256 1257 case LEAF_begemotBridgeStpVersion: 1258 bridge_set_stp_version(bif, ctx->scratch->int1); 1259 break; 1260 1261 case LEAF_begemotBridgeStpTxHoldCount: 1262 bridge_set_tx_hold_count(bif, ctx->scratch->int1); 1263 break;
|
1223 } 1224 return (SNMP_ERR_NOERROR); 1225 1226 case SNMP_OP_COMMIT: 1227 return (SNMP_ERR_NOERROR); 1228 } 1229 1230 switch (val->var.subs[sub - 1]) { 1231 case LEAF_begemotBridgeStpProtocolSpecification: 1232 val->v.integer = bif->prot_spec; 1233 break; 1234 1235 case LEAF_begemotBridgeStpPriority: 1236 val->v.integer = bif->priority; 1237 break; 1238 1239 case LEAF_begemotBridgeStpTimeSinceTopologyChange: 1240 if (bridge_get_time_since_tc(bif, &(val->v.uint32)) < 0) 1241 return (SNMP_ERR_GENERR); 1242 break; 1243 1244 case LEAF_begemotBridgeStpTopChanges: 1245 val->v.uint32 = bif->top_changes; 1246 break; 1247 1248 case LEAF_begemotBridgeStpDesignatedRoot: 1249 ret = string_get(val, bif->design_root, SNMP_BRIDGE_ID_LEN); 1250 break; 1251 1252 case LEAF_begemotBridgeStpRootCost: 1253 val->v.integer = bif->root_cost; 1254 break; 1255 1256 case LEAF_begemotBridgeStpRootPort: 1257 val->v.integer = bif->root_port; 1258 break; 1259 1260 case LEAF_begemotBridgeStpMaxAge: 1261 val->v.integer = bif->max_age; 1262 break; 1263 1264 case LEAF_begemotBridgeStpHelloTime: 1265 val->v.integer = bif->hello_time; 1266 break; 1267 1268 case LEAF_begemotBridgeStpHoldTime: 1269 val->v.integer = bif->hold_time; 1270 break; 1271 1272 case LEAF_begemotBridgeStpForwardDelay: 1273 val->v.integer = bif->fwd_delay; 1274 break; 1275 1276 case LEAF_begemotBridgeStpBridgeMaxAge: 1277 val->v.integer = bif->bridge_max_age; 1278 break; 1279 1280 case LEAF_begemotBridgeStpBridgeHelloTime: 1281 val->v.integer = bif->bridge_hello_time; 1282 break; 1283 1284 case LEAF_begemotBridgeStpBridgeForwardDelay: 1285 val->v.integer = bif->bridge_fwd_delay; 1286 break;
| 1264 } 1265 return (SNMP_ERR_NOERROR); 1266 1267 case SNMP_OP_COMMIT: 1268 return (SNMP_ERR_NOERROR); 1269 } 1270 1271 switch (val->var.subs[sub - 1]) { 1272 case LEAF_begemotBridgeStpProtocolSpecification: 1273 val->v.integer = bif->prot_spec; 1274 break; 1275 1276 case LEAF_begemotBridgeStpPriority: 1277 val->v.integer = bif->priority; 1278 break; 1279 1280 case LEAF_begemotBridgeStpTimeSinceTopologyChange: 1281 if (bridge_get_time_since_tc(bif, &(val->v.uint32)) < 0) 1282 return (SNMP_ERR_GENERR); 1283 break; 1284 1285 case LEAF_begemotBridgeStpTopChanges: 1286 val->v.uint32 = bif->top_changes; 1287 break; 1288 1289 case LEAF_begemotBridgeStpDesignatedRoot: 1290 ret = string_get(val, bif->design_root, SNMP_BRIDGE_ID_LEN); 1291 break; 1292 1293 case LEAF_begemotBridgeStpRootCost: 1294 val->v.integer = bif->root_cost; 1295 break; 1296 1297 case LEAF_begemotBridgeStpRootPort: 1298 val->v.integer = bif->root_port; 1299 break; 1300 1301 case LEAF_begemotBridgeStpMaxAge: 1302 val->v.integer = bif->max_age; 1303 break; 1304 1305 case LEAF_begemotBridgeStpHelloTime: 1306 val->v.integer = bif->hello_time; 1307 break; 1308 1309 case LEAF_begemotBridgeStpHoldTime: 1310 val->v.integer = bif->hold_time; 1311 break; 1312 1313 case LEAF_begemotBridgeStpForwardDelay: 1314 val->v.integer = bif->fwd_delay; 1315 break; 1316 1317 case LEAF_begemotBridgeStpBridgeMaxAge: 1318 val->v.integer = bif->bridge_max_age; 1319 break; 1320 1321 case LEAF_begemotBridgeStpBridgeHelloTime: 1322 val->v.integer = bif->bridge_hello_time; 1323 break; 1324 1325 case LEAF_begemotBridgeStpBridgeForwardDelay: 1326 val->v.integer = bif->bridge_fwd_delay; 1327 break;
|
| 1328 1329 case LEAF_begemotBridgeStpVersion: 1330 val->v.integer = bif->stp_version; 1331 break; 1332 1333 case LEAF_begemotBridgeStpTxHoldCount: 1334 val->v.integer = bif->tx_hold_count; 1335 break;
|
1287 } 1288 1289 return (ret); 1290} 1291 1292int 1293op_begemot_tp(struct snmp_context *ctx, struct snmp_value *val, 1294 uint sub, uint iidx __unused, enum snmp_op op) 1295{ 1296 struct bridge_if *bif = NULL; 1297 1298 if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1299 bridge_update_all_ifs(); 1300 1301 switch (op) { 1302 case SNMP_OP_GET: 1303 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1304 return (SNMP_ERR_NOSUCHNAME); 1305 break; 1306 1307 case SNMP_OP_GETNEXT: 1308 if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1309 return (SNMP_ERR_NOSUCHNAME); 1310 bridge_if_index_append(&val->var, sub, bif); 1311 break; 1312 1313 case SNMP_OP_SET: 1314 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1315 return (SNMP_ERR_NOSUCHNAME); 1316 1317 switch (val->var.subs[sub - 1]) { 1318 case LEAF_begemotBridgeTpAgingTime: 1319 ctx->scratch->int1 = bif->age_time; 1320 if (bridge_set_aging_time(bif, val->v.integer) < 0) 1321 return (SNMP_ERR_GENERR); 1322 return (SNMP_ERR_NOERROR); 1323 1324 case LEAF_begemotBridgeTpMaxAddresses: 1325 ctx->scratch->int1 = bif->max_addrs; 1326 if (bridge_set_max_cache(bif, val->v.integer) < 0) 1327 return (SNMP_ERR_GENERR); 1328 return (SNMP_ERR_NOERROR); 1329 1330 case LEAF_begemotBridgeTpLearnedEntryDiscards: 1331 return (SNMP_ERR_NOT_WRITEABLE); 1332 } 1333 abort(); 1334 1335 case SNMP_OP_ROLLBACK: 1336 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1337 return (SNMP_ERR_GENERR); 1338 1339 switch (val->var.subs[sub - 1]) { 1340 case LEAF_begemotBridgeTpAgingTime: 1341 bridge_set_aging_time(bif, ctx->scratch->int1); 1342 break; 1343 1344 case LEAF_begemotBridgeTpMaxAddresses: 1345 bridge_set_max_cache(bif, ctx->scratch->int1); 1346 break; 1347 } 1348 return (SNMP_ERR_NOERROR); 1349 1350 case SNMP_OP_COMMIT: 1351 return (SNMP_ERR_NOERROR); 1352 } 1353 1354 switch (val->var.subs[sub - 1]) { 1355 case LEAF_begemotBridgeTpLearnedEntryDiscards: 1356 val->v.uint32 = bif->lrnt_drops; 1357 break; 1358 1359 case LEAF_begemotBridgeTpAgingTime: 1360 val->v.integer = bif->age_time; 1361 break; 1362 1363 case LEAF_begemotBridgeTpMaxAddresses: 1364 val->v.integer = bif->max_addrs; 1365 break; 1366 } 1367 1368 return (SNMP_ERR_NOERROR); 1369}
| 1336 } 1337 1338 return (ret); 1339} 1340 1341int 1342op_begemot_tp(struct snmp_context *ctx, struct snmp_value *val, 1343 uint sub, uint iidx __unused, enum snmp_op op) 1344{ 1345 struct bridge_if *bif = NULL; 1346 1347 if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) 1348 bridge_update_all_ifs(); 1349 1350 switch (op) { 1351 case SNMP_OP_GET: 1352 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1353 return (SNMP_ERR_NOSUCHNAME); 1354 break; 1355 1356 case SNMP_OP_GETNEXT: 1357 if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) 1358 return (SNMP_ERR_NOSUCHNAME); 1359 bridge_if_index_append(&val->var, sub, bif); 1360 break; 1361 1362 case SNMP_OP_SET: 1363 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1364 return (SNMP_ERR_NOSUCHNAME); 1365 1366 switch (val->var.subs[sub - 1]) { 1367 case LEAF_begemotBridgeTpAgingTime: 1368 ctx->scratch->int1 = bif->age_time; 1369 if (bridge_set_aging_time(bif, val->v.integer) < 0) 1370 return (SNMP_ERR_GENERR); 1371 return (SNMP_ERR_NOERROR); 1372 1373 case LEAF_begemotBridgeTpMaxAddresses: 1374 ctx->scratch->int1 = bif->max_addrs; 1375 if (bridge_set_max_cache(bif, val->v.integer) < 0) 1376 return (SNMP_ERR_GENERR); 1377 return (SNMP_ERR_NOERROR); 1378 1379 case LEAF_begemotBridgeTpLearnedEntryDiscards: 1380 return (SNMP_ERR_NOT_WRITEABLE); 1381 } 1382 abort(); 1383 1384 case SNMP_OP_ROLLBACK: 1385 if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) 1386 return (SNMP_ERR_GENERR); 1387 1388 switch (val->var.subs[sub - 1]) { 1389 case LEAF_begemotBridgeTpAgingTime: 1390 bridge_set_aging_time(bif, ctx->scratch->int1); 1391 break; 1392 1393 case LEAF_begemotBridgeTpMaxAddresses: 1394 bridge_set_max_cache(bif, ctx->scratch->int1); 1395 break; 1396 } 1397 return (SNMP_ERR_NOERROR); 1398 1399 case SNMP_OP_COMMIT: 1400 return (SNMP_ERR_NOERROR); 1401 } 1402 1403 switch (val->var.subs[sub - 1]) { 1404 case LEAF_begemotBridgeTpLearnedEntryDiscards: 1405 val->v.uint32 = bif->lrnt_drops; 1406 break; 1407 1408 case LEAF_begemotBridgeTpAgingTime: 1409 val->v.integer = bif->age_time; 1410 break; 1411 1412 case LEAF_begemotBridgeTpMaxAddresses: 1413 val->v.integer = bif->max_addrs; 1414 break; 1415 } 1416 1417 return (SNMP_ERR_NOERROR); 1418}
|