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 OS specific ioctls. 28 * 29 * $FreeBSD$ 30 */ 31 32 #include <sys/ioctl.h> 33 #include <sys/param.h> 34 #include <sys/module.h> 35 #include <sys/linker.h> 36 #include <sys/socket.h> 37 #include <sys/sysctl.h> 38 39 #include <net/bridgestp.h> 40 #include <net/ethernet.h> 41 #include <net/if.h> 42 #include <net/if_bridgevar.h> 43 #include <net/if_dl.h> 44 #include <net/if_mib.h> 45 #include <net/if_types.h> 46 #include <netinet/in.h> 47 48 #include <errno.h> 49 #include <ifaddrs.h> 50 #include <stdarg.h> 51 #include <stdlib.h> 52 #include <stdio.h> 53 #include <string.h> 54 #include <syslog.h> 55 56 #include <bsnmp/snmpmod.h> 57 #include <bsnmp/snmp_mibII.h> 58 59 #include "bridge_tree.h" 60 #include "bridge_snmp.h" 61 62 int sock = -1; 63 64 int 65 bridge_ioctl_init(void) 66 { 67 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 68 syslog(LOG_ERR, "cannot open socket : %s", strerror(errno)); 69 return (-1); 70 } 71 72 return (0); 73 } 74 75 /* 76 * Load the if_bridge.ko module in kernel if not already there. 77 */ 78 int 79 bridge_kmod_load(void) 80 { 81 int fileid, modid; 82 const char mod_name[] = "if_bridge"; 83 struct module_stat mstat; 84 85 /* Scan files in kernel. */ 86 mstat.version = sizeof(struct module_stat); 87 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 88 /* Scan modules in file. */ 89 for (modid = kldfirstmod(fileid); modid > 0; 90 modid = modfnext(modid)) { 91 92 if (modstat(modid, &mstat) < 0) 93 continue; 94 95 if (strcmp(mod_name, mstat.name) == 0) 96 return (0); 97 } 98 } 99 100 /* Not present - load it. */ 101 if (kldload(mod_name) < 0) { 102 syslog(LOG_ERR, "failed to load %s kernel module", mod_name); 103 return (-1); 104 } 105 106 return (1); 107 } 108 109 /************************************************************************ 110 * Bridge interfaces. 111 */ 112 113 /* 114 * Convert the kernel uint64_t value for a bridge id 115 */ 116 static void 117 snmp_uint64_to_bridgeid(uint64_t id, bridge_id b_id) 118 { 119 int i; 120 u_char *o; 121 122 o = (u_char *) &id; 123 124 for (i = 0; i < SNMP_BRIDGE_ID_LEN; i++, o++) 125 b_id[SNMP_BRIDGE_ID_LEN - i - 1] = *o; 126 } 127 128 /* 129 * Fetch the bridge configuration parameters from the kernel excluding 130 * it's base MAC address. 131 */ 132 static int 133 bridge_get_conf_param(struct bridge_if *bif) 134 { 135 struct ifdrv ifd; 136 struct ifbrparam b_param; 137 138 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 139 ifd.ifd_len = sizeof(b_param); 140 ifd.ifd_data = &b_param; 141 142 /* Bridge priority. */ 143 ifd.ifd_cmd = BRDGGPRI; 144 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 145 syslog(LOG_ERR, "update bridge: ioctl(BRDGGPRI) failed: %s", 146 strerror(errno)); 147 return (-1); 148 } 149 150 bif->priority = b_param.ifbrp_prio; 151 152 /* Configured max age. */ 153 ifd.ifd_cmd = BRDGGMA; 154 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 155 syslog(LOG_ERR, "update bridge: ioctl(BRDGGMA) failed: %s", 156 strerror(errno)); 157 return (-1); 158 } 159 160 /* Centi-seconds. */ 161 bif->bridge_max_age = 100 * b_param.ifbrp_maxage; 162 163 /* Configured hello time. */ 164 ifd.ifd_cmd = BRDGGHT; 165 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 166 syslog(LOG_ERR, "update bridge: ioctl(BRDGGHT) failed: %s", 167 strerror(errno)); 168 return (-1); 169 } 170 bif->bridge_hello_time = 100 * b_param.ifbrp_hellotime; 171 172 /* Forward delay. */ 173 ifd.ifd_cmd = BRDGGFD; 174 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 175 syslog(LOG_ERR, "update bridge: ioctl(BRDGGFD) failed: %s", 176 strerror(errno)); 177 return (-1); 178 } 179 bif->bridge_fwd_delay = 100 * b_param.ifbrp_fwddelay; 180 181 /* Number of dropped addresses. */ 182 ifd.ifd_cmd = BRDGGRTE; 183 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 184 syslog(LOG_ERR, "update bridge: ioctl(BRDGGRTE) failed: %s", 185 strerror(errno)); 186 return (-1); 187 } 188 bif->lrnt_drops = b_param.ifbrp_cexceeded; 189 190 /* Address table timeout. */ 191 ifd.ifd_cmd = BRDGGTO; 192 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 193 syslog(LOG_ERR, "update bridge: ioctl(BRDGGTO) failed: %s", 194 strerror(errno)); 195 return (-1); 196 } 197 bif->age_time = b_param.ifbrp_ctime; 198 199 /* Address table size. */ 200 ifd.ifd_cmd = BRDGGCACHE; 201 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 202 syslog(LOG_ERR, "update bridge: ioctl(BRDGGCACHE) " 203 "failed: %s", strerror(errno)); 204 return (-1); 205 } 206 bif->max_addrs = b_param.ifbrp_csize; 207 208 return (0); 209 } 210 211 /* 212 * Fetch the current bridge STP operational parameters. 213 * Returns: -1 - on error; 214 * 0 - old TC time and Root Port values are same; 215 * 1 - topologyChange notification should be sent; 216 * 2 - newRoot notification should be sent. 217 */ 218 int 219 bridge_get_op_param(struct bridge_if *bif) 220 { 221 int new_root_send; 222 struct ifdrv ifd; 223 struct ifbropreq b_req; 224 225 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 226 ifd.ifd_len = sizeof(b_req); 227 ifd.ifd_data = &b_req; 228 ifd.ifd_cmd = BRDGPARAM; 229 230 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 231 syslog(LOG_ERR, "update bridge: ioctl(BRDGPARAM) failed: %s", 232 strerror(errno)); 233 return (-1); 234 } 235 236 bif->max_age = 100 * b_req.ifbop_maxage; 237 bif->hello_time = 100 * b_req.ifbop_hellotime; 238 bif->fwd_delay = 100 * b_req.ifbop_fwddelay; 239 bif->stp_version = b_req.ifbop_protocol; 240 bif->tx_hold_count = b_req.ifbop_holdcount; 241 242 if (b_req.ifbop_root_port == 0 && 243 bif->root_port != b_req.ifbop_root_port) 244 new_root_send = 2; 245 else 246 new_root_send = 0; 247 248 bif->root_port = b_req.ifbop_root_port; 249 bif->root_cost = b_req.ifbop_root_path_cost; 250 snmp_uint64_to_bridgeid(b_req.ifbop_designated_root, 251 bif->design_root); 252 253 if (bif->last_tc_time.tv_sec != b_req.ifbop_last_tc_time.tv_sec) { 254 bif->top_changes++; 255 bif->last_tc_time.tv_sec = b_req.ifbop_last_tc_time.tv_sec; 256 bif->last_tc_time.tv_usec = b_req.ifbop_last_tc_time.tv_usec; 257 258 /* 259 * "The trap is not sent if a (begemotBridge)NewRoot 260 * trap is sent for the same transition." 261 */ 262 if (new_root_send == 0) 263 return (1); 264 } 265 266 return (new_root_send); 267 } 268 269 int 270 bridge_getinfo_bif(struct bridge_if *bif) 271 { 272 if (bridge_get_conf_param(bif) < 0) 273 return (-1); 274 275 return (bridge_get_op_param(bif)); 276 } 277 278 int 279 bridge_set_priority(struct bridge_if *bif, int32_t priority) 280 { 281 struct ifdrv ifd; 282 struct ifbrparam b_param; 283 284 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 285 ifd.ifd_len = sizeof(b_param); 286 ifd.ifd_data = &b_param; 287 b_param.ifbrp_prio = (uint32_t) priority; 288 ifd.ifd_cmd = BRDGSPRI; 289 290 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 291 syslog(LOG_ERR, "set bridge param: ioctl(BRDGSPRI) " 292 "failed: %s", strerror(errno)); 293 return (-1); 294 } 295 296 /* 297 * Re-fetching the data from the driver after that might be a good 298 * idea, since changing our bridge's priority should invoke 299 * recalculation of the active spanning tree topology in the network. 300 */ 301 bif->priority = priority; 302 return (0); 303 } 304 305 /* 306 * Convert 1/100 of seconds to 1/256 of seconds. 307 * Timeout ::= TEXTUAL-CONVENTION. 308 * To convert a Timeout value into a value in units of 309 * 1/256 seconds, the following algorithm should be used: 310 * b = floor( (n * 256) / 100) 311 * The conversion to 1/256 of a second happens in the kernel - 312 * just make sure we correctly convert the seconds to Timout 313 * and vice versa. 314 */ 315 static uint32_t 316 snmp_timeout2_sec(int32_t secs) 317 { 318 return (secs / 100); 319 } 320 321 int 322 bridge_set_maxage(struct bridge_if *bif, int32_t max_age) 323 { 324 struct ifdrv ifd; 325 struct ifbrparam b_param; 326 327 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 328 ifd.ifd_len = sizeof(b_param); 329 ifd.ifd_data = &b_param; 330 b_param.ifbrp_maxage = snmp_timeout2_sec(max_age); 331 ifd.ifd_cmd = BRDGSMA; 332 333 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 334 syslog(LOG_ERR, "set bridge param: ioctl(BRDGSMA) " 335 "failed: %s", strerror(errno)); 336 return (-1); 337 } 338 339 bif->bridge_max_age = max_age; 340 return (0); 341 } 342 343 int 344 bridge_set_hello_time(struct bridge_if *bif, int32_t hello_time) 345 { 346 struct ifdrv ifd; 347 struct ifbrparam b_param; 348 349 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 350 ifd.ifd_len = sizeof(b_param); 351 ifd.ifd_data = &b_param; 352 b_param.ifbrp_hellotime = snmp_timeout2_sec(hello_time); 353 ifd.ifd_cmd = BRDGSHT; 354 355 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 356 syslog(LOG_ERR, "set bridge param: ioctl(BRDGSHT) " 357 "failed: %s", strerror(errno)); 358 return (-1); 359 } 360 361 bif->bridge_hello_time = b_param.ifbrp_hellotime; 362 return (0); 363 } 364 365 int 366 bridge_set_forward_delay(struct bridge_if *bif, int32_t fwd_delay) 367 { 368 struct ifdrv ifd; 369 struct ifbrparam b_param; 370 371 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 372 ifd.ifd_len = sizeof(b_param); 373 ifd.ifd_data = &b_param; 374 b_param.ifbrp_fwddelay = snmp_timeout2_sec(fwd_delay); 375 ifd.ifd_cmd = BRDGSFD; 376 377 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 378 syslog(LOG_ERR, "set bridge param: ioctl(BRDGSFD) " 379 "failed: %s", strerror(errno)); 380 return (-1); 381 } 382 383 bif->bridge_fwd_delay = b_param.ifbrp_fwddelay; 384 return (0); 385 } 386 387 int 388 bridge_set_aging_time(struct bridge_if *bif, int32_t age_time) 389 { 390 struct ifdrv ifd; 391 struct ifbrparam b_param; 392 393 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 394 ifd.ifd_len = sizeof(b_param); 395 ifd.ifd_data = &b_param; 396 b_param.ifbrp_ctime = (uint32_t) age_time; 397 ifd.ifd_cmd = BRDGSTO; 398 399 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 400 syslog(LOG_ERR, "set bridge param: ioctl(BRDGSTO) " 401 "failed: %s", strerror(errno)); 402 return (-1); 403 } 404 405 bif->age_time = age_time; 406 return (0); 407 } 408 409 int 410 bridge_set_max_cache(struct bridge_if *bif, int32_t max_cache) 411 { 412 struct ifdrv ifd; 413 struct ifbrparam b_param; 414 415 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 416 ifd.ifd_len = sizeof(b_param); 417 ifd.ifd_data = &b_param; 418 b_param.ifbrp_csize = max_cache; 419 ifd.ifd_cmd = BRDGSCACHE; 420 421 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 422 syslog(LOG_ERR, "set bridge param: ioctl(BRDGSCACHE) " 423 "failed: %s", strerror(errno)); 424 return (-1); 425 } 426 427 bif->max_addrs = b_param.ifbrp_csize; 428 return (0); 429 } 430 431 int 432 bridge_set_tx_hold_count(struct bridge_if *bif __unused, 433 int32_t tx_hc __unused) 434 { 435 struct ifdrv ifd; 436 struct ifbrparam b_param; 437 438 if (tx_hc < SNMP_BRIDGE_MIN_TXHC || tx_hc > SNMP_BRIDGE_MAX_TXHC) 439 return (-1); 440 441 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 442 ifd.ifd_len = sizeof(b_param); 443 ifd.ifd_data = &b_param; 444 b_param.ifbrp_txhc = tx_hc; 445 ifd.ifd_cmd = BRDGSTXHC; 446 447 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 448 syslog(LOG_ERR, "set bridge param: ioctl(BRDGSTXHC) " 449 "failed: %s", strerror(errno)); 450 return (-1); 451 } 452 453 bif->tx_hold_count = b_param.ifbrp_txhc; 454 return (0); 455 } 456 457 int 458 bridge_set_stp_version(struct bridge_if *bif __unused, 459 int32_t stp_proto __unused) 460 { 461 struct ifdrv ifd; 462 struct ifbrparam b_param; 463 464 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 465 ifd.ifd_len = sizeof(b_param); 466 ifd.ifd_data = &b_param; 467 b_param.ifbrp_proto = stp_proto; 468 ifd.ifd_cmd = BRDGSPROTO; 469 470 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 471 syslog(LOG_ERR, "set bridge param: ioctl(BRDGSPROTO) " 472 "failed: %s", strerror(errno)); 473 return (-1); 474 } 475 476 bif->stp_version = b_param.ifbrp_proto; 477 return (0); 478 } 479 480 /* 481 * Set the bridge interface status to up/down. 482 */ 483 int 484 bridge_set_if_up(const char* b_name, int8_t up) 485 { 486 int flags; 487 struct ifreq ifr; 488 489 bzero(&ifr, sizeof(ifr)); 490 strcpy(ifr.ifr_name, b_name); 491 if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { 492 syslog(LOG_ERR, "set bridge up: ioctl(SIOCGIFFLAGS) " 493 "failed: %s", strerror(errno)); 494 return (-1); 495 } 496 497 flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); 498 if (up == 1) 499 flags |= IFF_UP; 500 else 501 flags &= ~IFF_UP; 502 503 ifr.ifr_flags = flags & 0xffff; 504 ifr.ifr_flagshigh = flags >> 16; 505 if (ioctl(sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { 506 syslog(LOG_ERR, "set bridge up: ioctl(SIOCSIFFLAGS) " 507 "failed: %s", strerror(errno)); 508 return (-1); 509 } 510 511 return (0); 512 } 513 514 int 515 bridge_create(const char *b_name) 516 { 517 char *new_name; 518 struct ifreq ifr; 519 520 bzero(&ifr, sizeof(ifr)); 521 strcpy(ifr.ifr_name, b_name); 522 523 if (ioctl(sock, SIOCIFCREATE, &ifr) < 0) { 524 syslog(LOG_ERR, "create bridge: ioctl(SIOCIFCREATE) " 525 "failed: %s", strerror(errno)); 526 return (-1); 527 } 528 529 if (strcmp(b_name, ifr.ifr_name) == 0) 530 return (0); 531 532 if ((new_name = strdup(b_name)) == NULL) { 533 syslog(LOG_ERR, "create bridge: strdup() failed"); 534 return (-1); 535 } 536 537 ifr.ifr_data = new_name; 538 if (ioctl(sock, SIOCSIFNAME, (caddr_t) &ifr) < 0) { 539 syslog(LOG_ERR, "create bridge: ioctl(SIOCSIFNAME) " 540 "failed: %s", strerror(errno)); 541 free(new_name); 542 return (-1); 543 } 544 545 return (0); 546 } 547 548 int 549 bridge_destroy(const char *b_name) 550 { 551 struct ifreq ifr; 552 553 bzero(&ifr, sizeof(ifr)); 554 strcpy(ifr.ifr_name, b_name); 555 556 if (ioctl(sock, SIOCIFDESTROY, &ifr) < 0) { 557 syslog(LOG_ERR, "destroy bridge: ioctl(SIOCIFDESTROY) " 558 "failed: %s", strerror(errno)); 559 return (-1); 560 } 561 562 return (0); 563 } 564 565 /* 566 * Fetch the bridge base MAC address. Return pointer to the 567 * buffer containing the MAC address, NULL on failure. 568 */ 569 u_char * 570 bridge_get_basemac(const char *bif_name, u_char *mac, size_t mlen) 571 { 572 int len; 573 char if_name[IFNAMSIZ]; 574 struct ifaddrs *ifap, *ifa; 575 struct sockaddr_dl sdl; 576 577 if (getifaddrs(&ifap) != 0) { 578 syslog(LOG_ERR, "bridge get mac: getifaddrs() failed - %s", 579 strerror(errno)); 580 return (NULL); 581 } 582 583 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 584 if (ifa->ifa_addr->sa_family != AF_LINK) 585 continue; 586 587 /* 588 * Not just casting because of alignment constraints 589 * on sparc64 and ia64. 590 */ 591 bcopy(ifa->ifa_addr, &sdl, sizeof(struct sockaddr_dl)); 592 593 if (sdl.sdl_alen > mlen) 594 continue; 595 596 if ((len = sdl.sdl_nlen) >= IFNAMSIZ) 597 len = IFNAMSIZ - 1; 598 599 bcopy(sdl.sdl_data, if_name, len); 600 if_name[len] = '\0'; 601 602 if (strcmp(bif_name, if_name) == 0) { 603 bcopy(sdl.sdl_data + sdl.sdl_nlen, mac, sdl.sdl_alen); 604 freeifaddrs(ifap); 605 return (mac); 606 } 607 } 608 609 freeifaddrs(ifap); 610 return (NULL); 611 } 612 613 /************************************************************************ 614 * Bridge ports. 615 */ 616 617 /* 618 * Convert the kernel STP port state into 619 * the corresopnding enumerated type from SNMP Bridge MIB. 620 */ 621 static int 622 state2snmp_st(uint8_t ifbr_state) 623 { 624 switch (ifbr_state) { 625 case BSTP_IFSTATE_DISABLED: 626 return (StpPortState_disabled); 627 case BSTP_IFSTATE_LISTENING: 628 return (StpPortState_listening); 629 case BSTP_IFSTATE_LEARNING: 630 return (StpPortState_learning); 631 case BSTP_IFSTATE_FORWARDING: 632 return (StpPortState_forwarding); 633 case BSTP_IFSTATE_BLOCKING: 634 case BSTP_IFSTATE_DISCARDING: 635 return (StpPortState_blocking); 636 } 637 638 return (StpPortState_broken); 639 } 640 641 /* 642 * Fill in a bridge member information according to data polled from kernel. 643 */ 644 static void 645 bridge_port_getinfo_conf(struct ifbreq *k_info, struct bridge_port *bp) 646 { 647 bp->state = state2snmp_st(k_info->ifbr_state); 648 bp->priority = k_info->ifbr_priority; 649 650 /* 651 * RFC 4188: 652 * "New implementations should support dot1dStpPortPathCost32. 653 * If the port path costs exceeds the maximum value of this 654 * object then this object should report the maximum value, 655 * namely 65535. Applications should try to read the 656 * dot1dStpPortPathCost32 object if this object reports 657 * the maximum value." 658 */ 659 660 if (k_info->ifbr_ifsflags & IFBIF_BSTP_ADMCOST) 661 bp->admin_path_cost = k_info->ifbr_path_cost; 662 else 663 bp->admin_path_cost = 0; 664 665 bp->path_cost = k_info->ifbr_path_cost; 666 667 if (k_info->ifbr_ifsflags & IFBIF_STP) 668 bp->enable = dot1dStpPortEnable_enabled; 669 else 670 bp->enable = dot1dStpPortEnable_disabled; 671 672 /* Begemot Bridge MIB only. */ 673 if (k_info->ifbr_ifsflags & IFBIF_SPAN) 674 bp->span_enable = begemotBridgeBaseSpanEnabled_enabled; 675 else 676 bp->span_enable = begemotBridgeBaseSpanEnabled_disabled; 677 678 if (k_info->ifbr_ifsflags & IFBIF_BSTP_ADMEDGE) 679 bp->admin_edge = TruthValue_true; 680 else 681 bp->admin_edge = TruthValue_false; 682 683 if (k_info->ifbr_ifsflags & IFBIF_BSTP_EDGE) 684 bp->oper_edge = TruthValue_true; 685 else 686 bp->oper_edge = TruthValue_false; 687 688 if (k_info->ifbr_ifsflags & IFBIF_BSTP_AUTOPTP) { 689 bp->admin_ptp = StpPortAdminPointToPointType_auto; 690 if (k_info->ifbr_ifsflags & IFBIF_BSTP_PTP) 691 bp->oper_ptp = TruthValue_true; 692 else 693 bp->oper_ptp = TruthValue_false; 694 } else if (k_info->ifbr_ifsflags & IFBIF_BSTP_PTP) { 695 bp->admin_ptp = StpPortAdminPointToPointType_forceTrue; 696 bp->oper_ptp = TruthValue_true; 697 } else { 698 bp->admin_ptp = StpPortAdminPointToPointType_forceFalse; 699 bp->oper_ptp = TruthValue_false; 700 } 701 } 702 703 /* 704 * Fill in a bridge interface STP information according to 705 * data polled from kernel. 706 */ 707 static void 708 bridge_port_getinfo_opstp(struct ifbpstpreq *bp_stp, struct bridge_port *bp) 709 { 710 bp->enable = dot1dStpPortEnable_enabled; 711 bp->fwd_trans = bp_stp->ifbp_fwd_trans; 712 bp->design_cost = bp_stp->ifbp_design_cost; 713 snmp_uint64_to_bridgeid(bp_stp->ifbp_design_root, bp->design_root); 714 snmp_uint64_to_bridgeid(bp_stp->ifbp_design_bridge, bp->design_bridge); 715 bcopy(&(bp_stp->ifbp_design_port), &(bp->design_port), 716 sizeof(uint16_t)); 717 } 718 719 /* 720 * Clear a bridge interface STP information. 721 */ 722 static void 723 bridge_port_clearinfo_opstp(struct bridge_port *bp) 724 { 725 if (bp->enable == dot1dStpPortEnable_enabled) { 726 bp->design_cost = 0; 727 bzero(&(bp->design_root), sizeof(bridge_id)); 728 bzero(&(bp->design_bridge), sizeof(bridge_id)); 729 bzero(&(bp->design_port), sizeof(port_id)); 730 bp->fwd_trans = 0; 731 } 732 733 bp->enable = dot1dStpPortEnable_disabled; 734 } 735 736 /* 737 * Set a bridge member priority. 738 */ 739 int 740 bridge_port_set_priority(const char *bif_name, struct bridge_port *bp, 741 int32_t priority) 742 { 743 struct ifdrv ifd; 744 struct ifbreq b_req; 745 746 strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 747 ifd.ifd_len = sizeof(b_req); 748 ifd.ifd_data = &b_req; 749 strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 750 751 b_req.ifbr_priority = (uint8_t) priority; 752 ifd.ifd_cmd = BRDGSIFPRIO; 753 754 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 755 syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFPRIO) " 756 "failed: %s", bp->p_name, strerror(errno)); 757 return (-1); 758 } 759 760 bp->priority = priority; 761 return (0); 762 } 763 764 /* 765 * Set a bridge member STP-enabled flag. 766 */ 767 int 768 bridge_port_set_stp_enable(const char *bif_name, struct bridge_port *bp, 769 uint32_t enable) 770 { 771 struct ifdrv ifd; 772 struct ifbreq b_req; 773 774 if (bp->enable == enable) 775 return (0); 776 777 bzero(&b_req, sizeof(b_req)); 778 strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 779 ifd.ifd_len = sizeof(b_req); 780 ifd.ifd_data = &b_req; 781 strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 782 ifd.ifd_cmd = BRDGGIFFLGS; 783 784 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 785 syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) " 786 "failed: %s", bp->p_name, strerror(errno)); 787 return (-1); 788 } 789 790 if (enable == dot1dStpPortEnable_enabled) 791 b_req.ifbr_ifsflags |= IFBIF_STP; 792 else 793 b_req.ifbr_ifsflags &= ~IFBIF_STP; 794 795 ifd.ifd_cmd = BRDGSIFFLGS; 796 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 797 syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) " 798 "failed: %s", bp->p_name, strerror(errno)); 799 return (-1); 800 } 801 802 bp->enable = enable; 803 return (0); 804 } 805 806 /* 807 * Set a bridge member STP path cost. 808 */ 809 int 810 bridge_port_set_path_cost(const char *bif_name, struct bridge_port *bp, 811 int32_t path_cost) 812 { 813 struct ifdrv ifd; 814 struct ifbreq b_req; 815 816 if (path_cost < SNMP_PORT_MIN_PATHCOST || 817 path_cost > SNMP_PORT_PATHCOST_OBSOLETE) 818 return (-2); 819 820 strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 821 ifd.ifd_len = sizeof(b_req); 822 ifd.ifd_data = &b_req; 823 strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 824 825 b_req.ifbr_path_cost = path_cost; 826 ifd.ifd_cmd = BRDGSIFCOST; 827 828 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 829 syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFCOST) " 830 "failed: %s", bp->p_name, strerror(errno)); 831 return (-1); 832 } 833 834 bp->admin_path_cost = path_cost; 835 836 return (0); 837 } 838 839 /* 840 * Set the PonitToPoint status of the link administratively. 841 */ 842 int 843 bridge_port_set_admin_ptp(const char *bif_name __unused, 844 struct bridge_port *bp __unused, uint32_t admin_ptp __unused) 845 { 846 struct ifdrv ifd; 847 struct ifbreq b_req; 848 849 if (bp->admin_ptp == admin_ptp) 850 return (0); 851 852 bzero(&b_req, sizeof(b_req)); 853 strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 854 ifd.ifd_len = sizeof(b_req); 855 ifd.ifd_data = &b_req; 856 strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 857 ifd.ifd_cmd = BRDGGIFFLGS; 858 859 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 860 syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) " 861 "failed: %s", bp->p_name, strerror(errno)); 862 return (-1); 863 } 864 865 switch (admin_ptp) { 866 case StpPortAdminPointToPointType_forceTrue: 867 b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOPTP; 868 b_req.ifbr_ifsflags |= IFBIF_BSTP_PTP; 869 break; 870 case StpPortAdminPointToPointType_forceFalse: 871 b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOPTP; 872 b_req.ifbr_ifsflags &= ~IFBIF_BSTP_PTP; 873 break; 874 case StpPortAdminPointToPointType_auto: 875 b_req.ifbr_ifsflags |= IFBIF_BSTP_AUTOPTP; 876 break; 877 } 878 879 ifd.ifd_cmd = BRDGSIFFLGS; 880 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 881 syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) " 882 "failed: %s", bp->p_name, strerror(errno)); 883 return (-1); 884 } 885 886 bp->admin_ptp = admin_ptp; 887 return (0); 888 } 889 890 /* 891 * Set admin edge. 892 */ 893 int 894 bridge_port_set_admin_edge(const char *bif_name __unused, 895 struct bridge_port *bp __unused, uint32_t enable __unused) 896 { 897 struct ifdrv ifd; 898 struct ifbreq b_req; 899 900 if (bp->admin_edge == enable) 901 return (0); 902 903 bzero(&b_req, sizeof(b_req)); 904 strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 905 ifd.ifd_len = sizeof(b_req); 906 ifd.ifd_data = &b_req; 907 strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 908 ifd.ifd_cmd = BRDGGIFFLGS; 909 910 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 911 syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) " 912 "failed: %s", bp->p_name, strerror(errno)); 913 return (-1); 914 } 915 916 if (enable == TruthValue_true) { 917 b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOEDGE; 918 b_req.ifbr_ifsflags |= IFBIF_BSTP_EDGE; 919 } else 920 b_req.ifbr_ifsflags &= ~IFBIF_BSTP_EDGE; 921 922 ifd.ifd_cmd = BRDGSIFFLGS; 923 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 924 syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) " 925 "failed: %s", bp->p_name, strerror(errno)); 926 return (-1); 927 } 928 929 bp->admin_edge = enable; 930 931 return (0); 932 } 933 934 /* 935 * Add a bridge member port. 936 */ 937 int 938 bridge_port_addm(struct bridge_port *bp, const char *b_name) 939 { 940 struct ifdrv ifd; 941 struct ifbreq b_req; 942 943 bzero(&ifd, sizeof(ifd)); 944 bzero(&b_req, sizeof(b_req)); 945 946 strlcpy(ifd.ifd_name, b_name, sizeof(ifd.ifd_name)); 947 ifd.ifd_len = sizeof(b_req); 948 ifd.ifd_data = &b_req; 949 strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 950 951 if (bp->span_enable == begemotBridgeBaseSpanEnabled_enabled) 952 ifd.ifd_cmd = BRDGADDS; 953 else 954 ifd.ifd_cmd = BRDGADD; 955 956 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 957 syslog(LOG_ERR, "%s - add member : ioctl(%s) failed: %s", 958 bp->p_name, 959 (ifd.ifd_cmd == BRDGADDS ? "BRDGADDS" : "BRDGADD"), 960 strerror(errno)); 961 return (-1); 962 } 963 964 return (0); 965 } 966 967 /* 968 * Delete a bridge member port. 969 */ 970 int 971 bridge_port_delm(struct bridge_port *bp, const char *b_name) 972 { 973 struct ifdrv ifd; 974 struct ifbreq b_req; 975 976 bzero(&ifd, sizeof(ifd)); 977 bzero(&b_req, sizeof(b_req)); 978 979 strlcpy(ifd.ifd_name, b_name, sizeof(ifd.ifd_name)); 980 ifd.ifd_len = sizeof(b_req); 981 ifd.ifd_data = &b_req; 982 strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 983 984 if (bp->span_enable == begemotBridgeBaseSpanEnabled_enabled) 985 ifd.ifd_cmd = BRDGDELS; 986 else 987 ifd.ifd_cmd = BRDGDEL; 988 989 if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 990 syslog(LOG_ERR, "%s - add member : ioctl(%s) failed: %s", 991 bp->p_name, 992 (ifd.ifd_cmd == BRDGDELS ? "BRDGDELS" : "BRDGDEL"), 993 strerror(errno)); 994 return (-1); 995 } 996 997 return (0); 998 } 999 1000 /* 1001 * Fetch the bridge member list from kernel. 1002 * Return -1 on error, or buffer len if successful. 1003 */ 1004 static int32_t 1005 bridge_port_get_iflist(struct bridge_if *bif, struct ifbreq **buf) 1006 { 1007 int n = 128; 1008 uint32_t len; 1009 struct ifbreq *ninbuf; 1010 struct ifbifconf ifbc; 1011 struct ifdrv ifd; 1012 1013 *buf = NULL; 1014 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 1015 ifd.ifd_cmd = BRDGGIFS; 1016 ifd.ifd_len = sizeof(ifbc); 1017 ifd.ifd_data = &ifbc; 1018 1019 for ( ; ; ) { 1020 len = n * sizeof(struct ifbreq); 1021 if ((ninbuf = (struct ifbreq *)realloc(*buf, len)) == NULL) { 1022 syslog(LOG_ERR, "get bridge member list: " 1023 "realloc failed: %s", strerror(errno)); 1024 free(*buf); 1025 *buf = NULL; 1026 return (-1); 1027 } 1028 1029 ifbc.ifbic_len = len; 1030 ifbc.ifbic_req = *buf = ninbuf; 1031 1032 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 1033 syslog(LOG_ERR, "get bridge member list: ioctl " 1034 "(BRDGGIFS) failed: %s", strerror(errno)); 1035 free(*buf); 1036 buf = NULL; 1037 return (-1); 1038 } 1039 1040 if ((ifbc.ifbic_len + sizeof(struct ifbreq)) < len) 1041 break; 1042 1043 n += 64; 1044 } 1045 1046 return (ifbc.ifbic_len); 1047 } 1048 1049 /* 1050 * Fetch the bridge STP member list from kernel. 1051 * Return -1 on error, or buffer len if successful. 1052 */ 1053 static int32_t 1054 bridge_port_get_ifstplist(struct bridge_if *bif, struct ifbpstpreq **buf) 1055 { 1056 int n = 128; 1057 uint32_t len; 1058 struct ifbpstpreq *ninbuf; 1059 struct ifbpstpconf ifbstp; 1060 struct ifdrv ifd; 1061 1062 *buf = NULL; 1063 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 1064 ifd.ifd_cmd = BRDGGIFSSTP; 1065 ifd.ifd_len = sizeof(ifbstp); 1066 ifd.ifd_data = &ifbstp; 1067 1068 for ( ; ; ) { 1069 len = n * sizeof(struct ifbpstpreq); 1070 if ((ninbuf = (struct ifbpstpreq *) 1071 realloc(*buf, len)) == NULL) { 1072 syslog(LOG_ERR, "get bridge STP ports list: " 1073 "realloc failed: %s", strerror(errno)); 1074 free(*buf); 1075 *buf = NULL; 1076 return (-1); 1077 } 1078 1079 ifbstp.ifbpstp_len = len; 1080 ifbstp.ifbpstp_req = *buf = ninbuf; 1081 1082 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 1083 syslog(LOG_ERR, "get bridge STP ports list: ioctl " 1084 "(BRDGGIFSSTP) failed: %s", strerror(errno)); 1085 free(*buf); 1086 buf = NULL; 1087 return (-1); 1088 } 1089 1090 if ((ifbstp.ifbpstp_len + sizeof(struct ifbpstpreq)) < len) 1091 break; 1092 1093 n += 64; 1094 } 1095 1096 return (ifbstp.ifbpstp_len); 1097 } 1098 1099 /* 1100 * Locate a bridge if STP params structure in a buffer. 1101 */ 1102 static struct ifbpstpreq * 1103 bridge_port_find_ifstplist(uint8_t port_no, struct ifbpstpreq *buf, 1104 uint32_t buf_len) 1105 { 1106 uint32_t i; 1107 struct ifbpstpreq *bstp; 1108 1109 for (i = 0; i < buf_len / sizeof(struct ifbpstpreq); i++) { 1110 bstp = buf + i; 1111 if (bstp->ifbp_portno == port_no) 1112 return (bstp); 1113 } 1114 1115 return (NULL); 1116 } 1117 1118 /* 1119 * Read the initial info for all members of a bridge interface. 1120 * Returns the number of ports, 0 - if none, otherwise 1121 * -1 if some other error occured. 1122 */ 1123 int 1124 bridge_getinfo_bif_ports(struct bridge_if *bif) 1125 { 1126 uint32_t i; 1127 int32_t buf_len; 1128 struct ifbreq *b_req_buf, *b_req; 1129 struct ifbpstpreq *bs_req_buf, *bs_req; 1130 struct bridge_port *bp; 1131 struct mibif *m_if; 1132 1133 if ((buf_len = bridge_port_get_iflist(bif, &b_req_buf)) < 0) 1134 return (-1); 1135 1136 for (i = 0; i < buf_len / sizeof(struct ifbreq); i++) { 1137 b_req = b_req_buf + i; 1138 1139 if ((m_if = mib_find_if_sys(b_req->ifbr_portno)) != NULL) { 1140 /* Hopefully we will not fail here. */ 1141 if ((bp = bridge_new_port(m_if, bif)) != NULL) { 1142 bp->status = RowStatus_active; 1143 bridge_port_getinfo_conf(b_req, bp); 1144 bridge_port_getinfo_mibif(m_if, bp); 1145 } 1146 } else { 1147 syslog(LOG_ERR, "bridge member %s not present " 1148 "in mibII ifTable", b_req->ifbr_ifsname); 1149 } 1150 } 1151 free(b_req_buf); 1152 1153 if ((buf_len = bridge_port_get_ifstplist(bif, &bs_req_buf)) < 0) 1154 return (-1); 1155 1156 for (bp = bridge_port_bif_first(bif); bp != NULL; 1157 bp = bridge_port_bif_next(bp)) { 1158 if ((bs_req = bridge_port_find_ifstplist(bp->port_no, 1159 bs_req_buf, buf_len)) == NULL) 1160 bridge_port_clearinfo_opstp(bp); 1161 else 1162 bridge_port_getinfo_opstp(bs_req, bp); 1163 } 1164 free(bs_req_buf); 1165 1166 return (i); 1167 } 1168 1169 /* 1170 * Update the information for the bridge interface members. 1171 */ 1172 int 1173 bridge_update_memif(struct bridge_if *bif) 1174 { 1175 int added, updated; 1176 uint32_t i; 1177 int32_t buf_len; 1178 struct ifbreq *b_req_buf, *b_req; 1179 struct ifbpstpreq *bs_req_buf, *bs_req; 1180 struct bridge_port *bp, *bp_next; 1181 struct mibif *m_if; 1182 1183 if ((buf_len = bridge_port_get_iflist(bif, &b_req_buf)) < 0) 1184 return (-1); 1185 1186 added = updated = 0; 1187 1188 #define BP_FOUND 0x01 1189 for (i = 0; i < buf_len / sizeof(struct ifbreq); i++) { 1190 b_req = b_req_buf + i; 1191 1192 if ((m_if = mib_find_if_sys(b_req->ifbr_portno)) == NULL) { 1193 syslog(LOG_ERR, "bridge member %s not present " 1194 "in mibII ifTable", b_req->ifbr_ifsname); 1195 continue; 1196 } 1197 1198 if ((bp = bridge_port_find(m_if->index, bif)) == NULL && 1199 (bp = bridge_new_port(m_if, bif)) != NULL) { 1200 bp->status = RowStatus_active; 1201 added++; 1202 } 1203 1204 if (bp != NULL) { 1205 updated++; 1206 bridge_port_getinfo_conf(b_req, bp); 1207 bridge_port_getinfo_mibif(m_if, bp); 1208 bp->flags |= BP_FOUND; 1209 } 1210 } 1211 free(b_req_buf); 1212 1213 /* Clean up list. */ 1214 for (bp = bridge_port_bif_first(bif); bp != NULL; bp = bp_next) { 1215 bp_next = bridge_port_bif_next(bp); 1216 1217 if ((bp->flags & BP_FOUND) == 0 && 1218 bp->status == RowStatus_active) 1219 bridge_port_remove(bp, bif); 1220 else 1221 bp->flags |= ~BP_FOUND; 1222 } 1223 #undef BP_FOUND 1224 1225 if ((buf_len = bridge_port_get_ifstplist(bif, &bs_req_buf)) < 0) 1226 return (-1); 1227 1228 for (bp = bridge_port_bif_first(bif); bp != NULL; 1229 bp = bridge_port_bif_next(bp)) { 1230 if ((bs_req = bridge_port_find_ifstplist(bp->port_no, 1231 bs_req_buf, buf_len)) == NULL) 1232 bridge_port_clearinfo_opstp(bp); 1233 else 1234 bridge_port_getinfo_opstp(bs_req, bp); 1235 } 1236 free(bs_req_buf); 1237 bif->ports_age = time(NULL); 1238 1239 return (updated); 1240 } 1241 1242 /************************************************************************ 1243 * Bridge addresses. 1244 */ 1245 1246 /* 1247 * Update the bridge address info according to the polled data. 1248 */ 1249 static void 1250 bridge_addrs_info_ifaddrlist(struct ifbareq *ifba, struct tp_entry *tpe) 1251 { 1252 tpe->port_no = if_nametoindex(ifba->ifba_ifsname); 1253 1254 if ((ifba->ifba_flags & IFBAF_TYPEMASK) == IFBAF_STATIC) 1255 tpe->status = TpFdbStatus_mgmt; 1256 else 1257 tpe->status = TpFdbStatus_learned; 1258 } 1259 1260 /* 1261 * Read the bridge addresses from kernel. 1262 * Return -1 on error, or buffer len if successful. 1263 */ 1264 static int32_t 1265 bridge_addrs_getinfo_ifalist(struct bridge_if *bif, struct ifbareq **buf) 1266 { 1267 int n = 128; 1268 uint32_t len; 1269 struct ifbareq *ninbuf; 1270 struct ifbaconf bac; 1271 struct ifdrv ifd; 1272 1273 *buf = NULL; 1274 strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 1275 ifd.ifd_cmd = BRDGRTS; 1276 ifd.ifd_len = sizeof(bac); 1277 ifd.ifd_data = &bac; 1278 1279 for ( ; ; ) { 1280 len = n * sizeof(struct ifbareq); 1281 if ((ninbuf = (struct ifbareq *)realloc(*buf, len)) == NULL) { 1282 syslog(LOG_ERR, "get bridge address list: " 1283 " realloc failed: %s", strerror(errno)); 1284 free(*buf); 1285 *buf = NULL; 1286 return (-1); 1287 } 1288 1289 bac.ifbac_len = len; 1290 bac.ifbac_req = *buf = ninbuf; 1291 1292 if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 1293 syslog(LOG_ERR, "get bridge address list: " 1294 "ioctl(BRDGRTS) failed: %s", strerror(errno)); 1295 free(*buf); 1296 buf = NULL; 1297 return (-1); 1298 } 1299 1300 if ((bac.ifbac_len + sizeof(struct ifbareq)) < len) 1301 break; 1302 1303 n += 64; 1304 } 1305 1306 return (bac.ifbac_len); 1307 } 1308 1309 /* 1310 * Read the initial info for all addresses on a bridge interface. 1311 * Returns the number of addresses, 0 - if none, otherwise 1312 * -1 if some other error occured. 1313 */ 1314 int 1315 bridge_getinfo_bif_addrs(struct bridge_if *bif) 1316 { 1317 uint32_t i; 1318 int32_t buf_len; 1319 struct ifbareq *addr_req_buf, *addr_req; 1320 struct tp_entry *te; 1321 1322 if ((buf_len = bridge_addrs_getinfo_ifalist(bif, &addr_req_buf)) < 0) 1323 return (-1); 1324 1325 for (i = 0; i < buf_len / sizeof(struct ifbareq); i++) { 1326 addr_req = addr_req_buf + i; 1327 1328 if ((te = bridge_new_addrs(addr_req->ifba_dst, bif)) != NULL) 1329 bridge_addrs_info_ifaddrlist(addr_req, te); 1330 } 1331 1332 free(addr_req_buf); 1333 return (i); 1334 } 1335 1336 /* 1337 * Update the addresses for the bridge interface. 1338 */ 1339 int 1340 bridge_update_addrs(struct bridge_if *bif) 1341 { 1342 int added, updated; 1343 uint32_t i; 1344 int32_t buf_len; 1345 struct tp_entry *te, *te_next; 1346 struct ifbareq *addr_req_buf, *addr_req; 1347 1348 if ((buf_len = bridge_addrs_getinfo_ifalist(bif, &addr_req_buf)) < 0) 1349 return (-1); 1350 1351 added = updated = 0; 1352 1353 #define BA_FOUND 0x01 1354 for (i = 0; i < buf_len / sizeof(struct ifbareq); i++) { 1355 addr_req = addr_req_buf + i; 1356 1357 if ((te = bridge_addrs_find(addr_req->ifba_dst, bif)) == NULL) { 1358 added++; 1359 1360 if ((te = bridge_new_addrs(addr_req->ifba_dst, bif)) 1361 == NULL) 1362 continue; 1363 } else 1364 updated++; 1365 1366 bridge_addrs_info_ifaddrlist(addr_req, te); 1367 te-> flags |= BA_FOUND; 1368 } 1369 free(addr_req_buf); 1370 1371 for (te = bridge_addrs_bif_first(bif); te != NULL; te = te_next) { 1372 te_next = bridge_addrs_bif_next(te); 1373 1374 if ((te-> flags & BA_FOUND) == 0) 1375 bridge_addrs_remove(te, bif); 1376 else 1377 te-> flags &= ~BA_FOUND; 1378 } 1379 #undef BA_FOUND 1380 1381 bif->addrs_age = time(NULL); 1382 return (updated + added); 1383 } 1384 1385 /************************************************************************ 1386 * Bridge packet filtering. 1387 */ 1388 const char bridge_sysctl[] = "net.link.bridge."; 1389 1390 static struct { 1391 int32_t val; 1392 const char *name; 1393 } bridge_pf_sysctl[] = { 1394 { 1, "pfil_bridge" }, 1395 { 1, "pfil_member" }, 1396 { 1, "pfil_onlyip" }, 1397 { 0, "ipfw" }, 1398 }; 1399 1400 int32_t 1401 bridge_get_pfval(uint8_t which) 1402 { 1403 if (which > sizeof(bridge_pf_sysctl) / sizeof(bridge_pf_sysctl[0]) 1404 || which < 1) 1405 return (-1); 1406 1407 return (bridge_pf_sysctl[which - 1].val); 1408 } 1409 1410 int32_t 1411 bridge_do_pfctl(int32_t bridge_ctl, enum snmp_op op, int32_t *val) 1412 { 1413 char mib_name[100]; 1414 int32_t i, s_i; 1415 size_t len, s_len; 1416 1417 if (bridge_ctl >= LEAF_begemotBridgeLayer2PfStatus) 1418 return (-2); 1419 1420 if (op == SNMP_OP_SET) { 1421 s_i = *val; 1422 s_len = sizeof(s_i); 1423 } else 1424 s_len = 0; 1425 1426 len = sizeof(i); 1427 1428 strcpy(mib_name, bridge_sysctl); 1429 1430 if (sysctlbyname(strcat(mib_name, 1431 bridge_pf_sysctl[bridge_ctl].name), &i, &len, 1432 (op == SNMP_OP_SET ? &s_i : NULL), s_len) == -1) { 1433 syslog(LOG_ERR, "sysctl(%s%s) failed - %s", bridge_sysctl, 1434 bridge_pf_sysctl[bridge_ctl].name, strerror(errno)); 1435 return (-1); 1436 } 1437 1438 bridge_pf_sysctl[bridge_ctl].val = i; 1439 *val = i; 1440 1441 return (i); 1442 } 1443 1444 void 1445 bridge_pf_dump(void) 1446 { 1447 uint8_t i; 1448 1449 for (i = 0; i < sizeof(bridge_pf_sysctl) / sizeof(bridge_pf_sysctl[0]); 1450 i++) { 1451 syslog(LOG_ERR, "%s%s = %d", bridge_sysctl, 1452 bridge_pf_sysctl[i].name, bridge_pf_sysctl[i].val); 1453 } 1454 } 1455