mibII_ipaddr.c revision 128237
1258331Smarkj/* 2258331Smarkj * Copyright (c) 2001-2002 3258331Smarkj * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4258331Smarkj * All rights reserved. 5258331Smarkj * 6258331Smarkj * Author: Harti Brandt <harti@freebsd.org> 7258331Smarkj * 8258331Smarkj * Redistribution of this software and documentation and use in source and 9258331Smarkj * binary forms, with or without modification, are permitted provided that 10258331Smarkj * the following conditions are met: 11258331Smarkj * 12258331Smarkj * 1. Redistributions of source code or documentation must retain the above 13258331Smarkj * copyright notice, this list of conditions and the following disclaimer. 14258331Smarkj * 2. Redistributions in binary form must reproduce the above copyright 15258331Smarkj * notice, this list of conditions and the following disclaimer in the 16258331Smarkj * documentation and/or other materials provided with the distribution. 17258331Smarkj * 3. Neither the name of the Institute nor the names of its contributors 18258331Smarkj * may be used to endorse or promote products derived from this software 19258331Smarkj * without specific prior written permission. 20258331Smarkj * 21258331Smarkj * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS 22258331Smarkj * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23258331Smarkj * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24258331Smarkj * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25258331Smarkj * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26258331Smarkj * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27258331Smarkj * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28258331Smarkj * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29258331Smarkj * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30258331Smarkj * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31258331Smarkj * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32258331Smarkj * 33258331Smarkj * $Begemot: bsnmp/snmp_mibII/mibII_ipaddr.c,v 1.8 2004/04/13 14:58:46 novo Exp $ 34258331Smarkj * 35258331Smarkj * IP address table. This table is writeable! 36258331Smarkj * 37258331Smarkj * Writing to this table will add a new IP address to the interface. 38258331Smarkj * An address can be deleted with writing the interface index 0. 39258331Smarkj */ 40258331Smarkj#include "mibII.h" 41258331Smarkj#include "mibII_oid.h" 42258331Smarkj 43258331Smarkjstatic const struct asn_oid 44258331Smarkj oid_ipAddrTable = OIDX_ipAddrTable; 45258331Smarkj 46258331Smarkj/* 47258331Smarkj * Be careful not to hold any pointers during the SET processing - the 48258331Smarkj * interface and address lists can be relocated at any time. 49258331Smarkj */ 50258331Smarkjstruct update { 51258331Smarkj struct snmp_dependency dep; 52258331Smarkj 53258331Smarkj u_int32_t set; 54258331Smarkj struct in_addr addr; 55258331Smarkj struct in_addr mask; 56258331Smarkj int bcast; 57258331Smarkj u_int ifindex; 58258331Smarkj 59258331Smarkj u_int32_t rb; 60258331Smarkj struct in_addr rb_mask; 61258331Smarkj struct in_addr rb_bcast; 62258331Smarkj}; 63258331Smarkj#define UPD_IFINDEX 0x0001 64258331Smarkj#define UPD_MASK 0x0002 65258331Smarkj#define UPD_BCAST 0x0004 66258331Smarkj#define RB_CREATE 0x0001 67258331Smarkj#define RB_DESTROY 0x0002 68258331Smarkj#define RB_MODIFY 0x0004 69258331Smarkj 70258331Smarkj/* 71258331Smarkj * Create a new interface address 72258331Smarkj */ 73258331Smarkjstatic int 74258331Smarkjcreate(struct update *upd) 75258331Smarkj{ 76258331Smarkj struct in_addr bcast; 77258331Smarkj struct mibifa *ifa; 78258331Smarkj 79258331Smarkj if (!(upd->set & UPD_MASK)) { 80258331Smarkj if (IN_CLASSA(ntohl(upd->addr.s_addr))) 81258331Smarkj upd->mask.s_addr = htonl(IN_CLASSA_NET); 82258331Smarkj else if (IN_CLASSB(ntohl(upd->addr.s_addr))) 83258331Smarkj upd->mask.s_addr = htonl(IN_CLASSB_NET); 84258331Smarkj else if (IN_CLASSC(ntohl(upd->addr.s_addr))) 85258331Smarkj upd->mask.s_addr = htonl(IN_CLASSC_NET); 86258331Smarkj else 87258331Smarkj upd->mask.s_addr = 0xffffffff; 88258331Smarkj } 89258331Smarkj 90258331Smarkj bcast.s_addr = upd->addr.s_addr & upd->mask.s_addr; 91258331Smarkj if (!(upd->set & UPD_BCAST) || upd->bcast) 92258331Smarkj bcast.s_addr |= htonl(0xffffffff & ~ntohl(upd->mask.s_addr)); 93258331Smarkj 94258331Smarkj if ((ifa = mib_create_ifa(upd->ifindex, upd->addr, upd->mask, bcast)) == NULL) 95258331Smarkj return (SNMP_ERR_GENERR); 96258331Smarkj 97258331Smarkj upd->rb |= RB_CREATE; 98258331Smarkj return (SNMP_ERR_NOERROR); 99258331Smarkj} 100258331Smarkj 101258331Smarkj/* 102258331Smarkj * Modify the netmask or broadcast address. The ifindex cannot be 103258331Smarkj * changed (obviously). 104258331Smarkj */ 105258331Smarkjstatic int 106258331Smarkjmodify(struct update *upd, struct mibifa *ifa) 107258331Smarkj{ 108258331Smarkj struct mibif *ifp; 109258331Smarkj 110258331Smarkj if ((ifp = mib_find_if(ifa->ifindex)) == NULL) 111258331Smarkj return (SNMP_ERR_WRONG_VALUE); 112258331Smarkj if ((upd->set & UPD_IFINDEX) && upd->ifindex != ifa->ifindex) 113258331Smarkj return (SNMP_ERR_INCONS_VALUE); 114258331Smarkj 115258331Smarkj upd->rb_mask = ifa->inmask; 116258331Smarkj upd->rb_bcast = ifa->inbcast; 117258331Smarkj if (((upd->set & UPD_MASK) && upd->mask.s_addr != ifa->inmask.s_addr) || 118258331Smarkj (upd->set & UPD_BCAST)) { 119258331Smarkj if (upd->set & UPD_MASK) 120258331Smarkj ifa->inmask = upd->mask; 121258331Smarkj if (upd->set & UPD_BCAST) { 122258331Smarkj ifa->inbcast.s_addr = ifa->inaddr.s_addr 123258331Smarkj & ifa->inmask.s_addr; 124258331Smarkj if (upd->bcast) 125258331Smarkj ifa->inbcast.s_addr |= 0xffffffff 126258331Smarkj & ~ifa->inmask.s_addr; 127258331Smarkj } 128258331Smarkj if (mib_modify_ifa(ifa)) { 129258331Smarkj syslog(LOG_ERR, "set netmask/bcast: %m"); 130258331Smarkj ifa->inmask = upd->rb_mask; 131258331Smarkj ifa->inbcast = upd->rb_bcast; 132258331Smarkj mib_unmodify_ifa(ifa); 133258331Smarkj return (SNMP_ERR_GENERR); 134258331Smarkj } 135258331Smarkj upd->rb |= RB_MODIFY; 136258331Smarkj } 137258331Smarkj return (SNMP_ERR_NOERROR); 138258331Smarkj} 139258331Smarkj 140258331Smarkj/* 141258331Smarkj * Destroy the given row in the table. We remove the address from the 142258331Smarkj * system, but keep the structure around for the COMMIT. It's deleted 143258331Smarkj * only in the FINISH operation. 144258331Smarkj */ 145258331Smarkjstatic int 146258331Smarkjdestroy(struct snmp_context *ctx __unused, struct update *upd, 147258331Smarkj struct mibifa *ifa) 148258331Smarkj{ 149258331Smarkj if (mib_destroy_ifa(ifa)) 150258331Smarkj return (SNMP_ERR_GENERR); 151258331Smarkj upd->rb |= RB_DESTROY; 152258331Smarkj return (SNMP_ERR_NOERROR); 153258331Smarkj} 154258331Smarkj 155258331Smarkj/* 156258331Smarkj * This function is called to commit/rollback a SET on an IpAddrEntry 157258331Smarkj */ 158258331Smarkjstatic int 159258331Smarkjupdate_func(struct snmp_context *ctx, struct snmp_dependency *dep, 160258331Smarkj enum snmp_depop op) 161258331Smarkj{ 162258331Smarkj struct update *upd = (struct update *)dep; 163258331Smarkj struct mibifa *ifa; 164258331Smarkj 165258331Smarkj switch (op) { 166258331Smarkj 167258331Smarkj case SNMP_DEPOP_COMMIT: 168258331Smarkj if ((ifa = mib_find_ifa(upd->addr)) == NULL) { 169258331Smarkj /* non existing entry - must have ifindex */ 170258331Smarkj if (!(upd->set & UPD_IFINDEX)) 171258331Smarkj return (SNMP_ERR_INCONS_NAME); 172258331Smarkj return (create(upd)); 173258331Smarkj } 174258331Smarkj /* existing entry */ 175258331Smarkj if ((upd->set & UPD_IFINDEX) && upd->ifindex == 0) { 176258331Smarkj /* delete */ 177258331Smarkj return (destroy(ctx, upd, ifa)); 178258331Smarkj } 179258331Smarkj /* modify entry */ 180258331Smarkj return (modify(upd, ifa)); 181258331Smarkj 182258331Smarkj case SNMP_DEPOP_ROLLBACK: 183258331Smarkj if ((ifa = mib_find_ifa(upd->addr)) == NULL) { 184258331Smarkj /* ups */ 185258331Smarkj mib_iflist_bad = 1; 186258331Smarkj return (SNMP_ERR_NOERROR); 187258331Smarkj } 188258331Smarkj if (upd->rb & RB_CREATE) { 189258331Smarkj mib_uncreate_ifa(ifa); 190258331Smarkj return (SNMP_ERR_NOERROR); 191258331Smarkj } 192258331Smarkj if (upd->rb & RB_DESTROY) { 193258331Smarkj mib_undestroy_ifa(ifa); 194258331Smarkj return (SNMP_ERR_NOERROR); 195258331Smarkj } 196258331Smarkj if (upd->rb & RB_MODIFY) { 197258331Smarkj ifa->inmask = upd->rb_mask; 198258331Smarkj ifa->inbcast = upd->rb_bcast; 199258331Smarkj mib_unmodify_ifa(ifa); 200258331Smarkj return (SNMP_ERR_NOERROR); 201258331Smarkj } 202258331Smarkj return (SNMP_ERR_NOERROR); 203258331Smarkj 204258331Smarkj case SNMP_DEPOP_FINISH: 205258331Smarkj if ((upd->rb & RB_DESTROY) && 206258331Smarkj (ifa = mib_find_ifa(upd->addr)) != NULL && 207258331Smarkj (ifa->flags & MIBIFA_DESTROYED)) { 208258331Smarkj TAILQ_REMOVE(&mibifa_list, ifa, link); 209258331Smarkj free(ifa); 210258331Smarkj } 211258331Smarkj return (SNMP_ERR_NOERROR); 212258331Smarkj } 213258331Smarkj abort(); 214258331Smarkj} 215258331Smarkj 216258331Smarkj/**********************************************************************/ 217258331Smarkj/* 218258331Smarkj * ACTION 219258331Smarkj */ 220258331Smarkjint 221258331Smarkjop_ipaddr(struct snmp_context *ctx, struct snmp_value *value, 222258331Smarkj u_int sub, u_int iidx, enum snmp_op op) 223258331Smarkj{ 224258331Smarkj asn_subid_t which; 225258331Smarkj struct mibifa *ifa; 226258331Smarkj struct update *upd; 227258331Smarkj struct asn_oid idx; 228258331Smarkj u_char ipaddr[4]; 229258331Smarkj 230258331Smarkj which = value->var.subs[sub - 1]; 231258331Smarkj 232258331Smarkj ifa = NULL; 233258331Smarkj 234258331Smarkj switch (op) { 235258331Smarkj 236258331Smarkj case SNMP_OP_GETNEXT: 237258331Smarkj if ((ifa = NEXT_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL) 238258331Smarkj return (SNMP_ERR_NOSUCHNAME); 239258331Smarkj index_append(&value->var, sub, &ifa->index); 240258331Smarkj break; 241258331Smarkj 242258331Smarkj case SNMP_OP_GET: 243258331Smarkj if ((ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL) 244258331Smarkj return (SNMP_ERR_NOSUCHNAME); 245258331Smarkj break; 246258331Smarkj 247258331Smarkj case SNMP_OP_SET: 248258331Smarkj if (index_decode(&value->var, sub, iidx, ipaddr)) 249258331Smarkj return (SNMP_ERR_NO_CREATION); 250258331Smarkj ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub); 251258331Smarkj idx.len = 4; 252258331Smarkj idx.subs[0] = ipaddr[0]; 253258331Smarkj idx.subs[1] = ipaddr[1]; 254258331Smarkj idx.subs[2] = ipaddr[2]; 255258331Smarkj idx.subs[3] = ipaddr[3]; 256258331Smarkj 257258331Smarkj if ((upd = (struct update *)snmp_dep_lookup(ctx, 258258331Smarkj &oid_ipAddrTable, &idx, sizeof(*upd), update_func)) == NULL) 259258331Smarkj return (SNMP_ERR_RES_UNAVAIL); 260258331Smarkj 261258331Smarkj upd->addr.s_addr = htonl((ipaddr[0] << 24) | (ipaddr[1] << 16) | 262258331Smarkj (ipaddr[2] << 8) | (ipaddr[3] << 0)); 263258331Smarkj 264258331Smarkj switch (which) { 265258331Smarkj 266258331Smarkj case LEAF_ipAdEntIfIndex: 267258331Smarkj if (upd->set & UPD_IFINDEX) 268258331Smarkj return (SNMP_ERR_INCONS_VALUE); 269258331Smarkj if (value->v.integer < 0 || 270258331Smarkj value->v.integer > 0x07fffffff) 271258331Smarkj return (SNMP_ERR_WRONG_VALUE); 272258331Smarkj if (ifa != NULL) { 273258331Smarkj if (ifa->ifindex != (u_int)value->v.integer && 274258331Smarkj value->v.integer != 0) 275258331Smarkj return (SNMP_ERR_INCONS_VALUE); 276258331Smarkj } 277258331Smarkj upd->set |= UPD_IFINDEX; 278258331Smarkj upd->ifindex = (u_int)value->v.integer; 279258331Smarkj break; 280258331Smarkj 281258331Smarkj case LEAF_ipAdEntNetMask: 282258331Smarkj if (upd->set & UPD_MASK) 283258331Smarkj return (SNMP_ERR_INCONS_VALUE); 284258331Smarkj upd->mask.s_addr = htonl((value->v.ipaddress[0] << 24) 285258331Smarkj | (value->v.ipaddress[1] << 16) 286258331Smarkj | (value->v.ipaddress[2] << 8) 287258331Smarkj | (value->v.ipaddress[3] << 0)); 288258331Smarkj upd->set |= UPD_MASK; 289258331Smarkj break; 290258331Smarkj 291258331Smarkj case LEAF_ipAdEntBcastAddr: 292258331Smarkj if (upd->set & UPD_BCAST) 293258331Smarkj return (SNMP_ERR_INCONS_VALUE); 294258331Smarkj if (value->v.integer != 0 && value->v.integer != 1) 295258331Smarkj return (SNMP_ERR_WRONG_VALUE); 296258331Smarkj upd->bcast = value->v.integer; 297258331Smarkj upd->set |= UPD_BCAST; 298258331Smarkj break; 299258331Smarkj 300258331Smarkj } 301258331Smarkj return (SNMP_ERR_NOERROR); 302258331Smarkj 303258331Smarkj case SNMP_OP_ROLLBACK: 304258331Smarkj case SNMP_OP_COMMIT: 305258331Smarkj return (SNMP_ERR_NOERROR); 306258331Smarkj } 307258331Smarkj 308258331Smarkj switch (which) { 309258331Smarkj 310258331Smarkj case LEAF_ipAdEntAddr: 311258331Smarkj value->v.ipaddress[0] = ifa->index.subs[0]; 312258331Smarkj value->v.ipaddress[1] = ifa->index.subs[1]; 313258331Smarkj value->v.ipaddress[2] = ifa->index.subs[2]; 314258331Smarkj value->v.ipaddress[3] = ifa->index.subs[3]; 315258331Smarkj break; 316258331Smarkj 317258331Smarkj case LEAF_ipAdEntIfIndex: 318258331Smarkj if (ifa->flags & MIBIFA_DESTROYED) 319258331Smarkj value->v.integer = 0; 320258331Smarkj else 321258331Smarkj value->v.integer = ifa->ifindex; 322258331Smarkj break; 323258331Smarkj 324258331Smarkj case LEAF_ipAdEntNetMask: 325258331Smarkj value->v.ipaddress[0] = (ntohl(ifa->inmask.s_addr) >> 24) & 0xff; 326258331Smarkj value->v.ipaddress[1] = (ntohl(ifa->inmask.s_addr) >> 16) & 0xff; 327258331Smarkj value->v.ipaddress[2] = (ntohl(ifa->inmask.s_addr) >> 8) & 0xff; 328258331Smarkj value->v.ipaddress[3] = (ntohl(ifa->inmask.s_addr) >> 0) & 0xff; 329258331Smarkj break; 330258331Smarkj 331258331Smarkj case LEAF_ipAdEntBcastAddr: 332258331Smarkj value->v.integer = ntohl(ifa->inbcast.s_addr) & 1; 333258331Smarkj break; 334258331Smarkj 335258331Smarkj 336258331Smarkj case LEAF_ipAdEntReasmMaxSize: 337258331Smarkj value->v.integer = 65535; 338258331Smarkj break; 339258331Smarkj } 340258331Smarkj return (SNMP_ERR_NOERROR); 341258331Smarkj} 342258331Smarkj