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 ports. 28 * 29 * $FreeBSD$ 30 */ 31 32 #include <sys/queue.h> 33 #include <sys/socket.h> 34 #include <sys/types.h> 35 36 #include <net/ethernet.h> 37 #include <net/if.h> 38 #include <net/if_mib.h> 39 40 #include <assert.h> 41 #include <errno.h> 42 #include <stdarg.h> 43 #include <string.h> 44 #include <stdlib.h> 45 #include <syslog.h> 46 47 #include <bsnmp/snmpmod.h> 48 #include <bsnmp/snmp_mibII.h> 49 50 #include "bridge_tree.h" 51 #include "bridge_snmp.h" 52 53 TAILQ_HEAD(bridge_ports, bridge_port); 54 55 /* 56 * Free the bridge base ports list. 57 */ 58 static void 59 bridge_ports_free(struct bridge_ports *headp) 60 { 61 struct bridge_port *bp; 62 63 while ((bp = TAILQ_FIRST(headp)) != NULL) { 64 TAILQ_REMOVE(headp, bp, b_p); 65 free(bp); 66 } 67 } 68 69 /* 70 * Free the bridge base ports from the base ports list, 71 * members of a specified bridge interface only. 72 */ 73 static void 74 bridge_port_memif_free(struct bridge_ports *headp, 75 struct bridge_if *bif) 76 { 77 struct bridge_port *bp; 78 79 while (bif->f_bp != NULL && bif->sysindex == bif->f_bp->sysindex) { 80 bp = TAILQ_NEXT(bif->f_bp, b_p); 81 TAILQ_REMOVE(headp, bif->f_bp, b_p); 82 free(bif->f_bp); 83 bif->f_bp = bp; 84 } 85 } 86 87 /* 88 * Insert a port entry in the base port TAILQ starting to search 89 * for its place from the position of the first bridge port for the bridge 90 * interface. Update the first bridge port if neccessary. 91 */ 92 static void 93 bridge_port_insert_at(struct bridge_ports *headp, 94 struct bridge_port *bp, struct bridge_port **f_bp) 95 { 96 struct bridge_port *t1; 97 98 assert(f_bp != NULL); 99 100 for (t1 = *f_bp; 101 t1 != NULL && bp->sysindex == t1->sysindex; 102 t1 = TAILQ_NEXT(t1, b_p)) { 103 if (bp->if_idx < t1->if_idx) { 104 TAILQ_INSERT_BEFORE(t1, bp, b_p); 105 if (*f_bp == t1) 106 *f_bp = bp; 107 return; 108 } 109 } 110 111 /* 112 * Handle the case when our first port was actually the 113 * last element of the TAILQ. 114 */ 115 if (t1 == NULL) 116 TAILQ_INSERT_TAIL(headp, bp, b_p); 117 else 118 TAILQ_INSERT_BEFORE(t1, bp, b_p); 119 } 120 121 /* 122 * Find a port entry's possition in the ports list according 123 * to it's parent bridge interface name. Returns a NULL if 124 * we should be at the TAILQ head, otherwise the entry after 125 * which we should be inserted. 126 */ 127 static struct bridge_port * 128 bridge_port_find_pos(struct bridge_ports *headp, uint32_t b_idx) 129 { 130 uint32_t t_idx; 131 struct bridge_port *t1; 132 133 if ((t1 = TAILQ_FIRST(headp)) == NULL || 134 bridge_compare_sysidx(b_idx, t1->sysindex) < 0) 135 return (NULL); 136 137 t_idx = t1->sysindex; 138 139 for (t1 = TAILQ_NEXT(t1, b_p); t1 != NULL; t1 = TAILQ_NEXT(t1, b_p)) { 140 if (t1->sysindex != t_idx) { 141 if (bridge_compare_sysidx(b_idx, t1->sysindex) < 0) 142 return (TAILQ_PREV(t1, bridge_ports, b_p)); 143 else 144 t_idx = t1->sysindex; 145 } 146 } 147 148 if (t1 == NULL) 149 t1 = TAILQ_LAST(headp, bridge_ports); 150 151 return (t1); 152 } 153 154 /* 155 * Insert a bridge member interface in the ports TAILQ. 156 */ 157 static void 158 bridge_port_memif_insert(struct bridge_ports *headp, 159 struct bridge_port *bp, struct bridge_port **f_bp) 160 { 161 struct bridge_port *temp; 162 163 if (*f_bp != NULL) 164 bridge_port_insert_at(headp, bp, f_bp); 165 else { 166 temp = bridge_port_find_pos(headp, bp->sysindex); 167 168 if (temp == NULL) 169 TAILQ_INSERT_HEAD(headp, bp, b_p); 170 else 171 TAILQ_INSERT_AFTER(headp, temp, bp, b_p); 172 *f_bp = bp; 173 } 174 } 175 176 /* The global ports list. */ 177 static struct bridge_ports bridge_ports = TAILQ_HEAD_INITIALIZER(bridge_ports); 178 static time_t ports_list_age; 179 180 void 181 bridge_ports_update_listage(void) 182 { 183 ports_list_age = time(NULL); 184 } 185 186 void 187 bridge_ports_fini(void) 188 { 189 bridge_ports_free(&bridge_ports); 190 } 191 192 void 193 bridge_members_free(struct bridge_if *bif) 194 { 195 bridge_port_memif_free(&bridge_ports, bif); 196 } 197 198 /* 199 * Find the first port in the ports list. 200 */ 201 static struct bridge_port * 202 bridge_port_first(void) 203 { 204 return (TAILQ_FIRST(&bridge_ports)); 205 } 206 207 /* 208 * Find the next port in the ports list. 209 */ 210 static struct bridge_port * 211 bridge_port_next(struct bridge_port *bp) 212 { 213 return (TAILQ_NEXT(bp, b_p)); 214 } 215 216 /* 217 * Find the first member of the specified bridge interface. 218 */ 219 struct bridge_port * 220 bridge_port_bif_first(struct bridge_if *bif) 221 { 222 return (bif->f_bp); 223 } 224 225 /* 226 * Find the next member of the specified bridge interface. 227 */ 228 struct bridge_port * 229 bridge_port_bif_next(struct bridge_port *bp) 230 { 231 struct bridge_port *bp_next; 232 233 if ((bp_next = TAILQ_NEXT(bp, b_p)) == NULL || 234 bp_next->sysindex != bp->sysindex) 235 return (NULL); 236 237 return (bp_next); 238 } 239 240 /* 241 * Remove a bridge port from the ports list. 242 */ 243 void 244 bridge_port_remove(struct bridge_port *bp, struct bridge_if *bif) 245 { 246 if (bif->f_bp == bp) 247 bif->f_bp = bridge_port_bif_next(bp); 248 249 TAILQ_REMOVE(&bridge_ports, bp, b_p); 250 free(bp); 251 } 252 253 /* 254 * Allocate memory for a new bridge port and insert it 255 * in the base ports list. Return a pointer to the port's 256 * structure in case we want to do anything else with it. 257 */ 258 struct bridge_port * 259 bridge_new_port(struct mibif *mif, struct bridge_if *bif) 260 { 261 struct bridge_port *bp; 262 263 if ((bp = (struct bridge_port *) malloc(sizeof(*bp))) == NULL) { 264 syslog(LOG_ERR, "bridge new member: failed: %s", 265 strerror(errno)); 266 return (NULL); 267 } 268 269 bzero(bp, sizeof(*bp)); 270 271 bp->sysindex = bif->sysindex; 272 bp->if_idx = mif->index; 273 bp->port_no = mif->sysindex; 274 strlcpy(bp->p_name, mif->name, IFNAMSIZ); 275 bp->circuit = oid_zeroDotZero; 276 277 /* 278 * Initialize all rstpMib specific values to false/default. 279 * These will be set to their true values later if the bridge 280 * supports RSTP. 281 */ 282 bp->proto_migr = TruthValue_false; 283 bp->admin_edge = TruthValue_false; 284 bp->oper_edge = TruthValue_false; 285 bp->oper_ptp = TruthValue_false; 286 bp->admin_ptp = StpPortAdminPointToPointType_auto; 287 288 bridge_port_memif_insert(&bridge_ports, bp, &(bif->f_bp)); 289 290 return (bp); 291 } 292 293 /* 294 * Update our info from the corresponding mibII interface info. 295 */ 296 void 297 bridge_port_getinfo_mibif(struct mibif *m_if, struct bridge_port *bp) 298 { 299 bp->max_info = m_if->mib.ifmd_data.ifi_mtu; 300 bp->in_frames = m_if->mib.ifmd_data.ifi_ipackets; 301 bp->out_frames = m_if->mib.ifmd_data.ifi_opackets; 302 bp->in_drops = m_if->mib.ifmd_data.ifi_iqdrops; 303 } 304 305 /* 306 * Find a port, whose SNMP's mibII ifIndex matches one of the ports, 307 * members of the specified bridge interface. 308 */ 309 struct bridge_port * 310 bridge_port_find(int32_t if_idx, struct bridge_if *bif) 311 { 312 struct bridge_port *bp; 313 314 for (bp = bif->f_bp; bp != NULL; bp = TAILQ_NEXT(bp, b_p)) { 315 if (bp->sysindex != bif->sysindex) { 316 bp = NULL; 317 break; 318 } 319 320 if (bp->if_idx == if_idx) 321 break; 322 } 323 324 return (bp); 325 } 326 327 void 328 bridge_ports_dump(struct bridge_if *bif) 329 { 330 struct bridge_port *bp; 331 332 for (bp = bridge_port_bif_first(bif); bp != NULL; 333 bp = bridge_port_bif_next(bp)) { 334 syslog(LOG_ERR, "memif - %s, index - %d", 335 bp->p_name, bp->port_no); 336 } 337 } 338 339 /* 340 * RFC4188 specifics. 341 */ 342 int 343 op_dot1d_base_port(struct snmp_context *c __unused, struct snmp_value *val, 344 uint sub, uint iidx __unused, enum snmp_op op) 345 { 346 struct bridge_if *bif; 347 struct bridge_port *bp; 348 349 if ((bif = bridge_get_default()) == NULL) 350 return (SNMP_ERR_NOSUCHNAME); 351 352 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 353 bridge_update_memif(bif) <= 0) 354 return (SNMP_ERR_NOSUCHNAME); 355 356 switch (op) { 357 case SNMP_OP_GET: 358 if (val->var.len - sub != 1) 359 return (SNMP_ERR_NOSUCHNAME); 360 if ((bp = bridge_port_find(val->var.subs[sub], 361 bif)) == NULL) 362 return (SNMP_ERR_NOSUCHNAME); 363 goto get; 364 365 case SNMP_OP_GETNEXT: 366 if (val->var.len - sub == 0) { 367 if ((bp = bridge_port_bif_first(bif)) == NULL) 368 return (SNMP_ERR_NOSUCHNAME); 369 } else { 370 if ((bp = bridge_port_find(val->var.subs[sub], 371 bif)) == NULL || 372 (bp = bridge_port_bif_next(bp)) == NULL) 373 return (SNMP_ERR_NOSUCHNAME); 374 } 375 val->var.len = sub + 1; 376 val->var.subs[sub] = bp->port_no; 377 goto get; 378 379 case SNMP_OP_SET: 380 return (SNMP_ERR_NOT_WRITEABLE); 381 382 case SNMP_OP_ROLLBACK: 383 case SNMP_OP_COMMIT: 384 break; 385 } 386 abort(); 387 388 get: 389 switch (val->var.subs[sub - 1]) { 390 case LEAF_dot1dBasePort: 391 val->v.integer = bp->port_no; 392 return (SNMP_ERR_NOERROR); 393 394 case LEAF_dot1dBasePortIfIndex: 395 val->v.integer = bp->if_idx; 396 return (SNMP_ERR_NOERROR); 397 398 case LEAF_dot1dBasePortCircuit: 399 val->v.oid = bp->circuit; 400 return (SNMP_ERR_NOERROR); 401 402 case LEAF_dot1dBasePortDelayExceededDiscards: 403 val->v.uint32 = bp->dly_ex_drops; 404 return (SNMP_ERR_NOERROR); 405 406 case LEAF_dot1dBasePortMtuExceededDiscards: 407 val->v.uint32 = bp->dly_mtu_drops; 408 return (SNMP_ERR_NOERROR); 409 } 410 411 abort(); 412 } 413 414 int 415 op_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val, 416 uint sub, uint iidx __unused, enum snmp_op op) 417 { 418 struct bridge_if *bif; 419 struct bridge_port *bp; 420 421 if ((bif = bridge_get_default()) == NULL) 422 return (SNMP_ERR_NOSUCHNAME); 423 424 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 425 bridge_update_memif(bif) <= 0) 426 return (SNMP_ERR_NOSUCHNAME); 427 428 switch (op) { 429 case SNMP_OP_GET: 430 if (val->var.len - sub != 1) 431 return (SNMP_ERR_NOSUCHNAME); 432 if ((bp = bridge_port_find(val->var.subs[sub], 433 bif)) == NULL) 434 return (SNMP_ERR_NOSUCHNAME); 435 goto get; 436 437 case SNMP_OP_GETNEXT: 438 if (val->var.len - sub == 0) { 439 if ((bp = bridge_port_bif_first(bif)) == NULL) 440 return (SNMP_ERR_NOSUCHNAME); 441 } else { 442 if ((bp = bridge_port_find(val->var.subs[sub], 443 bif)) == NULL || 444 (bp = bridge_port_bif_next(bp)) == NULL) 445 return (SNMP_ERR_NOSUCHNAME); 446 } 447 val->var.len = sub + 1; 448 val->var.subs[sub] = bp->port_no; 449 goto get; 450 451 case SNMP_OP_SET: 452 if (val->var.len - sub != 1) 453 return (SNMP_ERR_NOSUCHNAME); 454 if ((bp = bridge_port_find(val->var.subs[sub], 455 bif)) == NULL) 456 return (SNMP_ERR_NOSUCHNAME); 457 458 switch (val->var.subs[sub - 1]) { 459 case LEAF_dot1dStpPortPriority: 460 if (val->v.integer < 0 || val->v.integer > 255) 461 return (SNMP_ERR_WRONG_VALUE); 462 463 ctx->scratch->int1 = bp->priority; 464 if (bridge_port_set_priority(bif->bif_name, bp, 465 val->v.integer) < 0) 466 return (SNMP_ERR_GENERR); 467 return (SNMP_ERR_NOERROR); 468 469 case LEAF_dot1dStpPortEnable: 470 if (val->v.integer != dot1dStpPortEnable_enabled && 471 val->v.integer != dot1dStpPortEnable_disabled) 472 return (SNMP_ERR_WRONG_VALUE); 473 474 ctx->scratch->int1 = bp->enable; 475 if (bridge_port_set_stp_enable(bif->bif_name, 476 bp, val->v.integer) < 0) 477 return (SNMP_ERR_GENERR); 478 return (SNMP_ERR_NOERROR); 479 480 case LEAF_dot1dStpPortPathCost: 481 if (val->v.integer < SNMP_PORT_MIN_PATHCOST || 482 val->v.integer > SNMP_PORT_MAX_PATHCOST) 483 return (SNMP_ERR_WRONG_VALUE); 484 485 ctx->scratch->int1 = bp->path_cost; 486 if (bridge_port_set_path_cost(bif->bif_name, bp, 487 val->v.integer) < 0) 488 return (SNMP_ERR_GENERR); 489 return (SNMP_ERR_NOERROR); 490 491 case LEAF_dot1dStpPort: 492 case LEAF_dot1dStpPortState: 493 case LEAF_dot1dStpPortDesignatedRoot: 494 case LEAF_dot1dStpPortDesignatedCost: 495 case LEAF_dot1dStpPortDesignatedBridge: 496 case LEAF_dot1dStpPortDesignatedPort: 497 case LEAF_dot1dStpPortForwardTransitions: 498 return (SNMP_ERR_NOT_WRITEABLE); 499 } 500 abort(); 501 502 case SNMP_OP_ROLLBACK: 503 if ((bp = bridge_port_find(val->var.subs[sub], 504 bif)) == NULL) 505 return (SNMP_ERR_GENERR); 506 switch (val->var.subs[sub - 1]) { 507 case LEAF_dot1dStpPortPriority: 508 bridge_port_set_priority(bif->bif_name, bp, 509 ctx->scratch->int1); 510 break; 511 case LEAF_dot1dStpPortEnable: 512 bridge_port_set_stp_enable(bif->bif_name, bp, 513 ctx->scratch->int1); 514 break; 515 case LEAF_dot1dStpPortPathCost: 516 bridge_port_set_path_cost(bif->bif_name, bp, 517 ctx->scratch->int1); 518 break; 519 } 520 return (SNMP_ERR_NOERROR); 521 522 case SNMP_OP_COMMIT: 523 return (SNMP_ERR_NOERROR); 524 } 525 abort(); 526 527 get: 528 switch (val->var.subs[sub - 1]) { 529 case LEAF_dot1dStpPort: 530 val->v.integer = bp->port_no; 531 return (SNMP_ERR_NOERROR); 532 533 case LEAF_dot1dStpPortPriority: 534 val->v.integer = bp->priority; 535 return (SNMP_ERR_NOERROR); 536 537 case LEAF_dot1dStpPortState: 538 val->v.integer = bp->state; 539 return (SNMP_ERR_NOERROR); 540 541 case LEAF_dot1dStpPortEnable: 542 val->v.integer = bp->enable; 543 return (SNMP_ERR_NOERROR); 544 545 case LEAF_dot1dStpPortPathCost: 546 val->v.integer = bp->path_cost; 547 return (SNMP_ERR_NOERROR); 548 549 case LEAF_dot1dStpPortDesignatedRoot: 550 return (string_get(val, bp->design_root, 551 SNMP_BRIDGE_ID_LEN)); 552 553 case LEAF_dot1dStpPortDesignatedCost: 554 val->v.integer = bp->design_cost; 555 return (SNMP_ERR_NOERROR); 556 557 case LEAF_dot1dStpPortDesignatedBridge: 558 return (string_get(val, bp->design_bridge, 559 SNMP_BRIDGE_ID_LEN)); 560 561 case LEAF_dot1dStpPortDesignatedPort: 562 return (string_get(val, bp->design_port, 2)); 563 564 case LEAF_dot1dStpPortForwardTransitions: 565 val->v.uint32 = bp->fwd_trans; 566 return (SNMP_ERR_NOERROR); 567 } 568 569 abort(); 570 } 571 572 int 573 op_dot1d_stp_ext_port(struct snmp_context *ctx, struct snmp_value *val, 574 uint sub, uint iidx __unused, enum snmp_op op) 575 { 576 struct bridge_if *bif; 577 struct bridge_port *bp; 578 579 if ((bif = bridge_get_default()) == NULL) 580 return (SNMP_ERR_NOSUCHNAME); 581 582 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 583 bridge_update_memif(bif) <= 0) 584 return (SNMP_ERR_NOSUCHNAME); 585 586 switch (op) { 587 case SNMP_OP_GET: 588 if (val->var.len - sub != 1) 589 return (SNMP_ERR_NOSUCHNAME); 590 if ((bp = bridge_port_find(val->var.subs[sub], 591 bif)) == NULL) 592 return (SNMP_ERR_NOSUCHNAME); 593 goto get; 594 595 case SNMP_OP_GETNEXT: 596 if (val->var.len - sub == 0) { 597 if ((bp = bridge_port_bif_first(bif)) == NULL) 598 return (SNMP_ERR_NOSUCHNAME); 599 } else { 600 if ((bp = bridge_port_find(val->var.subs[sub], 601 bif)) == NULL || 602 (bp = bridge_port_bif_next(bp)) == NULL) 603 return (SNMP_ERR_NOSUCHNAME); 604 } 605 val->var.len = sub + 1; 606 val->var.subs[sub] = bp->port_no; 607 goto get; 608 609 case SNMP_OP_SET: 610 if (val->var.len - sub != 1) 611 return (SNMP_ERR_NOSUCHNAME); 612 if ((bp = bridge_port_find(val->var.subs[sub], 613 bif)) == NULL) 614 return (SNMP_ERR_NOSUCHNAME); 615 616 switch (val->var.subs[sub - 1]) { 617 case LEAF_dot1dStpPortAdminEdgePort: 618 if (val->v.integer != TruthValue_true && 619 val->v.integer != TruthValue_false) 620 return (SNMP_ERR_WRONG_VALUE); 621 622 ctx->scratch->int1 = bp->admin_edge; 623 if (bridge_port_set_admin_edge(bif->bif_name, bp, 624 val->v.integer) < 0) 625 return (SNMP_ERR_GENERR); 626 return (SNMP_ERR_NOERROR); 627 628 case LEAF_dot1dStpPortAdminPointToPoint: 629 if (val->v.integer < 0 || val->v.integer > 630 StpPortAdminPointToPointType_auto) 631 return (SNMP_ERR_WRONG_VALUE); 632 633 ctx->scratch->int1 = bp->admin_ptp; 634 if (bridge_port_set_admin_ptp(bif->bif_name, bp, 635 val->v.integer) < 0) 636 return (SNMP_ERR_GENERR); 637 return (SNMP_ERR_NOERROR); 638 639 case LEAF_dot1dStpPortAdminPathCost: 640 if (val->v.integer < SNMP_PORT_MIN_PATHCOST || 641 val->v.integer > SNMP_PORT_MAX_PATHCOST) 642 return (SNMP_ERR_WRONG_VALUE); 643 644 ctx->scratch->int1 = bp->admin_path_cost; 645 if (bridge_port_set_path_cost(bif->bif_name, bp, 646 val->v.integer) < 0) 647 return (SNMP_ERR_GENERR); 648 return (SNMP_ERR_NOERROR); 649 650 case LEAF_dot1dStpPortProtocolMigration: 651 case LEAF_dot1dStpPortOperEdgePort: 652 case LEAF_dot1dStpPortOperPointToPoint: 653 return (SNMP_ERR_NOT_WRITEABLE); 654 } 655 abort(); 656 657 case SNMP_OP_ROLLBACK: 658 if ((bp = bridge_port_find(val->var.subs[sub], 659 bif)) == NULL) 660 return (SNMP_ERR_GENERR); 661 662 switch (val->var.subs[sub - 1]) { 663 case LEAF_dot1dStpPortAdminEdgePort: 664 bridge_port_set_admin_edge(bif->bif_name, bp, 665 ctx->scratch->int1); 666 break; 667 case LEAF_dot1dStpPortAdminPointToPoint: 668 bridge_port_set_admin_ptp(bif->bif_name, bp, 669 ctx->scratch->int1); 670 break; 671 case LEAF_dot1dStpPortAdminPathCost: 672 bridge_port_set_path_cost(bif->bif_name, bp, 673 ctx->scratch->int1); 674 break; 675 } 676 return (SNMP_ERR_NOERROR); 677 678 case SNMP_OP_COMMIT: 679 return (SNMP_ERR_NOERROR); 680 } 681 abort(); 682 683 get: 684 switch (val->var.subs[sub - 1]) { 685 case LEAF_dot1dStpPortProtocolMigration: 686 val->v.integer = bp->proto_migr; 687 return (SNMP_ERR_NOERROR); 688 689 case LEAF_dot1dStpPortAdminEdgePort: 690 val->v.integer = bp->admin_edge; 691 return (SNMP_ERR_NOERROR); 692 693 case LEAF_dot1dStpPortOperEdgePort: 694 val->v.integer = bp->oper_edge; 695 return (SNMP_ERR_NOERROR); 696 697 case LEAF_dot1dStpPortAdminPointToPoint: 698 val->v.integer = bp->admin_ptp; 699 return (SNMP_ERR_NOERROR); 700 701 case LEAF_dot1dStpPortOperPointToPoint: 702 val->v.integer = bp->oper_ptp; 703 return (SNMP_ERR_NOERROR); 704 705 case LEAF_dot1dStpPortAdminPathCost: 706 val->v.integer = bp->admin_path_cost; 707 return (SNMP_ERR_NOERROR); 708 } 709 710 abort(); 711 } 712 713 int 714 op_dot1d_tp_port(struct snmp_context *c __unused, struct snmp_value *val, 715 uint sub, uint iidx __unused, enum snmp_op op) 716 { 717 struct bridge_if *bif; 718 struct bridge_port *bp; 719 720 if ((bif = bridge_get_default()) == NULL) 721 return (SNMP_ERR_NOSUCHNAME); 722 723 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && 724 bridge_update_memif(bif) <= 0) 725 return (SNMP_ERR_NOSUCHNAME); 726 727 switch (op) { 728 case SNMP_OP_GET: 729 if (val->var.len - sub != 1) 730 return (SNMP_ERR_NOSUCHNAME); 731 if ((bp = bridge_port_find(val->var.subs[sub], 732 bif)) == NULL) 733 return (SNMP_ERR_NOSUCHNAME); 734 goto get; 735 736 case SNMP_OP_GETNEXT: 737 if (val->var.len - sub == 0) { 738 if ((bp = bridge_port_bif_first(bif)) == NULL) 739 return (SNMP_ERR_NOSUCHNAME); 740 } else { 741 if ((bp = bridge_port_find(val->var.subs[sub], 742 bif)) == NULL || 743 (bp = bridge_port_bif_next(bp)) == NULL) 744 return (SNMP_ERR_NOSUCHNAME); 745 } 746 val->var.len = sub + 1; 747 val->var.subs[sub] = bp->port_no; 748 goto get; 749 750 case SNMP_OP_SET: 751 return (SNMP_ERR_NOT_WRITEABLE); 752 753 case SNMP_OP_ROLLBACK: 754 case SNMP_OP_COMMIT: 755 break; 756 } 757 abort(); 758 759 get: 760 switch (val->var.subs[sub - 1]) { 761 case LEAF_dot1dTpPort: 762 val->v.integer = bp->port_no; 763 return (SNMP_ERR_NOERROR); 764 765 case LEAF_dot1dTpPortMaxInfo: 766 val->v.integer = bp->max_info; 767 return (SNMP_ERR_NOERROR); 768 769 case LEAF_dot1dTpPortInFrames: 770 val->v.uint32 = bp->in_frames; 771 return (SNMP_ERR_NOERROR); 772 773 case LEAF_dot1dTpPortOutFrames: 774 val->v.uint32 = bp->out_frames; 775 return (SNMP_ERR_NOERROR); 776 777 case LEAF_dot1dTpPortInDiscards: 778 val->v.uint32 = bp->in_drops; 779 return (SNMP_ERR_NOERROR); 780 } 781 782 abort(); 783 } 784 785 /* 786 * Private BEGEMOT-BRIDGE-MIB specifics. 787 */ 788 789 /* 790 * Construct a bridge port entry index. 791 */ 792 static int 793 bridge_port_index_append(struct asn_oid *oid, uint sub, 794 const struct bridge_port *bp) 795 { 796 uint i; 797 const char *b_name; 798 799 if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) 800 return (-1); 801 802 oid->len = sub + strlen(b_name) + 1 + 1; 803 oid->subs[sub] = strlen(b_name); 804 805 for (i = 1; i <= strlen(b_name); i++) 806 oid->subs[sub + i] = b_name[i - 1]; 807 808 oid->subs[sub + i] = bp->port_no; 809 810 return (0); 811 } 812 813 /* 814 * Get the port entry from an entry's index. 815 */ 816 static struct bridge_port * 817 bridge_port_index_get(const struct asn_oid *oid, uint sub, int8_t status) 818 { 819 uint i; 820 int32_t port_no; 821 char bif_name[IFNAMSIZ]; 822 struct bridge_if *bif; 823 struct bridge_port *bp; 824 825 if (oid->len - sub != oid->subs[sub] + 2 || 826 oid->subs[sub] >= IFNAMSIZ) 827 return (NULL); 828 829 for (i = 0; i < oid->subs[sub]; i++) 830 bif_name[i] = oid->subs[sub + i + 1]; 831 bif_name[i] = '\0'; 832 833 port_no = oid->subs[sub + i + 1]; 834 835 if ((bif = bridge_if_find_ifname(bif_name)) == NULL) 836 return (NULL); 837 838 if ((bp = bridge_port_find(port_no, bif)) == NULL || 839 (status == 0 && bp->status != RowStatus_active)) 840 return (NULL); 841 842 return (bp); 843 } 844 845 /* 846 * Get the next port entry from an entry's index. 847 */ 848 static struct bridge_port * 849 bridge_port_index_getnext(const struct asn_oid *oid, uint sub, int8_t status) 850 { 851 uint i; 852 int32_t port_no; 853 char bif_name[IFNAMSIZ]; 854 struct bridge_if *bif; 855 struct bridge_port *bp; 856 857 if (oid->len - sub == 0) 858 bp = bridge_port_first(); 859 else { 860 if (oid->len - sub != oid->subs[sub] + 2 || 861 oid->subs[sub] >= IFNAMSIZ) 862 return (NULL); 863 864 for (i = 0; i < oid->subs[sub]; i++) 865 bif_name[i] = oid->subs[sub + i + 1]; 866 bif_name[i] = '\0'; 867 868 port_no = oid->subs[sub + i + 1]; 869 870 if ((bif = bridge_if_find_ifname(bif_name)) == NULL || 871 (bp = bridge_port_find(port_no, bif)) == NULL) 872 return (NULL); 873 874 bp = bridge_port_next(bp); 875 } 876 877 if (status == 1) 878 return (bp); 879 880 while (bp != NULL) { 881 if (bp->status == RowStatus_active) 882 break; 883 bp = bridge_port_next(bp); 884 } 885 886 return (bp); 887 } 888 889 /* 890 * Read the bridge name and port index from a ASN OID structure. 891 */ 892 static int 893 bridge_port_index_decode(const struct asn_oid *oid, uint sub, 894 char *b_name, int32_t *idx) 895 { 896 uint i; 897 898 if (oid->len - sub != oid->subs[sub] + 2 || 899 oid->subs[sub] >= IFNAMSIZ) 900 return (-1); 901 902 for (i = 0; i < oid->subs[sub]; i++) 903 b_name[i] = oid->subs[sub + i + 1]; 904 b_name[i] = '\0'; 905 906 *idx = oid->subs[sub + i + 1]; 907 return (0); 908 } 909 910 static int 911 bridge_port_set_status(struct snmp_context *ctx, 912 struct snmp_value *val, uint sub) 913 { 914 int32_t if_idx; 915 char b_name[IFNAMSIZ]; 916 struct bridge_if *bif; 917 struct bridge_port *bp; 918 struct mibif *mif; 919 920 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 921 return (SNMP_ERR_INCONS_VALUE); 922 923 if ((bif = bridge_if_find_ifname(b_name)) == NULL || 924 (mif = mib_find_if(if_idx)) == NULL) 925 return (SNMP_ERR_INCONS_VALUE); 926 927 bp = bridge_port_find(if_idx, bif); 928 929 switch (val->v.integer) { 930 case RowStatus_active: 931 if (bp == NULL) 932 return (SNMP_ERR_INCONS_VALUE); 933 934 if (bp->span_enable == 0) 935 return (SNMP_ERR_INCONS_VALUE); 936 937 ctx->scratch->int1 = bp->status; 938 bp->status = RowStatus_active; 939 break; 940 941 case RowStatus_notInService: 942 if (bp == NULL || bp->span_enable == 0 || 943 bp->status == RowStatus_active) 944 return (SNMP_ERR_INCONS_VALUE); 945 946 ctx->scratch->int1 = bp->status; 947 bp->status = RowStatus_notInService; 948 949 case RowStatus_notReady: 950 /* FALLTHROUGH */ 951 case RowStatus_createAndGo: 952 return (SNMP_ERR_INCONS_VALUE); 953 954 case RowStatus_createAndWait: 955 if (bp != NULL) 956 return (SNMP_ERR_INCONS_VALUE); 957 958 if ((bp = bridge_new_port(mif, bif)) == NULL) 959 return (SNMP_ERR_GENERR); 960 961 ctx->scratch->int1 = RowStatus_destroy; 962 bp->status = RowStatus_notReady; 963 break; 964 965 case RowStatus_destroy: 966 if (bp == NULL) 967 return (SNMP_ERR_INCONS_VALUE); 968 969 ctx->scratch->int1 = bp->status; 970 bp->status = RowStatus_destroy; 971 break; 972 } 973 974 return (SNMP_ERR_NOERROR); 975 } 976 977 static int 978 bridge_port_rollback_status(struct snmp_context *ctx, 979 struct snmp_value *val, uint sub) 980 { 981 int32_t if_idx; 982 char b_name[IFNAMSIZ]; 983 struct bridge_if *bif; 984 struct bridge_port *bp; 985 986 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 987 return (SNMP_ERR_GENERR); 988 989 if ((bif = bridge_if_find_ifname(b_name)) == NULL || 990 (bp = bridge_port_find(if_idx, bif)) == NULL) 991 return (SNMP_ERR_GENERR); 992 993 if (ctx->scratch->int1 == RowStatus_destroy) 994 bridge_port_remove(bp, bif); 995 else 996 bp->status = ctx->scratch->int1; 997 998 return (SNMP_ERR_NOERROR); 999 } 1000 1001 static int 1002 bridge_port_commit_status(struct snmp_value *val, uint sub) 1003 { 1004 int32_t if_idx; 1005 char b_name[IFNAMSIZ]; 1006 struct bridge_if *bif; 1007 struct bridge_port *bp; 1008 1009 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 1010 return (SNMP_ERR_GENERR); 1011 1012 if ((bif = bridge_if_find_ifname(b_name)) == NULL || 1013 (bp = bridge_port_find(if_idx, bif)) == NULL) 1014 return (SNMP_ERR_GENERR); 1015 1016 switch (bp->status) { 1017 case RowStatus_active: 1018 if (bridge_port_addm(bp, b_name) < 0) 1019 return (SNMP_ERR_COMMIT_FAILED); 1020 break; 1021 1022 case RowStatus_destroy: 1023 if (bridge_port_delm(bp, b_name) < 0) 1024 return (SNMP_ERR_COMMIT_FAILED); 1025 bridge_port_remove(bp, bif); 1026 break; 1027 } 1028 1029 return (SNMP_ERR_NOERROR); 1030 } 1031 1032 static int 1033 bridge_port_set_span_enable(struct snmp_context *ctx, 1034 struct snmp_value *val, uint sub) 1035 { 1036 int32_t if_idx; 1037 char b_name[IFNAMSIZ]; 1038 struct bridge_if *bif; 1039 struct bridge_port *bp; 1040 struct mibif *mif; 1041 1042 if (val->v.integer != begemotBridgeBaseSpanEnabled_enabled && 1043 val->v.integer != begemotBridgeBaseSpanEnabled_disabled) 1044 return (SNMP_ERR_BADVALUE); 1045 1046 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) 1047 return (SNMP_ERR_INCONS_VALUE); 1048 1049 if ((bif = bridge_if_find_ifname(b_name)) == NULL) 1050 return (SNMP_ERR_INCONS_VALUE); 1051 1052 if ((bp = bridge_port_find(if_idx, bif)) == NULL) { 1053 if ((mif = mib_find_if(if_idx)) == NULL) 1054 return (SNMP_ERR_INCONS_VALUE); 1055 1056 if ((bp = bridge_new_port(mif, bif)) == NULL) 1057 return (SNMP_ERR_GENERR); 1058 1059 ctx->scratch->int1 = RowStatus_destroy; 1060 } else if (bp->status == RowStatus_active) { 1061 return (SNMP_ERR_INCONS_VALUE); 1062 } else { 1063 ctx->scratch->int1 = bp->status; 1064 } 1065 1066 bp->span_enable = val->v.integer; 1067 bp->status = RowStatus_notInService; 1068 1069 return (SNMP_ERR_NOERROR); 1070 } 1071 1072 int 1073 op_begemot_base_port(struct snmp_context *ctx, struct snmp_value *val, 1074 uint sub, uint iidx __unused, enum snmp_op op) 1075 { 1076 int8_t status, which; 1077 struct bridge_port *bp; 1078 1079 if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 1080 bridge_update_all_ports(); 1081 1082 which = val->var.subs[sub - 1]; 1083 status = 0; 1084 1085 switch (op) { 1086 case SNMP_OP_GET: 1087 if (which == LEAF_begemotBridgeBaseSpanEnabled || 1088 which == LEAF_begemotBridgeBasePortStatus) 1089 status = 1; 1090 if ((bp = bridge_port_index_get(&val->var, sub, 1091 status)) == NULL) 1092 return (SNMP_ERR_NOSUCHNAME); 1093 goto get; 1094 1095 case SNMP_OP_GETNEXT: 1096 if (which == LEAF_begemotBridgeBaseSpanEnabled || 1097 which == LEAF_begemotBridgeBasePortStatus) 1098 status = 1; 1099 if ((bp = bridge_port_index_getnext(&val->var, sub, 1100 status)) == NULL || 1101 bridge_port_index_append(&val->var, sub, bp) < 0) 1102 return (SNMP_ERR_NOSUCHNAME); 1103 goto get; 1104 1105 case SNMP_OP_SET: 1106 switch (which) { 1107 case LEAF_begemotBridgeBaseSpanEnabled: 1108 return (bridge_port_set_span_enable(ctx, val, sub)); 1109 1110 case LEAF_begemotBridgeBasePortStatus: 1111 return (bridge_port_set_status(ctx, val, sub)); 1112 1113 case LEAF_begemotBridgeBasePort: 1114 case LEAF_begemotBridgeBasePortIfIndex: 1115 case LEAF_begemotBridgeBasePortDelayExceededDiscards: 1116 case LEAF_begemotBridgeBasePortMtuExceededDiscards: 1117 return (SNMP_ERR_NOT_WRITEABLE); 1118 } 1119 abort(); 1120 1121 case SNMP_OP_ROLLBACK: 1122 switch (which) { 1123 case LEAF_begemotBridgeBaseSpanEnabled: 1124 /* FALLTHROUGH */ 1125 case LEAF_begemotBridgeBasePortStatus: 1126 return (bridge_port_rollback_status(ctx, val, sub)); 1127 } 1128 return (SNMP_ERR_NOERROR); 1129 1130 case SNMP_OP_COMMIT: 1131 if (which == LEAF_begemotBridgeBasePortStatus) 1132 return (bridge_port_commit_status(val, sub)); 1133 1134 return (SNMP_ERR_NOERROR); 1135 } 1136 abort(); 1137 1138 get: 1139 switch (which) { 1140 case LEAF_begemotBridgeBasePort: 1141 val->v.integer = bp->port_no; 1142 return (SNMP_ERR_NOERROR); 1143 1144 case LEAF_begemotBridgeBasePortIfIndex: 1145 val->v.integer = bp->if_idx; 1146 return (SNMP_ERR_NOERROR); 1147 1148 case LEAF_begemotBridgeBaseSpanEnabled: 1149 val->v.integer = bp->span_enable; 1150 return (SNMP_ERR_NOERROR); 1151 1152 case LEAF_begemotBridgeBasePortDelayExceededDiscards: 1153 val->v.uint32 = bp->dly_ex_drops; 1154 return (SNMP_ERR_NOERROR); 1155 1156 case LEAF_begemotBridgeBasePortMtuExceededDiscards: 1157 val->v.uint32 = bp->dly_mtu_drops; 1158 return (SNMP_ERR_NOERROR); 1159 1160 case LEAF_begemotBridgeBasePortStatus: 1161 val->v.integer = bp->status; 1162 return (SNMP_ERR_NOERROR); 1163 } 1164 1165 abort(); 1166 } 1167 1168 int 1169 op_begemot_stp_port(struct snmp_context *ctx, struct snmp_value *val, 1170 uint sub, uint iidx __unused, enum snmp_op op) 1171 { 1172 struct bridge_port *bp; 1173 const char *b_name; 1174 1175 if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 1176 bridge_update_all_ports(); 1177 1178 switch (op) { 1179 case SNMP_OP_GET: 1180 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1181 return (SNMP_ERR_NOSUCHNAME); 1182 goto get; 1183 1184 case SNMP_OP_GETNEXT: 1185 if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == 1186 NULL || bridge_port_index_append(&val->var, sub, bp) < 0) 1187 return (SNMP_ERR_NOSUCHNAME); 1188 goto get; 1189 1190 case SNMP_OP_SET: 1191 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1192 return (SNMP_ERR_NOSUCHNAME); 1193 if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) 1194 return (SNMP_ERR_GENERR); 1195 1196 switch (val->var.subs[sub - 1]) { 1197 case LEAF_begemotBridgeStpPortPriority: 1198 if (val->v.integer < 0 || val->v.integer > 255) 1199 return (SNMP_ERR_WRONG_VALUE); 1200 1201 ctx->scratch->int1 = bp->priority; 1202 if (bridge_port_set_priority(b_name, bp, 1203 val->v.integer) < 0) 1204 return (SNMP_ERR_GENERR); 1205 return (SNMP_ERR_NOERROR); 1206 1207 case LEAF_begemotBridgeStpPortEnable: 1208 if (val->v.integer != 1209 begemotBridgeStpPortEnable_enabled || 1210 val->v.integer != 1211 begemotBridgeStpPortEnable_disabled) 1212 return (SNMP_ERR_WRONG_VALUE); 1213 1214 ctx->scratch->int1 = bp->enable; 1215 if (bridge_port_set_stp_enable(b_name, bp, 1216 val->v.integer) < 0) 1217 return (SNMP_ERR_GENERR); 1218 return (SNMP_ERR_NOERROR); 1219 1220 case LEAF_begemotBridgeStpPortPathCost: 1221 if (val->v.integer < SNMP_PORT_MIN_PATHCOST || 1222 val->v.integer > SNMP_PORT_MAX_PATHCOST) 1223 return (SNMP_ERR_WRONG_VALUE); 1224 1225 ctx->scratch->int1 = bp->path_cost; 1226 if (bridge_port_set_path_cost(b_name, bp, 1227 val->v.integer) < 0) 1228 return (SNMP_ERR_GENERR); 1229 return (SNMP_ERR_NOERROR); 1230 1231 case LEAF_begemotBridgeStpPort: 1232 case LEAF_begemotBridgeStpPortState: 1233 case LEAF_begemotBridgeStpPortDesignatedRoot: 1234 case LEAF_begemotBridgeStpPortDesignatedCost: 1235 case LEAF_begemotBridgeStpPortDesignatedBridge: 1236 case LEAF_begemotBridgeStpPortDesignatedPort: 1237 case LEAF_begemotBridgeStpPortForwardTransitions: 1238 return (SNMP_ERR_NOT_WRITEABLE); 1239 } 1240 abort(); 1241 1242 case SNMP_OP_ROLLBACK: 1243 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL || 1244 (b_name = bridge_if_find_name(bp->sysindex)) == NULL) 1245 return (SNMP_ERR_GENERR); 1246 1247 switch (val->var.subs[sub - 1]) { 1248 case LEAF_begemotBridgeStpPortPriority: 1249 bridge_port_set_priority(b_name, bp, 1250 ctx->scratch->int1); 1251 break; 1252 case LEAF_begemotBridgeStpPortEnable: 1253 bridge_port_set_stp_enable(b_name, bp, 1254 ctx->scratch->int1); 1255 break; 1256 case LEAF_begemotBridgeStpPortPathCost: 1257 bridge_port_set_path_cost(b_name, bp, 1258 ctx->scratch->int1); 1259 break; 1260 } 1261 return (SNMP_ERR_NOERROR); 1262 1263 case SNMP_OP_COMMIT: 1264 return (SNMP_ERR_NOERROR); 1265 } 1266 abort(); 1267 1268 get: 1269 switch (val->var.subs[sub - 1]) { 1270 case LEAF_begemotBridgeStpPort: 1271 val->v.integer = bp->port_no; 1272 return (SNMP_ERR_NOERROR); 1273 1274 case LEAF_begemotBridgeStpPortPriority: 1275 val->v.integer = bp->priority; 1276 return (SNMP_ERR_NOERROR); 1277 1278 case LEAF_begemotBridgeStpPortState: 1279 val->v.integer = bp->state; 1280 return (SNMP_ERR_NOERROR); 1281 1282 case LEAF_begemotBridgeStpPortEnable: 1283 val->v.integer = bp->enable; 1284 return (SNMP_ERR_NOERROR); 1285 1286 case LEAF_begemotBridgeStpPortPathCost: 1287 val->v.integer = bp->path_cost; 1288 return (SNMP_ERR_NOERROR); 1289 1290 case LEAF_begemotBridgeStpPortDesignatedRoot: 1291 return (string_get(val, bp->design_root, SNMP_BRIDGE_ID_LEN)); 1292 1293 case LEAF_begemotBridgeStpPortDesignatedCost: 1294 val->v.integer = bp->design_cost; 1295 return (SNMP_ERR_NOERROR); 1296 1297 case LEAF_begemotBridgeStpPortDesignatedBridge: 1298 return (string_get(val, bp->design_bridge, SNMP_BRIDGE_ID_LEN)); 1299 1300 case LEAF_begemotBridgeStpPortDesignatedPort: 1301 return (string_get(val, bp->design_port, 2)); 1302 1303 case LEAF_begemotBridgeStpPortForwardTransitions: 1304 val->v.uint32 = bp->fwd_trans; 1305 return (SNMP_ERR_NOERROR); 1306 } 1307 1308 abort(); 1309 } 1310 1311 int 1312 op_begemot_stp_ext_port(struct snmp_context *ctx, struct snmp_value *val, 1313 uint sub, uint iidx __unused, enum snmp_op op) 1314 { 1315 struct bridge_port *bp; 1316 const char *b_name; 1317 1318 if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 1319 bridge_update_all_ports(); 1320 1321 switch (op) { 1322 case SNMP_OP_GET: 1323 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1324 return (SNMP_ERR_NOSUCHNAME); 1325 goto get; 1326 1327 case SNMP_OP_GETNEXT: 1328 if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == 1329 NULL || bridge_port_index_append(&val->var, sub, bp) < 0) 1330 return (SNMP_ERR_NOSUCHNAME); 1331 goto get; 1332 1333 case SNMP_OP_SET: 1334 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1335 return (SNMP_ERR_NOSUCHNAME); 1336 if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) 1337 return (SNMP_ERR_GENERR); 1338 1339 switch (val->var.subs[sub - 1]) { 1340 case LEAF_begemotBridgeStpPortAdminEdgePort: 1341 if (val->v.integer != TruthValue_true && 1342 val->v.integer != TruthValue_false) 1343 return (SNMP_ERR_WRONG_VALUE); 1344 1345 ctx->scratch->int1 = bp->admin_edge; 1346 if (bridge_port_set_admin_edge(b_name, bp, 1347 val->v.integer) < 0) 1348 return (SNMP_ERR_GENERR); 1349 return (SNMP_ERR_NOERROR); 1350 1351 case LEAF_begemotBridgeStpPortAdminPointToPoint: 1352 if (val->v.integer < 0 || val->v.integer > 1353 StpPortAdminPointToPointType_auto) 1354 return (SNMP_ERR_WRONG_VALUE); 1355 1356 ctx->scratch->int1 = bp->admin_ptp; 1357 if (bridge_port_set_admin_ptp(b_name, bp, 1358 val->v.integer) < 0) 1359 return (SNMP_ERR_GENERR); 1360 return (SNMP_ERR_NOERROR); 1361 1362 case LEAF_begemotBridgeStpPortAdminPathCost: 1363 if (val->v.integer < SNMP_PORT_MIN_PATHCOST || 1364 val->v.integer > SNMP_PORT_MAX_PATHCOST) 1365 return (SNMP_ERR_WRONG_VALUE); 1366 1367 ctx->scratch->int1 = bp->admin_path_cost; 1368 if (bridge_port_set_path_cost(b_name, bp, 1369 val->v.integer) < 0) 1370 return (SNMP_ERR_GENERR); 1371 return (SNMP_ERR_NOERROR); 1372 1373 case LEAF_begemotBridgeStpPortProtocolMigration: 1374 case LEAF_begemotBridgeStpPortOperEdgePort: 1375 case LEAF_begemotBridgeStpPortOperPointToPoint: 1376 return (SNMP_ERR_NOT_WRITEABLE); 1377 } 1378 abort(); 1379 1380 case SNMP_OP_ROLLBACK: 1381 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL || 1382 (b_name = bridge_if_find_name(bp->sysindex)) == NULL) 1383 return (SNMP_ERR_GENERR); 1384 1385 switch (val->var.subs[sub - 1]) { 1386 case LEAF_begemotBridgeStpPortAdminEdgePort: 1387 bridge_port_set_admin_edge(b_name, bp, 1388 ctx->scratch->int1); 1389 break; 1390 case LEAF_begemotBridgeStpPortAdminPointToPoint: 1391 bridge_port_set_admin_ptp(b_name, bp, 1392 ctx->scratch->int1); 1393 break; 1394 case LEAF_begemotBridgeStpPortAdminPathCost: 1395 bridge_port_set_path_cost(b_name, bp, 1396 ctx->scratch->int1); 1397 break; 1398 } 1399 return (SNMP_ERR_NOERROR); 1400 1401 case SNMP_OP_COMMIT: 1402 return (SNMP_ERR_NOERROR); 1403 } 1404 abort(); 1405 1406 get: 1407 switch (val->var.subs[sub - 1]) { 1408 case LEAF_begemotBridgeStpPortProtocolMigration: 1409 val->v.integer = bp->proto_migr; 1410 return (SNMP_ERR_NOERROR); 1411 1412 case LEAF_begemotBridgeStpPortAdminEdgePort: 1413 val->v.integer = bp->admin_edge; 1414 return (SNMP_ERR_NOERROR); 1415 1416 case LEAF_begemotBridgeStpPortOperEdgePort: 1417 val->v.integer = bp->oper_edge; 1418 return (SNMP_ERR_NOERROR); 1419 1420 case LEAF_begemotBridgeStpPortAdminPointToPoint: 1421 val->v.integer = bp->admin_ptp; 1422 return (SNMP_ERR_NOERROR); 1423 1424 case LEAF_begemotBridgeStpPortOperPointToPoint: 1425 val->v.integer = bp->oper_ptp; 1426 return (SNMP_ERR_NOERROR); 1427 1428 case LEAF_begemotBridgeStpPortAdminPathCost: 1429 val->v.integer = bp->admin_path_cost; 1430 return (SNMP_ERR_NOERROR); 1431 } 1432 1433 abort(); 1434 } 1435 1436 int 1437 op_begemot_tp_port(struct snmp_context *c __unused, struct snmp_value *val, 1438 uint sub, uint iidx __unused, enum snmp_op op) 1439 { 1440 struct bridge_port *bp; 1441 1442 if (time(NULL) - ports_list_age > bridge_get_data_maxage()) 1443 bridge_update_all_ports(); 1444 1445 switch (op) { 1446 case SNMP_OP_GET: 1447 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) 1448 return (SNMP_ERR_NOSUCHNAME); 1449 goto get; 1450 1451 case SNMP_OP_GETNEXT: 1452 if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == 1453 NULL || bridge_port_index_append(&val->var, sub, bp) < 0) 1454 return (SNMP_ERR_NOSUCHNAME); 1455 goto get; 1456 1457 case SNMP_OP_SET: 1458 return (SNMP_ERR_NOT_WRITEABLE); 1459 1460 case SNMP_OP_ROLLBACK: 1461 case SNMP_OP_COMMIT: 1462 break; 1463 } 1464 abort(); 1465 1466 get: 1467 switch (val->var.subs[sub - 1]) { 1468 case LEAF_begemotBridgeTpPort: 1469 val->v.integer = bp->port_no; 1470 return (SNMP_ERR_NOERROR); 1471 1472 case LEAF_begemotBridgeTpPortMaxInfo: 1473 val->v.integer = bp->max_info; 1474 return (SNMP_ERR_NOERROR); 1475 1476 case LEAF_begemotBridgeTpPortInFrames: 1477 val->v.uint32 = bp->in_frames; 1478 return (SNMP_ERR_NOERROR); 1479 1480 case LEAF_begemotBridgeTpPortOutFrames: 1481 val->v.uint32 = bp->out_frames; 1482 return (SNMP_ERR_NOERROR); 1483 1484 case LEAF_begemotBridgeTpPortInDiscards: 1485 val->v.uint32 = bp->in_drops; 1486 return (SNMP_ERR_NOERROR); 1487 } 1488 1489 abort(); 1490 } 1491