Path: blob/main/contrib/bsnmp/snmp_mibII/mibII_interfaces.c
39478 views
/*1* Copyright (c) 2001-20032* Fraunhofer Institute for Open Communication Systems (FhG Fokus).3* All rights reserved.4*5* Author: Harti Brandt <[email protected]>6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*28* $Begemot: bsnmp/snmp_mibII/mibII_interfaces.c,v 1.17 2006/02/14 09:04:19 brandt_h Exp $29*30* Interfaces group.31*/32#include "mibII.h"33#include "mibII_oid.h"3435/*36* This structure catches all changes to a interface entry37*/38struct ifchange {39struct snmp_dependency dep;4041u_int ifindex;4243uint32_t set;44int promisc;45int admin;46int traps;4748uint32_t rb;49int rb_flags;50int rb_traps;51};52#define IFC_PROMISC 0x000153#define IFC_ADMIN 0x000254#define IFC_TRAPS 0x000455#define IFRB_FLAGS 0x000156#define IFRB_TRAPS 0x00025758static const struct asn_oid59oid_ifTable = OIDX_ifTable;6061/*62* This function handles all changes to the interface table and interface63* extension table.64*/65static int66ifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep,67enum snmp_depop op)68{69struct ifchange *ifc = (struct ifchange *)dep;70struct mibif *ifp;71struct ifreq ifr, ifr1;7273if ((ifp = mib_find_if(ifc->ifindex)) == NULL)74return (SNMP_ERR_NO_CREATION);7576switch (op) {7778case SNMP_DEPOP_COMMIT:79strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));80if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) {81syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);82return (SNMP_ERR_GENERR);83}84if (ifc->set & IFC_PROMISC) {85ifr.ifr_flags &= ~IFF_PROMISC;86if (ifc->promisc)87ifr.ifr_flags |= IFF_PROMISC;88ifc->rb |= IFRB_FLAGS;89}90if (ifc->set & IFC_ADMIN) {91ifr.ifr_flags &= ~IFF_UP;92if (ifc->admin)93ifr.ifr_flags |= IFF_UP;94ifc->rb |= IFRB_FLAGS;95}96if (ifc->rb & IFRB_FLAGS) {97strlcpy(ifr1.ifr_name, ifp->name, sizeof(ifr1.ifr_name));98if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr1) == -1) {99syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);100return (SNMP_ERR_GENERR);101}102ifc->rb_flags = ifr1.ifr_flags;103if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {104syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);105return (SNMP_ERR_GENERR);106}107(void)mib_fetch_ifmib(ifp);108}109if (ifc->set & IFC_TRAPS) {110ifc->rb |= IFRB_TRAPS;111ifc->rb_traps = ifp->trap_enable;112ifp->trap_enable = ifc->traps;113}114return (SNMP_ERR_NOERROR);115116case SNMP_DEPOP_ROLLBACK:117if (ifc->rb & IFRB_FLAGS) {118strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));119ifr.ifr_flags = ifc->rb_flags;120if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {121syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);122return (SNMP_ERR_UNDO_FAILED);123}124(void)mib_fetch_ifmib(ifp);125}126if (ifc->rb & IFRB_TRAPS)127ifp->trap_enable = ifc->rb_traps;128return (SNMP_ERR_NOERROR);129130case SNMP_DEPOP_FINISH:131return (SNMP_ERR_NOERROR);132133}134abort();135}136137/*138* Return difference to daemon start time in ticks truncated to a139* 32-bit value. If the timeval is 0 then return 0.140*/141static uint32_t142ticks_get_timeval(struct timeval *tv)143{144uint64_t v;145146if (tv->tv_sec != 0 || tv->tv_usec != 0) {147v = 100ULL * tv->tv_sec + tv->tv_usec / 10000ULL;148if (v > start_tick)149return (v - start_tick);150}151return (0);152}153154/*155* Scalars156*/157int158op_interfaces(struct snmp_context *ctx __unused, struct snmp_value *value,159u_int sub, u_int idx __unused, enum snmp_op op)160{161switch (op) {162163case SNMP_OP_GETNEXT:164abort();165166case SNMP_OP_GET:167break;168169case SNMP_OP_SET:170return (SNMP_ERR_NOT_WRITEABLE);171172case SNMP_OP_ROLLBACK:173case SNMP_OP_COMMIT:174abort();175}176177switch (value->var.subs[sub - 1]) {178179case LEAF_ifNumber:180value->v.integer = mib_if_number;181break;182}183return (SNMP_ERR_NOERROR);184}185186/*187* Iftable entry188*/189int190op_ifentry(struct snmp_context *ctx, struct snmp_value *value,191u_int sub, u_int iidx __unused, enum snmp_op op)192{193struct mibif *ifp = NULL;194int ret;195struct ifchange *ifc;196struct asn_oid idx;197198switch (op) {199200case SNMP_OP_GETNEXT:201if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)202return (SNMP_ERR_NOSUCHNAME);203value->var.len = sub + 1;204value->var.subs[sub] = ifp->index;205break;206207case SNMP_OP_GET:208if (value->var.len - sub != 1)209return (SNMP_ERR_NOSUCHNAME);210if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)211return (SNMP_ERR_NOSUCHNAME);212break;213214case SNMP_OP_SET:215if (value->var.len - sub != 1)216return (SNMP_ERR_NO_CREATION);217if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)218return (SNMP_ERR_NO_CREATION);219if (value->var.subs[sub - 1] != LEAF_ifAdminStatus)220return (SNMP_ERR_NOT_WRITEABLE);221222idx.len = 1;223idx.subs[0] = ifp->index;224225if (value->v.integer != 1 && value->v.integer != 2)226return (SNMP_ERR_WRONG_VALUE);227228if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,229&oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)230return (SNMP_ERR_RES_UNAVAIL);231ifc->ifindex = ifp->index;232233if (ifc->set & IFC_ADMIN)234return (SNMP_ERR_INCONS_VALUE);235ifc->set |= IFC_ADMIN;236ifc->admin = (value->v.integer == 1) ? 1 : 0;237238return (SNMP_ERR_NOERROR);239240case SNMP_OP_ROLLBACK:241case SNMP_OP_COMMIT:242return (SNMP_ERR_NOERROR);243}244245if (ifp->mibtick < this_tick)246(void)mib_fetch_ifmib(ifp);247248ret = SNMP_ERR_NOERROR;249switch (value->var.subs[sub - 1]) {250251case LEAF_ifIndex:252value->v.integer = ifp->index;253break;254255case LEAF_ifDescr:256ret = string_get(value, ifp->descr, -1);257break;258259case LEAF_ifType:260value->v.integer = ifp->mib.ifmd_data.ifi_type;261break;262263case LEAF_ifMtu:264value->v.integer = ifp->mib.ifmd_data.ifi_mtu;265break;266267case LEAF_ifSpeed:268value->v.integer = ifp->mib.ifmd_data.ifi_baudrate;269break;270271case LEAF_ifPhysAddress:272ret = string_get(value, ifp->physaddr,273ifp->physaddrlen);274break;275276case LEAF_ifAdminStatus:277value->v.integer =278(ifp->mib.ifmd_flags & IFF_UP) ? 1 : 2;279break;280281case LEAF_ifOperStatus:282/*283* According to RFC 2863 the state should be Up if the284* interface is ready to transmit packets. We takes this to285* mean that the interface should be running and should have286* a carrier. If it is running and has no carrier we interpret287* this as 'waiting for an external event' (plugging in the288* cable) and hence return 'dormant'.289*/290if (ifp->mib.ifmd_flags & IFF_RUNNING) {291if (ifp->mib.ifmd_data.ifi_link_state != LINK_STATE_UP)292value->v.integer = 5; /* state dormant */293else294value->v.integer = 1; /* state up */295} else296value->v.integer = 2; /* state down */297break;298299case LEAF_ifLastChange:300value->v.uint32 =301ticks_get_timeval(&ifp->mib.ifmd_data.ifi_lastchange);302break;303304case LEAF_ifInOctets:305value->v.uint32 = ifp->mib.ifmd_data.ifi_ibytes;306break;307308case LEAF_ifInUcastPkts:309value->v.uint32 = ifp->mib.ifmd_data.ifi_ipackets -310ifp->mib.ifmd_data.ifi_imcasts;311break;312313case LEAF_ifInNUcastPkts:314value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;315break;316317case LEAF_ifInDiscards:318value->v.uint32 = ifp->mib.ifmd_data.ifi_iqdrops;319break;320321case LEAF_ifInErrors:322value->v.uint32 = ifp->mib.ifmd_data.ifi_ierrors;323break;324325case LEAF_ifInUnknownProtos:326value->v.uint32 = ifp->mib.ifmd_data.ifi_noproto;327break;328329case LEAF_ifOutOctets:330value->v.uint32 = ifp->mib.ifmd_data.ifi_obytes;331break;332333case LEAF_ifOutUcastPkts:334value->v.uint32 = ifp->mib.ifmd_data.ifi_opackets -335ifp->mib.ifmd_data.ifi_omcasts;336break;337338case LEAF_ifOutNUcastPkts:339value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;340break;341342case LEAF_ifOutDiscards:343value->v.uint32 = ifp->mib.ifmd_snd_drops;344break;345346case LEAF_ifOutErrors:347value->v.uint32 = ifp->mib.ifmd_data.ifi_oerrors;348break;349350case LEAF_ifOutQLen:351value->v.uint32 = ifp->mib.ifmd_snd_len;352break;353354case LEAF_ifSpecific:355value->v.oid = ifp->spec_oid;356break;357}358return (ret);359}360361/*362* IfXtable entry363*/364int365op_ifxtable(struct snmp_context *ctx, struct snmp_value *value,366u_int sub, u_int iidx __unused, enum snmp_op op)367{368struct mibif *ifp = NULL;369int ret;370struct ifchange *ifc;371struct asn_oid idx;372373switch (op) {374375case SNMP_OP_GETNEXT:376if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)377return (SNMP_ERR_NOSUCHNAME);378value->var.len = sub + 1;379value->var.subs[sub] = ifp->index;380break;381382case SNMP_OP_GET:383if (value->var.len - sub != 1)384return (SNMP_ERR_NOSUCHNAME);385if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)386return (SNMP_ERR_NOSUCHNAME);387break;388389case SNMP_OP_SET:390if (value->var.len - sub != 1)391return (SNMP_ERR_NO_CREATION);392if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)393return (SNMP_ERR_NO_CREATION);394395idx.len = 1;396idx.subs[0] = ifp->index;397398if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,399&oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)400return (SNMP_ERR_RES_UNAVAIL);401ifc->ifindex = ifp->index;402403switch (value->var.subs[sub - 1]) {404405case LEAF_ifLinkUpDownTrapEnable:406if (value->v.integer != 1 && value->v.integer != 2)407return (SNMP_ERR_WRONG_VALUE);408if (ifc->set & IFC_TRAPS)409return (SNMP_ERR_INCONS_VALUE);410ifc->set |= IFC_TRAPS;411ifc->traps = (value->v.integer == 1) ? 1 : 0;412return (SNMP_ERR_NOERROR);413414case LEAF_ifPromiscuousMode:415if (value->v.integer != 1 && value->v.integer != 2)416return (SNMP_ERR_WRONG_VALUE);417if (ifc->set & IFC_PROMISC)418return (SNMP_ERR_INCONS_VALUE);419ifc->set |= IFC_PROMISC;420ifc->promisc = (value->v.integer == 1) ? 1 : 0;421return (SNMP_ERR_NOERROR);422}423return (SNMP_ERR_NOT_WRITEABLE);424425case SNMP_OP_ROLLBACK:426case SNMP_OP_COMMIT:427return (SNMP_ERR_NOERROR);428}429430if (ifp->mibtick < this_tick)431(void)mib_fetch_ifmib(ifp);432433ret = SNMP_ERR_NOERROR;434switch (value->var.subs[sub - 1]) {435436case LEAF_ifName:437ret = string_get(value, ifp->name, -1);438break;439440case LEAF_ifInMulticastPkts:441value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;442break;443444case LEAF_ifInBroadcastPkts:445value->v.uint32 = 0;446break;447448case LEAF_ifOutMulticastPkts:449value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;450break;451452case LEAF_ifOutBroadcastPkts:453value->v.uint32 = 0;454break;455456case LEAF_ifHCInOctets:457value->v.counter64 = MIBIF_PRIV(ifp)->hc_inoctets;458break;459460case LEAF_ifHCInUcastPkts:461value->v.counter64 = MIBIF_PRIV(ifp)->hc_ipackets -462MIBIF_PRIV(ifp)->hc_imcasts;463break;464465case LEAF_ifHCInMulticastPkts:466value->v.counter64 = MIBIF_PRIV(ifp)->hc_imcasts;467break;468469case LEAF_ifHCInBroadcastPkts:470value->v.counter64 = 0;471break;472473case LEAF_ifHCOutOctets:474value->v.counter64 = MIBIF_PRIV(ifp)->hc_outoctets;475break;476477case LEAF_ifHCOutUcastPkts:478value->v.counter64 = MIBIF_PRIV(ifp)->hc_opackets -479MIBIF_PRIV(ifp)->hc_omcasts;480break;481482case LEAF_ifHCOutMulticastPkts:483value->v.counter64 = MIBIF_PRIV(ifp)->hc_omcasts;484break;485486case LEAF_ifHCOutBroadcastPkts:487value->v.counter64 = 0;488break;489490case LEAF_ifLinkUpDownTrapEnable:491value->v.integer = ifp->trap_enable ? 1 : 2;492break;493494case LEAF_ifHighSpeed:495value->v.integer =496(ifp->mib.ifmd_data.ifi_baudrate + 499999) / 1000000;497break;498499case LEAF_ifPromiscuousMode:500value->v.integer =501(ifp->mib.ifmd_flags & IFF_PROMISC) ? 1 : 2;502break;503504case LEAF_ifConnectorPresent:505value->v.integer = ifp->has_connector ? 1 : 2;506break;507508case LEAF_ifAlias:509ret = string_get(value, ifp->alias, ifp->alias_size - 1);510break;511512case LEAF_ifCounterDiscontinuityTime:513if (ifp->counter_disc > start_tick)514value->v.uint32 = ifp->counter_disc - start_tick;515else516value->v.uint32 = 0;517break;518}519return (ret);520}521522523