bridge_sys.c revision 268351
1164410Ssyrinx/*- 2164410Ssyrinx * Copyright (c) 2006 Shteryana Shopova <syrinx@FreeBSD.org> 3164410Ssyrinx * All rights reserved. 4164410Ssyrinx * 5164410Ssyrinx * Redistribution and use in source and binary forms, with or without 6164410Ssyrinx * modification, are permitted provided that the following conditions 7164410Ssyrinx * are met: 8164410Ssyrinx * 1. Redistributions of source code must retain the above copyright 9164410Ssyrinx * notice, this list of conditions and the following disclaimer. 10164410Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright 11164410Ssyrinx * notice, this list of conditions and the following disclaimer in the 12164410Ssyrinx * documentation and/or other materials provided with the distribution. 13164410Ssyrinx * 14164410Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15164410Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16164410Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17164410Ssyrinx * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18164410Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19164410Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20164410Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21164410Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22164410Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23164410Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24164410Ssyrinx * SUCH DAMAGE. 25164410Ssyrinx * 26164410Ssyrinx * Bridge MIB implementation for SNMPd. 27164410Ssyrinx * Bridge OS specific ioctls. 28164410Ssyrinx * 29164410Ssyrinx * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_sys.c 268351 2014-07-07 00:27:09Z marcel $ 30164410Ssyrinx */ 31164410Ssyrinx 32164410Ssyrinx#include <sys/ioctl.h> 33164410Ssyrinx#include <sys/param.h> 34164410Ssyrinx#include <sys/module.h> 35164410Ssyrinx#include <sys/linker.h> 36164410Ssyrinx#include <sys/socket.h> 37164410Ssyrinx#include <sys/sysctl.h> 38164410Ssyrinx 39164410Ssyrinx#include <net/bridgestp.h> 40164410Ssyrinx#include <net/ethernet.h> 41164410Ssyrinx#include <net/if.h> 42164410Ssyrinx#include <net/if_bridgevar.h> 43164410Ssyrinx#include <net/if_dl.h> 44164410Ssyrinx#include <net/if_mib.h> 45164410Ssyrinx#include <net/if_types.h> 46164410Ssyrinx#include <netinet/in.h> 47164410Ssyrinx 48164410Ssyrinx#include <errno.h> 49164410Ssyrinx#include <ifaddrs.h> 50164410Ssyrinx#include <stdarg.h> 51164410Ssyrinx#include <stdlib.h> 52164410Ssyrinx#include <stdio.h> 53164410Ssyrinx#include <string.h> 54164410Ssyrinx#include <syslog.h> 55164410Ssyrinx 56164410Ssyrinx#include <bsnmp/snmpmod.h> 57164410Ssyrinx#include <bsnmp/snmp_mibII.h> 58164410Ssyrinx 59164410Ssyrinx#include "bridge_tree.h" 60164410Ssyrinx#include "bridge_snmp.h" 61164410Ssyrinx 62164410Ssyrinxint sock = -1; 63164410Ssyrinx 64164410Ssyrinxint 65164410Ssyrinxbridge_ioctl_init(void) 66164410Ssyrinx{ 67164410Ssyrinx if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 68164410Ssyrinx syslog(LOG_ERR, "cannot open socket : %s", strerror(errno)); 69164410Ssyrinx return (-1); 70164410Ssyrinx } 71164410Ssyrinx 72164410Ssyrinx return (0); 73164410Ssyrinx} 74164410Ssyrinx 75164410Ssyrinx/* 76164410Ssyrinx * Load the if_bridge.ko module in kernel if not already there. 77164410Ssyrinx */ 78164410Ssyrinxint 79164410Ssyrinxbridge_kmod_load(void) 80164410Ssyrinx{ 81164410Ssyrinx int fileid, modid; 82164410Ssyrinx const char mod_name[] = "if_bridge"; 83164410Ssyrinx struct module_stat mstat; 84164410Ssyrinx 85164410Ssyrinx /* Scan files in kernel. */ 86164410Ssyrinx mstat.version = sizeof(struct module_stat); 87164410Ssyrinx for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 88164410Ssyrinx /* Scan modules in file. */ 89164410Ssyrinx for (modid = kldfirstmod(fileid); modid > 0; 90164410Ssyrinx modid = modfnext(modid)) { 91164410Ssyrinx 92164410Ssyrinx if (modstat(modid, &mstat) < 0) 93164410Ssyrinx continue; 94164410Ssyrinx 95164410Ssyrinx if (strcmp(mod_name, mstat.name) == 0) 96164410Ssyrinx return (0); 97164410Ssyrinx } 98164410Ssyrinx } 99164410Ssyrinx 100164410Ssyrinx /* Not present - load it. */ 101164410Ssyrinx if (kldload(mod_name) < 0) { 102164410Ssyrinx syslog(LOG_ERR, "failed to load %s kernel module", mod_name); 103164410Ssyrinx return (-1); 104164410Ssyrinx } 105164410Ssyrinx 106164410Ssyrinx return (1); 107164410Ssyrinx} 108164410Ssyrinx 109164410Ssyrinx/************************************************************************ 110164410Ssyrinx * Bridge interfaces. 111164410Ssyrinx */ 112164410Ssyrinx 113164410Ssyrinx/* 114164410Ssyrinx * Convert the kernel uint64_t value for a bridge id 115164410Ssyrinx */ 116164410Ssyrinxstatic void 117164410Ssyrinxsnmp_uint64_to_bridgeid(uint64_t id, bridge_id b_id) 118164410Ssyrinx{ 119164410Ssyrinx int i; 120164410Ssyrinx u_char *o; 121164410Ssyrinx 122164410Ssyrinx o = (u_char *) &id; 123164410Ssyrinx 124164410Ssyrinx for (i = 0; i < SNMP_BRIDGE_ID_LEN; i++, o++) 125164410Ssyrinx b_id[SNMP_BRIDGE_ID_LEN - i - 1] = *o; 126164410Ssyrinx} 127164410Ssyrinx 128164410Ssyrinx/* 129164410Ssyrinx * Fetch the bridge configuration parameters from the kernel excluding 130164410Ssyrinx * it's base MAC address. 131164410Ssyrinx */ 132164410Ssyrinxstatic int 133164410Ssyrinxbridge_get_conf_param(struct bridge_if *bif) 134164410Ssyrinx{ 135164410Ssyrinx struct ifdrv ifd; 136164410Ssyrinx struct ifbrparam b_param; 137164410Ssyrinx 138164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 139164410Ssyrinx ifd.ifd_len = sizeof(b_param); 140164410Ssyrinx ifd.ifd_data = &b_param; 141164410Ssyrinx 142164410Ssyrinx /* Bridge priority. */ 143164410Ssyrinx ifd.ifd_cmd = BRDGGPRI; 144164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 145164410Ssyrinx syslog(LOG_ERR, "update bridge: ioctl(BRDGGPRI) failed: %s", 146164410Ssyrinx strerror(errno)); 147164410Ssyrinx return (-1); 148164410Ssyrinx } 149164410Ssyrinx 150164410Ssyrinx bif->priority = b_param.ifbrp_prio; 151164410Ssyrinx 152164410Ssyrinx /* Configured max age. */ 153164410Ssyrinx ifd.ifd_cmd = BRDGGMA; 154164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 155164410Ssyrinx syslog(LOG_ERR, "update bridge: ioctl(BRDGGMA) failed: %s", 156164410Ssyrinx strerror(errno)); 157164410Ssyrinx return (-1); 158164410Ssyrinx } 159164410Ssyrinx 160164410Ssyrinx /* Centi-seconds. */ 161164410Ssyrinx bif->bridge_max_age = 100 * b_param.ifbrp_maxage; 162164410Ssyrinx 163164410Ssyrinx /* Configured hello time. */ 164164410Ssyrinx ifd.ifd_cmd = BRDGGHT; 165164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 166164410Ssyrinx syslog(LOG_ERR, "update bridge: ioctl(BRDGGHT) failed: %s", 167164410Ssyrinx strerror(errno)); 168164410Ssyrinx return (-1); 169164410Ssyrinx } 170164410Ssyrinx bif->bridge_hello_time = 100 * b_param.ifbrp_hellotime; 171164410Ssyrinx 172164410Ssyrinx /* Forward delay. */ 173164410Ssyrinx ifd.ifd_cmd = BRDGGFD; 174164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 175164410Ssyrinx syslog(LOG_ERR, "update bridge: ioctl(BRDGGFD) failed: %s", 176164410Ssyrinx strerror(errno)); 177164410Ssyrinx return (-1); 178164410Ssyrinx } 179164410Ssyrinx bif->bridge_fwd_delay = 100 * b_param.ifbrp_fwddelay; 180164410Ssyrinx 181164410Ssyrinx /* Number of dropped addresses. */ 182164410Ssyrinx ifd.ifd_cmd = BRDGGRTE; 183164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 184164410Ssyrinx syslog(LOG_ERR, "update bridge: ioctl(BRDGGRTE) failed: %s", 185164410Ssyrinx strerror(errno)); 186164410Ssyrinx return (-1); 187164410Ssyrinx } 188164410Ssyrinx bif->lrnt_drops = b_param.ifbrp_cexceeded; 189164410Ssyrinx 190164410Ssyrinx /* Address table timeout. */ 191164410Ssyrinx ifd.ifd_cmd = BRDGGTO; 192164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 193164410Ssyrinx syslog(LOG_ERR, "update bridge: ioctl(BRDGGTO) failed: %s", 194164410Ssyrinx strerror(errno)); 195164410Ssyrinx return (-1); 196164410Ssyrinx } 197164410Ssyrinx bif->age_time = b_param.ifbrp_ctime; 198164410Ssyrinx 199164410Ssyrinx /* Address table size. */ 200164410Ssyrinx ifd.ifd_cmd = BRDGGCACHE; 201164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 202164410Ssyrinx syslog(LOG_ERR, "update bridge: ioctl(BRDGGCACHE) " 203164410Ssyrinx "failed: %s", strerror(errno)); 204164410Ssyrinx return (-1); 205164410Ssyrinx } 206164410Ssyrinx bif->max_addrs = b_param.ifbrp_csize; 207164410Ssyrinx 208164410Ssyrinx return (0); 209164410Ssyrinx} 210164410Ssyrinx 211164410Ssyrinx/* 212164410Ssyrinx * Fetch the current bridge STP operational parameters. 213164410Ssyrinx * Returns: -1 - on error; 214164410Ssyrinx * 0 - old TC time and Root Port values are same; 215164410Ssyrinx * 1 - topologyChange notification should be sent; 216164410Ssyrinx * 2 - newRoot notification should be sent. 217164410Ssyrinx */ 218164410Ssyrinxint 219164410Ssyrinxbridge_get_op_param(struct bridge_if *bif) 220164410Ssyrinx{ 221164410Ssyrinx int new_root_send; 222164410Ssyrinx struct ifdrv ifd; 223164410Ssyrinx struct ifbropreq b_req; 224164410Ssyrinx 225164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 226164410Ssyrinx ifd.ifd_len = sizeof(b_req); 227164410Ssyrinx ifd.ifd_data = &b_req; 228164410Ssyrinx ifd.ifd_cmd = BRDGPARAM; 229164410Ssyrinx 230164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 231164410Ssyrinx syslog(LOG_ERR, "update bridge: ioctl(BRDGPARAM) failed: %s", 232164410Ssyrinx strerror(errno)); 233164410Ssyrinx return (-1); 234164410Ssyrinx } 235164410Ssyrinx 236164410Ssyrinx bif->max_age = 100 * b_req.ifbop_maxage; 237164410Ssyrinx bif->hello_time = 100 * b_req.ifbop_hellotime; 238164410Ssyrinx bif->fwd_delay = 100 * b_req.ifbop_fwddelay; 239164997Ssyrinx bif->stp_version = b_req.ifbop_protocol; 240164997Ssyrinx bif->tx_hold_count = b_req.ifbop_holdcount; 241164410Ssyrinx 242164410Ssyrinx if (b_req.ifbop_root_port == 0 && 243164410Ssyrinx bif->root_port != b_req.ifbop_root_port) 244164410Ssyrinx new_root_send = 2; 245164410Ssyrinx else 246164410Ssyrinx new_root_send = 0; 247164410Ssyrinx 248164410Ssyrinx bif->root_port = b_req.ifbop_root_port; 249164410Ssyrinx bif->root_cost = b_req.ifbop_root_path_cost; 250164410Ssyrinx snmp_uint64_to_bridgeid(b_req.ifbop_designated_root, 251164410Ssyrinx bif->design_root); 252164410Ssyrinx 253164410Ssyrinx if (bif->last_tc_time.tv_sec != b_req.ifbop_last_tc_time.tv_sec) { 254164410Ssyrinx bif->top_changes++; 255164410Ssyrinx bif->last_tc_time.tv_sec = b_req.ifbop_last_tc_time.tv_sec; 256164410Ssyrinx bif->last_tc_time.tv_usec = b_req.ifbop_last_tc_time.tv_usec; 257164410Ssyrinx 258164410Ssyrinx /* 259164410Ssyrinx * "The trap is not sent if a (begemotBridge)NewRoot 260164410Ssyrinx * trap is sent for the same transition." 261164410Ssyrinx */ 262164410Ssyrinx if (new_root_send == 0) 263164410Ssyrinx return (1); 264164410Ssyrinx } 265164410Ssyrinx 266164410Ssyrinx return (new_root_send); 267164410Ssyrinx} 268164410Ssyrinx 269164410Ssyrinxint 270164410Ssyrinxbridge_getinfo_bif(struct bridge_if *bif) 271164410Ssyrinx{ 272164410Ssyrinx if (bridge_get_conf_param(bif) < 0) 273164410Ssyrinx return (-1); 274164410Ssyrinx 275164410Ssyrinx return (bridge_get_op_param(bif)); 276164410Ssyrinx} 277164410Ssyrinx 278164410Ssyrinxint 279164410Ssyrinxbridge_set_priority(struct bridge_if *bif, int32_t priority) 280164410Ssyrinx{ 281164410Ssyrinx struct ifdrv ifd; 282164410Ssyrinx struct ifbrparam b_param; 283164410Ssyrinx 284164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 285164410Ssyrinx ifd.ifd_len = sizeof(b_param); 286164410Ssyrinx ifd.ifd_data = &b_param; 287164410Ssyrinx b_param.ifbrp_prio = (uint32_t) priority; 288164410Ssyrinx ifd.ifd_cmd = BRDGSPRI; 289164410Ssyrinx 290164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 291164410Ssyrinx syslog(LOG_ERR, "set bridge param: ioctl(BRDGSPRI) " 292164410Ssyrinx "failed: %s", strerror(errno)); 293164410Ssyrinx return (-1); 294164410Ssyrinx } 295164410Ssyrinx 296164410Ssyrinx /* 297164410Ssyrinx * Re-fetching the data from the driver after that might be a good 298164410Ssyrinx * idea, since changing our bridge's priority should invoke 299164410Ssyrinx * recalculation of the active spanning tree topology in the network. 300164410Ssyrinx */ 301164410Ssyrinx bif->priority = priority; 302164410Ssyrinx return (0); 303164410Ssyrinx} 304164410Ssyrinx 305164410Ssyrinx/* 306164410Ssyrinx * Convert 1/100 of seconds to 1/256 of seconds. 307164410Ssyrinx * Timeout ::= TEXTUAL-CONVENTION. 308164410Ssyrinx * To convert a Timeout value into a value in units of 309164410Ssyrinx * 1/256 seconds, the following algorithm should be used: 310164410Ssyrinx * b = floor( (n * 256) / 100) 311164997Ssyrinx * The conversion to 1/256 of a second happens in the kernel - 312164997Ssyrinx * just make sure we correctly convert the seconds to Timout 313164997Ssyrinx * and vice versa. 314164410Ssyrinx */ 315164410Ssyrinxstatic uint32_t 316164997Ssyrinxsnmp_timeout2_sec(int32_t secs) 317164410Ssyrinx{ 318164997Ssyrinx return (secs / 100); 319164410Ssyrinx} 320164410Ssyrinx 321164410Ssyrinxint 322164410Ssyrinxbridge_set_maxage(struct bridge_if *bif, int32_t max_age) 323164410Ssyrinx{ 324164410Ssyrinx struct ifdrv ifd; 325164410Ssyrinx struct ifbrparam b_param; 326164410Ssyrinx 327164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 328164410Ssyrinx ifd.ifd_len = sizeof(b_param); 329164410Ssyrinx ifd.ifd_data = &b_param; 330164997Ssyrinx b_param.ifbrp_maxage = snmp_timeout2_sec(max_age); 331164410Ssyrinx ifd.ifd_cmd = BRDGSMA; 332164410Ssyrinx 333164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 334164410Ssyrinx syslog(LOG_ERR, "set bridge param: ioctl(BRDGSMA) " 335164410Ssyrinx "failed: %s", strerror(errno)); 336164410Ssyrinx return (-1); 337164410Ssyrinx } 338164410Ssyrinx 339164410Ssyrinx bif->bridge_max_age = max_age; 340164410Ssyrinx return (0); 341164410Ssyrinx} 342164410Ssyrinx 343164410Ssyrinxint 344164410Ssyrinxbridge_set_hello_time(struct bridge_if *bif, int32_t hello_time) 345164410Ssyrinx{ 346164410Ssyrinx struct ifdrv ifd; 347164410Ssyrinx struct ifbrparam b_param; 348164410Ssyrinx 349164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 350164410Ssyrinx ifd.ifd_len = sizeof(b_param); 351164410Ssyrinx ifd.ifd_data = &b_param; 352164997Ssyrinx b_param.ifbrp_hellotime = snmp_timeout2_sec(hello_time); 353164410Ssyrinx ifd.ifd_cmd = BRDGSHT; 354164410Ssyrinx 355164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 356164410Ssyrinx syslog(LOG_ERR, "set bridge param: ioctl(BRDGSHT) " 357164410Ssyrinx "failed: %s", strerror(errno)); 358164410Ssyrinx return (-1); 359164410Ssyrinx } 360164410Ssyrinx 361164410Ssyrinx bif->bridge_hello_time = b_param.ifbrp_hellotime; 362164410Ssyrinx return (0); 363164410Ssyrinx} 364164410Ssyrinx 365164410Ssyrinxint 366164410Ssyrinxbridge_set_forward_delay(struct bridge_if *bif, int32_t fwd_delay) 367164410Ssyrinx{ 368164410Ssyrinx struct ifdrv ifd; 369164410Ssyrinx struct ifbrparam b_param; 370164410Ssyrinx 371164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 372164410Ssyrinx ifd.ifd_len = sizeof(b_param); 373164410Ssyrinx ifd.ifd_data = &b_param; 374164997Ssyrinx b_param.ifbrp_fwddelay = snmp_timeout2_sec(fwd_delay); 375164410Ssyrinx ifd.ifd_cmd = BRDGSFD; 376164410Ssyrinx 377164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 378164410Ssyrinx syslog(LOG_ERR, "set bridge param: ioctl(BRDGSFD) " 379164410Ssyrinx "failed: %s", strerror(errno)); 380164410Ssyrinx return (-1); 381164410Ssyrinx } 382164410Ssyrinx 383164410Ssyrinx bif->bridge_fwd_delay = b_param.ifbrp_fwddelay; 384164410Ssyrinx return (0); 385164410Ssyrinx} 386164410Ssyrinx 387164410Ssyrinxint 388164410Ssyrinxbridge_set_aging_time(struct bridge_if *bif, int32_t age_time) 389164410Ssyrinx{ 390164410Ssyrinx struct ifdrv ifd; 391164410Ssyrinx struct ifbrparam b_param; 392164410Ssyrinx 393164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 394164410Ssyrinx ifd.ifd_len = sizeof(b_param); 395164410Ssyrinx ifd.ifd_data = &b_param; 396164410Ssyrinx b_param.ifbrp_ctime = (uint32_t) age_time; 397164410Ssyrinx ifd.ifd_cmd = BRDGSTO; 398164410Ssyrinx 399164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 400164410Ssyrinx syslog(LOG_ERR, "set bridge param: ioctl(BRDGSTO) " 401164410Ssyrinx "failed: %s", strerror(errno)); 402164410Ssyrinx return (-1); 403164410Ssyrinx } 404164410Ssyrinx 405164410Ssyrinx bif->age_time = age_time; 406164410Ssyrinx return (0); 407164410Ssyrinx} 408164410Ssyrinx 409164410Ssyrinxint 410164410Ssyrinxbridge_set_max_cache(struct bridge_if *bif, int32_t max_cache) 411164410Ssyrinx{ 412164410Ssyrinx struct ifdrv ifd; 413164410Ssyrinx struct ifbrparam b_param; 414164410Ssyrinx 415164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 416164410Ssyrinx ifd.ifd_len = sizeof(b_param); 417164410Ssyrinx ifd.ifd_data = &b_param; 418164410Ssyrinx b_param.ifbrp_csize = max_cache; 419164410Ssyrinx ifd.ifd_cmd = BRDGSCACHE; 420164410Ssyrinx 421164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 422164410Ssyrinx syslog(LOG_ERR, "set bridge param: ioctl(BRDGSCACHE) " 423164410Ssyrinx "failed: %s", strerror(errno)); 424164410Ssyrinx return (-1); 425164410Ssyrinx } 426164410Ssyrinx 427164410Ssyrinx bif->max_addrs = b_param.ifbrp_csize; 428164410Ssyrinx return (0); 429164410Ssyrinx} 430164410Ssyrinx 431164997Ssyrinxint 432171791Ssyrinxbridge_set_tx_hold_count(struct bridge_if *bif, int32_t tx_hc) 433164997Ssyrinx{ 434164997Ssyrinx struct ifdrv ifd; 435164997Ssyrinx struct ifbrparam b_param; 436164997Ssyrinx 437164997Ssyrinx if (tx_hc < SNMP_BRIDGE_MIN_TXHC || tx_hc > SNMP_BRIDGE_MAX_TXHC) 438164997Ssyrinx return (-1); 439164997Ssyrinx 440164997Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 441164997Ssyrinx ifd.ifd_len = sizeof(b_param); 442164997Ssyrinx ifd.ifd_data = &b_param; 443164997Ssyrinx b_param.ifbrp_txhc = tx_hc; 444164997Ssyrinx ifd.ifd_cmd = BRDGSTXHC; 445164997Ssyrinx 446164997Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 447164997Ssyrinx syslog(LOG_ERR, "set bridge param: ioctl(BRDGSTXHC) " 448164997Ssyrinx "failed: %s", strerror(errno)); 449164997Ssyrinx return (-1); 450164997Ssyrinx } 451164997Ssyrinx 452164997Ssyrinx bif->tx_hold_count = b_param.ifbrp_txhc; 453164997Ssyrinx return (0); 454164997Ssyrinx} 455164997Ssyrinx 456164997Ssyrinxint 457171791Ssyrinxbridge_set_stp_version(struct bridge_if *bif, int32_t stp_proto) 458164997Ssyrinx{ 459164997Ssyrinx struct ifdrv ifd; 460164997Ssyrinx struct ifbrparam b_param; 461164997Ssyrinx 462164997Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 463164997Ssyrinx ifd.ifd_len = sizeof(b_param); 464164997Ssyrinx ifd.ifd_data = &b_param; 465164997Ssyrinx b_param.ifbrp_proto = stp_proto; 466164997Ssyrinx ifd.ifd_cmd = BRDGSPROTO; 467164997Ssyrinx 468164997Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 469164997Ssyrinx syslog(LOG_ERR, "set bridge param: ioctl(BRDGSPROTO) " 470164997Ssyrinx "failed: %s", strerror(errno)); 471164997Ssyrinx return (-1); 472164997Ssyrinx } 473164997Ssyrinx 474164997Ssyrinx bif->stp_version = b_param.ifbrp_proto; 475164997Ssyrinx return (0); 476164997Ssyrinx} 477164997Ssyrinx 478164410Ssyrinx/* 479164410Ssyrinx * Set the bridge interface status to up/down. 480164410Ssyrinx */ 481164410Ssyrinxint 482164410Ssyrinxbridge_set_if_up(const char* b_name, int8_t up) 483164410Ssyrinx{ 484164410Ssyrinx int flags; 485164410Ssyrinx struct ifreq ifr; 486164410Ssyrinx 487164410Ssyrinx bzero(&ifr, sizeof(ifr)); 488164410Ssyrinx strcpy(ifr.ifr_name, b_name); 489164410Ssyrinx if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { 490164410Ssyrinx syslog(LOG_ERR, "set bridge up: ioctl(SIOCGIFFLAGS) " 491164410Ssyrinx "failed: %s", strerror(errno)); 492164410Ssyrinx return (-1); 493164410Ssyrinx } 494164410Ssyrinx 495164410Ssyrinx flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); 496164410Ssyrinx if (up == 1) 497164410Ssyrinx flags |= IFF_UP; 498164410Ssyrinx else 499164410Ssyrinx flags &= ~IFF_UP; 500164410Ssyrinx 501164410Ssyrinx ifr.ifr_flags = flags & 0xffff; 502164410Ssyrinx ifr.ifr_flagshigh = flags >> 16; 503164410Ssyrinx if (ioctl(sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { 504164410Ssyrinx syslog(LOG_ERR, "set bridge up: ioctl(SIOCSIFFLAGS) " 505164410Ssyrinx "failed: %s", strerror(errno)); 506164410Ssyrinx return (-1); 507164410Ssyrinx } 508164410Ssyrinx 509164410Ssyrinx return (0); 510164410Ssyrinx} 511164410Ssyrinx 512164410Ssyrinxint 513164410Ssyrinxbridge_create(const char *b_name) 514164410Ssyrinx{ 515164410Ssyrinx char *new_name; 516164410Ssyrinx struct ifreq ifr; 517164410Ssyrinx 518164410Ssyrinx bzero(&ifr, sizeof(ifr)); 519164410Ssyrinx strcpy(ifr.ifr_name, b_name); 520164410Ssyrinx 521164410Ssyrinx if (ioctl(sock, SIOCIFCREATE, &ifr) < 0) { 522164410Ssyrinx syslog(LOG_ERR, "create bridge: ioctl(SIOCIFCREATE) " 523164410Ssyrinx "failed: %s", strerror(errno)); 524164410Ssyrinx return (-1); 525164410Ssyrinx } 526164410Ssyrinx 527164410Ssyrinx if (strcmp(b_name, ifr.ifr_name) == 0) 528164410Ssyrinx return (0); 529164410Ssyrinx 530164410Ssyrinx if ((new_name = strdup(b_name)) == NULL) { 531164410Ssyrinx syslog(LOG_ERR, "create bridge: strdup() failed"); 532164410Ssyrinx return (-1); 533164410Ssyrinx } 534164410Ssyrinx 535164410Ssyrinx ifr.ifr_data = new_name; 536164410Ssyrinx if (ioctl(sock, SIOCSIFNAME, (caddr_t) &ifr) < 0) { 537164410Ssyrinx syslog(LOG_ERR, "create bridge: ioctl(SIOCSIFNAME) " 538164410Ssyrinx "failed: %s", strerror(errno)); 539164410Ssyrinx free(new_name); 540164410Ssyrinx return (-1); 541164410Ssyrinx } 542164410Ssyrinx 543164410Ssyrinx return (0); 544164410Ssyrinx} 545164410Ssyrinx 546164410Ssyrinxint 547164410Ssyrinxbridge_destroy(const char *b_name) 548164410Ssyrinx{ 549164410Ssyrinx struct ifreq ifr; 550164410Ssyrinx 551164410Ssyrinx bzero(&ifr, sizeof(ifr)); 552164410Ssyrinx strcpy(ifr.ifr_name, b_name); 553164410Ssyrinx 554164410Ssyrinx if (ioctl(sock, SIOCIFDESTROY, &ifr) < 0) { 555164410Ssyrinx syslog(LOG_ERR, "destroy bridge: ioctl(SIOCIFDESTROY) " 556164410Ssyrinx "failed: %s", strerror(errno)); 557164410Ssyrinx return (-1); 558164410Ssyrinx } 559164410Ssyrinx 560164410Ssyrinx return (0); 561164410Ssyrinx} 562164410Ssyrinx 563164410Ssyrinx/* 564164410Ssyrinx * Fetch the bridge base MAC address. Return pointer to the 565165642Sbz * buffer containing the MAC address, NULL on failure. 566164410Ssyrinx */ 567164410Ssyrinxu_char * 568165642Sbzbridge_get_basemac(const char *bif_name, u_char *mac, size_t mlen) 569164410Ssyrinx{ 570164410Ssyrinx int len; 571164410Ssyrinx char if_name[IFNAMSIZ]; 572165642Sbz struct ifaddrs *ifap, *ifa; 573165642Sbz struct sockaddr_dl sdl; 574164410Ssyrinx 575165642Sbz if (getifaddrs(&ifap) != 0) { 576164410Ssyrinx syslog(LOG_ERR, "bridge get mac: getifaddrs() failed - %s", 577164410Ssyrinx strerror(errno)); 578164410Ssyrinx return (NULL); 579164410Ssyrinx } 580164410Ssyrinx 581165642Sbz for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 582165642Sbz if (ifa->ifa_addr->sa_family != AF_LINK) 583165642Sbz continue; 584164410Ssyrinx 585165642Sbz /* 586165642Sbz * Not just casting because of alignment constraints 587268351Smarcel * on sparc64. 588165642Sbz */ 589165642Sbz bcopy(ifa->ifa_addr, &sdl, sizeof(struct sockaddr_dl)); 590165642Sbz 591165642Sbz if (sdl.sdl_alen > mlen) 592165642Sbz continue; 593165642Sbz 594165642Sbz if ((len = sdl.sdl_nlen) >= IFNAMSIZ) 595164410Ssyrinx len = IFNAMSIZ - 1; 596164410Ssyrinx 597165642Sbz bcopy(sdl.sdl_data, if_name, len); 598164410Ssyrinx if_name[len] = '\0'; 599164410Ssyrinx 600165642Sbz if (strcmp(bif_name, if_name) == 0) { 601165642Sbz bcopy(sdl.sdl_data + sdl.sdl_nlen, mac, sdl.sdl_alen); 602164410Ssyrinx freeifaddrs(ifap); 603164410Ssyrinx return (mac); 604164410Ssyrinx } 605164410Ssyrinx } 606164410Ssyrinx 607164410Ssyrinx freeifaddrs(ifap); 608164410Ssyrinx return (NULL); 609164410Ssyrinx} 610164410Ssyrinx 611164410Ssyrinx/************************************************************************ 612164410Ssyrinx * Bridge ports. 613164410Ssyrinx */ 614164410Ssyrinx 615164410Ssyrinx/* 616164410Ssyrinx * Convert the kernel STP port state into 617164410Ssyrinx * the corresopnding enumerated type from SNMP Bridge MIB. 618164410Ssyrinx */ 619164410Ssyrinxstatic int 620164410Ssyrinxstate2snmp_st(uint8_t ifbr_state) 621164410Ssyrinx{ 622164410Ssyrinx switch (ifbr_state) { 623164410Ssyrinx case BSTP_IFSTATE_DISABLED: 624164410Ssyrinx return (StpPortState_disabled); 625164410Ssyrinx case BSTP_IFSTATE_LISTENING: 626164410Ssyrinx return (StpPortState_listening); 627164410Ssyrinx case BSTP_IFSTATE_LEARNING: 628164410Ssyrinx return (StpPortState_learning); 629164410Ssyrinx case BSTP_IFSTATE_FORWARDING: 630164410Ssyrinx return (StpPortState_forwarding); 631164410Ssyrinx case BSTP_IFSTATE_BLOCKING: 632164997Ssyrinx case BSTP_IFSTATE_DISCARDING: 633164410Ssyrinx return (StpPortState_blocking); 634164410Ssyrinx } 635164410Ssyrinx 636164410Ssyrinx return (StpPortState_broken); 637164410Ssyrinx} 638164410Ssyrinx 639164410Ssyrinx/* 640164410Ssyrinx * Fill in a bridge member information according to data polled from kernel. 641164410Ssyrinx */ 642164410Ssyrinxstatic void 643164410Ssyrinxbridge_port_getinfo_conf(struct ifbreq *k_info, struct bridge_port *bp) 644164410Ssyrinx{ 645164410Ssyrinx bp->state = state2snmp_st(k_info->ifbr_state); 646164410Ssyrinx bp->priority = k_info->ifbr_priority; 647164410Ssyrinx 648164410Ssyrinx /* 649164410Ssyrinx * RFC 4188: 650164410Ssyrinx * "New implementations should support dot1dStpPortPathCost32. 651164410Ssyrinx * If the port path costs exceeds the maximum value of this 652164410Ssyrinx * object then this object should report the maximum value, 653164410Ssyrinx * namely 65535. Applications should try to read the 654164410Ssyrinx * dot1dStpPortPathCost32 object if this object reports 655164410Ssyrinx * the maximum value." 656164410Ssyrinx */ 657164410Ssyrinx 658164997Ssyrinx if (k_info->ifbr_ifsflags & IFBIF_BSTP_ADMCOST) 659164997Ssyrinx bp->admin_path_cost = k_info->ifbr_path_cost; 660164997Ssyrinx else 661164997Ssyrinx bp->admin_path_cost = 0; 662166493Ssyrinx 663164410Ssyrinx bp->path_cost = k_info->ifbr_path_cost; 664164410Ssyrinx 665164410Ssyrinx if (k_info->ifbr_ifsflags & IFBIF_STP) 666164410Ssyrinx bp->enable = dot1dStpPortEnable_enabled; 667164410Ssyrinx else 668164410Ssyrinx bp->enable = dot1dStpPortEnable_disabled; 669164410Ssyrinx 670164410Ssyrinx /* Begemot Bridge MIB only. */ 671164410Ssyrinx if (k_info->ifbr_ifsflags & IFBIF_SPAN) 672164410Ssyrinx bp->span_enable = begemotBridgeBaseSpanEnabled_enabled; 673164410Ssyrinx else 674164410Ssyrinx bp->span_enable = begemotBridgeBaseSpanEnabled_disabled; 675164997Ssyrinx 676171791Ssyrinx if (k_info->ifbr_ifsflags & IFBIF_PRIVATE) 677171791Ssyrinx bp->priv_set = TruthValue_true; 678171791Ssyrinx else 679171791Ssyrinx bp->priv_set = TruthValue_false; 680171791Ssyrinx 681164997Ssyrinx if (k_info->ifbr_ifsflags & IFBIF_BSTP_ADMEDGE) 682164997Ssyrinx bp->admin_edge = TruthValue_true; 683164997Ssyrinx else 684164997Ssyrinx bp->admin_edge = TruthValue_false; 685164997Ssyrinx 686164997Ssyrinx if (k_info->ifbr_ifsflags & IFBIF_BSTP_EDGE) 687164997Ssyrinx bp->oper_edge = TruthValue_true; 688164997Ssyrinx else 689164997Ssyrinx bp->oper_edge = TruthValue_false; 690164997Ssyrinx 691165416Ssyrinx if (k_info->ifbr_ifsflags & IFBIF_BSTP_AUTOPTP) { 692165416Ssyrinx bp->admin_ptp = StpPortAdminPointToPointType_auto; 693165416Ssyrinx if (k_info->ifbr_ifsflags & IFBIF_BSTP_PTP) 694165416Ssyrinx bp->oper_ptp = TruthValue_true; 695164997Ssyrinx else 696165416Ssyrinx bp->oper_ptp = TruthValue_false; 697165416Ssyrinx } else if (k_info->ifbr_ifsflags & IFBIF_BSTP_PTP) { 698165416Ssyrinx bp->admin_ptp = StpPortAdminPointToPointType_forceTrue; 699165416Ssyrinx bp->oper_ptp = TruthValue_true; 700164997Ssyrinx } else { 701165416Ssyrinx bp->admin_ptp = StpPortAdminPointToPointType_forceFalse; 702165416Ssyrinx bp->oper_ptp = TruthValue_false; 703164997Ssyrinx } 704164410Ssyrinx} 705164410Ssyrinx 706164410Ssyrinx/* 707164410Ssyrinx * Fill in a bridge interface STP information according to 708164410Ssyrinx * data polled from kernel. 709164410Ssyrinx */ 710164410Ssyrinxstatic void 711164410Ssyrinxbridge_port_getinfo_opstp(struct ifbpstpreq *bp_stp, struct bridge_port *bp) 712164410Ssyrinx{ 713164410Ssyrinx bp->enable = dot1dStpPortEnable_enabled; 714164410Ssyrinx bp->fwd_trans = bp_stp->ifbp_fwd_trans; 715164410Ssyrinx bp->design_cost = bp_stp->ifbp_design_cost; 716164410Ssyrinx snmp_uint64_to_bridgeid(bp_stp->ifbp_design_root, bp->design_root); 717164410Ssyrinx snmp_uint64_to_bridgeid(bp_stp->ifbp_design_bridge, bp->design_bridge); 718164410Ssyrinx bcopy(&(bp_stp->ifbp_design_port), &(bp->design_port), 719164410Ssyrinx sizeof(uint16_t)); 720164410Ssyrinx} 721164410Ssyrinx 722164410Ssyrinx/* 723164410Ssyrinx * Clear a bridge interface STP information. 724164410Ssyrinx */ 725164410Ssyrinxstatic void 726164410Ssyrinxbridge_port_clearinfo_opstp(struct bridge_port *bp) 727164410Ssyrinx{ 728164410Ssyrinx if (bp->enable == dot1dStpPortEnable_enabled) { 729164410Ssyrinx bp->design_cost = 0; 730164410Ssyrinx bzero(&(bp->design_root), sizeof(bridge_id)); 731164410Ssyrinx bzero(&(bp->design_bridge), sizeof(bridge_id)); 732164410Ssyrinx bzero(&(bp->design_port), sizeof(port_id)); 733164410Ssyrinx bp->fwd_trans = 0; 734164410Ssyrinx } 735164410Ssyrinx 736164410Ssyrinx bp->enable = dot1dStpPortEnable_disabled; 737164410Ssyrinx} 738164410Ssyrinx 739164410Ssyrinx/* 740164410Ssyrinx * Set a bridge member priority. 741164410Ssyrinx */ 742164410Ssyrinxint 743164410Ssyrinxbridge_port_set_priority(const char *bif_name, struct bridge_port *bp, 744164410Ssyrinx int32_t priority) 745164410Ssyrinx{ 746164410Ssyrinx struct ifdrv ifd; 747164410Ssyrinx struct ifbreq b_req; 748164410Ssyrinx 749164410Ssyrinx strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 750164410Ssyrinx ifd.ifd_len = sizeof(b_req); 751164410Ssyrinx ifd.ifd_data = &b_req; 752164410Ssyrinx strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 753164410Ssyrinx 754164410Ssyrinx b_req.ifbr_priority = (uint8_t) priority; 755164410Ssyrinx ifd.ifd_cmd = BRDGSIFPRIO; 756164410Ssyrinx 757164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 758164410Ssyrinx syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFPRIO) " 759164410Ssyrinx "failed: %s", bp->p_name, strerror(errno)); 760164410Ssyrinx return (-1); 761164410Ssyrinx } 762164410Ssyrinx 763164410Ssyrinx bp->priority = priority; 764164410Ssyrinx return (0); 765164410Ssyrinx} 766164410Ssyrinx 767164410Ssyrinx/* 768164410Ssyrinx * Set a bridge member STP-enabled flag. 769164410Ssyrinx */ 770164410Ssyrinxint 771164410Ssyrinxbridge_port_set_stp_enable(const char *bif_name, struct bridge_port *bp, 772164410Ssyrinx uint32_t enable) 773164410Ssyrinx{ 774164410Ssyrinx struct ifdrv ifd; 775164410Ssyrinx struct ifbreq b_req; 776164410Ssyrinx 777164410Ssyrinx if (bp->enable == enable) 778164410Ssyrinx return (0); 779164410Ssyrinx 780164410Ssyrinx bzero(&b_req, sizeof(b_req)); 781164410Ssyrinx strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 782164410Ssyrinx ifd.ifd_len = sizeof(b_req); 783164410Ssyrinx ifd.ifd_data = &b_req; 784164410Ssyrinx strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 785164410Ssyrinx ifd.ifd_cmd = BRDGGIFFLGS; 786164410Ssyrinx 787164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 788164410Ssyrinx syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) " 789164410Ssyrinx "failed: %s", bp->p_name, strerror(errno)); 790164410Ssyrinx return (-1); 791164410Ssyrinx } 792164410Ssyrinx 793164410Ssyrinx if (enable == dot1dStpPortEnable_enabled) 794164410Ssyrinx b_req.ifbr_ifsflags |= IFBIF_STP; 795164410Ssyrinx else 796164410Ssyrinx b_req.ifbr_ifsflags &= ~IFBIF_STP; 797164410Ssyrinx 798164410Ssyrinx ifd.ifd_cmd = BRDGSIFFLGS; 799164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 800164410Ssyrinx syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) " 801164410Ssyrinx "failed: %s", bp->p_name, strerror(errno)); 802164410Ssyrinx return (-1); 803164410Ssyrinx } 804164410Ssyrinx 805164410Ssyrinx bp->enable = enable; 806164410Ssyrinx return (0); 807164410Ssyrinx} 808164410Ssyrinx 809164410Ssyrinx/* 810164410Ssyrinx * Set a bridge member STP path cost. 811164410Ssyrinx */ 812164410Ssyrinxint 813164410Ssyrinxbridge_port_set_path_cost(const char *bif_name, struct bridge_port *bp, 814164410Ssyrinx int32_t path_cost) 815164410Ssyrinx{ 816164410Ssyrinx struct ifdrv ifd; 817164410Ssyrinx struct ifbreq b_req; 818164410Ssyrinx 819164997Ssyrinx if (path_cost < SNMP_PORT_MIN_PATHCOST || 820164997Ssyrinx path_cost > SNMP_PORT_PATHCOST_OBSOLETE) 821164997Ssyrinx return (-2); 822164410Ssyrinx 823164410Ssyrinx strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 824164410Ssyrinx ifd.ifd_len = sizeof(b_req); 825164410Ssyrinx ifd.ifd_data = &b_req; 826164410Ssyrinx strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 827164410Ssyrinx 828164997Ssyrinx b_req.ifbr_path_cost = path_cost; 829164410Ssyrinx ifd.ifd_cmd = BRDGSIFCOST; 830164410Ssyrinx 831164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 832164410Ssyrinx syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFCOST) " 833164410Ssyrinx "failed: %s", bp->p_name, strerror(errno)); 834164410Ssyrinx return (-1); 835164410Ssyrinx } 836164410Ssyrinx 837164997Ssyrinx bp->admin_path_cost = path_cost; 838164997Ssyrinx 839164410Ssyrinx return (0); 840164410Ssyrinx} 841164410Ssyrinx 842164410Ssyrinx/* 843164997Ssyrinx * Set the PonitToPoint status of the link administratively. 844164997Ssyrinx */ 845164997Ssyrinxint 846171791Ssyrinxbridge_port_set_admin_ptp(const char *bif_name, struct bridge_port *bp, 847171791Ssyrinx uint32_t admin_ptp) 848164997Ssyrinx{ 849164997Ssyrinx struct ifdrv ifd; 850164997Ssyrinx struct ifbreq b_req; 851164997Ssyrinx 852165416Ssyrinx if (bp->admin_ptp == admin_ptp) 853164997Ssyrinx return (0); 854164997Ssyrinx 855164997Ssyrinx bzero(&b_req, sizeof(b_req)); 856164997Ssyrinx strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 857164997Ssyrinx ifd.ifd_len = sizeof(b_req); 858164997Ssyrinx ifd.ifd_data = &b_req; 859164997Ssyrinx strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 860164997Ssyrinx ifd.ifd_cmd = BRDGGIFFLGS; 861164997Ssyrinx 862164997Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 863164997Ssyrinx syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) " 864164997Ssyrinx "failed: %s", bp->p_name, strerror(errno)); 865164997Ssyrinx return (-1); 866164997Ssyrinx } 867164997Ssyrinx 868165416Ssyrinx switch (admin_ptp) { 869164997Ssyrinx case StpPortAdminPointToPointType_forceTrue: 870165416Ssyrinx b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOPTP; 871165416Ssyrinx b_req.ifbr_ifsflags |= IFBIF_BSTP_PTP; 872164997Ssyrinx break; 873164997Ssyrinx case StpPortAdminPointToPointType_forceFalse: 874165416Ssyrinx b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOPTP; 875165416Ssyrinx b_req.ifbr_ifsflags &= ~IFBIF_BSTP_PTP; 876164997Ssyrinx break; 877164997Ssyrinx case StpPortAdminPointToPointType_auto: 878165416Ssyrinx b_req.ifbr_ifsflags |= IFBIF_BSTP_AUTOPTP; 879164997Ssyrinx break; 880164997Ssyrinx } 881164997Ssyrinx 882164997Ssyrinx ifd.ifd_cmd = BRDGSIFFLGS; 883164997Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 884164997Ssyrinx syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) " 885164997Ssyrinx "failed: %s", bp->p_name, strerror(errno)); 886164997Ssyrinx return (-1); 887164997Ssyrinx } 888164997Ssyrinx 889165416Ssyrinx bp->admin_ptp = admin_ptp; 890164997Ssyrinx return (0); 891164997Ssyrinx} 892164997Ssyrinx 893164997Ssyrinx/* 894164997Ssyrinx * Set admin edge. 895164997Ssyrinx */ 896164997Ssyrinxint 897171791Ssyrinxbridge_port_set_admin_edge(const char *bif_name, struct bridge_port *bp, 898171791Ssyrinx uint32_t enable) 899164997Ssyrinx{ 900164997Ssyrinx struct ifdrv ifd; 901164997Ssyrinx struct ifbreq b_req; 902164997Ssyrinx 903164997Ssyrinx if (bp->admin_edge == enable) 904164997Ssyrinx return (0); 905164997Ssyrinx 906164997Ssyrinx bzero(&b_req, sizeof(b_req)); 907164997Ssyrinx strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 908164997Ssyrinx ifd.ifd_len = sizeof(b_req); 909164997Ssyrinx ifd.ifd_data = &b_req; 910164997Ssyrinx strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 911164997Ssyrinx ifd.ifd_cmd = BRDGGIFFLGS; 912164997Ssyrinx 913164997Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 914164997Ssyrinx syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) " 915164997Ssyrinx "failed: %s", bp->p_name, strerror(errno)); 916164997Ssyrinx return (-1); 917164997Ssyrinx } 918164997Ssyrinx 919164997Ssyrinx if (enable == TruthValue_true) { 920164997Ssyrinx b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOEDGE; 921164997Ssyrinx b_req.ifbr_ifsflags |= IFBIF_BSTP_EDGE; 922164997Ssyrinx } else 923164997Ssyrinx b_req.ifbr_ifsflags &= ~IFBIF_BSTP_EDGE; 924164997Ssyrinx 925164997Ssyrinx ifd.ifd_cmd = BRDGSIFFLGS; 926164997Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 927164997Ssyrinx syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) " 928164997Ssyrinx "failed: %s", bp->p_name, strerror(errno)); 929164997Ssyrinx return (-1); 930164997Ssyrinx } 931164997Ssyrinx 932164997Ssyrinx bp->admin_edge = enable; 933166493Ssyrinx 934164997Ssyrinx return (0); 935164997Ssyrinx} 936164997Ssyrinx 937164997Ssyrinx/* 938171791Ssyrinx * Set 'private' flag. 939171791Ssyrinx */ 940171791Ssyrinxint 941171791Ssyrinxbridge_port_set_private(const char *bif_name, struct bridge_port *bp, 942171791Ssyrinx uint32_t priv_set) 943171791Ssyrinx{ 944171791Ssyrinx struct ifdrv ifd; 945171791Ssyrinx struct ifbreq b_req; 946171791Ssyrinx 947171791Ssyrinx if (bp->priv_set == priv_set) 948171791Ssyrinx return (0); 949171791Ssyrinx 950171791Ssyrinx bzero(&b_req, sizeof(b_req)); 951171791Ssyrinx strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); 952171791Ssyrinx ifd.ifd_len = sizeof(b_req); 953171791Ssyrinx ifd.ifd_data = &b_req; 954171791Ssyrinx strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 955171791Ssyrinx ifd.ifd_cmd = BRDGGIFFLGS; 956171791Ssyrinx 957171791Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 958171791Ssyrinx syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) " 959171791Ssyrinx "failed: %s", bp->p_name, strerror(errno)); 960171791Ssyrinx return (-1); 961171791Ssyrinx } 962171791Ssyrinx 963171791Ssyrinx if (priv_set == TruthValue_true) 964171791Ssyrinx b_req.ifbr_ifsflags |= IFBIF_PRIVATE; 965171791Ssyrinx else if (priv_set == TruthValue_false) 966171791Ssyrinx b_req.ifbr_ifsflags &= ~IFBIF_PRIVATE; 967171791Ssyrinx else 968171791Ssyrinx return (SNMP_ERR_WRONG_VALUE); 969171791Ssyrinx 970171791Ssyrinx ifd.ifd_cmd = BRDGSIFFLGS; 971171791Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 972171791Ssyrinx syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) " 973171791Ssyrinx "failed: %s", bp->p_name, strerror(errno)); 974171791Ssyrinx return (-1); 975171791Ssyrinx } 976171791Ssyrinx 977171791Ssyrinx bp->priv_set = priv_set; 978171791Ssyrinx 979171791Ssyrinx return (0); 980171791Ssyrinx} 981171791Ssyrinx 982171791Ssyrinx 983171791Ssyrinx/* 984164410Ssyrinx * Add a bridge member port. 985164410Ssyrinx */ 986164410Ssyrinxint 987164410Ssyrinxbridge_port_addm(struct bridge_port *bp, const char *b_name) 988164410Ssyrinx{ 989164410Ssyrinx struct ifdrv ifd; 990164410Ssyrinx struct ifbreq b_req; 991164410Ssyrinx 992164410Ssyrinx bzero(&ifd, sizeof(ifd)); 993164410Ssyrinx bzero(&b_req, sizeof(b_req)); 994164410Ssyrinx 995164410Ssyrinx strlcpy(ifd.ifd_name, b_name, sizeof(ifd.ifd_name)); 996164410Ssyrinx ifd.ifd_len = sizeof(b_req); 997164410Ssyrinx ifd.ifd_data = &b_req; 998164410Ssyrinx strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 999164410Ssyrinx 1000164410Ssyrinx if (bp->span_enable == begemotBridgeBaseSpanEnabled_enabled) 1001164410Ssyrinx ifd.ifd_cmd = BRDGADDS; 1002164410Ssyrinx else 1003164410Ssyrinx ifd.ifd_cmd = BRDGADD; 1004164410Ssyrinx 1005164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 1006164410Ssyrinx syslog(LOG_ERR, "%s - add member : ioctl(%s) failed: %s", 1007164410Ssyrinx bp->p_name, 1008164410Ssyrinx (ifd.ifd_cmd == BRDGADDS ? "BRDGADDS" : "BRDGADD"), 1009164410Ssyrinx strerror(errno)); 1010164410Ssyrinx return (-1); 1011164410Ssyrinx } 1012164410Ssyrinx 1013164410Ssyrinx return (0); 1014164410Ssyrinx} 1015164410Ssyrinx 1016164410Ssyrinx/* 1017164410Ssyrinx * Delete a bridge member port. 1018164410Ssyrinx */ 1019164410Ssyrinxint 1020164410Ssyrinxbridge_port_delm(struct bridge_port *bp, const char *b_name) 1021164410Ssyrinx{ 1022164410Ssyrinx struct ifdrv ifd; 1023164410Ssyrinx struct ifbreq b_req; 1024164410Ssyrinx 1025164410Ssyrinx bzero(&ifd, sizeof(ifd)); 1026164410Ssyrinx bzero(&b_req, sizeof(b_req)); 1027164410Ssyrinx 1028164410Ssyrinx strlcpy(ifd.ifd_name, b_name, sizeof(ifd.ifd_name)); 1029164410Ssyrinx ifd.ifd_len = sizeof(b_req); 1030164410Ssyrinx ifd.ifd_data = &b_req; 1031164410Ssyrinx strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); 1032164410Ssyrinx 1033164410Ssyrinx if (bp->span_enable == begemotBridgeBaseSpanEnabled_enabled) 1034164410Ssyrinx ifd.ifd_cmd = BRDGDELS; 1035164410Ssyrinx else 1036164410Ssyrinx ifd.ifd_cmd = BRDGDEL; 1037164410Ssyrinx 1038164410Ssyrinx if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { 1039164410Ssyrinx syslog(LOG_ERR, "%s - add member : ioctl(%s) failed: %s", 1040164410Ssyrinx bp->p_name, 1041164410Ssyrinx (ifd.ifd_cmd == BRDGDELS ? "BRDGDELS" : "BRDGDEL"), 1042164410Ssyrinx strerror(errno)); 1043164410Ssyrinx return (-1); 1044164410Ssyrinx } 1045164410Ssyrinx 1046164410Ssyrinx return (0); 1047164410Ssyrinx} 1048164410Ssyrinx 1049164410Ssyrinx/* 1050164410Ssyrinx * Fetch the bridge member list from kernel. 1051164410Ssyrinx * Return -1 on error, or buffer len if successful. 1052164410Ssyrinx */ 1053164410Ssyrinxstatic int32_t 1054165642Sbzbridge_port_get_iflist(struct bridge_if *bif, struct ifbreq **buf) 1055164410Ssyrinx{ 1056165642Sbz int n = 128; 1057165642Sbz uint32_t len; 1058165642Sbz struct ifbreq *ninbuf; 1059164410Ssyrinx struct ifbifconf ifbc; 1060164410Ssyrinx struct ifdrv ifd; 1061164410Ssyrinx 1062164410Ssyrinx *buf = NULL; 1063164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 1064164410Ssyrinx ifd.ifd_cmd = BRDGGIFS; 1065164410Ssyrinx ifd.ifd_len = sizeof(ifbc); 1066164410Ssyrinx ifd.ifd_data = &ifbc; 1067164410Ssyrinx 1068164410Ssyrinx for ( ; ; ) { 1069165642Sbz len = n * sizeof(struct ifbreq); 1070165642Sbz if ((ninbuf = (struct ifbreq *)realloc(*buf, len)) == NULL) { 1071164410Ssyrinx syslog(LOG_ERR, "get bridge member list: " 1072164410Ssyrinx "realloc failed: %s", strerror(errno)); 1073164410Ssyrinx free(*buf); 1074164410Ssyrinx *buf = NULL; 1075164410Ssyrinx return (-1); 1076164410Ssyrinx } 1077164410Ssyrinx 1078164410Ssyrinx ifbc.ifbic_len = len; 1079165642Sbz ifbc.ifbic_req = *buf = ninbuf; 1080164410Ssyrinx 1081164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 1082164410Ssyrinx syslog(LOG_ERR, "get bridge member list: ioctl " 1083164410Ssyrinx "(BRDGGIFS) failed: %s", strerror(errno)); 1084164410Ssyrinx free(*buf); 1085164410Ssyrinx buf = NULL; 1086164410Ssyrinx return (-1); 1087164410Ssyrinx } 1088164410Ssyrinx 1089164410Ssyrinx if ((ifbc.ifbic_len + sizeof(struct ifbreq)) < len) 1090164410Ssyrinx break; 1091164410Ssyrinx 1092165642Sbz n += 64; 1093164410Ssyrinx } 1094164410Ssyrinx 1095164410Ssyrinx return (ifbc.ifbic_len); 1096164410Ssyrinx} 1097164410Ssyrinx 1098164410Ssyrinx/* 1099164410Ssyrinx * Fetch the bridge STP member list from kernel. 1100164410Ssyrinx * Return -1 on error, or buffer len if successful. 1101164410Ssyrinx */ 1102164410Ssyrinxstatic int32_t 1103165642Sbzbridge_port_get_ifstplist(struct bridge_if *bif, struct ifbpstpreq **buf) 1104164410Ssyrinx{ 1105165642Sbz int n = 128; 1106165642Sbz uint32_t len; 1107165642Sbz struct ifbpstpreq *ninbuf; 1108164410Ssyrinx struct ifbpstpconf ifbstp; 1109164410Ssyrinx struct ifdrv ifd; 1110164410Ssyrinx 1111164997Ssyrinx *buf = NULL; 1112164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 1113164410Ssyrinx ifd.ifd_cmd = BRDGGIFSSTP; 1114164410Ssyrinx ifd.ifd_len = sizeof(ifbstp); 1115164410Ssyrinx ifd.ifd_data = &ifbstp; 1116164410Ssyrinx 1117164410Ssyrinx for ( ; ; ) { 1118165642Sbz len = n * sizeof(struct ifbpstpreq); 1119165642Sbz if ((ninbuf = (struct ifbpstpreq *) 1120165642Sbz realloc(*buf, len)) == NULL) { 1121164410Ssyrinx syslog(LOG_ERR, "get bridge STP ports list: " 1122164410Ssyrinx "realloc failed: %s", strerror(errno)); 1123164410Ssyrinx free(*buf); 1124164410Ssyrinx *buf = NULL; 1125164410Ssyrinx return (-1); 1126164410Ssyrinx } 1127164410Ssyrinx 1128164410Ssyrinx ifbstp.ifbpstp_len = len; 1129165642Sbz ifbstp.ifbpstp_req = *buf = ninbuf; 1130164410Ssyrinx 1131164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 1132164410Ssyrinx syslog(LOG_ERR, "get bridge STP ports list: ioctl " 1133164410Ssyrinx "(BRDGGIFSSTP) failed: %s", strerror(errno)); 1134164410Ssyrinx free(*buf); 1135164410Ssyrinx buf = NULL; 1136164410Ssyrinx return (-1); 1137164410Ssyrinx } 1138164410Ssyrinx 1139164410Ssyrinx if ((ifbstp.ifbpstp_len + sizeof(struct ifbpstpreq)) < len) 1140164410Ssyrinx break; 1141164410Ssyrinx 1142165642Sbz n += 64; 1143164410Ssyrinx } 1144164410Ssyrinx 1145164410Ssyrinx return (ifbstp.ifbpstp_len); 1146164410Ssyrinx} 1147164410Ssyrinx 1148164410Ssyrinx/* 1149164410Ssyrinx * Locate a bridge if STP params structure in a buffer. 1150164410Ssyrinx */ 1151164410Ssyrinxstatic struct ifbpstpreq * 1152165642Sbzbridge_port_find_ifstplist(uint8_t port_no, struct ifbpstpreq *buf, 1153165642Sbz uint32_t buf_len) 1154164410Ssyrinx{ 1155164410Ssyrinx uint32_t i; 1156164410Ssyrinx struct ifbpstpreq *bstp; 1157164410Ssyrinx 1158165642Sbz for (i = 0; i < buf_len / sizeof(struct ifbpstpreq); i++) { 1159165642Sbz bstp = buf + i; 1160164410Ssyrinx if (bstp->ifbp_portno == port_no) 1161164410Ssyrinx return (bstp); 1162164410Ssyrinx } 1163164410Ssyrinx 1164164410Ssyrinx return (NULL); 1165164410Ssyrinx} 1166164410Ssyrinx 1167164410Ssyrinx/* 1168164410Ssyrinx * Read the initial info for all members of a bridge interface. 1169164410Ssyrinx * Returns the number of ports, 0 - if none, otherwise 1170228990Suqs * -1 if some other error occurred. 1171164410Ssyrinx */ 1172164410Ssyrinxint 1173164410Ssyrinxbridge_getinfo_bif_ports(struct bridge_if *bif) 1174164410Ssyrinx{ 1175164410Ssyrinx uint32_t i; 1176164410Ssyrinx int32_t buf_len; 1177165642Sbz struct ifbreq *b_req_buf, *b_req; 1178165642Sbz struct ifbpstpreq *bs_req_buf, *bs_req; 1179164410Ssyrinx struct bridge_port *bp; 1180164410Ssyrinx struct mibif *m_if; 1181164410Ssyrinx 1182165642Sbz if ((buf_len = bridge_port_get_iflist(bif, &b_req_buf)) < 0) 1183164410Ssyrinx return (-1); 1184164410Ssyrinx 1185164410Ssyrinx for (i = 0; i < buf_len / sizeof(struct ifbreq); i++) { 1186165642Sbz b_req = b_req_buf + i; 1187164410Ssyrinx 1188164410Ssyrinx if ((m_if = mib_find_if_sys(b_req->ifbr_portno)) != NULL) { 1189164410Ssyrinx /* Hopefully we will not fail here. */ 1190164410Ssyrinx if ((bp = bridge_new_port(m_if, bif)) != NULL) { 1191164410Ssyrinx bp->status = RowStatus_active; 1192164410Ssyrinx bridge_port_getinfo_conf(b_req, bp); 1193164410Ssyrinx bridge_port_getinfo_mibif(m_if, bp); 1194164410Ssyrinx } 1195164410Ssyrinx } else { 1196164410Ssyrinx syslog(LOG_ERR, "bridge member %s not present " 1197164410Ssyrinx "in mibII ifTable", b_req->ifbr_ifsname); 1198164410Ssyrinx } 1199164410Ssyrinx } 1200165642Sbz free(b_req_buf); 1201164410Ssyrinx 1202165642Sbz if ((buf_len = bridge_port_get_ifstplist(bif, &bs_req_buf)) < 0) 1203164410Ssyrinx return (-1); 1204164410Ssyrinx 1205164410Ssyrinx for (bp = bridge_port_bif_first(bif); bp != NULL; 1206164410Ssyrinx bp = bridge_port_bif_next(bp)) { 1207164410Ssyrinx if ((bs_req = bridge_port_find_ifstplist(bp->port_no, 1208165642Sbz bs_req_buf, buf_len)) == NULL) 1209164410Ssyrinx bridge_port_clearinfo_opstp(bp); 1210164410Ssyrinx else 1211164410Ssyrinx bridge_port_getinfo_opstp(bs_req, bp); 1212164410Ssyrinx } 1213165642Sbz free(bs_req_buf); 1214164410Ssyrinx 1215164410Ssyrinx return (i); 1216164410Ssyrinx} 1217164410Ssyrinx 1218164410Ssyrinx/* 1219164410Ssyrinx * Update the information for the bridge interface members. 1220164410Ssyrinx */ 1221164410Ssyrinxint 1222164410Ssyrinxbridge_update_memif(struct bridge_if *bif) 1223164410Ssyrinx{ 1224164410Ssyrinx int added, updated; 1225164410Ssyrinx uint32_t i; 1226164410Ssyrinx int32_t buf_len; 1227165642Sbz struct ifbreq *b_req_buf, *b_req; 1228165642Sbz struct ifbpstpreq *bs_req_buf, *bs_req; 1229164410Ssyrinx struct bridge_port *bp, *bp_next; 1230164410Ssyrinx struct mibif *m_if; 1231164410Ssyrinx 1232165642Sbz if ((buf_len = bridge_port_get_iflist(bif, &b_req_buf)) < 0) 1233164410Ssyrinx return (-1); 1234164410Ssyrinx 1235164410Ssyrinx added = updated = 0; 1236164410Ssyrinx 1237164410Ssyrinx#define BP_FOUND 0x01 1238164410Ssyrinx for (i = 0; i < buf_len / sizeof(struct ifbreq); i++) { 1239165642Sbz b_req = b_req_buf + i; 1240164410Ssyrinx 1241164410Ssyrinx if ((m_if = mib_find_if_sys(b_req->ifbr_portno)) == NULL) { 1242164410Ssyrinx syslog(LOG_ERR, "bridge member %s not present " 1243164410Ssyrinx "in mibII ifTable", b_req->ifbr_ifsname); 1244164410Ssyrinx continue; 1245164410Ssyrinx } 1246164410Ssyrinx 1247164410Ssyrinx if ((bp = bridge_port_find(m_if->index, bif)) == NULL && 1248164410Ssyrinx (bp = bridge_new_port(m_if, bif)) != NULL) { 1249164410Ssyrinx bp->status = RowStatus_active; 1250164410Ssyrinx added++; 1251164410Ssyrinx } 1252164410Ssyrinx 1253164410Ssyrinx if (bp != NULL) { 1254164410Ssyrinx updated++; 1255164410Ssyrinx bridge_port_getinfo_conf(b_req, bp); 1256164410Ssyrinx bridge_port_getinfo_mibif(m_if, bp); 1257164410Ssyrinx bp->flags |= BP_FOUND; 1258164410Ssyrinx } 1259164410Ssyrinx } 1260165642Sbz free(b_req_buf); 1261164410Ssyrinx 1262164410Ssyrinx /* Clean up list. */ 1263164410Ssyrinx for (bp = bridge_port_bif_first(bif); bp != NULL; bp = bp_next) { 1264164410Ssyrinx bp_next = bridge_port_bif_next(bp); 1265164410Ssyrinx 1266164410Ssyrinx if ((bp->flags & BP_FOUND) == 0 && 1267164410Ssyrinx bp->status == RowStatus_active) 1268164410Ssyrinx bridge_port_remove(bp, bif); 1269164410Ssyrinx else 1270164410Ssyrinx bp->flags |= ~BP_FOUND; 1271164410Ssyrinx } 1272164410Ssyrinx#undef BP_FOUND 1273164410Ssyrinx 1274165642Sbz if ((buf_len = bridge_port_get_ifstplist(bif, &bs_req_buf)) < 0) 1275164410Ssyrinx return (-1); 1276164410Ssyrinx 1277164410Ssyrinx for (bp = bridge_port_bif_first(bif); bp != NULL; 1278164410Ssyrinx bp = bridge_port_bif_next(bp)) { 1279164410Ssyrinx if ((bs_req = bridge_port_find_ifstplist(bp->port_no, 1280165642Sbz bs_req_buf, buf_len)) == NULL) 1281164410Ssyrinx bridge_port_clearinfo_opstp(bp); 1282164410Ssyrinx else 1283164410Ssyrinx bridge_port_getinfo_opstp(bs_req, bp); 1284164410Ssyrinx } 1285165642Sbz free(bs_req_buf); 1286164410Ssyrinx bif->ports_age = time(NULL); 1287164410Ssyrinx 1288164410Ssyrinx return (updated); 1289164410Ssyrinx} 1290164410Ssyrinx 1291164410Ssyrinx/************************************************************************ 1292164410Ssyrinx * Bridge addresses. 1293164410Ssyrinx */ 1294164410Ssyrinx 1295164410Ssyrinx/* 1296164410Ssyrinx * Update the bridge address info according to the polled data. 1297164410Ssyrinx */ 1298164410Ssyrinxstatic void 1299164410Ssyrinxbridge_addrs_info_ifaddrlist(struct ifbareq *ifba, struct tp_entry *tpe) 1300164410Ssyrinx{ 1301164410Ssyrinx tpe->port_no = if_nametoindex(ifba->ifba_ifsname); 1302164410Ssyrinx 1303164410Ssyrinx if ((ifba->ifba_flags & IFBAF_TYPEMASK) == IFBAF_STATIC) 1304164410Ssyrinx tpe->status = TpFdbStatus_mgmt; 1305164410Ssyrinx else 1306164410Ssyrinx tpe->status = TpFdbStatus_learned; 1307164410Ssyrinx} 1308164410Ssyrinx 1309164410Ssyrinx/* 1310164410Ssyrinx * Read the bridge addresses from kernel. 1311164410Ssyrinx * Return -1 on error, or buffer len if successful. 1312164410Ssyrinx */ 1313164410Ssyrinxstatic int32_t 1314165642Sbzbridge_addrs_getinfo_ifalist(struct bridge_if *bif, struct ifbareq **buf) 1315164410Ssyrinx{ 1316165642Sbz int n = 128; 1317165642Sbz uint32_t len; 1318165642Sbz struct ifbareq *ninbuf; 1319164410Ssyrinx struct ifbaconf bac; 1320164410Ssyrinx struct ifdrv ifd; 1321164410Ssyrinx 1322164410Ssyrinx *buf = NULL; 1323164410Ssyrinx strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); 1324164410Ssyrinx ifd.ifd_cmd = BRDGRTS; 1325164410Ssyrinx ifd.ifd_len = sizeof(bac); 1326164410Ssyrinx ifd.ifd_data = &bac; 1327164410Ssyrinx 1328164410Ssyrinx for ( ; ; ) { 1329165642Sbz len = n * sizeof(struct ifbareq); 1330165642Sbz if ((ninbuf = (struct ifbareq *)realloc(*buf, len)) == NULL) { 1331164410Ssyrinx syslog(LOG_ERR, "get bridge address list: " 1332164410Ssyrinx " realloc failed: %s", strerror(errno)); 1333164410Ssyrinx free(*buf); 1334164410Ssyrinx *buf = NULL; 1335164410Ssyrinx return (-1); 1336164410Ssyrinx } 1337164410Ssyrinx 1338164410Ssyrinx bac.ifbac_len = len; 1339165642Sbz bac.ifbac_req = *buf = ninbuf; 1340164410Ssyrinx 1341164410Ssyrinx if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { 1342164410Ssyrinx syslog(LOG_ERR, "get bridge address list: " 1343164410Ssyrinx "ioctl(BRDGRTS) failed: %s", strerror(errno)); 1344164410Ssyrinx free(*buf); 1345164410Ssyrinx buf = NULL; 1346164410Ssyrinx return (-1); 1347164410Ssyrinx } 1348164410Ssyrinx 1349164410Ssyrinx if ((bac.ifbac_len + sizeof(struct ifbareq)) < len) 1350164410Ssyrinx break; 1351164410Ssyrinx 1352165642Sbz n += 64; 1353164410Ssyrinx } 1354164410Ssyrinx 1355164410Ssyrinx return (bac.ifbac_len); 1356164410Ssyrinx} 1357164410Ssyrinx 1358164410Ssyrinx/* 1359164410Ssyrinx * Read the initial info for all addresses on a bridge interface. 1360164410Ssyrinx * Returns the number of addresses, 0 - if none, otherwise 1361228990Suqs * -1 if some other error occurred. 1362164410Ssyrinx */ 1363164410Ssyrinxint 1364164410Ssyrinxbridge_getinfo_bif_addrs(struct bridge_if *bif) 1365164410Ssyrinx{ 1366164410Ssyrinx uint32_t i; 1367164410Ssyrinx int32_t buf_len; 1368165642Sbz struct ifbareq *addr_req_buf, *addr_req; 1369164410Ssyrinx struct tp_entry *te; 1370164410Ssyrinx 1371165642Sbz if ((buf_len = bridge_addrs_getinfo_ifalist(bif, &addr_req_buf)) < 0) 1372164410Ssyrinx return (-1); 1373164410Ssyrinx 1374164410Ssyrinx for (i = 0; i < buf_len / sizeof(struct ifbareq); i++) { 1375165642Sbz addr_req = addr_req_buf + i; 1376164410Ssyrinx 1377164410Ssyrinx if ((te = bridge_new_addrs(addr_req->ifba_dst, bif)) != NULL) 1378164410Ssyrinx bridge_addrs_info_ifaddrlist(addr_req, te); 1379164410Ssyrinx } 1380164410Ssyrinx 1381165642Sbz free(addr_req_buf); 1382164410Ssyrinx return (i); 1383164410Ssyrinx} 1384164410Ssyrinx 1385164410Ssyrinx/* 1386164410Ssyrinx * Update the addresses for the bridge interface. 1387164410Ssyrinx */ 1388164410Ssyrinxint 1389164410Ssyrinxbridge_update_addrs(struct bridge_if *bif) 1390164410Ssyrinx{ 1391164410Ssyrinx int added, updated; 1392164410Ssyrinx uint32_t i; 1393164410Ssyrinx int32_t buf_len; 1394164410Ssyrinx struct tp_entry *te, *te_next; 1395165642Sbz struct ifbareq *addr_req_buf, *addr_req; 1396164410Ssyrinx 1397165642Sbz if ((buf_len = bridge_addrs_getinfo_ifalist(bif, &addr_req_buf)) < 0) 1398164410Ssyrinx return (-1); 1399164410Ssyrinx 1400164410Ssyrinx added = updated = 0; 1401164410Ssyrinx 1402164410Ssyrinx#define BA_FOUND 0x01 1403164410Ssyrinx for (i = 0; i < buf_len / sizeof(struct ifbareq); i++) { 1404165642Sbz addr_req = addr_req_buf + i; 1405164410Ssyrinx 1406165642Sbz if ((te = bridge_addrs_find(addr_req->ifba_dst, bif)) == NULL) { 1407164410Ssyrinx added++; 1408164410Ssyrinx 1409165642Sbz if ((te = bridge_new_addrs(addr_req->ifba_dst, bif)) 1410164410Ssyrinx == NULL) 1411164410Ssyrinx continue; 1412164410Ssyrinx } else 1413164410Ssyrinx updated++; 1414164410Ssyrinx 1415165642Sbz bridge_addrs_info_ifaddrlist(addr_req, te); 1416164410Ssyrinx te-> flags |= BA_FOUND; 1417164410Ssyrinx } 1418165642Sbz free(addr_req_buf); 1419164410Ssyrinx 1420164410Ssyrinx for (te = bridge_addrs_bif_first(bif); te != NULL; te = te_next) { 1421164410Ssyrinx te_next = bridge_addrs_bif_next(te); 1422164410Ssyrinx 1423164410Ssyrinx if ((te-> flags & BA_FOUND) == 0) 1424164410Ssyrinx bridge_addrs_remove(te, bif); 1425164410Ssyrinx else 1426164410Ssyrinx te-> flags &= ~BA_FOUND; 1427164410Ssyrinx } 1428164410Ssyrinx#undef BA_FOUND 1429164410Ssyrinx 1430164410Ssyrinx bif->addrs_age = time(NULL); 1431164410Ssyrinx return (updated + added); 1432164410Ssyrinx} 1433164410Ssyrinx 1434164410Ssyrinx/************************************************************************ 1435164410Ssyrinx * Bridge packet filtering. 1436164410Ssyrinx */ 1437164410Ssyrinxconst char bridge_sysctl[] = "net.link.bridge."; 1438164410Ssyrinx 1439164410Ssyrinxstatic struct { 1440164410Ssyrinx int32_t val; 1441164410Ssyrinx const char *name; 1442164410Ssyrinx} bridge_pf_sysctl[] = { 1443164410Ssyrinx { 1, "pfil_bridge" }, 1444164410Ssyrinx { 1, "pfil_member" }, 1445164410Ssyrinx { 1, "pfil_onlyip" }, 1446164410Ssyrinx { 0, "ipfw" }, 1447164410Ssyrinx}; 1448164410Ssyrinx 1449164410Ssyrinxint32_t 1450164410Ssyrinxbridge_get_pfval(uint8_t which) 1451164410Ssyrinx{ 1452164410Ssyrinx if (which > sizeof(bridge_pf_sysctl) / sizeof(bridge_pf_sysctl[0]) 1453164410Ssyrinx || which < 1) 1454164410Ssyrinx return (-1); 1455164410Ssyrinx 1456164410Ssyrinx return (bridge_pf_sysctl[which - 1].val); 1457164410Ssyrinx} 1458164410Ssyrinx 1459164410Ssyrinxint32_t 1460164410Ssyrinxbridge_do_pfctl(int32_t bridge_ctl, enum snmp_op op, int32_t *val) 1461164410Ssyrinx{ 1462164410Ssyrinx char mib_name[100]; 1463164410Ssyrinx int32_t i, s_i; 1464164410Ssyrinx size_t len, s_len; 1465164410Ssyrinx 1466164410Ssyrinx if (bridge_ctl >= LEAF_begemotBridgeLayer2PfStatus) 1467164410Ssyrinx return (-2); 1468164410Ssyrinx 1469164410Ssyrinx if (op == SNMP_OP_SET) { 1470164410Ssyrinx s_i = *val; 1471164410Ssyrinx s_len = sizeof(s_i); 1472164410Ssyrinx } else 1473164410Ssyrinx s_len = 0; 1474164410Ssyrinx 1475164410Ssyrinx len = sizeof(i); 1476164410Ssyrinx 1477164410Ssyrinx strcpy(mib_name, bridge_sysctl); 1478164410Ssyrinx 1479164410Ssyrinx if (sysctlbyname(strcat(mib_name, 1480164410Ssyrinx bridge_pf_sysctl[bridge_ctl].name), &i, &len, 1481164410Ssyrinx (op == SNMP_OP_SET ? &s_i : NULL), s_len) == -1) { 1482164410Ssyrinx syslog(LOG_ERR, "sysctl(%s%s) failed - %s", bridge_sysctl, 1483164410Ssyrinx bridge_pf_sysctl[bridge_ctl].name, strerror(errno)); 1484164410Ssyrinx return (-1); 1485164410Ssyrinx } 1486164410Ssyrinx 1487164410Ssyrinx bridge_pf_sysctl[bridge_ctl].val = i; 1488164410Ssyrinx *val = i; 1489164410Ssyrinx 1490164410Ssyrinx return (i); 1491164410Ssyrinx} 1492164410Ssyrinx 1493164410Ssyrinxvoid 1494164410Ssyrinxbridge_pf_dump(void) 1495164410Ssyrinx{ 1496164410Ssyrinx uint8_t i; 1497164410Ssyrinx 1498164410Ssyrinx for (i = 0; i < sizeof(bridge_pf_sysctl) / sizeof(bridge_pf_sysctl[0]); 1499164410Ssyrinx i++) { 1500164410Ssyrinx syslog(LOG_ERR, "%s%s = %d", bridge_sysctl, 1501164410Ssyrinx bridge_pf_sysctl[i].name, bridge_pf_sysctl[i].val); 1502164410Ssyrinx } 1503164410Ssyrinx} 1504