Path: blob/main/contrib/bsnmp/snmp_mibII/mibII_ipaddr.c
39478 views
/*1* Copyright (c) 2001-20022* 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_ipaddr.c,v 1.10 2005/10/04 11:21:35 brandt_h Exp $29*30* IP address table. This table is writeable!31*32* Writing to this table will add a new IP address to the interface.33* An address can be deleted with writing the interface index 0.34*/35#include "mibII.h"36#include "mibII_oid.h"3738static const struct asn_oid39oid_ipAddrTable = OIDX_ipAddrTable;4041/*42* Be careful not to hold any pointers during the SET processing - the43* interface and address lists can be relocated at any time.44*/45struct update {46struct snmp_dependency dep;4748uint32_t set;49struct in_addr addr;50struct in_addr mask;51int bcast;52u_int ifindex;5354uint32_t rb;55struct in_addr rb_mask;56struct in_addr rb_bcast;57};58#define UPD_IFINDEX 0x000159#define UPD_MASK 0x000260#define UPD_BCAST 0x000461#define RB_CREATE 0x000162#define RB_DESTROY 0x000263#define RB_MODIFY 0x00046465/*66* Create a new interface address67*/68static int69create(struct update *upd)70{71struct in_addr bcast;72struct mibifa *ifa;7374if (!(upd->set & UPD_MASK)) {75if (IN_CLASSA(ntohl(upd->addr.s_addr)))76upd->mask.s_addr = htonl(IN_CLASSA_NET);77else if (IN_CLASSB(ntohl(upd->addr.s_addr)))78upd->mask.s_addr = htonl(IN_CLASSB_NET);79else if (IN_CLASSC(ntohl(upd->addr.s_addr)))80upd->mask.s_addr = htonl(IN_CLASSC_NET);81else82upd->mask.s_addr = 0xffffffff;83}8485bcast.s_addr = upd->addr.s_addr & upd->mask.s_addr;86if (!(upd->set & UPD_BCAST) || upd->bcast) {87uint32_t tmp = ~ntohl(upd->mask.s_addr);88bcast.s_addr |= htonl(0xffffffff & ~tmp);89}9091if ((ifa = mib_create_ifa(upd->ifindex, upd->addr, upd->mask, bcast))92== NULL)93return (SNMP_ERR_GENERR);9495upd->rb |= RB_CREATE;96return (SNMP_ERR_NOERROR);97}9899/*100* Modify the netmask or broadcast address. The ifindex cannot be101* changed (obviously).102*/103static int104modify(struct update *upd, struct mibifa *ifa)105{106struct mibif *ifp;107108if ((ifp = mib_find_if(ifa->ifindex)) == NULL)109return (SNMP_ERR_WRONG_VALUE);110if ((upd->set & UPD_IFINDEX) && upd->ifindex != ifa->ifindex)111return (SNMP_ERR_INCONS_VALUE);112113upd->rb_mask = ifa->inmask;114upd->rb_bcast = ifa->inbcast;115if (((upd->set & UPD_MASK) && upd->mask.s_addr != ifa->inmask.s_addr) ||116(upd->set & UPD_BCAST)) {117if (upd->set & UPD_MASK)118ifa->inmask = upd->mask;119if (upd->set & UPD_BCAST) {120ifa->inbcast.s_addr = ifa->inaddr.s_addr121& ifa->inmask.s_addr;122if (upd->bcast)123ifa->inbcast.s_addr |= 0xffffffff124& ~ifa->inmask.s_addr;125}126if (mib_modify_ifa(ifa)) {127syslog(LOG_ERR, "set netmask/bcast: %m");128ifa->inmask = upd->rb_mask;129ifa->inbcast = upd->rb_bcast;130mib_unmodify_ifa(ifa);131return (SNMP_ERR_GENERR);132}133upd->rb |= RB_MODIFY;134}135return (SNMP_ERR_NOERROR);136}137138/*139* Destroy the given row in the table. We remove the address from the140* system, but keep the structure around for the COMMIT. It's deleted141* only in the FINISH operation.142*/143static int144destroy(struct snmp_context *ctx __unused, struct update *upd,145struct mibifa *ifa)146{147if (mib_destroy_ifa(ifa))148return (SNMP_ERR_GENERR);149upd->rb |= RB_DESTROY;150return (SNMP_ERR_NOERROR);151}152153/*154* This function is called to commit/rollback a SET on an IpAddrEntry155*/156static int157update_func(struct snmp_context *ctx, struct snmp_dependency *dep,158enum snmp_depop op)159{160struct update *upd = (struct update *)dep;161struct mibifa *ifa;162163switch (op) {164165case SNMP_DEPOP_COMMIT:166if ((ifa = mib_find_ifa(upd->addr)) == NULL) {167/* non existing entry - must have ifindex */168if (!(upd->set & UPD_IFINDEX))169return (SNMP_ERR_INCONS_NAME);170return (create(upd));171}172/* existing entry */173if ((upd->set & UPD_IFINDEX) && upd->ifindex == 0) {174/* delete */175return (destroy(ctx, upd, ifa));176}177/* modify entry */178return (modify(upd, ifa));179180case SNMP_DEPOP_ROLLBACK:181if ((ifa = mib_find_ifa(upd->addr)) == NULL) {182/* ups */183mib_iflist_bad = 1;184return (SNMP_ERR_NOERROR);185}186if (upd->rb & RB_CREATE) {187mib_uncreate_ifa(ifa);188return (SNMP_ERR_NOERROR);189}190if (upd->rb & RB_DESTROY) {191mib_undestroy_ifa(ifa);192return (SNMP_ERR_NOERROR);193}194if (upd->rb & RB_MODIFY) {195ifa->inmask = upd->rb_mask;196ifa->inbcast = upd->rb_bcast;197mib_unmodify_ifa(ifa);198return (SNMP_ERR_NOERROR);199}200return (SNMP_ERR_NOERROR);201202case SNMP_DEPOP_FINISH:203if ((upd->rb & RB_DESTROY) &&204(ifa = mib_find_ifa(upd->addr)) != NULL &&205(ifa->flags & MIBIFA_DESTROYED)) {206TAILQ_REMOVE(&mibifa_list, ifa, link);207free(ifa);208}209return (SNMP_ERR_NOERROR);210}211abort();212}213214/**********************************************************************/215/*216* ACTION217*/218int219op_ipaddr(struct snmp_context *ctx, struct snmp_value *value,220u_int sub, u_int iidx, enum snmp_op op)221{222asn_subid_t which;223struct mibifa *ifa;224struct update *upd;225struct asn_oid idx;226u_char ipaddr[4];227228which = value->var.subs[sub - 1];229230ifa = NULL;231232switch (op) {233234case SNMP_OP_GETNEXT:235if ((ifa = NEXT_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL)236return (SNMP_ERR_NOSUCHNAME);237index_append(&value->var, sub, &ifa->index);238break;239240case SNMP_OP_GET:241if ((ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL)242return (SNMP_ERR_NOSUCHNAME);243break;244245case SNMP_OP_SET:246if (index_decode(&value->var, sub, iidx, ipaddr))247return (SNMP_ERR_NO_CREATION);248ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub);249idx.len = 4;250idx.subs[0] = ipaddr[0];251idx.subs[1] = ipaddr[1];252idx.subs[2] = ipaddr[2];253idx.subs[3] = ipaddr[3];254255if ((upd = (struct update *)snmp_dep_lookup(ctx,256&oid_ipAddrTable, &idx, sizeof(*upd), update_func)) == NULL)257return (SNMP_ERR_RES_UNAVAIL);258259upd->addr.s_addr = htonl((ipaddr[0] << 24) | (ipaddr[1] << 16) |260(ipaddr[2] << 8) | (ipaddr[3] << 0));261262switch (which) {263264case LEAF_ipAdEntIfIndex:265if (upd->set & UPD_IFINDEX)266return (SNMP_ERR_INCONS_VALUE);267if (value->v.integer < 0 ||268value->v.integer > 0x07fffffff)269return (SNMP_ERR_WRONG_VALUE);270if (ifa != NULL) {271if (ifa->ifindex != (u_int)value->v.integer &&272value->v.integer != 0)273return (SNMP_ERR_INCONS_VALUE);274}275upd->set |= UPD_IFINDEX;276upd->ifindex = (u_int)value->v.integer;277break;278279case LEAF_ipAdEntNetMask:280if (upd->set & UPD_MASK)281return (SNMP_ERR_INCONS_VALUE);282upd->mask.s_addr = htonl((value->v.ipaddress[0] << 24)283| (value->v.ipaddress[1] << 16)284| (value->v.ipaddress[2] << 8)285| (value->v.ipaddress[3] << 0));286upd->set |= UPD_MASK;287break;288289case LEAF_ipAdEntBcastAddr:290if (upd->set & UPD_BCAST)291return (SNMP_ERR_INCONS_VALUE);292if (value->v.integer != 0 && value->v.integer != 1)293return (SNMP_ERR_WRONG_VALUE);294upd->bcast = value->v.integer;295upd->set |= UPD_BCAST;296break;297298}299return (SNMP_ERR_NOERROR);300301case SNMP_OP_ROLLBACK:302case SNMP_OP_COMMIT:303return (SNMP_ERR_NOERROR);304}305306switch (which) {307308case LEAF_ipAdEntAddr:309value->v.ipaddress[0] = ifa->index.subs[0];310value->v.ipaddress[1] = ifa->index.subs[1];311value->v.ipaddress[2] = ifa->index.subs[2];312value->v.ipaddress[3] = ifa->index.subs[3];313break;314315case LEAF_ipAdEntIfIndex:316if (ifa->flags & MIBIFA_DESTROYED)317value->v.integer = 0;318else319value->v.integer = ifa->ifindex;320break;321322case LEAF_ipAdEntNetMask:323value->v.ipaddress[0] = (ntohl(ifa->inmask.s_addr) >> 24) & 0xff;324value->v.ipaddress[1] = (ntohl(ifa->inmask.s_addr) >> 16) & 0xff;325value->v.ipaddress[2] = (ntohl(ifa->inmask.s_addr) >> 8) & 0xff;326value->v.ipaddress[3] = (ntohl(ifa->inmask.s_addr) >> 0) & 0xff;327break;328329case LEAF_ipAdEntBcastAddr:330value->v.integer = ntohl(ifa->inbcast.s_addr) & 1;331break;332333334case LEAF_ipAdEntReasmMaxSize:335value->v.integer = 65535;336break;337}338return (SNMP_ERR_NOERROR);339}340341342