Index: src/usr.sbin/bsnmpd/modules/Makefile =================================================================== RCS file: /home/ncvs/src/usr.sbin/bsnmpd/modules/Makefile,v retrieving revision 1.12 diff -u -r1.12 Makefile --- src/usr.sbin/bsnmpd/modules/Makefile 17 Mar 2006 18:54:40 -0000 1.12 +++ src/usr.sbin/bsnmpd/modules/Makefile 17 Nov 2006 16:30:43 -0000 @@ -9,6 +9,7 @@ .endif SUBDIR= ${_snmp_atm} \ + snmp_bridge \ snmp_hostres \ snmp_mibII \ snmp_netgraph \ Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt 17 Nov 2006 16:30:43 -0000 @@ -0,0 +1,965 @@ +-- +-- Copyright (C) 2006 Shteryana Shopova +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +-- SUCH DAMAGE. +-- +-- $FreeBSD$ +-- + +BEGEMOT-BRIDGE-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + Counter32, Integer32, TimeTicks, mib-2 + FROM SNMPv2-SMI + TEXTUAL-CONVENTION, MacAddress, TruthValue, RowStatus + FROM SNMPv2-TC + BridgeId, Timeout + FROM BRIDGE-MIB + InterfaceIndex FROM IF-MIB + begemot + FROM BEGEMOT-MIB; + +begemotBridge MODULE-IDENTITY + LAST-UPDATED "200608100000Z" + ORGANIZATION "Sofia University St. Kliment Ohridski" + CONTACT-INFO + " Shteryana Shopova + + Postal: Faculty of Mathematics and Informatics + 5 James Bourchier Blvd. + 1164 Sofia + Bulgaria + + Fax: +359 2 687 180 + + E-Mail: syrinx@FreeBSD.org" + DESCRIPTION + "The Begemot MIB for managing bridge interfaces." + + ::= { begemot 205 } + +-- ---------------------------------------------------------- -- +BridgeIfName ::= TEXTUAL-CONVENTION + DISPLAY-HINT "16a" + STATUS current + DESCRIPTION + "Name of a bridge interface." + SYNTAX OCTET STRING (SIZE(1..16)) + +BridgeIfNameOrEmpty ::= TEXTUAL-CONVENTION + DISPLAY-HINT "16a" + STATUS current + DESCRIPTION + "Name of a bridge interface." + SYNTAX OCTET STRING (SIZE(0..16)) + +BridgePortId ::= TEXTUAL-CONVENTION + DISPLAY-HINT "1x.1x" + STATUS current + DESCRIPTION + "A port identifier that contains a bridge port's STP priority + in the first octet and the port number in the second octet." + SYNTAX OCTET STRING (SIZE(2)) + +-- ---------------------------------------------------------- -- +-- subtrees in the Begemot Bridge MIB +-- ---------------------------------------------------------- -- +begemotBridgeNotifications OBJECT IDENTIFIER ::= { begemotBridge 0 } + +begemotBridgeBase OBJECT IDENTIFIER ::= { begemotBridge 1 } + +begemotBridgeStp OBJECT IDENTIFIER ::= { begemotBridge 2 } + +begemotBridgeTp OBJECT IDENTIFIER ::= { begemotBridge 3 } + +begemotBridgePf OBJECT IDENTIFIER ::= { begemotBridge 4 } + +begemotBridgeConfigObjects OBJECT IDENTIFIER ::= { begemotBridge 5 } + +-- ---------------------------------------------------------- -- +-- the base Bridge interface table +-- ---------------------------------------------------------- -- + +begemotBridgeBaseTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotBridgeBaseEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains generic information for each + bridge interface on the managed device." + ::= { begemotBridgeBase 1 } + +begemotBridgeBaseEntry OBJECT-TYPE + SYNTAX BegemotBridgeBaseEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of information for the bridge interfaces on + the managed device." + INDEX { begemotBridgeBaseName } + ::= { begemotBridgeBaseTable 1 } + +BegemotBridgeBaseEntry ::= SEQUENCE { + begemotBridgeBaseName BridgeIfName, + begemotBridgeBaseAddress MacAddress, + begemotBridgeBaseNumPorts Integer32, + begemotBridgeBaseType INTEGER, + begemotBridgeBaseStatus RowStatus +} + +begemotBridgeBaseName OBJECT-TYPE + SYNTAX BridgeIfName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The name of the bridge interface for which this + entry contains management information." + ::= { begemotBridgeBaseEntry 1 } + +begemotBridgeBaseAddress OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The MAC address of the bridge interface." + ::= { begemotBridgeBaseEntry 2 } + +begemotBridgeBaseNumPorts OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of ports, members of this bridge." + ::= { begemotBridgeBaseEntry 3 } + +begemotBridgeBaseType OBJECT-TYPE + SYNTAX INTEGER { + unknown(1), + transparent-only(2), + sourceroute-only(3), + srt(4) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Indicates what type of bridging this bridge can + perform." + ::= { begemotBridgeBaseEntry 4 } + +begemotBridgeBaseStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Used to create/destroy bridge interfaces on the + managed device." + ::= { begemotBridgeBaseEntry 5 } + +-- ---------------------------------------------------------- -- +-- the base Bridge ports table +-- ---------------------------------------------------------- -- + +begemotBridgeBasePortTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotBridgeBasePortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing generic information about ports, + members of each bridge interface." + ::= { begemotBridgeBase 2 } + +begemotBridgeBasePortEntry OBJECT-TYPE + SYNTAX BegemotBridgeBasePortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of information about a specific port, member of + a bridge interface." + INDEX { begemotBridgeBaseName, begemotBridgeBasePortIfIndex } + ::= { begemotBridgeBasePortTable 1 } + +BegemotBridgeBasePortEntry ::= SEQUENCE { + begemotBridgeBasePort Integer32, + begemotBridgeBasePortIfIndex InterfaceIndex, + begemotBridgeBaseSpanEnabled INTEGER, + begemotBridgeBasePortDelayExceededDiscards Counter32, + begemotBridgeBasePortMtuExceededDiscards Counter32, + begemotBridgeBasePortStatus RowStatus +} + +begemotBridgeBasePort OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The system interface index of the interface corresponding + to this port." + ::= { begemotBridgeBasePortEntry 1 } + +begemotBridgeBasePortIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of the instance of the ifIndex object, + defined in IF-MIB, for the interface corresponding + to this port." + ::= { begemotBridgeBasePortEntry 2 } + +begemotBridgeBaseSpanEnabled OBJECT-TYPE + SYNTAX INTEGER { + enabled(1), + disabled(2) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value of this objects reflects whether the port + is a span port on the specified bridge interface." + ::= { begemotBridgeBasePortEntry 3 } + +begemotBridgeBasePortDelayExceededDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of frames discarded by this port due + to excessive transit delay through the bridge." + ::= { begemotBridgeBasePortEntry 4 } + +begemotBridgeBasePortMtuExceededDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of frames discarded by this port due + to an excessive size." + ::= { begemotBridgeBasePortEntry 5 } + +begemotBridgeBasePortStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Used to control addition of member ports to or + removal of member ports from a specified bridge." + ::= { begemotBridgeBasePortEntry 6 } + +-- ---------------------------------------------------------- -- +-- the Bridge interface STP table +-- ---------------------------------------------------------- -- + +begemotBridgeStpTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotBridgeStpEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains Spanning Tree Protocol information + for each bridge interface on the managed device." + ::= { begemotBridgeStp 1 } + +begemotBridgeStpEntry OBJECT-TYPE + SYNTAX BegemotBridgeStpEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of information about the Spanning Tree Protocol + operation on a bridge interface." + AUGMENTS { begemotBridgeBaseEntry } + ::= { begemotBridgeStpTable 1 } + +BegemotBridgeStpEntry ::= SEQUENCE { + begemotBridgeStpProtocolSpecification INTEGER, + begemotBridgeStpPriority Integer32, + begemotBridgeStpTimeSinceTopologyChange TimeTicks, + begemotBridgeStpTopChanges Counter32, + begemotBridgeStpDesignatedRoot BridgeId, + begemotBridgeStpRootCost Integer32, + begemotBridgeStpRootPort Integer32, + begemotBridgeStpMaxAge Timeout, + begemotBridgeStpHelloTime Timeout, + begemotBridgeStpHoldTime Integer32, + begemotBridgeStpForwardDelay Timeout, + begemotBridgeStpBridgeMaxAge Timeout, + begemotBridgeStpBridgeHelloTime Timeout, + begemotBridgeStpBridgeForwardDelay Timeout +} + +begemotBridgeStpProtocolSpecification OBJECT-TYPE + SYNTAX INTEGER { + unknown(1), + decLb100(2), + ieee8021d(3) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The Spanning Tree Protocol version being run on the + bridge interface. The value 'decLb100(2)' indicates the + DEC LANbridge 100 Spanning Tree protocol, 'ieee8021d(3)' + indicates the bridge is running IEEE 802.1D STP + implementation." + ::= { begemotBridgeStpEntry 1 } + +begemotBridgeStpPriority OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The priority value of the bridge interface forming the + first two octets of the bridge identifier. Acceptable + values are 0-61440, in steps of 4096." + ::= { begemotBridgeStpEntry 2 } + +begemotBridgeStpTimeSinceTopologyChange OBJECT-TYPE + SYNTAX TimeTicks + UNITS "centi-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The time (in hundreds of a second) since a topology change + was last detected by this bridge." + ::= { begemotBridgeStpEntry 3 } + +begemotBridgeStpTopChanges OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times a topology change was detected by the + bridge interface since the management entity was initialized + or reset." + ::= { begemotBridgeStpEntry 4 } + +begemotBridgeStpDesignatedRoot OBJECT-TYPE + SYNTAX BridgeId + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The bridge identifier of the root of the spanning tree as + calculated by the Spanning Tree Protocol." + ::= { begemotBridgeStpEntry 5 } + +begemotBridgeStpRootCost OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The cost of the path from this bridge to the root bridge." + ::= { begemotBridgeStpEntry 6 } + +begemotBridgeStpRootPort OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The port number of the port that offers the lowest + cost path from this bridge to the root bridge of + the spanning tree. If this bridge is the root bridge, + this object shall have a value of zero." + ::= { begemotBridgeStpEntry 7 } + +begemotBridgeStpMaxAge OBJECT-TYPE + SYNTAX Timeout + UNITS "centi-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum age of Spanning Tree Protocol information + received from the network on any port, before that + information is discarded. This is the actual value that + the bridge is currently using." + ::= { begemotBridgeStpEntry 8 } + +begemotBridgeStpHelloTime OBJECT-TYPE + SYNTAX Timeout + UNITS "centi-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The amount of time between transmission of + Configuration BPDUs by this bridge on any port, + when it is the root of the spanning tree or is + trying to become so. This is the actual value that + this bridge is currently using." + ::= { begemotBridgeStpEntry 9 } + +begemotBridgeStpHoldTime OBJECT-TYPE + SYNTAX Integer32 + UNITS "centi-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This time value determines the interval length + during which no more than two Configuration BPDUs + shall be transmitted by this node, in units of + hundredths of a second." + ::= { begemotBridgeStpEntry 10 } + +begemotBridgeStpForwardDelay OBJECT-TYPE + SYNTAX Timeout + UNITS "centi-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This value, measured in units of hundredths of a second + determines how long a port will stay consecutively in the + Listening and Learning states before transitioning to + Forwarding state. + This is the actual value currently used by the bridge + as opposed to begemotBridgeStpBridgeForwardDelay, which + is the value this and all bridges participating in the + spanning tree were to use, if this was the root bridge." + ::= { begemotBridgeStpEntry 11 } + +begemotBridgeStpBridgeMaxAge OBJECT-TYPE + SYNTAX Timeout (600..4000) + UNITS "centi-seconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value that all bridges participating in the + spanning tree would use for MaxAge if this bridge + was the root of the spanning tree." + ::= { begemotBridgeStpEntry 12 } + +begemotBridgeStpBridgeHelloTime OBJECT-TYPE + SYNTAX Timeout (100..1000) + UNITS "centi-seconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value that all bridges participating in the + spanning tree would use for HelloTime if this + bridge was the root of the spanning tree." + ::= { begemotBridgeStpEntry 13 } + +begemotBridgeStpBridgeForwardDelay OBJECT-TYPE + SYNTAX Timeout (400..3000) + UNITS "centi-seconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value that all bridges participating in the + spanning tree would use for ForwardDelay if this + bridge was the root of the spanning tree." + ::= { begemotBridgeStpEntry 14 } + +-- ---------------------------------------------------------- -- +-- the Bridge STP ports table +-- ---------------------------------------------------------- -- + +begemotBridgeStpPortTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotBridgeStpPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing Spanning Tree Protocol information + about the members of each bridge interface." + ::= { begemotBridgeStp 2 } + +begemotBridgeStpPortEntry OBJECT-TYPE + SYNTAX BegemotBridgeStpPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of Spanning Tree Protocol information about + a specific member of a bridge interface." + INDEX { begemotBridgeBaseName, begemotBridgeBasePortIfIndex } + ::= { begemotBridgeStpPortTable 1 } + +BegemotBridgeStpPortEntry ::= SEQUENCE { + begemotBridgeStpPort Integer32, + begemotBridgeStpPortPriority Integer32, + begemotBridgeStpPortState INTEGER, + begemotBridgeStpPortEnable INTEGER, + begemotBridgeStpPortPathCost Integer32, + begemotBridgeStpPortDesignatedRoot BridgeId, + begemotBridgeStpPortDesignatedCost Integer32, + begemotBridgeStpPortDesignatedBridge BridgeId, + begemotBridgeStpPortDesignatedPort BridgePortId, + begemotBridgeStpPortForwardTransitions Counter32 +} + +begemotBridgeStpPort OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The system interface index of the interface corresponding + to this port, for which the management entity has Spanning + Tree Protocol information." + ::= { begemotBridgeStpPortEntry 1 } + +begemotBridgeStpPortPriority OBJECT-TYPE + SYNTAX Integer32 (0..255) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The STP priority of this port that is contained in the first + octet of its Port Identifier. The second octet contains the + value of begemotBridgeStpPort." + ::= { begemotBridgeStpPortEntry 2 } + +begemotBridgeStpPortState OBJECT-TYPE + SYNTAX INTEGER { + disabled(1), + blocking(2), + listening(3), + learning(4), + forwarding(5), + broken(6) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The current state of the port as defined by the operation + of the Spanning Tree Protocol. If the Spanning Tree Protocol + is administratively disabled on the port, this object shall + have value disabled(1). A value of broken(6) does not correspond + to any legal state of a port, and if present should indicate + error in the operation of either the Spanning Tree Protocol + implementation running on the device or the management entity." + ::= { begemotBridgeStpPortEntry 3 } + +begemotBridgeStpPortEnable OBJECT-TYPE + SYNTAX INTEGER { + enabled(1), + disabled(2) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The administrative Spanning Tree Protocol state of the + port - value of enabled(1) indicates that the port is + participating in the Spanning Tree Protocol operation." + ::= { begemotBridgeStpPortEntry 4 } + +begemotBridgeStpPortPathCost OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The contribution of the path through this port, when the port + is the Root Port, to the total cost of the path to the root + bridge for this bridge." + ::= { begemotBridgeStpPortEntry 5 } + +begemotBridgeStpPortDesignatedRoot OBJECT-TYPE + SYNTAX BridgeId + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The unique Bridge Identifier of the bridge recorded as the + root in the Root Identifier parameter of Configuration BPDUs + transmitted by the Designated Bridge for the LAN to which + the port is attached." + ::= { begemotBridgeStpPortEntry 6 } + +begemotBridgeStpPortDesignatedCost OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "For a Designated port, the path cost (equal to the Root + Path Cost of the bridge) offered to the LAN to which the + port is attached otherwise the cost of the path to the Root + offered by the Designated Port on the LAN to which this + Port is attached." + ::= { begemotBridgeStpPortEntry 7 } + +begemotBridgeStpPortDesignatedBridge OBJECT-TYPE + SYNTAX BridgeId + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The unique Bridge Identifier of the bridge to which the + port belongs, in the case when the port is a designated + port, otherwise the bridge believed to be the Designated + Bridge for the LAN to which this port is attached." + ::= { begemotBridgeStpPortEntry 8 } + +begemotBridgeStpPortDesignatedPort OBJECT-TYPE + SYNTAX BridgePortId + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The Port Identifier of the Bridge port, on the Designated + Bridge, through which the Designated Bridge transmits the + Configuration Message information stored by this port." + ::= { begemotBridgeStpPortEntry 9 } + +begemotBridgeStpPortForwardTransitions OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times this port has transitioned + from the Learning state to the Forwarding state." + ::= { begemotBridgeStpPortEntry 10 } + +-- ---------------------------------------------------------- -- +-- the Bridge interface Transparent bridging table +-- ---------------------------------------------------------- -- + +begemotBridgeTpTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotBridgeTpEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains information regarding transparent + bridging for each bridge interface on the managed device." + ::= { begemotBridgeTp 1 } + +begemotBridgeTpEntry OBJECT-TYPE + SYNTAX BegemotBridgeTpEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of information regarding transparent bridging + on a bridge interface." + AUGMENTS { begemotBridgeBaseEntry } + ::= { begemotBridgeTpTable 1 } + +BegemotBridgeTpEntry ::= SEQUENCE { + begemotBridgeTpLearnedEntryDiscards Counter32, + begemotBridgeTpAgingTime Integer32, + begemotBridgeTpMaxAddresses Integer32 +} + +begemotBridgeTpLearnedEntryDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of Forwarding Database entries that would + have been learnt, but have been discarded due to Forwarding + Address Table having reached it's maximum entries limit." + ::= { begemotBridgeTpEntry 1 } + +begemotBridgeTpAgingTime OBJECT-TYPE + SYNTAX Integer32 (10..1000000) + UNITS "seconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The timeout period in seconds before aging out + dynamically learnt forwarding entries." + ::= { begemotBridgeTpEntry 2 } + +begemotBridgeTpMaxAddresses OBJECT-TYPE + SYNTAX Integer32 (1..10000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The maximum number of entires that this bridge can + learn in it's Forwarding Address Table and use for + making forwarding decisions." + ::= { begemotBridgeTpEntry 3 } + +-- ---------------------------------------------------------- -- +-- The Forwarding Database for Transparent Bridging interfaces +-- ---------------------------------------------------------- -- + +begemotBridgeTpFdbTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotBridgeTpFdbEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains information about unicast entries + for which the bridge interfaces have forwarding and/or + filtering information. This information is used by the + bridge interfaces to make forwarding decisions." + ::= { begemotBridgeTp 2 } + +begemotBridgeTpFdbEntry OBJECT-TYPE + SYNTAX BegemotBridgeTpFdbEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Information about a specific unicast MAC address + for which the bridge interface has some forwarding + and/or filtering information." + INDEX { begemotBridgeBaseName, begemotBridgeTpFdbAddress } + ::= { begemotBridgeTpFdbTable 1 } + +BegemotBridgeTpFdbEntry ::= SEQUENCE { + begemotBridgeTpFdbAddress MacAddress, + begemotBridgeTpFdbPort Integer32, + begemotBridgeTpFdbStatus INTEGER +} + +begemotBridgeTpFdbAddress OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A unicast MAC address for which the bridge has which the + bridge interface has some forwarding and/or filtering + information." + ::= { begemotBridgeTpFdbEntry 1 } + +begemotBridgeTpFdbPort OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The port number of the bridge port on which a frame having + a source address equal to the value of the corresponding + instance of begemotBridgeTpFdbAddress has been seen." + ::= { begemotBridgeTpFdbEntry 2 } + +begemotBridgeTpFdbStatus OBJECT-TYPE + SYNTAX INTEGER { + other(1), + invalid(2), + learned(3), + self(4), + mgmt(5) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The status of this entry. The meanings of the + values are: + other(1) - none of the following. + invalid(2) - this entry is no longer valid (e.g., + it was learned but has since aged out), but has + not yet been flushed from the table. + learned(3) - the value of the corresponding instance + of begemotBridgeTpFdbPort was learned, and is being + used. + self(4) - the value of the corresponding instance of + begemotBridgeTpFdbAddress represents one of the + bridge's addresses. The corresponding instance of + begemotBridgeTpFdbPort indicates which of the bridge's + ports has this address. + mgmt(5) - the value of the corresponding instance of + begemotBridgeTpFdbAddress has been added to the + bridge's Forwarding Database by some management + means." + ::= { begemotBridgeTpFdbEntry 3 } + +-- ---------------------------------------------------------- -- +-- Ports table for Transparent Bridging interfaces +-- ---------------------------------------------------------- -- + +begemotBridgeTpPortTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotBridgeTpPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains information about every bridge port, + member of a bridge interface, associated with the transparent + bridging function of the bridge." + ::= { begemotBridgeTp 3 } + +begemotBridgeTpPortEntry OBJECT-TYPE + SYNTAX BegemotBridgeTpPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of information about every bridge port, member of a + bridge interface, associated with the bridge's transparent + bridging function." + INDEX { begemotBridgeBaseName, begemotBridgeBasePortIfIndex } + ::= { begemotBridgeTpPortTable 1 } + +BegemotBridgeTpPortEntry ::= SEQUENCE { + begemotBridgeTpPort Integer32, + begemotBridgeTpPortMaxInfo Integer32, + begemotBridgeTpPortInFrames Counter32, + begemotBridgeTpPortOutFrames Counter32, + begemotBridgeTpPortInDiscards Counter32 +} + +begemotBridgeTpPort OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The system interface index of the port for which this entry + contains Transparent bridging management information." + ::= { begemotBridgeTpPortEntry 1 } + +begemotBridgeTpPortMaxInfo OBJECT-TYPE + SYNTAX Integer32 + UNITS "bytes" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum size of the INFO (non-MAC) field that this port + will receive or transmit." + ::= { begemotBridgeTpPortEntry 2 } + +begemotBridgeTpPortInFrames OBJECT-TYPE + SYNTAX Counter32 + UNITS "frames" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of frames that have been received by this + port from its segment. Note that a frame received on the + interface corresponding to this port is only counted by + this object if and only if it is for a protocol being + processed by the local bridging function, including + bridge management frames." + ::= { begemotBridgeTpPortEntry 3 } + +begemotBridgeTpPortOutFrames OBJECT-TYPE + SYNTAX Counter32 + UNITS "frames" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of frames that have been transmitted by this + port to its segment. Note that a frame transmitted on + the interface corresponding to this port is only counted + by this object if and only if it is for a protocol being + processed by the local bridging function, including + bridge management frames." + ::= { begemotBridgeTpPortEntry 4 } + +begemotBridgeTpPortInDiscards OBJECT-TYPE + SYNTAX Counter32 + UNITS "frames" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Count of received valid frames that were discarded + (i.e., filtered) by the Forwarding Process." + ::= { begemotBridgeTpPortEntry 5 } + +-- ---------------------------------------------------------- -- +-- the begemotBridgePf objects +-- ---------------------------------------------------------- -- + +begemotBridgePfilStatus OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Indicates whether packet filtering by some firewall + package is enabled on the bridge interface." + ::= { begemotBridgePf 1 } + +begemotBridgePfilMembers OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "A value of true(1) indicates that packet filtering is + enabled on both incoming and outgoing bridge member + interfaces." + ::= { begemotBridgePf 2 } + +begemotBridgePfilIpOnly OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "This value controls the handling of non-IP packets which + are not passed on for further processing to a firewall + package. A value of false(0) indicates that all non-IP + Ethernet frames are passed unconditionally." + ::= { begemotBridgePf 3 } + +begemotBridgeLayer2PfStatus OBJECT-TYPE + SYNTAX INTEGER { + enabled(1), + disabled(2) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "This value indicates whether layer2 filtering by a + firewall package is enabled for bridge interfaces." + ::= { begemotBridgePf 4 } + +-- ---------------------------------------------------------- -- +-- the begemotBridgeConfigObjects objects +-- ---------------------------------------------------------- -- + +begemotBridgeDefaultBridgeIf OBJECT-TYPE + + SYNTAX BridgeIfNameOrEmpty + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The name of the bridge interface that will be managed + via objects in IETF BRIDGE-MIB (RFC4188). If the + object's value is set to an empty string, bridge interfaces + will only be managed via objects in this MIB module." + DEFVAL { "bridge0" } + ::= { begemotBridgeConfigObjects 1 } + +begemotBridgeDataUpdate OBJECT-TYPE + + SYNTAX Timeout (1..300) + UNITS "seconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The maximum age in seconds of the cached data." + DEFVAL { 10 } + ::= { begemotBridgeConfigObjects 2 } + +begemotBridgeDataPoll OBJECT-TYPE + + SYNTAX Timeout (1..3600) + UNITS "seconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The polling rate of data when the module is idle." + DEFVAL { 300 } + ::= { begemotBridgeConfigObjects 3 } + +-- ---------------------------------------------------------- -- +-- Notifications for the Spanning Tree Protocol +-- ---------------------------------------------------------- -- + +begemotBridgeNewRoot NOTIFICATION-TYPE + OBJECTS { begemotBridgeBaseName } + STATUS current + DESCRIPTION + "The begemotBridgeNewRoot trap indicates that one of the + bridge interfaces on the sending agent's device has + become the new root of the spanning tree topology it is + participating in." + ::= { begemotBridgeNotifications 1 } + +begemotBridgeTopologyChange NOTIFICATION-TYPE + OBJECTS { begemotBridgeBaseName } + STATUS current + DESCRIPTION + "A begemotBridgeTopologyChange trap is send when a member + port on one of the bridge interfaces, monitored by the agent, + transitions from the Learning state to the Forwarding state, + or from the Forwarding state to the Blocking state. The trap + is not sent if a begemotBridgeNewRoot trap is sent for the + same transition." + ::= { begemotBridgeNotifications 2 } + +END Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/BRIDGE-MIB.txt =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/BRIDGE-MIB.txt diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/BRIDGE-MIB.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/BRIDGE-MIB.txt 17 Nov 2006 16:30:44 -0000 @@ -0,0 +1,1465 @@ +BRIDGE-MIB DEFINITIONS ::= BEGIN + +-- ---------------------------------------------------------- -- +-- MIB for IEEE 802.1D devices +-- ---------------------------------------------------------- -- +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + Counter32, Integer32, TimeTicks, mib-2 + FROM SNMPv2-SMI + TEXTUAL-CONVENTION, MacAddress + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF + InterfaceIndex FROM IF-MIB + ; + +dot1dBridge MODULE-IDENTITY + LAST-UPDATED "200509190000Z" + ORGANIZATION "IETF Bridge MIB Working Group" + CONTACT-INFO + "Email: bridge-mib@ietf.org + + K.C. Norseth (Editor) + L-3 Communications + Tel: +1 801-594-2809 + Email: kenyon.c.norseth@L-3com.com + Postal: 640 N. 2200 West. + Salt Lake City, Utah 84116-0850 + Les Bell (Editor) + 3Com Europe Limited + Phone: +44 1442 438025 + Email: elbell@ntlworld.com + Postal: 3Com Centre, Boundary Way + Hemel Hempstead + Herts. HP2 7YU + UK + + Send comments to " + DESCRIPTION + "The Bridge MIB module for managing devices that support + IEEE 802.1D. + + Copyright (C) The Internet Society (2005). This version of + this MIB module is part of RFC 4188; see the RFC itself for + full legal notices." + REVISION "200509190000Z" + DESCRIPTION + "Third revision, published as part of RFC 4188. + + The MIB module has been converted to SMIv2 format. + Conformance statements have been added and some + description and reference clauses have been updated. + + The object dot1dStpPortPathCost32 was added to + support IEEE 802.1t and the permissible values of + dot1dStpPriority and dot1dStpPortPriority have been + clarified for bridges supporting IEEE 802.1t or + IEEE 802.1w. + + The interpretation of dot1dStpTimeSinceTopologyChange + has been clarified for bridges supporting the Rapid + Spanning Tree Protocol (RSTP)." + REVISION "199307310000Z" + DESCRIPTION + "Second revision, published as part of RFC 1493." + REVISION "199112310000Z" + DESCRIPTION + "Initial revision, published as part of RFC 1286." + ::= { mib-2 17 } + + +-- ---------------------------------------------------------- -- +-- Textual Conventions +-- ---------------------------------------------------------- -- + +BridgeId ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The Bridge-Identifier, as used in the Spanning Tree + Protocol, to uniquely identify a bridge. Its first two + octets (in network byte order) contain a priority value, + and its last 6 octets contain the MAC address used to + refer to a bridge in a unique fashion (typically, the + numerically smallest MAC address of all ports on the + bridge)." + SYNTAX OCTET STRING (SIZE (8)) + +Timeout ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d" + STATUS current + DESCRIPTION + "A Spanning Tree Protocol (STP) timer in units of 1/100 + seconds. Several objects in this MIB module represent + values of timers used by the Spanning Tree Protocol. + In this MIB, these timers have values in units of + hundredths of a second (i.e., 1/100 secs). + + These timers, when stored in a Spanning Tree Protocol's + BPDU, are in units of 1/256 seconds. Note, however, that + 802.1D-1998 specifies a settable granularity of no more + than one second for these timers. To avoid ambiguity, + a conversion algorithm is defined below for converting + between the different units, which ensures a timer's + value is not distorted by multiple conversions. + + To convert a Timeout value into a value in units of + 1/256 seconds, the following algorithm should be used: + + b = floor( (n * 256) / 100) + + where: + floor = quotient [ignore remainder] + n is the value in 1/100 second units + b is the value in 1/256 second units + + To convert the value from 1/256 second units back to + 1/100 seconds, the following algorithm should be used: + + n = ceiling( (b * 100) / 256) + + where: + ceiling = quotient [if remainder is 0], or + quotient + 1 [if remainder is nonzero] + n is the value in 1/100 second units + b is the value in 1/256 second units + + Note: it is important that the arithmetic operations are + done in the order specified (i.e., multiply first, + divide second)." + SYNTAX Integer32 + +-- ---------------------------------------------------------- -- +-- subtrees in the Bridge MIB +-- ---------------------------------------------------------- -- + +dot1dNotifications OBJECT IDENTIFIER ::= { dot1dBridge 0 } + +dot1dBase OBJECT IDENTIFIER ::= { dot1dBridge 1 } +dot1dStp OBJECT IDENTIFIER ::= { dot1dBridge 2 } + +dot1dSr OBJECT IDENTIFIER ::= { dot1dBridge 3 } +-- documented in RFC 1525 + +dot1dTp OBJECT IDENTIFIER ::= { dot1dBridge 4 } +dot1dStatic OBJECT IDENTIFIER ::= { dot1dBridge 5 } + +-- Subtrees used by Bridge MIB Extensions: +-- pBridgeMIB MODULE-IDENTITY ::= { dot1dBridge 6 } +-- qBridgeMIB MODULE-IDENTITY ::= { dot1dBridge 7 } +-- Note that the practice of registering related MIB modules +-- below dot1dBridge has been discouraged since there is no +-- robust mechanism to track such registrations. + +dot1dConformance OBJECT IDENTIFIER ::= { dot1dBridge 8 } + +-- ---------------------------------------------------------- -- +-- the dot1dBase subtree +-- ---------------------------------------------------------- -- +-- Implementation of the dot1dBase subtree is mandatory for all +-- bridges. +-- ---------------------------------------------------------- -- + +dot1dBaseBridgeAddress OBJECT-TYPE + + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The MAC address used by this bridge when it must be + referred to in a unique fashion. It is recommended + that this be the numerically smallest MAC address of + all ports that belong to this bridge. However, it is only + required to be unique. When concatenated with + dot1dStpPriority, a unique BridgeIdentifier is formed, + which is used in the Spanning Tree Protocol." + REFERENCE + "IEEE 802.1D-1998: clauses 14.4.1.1.3 and 7.12.5" + ::= { dot1dBase 1 } + +dot1dBaseNumPorts OBJECT-TYPE + SYNTAX Integer32 + UNITS "ports" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of ports controlled by this bridging + entity." + REFERENCE + "IEEE 802.1D-1998: clause 14.4.1.1.3" + ::= { dot1dBase 2 } + +dot1dBaseType OBJECT-TYPE + SYNTAX INTEGER { + unknown(1), + transparent-only(2), + sourceroute-only(3), + srt(4) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Indicates what type of bridging this bridge can + perform. If a bridge is actually performing a + certain type of bridging, this will be indicated by + entries in the port table for the given type." + ::= { dot1dBase 3 } + +-- ---------------------------------------------------------- -- +-- The Generic Bridge Port Table +-- ---------------------------------------------------------- -- +dot1dBasePortTable OBJECT-TYPE + SYNTAX SEQUENCE OF Dot1dBasePortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains generic information about every + port that is associated with this bridge. Transparent, + source-route, and srt ports are included." + ::= { dot1dBase 4 } + +dot1dBasePortEntry OBJECT-TYPE + SYNTAX Dot1dBasePortEntry + MAX-ACCESS not-accessible + STATUS current + + DESCRIPTION + "A list of information for each port of the bridge." + REFERENCE + "IEEE 802.1D-1998: clause 14.4.2, 14.6.1" + INDEX { dot1dBasePort } + ::= { dot1dBasePortTable 1 } + +Dot1dBasePortEntry ::= + SEQUENCE { + dot1dBasePort + Integer32, + dot1dBasePortIfIndex + InterfaceIndex, + dot1dBasePortCircuit + OBJECT IDENTIFIER, + dot1dBasePortDelayExceededDiscards + Counter32, + dot1dBasePortMtuExceededDiscards + Counter32 + } + +dot1dBasePort OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The port number of the port for which this entry + contains bridge management information." + ::= { dot1dBasePortEntry 1 } + +dot1dBasePortIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of the instance of the ifIndex object, + defined in IF-MIB, for the interface corresponding + to this port." + ::= { dot1dBasePortEntry 2 } + +dot1dBasePortCircuit OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "For a port that (potentially) has the same value of + dot1dBasePortIfIndex as another port on the same bridge. + This object contains the name of an object instance + unique to this port. For example, in the case where + multiple ports correspond one-to-one with multiple X.25 + virtual circuits, this value might identify an (e.g., + the first) object instance associated with the X.25 + virtual circuit corresponding to this port. + + For a port which has a unique value of + dot1dBasePortIfIndex, this object can have the value + { 0 0 }." + ::= { dot1dBasePortEntry 3 } + +dot1dBasePortDelayExceededDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of frames discarded by this port due + to excessive transit delay through the bridge. It + is incremented by both transparent and source + route bridges." + REFERENCE + "IEEE 802.1D-1998: clause 14.6.1.1.3" + ::= { dot1dBasePortEntry 4 } + +dot1dBasePortMtuExceededDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of frames discarded by this port due + to an excessive size. It is incremented by both + transparent and source route bridges." + REFERENCE + "IEEE 802.1D-1998: clause 14.6.1.1.3" + ::= { dot1dBasePortEntry 5 } + +-- ---------------------------------------------------------- -- +-- the dot1dStp subtree +-- ---------------------------------------------------------- -- +-- Implementation of the dot1dStp subtree is optional. It is +-- implemented by those bridges that support the Spanning Tree +-- Protocol. +-- ---------------------------------------------------------- -- +dot1dStpProtocolSpecification OBJECT-TYPE + SYNTAX INTEGER { + unknown(1), + decLb100(2), + ieee8021d(3) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An indication of what version of the Spanning Tree + Protocol is being run. The value 'decLb100(2)' + indicates the DEC LANbridge 100 Spanning Tree protocol. + IEEE 802.1D implementations will return 'ieee8021d(3)'. + If future versions of the IEEE Spanning Tree Protocol + that are incompatible with the current version + are released a new value will be defined." + ::= { dot1dStp 1 } + +dot1dStpPriority OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value of the write-able portion of the Bridge ID + (i.e., the first two octets of the (8 octet long) Bridge + ID). The other (last) 6 octets of the Bridge ID are + given by the value of dot1dBaseBridgeAddress. + On bridges supporting IEEE 802.1t or IEEE 802.1w, + permissible values are 0-61440, in steps of 4096." + REFERENCE + "IEEE 802.1D-1998 clause 8.10.2, Table 8-4, + IEEE 802.1t clause 8.10.2, Table 8-4, clause 14.3." + ::= { dot1dStp 2 } + +dot1dStpTimeSinceTopologyChange OBJECT-TYPE + SYNTAX TimeTicks + UNITS "centi-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The time (in hundredths of a second) since the + last time a topology change was detected by the + bridge entity. + For RSTP, this reports the time since the tcWhile + timer for any port on this Bridge was nonzero." + REFERENCE + "IEEE 802.1D-1998 clause 14.8.1.1., + IEEE 802.1w clause 14.8.1.1." + ::= { dot1dStp 3 } + +dot1dStpTopChanges OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of topology changes detected by + this bridge since the management entity was last + reset or initialized." + REFERENCE + "IEEE 802.1D-1998 clause 14.8.1.1." + ::= { dot1dStp 4 } + +dot1dStpDesignatedRoot OBJECT-TYPE + SYNTAX BridgeId + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The bridge identifier of the root of the spanning + tree, as determined by the Spanning Tree Protocol, + as executed by this node. This value is used as + the Root Identifier parameter in all Configuration + Bridge PDUs originated by this node." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.3.1" + ::= { dot1dStp 5 } + +dot1dStpRootCost OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The cost of the path to the root as seen from + this bridge." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.3.2" + ::= { dot1dStp 6 } + +dot1dStpRootPort OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The port number of the port that offers the lowest + cost path from this bridge to the root bridge." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.3.3" + ::= { dot1dStp 7 } + +dot1dStpMaxAge OBJECT-TYPE + SYNTAX Timeout + UNITS "centi-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum age of Spanning Tree Protocol information + learned from the network on any port before it is + discarded, in units of hundredths of a second. This is + the actual value that this bridge is currently using." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.3.4" + ::= { dot1dStp 8 } + +dot1dStpHelloTime OBJECT-TYPE + SYNTAX Timeout + UNITS "centi-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The amount of time between the transmission of + Configuration bridge PDUs by this node on any port when + it is the root of the spanning tree, or trying to become + so, in units of hundredths of a second. This is the + actual value that this bridge is currently using." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.3.5" + ::= { dot1dStp 9 } + +dot1dStpHoldTime OBJECT-TYPE + SYNTAX Integer32 + UNITS "centi-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This time value determines the interval length + during which no more than two Configuration bridge + PDUs shall be transmitted by this node, in units + of hundredths of a second." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.3.14" + ::= { dot1dStp 10 } + +dot1dStpForwardDelay OBJECT-TYPE + SYNTAX Timeout + UNITS "centi-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This time value, measured in units of hundredths of a + second, controls how fast a port changes its spanning + state when moving towards the Forwarding state. The + value determines how long the port stays in each of the + Listening and Learning states, which precede the + Forwarding state. This value is also used when a + topology change has been detected and is underway, to + age all dynamic entries in the Forwarding Database. + [Note that this value is the one that this bridge is + currently using, in contrast to + dot1dStpBridgeForwardDelay, which is the value that this + bridge and all others would start using if/when this + bridge were to become the root.]" + REFERENCE + "IEEE 802.1D-1998: clause 8.5.3.6" + ::= { dot1dStp 11 } + +dot1dStpBridgeMaxAge OBJECT-TYPE + SYNTAX Timeout (600..4000) + UNITS "centi-seconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value that all bridges use for MaxAge when this + bridge is acting as the root. Note that 802.1D-1998 + specifies that the range for this parameter is related + to the value of dot1dStpBridgeHelloTime. The + granularity of this timer is specified by 802.1D-1998 to + be 1 second. An agent may return a badValue error if a + set is attempted to a value that is not a whole number + of seconds." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.3.8" + ::= { dot1dStp 12 } + +dot1dStpBridgeHelloTime OBJECT-TYPE + SYNTAX Timeout (100..1000) + UNITS "centi-seconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value that all bridges use for HelloTime when this + bridge is acting as the root. The granularity of this + timer is specified by 802.1D-1998 to be 1 second. An + agent may return a badValue error if a set is attempted + to a value that is not a whole number of seconds." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.3.9" + ::= { dot1dStp 13 } + +dot1dStpBridgeForwardDelay OBJECT-TYPE + SYNTAX Timeout (400..3000) + UNITS "centi-seconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value that all bridges use for ForwardDelay when + this bridge is acting as the root. Note that + 802.1D-1998 specifies that the range for this parameter + is related to the value of dot1dStpBridgeMaxAge. The + granularity of this timer is specified by 802.1D-1998 to + be 1 second. An agent may return a badValue error if a + set is attempted to a value that is not a whole number + of seconds." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.3.10" + ::= { dot1dStp 14 } + +-- ---------------------------------------------------------- -- +-- The Spanning Tree Port Table +-- ---------------------------------------------------------- -- + +dot1dStpPortTable OBJECT-TYPE + SYNTAX SEQUENCE OF Dot1dStpPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains port-specific information + for the Spanning Tree Protocol." + ::= { dot1dStp 15 } + +dot1dStpPortEntry OBJECT-TYPE + SYNTAX Dot1dStpPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of information maintained by every port about + the Spanning Tree Protocol state for that port." + INDEX { dot1dStpPort } + ::= { dot1dStpPortTable 1 } + +Dot1dStpPortEntry ::= + SEQUENCE { + dot1dStpPort + Integer32, + dot1dStpPortPriority + Integer32, + dot1dStpPortState + INTEGER, + dot1dStpPortEnable + INTEGER, + dot1dStpPortPathCost + Integer32, + dot1dStpPortDesignatedRoot + BridgeId, + dot1dStpPortDesignatedCost + Integer32, + dot1dStpPortDesignatedBridge + BridgeId, + dot1dStpPortDesignatedPort + OCTET STRING, + dot1dStpPortForwardTransitions + Counter32, + dot1dStpPortPathCost32 + Integer32 + } + +dot1dStpPort OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The port number of the port for which this entry + contains Spanning Tree Protocol management information." + REFERENCE + "IEEE 802.1D-1998: clause 14.8.2.1.2" + ::= { dot1dStpPortEntry 1 } + +dot1dStpPortPriority OBJECT-TYPE + SYNTAX Integer32 (0..255) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value of the priority field that is contained in + the first (in network byte order) octet of the (2 octet + long) Port ID. The other octet of the Port ID is given + by the value of dot1dStpPort. + On bridges supporting IEEE 802.1t or IEEE 802.1w, + permissible values are 0-240, in steps of 16." + REFERENCE + "IEEE 802.1D-1998 clause 8.10.2, Table 8-4, + IEEE 802.1t clause 8.10.2, Table 8-4, clause 14.3." + ::= { dot1dStpPortEntry 2 } + +dot1dStpPortState OBJECT-TYPE + SYNTAX INTEGER { + disabled(1), + blocking(2), + listening(3), + learning(4), + forwarding(5), + broken(6) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The port's current state, as defined by application of + the Spanning Tree Protocol. This state controls what + action a port takes on reception of a frame. If the + bridge has detected a port that is malfunctioning, it + will place that port into the broken(6) state. For + ports that are disabled (see dot1dStpPortEnable), this + object will have a value of disabled(1)." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.5.2" + ::= { dot1dStpPortEntry 3 } + +dot1dStpPortEnable OBJECT-TYPE + SYNTAX INTEGER { + enabled(1), + disabled(2) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The enabled/disabled status of the port." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.5.2" + ::= { dot1dStpPortEntry 4 } + +dot1dStpPortPathCost OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The contribution of this port to the path cost of + paths towards the spanning tree root which include + this port. 802.1D-1998 recommends that the default + value of this parameter be in inverse proportion to + the speed of the attached LAN. + + New implementations should support dot1dStpPortPathCost32. + If the port path costs exceeds the maximum value of this + object then this object should report the maximum value, + namely 65535. Applications should try to read the + dot1dStpPortPathCost32 object if this object reports + the maximum value." + REFERENCE "IEEE 802.1D-1998: clause 8.5.5.3" + ::= { dot1dStpPortEntry 5 } + +dot1dStpPortDesignatedRoot OBJECT-TYPE + SYNTAX BridgeId + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The unique Bridge Identifier of the Bridge + recorded as the Root in the Configuration BPDUs + transmitted by the Designated Bridge for the + segment to which the port is attached." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.5.4" + ::= { dot1dStpPortEntry 6 } + +dot1dStpPortDesignatedCost OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The path cost of the Designated Port of the segment + connected to this port. This value is compared to the + Root Path Cost field in received bridge PDUs." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.5.5" + ::= { dot1dStpPortEntry 7 } + +dot1dStpPortDesignatedBridge OBJECT-TYPE + SYNTAX BridgeId + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The Bridge Identifier of the bridge that this + port considers to be the Designated Bridge for + this port's segment." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.5.6" + ::= { dot1dStpPortEntry 8 } + +dot1dStpPortDesignatedPort OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (2)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The Port Identifier of the port on the Designated + Bridge for this port's segment." + REFERENCE + "IEEE 802.1D-1998: clause 8.5.5.7" + ::= { dot1dStpPortEntry 9 } + +dot1dStpPortForwardTransitions OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times this port has transitioned + from the Learning state to the Forwarding state." + ::= { dot1dStpPortEntry 10 } + +dot1dStpPortPathCost32 OBJECT-TYPE + SYNTAX Integer32 (1..200000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The contribution of this port to the path cost of + paths towards the spanning tree root which include + this port. 802.1D-1998 recommends that the default + value of this parameter be in inverse proportion to + the speed of the attached LAN. + + This object replaces dot1dStpPortPathCost to support + IEEE 802.1t." + REFERENCE + "IEEE 802.1t clause 8.10.2, Table 8-5." + ::= { dot1dStpPortEntry 11 } + +-- ---------------------------------------------------------- -- +-- the dot1dTp subtree +-- ---------------------------------------------------------- -- +-- Implementation of the dot1dTp subtree is optional. It is +-- implemented by those bridges that support the transparent +-- bridging mode. A transparent or SRT bridge will implement +-- this subtree. +-- ---------------------------------------------------------- -- + +dot1dTpLearnedEntryDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of Forwarding Database entries that + have been or would have been learned, but have been + discarded due to a lack of storage space in the + Forwarding Database. If this counter is increasing, it + indicates that the Forwarding Database is regularly + becoming full (a condition that has unpleasant + performance effects on the subnetwork). If this counter + has a significant value but is not presently increasing, + it indicates that the problem has been occurring but is + not persistent." + REFERENCE + "IEEE 802.1D-1998: clause 14.7.1.1.3" + ::= { dot1dTp 1 } + +dot1dTpAgingTime OBJECT-TYPE + SYNTAX Integer32 (10..1000000) + UNITS "seconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The timeout period in seconds for aging out + dynamically-learned forwarding information. + 802.1D-1998 recommends a default of 300 seconds." + REFERENCE + "IEEE 802.1D-1998: clause 14.7.1.1.3" + ::= { dot1dTp 2 } + + +-- ---------------------------------------------------------- -- +-- The Forwarding Database for Transparent Bridges +-- ---------------------------------------------------------- -- + +dot1dTpFdbTable OBJECT-TYPE + SYNTAX SEQUENCE OF Dot1dTpFdbEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains information about unicast + entries for which the bridge has forwarding and/or + filtering information. This information is used + by the transparent bridging function in + determining how to propagate a received frame." + ::= { dot1dTp 3 } + +dot1dTpFdbEntry OBJECT-TYPE + SYNTAX Dot1dTpFdbEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Information about a specific unicast MAC address + for which the bridge has some forwarding and/or + filtering information." + INDEX { dot1dTpFdbAddress } + ::= { dot1dTpFdbTable 1 } + +Dot1dTpFdbEntry ::= + SEQUENCE { + dot1dTpFdbAddress + MacAddress, + dot1dTpFdbPort + Integer32, + dot1dTpFdbStatus + INTEGER + } + +dot1dTpFdbAddress OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A unicast MAC address for which the bridge has + forwarding and/or filtering information." + REFERENCE + "IEEE 802.1D-1998: clause 7.9.1, 7.9.2" + ::= { dot1dTpFdbEntry 1 } + +dot1dTpFdbPort OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Either the value '0', or the port number of the port on + which a frame having a source address equal to the value + of the corresponding instance of dot1dTpFdbAddress has + been seen. A value of '0' indicates that the port + number has not been learned, but that the bridge does + have some forwarding/filtering information about this + address (e.g., in the dot1dStaticTable). Implementors + are encouraged to assign the port value to this object + whenever it is learned, even for addresses for which the + corresponding value of dot1dTpFdbStatus is not + learned(3)." + ::= { dot1dTpFdbEntry 2 } +dot1dTpFdbStatus OBJECT-TYPE + SYNTAX INTEGER { + other(1), + invalid(2), + learned(3), + self(4), + mgmt(5) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The status of this entry. The meanings of the + values are: + other(1) - none of the following. This would + include the case where some other MIB object + (not the corresponding instance of + dot1dTpFdbPort, nor an entry in the + dot1dStaticTable) is being used to determine if + and how frames addressed to the value of the + corresponding instance of dot1dTpFdbAddress are + being forwarded. + invalid(2) - this entry is no longer valid (e.g., + it was learned but has since aged out), but has + not yet been flushed from the table. + learned(3) - the value of the corresponding instance + of dot1dTpFdbPort was learned, and is being + used. + self(4) - the value of the corresponding instance of + dot1dTpFdbAddress represents one of the bridge's + addresses. The corresponding instance of + dot1dTpFdbPort indicates which of the bridge's + ports has this address. + mgmt(5) - the value of the corresponding instance of + dot1dTpFdbAddress is also the value of an + existing instance of dot1dStaticAddress." + ::= { dot1dTpFdbEntry 3 } + +-- ---------------------------------------------------------- -- +-- Port Table for Transparent Bridges +-- ---------------------------------------------------------- -- + +dot1dTpPortTable OBJECT-TYPE + SYNTAX SEQUENCE OF Dot1dTpPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains information about every port that + is associated with this transparent bridge." + ::= { dot1dTp 4 } + +dot1dTpPortEntry OBJECT-TYPE + SYNTAX Dot1dTpPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of information for each port of a transparent + bridge." + INDEX { dot1dTpPort } + ::= { dot1dTpPortTable 1 } + +Dot1dTpPortEntry ::= + SEQUENCE { + dot1dTpPort + Integer32, + dot1dTpPortMaxInfo + Integer32, + dot1dTpPortInFrames + Counter32, + dot1dTpPortOutFrames + Counter32, + dot1dTpPortInDiscards + Counter32 + } + +dot1dTpPort OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The port number of the port for which this entry + contains Transparent bridging management information." + ::= { dot1dTpPortEntry 1 } + +-- It would be nice if we could use ifMtu as the size of the +-- largest INFO field, but we can't because ifMtu is defined +-- to be the size that the (inter-)network layer can use, which +-- can differ from the MAC layer (especially if several layers +-- of encapsulation are used). + +dot1dTpPortMaxInfo OBJECT-TYPE + SYNTAX Integer32 + UNITS "bytes" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum size of the INFO (non-MAC) field that + this port will receive or transmit." + ::= { dot1dTpPortEntry 2 } + +dot1dTpPortInFrames OBJECT-TYPE + SYNTAX Counter32 + UNITS "frames" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of frames that have been received by this + port from its segment. Note that a frame received on the + interface corresponding to this port is only counted by + this object if and only if it is for a protocol being + processed by the local bridging function, including + bridge management frames." + REFERENCE + "IEEE 802.1D-1998: clause 14.6.1.1.3" + ::= { dot1dTpPortEntry 3 } + +dot1dTpPortOutFrames OBJECT-TYPE + SYNTAX Counter32 + UNITS "frames" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of frames that have been transmitted by this + port to its segment. Note that a frame transmitted on + the interface corresponding to this port is only counted + by this object if and only if it is for a protocol being + processed by the local bridging function, including + bridge management frames." + REFERENCE + "IEEE 802.1D-1998: clause 14.6.1.1.3" + ::= { dot1dTpPortEntry 4 } + +dot1dTpPortInDiscards OBJECT-TYPE + SYNTAX Counter32 + UNITS "frames" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Count of received valid frames that were discarded + (i.e., filtered) by the Forwarding Process." + REFERENCE + "IEEE 802.1D-1998: clause 14.6.1.1.3" + ::= { dot1dTpPortEntry 5 } + +-- ---------------------------------------------------------- -- +-- The Static (Destination-Address Filtering) Database +-- ---------------------------------------------------------- -- +-- Implementation of this subtree is optional. +-- ---------------------------------------------------------- -- + +dot1dStaticTable OBJECT-TYPE + SYNTAX SEQUENCE OF Dot1dStaticEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing filtering information configured + into the bridge by (local or network) management + specifying the set of ports to which frames received + from specific ports and containing specific destination + addresses are allowed to be forwarded. The value of + zero in this table, as the port number from which frames + with a specific destination address are received, is + used to specify all ports for which there is no specific + entry in this table for that particular destination + address. Entries are valid for unicast and for + group/broadcast addresses." + REFERENCE + "IEEE 802.1D-1998: clause 14.7.2" + ::= { dot1dStatic 1 } + +dot1dStaticEntry OBJECT-TYPE + SYNTAX Dot1dStaticEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Filtering information configured into the bridge by + (local or network) management specifying the set of + ports to which frames received from a specific port and + containing a specific destination address are allowed to + be forwarded." + REFERENCE + "IEEE 802.1D-1998: clause 14.7.2" + INDEX { dot1dStaticAddress, dot1dStaticReceivePort } + ::= { dot1dStaticTable 1 } + +Dot1dStaticEntry ::= + SEQUENCE { + dot1dStaticAddress MacAddress, + dot1dStaticReceivePort Integer32, + dot1dStaticAllowedToGoTo OCTET STRING, + dot1dStaticStatus INTEGER + } + +dot1dStaticAddress OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The destination MAC address in a frame to which this + entry's filtering information applies. This object can + take the value of a unicast address, a group address, or + the broadcast address." + REFERENCE + "IEEE 802.1D-1998: clause 7.9.1, 7.9.2" + ::= { dot1dStaticEntry 1 } + +dot1dStaticReceivePort OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Either the value '0', or the port number of the port + from which a frame must be received in order for this + entry's filtering information to apply. A value of zero + indicates that this entry applies on all ports of the + bridge for which there is no other applicable entry." + ::= { dot1dStaticEntry 2 } + +dot1dStaticAllowedToGoTo OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..512)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The set of ports to which frames received from a + specific port and destined for a specific MAC address, + are allowed to be forwarded. Each octet within the + value of this object specifies a set of eight ports, + with the first octet specifying ports 1 through 8, the + second octet specifying ports 9 through 16, etc. Within + each octet, the most significant bit represents the + lowest numbered port, and the least significant bit + represents the highest numbered port. Thus, each port + of the bridge is represented by a single bit within the + value of this object. If that bit has a value of '1', + then that port is included in the set of ports; the port + is not included if its bit has a value of '0'. (Note + that the setting of the bit corresponding to the port + from which a frame is received is irrelevant.) The + default value of this object is a string of ones of + appropriate length. + + The value of this object may exceed the required minimum + maximum message size of some SNMP transport (484 bytes, + in the case of SNMP over UDP, see RFC 3417, section 3.2). + SNMP engines on bridges supporting a large number of + ports must support appropriate maximum message sizes." + ::= { dot1dStaticEntry 3 } + +dot1dStaticStatus OBJECT-TYPE + SYNTAX INTEGER { + other(1), + invalid(2), + permanent(3), + deleteOnReset(4), + deleteOnTimeout(5) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object indicates the status of this entry. + The default value is permanent(3). + other(1) - this entry is currently in use but the + conditions under which it will remain so are + different from each of the following values. + invalid(2) - writing this value to the object + removes the corresponding entry. + permanent(3) - this entry is currently in use and + will remain so after the next reset of the + bridge. + deleteOnReset(4) - this entry is currently in use + and will remain so until the next reset of the + bridge. + deleteOnTimeout(5) - this entry is currently in use + and will remain so until it is aged out." + ::= { dot1dStaticEntry 4 } + +-- ---------------------------------------------------------- -- +-- Notifications for use by Bridges +-- ---------------------------------------------------------- -- +-- Notifications for the Spanning Tree Protocol +-- ---------------------------------------------------------- -- + +newRoot NOTIFICATION-TYPE + -- OBJECTS { } + STATUS current + DESCRIPTION + "The newRoot trap indicates that the sending agent has + become the new root of the Spanning Tree; the trap is + sent by a bridge soon after its election as the new + root, e.g., upon expiration of the Topology Change Timer, + immediately subsequent to its election. Implementation + of this trap is optional." + ::= { dot1dNotifications 1 } + +topologyChange NOTIFICATION-TYPE + -- OBJECTS { } + STATUS current + DESCRIPTION + "A topologyChange trap is sent by a bridge when any of + its configured ports transitions from the Learning state + to the Forwarding state, or from the Forwarding state to + the Blocking state. The trap is not sent if a newRoot + trap is sent for the same transition. Implementation of + this trap is optional." + ::= { dot1dNotifications 2 } + +-- ---------------------------------------------------------- -- +-- IEEE 802.1D MIB - Conformance Information +-- ---------------------------------------------------------- -- + +dot1dGroups OBJECT IDENTIFIER ::= { dot1dConformance 1 } +dot1dCompliances OBJECT IDENTIFIER ::= { dot1dConformance 2 } + +-- ---------------------------------------------------------- -- +-- units of conformance +-- ---------------------------------------------------------- -- + +-- ---------------------------------------------------------- -- +-- the dot1dBase group +-- ---------------------------------------------------------- -- + +dot1dBaseBridgeGroup OBJECT-GROUP + OBJECTS { + dot1dBaseBridgeAddress, + dot1dBaseNumPorts, + dot1dBaseType + } + STATUS current + DESCRIPTION + "Bridge level information for this device." + ::= { dot1dGroups 1 } + +dot1dBasePortGroup OBJECT-GROUP + OBJECTS { + dot1dBasePort, + dot1dBasePortIfIndex, + dot1dBasePortCircuit, + dot1dBasePortDelayExceededDiscards, + dot1dBasePortMtuExceededDiscards + } + STATUS current + DESCRIPTION + "Information for each port on this device." + ::= { dot1dGroups 2 } + +-- ---------------------------------------------------------- -- +-- the dot1dStp group +-- ---------------------------------------------------------- -- + +dot1dStpBridgeGroup OBJECT-GROUP + OBJECTS { + dot1dStpProtocolSpecification, + dot1dStpPriority, + dot1dStpTimeSinceTopologyChange, + dot1dStpTopChanges, + dot1dStpDesignatedRoot, + dot1dStpRootCost, + dot1dStpRootPort, + dot1dStpMaxAge, + dot1dStpHelloTime, + dot1dStpHoldTime, + dot1dStpForwardDelay, + dot1dStpBridgeMaxAge, + dot1dStpBridgeHelloTime, + dot1dStpBridgeForwardDelay + } + STATUS current + DESCRIPTION + "Bridge level Spanning Tree data for this device." + ::= { dot1dGroups 3 } + +dot1dStpPortGroup OBJECT-GROUP + OBJECTS { + dot1dStpPort, + dot1dStpPortPriority, + dot1dStpPortState, + dot1dStpPortEnable, + dot1dStpPortPathCost, + dot1dStpPortDesignatedRoot, + dot1dStpPortDesignatedCost, + dot1dStpPortDesignatedBridge, + dot1dStpPortDesignatedPort, + dot1dStpPortForwardTransitions + } + STATUS current + DESCRIPTION + "Spanning Tree data for each port on this device." + ::= { dot1dGroups 4 } + +dot1dStpPortGroup2 OBJECT-GROUP + OBJECTS { + dot1dStpPort, + dot1dStpPortPriority, + dot1dStpPortState, + dot1dStpPortEnable, + dot1dStpPortDesignatedRoot, + dot1dStpPortDesignatedCost, + dot1dStpPortDesignatedBridge, + dot1dStpPortDesignatedPort, + dot1dStpPortForwardTransitions, + dot1dStpPortPathCost32 + } + STATUS current + DESCRIPTION + "Spanning Tree data for each port on this device." + ::= { dot1dGroups 5 } + +dot1dStpPortGroup3 OBJECT-GROUP + OBJECTS { + dot1dStpPortPathCost32 + } + STATUS current + DESCRIPTION + "Spanning Tree data for devices supporting 32-bit + path costs." + ::= { dot1dGroups 6 } + +-- ---------------------------------------------------------- -- +-- the dot1dTp group +-- ---------------------------------------------------------- -- + +dot1dTpBridgeGroup OBJECT-GROUP + OBJECTS { + dot1dTpLearnedEntryDiscards, + dot1dTpAgingTime + } + STATUS current + DESCRIPTION + "Bridge level Transparent Bridging data." + ::= { dot1dGroups 7 } + +dot1dTpFdbGroup OBJECT-GROUP + OBJECTS { + dot1dTpFdbAddress, + dot1dTpFdbPort, + dot1dTpFdbStatus + } + + STATUS current + DESCRIPTION + "Filtering Database information for the Bridge." + ::= { dot1dGroups 8 } + +dot1dTpGroup OBJECT-GROUP + OBJECTS { + dot1dTpPort, + dot1dTpPortMaxInfo, + dot1dTpPortInFrames, + dot1dTpPortOutFrames, + dot1dTpPortInDiscards + } + STATUS current + DESCRIPTION + "Dynamic Filtering Database information for each port of + the Bridge." + ::= { dot1dGroups 9 } + +-- ---------------------------------------------------------- -- +-- The Static (Destination-Address Filtering) Database +-- ---------------------------------------------------------- -- + +dot1dStaticGroup OBJECT-GROUP + OBJECTS { + dot1dStaticAddress, + dot1dStaticReceivePort, + dot1dStaticAllowedToGoTo, + dot1dStaticStatus + } + STATUS current + DESCRIPTION + "Static Filtering Database information for each port of + the Bridge." + ::= { dot1dGroups 10 } + +-- ---------------------------------------------------------- -- +-- The Trap Notification Group +-- ---------------------------------------------------------- -- + +dot1dNotificationGroup NOTIFICATION-GROUP + NOTIFICATIONS { + newRoot, + topologyChange + } + STATUS current + DESCRIPTION + "Group of objects describing notifications (traps)." + ::= { dot1dGroups 11 } + +-- ---------------------------------------------------------- -- +-- compliance statements +-- ---------------------------------------------------------- -- + +bridgeCompliance1493 MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for device support of bridging + services, as per RFC1493." + + MODULE + MANDATORY-GROUPS { + dot1dBaseBridgeGroup, + dot1dBasePortGroup + } + + GROUP dot1dStpBridgeGroup + DESCRIPTION + "Implementation of this group is mandatory for bridges + that support the Spanning Tree Protocol." + + GROUP dot1dStpPortGroup + DESCRIPTION + "Implementation of this group is mandatory for bridges + that support the Spanning Tree Protocol." + + GROUP dot1dTpBridgeGroup + DESCRIPTION + "Implementation of this group is mandatory for bridges + that support the transparent bridging mode. A + transparent or SRT bridge will implement this group." + + GROUP dot1dTpFdbGroup + DESCRIPTION + "Implementation of this group is mandatory for bridges + that support the transparent bridging mode. A + transparent or SRT bridge will implement this group." + + GROUP dot1dTpGroup + DESCRIPTION + "Implementation of this group is mandatory for bridges + that support the transparent bridging mode. A + transparent or SRT bridge will implement this group." + + GROUP dot1dStaticGroup + DESCRIPTION + "Implementation of this group is optional." + + GROUP dot1dNotificationGroup + DESCRIPTION + "Implementation of this group is optional." + ::= { dot1dCompliances 1 } + +bridgeCompliance4188 MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for device support of bridging + services. This supports 32-bit Path Cost values and the + more restricted bridge and port priorities, as per IEEE + 802.1t. + + Full support for the 802.1D management objects requires that + the SNMPv2-MIB [RFC3418] objects sysDescr, and sysUpTime, as + well as the IF-MIB [RFC2863] objects ifIndex, ifType, + ifDescr, ifPhysAddress, and ifLastChange are implemented." + + MODULE + MANDATORY-GROUPS { + dot1dBaseBridgeGroup, + dot1dBasePortGroup + } + + GROUP dot1dStpBridgeGroup + DESCRIPTION + "Implementation of this group is mandatory for + bridges that support the Spanning Tree Protocol." + + OBJECT dot1dStpPriority + SYNTAX Integer32 (0|4096|8192|12288|16384|20480|24576 + |28672|32768|36864|40960|45056|49152 + |53248|57344|61440) + DESCRIPTION + "The possible values defined by IEEE 802.1t." + + GROUP dot1dStpPortGroup2 + DESCRIPTION + "Implementation of this group is mandatory for + bridges that support the Spanning Tree Protocol." + + GROUP dot1dStpPortGroup3 + DESCRIPTION + "Implementation of this group is mandatory for bridges + that support the Spanning Tree Protocol and 32-bit path + costs. In particular, this includes devices supporting + IEEE 802.1t and IEEE 802.1w." + + OBJECT dot1dStpPortPriority + SYNTAX Integer32 (0|16|32|48|64|80|96|112|128 + |144|160|176|192|208|224|240) + DESCRIPTION + "The possible values defined by IEEE 802.1t." + + GROUP dot1dTpBridgeGroup + DESCRIPTION + "Implementation of this group is mandatory for + bridges that support the transparent bridging + mode. A transparent or SRT bridge will implement + this group." + + GROUP dot1dTpFdbGroup + DESCRIPTION + "Implementation of this group is mandatory for + bridges that support the transparent bridging + mode. A transparent or SRT bridge will implement + this group." + + GROUP dot1dTpGroup + DESCRIPTION + "Implementation of this group is mandatory for + bridges that support the transparent bridging + mode. A transparent or SRT bridge will implement + this group." + + GROUP dot1dStaticGroup + DESCRIPTION + "Implementation of this group is optional." + + GROUP dot1dNotificationGroup + DESCRIPTION + "Implementation of this group is optional." + + ::= { dot1dCompliances 2 } + +END Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/Makefile =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/Makefile diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/Makefile 17 Nov 2006 16:30:44 -0000 @@ -0,0 +1,19 @@ +# +# $FreeBSD$ +# + +MOD= bridge +SRCS= bridge_snmp.c bridge_if.c bridge_port.c bridge_addrs.c \ + bridge_pf.c bridge_sys.c +CFLAGS+= -DSNMPTREE_TYPES + +XSYM= dot1dBridge newRoot topologyChange begemotBridgeNewRoot \ + begemotBridgeTopologyChange begemotBridgeBaseName + +MAN= snmp_bridge.3 + +BMIBS= BRIDGE-MIB.txt BEGEMOT-BRIDGE-MIB.txt +DEFS= ${MOD}_tree.def +INCS= ${MOD}_snmp.h + +.include Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_addrs.c =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_addrs.c diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_addrs.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_addrs.c 17 Nov 2006 16:30:44 -0000 @@ -0,0 +1,592 @@ +/*- + * Copyright (c) 2006 Shteryana Shopova + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Bridge MIB implementation for SNMPd. + * Bridge addresses. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bridge_tree.h" +#include "bridge_snmp.h" + +TAILQ_HEAD(tp_entries, tp_entry); + +/* + * Free the bridge address list. + */ +static void +bridge_tpe_free(struct tp_entries *headp) +{ + struct tp_entry *t; + + while ((t = TAILQ_FIRST(headp)) != NULL) { + TAILQ_REMOVE(headp, t, tp_e); + free(t); + } +} + +/* + * Free the bridge address entries from the address list, + * for the specified bridge interface only. + */ +static void +bridge_tpe_bif_free(struct tp_entries *headp, + struct bridge_if *bif) +{ + struct tp_entry *tp; + + while (bif->f_tpa != NULL && bif->sysindex == bif->f_tpa->sysindex) { + tp = TAILQ_NEXT(bif->f_tpa, tp_e); + TAILQ_REMOVE(headp, bif->f_tpa, tp_e); + free(bif->f_tpa); + bif->f_tpa = tp; + } +} + +/* + * Compare two mac addresses. + * m1 < m2 : -1 + * m1 > m2 : +1 + * m1 = m2 : 0 + */ +static int +bridge_compare_macs(const uint8_t *m1, const uint8_t *m2) +{ + int i; + + for (i = 0; i < ETHER_ADDR_LEN; i++) { + if (m1[i] < m2[i]) + return (-1); + if (m1[i] > m2[i]) + return (1); + } + + return (0); +} + +/* + * Insert an address entry in the bridge address TAILQ starting to search + * for its place from the position of the first bridge address for the bridge + * interface. Update the first bridge address if neccessary. + */ +static void +bridge_addrs_insert_at(struct tp_entries *headp, + struct tp_entry *ta, struct tp_entry **f_tpa) +{ + struct tp_entry *t1; + + assert(f_tpa != NULL); + + for (t1 = *f_tpa; + t1 != NULL && ta->sysindex == t1->sysindex; + t1 = TAILQ_NEXT(t1, tp_e)) { + if (bridge_compare_macs(ta->tp_addr, t1->tp_addr) < 0) { + TAILQ_INSERT_BEFORE(t1, ta, tp_e); + if (*f_tpa == t1) + (*f_tpa) = ta; + return; + } + } + + if (t1 == NULL) + TAILQ_INSERT_TAIL(headp, ta, tp_e); + else + TAILQ_INSERT_BEFORE(t1, ta, tp_e); +} + +/* + * Find an address entry's possition in the address list + * according to bridge interface name. + */ +static struct tp_entry * +bridge_addrs_find_pos(struct tp_entries *headp, uint32_t b_idx) +{ + uint32_t t_idx; + struct tp_entry *t1; + + if ((t1 = TAILQ_FIRST(headp)) == NULL || + bridge_compare_sysidx(b_idx, t1->sysindex) < 0) + return (NULL); + + t_idx = t1->sysindex; + + for (t1 = TAILQ_NEXT(t1, tp_e); t1 != NULL; t1 = TAILQ_NEXT(t1, tp_e)) { + + if (t1->sysindex != t_idx) { + if (bridge_compare_sysidx(b_idx, t1->sysindex) < 0) + return (TAILQ_PREV(t1, tp_entries, tp_e)); + else + t_idx = t1->sysindex; + } + } + + if (t1 == NULL) + t1 = TAILQ_LAST(headp, tp_entries); + + return (t1); +} + +/* + * Insert a bridge address in the bridge addresses list. + */ +static void +bridge_addrs_bif_insert(struct tp_entries *headp, struct tp_entry *te, + struct tp_entry **f_tpa) +{ + struct tp_entry *temp; + + if (*f_tpa != NULL) + bridge_addrs_insert_at(headp, te, f_tpa); + else { + temp = bridge_addrs_find_pos(headp, te->sysindex); + + if (temp == NULL) + TAILQ_INSERT_HEAD(headp, te, tp_e); + else + TAILQ_INSERT_AFTER(headp, temp, te, tp_e); + *f_tpa = te; + } +} + +static struct tp_entries tp_entries = TAILQ_HEAD_INITIALIZER(tp_entries); +static time_t address_list_age; + +void +bridge_addrs_update_listage(void) +{ + address_list_age = time(NULL); +} + +void +bridge_addrs_fini(void) +{ + bridge_tpe_free(&tp_entries); +} + +void +bridge_addrs_free(struct bridge_if *bif) +{ + bridge_tpe_bif_free(&tp_entries, bif); +} + +/* + * Find the first address in the list. + */ +static struct tp_entry * +bridge_addrs_first(void) +{ + return (TAILQ_FIRST(&tp_entries)); +} + +/* + * Find the next address in the list. + */ +static struct tp_entry * +bridge_addrs_next(struct tp_entry *te) +{ + return (TAILQ_NEXT(te, tp_e)); +} + +/* + * Find the first address, learnt by the specified bridge interface. + */ +struct tp_entry * +bridge_addrs_bif_first(struct bridge_if *bif) +{ + return (bif->f_tpa); +} + +/* + * Find the next address, learnt by the specified bridge interface. + */ +struct tp_entry * +bridge_addrs_bif_next(struct tp_entry *te) +{ + struct tp_entry *te_next; + + if ((te_next = TAILQ_NEXT(te, tp_e)) == NULL || + te_next->sysindex != te->sysindex) + return (NULL); + + return (te_next); +} + +/* + * Remove a bridge address from the list. + */ +void +bridge_addrs_remove(struct tp_entry *te, struct bridge_if *bif) +{ + if (bif->f_tpa == te) + bif->f_tpa = bridge_addrs_bif_next(te); + + TAILQ_REMOVE(&tp_entries, te, tp_e); + free(te); +} + +/* + * Allocate memory for a new bridge address and insert it in the list. + */ +struct tp_entry * +bridge_new_addrs(uint8_t *mac, struct bridge_if *bif) +{ + struct tp_entry *te; + + if ((te = (struct tp_entry *) malloc(sizeof(*te))) == NULL) { + syslog(LOG_ERR, "bridge new address: failed: %s", + strerror(errno)); + return (NULL); + } + + bzero(te, sizeof(*te)); + + te->sysindex = bif->sysindex; + bcopy(mac, te->tp_addr, ETHER_ADDR_LEN); + bridge_addrs_bif_insert(&tp_entries, te, &(bif->f_tpa)); + + return (te); +} + +/* + * Given a mac address, learnt on a bridge, + * find the corrsponding TP entry for it. + */ +struct tp_entry * +bridge_addrs_find(uint8_t *mac, struct bridge_if *bif) +{ + struct tp_entry *te; + + for (te = bif->f_tpa; te != NULL; te = TAILQ_NEXT(te, tp_e)) { + if (te->sysindex != bif->sysindex) { + te = NULL; + break; + } + + if (bridge_compare_macs(te->tp_addr, mac) == 0) + break; + } + + return (te); +} + +void +bridge_addrs_dump(struct bridge_if *bif) +{ + struct tp_entry *te; + + syslog(LOG_ERR, "Addresses count - %d", bif->num_addrs); + for (te = bridge_addrs_bif_first(bif); te != NULL; + te = bridge_addrs_bif_next(te)) { + syslog(LOG_ERR, "address %x:%x:%x:%x:%x:%x on port %d.%d", + te->tp_addr[0], te->tp_addr[1], te->tp_addr[2], + te->tp_addr[3], te->tp_addr[4], te->tp_addr[5], + te->sysindex, te->port_no); + } +} + +/* + * RFC4188 specifics. + */ + +/* + * Construct the SNMP index from the address DST Mac. + */ +static void +bridge_addrs_index_append(struct asn_oid *oid, uint sub, + const struct tp_entry *te) +{ + int i; + + oid->len = sub + ETHER_ADDR_LEN + 1; + oid->subs[sub] = ETHER_ADDR_LEN; + + for (i = 1; i <= ETHER_ADDR_LEN; i++) + oid->subs[sub + i] = te->tp_addr[i - 1]; +} + +/* + * Find the address entry for the SNMP index from the default bridge only. + */ +static struct tp_entry * +bridge_addrs_get(const struct asn_oid *oid, uint sub, + struct bridge_if *bif) +{ + int i; + uint8_t tp_addr[ETHER_ADDR_LEN]; + + if (oid->len - sub != ETHER_ADDR_LEN + 1 || + oid->subs[sub] != ETHER_ADDR_LEN) + return (NULL); + + for (i = 0; i < ETHER_ADDR_LEN; i++) + tp_addr[i] = oid->subs[sub + i + 1]; + + return (bridge_addrs_find(tp_addr, bif)); +} + +/* + * Find the next address entry for the SNMP index + * from the default bridge only. + */ +static struct tp_entry * +bridge_addrs_getnext(const struct asn_oid *oid, uint sub, + struct bridge_if *bif) +{ + int i; + uint8_t tp_addr[ETHER_ADDR_LEN]; + static struct tp_entry *te; + + if (oid->len - sub == 0) + return (bridge_addrs_bif_first(bif)); + + if (oid->len - sub != ETHER_ADDR_LEN + 1 || + oid->subs[sub] != ETHER_ADDR_LEN) + return (NULL); + + for (i = 0; i < ETHER_ADDR_LEN; i++) + tp_addr[i] = oid->subs[sub + i + 1]; + + if ((te = bridge_addrs_find(tp_addr, bif)) == NULL) + return (NULL); + + return (bridge_addrs_bif_next(te)); +} + +int +op_dot1d_tp_fdb(struct snmp_context *c __unused, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int ret; + struct bridge_if *bif; + struct tp_entry *te; + + if ((bif = bridge_get_default()) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + if (time(NULL) - bif->addrs_age > bridge_get_data_maxage() && + bridge_update_addrs(bif) <= 0) + return (SNMP_ERR_NOSUCHNAME); + + te = NULL; /* Make the compiler happy. */ + switch (op) { + case SNMP_OP_GET: + if ((te = bridge_addrs_get(&val->var, sub, bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((te = bridge_addrs_getnext(&val->var, sub, bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + bridge_addrs_index_append(&val->var, sub, te); + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + ret = SNMP_ERR_NOERROR; + switch (val->var.subs[sub - 1]) { + case LEAF_dot1dTpFdbAddress: + ret = string_get(val, te->tp_addr, ETHER_ADDR_LEN); + break; + case LEAF_dot1dTpFdbPort : + val->v.integer = te->port_no; + break; + case LEAF_dot1dTpFdbStatus: + val->v.integer = te->status; + break; + } + + return (ret); +} + +/* + * Private BEGEMOT-BRIDGE-MIB specifics. + */ + +/* + * Construct the SNMP index from the bridge interface name + * and the address DST Mac. + */ +static int +bridge_addrs_begemot_index_append(struct asn_oid *oid, uint sub, + const struct tp_entry *te) +{ + uint i, n_len; + const char *b_name; + + if ((b_name = bridge_if_find_name(te->sysindex)) == NULL) + return (-1); + + n_len = strlen(b_name); + oid->len = sub++; + oid->subs[oid->len++] = n_len; + + for (i = 1; i <= n_len; i++) + oid->subs[oid->len++] = b_name[i - 1]; + + oid->subs[oid->len++] = ETHER_ADDR_LEN; + for (i = 1 ; i <= ETHER_ADDR_LEN; i++) + oid->subs[oid->len++] = te->tp_addr[i - 1]; + + return (0); +} + +/* + * Find a bridge address entry by the bridge interface name + * and the address DST Mac. + */ +static struct tp_entry * +bridge_addrs_begemot_get(const struct asn_oid *oid, uint sub) +{ + uint i, n_len; + uint8_t tp_addr[ETHER_ADDR_LEN]; + char bif_name[IFNAMSIZ]; + struct bridge_if *bif; + + n_len = oid->subs[sub]; + if (oid->len - sub != n_len + ETHER_ADDR_LEN + 3 || + n_len >= IFNAMSIZ || oid->subs[sub + n_len + 1] != ETHER_ADDR_LEN) + return (NULL); + + for (i = 0; i < n_len; i++) + bif_name[i] = oid->subs[n_len + i + 1]; + bif_name[i] = '\0'; + + for (i = 1; i <= ETHER_ADDR_LEN; i++) + tp_addr[i - 1] = oid->subs[n_len + i + 1]; + + if ((bif = bridge_if_find_ifname(bif_name)) == NULL) + return (NULL); + + return (bridge_addrs_find(tp_addr, bif)); +} + +/* + * Find the next bridge address entry by the bridge interface name + * and the address DST Mac. + */ +static struct tp_entry * +bridge_addrs_begemot_getnext(const struct asn_oid *oid, uint sub) +{ + uint i, n_len; + uint8_t tp_addr[ETHER_ADDR_LEN]; + char bif_name[IFNAMSIZ]; + struct bridge_if *bif; + struct tp_entry *tp; + + if (oid->len - sub == 0) + return (bridge_addrs_first()); + + n_len = oid->subs[sub]; + if (oid->len - sub != n_len + ETHER_ADDR_LEN + 2 || + n_len >= IFNAMSIZ || oid->subs[sub + n_len + 1] != ETHER_ADDR_LEN) + return (NULL); + + for (i = 1; i <= n_len; i++) + bif_name[i - 1] = oid->subs[sub + i]; + + bif_name[i - 1] = '\0'; + + for (i = 1; i <= ETHER_ADDR_LEN; i++) + tp_addr[i - 1] = oid->subs[sub + n_len + i + 1]; + + if ((bif = bridge_if_find_ifname(bif_name)) == NULL || + (tp = bridge_addrs_find(tp_addr, bif)) == NULL) + return (NULL); + + return (bridge_addrs_next(tp)); +} + +int +op_begemot_tp_fdb(struct snmp_context *c __unused, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int ret; + struct tp_entry *te = NULL; + + if (time(NULL) - address_list_age > bridge_get_data_maxage()) + bridge_update_all_addrs(); + + switch (op) { + case SNMP_OP_GET: + if ((te = bridge_addrs_begemot_get(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((te = bridge_addrs_begemot_getnext(&val->var, + sub)) == NULL || + bridge_addrs_begemot_index_append(&val->var, + sub, te) < 0) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + ret = SNMP_ERR_NOERROR; + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeTpFdbAddress: + ret = string_get(val, te->tp_addr, ETHER_ADDR_LEN); + break; + case LEAF_begemotBridgeTpFdbPort: + val->v.integer = te->port_no; + break; + case LEAF_begemotBridgeTpFdbStatus: + val->v.integer = te->status; + break; + } + + return (ret); +} Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c 17 Nov 2006 16:30:45 -0000 @@ -0,0 +1,1369 @@ +/*- + * Copyright (c) 2006 Shteryana Shopova + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Bridge MIB implementation for SNMPd. + * Bridge interface objects. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "bridge_tree.h" +#include "bridge_snmp.h" +#include "bridge_oid.h" + +static const struct asn_oid oid_newRoot = OIDX_newRoot; +static const struct asn_oid oid_TopologyChange = OIDX_topologyChange; +static const struct asn_oid oid_begemotBrigeName = \ + OIDX_begemotBridgeBaseName; +static const struct asn_oid oid_begemotNewRoot = OIDX_begemotBridgeNewRoot; +static const struct asn_oid oid_begemotTopologyChange = \ + OIDX_begemotBridgeTopologyChange; + +TAILQ_HEAD(bridge_ifs, bridge_if); + +/* + * Free the bridge interface list. + */ +static void +bridge_ifs_free(struct bridge_ifs *headp) +{ + struct bridge_if *b; + + while ((b = TAILQ_FIRST(headp)) != NULL) { + TAILQ_REMOVE(headp, b, b_if); + free(b); + } +} + +/* + * Insert an entry in the bridge interface TAILQ. Keep the + * TAILQ sorted by the bridge's interface name. + */ +static void +bridge_ifs_insert(struct bridge_ifs *headp, + struct bridge_if *b) +{ + struct bridge_if *temp; + + if ((temp = TAILQ_FIRST(headp)) == NULL || + strcmp(b->bif_name, temp->bif_name) < 0) { + TAILQ_INSERT_HEAD(headp, b, b_if); + return; + } + + TAILQ_FOREACH(temp, headp, b_if) + if(strcmp(b->bif_name, temp->bif_name) < 0) + TAILQ_INSERT_BEFORE(temp, b, b_if); + + TAILQ_INSERT_TAIL(headp, b, b_if); +} + +/* The global bridge interface list. */ +static struct bridge_ifs bridge_ifs = TAILQ_HEAD_INITIALIZER(bridge_ifs); +static time_t bridge_list_age; + +/* + * Free the global list. + */ +void +bridge_ifs_fini(void) +{ + bridge_ifs_free(&bridge_ifs); +} + +/* + * Find a bridge interface entry by the bridge interface system index. + */ +struct bridge_if * +bridge_if_find_ifs(uint32_t sysindex) +{ + struct bridge_if *b; + + TAILQ_FOREACH(b, &bridge_ifs, b_if) + if (b->sysindex == sysindex) + return (b); + + return (NULL); +} + +/* + * Find a bridge interface entry by the bridge interface name. + */ +struct bridge_if * +bridge_if_find_ifname(const char *b_name) +{ + struct bridge_if *b; + + TAILQ_FOREACH(b, &bridge_ifs, b_if) + if (strcmp(b_name, b->bif_name) == 0) + return (b); + + return (NULL); +} + +/* + * Find a bridge name by the bridge interface system index. + */ +const char * +bridge_if_find_name(uint32_t sysindex) +{ + struct bridge_if *b; + + TAILQ_FOREACH(b, &bridge_ifs, b_if) + if (b->sysindex == sysindex) + return (b->bif_name); + + return (NULL); +} + +/* + * Given two bridge interfaces' system indexes, find their + * corresponding names and return the result of the name + * comparison. Returns: + * error : -2 + * i1 < i2 : -1 + * i1 > i2 : +1 + * i1 = i2 : 0 + */ +int +bridge_compare_sysidx(uint32_t i1, uint32_t i2) +{ + int c; + const char *b1, *b2; + + if (i1 == i2) + return (0); + + if ((b1 = bridge_if_find_name(i1)) == NULL) { + syslog(LOG_ERR, "Bridge interface %d does not exist", i1); + return (-2); + } + + if ((b2 = bridge_if_find_name(i2)) == NULL) { + syslog(LOG_ERR, "Bridge interface %d does not exist", i2); + return (-2); + } + + if ((c = strcmp(b1, b2)) < 0) + return (-1); + else if (c > 0) + return (1); + + return (0); +} + +/* + * Fetch the first bridge interface from the list. + */ +struct bridge_if * +bridge_first_bif(void) +{ + return (TAILQ_FIRST(&bridge_ifs)); +} + +/* + * Fetch the next bridge interface from the list. + */ +struct bridge_if * +bridge_next_bif(struct bridge_if *b_pr) +{ + return (TAILQ_NEXT(b_pr, b_if)); +} + +/* + * Create a new entry for a bridge interface and insert + * it in the list. + */ +static struct bridge_if * +bridge_new_bif(const char *bif_n, uint32_t sysindex, const u_char *physaddr) +{ + struct bridge_if *bif; + + if ((bif = (struct bridge_if *) malloc(sizeof(*bif)))== NULL) { + syslog(LOG_ERR, "bridge new interface failed: %s", + strerror(errno)); + return (NULL); + } + + bzero(bif, sizeof(struct bridge_if)); + strlcpy(bif->bif_name, bif_n, IFNAMSIZ); + bcopy(physaddr, bif->br_addr.octet, ETHER_ADDR_LEN); + bif->sysindex = sysindex; + bif->br_type = BaseType_transparent_only; + /* 1 - all bridges default hold time * 100 - centi-seconds */ + bif->hold_time = 1 * 100; + bif->prot_spec = dot1dStpProtocolSpecification_ieee8021d; + bridge_ifs_insert(&bridge_ifs, bif); + + return (bif); +} + +/* + * Remove a bridge interface from the list, freeing all it's ports + * and address entries. + */ +void +bridge_remove_bif(struct bridge_if *bif) +{ + bridge_members_free(bif); + bridge_addrs_free(bif); + TAILQ_REMOVE(&bridge_ifs, bif, b_if); + free(bif); +} + + +/* + * Prepare the variable (bridge interface name) for the private + * begemot notifications. + */ +static struct snmp_value* +bridge_basename_var(struct bridge_if *bif, struct snmp_value* b_val) +{ + uint i; + + b_val->var = oid_begemotBrigeName; + b_val->var.subs[b_val->var.len++] = strlen(bif->bif_name); + + if ((b_val->v.octetstring.octets = (u_char *) + malloc(strlen(bif->bif_name))) == NULL) + return (NULL); + + for (i = 0; i < strlen(bif->bif_name); i++) + b_val->var.subs[b_val->var.len++] = bif->bif_name[i]; + + b_val->v.octetstring.len = strlen(bif->bif_name); + bcopy(bif->bif_name, b_val->v.octetstring.octets, + strlen(bif->bif_name)); + b_val->syntax = SNMP_SYNTAX_OCTETSTRING; + + return (b_val); +} + +/* + * Compare the values of the old and the new root port and + * send a new root notification, if they are not matching. + */ +static void +bridge_new_root(struct bridge_if *bif) +{ + struct snmp_value bif_idx; + + if (bridge_get_default() == bif) + snmp_send_trap(&oid_newRoot, (struct snmp_value *) NULL); + + if (bridge_basename_var(bif, &bif_idx) == NULL) + return; + + snmp_send_trap(&oid_begemotTopologyChange, + &bif_idx, (struct snmp_value *) NULL); +} + +/* + * Compare the new and old topology change times and send a + * topology change notification if necessary. + */ +static void +bridge_top_change(struct bridge_if *bif) +{ + struct snmp_value bif_idx; + + if (bridge_get_default() == bif) + snmp_send_trap(&oid_TopologyChange, + (struct snmp_value *) NULL); + + if (bridge_basename_var(bif, &bif_idx) == NULL) + return; + + snmp_send_trap(&oid_begemotNewRoot, + &bif_idx, (struct snmp_value *) NULL); +} + +static int +bridge_if_create(const char* b_name, int8_t up) +{ + if (bridge_create(b_name) < 0) + return (-1); + + if (up == 1 && (bridge_set_if_up(b_name, 1) < 0)) + return (-1); + + /* + * Do not create a new bridge entry here - + * wait until the mibII module notifies us. + */ + return (0); +} + +static int +bridge_if_destroy(struct bridge_if *bif) +{ + if (bridge_destroy(bif->bif_name) < 0) + return (-1); + + bridge_remove_bif(bif); + + return (0); +} + +/* + * Calculate the timeticks since the last topology change. + */ +static int +bridge_get_time_since_tc(struct bridge_if *bif, uint32_t *ticks) +{ + struct timeval ct; + + if (gettimeofday(&ct, NULL) < 0) { + syslog(LOG_ERR, "bridge get time since last TC:" + "getttimeofday failed: %s", strerror(errno)); + return (-1); + } + + if (ct.tv_usec - bif->last_tc_time.tv_usec < 0) { + ct.tv_sec -= 1; + ct.tv_usec += 1000000; + } + + ct.tv_sec -= bif->last_tc_time.tv_sec; + ct.tv_usec -= bif->last_tc_time.tv_usec; + + *ticks = ct.tv_sec * 100 + ct.tv_usec/10000; + + return (0); +} + +/* + * Update the info we have for a single bridge interface. + * Return: + * 1, if successful + * 0, if the interface was deleted + * -1, error occured while fetching the info from the kernel. + */ +static int +bridge_update_bif(struct bridge_if *bif) +{ + struct mibif *ifp; + + /* Walk through the mibII interface list. */ + for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) + if (strcmp(ifp->name, bif->bif_name) == 0) + break; + + if (ifp == NULL) { + /* Ops, we do not exist anymore. */ + bridge_remove_bif(bif); + return (0); + } + + if (ifp->physaddr != NULL ) + bcopy(ifp->physaddr, bif->br_addr.octet, ETHER_ADDR_LEN); + else + bridge_get_basemac(bif->bif_name, bif->br_addr.octet); + + if (ifp->mib.ifmd_flags & IFF_RUNNING) + bif->if_status = RowStatus_active; + else + bif->if_status = RowStatus_notInService; + + switch (bridge_getinfo_bif(bif)) { + case 2: + bridge_new_root(bif); + break; + case 1: + bridge_top_change(bif); + break; + case -1: + bridge_remove_bif(bif); + return (-1); + default: + break; + } + + /* + * The number of ports is accessible via SNMP - + * update the ports each time the bridge interface data + * is refreshed too. + */ + bif->num_ports = bridge_update_memif(bif); + bif->entry_age = time(NULL); + + return (1); +} + +/* + * Update all bridge interfaces' ports only - + * make sure each bridge interface exists first. + */ +void +bridge_update_all_ports(void) +{ + struct mibif *ifp; + struct bridge_if *bif, *t_bif; + + for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { + t_bif = bridge_next_bif(bif); + + for (ifp = mib_first_if(); ifp != NULL; + ifp = mib_next_if(ifp)) + if (strcmp(ifp->name, bif->bif_name) == 0) + break; + + if (ifp != NULL) + bif->num_ports = bridge_update_memif(bif); + else /* Ops, we do not exist anymore. */ + bridge_remove_bif(bif); + } + + bridge_ports_update_listage(); +} + +/* + * Update all addresses only. + */ +void +bridge_update_all_addrs(void) +{ + struct mibif *ifp; + struct bridge_if *bif, *t_bif; + + for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { + t_bif = bridge_next_bif(bif); + + for (ifp = mib_first_if(); ifp != NULL; + ifp = mib_next_if(ifp)) + if (strcmp(ifp->name, bif->bif_name) == 0) + break; + + if (ifp != NULL) + bif->num_addrs = bridge_update_addrs(bif); + else /* Ops, we don't exist anymore. */ + bridge_remove_bif(bif); + } + + bridge_addrs_update_listage(); +} + +/* + * Update only the bridge interfaces' data - skip addresses. + */ +void +bridge_update_all_ifs(void) +{ + struct bridge_if *bif, *t_bif; + + for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { + t_bif = bridge_next_bif(bif); + bridge_update_bif(bif); + } + + bridge_ports_update_listage(); + bridge_list_age = time(NULL); +} + +/* + * Update all info we have for all bridges. + */ +void +bridge_update_all(void *arg __unused) +{ + struct bridge_if *bif, *t_bif; + + for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) { + t_bif = bridge_next_bif(bif); + if (bridge_update_bif(bif) <= 0) + continue; + + /* Update our learnt addresses. */ + bif->num_addrs = bridge_update_addrs(bif); + } + + bridge_list_age = time(NULL); + bridge_ports_update_listage(); + bridge_addrs_update_listage(); +} + +/* + * Callback for polling our last topology change time - + * check whether we are root or whether a TC was detected once every + * 30 seconds, so that we can send the newRoot and TopologyChange traps + * on time. The rest of the data is polled only once every 5 min. + */ +void +bridge_update_tc_time(void *arg __unused) +{ + struct bridge_if *bif; + struct mibif *ifp; + + TAILQ_FOREACH(bif, &bridge_ifs, b_if) { + /* Walk through the mibII interface list. */ + for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) + if (strcmp(ifp->name, bif->bif_name) == 0) + break; + + if (ifp == NULL) { + bridge_remove_bif(bif); + continue; + } + + switch (bridge_get_op_param(bif)) { + case 2: + bridge_new_root(bif); + break; + case 1: + bridge_top_change(bif); + break; + } + } +} + +/* + * Callback for handling new bridge interface creation. + */ +int +bridge_attach_newif(struct mibif *ifp) +{ + u_char *p_mac, mac[ETHER_ADDR_LEN]; + struct bridge_if *bif; + + if (ifp->mib.ifmd_data.ifi_type != IFT_BRIDGE) + return (0); + + /* Make sure it does not exist in our list. */ + TAILQ_FOREACH(bif, &bridge_ifs, b_if) + if(strcmp(bif->bif_name, ifp->name) == 0) { + syslog(LOG_ERR, "bridge interface %s already " + "in list", bif->bif_name); + return (-1); + } + + if ((p_mac = ifp->physaddr) == NULL && + (p_mac = bridge_get_basemac(ifp->name, mac)) == NULL) { + syslog(LOG_ERR, "bridge attach new %s failed - " + "no bridge mac address", ifp->name); + return (-1); + } + + if ((bif = bridge_new_bif(ifp->name, ifp->sysindex, p_mac)) == NULL) + return (-1); + + if (ifp->mib.ifmd_flags & IFF_RUNNING) + bif->if_status = RowStatus_active; + else + bif->if_status = RowStatus_notInService; + + /* Skip sending notifications if the interface was just created. */ + if (bridge_getinfo_bif(bif) < 0 || + (bif->num_ports = bridge_getinfo_bif_ports(bif)) < 0 || + (bif->num_addrs = bridge_getinfo_bif_addrs(bif)) < 0) { + bridge_remove_bif(bif); + return (-1); + } + + /* Check whether we are the default bridge interface. */ + if (strcmp(ifp->name, bridge_get_default_name()) == 0) + bridge_set_default(bif); + + return (0); +} + +void +bridge_ifs_dump(void) +{ + struct bridge_if *bif; + + for (bif = bridge_first_bif(); bif != NULL; + bif = bridge_next_bif(bif)) { + syslog(LOG_ERR, "Bridge %s, index - %d", bif->bif_name, + bif->sysindex); + bridge_ports_dump(bif); + bridge_addrs_dump(bif); + } +} + +/* + * RFC4188 specifics. + */ +int +op_dot1d_base(struct snmp_context *ctx __unused, struct snmp_value *value, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int ret; + struct bridge_if *bif; + + if ((bif = bridge_get_default()) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && + bridge_update_bif(bif) <= 0) /* It was just deleted. */ + return (SNMP_ERR_NOSUCHNAME); + + ret = SNMP_ERR_NOERROR; + + switch (op) { + case SNMP_OP_GET: + switch (value->var.subs[sub - 1]) { + case LEAF_dot1dBaseBridgeAddress: + ret = string_get(value, bif->br_addr.octet, + ETHER_ADDR_LEN); + break; + case LEAF_dot1dBaseNumPorts: + value->v.integer = bif->num_ports; + break; + case LEAF_dot1dBaseType: + value->v.integer = bif->br_type; + break; + abort(); + } + break; + + case SNMP_OP_SET: + ret = SNMP_ERR_NOT_WRITEABLE; + break; + + case SNMP_OP_GETNEXT: + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + return (ret); +} + +int +op_dot1d_stp(struct snmp_context *ctx, struct snmp_value *value, + uint sub, uint iidx __unused, enum snmp_op op) +{ + struct bridge_if *bif; + + if ((bif = bridge_get_default()) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && + bridge_update_bif(bif) <= 0) /* It was just deleted. */ + return (SNMP_ERR_NOSUCHNAME); + + switch (op) { + case SNMP_OP_GET: + switch (value->var.subs[sub - 1]) { + case LEAF_dot1dStpProtocolSpecification: + value->v.integer = bif->prot_spec; + break; + + case LEAF_dot1dStpPriority: + value->v.integer = bif->priority; + break; + + case LEAF_dot1dStpTimeSinceTopologyChange: + if (bridge_get_time_since_tc(bif, + &(value->v.uint32)) < 0) + return (SNMP_ERR_GENERR); + break; + + case LEAF_dot1dStpTopChanges: + value->v.uint32 = bif->top_changes; + break; + + case LEAF_dot1dStpDesignatedRoot: + return (string_get(value, bif->design_root, + SNMP_BRIDGE_ID_LEN)); + + case LEAF_dot1dStpRootCost: + value->v.integer = bif->root_cost; + break; + + case LEAF_dot1dStpRootPort: + value->v.integer = bif->root_port; + break; + + case LEAF_dot1dStpMaxAge: + value->v.integer = bif->max_age; + break; + + case LEAF_dot1dStpHelloTime: + value->v.integer = bif->hello_time; + break; + + case LEAF_dot1dStpHoldTime: + value->v.integer = bif->hold_time; + break; + + case LEAF_dot1dStpForwardDelay: + value->v.integer = bif->fwd_delay; + break; + + case LEAF_dot1dStpBridgeMaxAge: + value->v.integer = bif->bridge_max_age; + break; + + case LEAF_dot1dStpBridgeHelloTime: + value->v.integer = bif->bridge_hello_time; + break; + + case LEAF_dot1dStpBridgeForwardDelay: + value->v.integer = bif->bridge_fwd_delay; + break; + } + + return (SNMP_ERR_NOERROR); + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_SET: + switch (value->var.subs[sub - 1]) { + case LEAF_dot1dStpPriority: + ctx->scratch->int1 = bif->priority; + if (bridge_set_priority(bif, value->v.integer) < 0) + return (SNMP_ERR_GENERR); + break; + + case LEAF_dot1dStpBridgeMaxAge: + ctx->scratch->int1 = bif->bridge_max_age; + if (bridge_set_maxage(bif, value->v.integer) < 0) + return (SNMP_ERR_GENERR); + break; + + case LEAF_dot1dStpBridgeHelloTime: + ctx->scratch->int1 = bif->bridge_hello_time; + if (bridge_set_hello_time(bif, value->v.integer) < 0) + return (SNMP_ERR_GENERR); + break; + + case LEAF_dot1dStpBridgeForwardDelay: + ctx->scratch->int1 = bif->bridge_fwd_delay; + if (bridge_set_forward_delay(bif, value->v.integer) < 0) + return (SNMP_ERR_GENERR); + break; + + case LEAF_dot1dStpProtocolSpecification: + case LEAF_dot1dStpTimeSinceTopologyChange: + case LEAF_dot1dStpTopChanges: + case LEAF_dot1dStpDesignatedRoot: + case LEAF_dot1dStpRootCost: + case LEAF_dot1dStpRootPort: + case LEAF_dot1dStpMaxAge: + case LEAF_dot1dStpHelloTime: + case LEAF_dot1dStpHoldTime: + case LEAF_dot1dStpForwardDelay: + return (SNMP_ERR_NOT_WRITEABLE); + } + + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + switch (value->var.subs[sub - 1]) { + case LEAF_dot1dStpPriority: + (void) bridge_set_priority(bif, ctx->scratch->int1); + break; + case LEAF_dot1dStpBridgeMaxAge: + (void) bridge_set_maxage(bif, ctx->scratch->int1); + break; + case LEAF_dot1dStpBridgeHelloTime: + (void) bridge_set_hello_time(bif, ctx->scratch->int1); + break; + case LEAF_dot1dStpBridgeForwardDelay: + (void) bridge_set_forward_delay(bif, + ctx->scratch->int1); + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + return (SNMP_ERR_NOERROR); +} + +int +op_dot1d_tp(struct snmp_context *ctx, struct snmp_value *value, + uint sub, uint iidx __unused, enum snmp_op op) +{ + struct bridge_if *bif; + + if ((bif = bridge_get_default()) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + if (time(NULL) - bif->entry_age > bridge_get_data_maxage() && + bridge_update_bif(bif) <= 0) /* It was just deleted. */ + return (SNMP_ERR_NOSUCHNAME); + + switch (op) { + case SNMP_OP_GET: + switch (value->var.subs[sub - 1]) { + case LEAF_dot1dTpLearnedEntryDiscards: + value->v.uint32 = bif->lrnt_drops; + break; + case LEAF_dot1dTpAgingTime: + value->v.integer = bif->age_time; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_SET: + if (value->var.subs[sub - 1] == LEAF_dot1dTpAgingTime) { + ctx->scratch->int1 = bif->age_time; + if (bridge_set_aging_time(bif, value->v.integer) < 0) + return (SNMP_ERR_GENERR); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + if (value->var.subs[sub - 1] == LEAF_dot1dTpAgingTime) + (void) bridge_set_aging_time(bif, ctx->scratch->int1); + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + return (SNMP_ERR_NOERROR); +} + +/* + * Private BEGEMOT-BRIDGE-MIB specifics. + */ + +/* + * Get the bridge name from an OID index. + */ +static char * +bridge_name_index_get(const struct asn_oid *oid, uint sub, char *b_name) +{ + uint i; + + if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) + return (NULL); + + for (i = 0; i < oid->subs[sub]; i++) + b_name[i] = oid->subs[sub + i + 1]; + b_name[i] = '\0'; + + return (b_name); +} + +static void +bridge_if_index_append(struct asn_oid *oid, uint sub, + const struct bridge_if *bif) +{ + uint i; + + oid->len = sub + strlen(bif->bif_name) + 1; + oid->subs[sub] = strlen(bif->bif_name); + + for (i = 1; i <= strlen(bif->bif_name); i++) + oid->subs[sub + i] = bif->bif_name[i - 1]; +} + +static struct bridge_if * +bridge_if_index_get(const struct asn_oid *oid, uint sub) +{ + uint i; + char bif_name[IFNAMSIZ]; + + if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) + return (NULL); + + for (i = 0; i < oid->subs[sub]; i++) + bif_name[i] = oid->subs[sub + i + 1]; + bif_name[i] = '\0'; + + return (bridge_if_find_ifname(bif_name)); +} + +static struct bridge_if * +bridge_if_index_getnext(const struct asn_oid *oid, uint sub) +{ + uint i; + char bif_name[IFNAMSIZ]; + struct bridge_if *bif; + + if (oid->len - sub == 0) + return (bridge_first_bif()); + + if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ) + return (NULL); + + for (i = 0; i < oid->subs[sub]; i++) + bif_name[i] = oid->subs[sub + i + 1]; + bif_name[i] = '\0'; + + if ((bif = bridge_if_find_ifname(bif_name)) == NULL) + return (NULL); + + return (bridge_next_bif(bif)); +} + +static int +bridge_set_if_status(struct snmp_context *ctx, + struct snmp_value *val, uint sub) +{ + struct bridge_if *bif; + char bif_name[IFNAMSIZ]; + + bif = bridge_if_index_get(&val->var, sub); + + switch (val->v.integer) { + case RowStatus_active: + if (bif == NULL) + return (SNMP_ERR_INCONS_VALUE); + + ctx->scratch->int1 = bif->if_status; + + switch (bif->if_status) { + case RowStatus_active: + return (SNMP_ERR_NOERROR); + case RowStatus_notInService: + if (bridge_set_if_up(bif->bif_name, 1) < 0) + return (SNMP_ERR_GENERR); + return (SNMP_ERR_NOERROR); + default: + break; + } + return (SNMP_ERR_INCONS_VALUE); + + case RowStatus_notInService: + if (bif == NULL) + return (SNMP_ERR_INCONS_VALUE); + + ctx->scratch->int1 = bif->if_status; + + switch (bif->if_status) { + case RowStatus_active: + if (bridge_set_if_up(bif->bif_name, 1) < 0) + return (SNMP_ERR_GENERR); + return (SNMP_ERR_NOERROR); + case RowStatus_notInService: + return (SNMP_ERR_NOERROR); + default: + break; + } + return (SNMP_ERR_INCONS_VALUE); + + case RowStatus_notReady: + return (SNMP_ERR_INCONS_VALUE); + + case RowStatus_createAndGo: + if (bif != NULL) + return (SNMP_ERR_INCONS_VALUE); + + ctx->scratch->int1 = RowStatus_destroy; + + if (bridge_name_index_get(&val->var, sub, bif_name) == NULL) + return (SNMP_ERR_BADVALUE); + if (bridge_if_create(bif_name, 1) < 0) + return (SNMP_ERR_GENERR); + return (SNMP_ERR_NOERROR); + + case RowStatus_createAndWait: + if (bif != NULL) + return (SNMP_ERR_INCONS_VALUE); + + if (bridge_name_index_get(&val->var, sub, bif_name) == NULL) + return (SNMP_ERR_BADVALUE); + + ctx->scratch->int1 = RowStatus_destroy; + + if (bridge_if_create(bif_name, 0) < 0) + return (SNMP_ERR_GENERR); + return (SNMP_ERR_NOERROR); + + case RowStatus_destroy: + if (bif == NULL) + return (SNMP_ERR_NOSUCHNAME); + + ctx->scratch->int1 = bif->if_status; + bif->if_status = RowStatus_destroy; + } + + return (SNMP_ERR_NOERROR); +} + +static int +bridge_rollback_if_status(struct snmp_context *ctx, + struct snmp_value *val, uint sub) +{ + struct bridge_if *bif; + + if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + + switch (ctx->scratch->int1) { + case RowStatus_destroy: + bridge_if_destroy(bif); + return (SNMP_ERR_NOERROR); + + case RowStatus_notInService: + if (bif->if_status != ctx->scratch->int1) + bridge_set_if_up(bif->bif_name, 0); + bif->if_status = RowStatus_notInService; + return (SNMP_ERR_NOERROR); + + case RowStatus_active: + if (bif->if_status != ctx->scratch->int1) + bridge_set_if_up(bif->bif_name, 1); + bif->if_status = RowStatus_active; + return (SNMP_ERR_NOERROR); + } + + abort(); +} + +static int +bridge_commit_if_status(struct snmp_value *val, uint sub) +{ + struct bridge_if *bif; + + if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + + if (bif->if_status == RowStatus_destroy && + bridge_if_destroy(bif) < 0) + return (SNMP_ERR_COMMIT_FAILED); + + return (SNMP_ERR_NOERROR); +} + +int +op_begemot_base_bridge(struct snmp_context *ctx, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int ret; + struct bridge_if *bif = NULL; + + if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) + bridge_update_all_ifs(); + + switch (op) { + case SNMP_OP_GET: + if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + bridge_if_index_append(&val->var, sub, bif); + break; + + case SNMP_OP_SET: + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeBaseStatus: + return (bridge_set_if_status(ctx, val, sub)); + case LEAF_begemotBridgeBaseName: + case LEAF_begemotBridgeBaseAddress: + case LEAF_begemotBridgeBaseNumPorts: + case LEAF_begemotBridgeBaseType: + return (SNMP_ERR_NOT_WRITEABLE); + } + abort(); + + case SNMP_OP_ROLLBACK: + return (bridge_rollback_if_status(ctx, val, sub)); + case SNMP_OP_COMMIT: + return (bridge_commit_if_status(val, sub)); + } + + ret = SNMP_ERR_NOERROR; + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeBaseName: + ret = string_get(val, bif->bif_name, -1); + break; + + case LEAF_begemotBridgeBaseAddress: + ret = string_get(val, bif->br_addr.octet, ETHER_ADDR_LEN); + break; + + case LEAF_begemotBridgeBaseNumPorts: + val->v.integer = bif->num_ports; + break; + + case LEAF_begemotBridgeBaseType: + val->v.integer = bif->br_type; + break; + + case LEAF_begemotBridgeBaseStatus: + val->v.integer = bif->if_status; + break; + } + + return (ret); +} + +int +op_begemot_stp(struct snmp_context *ctx, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int ret = SNMP_ERR_NOERROR; /* Make the compiler happy. */ + struct bridge_if *bif = NULL; + + if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) + bridge_update_all_ifs(); + + switch (op) { + case SNMP_OP_GET: + if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + bridge_if_index_append(&val->var, sub, bif); + break; + + case SNMP_OP_SET: + if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeStpPriority: + ctx->scratch->int1 = bif->priority; + ret = bridge_set_priority(bif, val->v.integer); + break; + + case LEAF_begemotBridgeStpBridgeMaxAge: + ctx->scratch->int1 = bif->bridge_max_age; + ret = bridge_set_maxage(bif, val->v.integer); + break; + + case LEAF_begemotBridgeStpBridgeHelloTime: + ctx->scratch->int1 = bif->bridge_hello_time; + ret = bridge_set_hello_time(bif, val->v.integer); + break; + + case LEAF_begemotBridgeStpBridgeForwardDelay: + ctx->scratch->int1 = bif->bridge_fwd_delay; + ret = bridge_set_forward_delay(bif, val->v.integer); + break; + + case LEAF_begemotBridgeStpProtocolSpecification: + case LEAF_begemotBridgeStpTimeSinceTopologyChange: + case LEAF_begemotBridgeStpTopChanges: + case LEAF_begemotBridgeStpDesignatedRoot: + case LEAF_begemotBridgeStpRootCost: + case LEAF_begemotBridgeStpRootPort: + case LEAF_begemotBridgeStpMaxAge: + case LEAF_begemotBridgeStpHelloTime: + case LEAF_begemotBridgeStpHoldTime: + case LEAF_begemotBridgeStpForwardDelay: + return (SNMP_ERR_NOT_WRITEABLE); + } + + if (ret == 0) + return (SNMP_ERR_NOERROR); + else if (ret == -2) + return (SNMP_ERR_WRONG_VALUE); + return (SNMP_ERR_GENERR); + + case SNMP_OP_ROLLBACK: + if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeStpPriority: + bridge_set_priority(bif, ctx->scratch->int1); + break; + + case LEAF_begemotBridgeStpBridgeMaxAge: + bridge_set_maxage(bif, ctx->scratch->int1); + break; + + case LEAF_begemotBridgeStpBridgeHelloTime: + bridge_set_hello_time(bif, ctx->scratch->int1); + break; + + case LEAF_begemotBridgeStpBridgeForwardDelay: + bridge_set_forward_delay(bif, ctx->scratch->int1); + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeStpProtocolSpecification: + val->v.integer = bif->prot_spec; + break; + + case LEAF_begemotBridgeStpPriority: + val->v.integer = bif->priority; + break; + + case LEAF_begemotBridgeStpTimeSinceTopologyChange: + if (bridge_get_time_since_tc(bif, &(val->v.uint32)) < 0) + return (SNMP_ERR_GENERR); + break; + + case LEAF_begemotBridgeStpTopChanges: + val->v.uint32 = bif->top_changes; + break; + + case LEAF_begemotBridgeStpDesignatedRoot: + ret = string_get(val, bif->design_root, SNMP_BRIDGE_ID_LEN); + break; + + case LEAF_begemotBridgeStpRootCost: + val->v.integer = bif->root_cost; + break; + + case LEAF_begemotBridgeStpRootPort: + val->v.integer = bif->root_port; + break; + + case LEAF_begemotBridgeStpMaxAge: + val->v.integer = bif->max_age; + break; + + case LEAF_begemotBridgeStpHelloTime: + val->v.integer = bif->hello_time; + break; + + case LEAF_begemotBridgeStpHoldTime: + val->v.integer = bif->hold_time; + break; + + case LEAF_begemotBridgeStpForwardDelay: + val->v.integer = bif->fwd_delay; + break; + + case LEAF_begemotBridgeStpBridgeMaxAge: + val->v.integer = bif->bridge_max_age; + break; + + case LEAF_begemotBridgeStpBridgeHelloTime: + val->v.integer = bif->bridge_hello_time; + break; + + case LEAF_begemotBridgeStpBridgeForwardDelay: + val->v.integer = bif->bridge_fwd_delay; + break; + } + + return (ret); +} + +int +op_begemot_tp(struct snmp_context *ctx, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + struct bridge_if *bif = NULL; + + if (time(NULL) - bridge_list_age > bridge_get_data_maxage()) + bridge_update_all_ifs(); + + switch (op) { + case SNMP_OP_GET: + if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + bridge_if_index_append(&val->var, sub, bif); + break; + + case SNMP_OP_SET: + if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeTpAgingTime: + ctx->scratch->int1 = bif->age_time; + if (bridge_set_aging_time(bif, val->v.integer) < 0) + return (SNMP_ERR_GENERR); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotBridgeTpMaxAddresses: + ctx->scratch->int1 = bif->max_addrs; + if (bridge_set_max_cache(bif, val->v.integer) < 0) + return (SNMP_ERR_GENERR); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotBridgeTpLearnedEntryDiscards: + return (SNMP_ERR_NOT_WRITEABLE); + } + abort(); + + case SNMP_OP_ROLLBACK: + if ((bif = bridge_if_index_get(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeTpAgingTime: + bridge_set_aging_time(bif, ctx->scratch->int1); + break; + + case LEAF_begemotBridgeTpMaxAddresses: + bridge_set_max_cache(bif, ctx->scratch->int1); + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeTpLearnedEntryDiscards: + val->v.uint32 = bif->lrnt_drops; + break; + + case LEAF_begemotBridgeTpAgingTime: + val->v.integer = bif->age_time; + break; + + case LEAF_begemotBridgeTpMaxAddresses: + val->v.integer = bif->max_addrs; + break; + } + + return (SNMP_ERR_NOERROR); +} Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_pf.c =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_pf.c diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_pf.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_pf.c 17 Nov 2006 16:30:45 -0000 @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 2006 Shteryana Shopova + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Bridge MIB implementation for SNMPd. + * Bridge pfil controls. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "bridge_tree.h" +#include "bridge_snmp.h" + +static int +val2snmp_truth(uint8_t val) +{ + if (val == 0) + return (2); + + return (1); +} + +static int +snmp_truth2val(int32_t truth) +{ + if (truth == 2) + return (0); + else if (truth == 1) + return (1); + + return (-1); +} + +int +op_begemot_bridge_pf(struct snmp_context *ctx, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int k_val; + + if (val->var.subs[sub - 1] > LEAF_begemotBridgeLayer2PfStatus) + return (SNMP_ERR_NOSUCHNAME); + + switch (op) { + case SNMP_OP_GETNEXT: + abort(); + case SNMP_OP_ROLLBACK: + bridge_do_pfctl(val->var.subs[sub - 1] - 1, + op, &(ctx->scratch->int1)); + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + ctx->scratch->int1 = + bridge_get_pfval(val->var.subs[sub - 1]); + + if ((k_val = snmp_truth2val(val->v.integer)) < 0) + return (SNMP_ERR_BADVALUE); + + case SNMP_OP_GET: + break; + } + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgePfilStatus: + case LEAF_begemotBridgePfilMembers: + case LEAF_begemotBridgePfilIpOnly: + case LEAF_begemotBridgeLayer2PfStatus: + if (bridge_do_pfctl(val->var.subs[sub - 1] - 1, + op, &k_val) < 0) + return (SNMP_ERR_GENERR); + val->v.integer = val2snmp_truth(k_val); + break; + abort(); + } + + return (SNMP_ERR_NOERROR); +} Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c 17 Nov 2006 16:30:46 -0000 @@ -0,0 +1,1152 @@ +/*- + * Copyright (c) 2006 Shteryana Shopova + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Bridge MIB implementation for SNMPd. + * Bridge ports. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bridge_tree.h" +#include "bridge_snmp.h" + +TAILQ_HEAD(bridge_ports, bridge_port); + +/* + * Free the bridge base ports list. + */ +static void +bridge_ports_free(struct bridge_ports *headp) +{ + struct bridge_port *bp; + + while ((bp = TAILQ_FIRST(headp)) != NULL) { + TAILQ_REMOVE(headp, bp, b_p); + free(bp); + } +} + +/* + * Free the bridge base ports from the base ports list, + * members of a specified bridge interface only. + */ +static void +bridge_port_memif_free(struct bridge_ports *headp, + struct bridge_if *bif) +{ + struct bridge_port *bp; + + while (bif->f_bp != NULL && bif->sysindex == bif->f_bp->sysindex) { + bp = TAILQ_NEXT(bif->f_bp, b_p); + TAILQ_REMOVE(headp, bif->f_bp, b_p); + free(bif->f_bp); + bif->f_bp = bp; + } +} + +/* + * Insert a port entry in the base port TAILQ starting to search + * for its place from the position of the first bridge port for the bridge + * interface. Update the first bridge port if neccessary. + */ +static void +bridge_port_insert_at(struct bridge_ports *headp, + struct bridge_port *bp, struct bridge_port **f_bp) +{ + struct bridge_port *t1; + + assert(f_bp != NULL); + + for (t1 = *f_bp; + t1 != NULL && bp->sysindex == t1->sysindex; + t1 = TAILQ_NEXT(t1, b_p)) { + if (bp->if_idx < t1->if_idx) { + TAILQ_INSERT_BEFORE(t1, bp, b_p); + if (*f_bp == t1) + *f_bp = bp; + return; + } + } + + /* + * Handle the case when our first port was actually the + * last element of the TAILQ. + */ + if (t1 == NULL) + TAILQ_INSERT_TAIL(headp, bp, b_p); + else + TAILQ_INSERT_BEFORE(t1, bp, b_p); +} + +/* + * Find a port entry's possition in the ports list according + * to it's parent bridge interface name. Returns a NULL if + * we should be at the TAILQ head, otherwise the entry after + * which we should be inserted. + */ +static struct bridge_port * +bridge_port_find_pos(struct bridge_ports *headp, uint32_t b_idx) +{ + uint32_t t_idx; + struct bridge_port *t1; + + if ((t1 = TAILQ_FIRST(headp)) == NULL || + bridge_compare_sysidx(b_idx, t1->sysindex) < 0) + return (NULL); + + t_idx = t1->sysindex; + + for (t1 = TAILQ_NEXT(t1, b_p); t1 != NULL; t1 = TAILQ_NEXT(t1, b_p)) { + if (t1->sysindex != t_idx) { + if (bridge_compare_sysidx(b_idx, t1->sysindex) < 0) + return (TAILQ_PREV(t1, bridge_ports, b_p)); + else + t_idx = t1->sysindex; + } + } + + if (t1 == NULL) + t1 = TAILQ_LAST(headp, bridge_ports); + + return (t1); +} + +/* + * Insert a bridge member interface in the ports TAILQ. + */ +static void +bridge_port_memif_insert(struct bridge_ports *headp, + struct bridge_port *bp, struct bridge_port **f_bp) +{ + struct bridge_port *temp; + + if (*f_bp != NULL) + bridge_port_insert_at(headp, bp, f_bp); + else { + temp = bridge_port_find_pos(headp, bp->sysindex); + + if (temp == NULL) + TAILQ_INSERT_HEAD(headp, bp, b_p); + else + TAILQ_INSERT_AFTER(headp, temp, bp, b_p); + *f_bp = bp; + } +} + +/* The global ports list. */ +static struct bridge_ports bridge_ports = TAILQ_HEAD_INITIALIZER(bridge_ports); +static time_t ports_list_age; + +void +bridge_ports_update_listage(void) +{ + ports_list_age = time(NULL); +} + +void +bridge_ports_fini(void) +{ + bridge_ports_free(&bridge_ports); +} + +void +bridge_members_free(struct bridge_if *bif) +{ + bridge_port_memif_free(&bridge_ports, bif); +} + +/* + * Find the first port in the ports list. + */ +static struct bridge_port * +bridge_port_first(void) +{ + return (TAILQ_FIRST(&bridge_ports)); +} + +/* + * Find the next port in the ports list. + */ +static struct bridge_port * +bridge_port_next(struct bridge_port *bp) +{ + return (TAILQ_NEXT(bp, b_p)); +} + +/* + * Find the first member of the specified bridge interface. + */ +struct bridge_port * +bridge_port_bif_first(struct bridge_if *bif) +{ + return (bif->f_bp); +} + +/* + * Find the next member of the specified bridge interface. + */ +struct bridge_port * +bridge_port_bif_next(struct bridge_port *bp) +{ + struct bridge_port *bp_next; + + if ((bp_next = TAILQ_NEXT(bp, b_p)) == NULL || + bp_next->sysindex != bp->sysindex) + return (NULL); + + return (bp_next); +} + +/* + * Remove a bridge port from the ports list. + */ +void +bridge_port_remove(struct bridge_port *bp, struct bridge_if *bif) +{ + if (bif->f_bp == bp) + bif->f_bp = bridge_port_bif_next(bp); + + TAILQ_REMOVE(&bridge_ports, bp, b_p); + free(bp); +} + +/* + * Allocate memory for a new bridge port and insert it + * in the base ports list. Return a pointer to the port's + * structure in case we want to do anything else with it. + */ +struct bridge_port * +bridge_new_port(struct mibif *mif, struct bridge_if *bif) +{ + struct bridge_port *bp; + + if ((bp = (struct bridge_port *) malloc(sizeof(*bp))) == NULL) { + syslog(LOG_ERR, "bridge new member: failed: %s", + strerror(errno)); + return (NULL); + } + + bzero(bp, sizeof(*bp)); + + bp->sysindex = bif->sysindex; + bp->if_idx = mif->index; + bp->port_no = mif->sysindex; + strlcpy(bp->p_name, mif->name, IFNAMSIZ); + bp->circuit = oid_zeroDotZero; + + bridge_port_memif_insert(&bridge_ports, bp, &(bif->f_bp)); + + return (bp); +} + +/* + * Update our info from the corresponding mibII interface info. + */ +void +bridge_port_getinfo_mibif(struct mibif *m_if, struct bridge_port *bp) +{ + bp->max_info = m_if->mib.ifmd_data.ifi_mtu; + bp->in_frames = m_if->mib.ifmd_data.ifi_ipackets; + bp->out_frames = m_if->mib.ifmd_data.ifi_opackets; + bp->in_drops = m_if->mib.ifmd_data.ifi_iqdrops; +} + +/* + * Find a port, whose SNMP's mibII ifIndex matches one of the ports, + * members of the specified bridge interface. + */ +struct bridge_port * +bridge_port_find(int32_t if_idx, struct bridge_if *bif) +{ + struct bridge_port *bp; + + for (bp = bif->f_bp; bp != NULL; bp = TAILQ_NEXT(bp, b_p)) { + if (bp->sysindex != bif->sysindex) { + bp = NULL; + break; + } + + if (bp->if_idx == if_idx) + break; + } + + return (bp); +} + +void +bridge_ports_dump(struct bridge_if *bif) +{ + struct bridge_port *bp; + + for (bp = bridge_port_bif_first(bif); bp != NULL; + bp = bridge_port_bif_next(bp)) { + syslog(LOG_ERR, "memif - %s, index - %d", + bp->p_name, bp->port_no); + } +} + +/* + * RFC4188 specifics. + */ +int +op_dot1d_base_port(struct snmp_context *c __unused, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + struct bridge_if *bif; + struct bridge_port *bp; + + if ((bif = bridge_get_default()) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && + bridge_update_memif(bif) <= 0) + return (SNMP_ERR_NOSUCHNAME); + + bp = NULL; /* Make the compiler happy. */ + switch (op) { + case SNMP_OP_GET: + if (val->var.len - sub != 1) + return (SNMP_ERR_NOSUCHNAME); + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if (val->var.len - sub == 0) { + if ((bp = bridge_port_bif_first(bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + } else { + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL || + (bp = bridge_port_bif_next(bp)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + } + val->var.len = sub + 1; + val->var.subs[sub] = bp->port_no; + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_dot1dBasePort: + val->v.integer = bp->port_no; + break; + case LEAF_dot1dBasePortIfIndex: + val->v.integer = bp->if_idx; + break; + case LEAF_dot1dBasePortCircuit: + val->v.oid = bp->circuit; + break; + case LEAF_dot1dBasePortDelayExceededDiscards: + val->v.uint32 = bp->dly_ex_drops; + break; + case LEAF_dot1dBasePortMtuExceededDiscards: + val->v.uint32 = bp->dly_mtu_drops; + break; + } + + return (SNMP_ERR_NOERROR); +} + +int +op_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int ret; + struct bridge_if *bif; + struct bridge_port *bp; + + if ((bif = bridge_get_default()) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && + bridge_update_memif(bif) <= 0) + return (SNMP_ERR_NOSUCHNAME); + + bp = NULL; /* Make the compiler happy. */ + ret = SNMP_ERR_NOERROR; + + switch (op) { + case SNMP_OP_GET: + if (val->var.len - sub != 1) + return (SNMP_ERR_NOSUCHNAME); + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if (val->var.len - sub == 0) { + if ((bp = bridge_port_bif_first(bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + } else { + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL || + (bp = bridge_port_bif_next(bp)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + } + val->var.len = sub + 1; + val->var.subs[sub] = bp->port_no; + break; + + case SNMP_OP_SET: + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + switch (val->var.subs[sub - 1]) { + case LEAF_dot1dStpPortPriority: + ctx->scratch->int1 = bp->priority; + ret = bridge_port_set_priority(bif->bif_name, bp, + val->v.integer); + break; + case LEAF_dot1dStpPortEnable: + ctx->scratch->int1 = bp->enable; + ret = bridge_port_set_stp_enable(bif->bif_name, + bp, val->v.integer); + break; + case LEAF_dot1dStpPortPathCost: + ctx->scratch->int1 = bp->path_cost; + ret = bridge_port_set_path_cost(bif->bif_name, bp, + val->v.integer); + break; + case LEAF_dot1dStpPort: + case LEAF_dot1dStpPortState: + case LEAF_dot1dStpPortDesignatedRoot: + case LEAF_dot1dStpPortDesignatedCost: + case LEAF_dot1dStpPortDesignatedBridge: + case LEAF_dot1dStpPortDesignatedPort: + case LEAF_dot1dStpPortForwardTransitions: + return (SNMP_ERR_NOT_WRITEABLE); + } + if (ret == 0) + return (SNMP_ERR_NOERROR); + else if (ret == -2) + return (SNMP_ERR_WRONG_VALUE); + return (SNMP_ERR_GENERR); + + case SNMP_OP_ROLLBACK: + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL) + return (SNMP_ERR_GENERR); + switch (val->var.subs[sub - 1]) { + case LEAF_dot1dStpPortPriority: + bridge_port_set_priority(bif->bif_name, bp, + ctx->scratch->int1); + break; + case LEAF_dot1dStpPortEnable: + bridge_port_set_stp_enable(bif->bif_name, bp, + ctx->scratch->int1); + break; + case LEAF_dot1dStpPortPathCost: + bridge_port_set_path_cost(bif->bif_name, bp, + ctx->scratch->int1); + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_dot1dStpPort: + val->v.integer = bp->port_no; + break; + case LEAF_dot1dStpPortPriority: + val->v.integer = bp->priority; + break; + case LEAF_dot1dStpPortState: + val->v.integer = bp->state; + break; + case LEAF_dot1dStpPortEnable: + val->v.integer = bp->enable; + break; + case LEAF_dot1dStpPortPathCost: + val->v.integer = bp->path_cost; + break; + case LEAF_dot1dStpPortDesignatedRoot: + ret = string_get(val, bp->design_root, + SNMP_BRIDGE_ID_LEN); + break; + case LEAF_dot1dStpPortDesignatedCost: + val->v.integer = bp->design_cost; + break; + case LEAF_dot1dStpPortDesignatedBridge: + ret = string_get(val, bp->design_bridge, + SNMP_BRIDGE_ID_LEN); + break; + case LEAF_dot1dStpPortDesignatedPort: + ret = string_get(val, bp->design_port, 2); + break; + case LEAF_dot1dStpPortForwardTransitions: + val->v.uint32 = bp->fwd_trans; + break; + } + + return (ret); +} + +int +op_dot1d_tp_port(struct snmp_context *c __unused, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + struct bridge_if *bif; + struct bridge_port *bp; + + if ((bif = bridge_get_default()) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && + bridge_update_memif(bif) <= 0) + return (SNMP_ERR_NOSUCHNAME); + + bp = NULL; /* Make the compiler happy. */ + switch (op) { + case SNMP_OP_GET: + if (val->var.len - sub != 1) + return (SNMP_ERR_NOSUCHNAME); + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if (val->var.len - sub == 0) { + if ((bp = bridge_port_bif_first(bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + } else { + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL || + (bp = bridge_port_bif_next(bp)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + } + val->var.len = sub + 1; + val->var.subs[sub] = bp->port_no; + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_dot1dTpPort: + val->v.integer = bp->port_no; + break; + case LEAF_dot1dTpPortMaxInfo: + val->v.integer = bp->max_info; + break; + case LEAF_dot1dTpPortInFrames: + val->v.uint32 = bp->in_frames; + break; + case LEAF_dot1dTpPortOutFrames: + val->v.uint32 = bp->out_frames; + break; + case LEAF_dot1dTpPortInDiscards: + val->v.uint32 = bp->in_drops; + break; + } + + return (SNMP_ERR_NOERROR); +} + +/* + * Private BEGEMOT-BRIDGE-MIB specifics. + */ + +/* + * Construct a bridge port entry index. + */ +static int +bridge_port_index_append(struct asn_oid *oid, uint sub, + const struct bridge_port *bp) +{ + uint i; + const char *b_name; + + if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) + return (-1); + + oid->len = sub + strlen(b_name) + 1 + 1; + oid->subs[sub] = strlen(b_name); + + for (i = 1; i <= strlen(b_name); i++) + oid->subs[sub + i] = b_name[i - 1]; + + oid->subs[sub + i] = bp->port_no; + + return (0); +} + +/* + * Get the port entry from an entry's index. + */ +static struct bridge_port * +bridge_port_index_get(const struct asn_oid *oid, uint sub, int8_t status) +{ + uint i; + int32_t port_no; + char bif_name[IFNAMSIZ]; + struct bridge_if *bif; + struct bridge_port *bp; + + if (oid->len - sub != oid->subs[sub] + 2 || + oid->subs[sub] >= IFNAMSIZ) + return (NULL); + + for (i = 0; i < oid->subs[sub]; i++) + bif_name[i] = oid->subs[sub + i + 1]; + bif_name[i] = '\0'; + + port_no = oid->subs[sub + i + 1]; + + if ((bif = bridge_if_find_ifname(bif_name)) == NULL) + return (NULL); + + if ((bp = bridge_port_find(port_no, bif)) == NULL || + (status == 0 && bp->status != RowStatus_active)) + return (NULL); + + return (bp); +} + +/* + * Get the next port entry from an entry's index. + */ +static struct bridge_port * +bridge_port_index_getnext(const struct asn_oid *oid, uint sub, int8_t status) +{ + uint i; + int32_t port_no; + char bif_name[IFNAMSIZ]; + struct bridge_if *bif; + struct bridge_port *bp; + + if (oid->len - sub == 0) + bp = bridge_port_first(); + else { + if (oid->len - sub != oid->subs[sub] + 2 || + oid->subs[sub] >= IFNAMSIZ) + return (NULL); + + for (i = 0; i < oid->subs[sub]; i++) + bif_name[i] = oid->subs[sub + i + 1]; + bif_name[i] = '\0'; + + port_no = oid->subs[sub + i + 1]; + + if ((bif = bridge_if_find_ifname(bif_name)) == NULL || + (bp = bridge_port_find(port_no, bif)) == NULL) + return (NULL); + + bp = bridge_port_next(bp); + } + + if (status == 1) + return (bp); + + while (bp != NULL) { + if (bp->status == RowStatus_active) + break; + bp = bridge_port_next(bp); + } + + return (bp); +} + +/* + * Read the bridge name and port index from a ASN OID structure. + */ +static int +bridge_port_index_decode(const struct asn_oid *oid, uint sub, + char *b_name, int32_t *idx) +{ + uint i; + + if (oid->len - sub != oid->subs[sub] + 2 || + oid->subs[sub] >= IFNAMSIZ) + return (-1); + + for (i = 0; i < oid->subs[sub]; i++) + b_name[i] = oid->subs[sub + i + 1]; + b_name[i] = '\0'; + + *idx = oid->subs[sub + i + 1]; + return (0); +} + +static int +bridge_port_set_status(struct snmp_context *ctx, + struct snmp_value *val, uint sub) +{ + int32_t if_idx; + char b_name[IFNAMSIZ]; + struct bridge_if *bif; + struct bridge_port *bp; + struct mibif *mif; + + if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) + return (SNMP_ERR_INCONS_VALUE); + + if ((bif = bridge_if_find_ifname(b_name)) == NULL || + (mif = mib_find_if(if_idx)) == NULL) + return (SNMP_ERR_INCONS_VALUE); + + bp = bridge_port_find(if_idx, bif); + + switch (val->v.integer) { + case RowStatus_active: + if (bp == NULL) + return (SNMP_ERR_INCONS_VALUE); + + if (bp->span_enable == 0) + return (SNMP_ERR_INCONS_VALUE); + + ctx->scratch->int1 = bp->status; + bp->status = RowStatus_active; + break; + + case RowStatus_notInService: + if (bp == NULL || bp->span_enable == 0 || + bp->status == RowStatus_active) + return (SNMP_ERR_INCONS_VALUE); + + ctx->scratch->int1 = bp->status; + bp->status = RowStatus_notInService; + + case RowStatus_notReady: + /* FALLTHROUGH */ + case RowStatus_createAndGo: + return (SNMP_ERR_INCONS_VALUE); + + case RowStatus_createAndWait: + if (bp != NULL) + return (SNMP_ERR_INCONS_VALUE); + + if ((bp = bridge_new_port(mif, bif)) == NULL) + return (SNMP_ERR_GENERR); + + ctx->scratch->int1 = RowStatus_destroy; + bp->status = RowStatus_notReady; + break; + + case RowStatus_destroy: + if (bp == NULL) + return (SNMP_ERR_INCONS_VALUE); + + ctx->scratch->int1 = bp->status; + bp->status = RowStatus_destroy; + break; + } + + return (SNMP_ERR_NOERROR); +} + +static int +bridge_port_rollback_status(struct snmp_context *ctx, + struct snmp_value *val, uint sub) +{ + int32_t if_idx; + char b_name[IFNAMSIZ]; + struct bridge_if *bif; + struct bridge_port *bp; + + if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) + return (SNMP_ERR_GENERR); + + if ((bif = bridge_if_find_ifname(b_name)) == NULL || + (bp = bridge_port_find(if_idx, bif)) == NULL) + return (SNMP_ERR_GENERR); + + if (ctx->scratch->int1 == RowStatus_destroy) + bridge_port_remove(bp, bif); + else + bp->status = ctx->scratch->int1; + + return (SNMP_ERR_NOERROR); +} + +static int +bridge_port_commit_status(struct snmp_value *val, uint sub) +{ + int32_t if_idx; + char b_name[IFNAMSIZ]; + struct bridge_if *bif; + struct bridge_port *bp; + + if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) + return (SNMP_ERR_GENERR); + + if ((bif = bridge_if_find_ifname(b_name)) == NULL || + (bp = bridge_port_find(if_idx, bif)) == NULL) + return (SNMP_ERR_GENERR); + + switch (bp->status) { + case RowStatus_active: + if (bridge_port_addm(bp, b_name) < 0) + return (SNMP_ERR_COMMIT_FAILED); + break; + + case RowStatus_destroy: + if (bridge_port_delm(bp, b_name) < 0) + return (SNMP_ERR_COMMIT_FAILED); + bridge_port_remove(bp, bif); + break; + } + + return (SNMP_ERR_NOERROR); +} + +static int +bridge_port_set_span_enable(struct snmp_context *ctx, + struct snmp_value *val, uint sub) +{ + int32_t if_idx; + char b_name[IFNAMSIZ]; + struct bridge_if *bif; + struct bridge_port *bp; + struct mibif *mif; + + if (val->v.integer != begemotBridgeBaseSpanEnabled_enabled && + val->v.integer != begemotBridgeBaseSpanEnabled_disabled) + return (SNMP_ERR_BADVALUE); + + if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0) + return (SNMP_ERR_INCONS_VALUE); + + if ((bif = bridge_if_find_ifname(b_name)) == NULL) + return (SNMP_ERR_INCONS_VALUE); + + if ((bp = bridge_port_find(if_idx, bif)) == NULL) { + if ((mif = mib_find_if(if_idx)) == NULL) + return (SNMP_ERR_INCONS_VALUE); + + if ((bp = bridge_new_port(mif, bif)) == NULL) + return (SNMP_ERR_GENERR); + + ctx->scratch->int1 = RowStatus_destroy; + } else if (bp->status == RowStatus_active) { + return (SNMP_ERR_INCONS_VALUE); + } else { + ctx->scratch->int1 = bp->status; + } + + bp->span_enable = val->v.integer; + bp->status = RowStatus_notInService; + + return (SNMP_ERR_NOERROR); +} + +int +op_begemot_base_port(struct snmp_context *ctx, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int8_t status, which; + struct bridge_port *bp = NULL; + + if (time(NULL) - ports_list_age > bridge_get_data_maxage()) + bridge_update_all_ports(); + + which = val->var.subs[sub - 1]; + status = 0; + + switch (op) { + case SNMP_OP_GET: + if (which == LEAF_begemotBridgeBaseSpanEnabled || + which == LEAF_begemotBridgeBasePortStatus) + status = 1; + if ((bp = bridge_port_index_get(&val->var, sub, + status)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if (which == LEAF_begemotBridgeBaseSpanEnabled || + which == LEAF_begemotBridgeBasePortStatus) + status = 1; + if ((bp = bridge_port_index_getnext(&val->var, sub, + status)) == NULL || + bridge_port_index_append(&val->var, sub, bp) < 0) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + switch (which) { + case LEAF_begemotBridgeBaseSpanEnabled: + return (bridge_port_set_span_enable(ctx, val, sub)); + + case LEAF_begemotBridgeBasePortStatus: + return (bridge_port_set_status(ctx, val, sub)); + + case LEAF_begemotBridgeBasePort: + case LEAF_begemotBridgeBasePortIfIndex: + case LEAF_begemotBridgeBasePortDelayExceededDiscards: + case LEAF_begemotBridgeBasePortMtuExceededDiscards: + return (SNMP_ERR_NOT_WRITEABLE); + } + abort(); + + case SNMP_OP_ROLLBACK: + switch (which) { + case LEAF_begemotBridgeBaseSpanEnabled: + /* FALLTHROUGH */ + case LEAF_begemotBridgeBasePortStatus: + return (bridge_port_rollback_status(ctx, val, sub)); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + if (which == LEAF_begemotBridgeBasePortStatus) + return (bridge_port_commit_status(val, sub)); + + return (SNMP_ERR_NOERROR); + } + + switch (which) { + case LEAF_begemotBridgeBasePort: + val->v.integer = bp->port_no; + break; + case LEAF_begemotBridgeBasePortIfIndex: + val->v.integer = bp->if_idx; + break; + case LEAF_begemotBridgeBaseSpanEnabled: + val->v.integer = bp->span_enable; + break; + case LEAF_begemotBridgeBasePortDelayExceededDiscards: + val->v.uint32 = bp->dly_ex_drops; + break; + case LEAF_begemotBridgeBasePortMtuExceededDiscards: + val->v.uint32 = bp->dly_mtu_drops; + break; + case LEAF_begemotBridgeBasePortStatus: + val->v.integer = bp->status; + break; + } + + return (SNMP_ERR_NOERROR); +} + +int +op_begemot_stp_port(struct snmp_context *ctx, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int ret; + struct bridge_port *bp = NULL; + const char *b_name; + + if (time(NULL) - ports_list_age > bridge_get_data_maxage()) + bridge_update_all_ports(); + + switch (op) { + case SNMP_OP_GET: + if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == + NULL || bridge_port_index_append(&val->var, sub, bp) < 0) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) + return (SNMP_ERR_GENERR); + + ret = SNMP_ERR_NOERROR; + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeStpPortPriority: + ctx->scratch->int1 = bp->priority; + ret = bridge_port_set_priority(b_name, bp, + val->v.integer); + break; + case LEAF_begemotBridgeStpPortEnable: + ctx->scratch->int1 = bp->enable; + ret = bridge_port_set_stp_enable(b_name, bp, + val->v.integer); + break; + case LEAF_begemotBridgeStpPortPathCost: + ctx->scratch->int1 = bp->path_cost; + ret = bridge_port_set_path_cost(b_name, bp, + val->v.integer); + break; + case LEAF_begemotBridgeStpPort: + case LEAF_begemotBridgeStpPortState: + case LEAF_begemotBridgeStpPortDesignatedRoot: + case LEAF_begemotBridgeStpPortDesignatedCost: + case LEAF_begemotBridgeStpPortDesignatedBridge: + case LEAF_begemotBridgeStpPortDesignatedPort: + case LEAF_begemotBridgeStpPortForwardTransitions: + return (SNMP_ERR_NOT_WRITEABLE); + } + if (ret == 0) + return (SNMP_ERR_NOERROR); + else if (ret == -2) + return (SNMP_ERR_WRONG_VALUE); + return (SNMP_ERR_GENERR); + + case SNMP_OP_ROLLBACK: + if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL || + (b_name = bridge_if_find_name(bp->sysindex)) == NULL) + return (SNMP_ERR_GENERR); + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeStpPortPriority: + bridge_port_set_priority(b_name, bp, + ctx->scratch->int1); + break; + case LEAF_begemotBridgeStpPortEnable: + bridge_port_set_stp_enable(b_name, bp, + ctx->scratch->int1); + break; + case LEAF_begemotBridgeStpPortPathCost: + bridge_port_set_path_cost(b_name, bp, + ctx->scratch->int1); + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + ret = SNMP_ERR_NOERROR; + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeStpPort: + val->v.integer = bp->port_no; + break; + case LEAF_begemotBridgeStpPortPriority: + val->v.integer = bp->priority; + break; + case LEAF_begemotBridgeStpPortState: + val->v.integer = bp->state; + break; + case LEAF_begemotBridgeStpPortEnable: + val->v.integer = bp->enable; + break; + case LEAF_begemotBridgeStpPortPathCost: + val->v.integer = bp->path_cost; + break; + case LEAF_begemotBridgeStpPortDesignatedRoot: + ret = string_get(val, bp->design_root, SNMP_BRIDGE_ID_LEN); + break; + case LEAF_begemotBridgeStpPortDesignatedCost: + val->v.integer = bp->design_cost; + break; + case LEAF_begemotBridgeStpPortDesignatedBridge: + ret = string_get(val, bp->design_bridge, SNMP_BRIDGE_ID_LEN); + break; + case LEAF_begemotBridgeStpPortDesignatedPort: + ret = string_get(val, bp->design_port, 2); + break; + case LEAF_begemotBridgeStpPortForwardTransitions: + val->v.uint32 = bp->fwd_trans; + break; + } + + return (ret); +} + +int +op_begemot_tp_port(struct snmp_context *c __unused, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + struct bridge_port *bp = NULL; + + if (time(NULL) - ports_list_age > bridge_get_data_maxage()) + bridge_update_all_ports(); + + switch (op) { + case SNMP_OP_GET: + if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == + NULL || bridge_port_index_append(&val->var, sub, bp) < 0) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeTpPort: + val->v.integer = bp->port_no; + break; + case LEAF_begemotBridgeTpPortMaxInfo: + val->v.integer = bp->max_info; + break; + case LEAF_begemotBridgeTpPortInFrames: + val->v.uint32 = bp->in_frames; + break; + case LEAF_begemotBridgeTpPortOutFrames: + val->v.uint32 = bp->out_frames; + break; + case LEAF_begemotBridgeTpPortInDiscards: + val->v.uint32 = bp->in_drops; + break; + } + + return (SNMP_ERR_NOERROR); +} Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.c =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.c diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.c 17 Nov 2006 16:30:46 -0000 @@ -0,0 +1,327 @@ +/*- + * Copyright (c) 2006 Shteryana Shopova + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Bridge MIB implementation for SNMPd. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bridge_tree.h" +#include "bridge_snmp.h" +#include "bridge_oid.h" + +static struct lmodule *bridge_module; + +/* For the registration. */ +static const struct asn_oid oid_dot1Bridge = OIDX_dot1dBridge; +/* The registration. */ +static uint reg_bridge; + +/* Periodic timer for polling all bridges' data. */ +static void *bridge_data_timer; +static void *bridge_tc_timer; + +static int bridge_data_maxage = SNMP_BRIDGE_DATA_MAXAGE; +static int bridge_poll_ticks = SNMP_BRIDGE_POLL_INTERVAL * 100; +static int bridge_tc_poll_ticks = SNMP_BRIDGE_TC_POLL_INTERVAL * 100; + +/* + * Our default bridge, whose info will be visible under + * the dot1dBridge subtree and functions to set/fetch it. + */ +static char bif_default_name[IFNAMSIZ] = "bridge0"; +static struct bridge_if *bif_default; + +struct bridge_if * +bridge_get_default(void) +{ + struct mibif *ifp; + + if (bif_default != NULL) { + + /* Walk through the mibII interface list. */ + for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) + if (strcmp(ifp->name, bif_default->bif_name) == 0) + break; + + if (ifp == NULL) + bif_default = NULL; + } + + return (bif_default); +} + +void +bridge_set_default(struct bridge_if *bif) +{ + bif_default = bif; + + syslog(LOG_ERR, "Set default bridge interface to: %s", + bif == NULL ? "(none)" : bif->bif_name); +} + +const char * +bridge_get_default_name(void) +{ + return (bif_default_name); +} + +static int +bridge_set_default_name(const char *bif_name, uint len) +{ + struct bridge_if *bif; + + if (len >= IFNAMSIZ) + return (-1); + + bcopy(bif_name, bif_default_name, len); + bif_default_name[len] = '\0'; + + if ((bif = bridge_if_find_ifname(bif_default_name)) == NULL) + return (0); + + bif_default = bif; + return (1); +} + +int +bridge_get_data_maxage(void) +{ + return (bridge_data_maxage); +} + +static void +bridge_set_poll_ticks(int poll_ticks) +{ + if (bridge_data_timer != NULL) + timer_stop(bridge_data_timer); + + bridge_poll_ticks = poll_ticks; + bridge_data_timer = timer_start_repeat(bridge_poll_ticks, + bridge_poll_ticks, bridge_update_all, NULL, bridge_module); +} +/* + * The bridge module configuration via SNMP. + */ +static int +bridge_default_name_save(struct snmp_context *ctx, const char *bridge_default) +{ + if ((ctx->scratch->int1 = strlen(bridge_default)) >= IFNAMSIZ) + return (-1); + + if ((ctx->scratch->ptr1 = malloc(IFNAMSIZ)) == NULL) + return (-1); + + strncpy(ctx->scratch->ptr1, bridge_default, ctx->scratch->int1); + return (0); +} + +int +op_begemot_bridge_config(struct snmp_context *ctx, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + switch (op) { + case SNMP_OP_GET: + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeDefaultBridgeIf: + string_get(val, bridge_get_default_name(), -1); + break; + case LEAF_begemotBridgeDataUpdate: + val->v.integer = bridge_data_maxage; + break; + case LEAF_begemotBridgeDataPoll: + val->v.integer = bridge_poll_ticks / 100; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_SET: + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeDefaultBridgeIf: + /* + * Cannot use string_save() here - requires either + * a fixed-sized or var-length string - not less + * than or equal. + */ + if (bridge_default_name_save(ctx, + bridge_get_default_name()) < 0) + return (SNMP_ERR_RES_UNAVAIL); + + if (bridge_set_default_name(val->v.octetstring.octets, + val->v.octetstring.len) < 0) + return (SNMP_ERR_BADVALUE); + break; + case LEAF_begemotBridgeDataUpdate: + ctx->scratch->int1 = bridge_data_maxage; + bridge_data_maxage = val->v.integer; + break; + case LEAF_begemotBridgeDataPoll: + ctx->scratch->int1 = val->v.integer; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeDefaultBridgeIf: + bridge_set_default_name(ctx->scratch->ptr1, + ctx->scratch->int1); + free(ctx->scratch->ptr1); + break; + case LEAF_begemotBridgeDataUpdate: + bridge_data_maxage = ctx->scratch->int1; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeDefaultBridgeIf: + free(ctx->scratch->ptr1); + break; + case LEAF_begemotBridgeDataPoll: + bridge_set_poll_ticks(ctx->scratch->int1 * 100); + break; + } + return (SNMP_ERR_NOERROR); + } + + return (SNMP_ERR_NOERROR); +} + +/* + * Bridge mib module initialization hook. + * Returns 0 on success, < 0 on error. + */ +static int +bridge_init(struct lmodule * mod, int argc __unused, char *argv[] __unused) +{ + bridge_module = mod; + + if (bridge_kmod_load() < 0) + return (-1); + + if (bridge_ioctl_init() < 0) + return (-1); + + /* Register to get creation messages for bridge interfaces. */ + if (mib_register_newif(bridge_attach_newif, bridge_module)) { + syslog(LOG_ERR, "Cannot register newif function: %s", + strerror(errno)); + return (-1); + } + + return (0); +} + +/* + * Bridge mib module finalization hook. + */ +static int +bridge_fini(void) +{ + mib_unregister_newif(bridge_module); + or_unregister(reg_bridge); + + if (bridge_data_timer != NULL) { + timer_stop(bridge_data_timer); + bridge_data_timer = NULL; + } + + if (bridge_tc_timer != NULL) { + timer_stop(bridge_tc_timer); + bridge_tc_timer = NULL; + } + + bridge_ifs_fini(); + bridge_ports_fini(); + bridge_addrs_fini(); + + return (0); +} + +/* + * Bridge mib module start operation. + */ +static void +bridge_start(void) +{ + reg_bridge = or_register(&oid_dot1Bridge, + "The IETF MIB for Bridges (RFC 4188).", bridge_module); + + bridge_data_timer = timer_start_repeat(bridge_poll_ticks, + bridge_poll_ticks, bridge_update_all, NULL, bridge_module); + + bridge_tc_timer = timer_start_repeat(bridge_tc_poll_ticks, + bridge_tc_poll_ticks, bridge_update_tc_time, NULL, bridge_module); +} + +static void +bridge_dump(void) +{ + struct bridge_if *bif; + + if ((bif = bridge_get_default()) == NULL) + syslog(LOG_ERR, "Dump: no default bridge interface"); + else + syslog(LOG_ERR, "Dump: default bridge interface %s", + bif->bif_name); + + bridge_ifs_dump(); + bridge_pf_dump(); +} + +const struct snmp_module config = { + .comment = "This module implements the bridge mib (RFC 4188).", + .init = bridge_init, + .fini = bridge_fini, + .start = bridge_start, + .tree = bridge_ctree, + .dump = bridge_dump, + .tree_size = bridge_CTREE_SIZE, +}; Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.h =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.h diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.h 17 Nov 2006 16:30:46 -0000 @@ -0,0 +1,307 @@ +/*- + * Copyright (c) 2006 Shteryana Shopova + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Bridge MIB implementation for SNMPd. + * + * $FreeBSD$ + */ + +#ifndef SNMP_BRIDGE_H +#define SNMP_BRIDGE_H + +#define SNMP_BRIDGE_ID_LEN 8 + +typedef uint8_t port_id[2]; +typedef u_char bridge_id[SNMP_BRIDGE_ID_LEN]; + +#define SNMP_BRIDGE_MAX_PRIORITY 65535 + +#define SNMP_BRIDGE_MIN_AGE_TIME 10 +#define SNMP_BRIDGE_MAX_AGE_TIME 1000000 + +#define SNMP_PORT_PATHCOST_OBSOLETE 65535 + +#define SNMP_BRIDGE_DATA_MAXAGE 10 +/* By default poll kernel data every 5 minutes. */ +#define SNMP_BRIDGE_POLL_INTERVAL (5 * 60) +/* Poll for a topology change once every 30 seconds. */ +#define SNMP_BRIDGE_TC_POLL_INTERVAL 30 + +struct bridge_if *bridge_get_default(void); + +void bridge_set_default(struct bridge_if *bif); + +const char *bridge_get_default_name(void); + +int bridge_get_data_maxage(void); + +/* + * Bridge Addresses Table. + */ +struct tp_entry { + uint32_t sysindex; /* The bridge if sysindex. */ + int32_t port_no; + enum TpFdbStatus status; + uint8_t tp_addr[ETHER_ADDR_LEN]; + uint8_t flags; + TAILQ_ENTRY(tp_entry) tp_e; +}; + +/* + * Bridge ports. + * The bridge port system interface index is used for a + * port number. Transparent bridging statistics and STP + * information for a port are also contained here. + */ +struct bridge_port { + /* dot1dBase subtree objects. */ + uint32_t sysindex; /* The bridge interface sysindex. */ + int32_t port_no; /* The bridge member system index. */ + int32_t if_idx; /* SNMP ifIndex from mibII. */ + int8_t span_enable; /* Span flag set - private MIB. */ + struct asn_oid circuit; /* Unused. */ + uint32_t dly_ex_drops; /* Drops on output. */ + uint32_t dly_mtu_drops; /* MTU exceeded drops. */ + int32_t status; /* The entry status. */ + + /* dot1dStp subtree objects. */ + int32_t path_cost; + int32_t priority; + int32_t design_cost; + uint32_t fwd_trans; + char p_name[IFNAMSIZ]; /* Not in BRIDGE-MIB. */ + enum StpPortState state; + enum dot1dStpPortEnable enable; + port_id design_port; + bridge_id design_root; + bridge_id design_bridge; + + /* dot1dTp subtree objects. */ + int32_t max_info; + int32_t in_frames; + int32_t out_frames; + int32_t in_drops; + + uint8_t flags; + TAILQ_ENTRY(bridge_port) b_p; +}; + +/* + * A bridge interface. + * The system interface index of the bridge is not required neither by the + * standard BRIDGE-MIB nor by the private BEGEMOT-BRIDGE-MIB, but is used + * as key for looking up the other info for this bridge. + */ +struct bridge_if { + /* dot1dBase subtree objects. */ + uint32_t sysindex; /* The system interface index. */ + int32_t num_ports; /* Number of ports. */ + enum BaseType br_type; /* Bridge type. */ + enum RowStatus if_status; /* Bridge status. */ + char bif_name[IFNAMSIZ]; /* Bridge interface name. */ + struct ether_addr br_addr; /* Bridge address. */ + struct bridge_port *f_bp; /* This bridge's first entry + * in the base ports TAILQ. */ + /* dot1dStp subtree objects. */ + int32_t priority; + int32_t root_cost; + int32_t root_port; + int32_t max_age; /* Current max age. */ + int32_t hello_time; /* Current hello time. */ + int32_t fwd_delay; /* Current forward delay. */ + int32_t hold_time; + int32_t bridge_max_age; /* Configured max age. */ + int32_t bridge_hello_time; /* Configured hello time. */ + int32_t bridge_fwd_delay; /* Configured forward delay. */ + uint32_t top_changes; + enum dot1dStpProtocolSpecification prot_spec; + struct timeval last_tc_time; + bridge_id design_root; + + /* dot1dTp subtree objects. */ + int32_t lrnt_drops; /* Dropped addresses. */ + int32_t age_time; /* Address entry timeout. */ + int32_t num_addrs; /* Current # of addresses in cache. */ + int32_t max_addrs; /* Max # of addresses in cache. */ + struct tp_entry *f_tpa; /* This bridge's first entry in + * the tp addresses TAILQ. */ + + time_t entry_age; + time_t ports_age; + time_t addrs_age; + TAILQ_ENTRY(bridge_if) b_if; +}; + +void bridge_ifs_fini(void); + +struct bridge_if *bridge_if_find_ifs(uint32_t sysindex); + +struct bridge_if *bridge_if_find_ifname(const char *b_name); + +const char *bridge_if_find_name(uint32_t sysindex); + +int bridge_compare_sysidx(uint32_t i1, uint32_t i2); + +int bridge_attach_newif(struct mibif *ifp); + +struct bridge_if *bridge_first_bif(void); + +struct bridge_if *bridge_next_bif(struct bridge_if *b_pr); + +void bridge_remove_bif(struct bridge_if *bif); + +void bridge_update_all_ports(void); + +void bridge_update_all_addrs(void); + +void bridge_update_all_ifs(void); + +void bridge_update_all(void *arg); + +void bridge_update_tc_time(void *arg); + +void bridge_ifs_dump(void); + +/* Bridge ports. */ +void bridge_ports_update_listage(void); + +void bridge_ports_fini(void); + +void bridge_members_free(struct bridge_if *bif); + +struct bridge_port *bridge_new_port(struct mibif *mif, struct bridge_if *bif); + +void bridge_port_remove(struct bridge_port *bp, struct bridge_if *bif); + +struct bridge_port *bridge_port_bif_first(struct bridge_if *bif); + +struct bridge_port *bridge_port_bif_next(struct bridge_port *bp); + +struct bridge_port *bridge_port_find(int32_t if_idx, struct bridge_if *bif); + +void bridge_port_getinfo_mibif(struct mibif *m_if, struct bridge_port *bp); + +int bridge_getinfo_bif_ports(struct bridge_if *bif); + +int bridge_update_memif(struct bridge_if *bif); + +void bridge_ports_dump(struct bridge_if *bif); + +/* Bridge addresses. */ +void bridge_addrs_update_listage(void); + +void bridge_addrs_fini(void); + +void bridge_addrs_free(struct bridge_if *bif); + +struct tp_entry *bridge_new_addrs(uint8_t *mac, struct bridge_if *bif); + +void bridge_addrs_remove(struct tp_entry *te, struct bridge_if *bif); + +struct tp_entry *bridge_addrs_find(uint8_t *mac, struct bridge_if *bif); + +struct tp_entry *bridge_addrs_bif_first(struct bridge_if *bif); + +struct tp_entry *bridge_addrs_bif_next(struct tp_entry *te); + +int bridge_getinfo_bif_addrs(struct bridge_if *bif); + +int bridge_update_addrs(struct bridge_if *bif); + +void bridge_addrs_dump(struct bridge_if *bif); + +/* Bridge PF. */ + +void bridge_pf_dump(void); + +/* System specific. */ + +/* Open the socket for the ioctls. */ +int bridge_ioctl_init(void); + +/* Load bridge kernel module. */ +int bridge_kmod_load(void); + +/* Get the bridge interface information. */ +int bridge_getinfo_bif(struct bridge_if *bif); + +/* Get the bridge interface STP parameters. */ +int bridge_get_op_param(struct bridge_if *bif); + +/* Set the bridge priority. */ +int bridge_set_priority(struct bridge_if *bif, int32_t priority); + +/* Set the bridge max age. */ +int bridge_set_maxage(struct bridge_if *bif, int32_t max_age); + +/* Set the bridge hello time.*/ +int bridge_set_hello_time(struct bridge_if *bif, int32_t hello_time); + +/* Set the bridge forward delay.*/ +int bridge_set_forward_delay(struct bridge_if *bif, int32_t fwd_delay); + +/* Set the bridge address cache max age. */ +int bridge_set_aging_time(struct bridge_if *bif, int32_t age_time); + +/* Set the max number of entries in the bridge address cache. */ +int bridge_set_max_cache(struct bridge_if *bif, int32_t max_cache); + +/* Set the bridge interface status to up/down. */ +int bridge_set_if_up(const char* b_name, int8_t up); + +/* Create a bridge interface. */ +int bridge_create(const char *b_name); + +/* Destroy a bridge interface. */ +int bridge_destroy(const char *b_name); + +/* Fetch the bridge mac address. */ +u_char *bridge_get_basemac(const char *bif_name, u_char *mac); + +/* Set a bridge member priority. */ +int bridge_port_set_priority(const char *bif_name, struct bridge_port *bp, + int32_t priority); + +/* Set a bridge member STP-enabled flag. */ +int bridge_port_set_stp_enable(const char *bif_name, struct bridge_port *bp, + uint32_t enable); + +/* Set a bridge member STP path cost. */ +int bridge_port_set_path_cost(const char *bif_name, struct bridge_port *bp, + int32_t path_cost); + +/* Add a bridge member port. */ +int bridge_port_addm(struct bridge_port *bp, const char *b_name); + +/* Delete a bridge member port. */ +int bridge_port_delm(struct bridge_port *bp, const char *b_name); + +/* Get the current value from the module for bridge PF control. */ +int32_t bridge_get_pfval(uint8_t which); + +/* Get/Set a bridge PF control. */ +int32_t bridge_do_pfctl(int32_t bridge_ctl, enum snmp_op op, int32_t *val); + +#endif /* SNMP_BRIDGE_H */ Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_sys.c =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_sys.c diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_sys.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_sys.c 17 Nov 2006 16:30:47 -0000 @@ -0,0 +1,1293 @@ +/*- + * Copyright (c) 2006 Shteryana Shopova + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Bridge MIB implementation for SNMPd. + * Bridge OS specific ioctls. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include + +#if __FreeBSD_version > 700018 +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bridge_tree.h" +#include "bridge_snmp.h" + +int sock = -1; + +int +bridge_ioctl_init(void) +{ + if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "cannot open socket : %s", strerror(errno)); + return (-1); + } + + return (0); +} + +/* + * Load the if_bridge.ko module in kernel if not already there. + */ +int +bridge_kmod_load(void) +{ + int fileid, modid; + const char mod_name[] = "if_bridge"; + struct module_stat mstat; + + /* Scan files in kernel. */ + mstat.version = sizeof(struct module_stat); + for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { + /* Scan modules in file. */ + for (modid = kldfirstmod(fileid); modid > 0; + modid = modfnext(modid)) { + + if (modstat(modid, &mstat) < 0) + continue; + + if (strcmp(mod_name, mstat.name) == 0) + return (0); + } + } + + /* Not present - load it. */ + if (kldload(mod_name) < 0) { + syslog(LOG_ERR, "failed to load %s kernel module", mod_name); + return (-1); + } + + return (1); +} + +/************************************************************************ + * Bridge interfaces. + */ + +/* + * Convert the kernel uint64_t value for a bridge id + */ +static void +snmp_uint64_to_bridgeid(uint64_t id, bridge_id b_id) +{ + int i; + u_char *o; + + o = (u_char *) &id; + + for (i = 0; i < SNMP_BRIDGE_ID_LEN; i++, o++) + b_id[SNMP_BRIDGE_ID_LEN - i - 1] = *o; +} + +/* + * Fetch the bridge configuration parameters from the kernel excluding + * it's base MAC address. + */ +static int +bridge_get_conf_param(struct bridge_if *bif) +{ + struct ifdrv ifd; + struct ifbrparam b_param; + + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_len = sizeof(b_param); + ifd.ifd_data = &b_param; + + /* Bridge priority. */ + ifd.ifd_cmd = BRDGGPRI; + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "update bridge: ioctl(BRDGGPRI) failed: %s", + strerror(errno)); + return (-1); + } + + bif->priority = b_param.ifbrp_prio; + + /* Configured max age. */ + ifd.ifd_cmd = BRDGGMA; + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "update bridge: ioctl(BRDGGMA) failed: %s", + strerror(errno)); + return (-1); + } + + /* Centi-seconds. */ + bif->bridge_max_age = 100 * b_param.ifbrp_maxage; + + /* Configured hello time. */ + ifd.ifd_cmd = BRDGGHT; + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "update bridge: ioctl(BRDGGHT) failed: %s", + strerror(errno)); + return (-1); + } + bif->bridge_hello_time = 100 * b_param.ifbrp_hellotime; + + /* Forward delay. */ + ifd.ifd_cmd = BRDGGFD; + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "update bridge: ioctl(BRDGGFD) failed: %s", + strerror(errno)); + return (-1); + } + bif->bridge_fwd_delay = 100 * b_param.ifbrp_fwddelay; + + /* Number of dropped addresses. */ + ifd.ifd_cmd = BRDGGRTE; + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "update bridge: ioctl(BRDGGRTE) failed: %s", + strerror(errno)); + return (-1); + } + bif->lrnt_drops = b_param.ifbrp_cexceeded; + + /* Address table timeout. */ + ifd.ifd_cmd = BRDGGTO; + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "update bridge: ioctl(BRDGGTO) failed: %s", + strerror(errno)); + return (-1); + } + bif->age_time = b_param.ifbrp_ctime; + + /* Address table size. */ + ifd.ifd_cmd = BRDGGCACHE; + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "update bridge: ioctl(BRDGGCACHE) " + "failed: %s", strerror(errno)); + return (-1); + } + bif->max_addrs = b_param.ifbrp_csize; + + return (0); +} + +/* + * Fetch the current bridge STP operational parameters. + * Returns: -1 - on error; + * 0 - old TC time and Root Port values are same; + * 1 - topologyChange notification should be sent; + * 2 - newRoot notification should be sent. + */ +int +bridge_get_op_param(struct bridge_if *bif) +{ + int new_root_send; + struct ifdrv ifd; + struct ifbropreq b_req; + + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_len = sizeof(b_req); + ifd.ifd_data = &b_req; + ifd.ifd_cmd = BRDGPARAM; + + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "update bridge: ioctl(BRDGPARAM) failed: %s", + strerror(errno)); + return (-1); + } + + bif->max_age = 100 * b_req.ifbop_maxage; + bif->hello_time = 100 * b_req.ifbop_hellotime; + bif->fwd_delay = 100 * b_req.ifbop_fwddelay; + + if (b_req.ifbop_root_port == 0 && + bif->root_port != b_req.ifbop_root_port) + new_root_send = 2; + else + new_root_send = 0; + + bif->root_port = b_req.ifbop_root_port; + bif->root_cost = b_req.ifbop_root_path_cost; + snmp_uint64_to_bridgeid(b_req.ifbop_designated_root, + bif->design_root); + + if (bif->last_tc_time.tv_sec != b_req.ifbop_last_tc_time.tv_sec) { + bif->top_changes++; + bif->last_tc_time.tv_sec = b_req.ifbop_last_tc_time.tv_sec; + bif->last_tc_time.tv_usec = b_req.ifbop_last_tc_time.tv_usec; + + /* + * "The trap is not sent if a (begemotBridge)NewRoot + * trap is sent for the same transition." + */ + if (new_root_send == 0) + return (1); + } + + return (new_root_send); +} + +int +bridge_getinfo_bif(struct bridge_if *bif) +{ + if (bridge_get_conf_param(bif) < 0) + return (-1); + + return (bridge_get_op_param(bif)); +} + +int +bridge_set_priority(struct bridge_if *bif, int32_t priority) +{ + struct ifdrv ifd; + struct ifbrparam b_param; + + /* Sanity check. */ + if (priority > SNMP_BRIDGE_MAX_PRIORITY || priority % 4096 != 0) + return (-1); + + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_len = sizeof(b_param); + ifd.ifd_data = &b_param; + b_param.ifbrp_prio = (uint32_t) priority; + ifd.ifd_cmd = BRDGSPRI; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set bridge param: ioctl(BRDGSPRI) " + "failed: %s", strerror(errno)); + return (-1); + } + + /* + * Re-fetching the data from the driver after that might be a good + * idea, since changing our bridge's priority should invoke + * recalculation of the active spanning tree topology in the network. + */ + bif->priority = priority; + return (0); +} + +/* + * Convert 1/100 of seconds to 1/256 of seconds. + * Timeout ::= TEXTUAL-CONVENTION. + * To convert a Timeout value into a value in units of + * 1/256 seconds, the following algorithm should be used: + * b = floor( (n * 256) / 100) + */ +static uint32_t +snmp_hundred_secs2_256(int32_t h_secs) +{ + return ((h_secs * 256) / 100); +} + +int +bridge_set_maxage(struct bridge_if *bif, int32_t max_age) +{ + struct ifdrv ifd; + struct ifbrparam b_param; + + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_len = sizeof(b_param); + ifd.ifd_data = &b_param; + b_param.ifbrp_maxage = (uint32_t) max_age; + ifd.ifd_cmd = BRDGSMA; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set bridge param: ioctl(BRDGSMA) " + "failed: %s", strerror(errno)); + return (-1); + } + + bif->bridge_max_age = max_age; + return (0); +} + +int +bridge_set_hello_time(struct bridge_if *bif, int32_t hello_time) +{ + struct ifdrv ifd; + struct ifbrparam b_param; + + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_len = sizeof(b_param); + ifd.ifd_data = &b_param; + b_param.ifbrp_hellotime = snmp_hundred_secs2_256(hello_time); + ifd.ifd_cmd = BRDGSHT; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set bridge param: ioctl(BRDGSHT) " + "failed: %s", strerror(errno)); + return (-1); + } + + bif->bridge_hello_time = b_param.ifbrp_hellotime; + return (0); +} + +int +bridge_set_forward_delay(struct bridge_if *bif, int32_t fwd_delay) +{ + struct ifdrv ifd; + struct ifbrparam b_param; + + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_len = sizeof(b_param); + ifd.ifd_data = &b_param; + b_param.ifbrp_fwddelay = snmp_hundred_secs2_256(fwd_delay); + ifd.ifd_cmd = BRDGSFD; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set bridge param: ioctl(BRDGSFD) " + "failed: %s", strerror(errno)); + return (-1); + } + + bif->bridge_fwd_delay = b_param.ifbrp_fwddelay; + return (0); +} + +int +bridge_set_aging_time(struct bridge_if *bif, int32_t age_time) +{ + struct ifdrv ifd; + struct ifbrparam b_param; + + /* Sanity check. */ + if (age_time < SNMP_BRIDGE_MIN_AGE_TIME || + age_time > SNMP_BRIDGE_MAX_AGE_TIME) + return (-1); + + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_len = sizeof(b_param); + ifd.ifd_data = &b_param; + b_param.ifbrp_ctime = (uint32_t) age_time; + ifd.ifd_cmd = BRDGSTO; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set bridge param: ioctl(BRDGSTO) " + "failed: %s", strerror(errno)); + return (-1); + } + + bif->age_time = age_time; + return (0); +} + +int +bridge_set_max_cache(struct bridge_if *bif, int32_t max_cache) +{ + struct ifdrv ifd; + struct ifbrparam b_param; + + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_len = sizeof(b_param); + ifd.ifd_data = &b_param; + b_param.ifbrp_csize = max_cache; + ifd.ifd_cmd = BRDGSCACHE; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set bridge param: ioctl(BRDGSCACHE) " + "failed: %s", strerror(errno)); + return (-1); + } + + bif->max_addrs = b_param.ifbrp_csize; + return (0); +} + +/* + * Set the bridge interface status to up/down. + */ +int +bridge_set_if_up(const char* b_name, int8_t up) +{ + int flags; + struct ifreq ifr; + + bzero(&ifr, sizeof(ifr)); + strcpy(ifr.ifr_name, b_name); + if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { + syslog(LOG_ERR, "set bridge up: ioctl(SIOCGIFFLAGS) " + "failed: %s", strerror(errno)); + return (-1); + } + + flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); + if (up == 1) + flags |= IFF_UP; + else + flags &= ~IFF_UP; + + ifr.ifr_flags = flags & 0xffff; + ifr.ifr_flagshigh = flags >> 16; + if (ioctl(sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { + syslog(LOG_ERR, "set bridge up: ioctl(SIOCSIFFLAGS) " + "failed: %s", strerror(errno)); + return (-1); + } + + return (0); +} + +int +bridge_create(const char *b_name) +{ + char *new_name; + struct ifreq ifr; + + bzero(&ifr, sizeof(ifr)); + strcpy(ifr.ifr_name, b_name); + + if (ioctl(sock, SIOCIFCREATE, &ifr) < 0) { + syslog(LOG_ERR, "create bridge: ioctl(SIOCIFCREATE) " + "failed: %s", strerror(errno)); + return (-1); + } + + if (strcmp(b_name, ifr.ifr_name) == 0) + return (0); + + if ((new_name = strdup(b_name)) == NULL) { + syslog(LOG_ERR, "create bridge: strdup() failed"); + return (-1); + } + + ifr.ifr_data = new_name; + if (ioctl(sock, SIOCSIFNAME, (caddr_t) &ifr) < 0) { + syslog(LOG_ERR, "create bridge: ioctl(SIOCSIFNAME) " + "failed: %s", strerror(errno)); + free(new_name); + return (-1); + } + + return (0); +} + +int +bridge_destroy(const char *b_name) +{ + struct ifreq ifr; + + bzero(&ifr, sizeof(ifr)); + strcpy(ifr.ifr_name, b_name); + + if (ioctl(sock, SIOCIFDESTROY, &ifr) < 0) { + syslog(LOG_ERR, "destroy bridge: ioctl(SIOCIFDESTROY) " + "failed: %s", strerror(errno)); + return (-1); + } + + return (0); +} + +/* + * Fetch the bridge base MAC address. Return pointer to the + * buffer containing the mac address, NULL on failure. + */ +u_char * +bridge_get_basemac(const char *bif_name, u_char *mac) +{ + int len; + char if_name[IFNAMSIZ]; + struct ifaddrs *ifap, *tmp; + struct sockaddr_dl *sdl; + + if (getifaddrs(&ifap) < 0) { + syslog(LOG_ERR, "bridge get mac: getifaddrs() failed - %s", + strerror(errno)); + return (NULL); + } + + for (tmp = ifap; tmp != NULL; tmp = tmp->ifa_next) { + sdl = (struct sockaddr_dl *) tmp->ifa_addr; + + if ((len = sdl->sdl_nlen) >= IFNAMSIZ) + len = IFNAMSIZ - 1; + + bcopy(sdl->sdl_data, if_name, len); + if_name[len] = '\0'; + + if (sdl->sdl_family == AF_LINK && !strncmp(bif_name, + if_name, strlen(bif_name))) { + bcopy(sdl->sdl_data + sdl->sdl_nlen, mac, + ETHER_ADDR_LEN); + freeifaddrs(ifap); + return (mac); + } + } + + freeifaddrs(ifap); + return (NULL); +} + +/************************************************************************ + * Bridge ports. + */ + +/* + * Convert the kernel STP port state into + * the corresopnding enumerated type from SNMP Bridge MIB. + */ +static int +state2snmp_st(uint8_t ifbr_state) +{ + switch (ifbr_state) { + case BSTP_IFSTATE_DISABLED: + return (StpPortState_disabled); + case BSTP_IFSTATE_LISTENING: + return (StpPortState_listening); + case BSTP_IFSTATE_LEARNING: + return (StpPortState_learning); + case BSTP_IFSTATE_FORWARDING: + return (StpPortState_forwarding); + case BSTP_IFSTATE_BLOCKING: + return (StpPortState_blocking); + } + + return (StpPortState_broken); +} + +/* + * Fill in a bridge member information according to data polled from kernel. + */ +static void +bridge_port_getinfo_conf(struct ifbreq *k_info, struct bridge_port *bp) +{ + bp->state = state2snmp_st(k_info->ifbr_state); + bp->priority = k_info->ifbr_priority; + + /* + * RFC 4188: + * "New implementations should support dot1dStpPortPathCost32. + * If the port path costs exceeds the maximum value of this + * object then this object should report the maximum value, + * namely 65535. Applications should try to read the + * dot1dStpPortPathCost32 object if this object reports + * the maximum value." + */ + +#if 0 + /* + * Kernel variable is a 32-bit integer but the ioctl supports + * only getting/setting a 8-bit value. + */ + + if (k_info->ifbr_path_cost > SNMP_PORT_PATHCOST_OBSOLETE) { + bp->path_cost = SNMP_PORT_PATHCOST_OBSOLETE; + bp->path_cost32 = k_info->ifbr_path_cost; + } else + + bp->path_cost = bp->path_cost32 = k_info->ifbr_path_cost; +#endif + + bp->path_cost = k_info->ifbr_path_cost; + + if (k_info->ifbr_ifsflags & IFBIF_STP) + bp->enable = dot1dStpPortEnable_enabled; + else + bp->enable = dot1dStpPortEnable_disabled; + + /* Begemot Bridge MIB only. */ + if (k_info->ifbr_ifsflags & IFBIF_SPAN) + bp->span_enable = begemotBridgeBaseSpanEnabled_enabled; + else + bp->span_enable = begemotBridgeBaseSpanEnabled_disabled; +} + +/* + * Fill in a bridge interface STP information according to + * data polled from kernel. + */ +static void +bridge_port_getinfo_opstp(struct ifbpstpreq *bp_stp, struct bridge_port *bp) +{ + bp->enable = dot1dStpPortEnable_enabled; + bp->fwd_trans = bp_stp->ifbp_fwd_trans; + bp->design_cost = bp_stp->ifbp_design_cost; + snmp_uint64_to_bridgeid(bp_stp->ifbp_design_root, bp->design_root); + snmp_uint64_to_bridgeid(bp_stp->ifbp_design_bridge, bp->design_bridge); + bcopy(&(bp_stp->ifbp_design_port), &(bp->design_port), + sizeof(uint16_t)); +} + +/* + * Clear a bridge interface STP information. + */ +static void +bridge_port_clearinfo_opstp(struct bridge_port *bp) +{ + if (bp->enable == dot1dStpPortEnable_enabled) { + bp->design_cost = 0; + bzero(&(bp->design_root), sizeof(bridge_id)); + bzero(&(bp->design_bridge), sizeof(bridge_id)); + bzero(&(bp->design_port), sizeof(port_id)); + bp->fwd_trans = 0; + } + + bp->enable = dot1dStpPortEnable_disabled; +} + +/* + * Set a bridge member priority. + */ +int +bridge_port_set_priority(const char *bif_name, struct bridge_port *bp, + int32_t priority) +{ + struct ifdrv ifd; + struct ifbreq b_req; + + if (priority < 0 || priority > 255) + return (-2); + + strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); + ifd.ifd_len = sizeof(b_req); + ifd.ifd_data = &b_req; + strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); + + b_req.ifbr_priority = (uint8_t) priority; + ifd.ifd_cmd = BRDGSIFPRIO; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFPRIO) " + "failed: %s", bp->p_name, strerror(errno)); + return (-1); + } + + bp->priority = priority; + return (0); +} + +/* + * Set a bridge member STP-enabled flag. + */ +int +bridge_port_set_stp_enable(const char *bif_name, struct bridge_port *bp, + uint32_t enable) +{ + struct ifdrv ifd; + struct ifbreq b_req; + + if (bp->enable == enable) + return (0); + + if (enable != dot1dStpPortEnable_enabled && + enable != dot1dStpPortEnable_disabled) + return (-2); + + bzero(&b_req, sizeof(b_req)); + strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); + ifd.ifd_len = sizeof(b_req); + ifd.ifd_data = &b_req; + strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); + ifd.ifd_cmd = BRDGGIFFLGS; + + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) " + "failed: %s", bp->p_name, strerror(errno)); + return (-1); + } + + if (enable == dot1dStpPortEnable_enabled) + b_req.ifbr_ifsflags |= IFBIF_STP; + else + b_req.ifbr_ifsflags &= ~IFBIF_STP; + + ifd.ifd_cmd = BRDGSIFFLGS; + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) " + "failed: %s", bp->p_name, strerror(errno)); + return (-1); + } + + bp->enable = enable; + return (0); +} + +/* + * Set a bridge member STP path cost. + */ +int +bridge_port_set_path_cost(const char *bif_name, struct bridge_port *bp, + int32_t path_cost) +{ + struct ifdrv ifd; + struct ifbreq b_req; + + if (path_cost > SNMP_PORT_PATHCOST_OBSOLETE) + return (-2); + + strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); + ifd.ifd_len = sizeof(b_req); + ifd.ifd_data = &b_req; + strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); + + b_req.ifbr_path_cost = (uint16_t) path_cost; + ifd.ifd_cmd = BRDGSIFCOST; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFCOST) " + "failed: %s", bp->p_name, strerror(errno)); + return (-1); + } + + bp->path_cost = path_cost; + return (0); +} + +/* + * Add a bridge member port. + */ +int +bridge_port_addm(struct bridge_port *bp, const char *b_name) +{ + struct ifdrv ifd; + struct ifbreq b_req; + + bzero(&ifd, sizeof(ifd)); + bzero(&b_req, sizeof(b_req)); + + strlcpy(ifd.ifd_name, b_name, sizeof(ifd.ifd_name)); + ifd.ifd_len = sizeof(b_req); + ifd.ifd_data = &b_req; + strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); + + if (bp->span_enable == begemotBridgeBaseSpanEnabled_enabled) + ifd.ifd_cmd = BRDGADDS; + else + ifd.ifd_cmd = BRDGADD; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "%s - add member : ioctl(%s) failed: %s", + bp->p_name, + (ifd.ifd_cmd == BRDGADDS ? "BRDGADDS" : "BRDGADD"), + strerror(errno)); + return (-1); + } + + return (0); +} + +/* + * Delete a bridge member port. + */ +int +bridge_port_delm(struct bridge_port *bp, const char *b_name) +{ + struct ifdrv ifd; + struct ifbreq b_req; + + bzero(&ifd, sizeof(ifd)); + bzero(&b_req, sizeof(b_req)); + + strlcpy(ifd.ifd_name, b_name, sizeof(ifd.ifd_name)); + ifd.ifd_len = sizeof(b_req); + ifd.ifd_data = &b_req; + strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); + + if (bp->span_enable == begemotBridgeBaseSpanEnabled_enabled) + ifd.ifd_cmd = BRDGDELS; + else + ifd.ifd_cmd = BRDGDEL; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "%s - add member : ioctl(%s) failed: %s", + bp->p_name, + (ifd.ifd_cmd == BRDGDELS ? "BRDGDELS" : "BRDGDEL"), + strerror(errno)); + return (-1); + } + + return (0); +} + +/* + * Fetch the bridge member list from kernel. + * Return -1 on error, or buffer len if successful. + */ +static int32_t +bridge_port_get_iflist(struct bridge_if *bif, char **buf) +{ + uint32_t len = 8192; /* ??? */ + char *ninbuf; + struct ifbifconf ifbc; + struct ifdrv ifd; + + *buf = NULL; + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_cmd = BRDGGIFS; + ifd.ifd_len = sizeof(ifbc); + ifd.ifd_data = &ifbc; + + for ( ; ; ) { + if ((ninbuf = realloc(*buf, len) /* ??? */) == NULL) { + syslog(LOG_ERR, "get bridge member list: " + "realloc failed: %s", strerror(errno)); + free(*buf); + *buf = NULL; + return (-1); + } + + ifbc.ifbic_len = len; + ifbc.ifbic_buf = *buf = ninbuf; + + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "get bridge member list: ioctl " + "(BRDGGIFS) failed: %s", strerror(errno)); + free(*buf); + buf = NULL; + return (-1); + } + + if ((ifbc.ifbic_len + sizeof(struct ifbreq)) < len) + break; + + len += 8192; + } + + return (ifbc.ifbic_len); +} + +/* + * Fetch the bridge STP member list from kernel. + * Return -1 on error, or buffer len if successful. + */ +static int32_t +bridge_port_get_ifstplist(struct bridge_if *bif, char **buf) +{ + uint32_t len = 8192; /* ??? */ + char *ninbuf; + struct ifbpstpconf ifbstp; + struct ifdrv ifd; + + *buf = NULL; + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_cmd = BRDGGIFSSTP; + ifd.ifd_len = sizeof(ifbstp); + ifd.ifd_data = &ifbstp; + + for ( ; ; ) { + if ((ninbuf = realloc(*buf, len) /* ??? */) == NULL) { + syslog(LOG_ERR, "get bridge STP ports list: " + "realloc failed: %s", strerror(errno)); + free(*buf); + *buf = NULL; + return (-1); + } + + ifbstp.ifbpstp_len = len; + ifbstp.ifbpstp_buf = *buf = ninbuf; + + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "get bridge STP ports list: ioctl " + "(BRDGGIFSSTP) failed: %s", strerror(errno)); + free(*buf); + buf = NULL; + return (-1); + } + + if ((ifbstp.ifbpstp_len + sizeof(struct ifbpstpreq)) < len) + break; + + len += 8192; + } + + return (ifbstp.ifbpstp_len); +} + +/* + * Locate a bridge if STP params structure in a buffer. + */ +static struct ifbpstpreq * +bridge_port_find_ifstplist(uint8_t port_no, char *buf, uint32_t buf_len) +{ + uint32_t i; + struct ifbpstpreq *bstp; + + for (i = 0; i < buf_len / sizeof(*bstp); i++) { + bstp = (struct ifbpstpreq *) buf + i; + if (bstp->ifbp_portno == port_no) + return (bstp); + } + + return (NULL); +} + +/* + * Read the initial info for all members of a bridge interface. + * Returns the number of ports, 0 - if none, otherwise + * -1 if some other error occured. + */ +int +bridge_getinfo_bif_ports(struct bridge_if *bif) +{ + uint32_t i; + int32_t buf_len; + char *mem_buf; + struct ifbreq *b_req; + struct ifbpstpreq *bs_req; + struct bridge_port *bp; + struct mibif *m_if; + + if ((buf_len = bridge_port_get_iflist(bif, &mem_buf)) < 0) + return (-1); + + for (i = 0; i < buf_len / sizeof(struct ifbreq); i++) { + b_req = (struct ifbreq *) mem_buf + i; + + if ((m_if = mib_find_if_sys(b_req->ifbr_portno)) != NULL) { + /* Hopefully we will not fail here. */ + if ((bp = bridge_new_port(m_if, bif)) != NULL) { + bp->status = RowStatus_active; + bridge_port_getinfo_conf(b_req, bp); + bridge_port_getinfo_mibif(m_if, bp); + } + } else { + syslog(LOG_ERR, "bridge member %s not present " + "in mibII ifTable", b_req->ifbr_ifsname); + } + } + free(mem_buf); + + if ((buf_len = bridge_port_get_ifstplist(bif, &mem_buf)) < 0) + return (-1); + + for (bp = bridge_port_bif_first(bif); bp != NULL; + bp = bridge_port_bif_next(bp)) { + if ((bs_req = bridge_port_find_ifstplist(bp->port_no, + mem_buf, buf_len)) == NULL) + bridge_port_clearinfo_opstp(bp); + else + bridge_port_getinfo_opstp(bs_req, bp); + } + free(mem_buf); + + return (i); +} + +/* + * Update the information for the bridge interface members. + */ +int +bridge_update_memif(struct bridge_if *bif) +{ + int added, updated; + uint32_t i; + int32_t buf_len; + char *if_buf; + struct ifbreq *b_req; + struct ifbpstpreq *bs_req; + struct bridge_port *bp, *bp_next; + struct mibif *m_if; + + if ((buf_len = bridge_port_get_iflist(bif, &if_buf)) < 0) + return (-1); + + added = updated = 0; + +#define BP_FOUND 0x01 + for (i = 0; i < buf_len / sizeof(struct ifbreq); i++) { + b_req = (struct ifbreq *) if_buf + i; + + if ((m_if = mib_find_if_sys(b_req->ifbr_portno)) == NULL) { + syslog(LOG_ERR, "bridge member %s not present " + "in mibII ifTable", b_req->ifbr_ifsname); + continue; + } + + if ((bp = bridge_port_find(m_if->index, bif)) == NULL && + (bp = bridge_new_port(m_if, bif)) != NULL) { + bp->status = RowStatus_active; + added++; + } + + if (bp != NULL) { + updated++; + bridge_port_getinfo_conf(b_req, bp); + bridge_port_getinfo_mibif(m_if, bp); + bp->flags |= BP_FOUND; + } + } + free(if_buf); + + /* Clean up list. */ + for (bp = bridge_port_bif_first(bif); bp != NULL; bp = bp_next) { + bp_next = bridge_port_bif_next(bp); + + if ((bp->flags & BP_FOUND) == 0 && + bp->status == RowStatus_active) + bridge_port_remove(bp, bif); + else + bp->flags |= ~BP_FOUND; + } +#undef BP_FOUND + + if ((buf_len = bridge_port_get_ifstplist(bif, &if_buf)) < 0) + return (-1); + + for (bp = bridge_port_bif_first(bif); bp != NULL; + bp = bridge_port_bif_next(bp)) { + if ((bs_req = bridge_port_find_ifstplist(bp->port_no, + if_buf, buf_len)) == NULL) + bridge_port_clearinfo_opstp(bp); + else + bridge_port_getinfo_opstp(bs_req, bp); + } + free(if_buf); + bif->ports_age = time(NULL); + + return (updated); +} + +/************************************************************************ + * Bridge addresses. + */ + +/* + * Update the bridge address info according to the polled data. + */ +static void +bridge_addrs_info_ifaddrlist(struct ifbareq *ifba, struct tp_entry *tpe) +{ + tpe->port_no = if_nametoindex(ifba->ifba_ifsname); + + if ((ifba->ifba_flags & IFBAF_TYPEMASK) == IFBAF_STATIC) + tpe->status = TpFdbStatus_mgmt; + else + tpe->status = TpFdbStatus_learned; +} + +/* + * Read the bridge addresses from kernel. + * Return -1 on error, or buffer len if successful. + */ +static int32_t +bridge_addrs_getinfo_ifalist(struct bridge_if *bif, char **buf) +{ + uint32_t len = 8192; /* ??? */ + char *ninbuf; + struct ifbaconf bac; + struct ifdrv ifd; + + *buf = NULL; + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_cmd = BRDGRTS; + ifd.ifd_len = sizeof(bac); + ifd.ifd_data = &bac; + + for ( ; ; ) { + if ((ninbuf = realloc(*buf, len) /* ??? */) == NULL) { + syslog(LOG_ERR, "get bridge address list: " + " realloc failed: %s", strerror(errno)); + free(*buf); + *buf = NULL; + return (-1); + } + + bac.ifbac_len = len; + bac.ifbac_buf = *buf = ninbuf; + + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "get bridge address list: " + "ioctl(BRDGRTS) failed: %s", strerror(errno)); + free(*buf); + buf = NULL; + return (-1); + } + + if ((bac.ifbac_len + sizeof(struct ifbareq)) < len) + break; + + len += 8192; + } + + return (bac.ifbac_len); +} + +/* + * Read the initial info for all addresses on a bridge intrface. + * Returns the number of addresses, 0 - if none, otherwise + * -1 if some other error occured. + */ +int +bridge_getinfo_bif_addrs(struct bridge_if *bif) +{ + uint32_t i; + int32_t buf_len; + char *addr_buf; + struct ifbareq *addr_req; + struct tp_entry *te; + + if ((buf_len = bridge_addrs_getinfo_ifalist(bif, &addr_buf)) < 0) + return (-1); + + for (i = 0; i < buf_len / sizeof(struct ifbareq); i++) { + addr_req = (struct ifbareq *) addr_buf + i; + + if ((te = bridge_new_addrs(addr_req->ifba_dst, bif)) != NULL) + bridge_addrs_info_ifaddrlist(addr_req, te); + } + + free(addr_buf); + return (i); +} + +/* + * Update the addresses for the bridge interface. + */ +int +bridge_update_addrs(struct bridge_if *bif) +{ + int added, updated; + uint32_t i; + int32_t buf_len; + char *ifbad_buf; + struct tp_entry *te, *te_next; + struct ifbareq *a_req; + + if ((buf_len = bridge_addrs_getinfo_ifalist(bif, &ifbad_buf)) < 0) + return (-1); + + added = updated = 0; + +#define BA_FOUND 0x01 + for (i = 0; i < buf_len / sizeof(struct ifbareq); i++) { + a_req = (struct ifbareq *) ifbad_buf + i; + + if ((te = bridge_addrs_find(a_req->ifba_dst, bif)) == NULL) { + added++; + + if ((te = bridge_new_addrs(a_req->ifba_dst, bif)) + == NULL) + continue; + } else + updated++; + + bridge_addrs_info_ifaddrlist(a_req, te); + te-> flags |= BA_FOUND; + } + free(ifbad_buf); + + for (te = bridge_addrs_bif_first(bif); te != NULL; te = te_next) { + te_next = bridge_addrs_bif_next(te); + + if ((te-> flags & BA_FOUND) == 0) + bridge_addrs_remove(te, bif); + else + te-> flags &= ~BA_FOUND; + } +#undef BA_FOUND + + bif->addrs_age = time(NULL); + return (updated + added); +} + +/************************************************************************ + * Bridge packet filtering. + */ +const char bridge_sysctl[] = "net.link.bridge."; + +static struct { + int32_t val; + const char *name; +} bridge_pf_sysctl[] = { + { 1, "pfil_bridge" }, + { 1, "pfil_member" }, + { 1, "pfil_onlyip" }, + { 0, "ipfw" }, +}; + +int32_t +bridge_get_pfval(uint8_t which) +{ + if (which > sizeof(bridge_pf_sysctl) / sizeof(bridge_pf_sysctl[0]) + || which < 1) + return (-1); + + return (bridge_pf_sysctl[which - 1].val); +} + +int32_t +bridge_do_pfctl(int32_t bridge_ctl, enum snmp_op op, int32_t *val) +{ + char mib_name[100]; + int32_t i, s_i; + size_t len, s_len; + + if (bridge_ctl >= LEAF_begemotBridgeLayer2PfStatus) + return (-2); + + if (op == SNMP_OP_SET) { + s_i = *val; + s_len = sizeof(s_i); + } else + s_len = 0; + + len = sizeof(i); + + strcpy(mib_name, bridge_sysctl); + + if (sysctlbyname(strcat(mib_name, + bridge_pf_sysctl[bridge_ctl].name), &i, &len, + (op == SNMP_OP_SET ? &s_i : NULL), s_len) == -1) { + syslog(LOG_ERR, "sysctl(%s%s) failed - %s", bridge_sysctl, + bridge_pf_sysctl[bridge_ctl].name, strerror(errno)); + return (-1); + } + + bridge_pf_sysctl[bridge_ctl].val = i; + *val = i; + + return (i); +} + +void +bridge_pf_dump(void) +{ + uint8_t i; + + for (i = 0; i < sizeof(bridge_pf_sysctl) / sizeof(bridge_pf_sysctl[0]); + i++) { + syslog(LOG_ERR, "%s%s = %d", bridge_sysctl, + bridge_pf_sysctl[i].name, bridge_pf_sysctl[i].val); + } +} Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_tree.def =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_tree.def diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_tree.def --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_tree.def 17 Nov 2006 16:30:47 -0000 @@ -0,0 +1,242 @@ +#- +# Copyright (c) 2006 Shteryana Shopova +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +#include "tc.def" + +typedef TruthValue ENUM ( + 1 true + 2 false +) + +typedef RowStatus ENUM ( + 1 active + 2 notInService + 3 notReady + 4 createAndGo + 5 createAndWait + 6 destroy +) + +typedef StpPortState ENUM ( + 1 disabled + 2 blocking + 3 listening + 4 learning + 5 forwarding + 6 broken +) + +typedef BaseType ENUM ( + 1 unknown + 2 transparent-only + 3 sourceroute-only + 4 srt +) + +typedef TpFdbStatus ENUM ( + 1 other + 2 invalid + 3 learned + 4 self + 5 mgmt +) + +(1 internet + (2 mgmt + (1 mib_2 + (17 dot1dBridge + (0 dot1dNotifications + (1 newRoot OID op_snmp_trap) + (2 topologyChange OID op_snmp_trap) + ) + (1 dot1dBase + (1 dot1dBaseBridgeAddress OCTETSTRING | MacAddress op_dot1d_base GET) + (2 dot1dBaseNumPorts INTEGER32 op_dot1d_base GET) + (3 dot1dBaseType BaseType op_dot1d_base GET) + (4 dot1dBasePortTable + (1 dot1dBasePortEntry : INTEGER op_dot1d_base_port + (1 dot1dBasePort INTEGER GET) + (2 dot1dBasePortIfIndex INTEGER GET) + (3 dot1dBasePortCircuit OID GET) + (4 dot1dBasePortDelayExceededDiscards COUNTER GET) + (5 dot1dBasePortMtuExceededDiscards COUNTER GET) + )) + ) + (2 dot1dStp + (1 dot1dStpProtocolSpecification ENUM ( 1 unknown 2 decLb100 3 ieee8021d ) op_dot1d_stp GET) + (2 dot1dStpPriority INTEGER op_dot1d_stp GET SET) + (3 dot1dStpTimeSinceTopologyChange TIMETICKS op_dot1d_stp GET) + (4 dot1dStpTopChanges COUNTER op_dot1d_stp GET) + (5 dot1dStpDesignatedRoot OCTETSTRING | BridgeId op_dot1d_stp GET) + (6 dot1dStpRootCost INTEGER32 op_dot1d_stp GET) + (7 dot1dStpRootPort INTEGER32 op_dot1d_stp GET) + (8 dot1dStpMaxAge INTEGER op_dot1d_stp GET) + (9 dot1dStpHelloTime INTEGER op_dot1d_stp GET) + (10 dot1dStpHoldTime INTEGER32 op_dot1d_stp GET) + (11 dot1dStpForwardDelay INTEGER op_dot1d_stp GET) + (12 dot1dStpBridgeMaxAge INTEGER op_dot1d_stp GET SET) + (13 dot1dStpBridgeHelloTime INTEGER op_dot1d_stp GET SET) + (14 dot1dStpBridgeForwardDelay INTEGER op_dot1d_stp GET SET) + (15 dot1dStpPortTable + (1 dot1dStpPortEntry : INTEGER op_dot1d_stp_port + (1 dot1dStpPort INTEGER GET) + (2 dot1dStpPortPriority INTEGER GET SET) + (3 dot1dStpPortState StpPortState GET) + (4 dot1dStpPortEnable ENUM ( 1 enabled 2 disabled ) GET SET) + (5 dot1dStpPortPathCost INTEGER GET SET) + (6 dot1dStpPortDesignatedRoot OCTETSTRING | BridgeId GET) + (7 dot1dStpPortDesignatedCost INTEGER32 GET) + (8 dot1dStpPortDesignatedBridge OCTETSTRING | BridgeId GET) + (9 dot1dStpPortDesignatedPort OCTETSTRING | BridgePortId GET) + (10 dot1dStpPortForwardTransitions COUNTER GET) + )) + ) + (3 dot1dSr + ) + (4 dot1dTp + (1 dot1dTpLearnedEntryDiscards COUNTER op_dot1d_tp GET) + (2 dot1dTpAgingTime INTEGER op_dot1d_tp GET SET) + (3 dot1dTpFdbTable + (1 dot1dTpFdbEntry : OCTETSTRING | MacAddress op_dot1d_tp_fdb + (1 dot1dTpFdbAddress OCTETSTRING | MacAddress GET) + (2 dot1dTpFdbPort INTEGER32 GET) + (3 dot1dTpFdbStatus TpFdbStatus GET) + )) + (4 dot1dTpPortTable + (1 dot1dTpPortEntry : INTEGER op_dot1d_tp_port + (1 dot1dTpPort INTEGER GET) + (2 dot1dTpPortMaxInfo INTEGER32 GET) + (3 dot1dTpPortInFrames COUNTER GET) + (4 dot1dTpPortOutFrames COUNTER GET) + (5 dot1dTpPortInDiscards COUNTER GET) + )) + ) + (5 dot1dStatic + ) + (8 dot1dConformance + (1 dot1dGroups + ) + (2 dot1dCompliances + ) + ) + ))) + (4 private + (1 enterprises + (12325 fokus + (1 begemot + (205 begemotBridge + (0 begemotBridgeNotifications + (1 begemotBridgeNewRoot OID op_snmp_trap) + (2 begemotBridgeTopologyChange OID op_snmp_trap) + ) + (1 begemotBridgeBase + (1 begemotBridgeBaseTable + (1 begemotBridgeBaseEntry : OCTETSTRING | BridgeIfName op_begemot_base_bridge + (1 begemotBridgeBaseName OCTETSTRING | BridgeIfName GET) + (2 begemotBridgeBaseAddress OCTETSTRING | MacAddress GET) + (3 begemotBridgeBaseNumPorts INTEGER32 GET) + (4 begemotBridgeBaseType BaseType GET) + (5 begemotBridgeBaseStatus RowStatus GET SET) + )) + (2 begemotBridgeBasePortTable + (1 begemotBridgeBasePortEntry : OCTETSTRING | BridgeIfName INTEGER op_begemot_base_port + (1 begemotBridgeBasePort INTEGER GET) + (2 begemotBridgeBasePortIfIndex INTEGER GET) + (3 begemotBridgeBaseSpanEnabled ENUM ( 1 enabled 2 disabled ) GET SET) + (4 begemotBridgeBasePortDelayExceededDiscards COUNTER GET) + (5 begemotBridgeBasePortMtuExceededDiscards COUNTER GET) + (6 begemotBridgeBasePortStatus RowStatus GET SET) + )) + ) + (2 begemotBridgeStp + (1 begemotBridgeStpTable + (1 begemotBridgeStpEntry : OCTETSTRING | BridgeIfName op_begemot_stp + (1 begemotBridgeStpProtocolSpecification ENUM ( 1 unknown 2 decLb100 3 ieee8021d ) GET) + (2 begemotBridgeStpPriority INTEGER GET SET) + (3 begemotBridgeStpTimeSinceTopologyChange TIMETICKS GET) + (4 begemotBridgeStpTopChanges COUNTER GET) + (5 begemotBridgeStpDesignatedRoot OCTETSTRING | BridgeId GET) + (6 begemotBridgeStpRootCost INTEGER32 GET) + (7 begemotBridgeStpRootPort INTEGER32 GET) + (8 begemotBridgeStpMaxAge INTEGER GET) + (9 begemotBridgeStpHelloTime INTEGER GET) + (10 begemotBridgeStpHoldTime INTEGER32 GET) + (11 begemotBridgeStpForwardDelay INTEGER GET) + (12 begemotBridgeStpBridgeMaxAge INTEGER GET SET) + (13 begemotBridgeStpBridgeHelloTime INTEGER GET SET) + (14 begemotBridgeStpBridgeForwardDelay INTEGER GET SET) + )) + (2 begemotBridgeStpPortTable + (1 begemotBridgeStpPortEntry : OCTETSTRING | BridgeIfName INTEGER op_begemot_stp_port + (1 begemotBridgeStpPort INTEGER GET) + (2 begemotBridgeStpPortPriority INTEGER GET SET) + (3 begemotBridgeStpPortState StpPortState GET) + (4 begemotBridgeStpPortEnable ENUM ( 1 enabled 2 disabled ) GET SET) + (5 begemotBridgeStpPortPathCost INTEGER GET SET) + (6 begemotBridgeStpPortDesignatedRoot OCTETSTRING | BridgeId GET) + (7 begemotBridgeStpPortDesignatedCost INTEGER32 GET) + (8 begemotBridgeStpPortDesignatedBridge OCTETSTRING | BridgeId GET) + (9 begemotBridgeStpPortDesignatedPort OCTETSTRING | BridgePortId GET) + (10 begemotBridgeStpPortForwardTransitions COUNTER GET) + )) + ) + (3 begemotBridgeTp + (1 begemotBridgeTpTable + (1 begemotBridgeTpEntry : OCTETSTRING | BridgeIfName op_begemot_tp + (1 begemotBridgeTpLearnedEntryDiscards COUNTER GET) + (2 begemotBridgeTpAgingTime INTEGER GET SET) + (3 begemotBridgeTpMaxAddresses INTEGER GET SET) + )) + (2 begemotBridgeTpFdbTable + (1 begemotBridgeTpFdbEntry : OCTETSTRING | BridgeIfName OCTETSTRING | MacAddress op_begemot_tp_fdb + (1 begemotBridgeTpFdbAddress OCTETSTRING | MacAddress GET) + (2 begemotBridgeTpFdbPort INTEGER32 GET) + (3 begemotBridgeTpFdbStatus TpFdbStatus GET) + )) + (3 begemotBridgeTpPortTable + (1 begemotBridgeTpPortEntry : OCTETSTRING | BridgeIfName INTEGER op_begemot_tp_port + (1 begemotBridgeTpPort INTEGER GET) + (2 begemotBridgeTpPortMaxInfo INTEGER32 GET) + (3 begemotBridgeTpPortInFrames COUNTER GET) + (4 begemotBridgeTpPortOutFrames COUNTER GET) + (5 begemotBridgeTpPortInDiscards COUNTER GET) + )) + ) + (4 begemotBridgePf + (1 begemotBridgePfilStatus TruthValue op_begemot_bridge_pf GET SET) + (2 begemotBridgePfilMembers TruthValue op_begemot_bridge_pf GET SET) + (3 begemotBridgePfilIpOnly TruthValue op_begemot_bridge_pf GET SET) + (4 begemotBridgeLayer2PfStatus ENUM ( 1 enabled 2 disabled ) op_begemot_bridge_pf GET SET) + ) + (5 begemotBridgeConfigObjects + (1 begemotBridgeDefaultBridgeIf OCTETSTRING | BridgeIfNameOrEmpty op_begemot_bridge_config GET SET) + (2 begemotBridgeDataUpdate INTEGER op_begemot_bridge_config GET SET) + (3 begemotBridgeDataPoll INTEGER op_begemot_bridge_config GET SET) + ) + ))))) +) Index: src/usr.sbin/bsnmpd/modules/snmp_bridge/snmp_bridge.3 =================================================================== RCS file: src/usr.sbin/bsnmpd/modules/snmp_bridge/snmp_bridge.3 diff -N src/usr.sbin/bsnmpd/modules/snmp_bridge/snmp_bridge.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/usr.sbin/bsnmpd/modules/snmp_bridge/snmp_bridge.3 17 Nov 2006 16:30:47 -0000 @@ -0,0 +1,113 @@ +.\"- +.\" Copyright (C) 2006 Shteryana Shopova +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd August 18, 2006 +.Dt snmp_bridge 3 +.Os +.Sh NAME +.Nm snmp_bridge +.Nd "bridge module for snmpd. +.Sh LIBRARY +.Pq begemotSnmpdModulePath."bridge" = "/usr/lib/snmp_bridge.so" +.Sh DESCRIPTION +The +.Nm snmp_bridge +module implements the BRIDGE-MIB as standardized in RFC 4188 and a private +BEGEMOT-BRIDGE-MIB, which allows management of multiple bridge interfaces. +Most of the objects defined in the private BEGEMOT-BRIDGE-MIB are duplicates +of the original objects defined by the standard BRIDGE-MIB, but the private +MIB also defines additional objects which make the functionality of +.Nm +similar to +.Xr ifconfig 8 +for configuring bridge interfaces. +Therefore one should consider adding write comminities or loading the +.Nm +module on systems where security is crucial. +.Sh IMPLEMENTATION NOTES +The additional objects to configure a bridge are: +.Bl -tag -width "XXXXXXXXX" +.It Va begemotBridgeBaseStatus +Bridge interfaces can be created and destroyed via this object. +SNMP SET operations with the following values are allowed: +.Bl -tag -width ".It Va createAndWait" +.It Va createAndWait +will attempt to create a bridge interface with the name given by the table +index. +.It Va createAndGo +will attempt to create a bridge interface with the name given by the table +index and set the status of the interface to "active/up". +.It Va destroy +will attempt to destory the bridge interface. +.El +.It Va begemotBridgeBaseSpanEnabled +A SNMP SET operation on this object is only successfull if the corresponding +port has not been added as member of the bridge interface on the system. +.It Va begemotBridgeBasePortStatus +SNMP SET operations with the following values are allowed: +.Bl -tag -width ".It Va createAndWait" +.It Va createAndWait +will create a new row for the bridge member in the SNMP +.Va begemotBridgeBasePortTable +but will not try to commit the information to the system. +.It Va active +will attempt to commit the information to the system and will be successful +only if a value for +.Va begemotBridgeBaseSpanEnabled +has been SET already. +.It Va destroy +will attempt to remove the interface from the system bridge interface. +.El +.El +.Sh RESTRICTIONS +Not all information in the MIBs is currently available in FreeBSD. +The following variables carry no information: +.Bl -tag -width "XXXXXXXXX" +.It Va dot1dBasePortCircuit +.It Va dot1dBasePortDelayExceededDiscards +.It Va dot1dBasePortMtuExceededDiscards +.It Va begemotBridgeBasePortDelayExceededDiscards +.It Va begemotBridgeBasePortMtuExceededDiscards +.El +.Sh FILES +.Bl -tag -width "XXXXXXXXX" +.It Pa /usr/share/snmp/defs/bridge_tree.def +The description of the MIB tree implemented by +.Nm . +.It Pa /usr/share/snmp/mibs/BRIDGE-MIB.txt +This is the BRIDGE-MIB that is implemented by this module. +.It Pa /usr/share/snmp/mibs/BEGEMOT-BRIDGE-MIB.txt +This is the private BEGEMOT-BRIDGE-MIB that is implemented by this module. +.El +.Sh SEE ALSO +.Xr bsnmpd 1 , +.Xr gensnmptree 1 , +.Xr if_bridge 4 , +.Xr ifconfig 8 , +.Xr snmpmod 3 +.Sh AUTHORS +.An Shteryana Shopova Aq syrinx@FreeBSD.org