aboutsummaryrefslogtreecommitdiff
path: root/contrib/bsnmp/snmp_mibII/mibII_interfaces.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bsnmp/snmp_mibII/mibII_interfaces.c')
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII_interfaces.c524
1 files changed, 524 insertions, 0 deletions
diff --git a/contrib/bsnmp/snmp_mibII/mibII_interfaces.c b/contrib/bsnmp/snmp_mibII/mibII_interfaces.c
new file mode 100644
index 000000000000..02a90caa36c0
--- /dev/null
+++ b/contrib/bsnmp/snmp_mibII/mibII_interfaces.c
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * Author: Harti Brandt <harti@freebsd.org>
+ *
+ * Redistribution of this software and documentation 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 or documentation 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.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
+ * AND ITS 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
+ * FRAUNHOFER FOKUS OR ITS 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.
+ *
+ * $Begemot: bsnmp/snmp_mibII/mibII_interfaces.c,v 1.9 2003/01/28 13:44:35 hbb Exp $
+ *
+ * Interfaces group.
+ */
+#include "mibII.h"
+#include "mibII_oid.h"
+
+/*
+ * This structure catches all changes to a interface entry
+ */
+struct ifchange {
+ struct snmp_dependency dep;
+
+ u_int ifindex;
+
+ u_int32_t set;
+ int promisc;
+ int admin;
+ int traps;
+
+ u_int32_t rb;
+ int rb_flags;
+ int rb_traps;
+};
+#define IFC_PROMISC 0x0001
+#define IFC_ADMIN 0x0002
+#define IFC_TRAPS 0x0004
+#define IFRB_FLAGS 0x0001
+#define IFRB_TRAPS 0x0002
+
+static const struct asn_oid
+ oid_ifTable = OIDX_ifTable;
+
+/*
+ * This function handles all changes to the interface table and interface
+ * extension table.
+ */
+static int
+ifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep,
+ enum snmp_depop op)
+{
+ struct ifchange *ifc = (struct ifchange *)dep;
+ struct mibif *ifp;
+ struct ifreq ifr, ifr1;
+
+ if ((ifp = mib_find_if(ifc->ifindex)) == NULL)
+ return (SNMP_ERR_NO_CREATION);
+
+ switch (op) {
+
+ case SNMP_DEPOP_COMMIT:
+ strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+ if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) {
+ syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);
+ return (SNMP_ERR_GENERR);
+ }
+ if (ifc->set & IFC_PROMISC) {
+ ifr.ifr_flags &= ~IFF_PROMISC;
+ if (ifc->promisc)
+ ifr.ifr_flags |= IFF_PROMISC;
+ ifc->rb |= IFRB_FLAGS;
+ }
+ if (ifc->set & IFC_ADMIN) {
+ ifr.ifr_flags &= ~IFF_UP;
+ if (ifc->admin)
+ ifr.ifr_flags |= IFF_UP;
+ ifc->rb |= IFRB_FLAGS;
+ }
+ if (ifc->rb & IFRB_FLAGS) {
+ strncpy(ifr1.ifr_name, ifp->name, sizeof(ifr1.ifr_name));
+ if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr1) == -1) {
+ syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);
+ return (SNMP_ERR_GENERR);
+ }
+ ifc->rb_flags = ifr1.ifr_flags;
+ if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {
+ syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);
+ return (SNMP_ERR_GENERR);
+ }
+ (void)mib_fetch_ifmib(ifp);
+ }
+ if (ifc->set & IFC_TRAPS) {
+ ifc->rb |= IFRB_TRAPS;
+ ifc->rb_traps = ifp->trap_enable;
+ ifp->trap_enable = ifc->traps;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_DEPOP_ROLLBACK:
+ if (ifc->rb & IFRB_FLAGS) {
+ strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+ ifr.ifr_flags = ifc->rb_flags;
+ if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {
+ syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);
+ return (SNMP_ERR_UNDO_FAILED);
+ }
+ (void)mib_fetch_ifmib(ifp);
+ }
+ if (ifc->rb & IFRB_TRAPS)
+ ifp->trap_enable = ifc->rb_traps;
+ return (SNMP_ERR_NOERROR);
+
+ }
+ abort();
+}
+
+static u_int32_t
+ticks_get_timeval(struct timeval *tv)
+{
+ u_int32_t v;
+
+ if (tv->tv_sec != 0 || tv->tv_usec != 0) {
+ v = 100 * tv->tv_sec + tv->tv_usec / 10000;
+ if (v > start_tick)
+ return (v - start_tick);
+ }
+ return (0);
+}
+
+/*
+ * Scalars
+ */
+int
+op_interfaces(struct snmp_context *ctx __unused, struct snmp_value *value,
+ u_int sub, u_int idx __unused, enum snmp_op op)
+{
+ switch (op) {
+
+ case SNMP_OP_GETNEXT:
+ abort();
+
+ case SNMP_OP_GET:
+ break;
+
+ case SNMP_OP_SET:
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ case SNMP_OP_ROLLBACK:
+ case SNMP_OP_COMMIT:
+ abort();
+ }
+
+ switch (value->var.subs[sub - 1]) {
+
+ case LEAF_ifNumber:
+ value->v.integer = mib_if_number;
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+}
+
+/*
+ * Iftable entry
+ */
+int
+op_ifentry(struct snmp_context *ctx, struct snmp_value *value,
+ u_int sub, u_int iidx __unused, enum snmp_op op)
+{
+ struct mibif *ifp = NULL;
+ int ret;
+ struct ifchange *ifc;
+ struct asn_oid idx;
+
+ switch (op) {
+
+ case SNMP_OP_GETNEXT:
+ if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->var.len = sub + 1;
+ value->var.subs[sub] = ifp->index;
+ break;
+
+ case SNMP_OP_GET:
+ if (value->var.len - sub != 1)
+ return (SNMP_ERR_NOSUCHNAME);
+ if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_SET:
+ if (value->var.len - sub != 1)
+ return (SNMP_ERR_NO_CREATION);
+ if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
+ return (SNMP_ERR_NO_CREATION);
+ if (value->var.subs[sub - 1] != LEAF_ifAdminStatus)
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ idx.len = 1;
+ idx.subs[0] = ifp->index;
+
+ if (value->v.integer != 1 && value->v.integer != 2)
+ return (SNMP_ERR_WRONG_VALUE);
+
+ if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,
+ &oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)
+ return (SNMP_ERR_RES_UNAVAIL);
+ ifc->ifindex = ifp->index;
+
+ if (ifc->set & IFC_ADMIN)
+ return (SNMP_ERR_INCONS_VALUE);
+ ifc->set |= IFC_ADMIN;
+ ifc->admin = (value->v.integer == 1) ? 1 : 0;
+
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_ROLLBACK:
+ case SNMP_OP_COMMIT:
+ return (SNMP_ERR_NOERROR);
+ }
+
+ if (ifp->mibtick < this_tick)
+ (void)mib_fetch_ifmib(ifp);
+
+ ret = SNMP_ERR_NOERROR;
+ switch (value->var.subs[sub - 1]) {
+
+ case LEAF_ifIndex:
+ value->v.integer = ifp->index;
+ break;
+
+ case LEAF_ifDescr:
+ ret = string_get(value, ifp->descr, -1);
+ break;
+
+ case LEAF_ifType:
+ value->v.integer = ifp->mib.ifmd_data.ifi_type;
+ break;
+
+ case LEAF_ifMtu:
+ value->v.integer = ifp->mib.ifmd_data.ifi_mtu;
+ break;
+
+ case LEAF_ifSpeed:
+ value->v.integer = ifp->mib.ifmd_data.ifi_baudrate;
+ break;
+
+ case LEAF_ifPhysAddress:
+ ret = string_get(value, ifp->physaddr,
+ ifp->physaddrlen);
+ break;
+
+ case LEAF_ifAdminStatus:
+ value->v.integer =
+ (ifp->mib.ifmd_flags & IFF_UP) ? 1 : 2;
+ break;
+
+ case LEAF_ifOperStatus:
+ value->v.integer =
+ (ifp->mib.ifmd_flags & IFF_RUNNING) ? 1 : 2;
+ break;
+
+ case LEAF_ifLastChange:
+ value->v.uint32 =
+ ticks_get_timeval(&ifp->mib.ifmd_data.ifi_lastchange);
+ break;
+
+ case LEAF_ifInOctets:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_ibytes;
+ break;
+
+ case LEAF_ifInUcastPkts:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_ipackets -
+ ifp->mib.ifmd_data.ifi_imcasts;
+ break;
+
+ case LEAF_ifInNUcastPkts:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;
+ break;
+
+ case LEAF_ifInDiscards:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_iqdrops;
+ break;
+
+ case LEAF_ifInErrors:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_ierrors;
+ break;
+
+ case LEAF_ifInUnknownProtos:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_noproto;
+ break;
+
+ case LEAF_ifOutOctets:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_obytes;
+ break;
+
+ case LEAF_ifOutUcastPkts:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_opackets -
+ ifp->mib.ifmd_data.ifi_omcasts;
+ break;
+
+ case LEAF_ifOutNUcastPkts:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;
+ break;
+
+ case LEAF_ifOutDiscards:
+ value->v.uint32 = ifp->mib.ifmd_snd_drops;
+ break;
+
+ case LEAF_ifOutErrors:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_oerrors;
+ break;
+
+ case LEAF_ifOutQLen:
+ value->v.uint32 = ifp->mib.ifmd_snd_len;
+ break;
+
+ case LEAF_ifSpecific:
+ value->v.oid = oid_zeroDotZero;
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+}
+
+/*
+ * IfXtable entry
+ */
+int
+op_ifxtable(struct snmp_context *ctx, struct snmp_value *value,
+ u_int sub, u_int iidx __unused, enum snmp_op op)
+{
+ struct mibif *ifp = NULL;
+ int ret;
+ struct ifchange *ifc;
+ struct asn_oid idx;
+
+ switch (op) {
+
+ again:
+ if (op != SNMP_OP_GETNEXT)
+ return (SNMP_ERR_NOSUCHNAME);
+ /* FALLTHROUGH */
+
+ case SNMP_OP_GETNEXT:
+ if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->var.len = sub + 1;
+ value->var.subs[sub] = ifp->index;
+ break;
+
+ case SNMP_OP_GET:
+ if (value->var.len - sub != 1)
+ return (SNMP_ERR_NOSUCHNAME);
+ if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_SET:
+ if (value->var.len - sub != 1)
+ return (SNMP_ERR_NO_CREATION);
+ if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
+ return (SNMP_ERR_NO_CREATION);
+
+ idx.len = 1;
+ idx.subs[0] = ifp->index;
+
+ if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,
+ &oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)
+ return (SNMP_ERR_RES_UNAVAIL);
+ ifc->ifindex = ifp->index;
+
+ switch (value->var.subs[sub - 1]) {
+
+ case LEAF_ifLinkUpDownTrapEnable:
+ if (value->v.integer != 1 && value->v.integer != 2)
+ return (SNMP_ERR_WRONG_VALUE);
+ if (ifc->set & IFC_TRAPS)
+ return (SNMP_ERR_INCONS_VALUE);
+ ifc->set |= IFC_TRAPS;
+ ifc->traps = (value->v.integer == 1) ? 1 : 0;
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_ifPromiscuousMode:
+ if (value->v.integer != 1 && value->v.integer != 2)
+ return (SNMP_ERR_WRONG_VALUE);
+ if (ifc->set & IFC_PROMISC)
+ return (SNMP_ERR_INCONS_VALUE);
+ ifc->set |= IFC_PROMISC;
+ ifc->promisc = (value->v.integer == 1) ? 1 : 0;
+ return (SNMP_ERR_NOERROR);
+ }
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ case SNMP_OP_ROLLBACK:
+ case SNMP_OP_COMMIT:
+ return (SNMP_ERR_NOERROR);
+ }
+
+ if (ifp->mibtick < this_tick)
+ (void)mib_fetch_ifmib(ifp);
+
+ ret = SNMP_ERR_NOERROR;
+ switch (value->var.subs[sub - 1]) {
+
+ case LEAF_ifName:
+ ret = string_get(value, ifp->name, -1);
+ break;
+
+ case LEAF_ifInMulticastPkts:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;
+ break;
+
+ case LEAF_ifInBroadcastPkts:
+ value->v.uint32 = 0;
+ break;
+
+ case LEAF_ifOutMulticastPkts:
+ value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;
+ break;
+
+ case LEAF_ifOutBroadcastPkts:
+ value->v.uint32 = 0;
+ break;
+
+ case LEAF_ifHCInOctets:
+ if (!(ifp->flags & MIBIF_HIGHSPEED))
+ goto again;
+ value->v.counter64 = ifp->hc_inoctets;
+ break;
+
+ case LEAF_ifHCInUcastPkts:
+ if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
+ goto again;
+ value->v.counter64 = ifp->hc_ipackets - ifp->hc_imcasts;
+ break;
+
+ case LEAF_ifHCInMulticastPkts:
+ if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
+ goto again;
+ value->v.counter64 = ifp->hc_imcasts;
+ break;
+
+ case LEAF_ifHCInBroadcastPkts:
+ if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
+ goto again;
+ value->v.counter64 = 0;
+ break;
+
+ case LEAF_ifHCOutOctets:
+ if (!(ifp->flags & MIBIF_HIGHSPEED))
+ goto again;
+ value->v.counter64 = ifp->hc_inoctets;
+ break;
+
+ case LEAF_ifHCOutUcastPkts:
+ if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
+ goto again;
+ value->v.counter64 = ifp->hc_opackets - ifp->hc_omcasts;
+ break;
+
+ case LEAF_ifHCOutMulticastPkts:
+ if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
+ goto again;
+ value->v.counter64 = ifp->hc_omcasts;
+ break;
+
+ case LEAF_ifHCOutBroadcastPkts:
+ if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
+ goto again;
+ value->v.counter64 = 0;
+ break;
+
+ case LEAF_ifLinkUpDownTrapEnable:
+ value->v.integer = ifp->trap_enable ? 1 : 2;
+ break;
+
+ case LEAF_ifHighSpeed:
+ value->v.integer =
+ (ifp->mib.ifmd_data.ifi_baudrate + 499999) / 1000000;
+ break;
+
+ case LEAF_ifPromiscuousMode:
+ value->v.integer =
+ (ifp->mib.ifmd_flags & IFF_PROMISC) ? 1 : 2;
+ break;
+
+ case LEAF_ifConnectorPresent:
+ value->v.integer = ifp->has_connector ? 1 : 2;
+ break;
+
+ case LEAF_ifAlias:
+ ret = string_get(value, "", -1);
+ break;
+
+ case LEAF_ifCounterDiscontinuityTime:
+ if (ifp->counter_disc > start_tick)
+ value->v.uint32 = ifp->counter_disc - start_tick;
+ else
+ value->v.uint32 = 0;
+ break;
+ }
+ return (ret);
+}