mibII_ipaddr.c revision 122394
1122394Sharti/* 2122394Sharti * Copyright (c) 2001-2002 3122394Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4122394Sharti * All rights reserved. 5122394Sharti * 6122394Sharti * Author: Harti Brandt <harti@freebsd.org> 7122394Sharti * 8122394Sharti * Redistribution of this software and documentation and use in source and 9122394Sharti * binary forms, with or without modification, are permitted provided that 10122394Sharti * the following conditions are met: 11122394Sharti * 12122394Sharti * 1. Redistributions of source code or documentation must retain the above 13122394Sharti * copyright notice, this list of conditions and the following disclaimer. 14122394Sharti * 2. Redistributions in binary form must reproduce the above copyright 15122394Sharti * notice, this list of conditions and the following disclaimer in the 16122394Sharti * documentation and/or other materials provided with the distribution. 17122394Sharti * 3. Neither the name of the Institute nor the names of its contributors 18122394Sharti * may be used to endorse or promote products derived from this software 19122394Sharti * without specific prior written permission. 20122394Sharti * 21122394Sharti * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS 22122394Sharti * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23122394Sharti * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24122394Sharti * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25122394Sharti * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26122394Sharti * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27122394Sharti * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28122394Sharti * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29122394Sharti * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30122394Sharti * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31122394Sharti * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32122394Sharti * 33122394Sharti * $Begemot: bsnmp/snmp_mibII/mibII_ipaddr.c,v 1.6 2003/01/28 13:44:35 hbb Exp $ 34122394Sharti * 35122394Sharti * IP address table. This table is writeable! 36122394Sharti * 37122394Sharti * Writing to this table will add a new IP address to the interface. 38122394Sharti * An address can be deleted with writing the interface index 0. 39122394Sharti */ 40122394Sharti#include "mibII.h" 41122394Sharti#include "mibII_oid.h" 42122394Sharti 43122394Shartistatic const struct asn_oid 44122394Sharti oid_ipAddrTable = OIDX_ipAddrTable; 45122394Sharti 46122394Sharti/* 47122394Sharti * Be careful not to hold any pointers during the SET processing - the 48122394Sharti * interface and address lists can be relocated at any time. 49122394Sharti */ 50122394Shartistruct update { 51122394Sharti struct snmp_dependency dep; 52122394Sharti 53122394Sharti u_int32_t set; 54122394Sharti struct in_addr addr; 55122394Sharti struct in_addr mask; 56122394Sharti int bcast; 57122394Sharti u_int ifindex; 58122394Sharti 59122394Sharti u_int32_t rb; 60122394Sharti struct in_addr rb_mask; 61122394Sharti struct in_addr rb_bcast; 62122394Sharti}; 63122394Sharti#define UPD_IFINDEX 0x0001 64122394Sharti#define UPD_MASK 0x0002 65122394Sharti#define UPD_BCAST 0x0004 66122394Sharti#define RB_CREATE 0x0001 67122394Sharti#define RB_DESTROY 0x0002 68122394Sharti#define RB_MODIFY 0x0004 69122394Sharti 70122394Sharti/* 71122394Sharti * Create a new interface address 72122394Sharti */ 73122394Shartistatic int 74122394Sharticreate(struct update *upd) 75122394Sharti{ 76122394Sharti struct in_addr bcast; 77122394Sharti struct mibifa *ifa; 78122394Sharti 79122394Sharti if (!(upd->set & UPD_MASK)) { 80122394Sharti if (IN_CLASSA(ntohl(upd->addr.s_addr))) 81122394Sharti upd->mask.s_addr = htonl(IN_CLASSA_NET); 82122394Sharti else if (IN_CLASSB(ntohl(upd->addr.s_addr))) 83122394Sharti upd->mask.s_addr = htonl(IN_CLASSB_NET); 84122394Sharti else if (IN_CLASSC(ntohl(upd->addr.s_addr))) 85122394Sharti upd->mask.s_addr = htonl(IN_CLASSC_NET); 86122394Sharti else 87122394Sharti upd->mask.s_addr = 0xffffffff; 88122394Sharti } 89122394Sharti 90122394Sharti bcast.s_addr = upd->addr.s_addr & upd->mask.s_addr; 91122394Sharti if (!(upd->set & UPD_BCAST) || upd->bcast) 92122394Sharti bcast.s_addr |= htonl(0xffffffff & ~ntohl(upd->mask.s_addr)); 93122394Sharti 94122394Sharti if ((ifa = mib_create_ifa(upd->ifindex, upd->addr, upd->mask, bcast)) == NULL) 95122394Sharti return (SNMP_ERR_GENERR); 96122394Sharti 97122394Sharti upd->rb |= RB_CREATE; 98122394Sharti return (SNMP_ERR_NOERROR); 99122394Sharti} 100122394Sharti 101122394Sharti/* 102122394Sharti * Modify the netmask or broadcast address. The ifindex cannot be 103122394Sharti * changed (obviously). 104122394Sharti */ 105122394Shartistatic int 106122394Shartimodify(struct update *upd, struct mibifa *ifa) 107122394Sharti{ 108122394Sharti struct mibif *ifp; 109122394Sharti 110122394Sharti if ((ifp = mib_find_if(ifa->ifindex)) == NULL) 111122394Sharti return (SNMP_ERR_WRONG_VALUE); 112122394Sharti if ((upd->set & UPD_IFINDEX) && upd->ifindex != ifa->ifindex) 113122394Sharti return (SNMP_ERR_INCONS_VALUE); 114122394Sharti 115122394Sharti upd->rb_mask = ifa->inmask; 116122394Sharti upd->rb_bcast = ifa->inbcast; 117122394Sharti if (((upd->set & UPD_MASK) && upd->mask.s_addr != ifa->inmask.s_addr) || 118122394Sharti (upd->set & UPD_BCAST)) { 119122394Sharti if (upd->set & UPD_MASK) 120122394Sharti ifa->inmask = upd->mask; 121122394Sharti if (upd->set & UPD_BCAST) { 122122394Sharti ifa->inbcast.s_addr = ifa->inaddr.s_addr 123122394Sharti & ifa->inmask.s_addr; 124122394Sharti if (upd->bcast) 125122394Sharti ifa->inbcast.s_addr |= 0xffffffff 126122394Sharti & ~ifa->inmask.s_addr; 127122394Sharti } 128122394Sharti if (mib_modify_ifa(ifa)) { 129122394Sharti syslog(LOG_ERR, "set netmask/bcast: %m"); 130122394Sharti ifa->inmask = upd->rb_mask; 131122394Sharti ifa->inbcast = upd->rb_bcast; 132122394Sharti mib_unmodify_ifa(ifa); 133122394Sharti return (SNMP_ERR_GENERR); 134122394Sharti } 135122394Sharti upd->rb |= RB_MODIFY; 136122394Sharti } 137122394Sharti return (SNMP_ERR_NOERROR); 138122394Sharti} 139122394Sharti 140122394Sharti/* 141122394Sharti * Remove an IP address from an interface. This is called when 142122394Sharti * the SET finishes. 143122394Sharti */ 144122394Shartistatic void 145122394Shartidestroy_func(struct snmp_context *ctx __unused, int fail __unused, void *arg) 146122394Sharti{ 147122394Sharti struct mibifa *ifa = arg; 148122394Sharti 149122394Sharti if (ifa->flags & MIBIFA_DESTROYED) { 150122394Sharti TAILQ_REMOVE(&mibifa_list, ifa, link); 151122394Sharti free(ifa); 152122394Sharti } 153122394Sharti} 154122394Sharti 155122394Sharti/* 156122394Sharti * Destroy the given row in the table. We remove the address from the 157122394Sharti * system, but keep the structure around for the COMMIT. It's deleted 158122394Sharti * only in the finish function. 159122394Sharti */ 160122394Shartistatic int 161122394Shartidestroy(struct snmp_context *ctx, struct update *upd, struct mibifa *ifa) 162122394Sharti{ 163122394Sharti if (mib_destroy_ifa(ifa)) 164122394Sharti return (SNMP_ERR_GENERR); 165122394Sharti if (snmp_set_atfinish(ctx, destroy_func, ifa)) { 166122394Sharti syslog(LOG_ERR, "atfinish: %m"); 167122394Sharti mib_undestroy_ifa(ifa); 168122394Sharti return (SNMP_ERR_GENERR); 169122394Sharti } 170122394Sharti upd->rb |= RB_DESTROY; 171122394Sharti return (SNMP_ERR_NOERROR); 172122394Sharti} 173122394Sharti 174122394Sharti/* 175122394Sharti * This function is called to commit/rollback a SET on an IpAddrEntry 176122394Sharti */ 177122394Shartistatic int 178122394Shartiupdate_func(struct snmp_context *ctx, struct snmp_dependency *dep, 179122394Sharti enum snmp_depop op) 180122394Sharti{ 181122394Sharti struct update *upd = (struct update *)dep; 182122394Sharti struct mibifa *ifa; 183122394Sharti 184122394Sharti switch (op) { 185122394Sharti 186122394Sharti case SNMP_DEPOP_COMMIT: 187122394Sharti if ((ifa = mib_find_ifa(upd->addr)) == NULL) { 188122394Sharti /* non existing entry - must have ifindex */ 189122394Sharti if (!(upd->set & UPD_IFINDEX)) 190122394Sharti return (SNMP_ERR_INCONS_NAME); 191122394Sharti return (create(upd)); 192122394Sharti } 193122394Sharti /* existing entry */ 194122394Sharti if ((upd->set & UPD_IFINDEX) && upd->ifindex == 0) { 195122394Sharti /* delete */ 196122394Sharti return (destroy(ctx, upd, ifa)); 197122394Sharti } 198122394Sharti /* modify entry */ 199122394Sharti return (modify(upd, ifa)); 200122394Sharti 201122394Sharti case SNMP_DEPOP_ROLLBACK: 202122394Sharti if ((ifa = mib_find_ifa(upd->addr)) == NULL) { 203122394Sharti /* ups */ 204122394Sharti mib_iflist_bad = 1; 205122394Sharti return (SNMP_ERR_NOERROR); 206122394Sharti } 207122394Sharti if (upd->rb & RB_CREATE) { 208122394Sharti mib_uncreate_ifa(ifa); 209122394Sharti return (SNMP_ERR_NOERROR); 210122394Sharti } 211122394Sharti if (upd->rb & RB_DESTROY) { 212122394Sharti mib_undestroy_ifa(ifa); 213122394Sharti return (SNMP_ERR_NOERROR); 214122394Sharti } 215122394Sharti if (upd->rb & RB_MODIFY) { 216122394Sharti ifa->inmask = upd->rb_mask; 217122394Sharti ifa->inbcast = upd->rb_bcast; 218122394Sharti mib_unmodify_ifa(ifa); 219122394Sharti return (SNMP_ERR_NOERROR); 220122394Sharti } 221122394Sharti return (SNMP_ERR_NOERROR); 222122394Sharti } 223122394Sharti abort(); 224122394Sharti} 225122394Sharti 226122394Sharti/**********************************************************************/ 227122394Sharti/* 228122394Sharti * ACTION 229122394Sharti */ 230122394Shartiint 231122394Shartiop_ipaddr(struct snmp_context *ctx, struct snmp_value *value, 232122394Sharti u_int sub, u_int iidx, enum snmp_op op) 233122394Sharti{ 234122394Sharti asn_subid_t which; 235122394Sharti struct mibifa *ifa; 236122394Sharti struct update *upd; 237122394Sharti struct asn_oid idx; 238122394Sharti u_char ipaddr[4]; 239122394Sharti 240122394Sharti which = value->var.subs[sub - 1]; 241122394Sharti 242122394Sharti ifa = NULL; 243122394Sharti 244122394Sharti switch (op) { 245122394Sharti 246122394Sharti case SNMP_OP_GETNEXT: 247122394Sharti if ((ifa = NEXT_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL) 248122394Sharti return (SNMP_ERR_NOSUCHNAME); 249122394Sharti index_append(&value->var, sub, &ifa->index); 250122394Sharti break; 251122394Sharti 252122394Sharti case SNMP_OP_GET: 253122394Sharti if ((ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL) 254122394Sharti return (SNMP_ERR_NOSUCHNAME); 255122394Sharti break; 256122394Sharti 257122394Sharti case SNMP_OP_SET: 258122394Sharti if (index_decode(&value->var, sub, iidx, ipaddr)) 259122394Sharti return (SNMP_ERR_NO_CREATION); 260122394Sharti ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub); 261122394Sharti idx.len = 4; 262122394Sharti idx.subs[0] = ipaddr[0]; 263122394Sharti idx.subs[1] = ipaddr[1]; 264122394Sharti idx.subs[2] = ipaddr[2]; 265122394Sharti idx.subs[3] = ipaddr[3]; 266122394Sharti 267122394Sharti if ((upd = (struct update *)snmp_dep_lookup(ctx, 268122394Sharti &oid_ipAddrTable, &idx, sizeof(*upd), update_func)) == NULL) 269122394Sharti return (SNMP_ERR_RES_UNAVAIL); 270122394Sharti 271122394Sharti upd->addr.s_addr = htonl((ipaddr[0] << 24) | (ipaddr[1] << 16) | 272122394Sharti (ipaddr[2] << 8) | (ipaddr[3] << 0)); 273122394Sharti 274122394Sharti switch (which) { 275122394Sharti 276122394Sharti case LEAF_ipAdEntIfIndex: 277122394Sharti if (upd->set & UPD_IFINDEX) 278122394Sharti return (SNMP_ERR_INCONS_VALUE); 279122394Sharti if (value->v.integer < 0 || 280122394Sharti value->v.integer > 0x07fffffff) 281122394Sharti return (SNMP_ERR_WRONG_VALUE); 282122394Sharti if (ifa != NULL) { 283122394Sharti if (ifa->ifindex != (u_int)value->v.integer && 284122394Sharti value->v.integer != 0) 285122394Sharti return (SNMP_ERR_INCONS_VALUE); 286122394Sharti } 287122394Sharti upd->set |= UPD_IFINDEX; 288122394Sharti upd->ifindex = (u_int)value->v.integer; 289122394Sharti break; 290122394Sharti 291122394Sharti case LEAF_ipAdEntNetMask: 292122394Sharti if (upd->set & UPD_MASK) 293122394Sharti return (SNMP_ERR_INCONS_VALUE); 294122394Sharti upd->mask.s_addr = htonl((value->v.ipaddress[0] << 24) 295122394Sharti | (value->v.ipaddress[1] << 16) 296122394Sharti | (value->v.ipaddress[2] << 8) 297122394Sharti | (value->v.ipaddress[3] << 0)); 298122394Sharti upd->set |= UPD_MASK; 299122394Sharti break; 300122394Sharti 301122394Sharti case LEAF_ipAdEntBcastAddr: 302122394Sharti if (upd->set & UPD_BCAST) 303122394Sharti return (SNMP_ERR_INCONS_VALUE); 304122394Sharti if (value->v.integer != 0 && value->v.integer != 1) 305122394Sharti return (SNMP_ERR_WRONG_VALUE); 306122394Sharti upd->bcast = value->v.integer; 307122394Sharti upd->set |= UPD_BCAST; 308122394Sharti break; 309122394Sharti 310122394Sharti } 311122394Sharti return (SNMP_ERR_NOERROR); 312122394Sharti 313122394Sharti case SNMP_OP_ROLLBACK: 314122394Sharti case SNMP_OP_COMMIT: 315122394Sharti return (SNMP_ERR_NOERROR); 316122394Sharti } 317122394Sharti 318122394Sharti switch (which) { 319122394Sharti 320122394Sharti case LEAF_ipAdEntAddr: 321122394Sharti value->v.ipaddress[0] = ifa->index.subs[0]; 322122394Sharti value->v.ipaddress[1] = ifa->index.subs[1]; 323122394Sharti value->v.ipaddress[2] = ifa->index.subs[2]; 324122394Sharti value->v.ipaddress[3] = ifa->index.subs[3]; 325122394Sharti break; 326122394Sharti 327122394Sharti case LEAF_ipAdEntIfIndex: 328122394Sharti if (ifa->flags & MIBIFA_DESTROYED) 329122394Sharti value->v.integer = 0; 330122394Sharti else 331122394Sharti value->v.integer = ifa->ifindex; 332122394Sharti break; 333122394Sharti 334122394Sharti case LEAF_ipAdEntNetMask: 335122394Sharti value->v.ipaddress[0] = (ntohl(ifa->inmask.s_addr) >> 24) & 0xff; 336122394Sharti value->v.ipaddress[1] = (ntohl(ifa->inmask.s_addr) >> 16) & 0xff; 337122394Sharti value->v.ipaddress[2] = (ntohl(ifa->inmask.s_addr) >> 8) & 0xff; 338122394Sharti value->v.ipaddress[3] = (ntohl(ifa->inmask.s_addr) >> 0) & 0xff; 339122394Sharti break; 340122394Sharti 341122394Sharti case LEAF_ipAdEntBcastAddr: 342122394Sharti value->v.integer = ntohl(ifa->inbcast.s_addr) & 1; 343122394Sharti break; 344122394Sharti 345122394Sharti 346122394Sharti case LEAF_ipAdEntReasmMaxSize: 347122394Sharti value->v.integer = 65535; 348122394Sharti break; 349122394Sharti } 350122394Sharti return (SNMP_ERR_NOERROR); 351122394Sharti} 352