mibII_ipaddr.c revision 133211
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> 7133211Sharti * 8133211Sharti * Redistribution and use in source and binary forms, with or without 9133211Sharti * modification, are permitted provided that the following conditions 10133211Sharti * are met: 11133211Sharti * 1. Redistributions of source code must retain the above copyright 12133211Sharti * notice, this list of conditions and the following disclaimer. 13122394Sharti * 2. Redistributions in binary form must reproduce the above copyright 14122394Sharti * notice, this list of conditions and the following disclaimer in the 15122394Sharti * documentation and/or other materials provided with the distribution. 16133211Sharti * 17133211Sharti * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18133211Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19133211Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20133211Sharti * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 21133211Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22133211Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23133211Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24133211Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25133211Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26133211Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27133211Sharti * SUCH DAMAGE. 28122394Sharti * 29133211Sharti * $Begemot: bsnmp/snmp_mibII/mibII_ipaddr.c,v 1.9 2004/08/06 08:47:02 brandt Exp $ 30122394Sharti * 31122394Sharti * IP address table. This table is writeable! 32122394Sharti * 33122394Sharti * Writing to this table will add a new IP address to the interface. 34122394Sharti * An address can be deleted with writing the interface index 0. 35122394Sharti */ 36122394Sharti#include "mibII.h" 37122394Sharti#include "mibII_oid.h" 38122394Sharti 39122394Shartistatic const struct asn_oid 40122394Sharti oid_ipAddrTable = OIDX_ipAddrTable; 41122394Sharti 42122394Sharti/* 43122394Sharti * Be careful not to hold any pointers during the SET processing - the 44122394Sharti * interface and address lists can be relocated at any time. 45122394Sharti */ 46122394Shartistruct update { 47122394Sharti struct snmp_dependency dep; 48122394Sharti 49133211Sharti uint32_t set; 50122394Sharti struct in_addr addr; 51122394Sharti struct in_addr mask; 52122394Sharti int bcast; 53122394Sharti u_int ifindex; 54122394Sharti 55133211Sharti uint32_t rb; 56122394Sharti struct in_addr rb_mask; 57122394Sharti struct in_addr rb_bcast; 58122394Sharti}; 59122394Sharti#define UPD_IFINDEX 0x0001 60122394Sharti#define UPD_MASK 0x0002 61122394Sharti#define UPD_BCAST 0x0004 62122394Sharti#define RB_CREATE 0x0001 63122394Sharti#define RB_DESTROY 0x0002 64122394Sharti#define RB_MODIFY 0x0004 65122394Sharti 66122394Sharti/* 67122394Sharti * Create a new interface address 68122394Sharti */ 69122394Shartistatic int 70122394Sharticreate(struct update *upd) 71122394Sharti{ 72122394Sharti struct in_addr bcast; 73122394Sharti struct mibifa *ifa; 74122394Sharti 75122394Sharti if (!(upd->set & UPD_MASK)) { 76122394Sharti if (IN_CLASSA(ntohl(upd->addr.s_addr))) 77122394Sharti upd->mask.s_addr = htonl(IN_CLASSA_NET); 78122394Sharti else if (IN_CLASSB(ntohl(upd->addr.s_addr))) 79122394Sharti upd->mask.s_addr = htonl(IN_CLASSB_NET); 80122394Sharti else if (IN_CLASSC(ntohl(upd->addr.s_addr))) 81122394Sharti upd->mask.s_addr = htonl(IN_CLASSC_NET); 82122394Sharti else 83122394Sharti upd->mask.s_addr = 0xffffffff; 84122394Sharti } 85122394Sharti 86122394Sharti bcast.s_addr = upd->addr.s_addr & upd->mask.s_addr; 87122394Sharti if (!(upd->set & UPD_BCAST) || upd->bcast) 88122394Sharti bcast.s_addr |= htonl(0xffffffff & ~ntohl(upd->mask.s_addr)); 89122394Sharti 90122394Sharti if ((ifa = mib_create_ifa(upd->ifindex, upd->addr, upd->mask, bcast)) == NULL) 91122394Sharti return (SNMP_ERR_GENERR); 92122394Sharti 93122394Sharti upd->rb |= RB_CREATE; 94122394Sharti return (SNMP_ERR_NOERROR); 95122394Sharti} 96122394Sharti 97122394Sharti/* 98122394Sharti * Modify the netmask or broadcast address. The ifindex cannot be 99122394Sharti * changed (obviously). 100122394Sharti */ 101122394Shartistatic int 102122394Shartimodify(struct update *upd, struct mibifa *ifa) 103122394Sharti{ 104122394Sharti struct mibif *ifp; 105122394Sharti 106122394Sharti if ((ifp = mib_find_if(ifa->ifindex)) == NULL) 107122394Sharti return (SNMP_ERR_WRONG_VALUE); 108122394Sharti if ((upd->set & UPD_IFINDEX) && upd->ifindex != ifa->ifindex) 109122394Sharti return (SNMP_ERR_INCONS_VALUE); 110122394Sharti 111122394Sharti upd->rb_mask = ifa->inmask; 112122394Sharti upd->rb_bcast = ifa->inbcast; 113122394Sharti if (((upd->set & UPD_MASK) && upd->mask.s_addr != ifa->inmask.s_addr) || 114122394Sharti (upd->set & UPD_BCAST)) { 115122394Sharti if (upd->set & UPD_MASK) 116122394Sharti ifa->inmask = upd->mask; 117122394Sharti if (upd->set & UPD_BCAST) { 118122394Sharti ifa->inbcast.s_addr = ifa->inaddr.s_addr 119122394Sharti & ifa->inmask.s_addr; 120122394Sharti if (upd->bcast) 121122394Sharti ifa->inbcast.s_addr |= 0xffffffff 122122394Sharti & ~ifa->inmask.s_addr; 123122394Sharti } 124122394Sharti if (mib_modify_ifa(ifa)) { 125122394Sharti syslog(LOG_ERR, "set netmask/bcast: %m"); 126122394Sharti ifa->inmask = upd->rb_mask; 127122394Sharti ifa->inbcast = upd->rb_bcast; 128122394Sharti mib_unmodify_ifa(ifa); 129122394Sharti return (SNMP_ERR_GENERR); 130122394Sharti } 131122394Sharti upd->rb |= RB_MODIFY; 132122394Sharti } 133122394Sharti return (SNMP_ERR_NOERROR); 134122394Sharti} 135122394Sharti 136122394Sharti/* 137122394Sharti * Destroy the given row in the table. We remove the address from the 138122394Sharti * system, but keep the structure around for the COMMIT. It's deleted 139128237Sharti * only in the FINISH operation. 140122394Sharti */ 141122394Shartistatic int 142128237Shartidestroy(struct snmp_context *ctx __unused, struct update *upd, 143128237Sharti struct mibifa *ifa) 144122394Sharti{ 145122394Sharti if (mib_destroy_ifa(ifa)) 146122394Sharti return (SNMP_ERR_GENERR); 147122394Sharti upd->rb |= RB_DESTROY; 148122394Sharti return (SNMP_ERR_NOERROR); 149122394Sharti} 150122394Sharti 151122394Sharti/* 152122394Sharti * This function is called to commit/rollback a SET on an IpAddrEntry 153122394Sharti */ 154122394Shartistatic int 155122394Shartiupdate_func(struct snmp_context *ctx, struct snmp_dependency *dep, 156122394Sharti enum snmp_depop op) 157122394Sharti{ 158122394Sharti struct update *upd = (struct update *)dep; 159122394Sharti struct mibifa *ifa; 160122394Sharti 161122394Sharti switch (op) { 162122394Sharti 163122394Sharti case SNMP_DEPOP_COMMIT: 164122394Sharti if ((ifa = mib_find_ifa(upd->addr)) == NULL) { 165122394Sharti /* non existing entry - must have ifindex */ 166122394Sharti if (!(upd->set & UPD_IFINDEX)) 167122394Sharti return (SNMP_ERR_INCONS_NAME); 168122394Sharti return (create(upd)); 169122394Sharti } 170122394Sharti /* existing entry */ 171122394Sharti if ((upd->set & UPD_IFINDEX) && upd->ifindex == 0) { 172122394Sharti /* delete */ 173122394Sharti return (destroy(ctx, upd, ifa)); 174122394Sharti } 175122394Sharti /* modify entry */ 176122394Sharti return (modify(upd, ifa)); 177122394Sharti 178122394Sharti case SNMP_DEPOP_ROLLBACK: 179122394Sharti if ((ifa = mib_find_ifa(upd->addr)) == NULL) { 180122394Sharti /* ups */ 181122394Sharti mib_iflist_bad = 1; 182122394Sharti return (SNMP_ERR_NOERROR); 183122394Sharti } 184122394Sharti if (upd->rb & RB_CREATE) { 185122394Sharti mib_uncreate_ifa(ifa); 186122394Sharti return (SNMP_ERR_NOERROR); 187122394Sharti } 188122394Sharti if (upd->rb & RB_DESTROY) { 189122394Sharti mib_undestroy_ifa(ifa); 190122394Sharti return (SNMP_ERR_NOERROR); 191122394Sharti } 192122394Sharti if (upd->rb & RB_MODIFY) { 193122394Sharti ifa->inmask = upd->rb_mask; 194122394Sharti ifa->inbcast = upd->rb_bcast; 195122394Sharti mib_unmodify_ifa(ifa); 196122394Sharti return (SNMP_ERR_NOERROR); 197122394Sharti } 198122394Sharti return (SNMP_ERR_NOERROR); 199128237Sharti 200128237Sharti case SNMP_DEPOP_FINISH: 201128237Sharti if ((upd->rb & RB_DESTROY) && 202128237Sharti (ifa = mib_find_ifa(upd->addr)) != NULL && 203128237Sharti (ifa->flags & MIBIFA_DESTROYED)) { 204128237Sharti TAILQ_REMOVE(&mibifa_list, ifa, link); 205128237Sharti free(ifa); 206128237Sharti } 207128237Sharti return (SNMP_ERR_NOERROR); 208122394Sharti } 209122394Sharti abort(); 210122394Sharti} 211122394Sharti 212122394Sharti/**********************************************************************/ 213122394Sharti/* 214122394Sharti * ACTION 215122394Sharti */ 216122394Shartiint 217122394Shartiop_ipaddr(struct snmp_context *ctx, struct snmp_value *value, 218122394Sharti u_int sub, u_int iidx, enum snmp_op op) 219122394Sharti{ 220122394Sharti asn_subid_t which; 221122394Sharti struct mibifa *ifa; 222122394Sharti struct update *upd; 223122394Sharti struct asn_oid idx; 224122394Sharti u_char ipaddr[4]; 225122394Sharti 226122394Sharti which = value->var.subs[sub - 1]; 227122394Sharti 228122394Sharti ifa = NULL; 229122394Sharti 230122394Sharti switch (op) { 231122394Sharti 232122394Sharti case SNMP_OP_GETNEXT: 233122394Sharti if ((ifa = NEXT_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL) 234122394Sharti return (SNMP_ERR_NOSUCHNAME); 235122394Sharti index_append(&value->var, sub, &ifa->index); 236122394Sharti break; 237122394Sharti 238122394Sharti case SNMP_OP_GET: 239122394Sharti if ((ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL) 240122394Sharti return (SNMP_ERR_NOSUCHNAME); 241122394Sharti break; 242122394Sharti 243122394Sharti case SNMP_OP_SET: 244122394Sharti if (index_decode(&value->var, sub, iidx, ipaddr)) 245122394Sharti return (SNMP_ERR_NO_CREATION); 246122394Sharti ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub); 247122394Sharti idx.len = 4; 248122394Sharti idx.subs[0] = ipaddr[0]; 249122394Sharti idx.subs[1] = ipaddr[1]; 250122394Sharti idx.subs[2] = ipaddr[2]; 251122394Sharti idx.subs[3] = ipaddr[3]; 252122394Sharti 253122394Sharti if ((upd = (struct update *)snmp_dep_lookup(ctx, 254122394Sharti &oid_ipAddrTable, &idx, sizeof(*upd), update_func)) == NULL) 255122394Sharti return (SNMP_ERR_RES_UNAVAIL); 256122394Sharti 257122394Sharti upd->addr.s_addr = htonl((ipaddr[0] << 24) | (ipaddr[1] << 16) | 258122394Sharti (ipaddr[2] << 8) | (ipaddr[3] << 0)); 259122394Sharti 260122394Sharti switch (which) { 261122394Sharti 262122394Sharti case LEAF_ipAdEntIfIndex: 263122394Sharti if (upd->set & UPD_IFINDEX) 264122394Sharti return (SNMP_ERR_INCONS_VALUE); 265122394Sharti if (value->v.integer < 0 || 266122394Sharti value->v.integer > 0x07fffffff) 267122394Sharti return (SNMP_ERR_WRONG_VALUE); 268122394Sharti if (ifa != NULL) { 269122394Sharti if (ifa->ifindex != (u_int)value->v.integer && 270122394Sharti value->v.integer != 0) 271122394Sharti return (SNMP_ERR_INCONS_VALUE); 272122394Sharti } 273122394Sharti upd->set |= UPD_IFINDEX; 274122394Sharti upd->ifindex = (u_int)value->v.integer; 275122394Sharti break; 276122394Sharti 277122394Sharti case LEAF_ipAdEntNetMask: 278122394Sharti if (upd->set & UPD_MASK) 279122394Sharti return (SNMP_ERR_INCONS_VALUE); 280122394Sharti upd->mask.s_addr = htonl((value->v.ipaddress[0] << 24) 281122394Sharti | (value->v.ipaddress[1] << 16) 282122394Sharti | (value->v.ipaddress[2] << 8) 283122394Sharti | (value->v.ipaddress[3] << 0)); 284122394Sharti upd->set |= UPD_MASK; 285122394Sharti break; 286122394Sharti 287122394Sharti case LEAF_ipAdEntBcastAddr: 288122394Sharti if (upd->set & UPD_BCAST) 289122394Sharti return (SNMP_ERR_INCONS_VALUE); 290122394Sharti if (value->v.integer != 0 && value->v.integer != 1) 291122394Sharti return (SNMP_ERR_WRONG_VALUE); 292122394Sharti upd->bcast = value->v.integer; 293122394Sharti upd->set |= UPD_BCAST; 294122394Sharti break; 295122394Sharti 296122394Sharti } 297122394Sharti return (SNMP_ERR_NOERROR); 298122394Sharti 299122394Sharti case SNMP_OP_ROLLBACK: 300122394Sharti case SNMP_OP_COMMIT: 301122394Sharti return (SNMP_ERR_NOERROR); 302122394Sharti } 303122394Sharti 304122394Sharti switch (which) { 305122394Sharti 306122394Sharti case LEAF_ipAdEntAddr: 307122394Sharti value->v.ipaddress[0] = ifa->index.subs[0]; 308122394Sharti value->v.ipaddress[1] = ifa->index.subs[1]; 309122394Sharti value->v.ipaddress[2] = ifa->index.subs[2]; 310122394Sharti value->v.ipaddress[3] = ifa->index.subs[3]; 311122394Sharti break; 312122394Sharti 313122394Sharti case LEAF_ipAdEntIfIndex: 314122394Sharti if (ifa->flags & MIBIFA_DESTROYED) 315122394Sharti value->v.integer = 0; 316122394Sharti else 317122394Sharti value->v.integer = ifa->ifindex; 318122394Sharti break; 319122394Sharti 320122394Sharti case LEAF_ipAdEntNetMask: 321122394Sharti value->v.ipaddress[0] = (ntohl(ifa->inmask.s_addr) >> 24) & 0xff; 322122394Sharti value->v.ipaddress[1] = (ntohl(ifa->inmask.s_addr) >> 16) & 0xff; 323122394Sharti value->v.ipaddress[2] = (ntohl(ifa->inmask.s_addr) >> 8) & 0xff; 324122394Sharti value->v.ipaddress[3] = (ntohl(ifa->inmask.s_addr) >> 0) & 0xff; 325122394Sharti break; 326122394Sharti 327122394Sharti case LEAF_ipAdEntBcastAddr: 328122394Sharti value->v.integer = ntohl(ifa->inbcast.s_addr) & 1; 329122394Sharti break; 330122394Sharti 331122394Sharti 332122394Sharti case LEAF_ipAdEntReasmMaxSize: 333122394Sharti value->v.integer = 65535; 334122394Sharti break; 335122394Sharti } 336122394Sharti return (SNMP_ERR_NOERROR); 337122394Sharti} 338