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