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> 7310903Sngie * 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. 16310903Sngie * 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 * 29150920Sharti * $Begemot: bsnmp/snmp_mibII/mibII_ipaddr.c,v 1.10 2005/10/04 11:21:35 brandt_h 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; 87150920Sharti if (!(upd->set & UPD_BCAST) || upd->bcast) { 88150920Sharti uint32_t tmp = ~ntohl(upd->mask.s_addr); 89150920Sharti bcast.s_addr |= htonl(0xffffffff & ~tmp); 90150920Sharti } 91122394Sharti 92150920Sharti if ((ifa = mib_create_ifa(upd->ifindex, upd->addr, upd->mask, bcast)) 93150920Sharti == NULL) 94122394Sharti return (SNMP_ERR_GENERR); 95122394Sharti 96122394Sharti upd->rb |= RB_CREATE; 97122394Sharti return (SNMP_ERR_NOERROR); 98122394Sharti} 99122394Sharti 100122394Sharti/* 101122394Sharti * Modify the netmask or broadcast address. The ifindex cannot be 102122394Sharti * changed (obviously). 103122394Sharti */ 104122394Shartistatic int 105122394Shartimodify(struct update *upd, struct mibifa *ifa) 106122394Sharti{ 107122394Sharti struct mibif *ifp; 108122394Sharti 109122394Sharti if ((ifp = mib_find_if(ifa->ifindex)) == NULL) 110122394Sharti return (SNMP_ERR_WRONG_VALUE); 111122394Sharti if ((upd->set & UPD_IFINDEX) && upd->ifindex != ifa->ifindex) 112122394Sharti return (SNMP_ERR_INCONS_VALUE); 113122394Sharti 114122394Sharti upd->rb_mask = ifa->inmask; 115122394Sharti upd->rb_bcast = ifa->inbcast; 116122394Sharti if (((upd->set & UPD_MASK) && upd->mask.s_addr != ifa->inmask.s_addr) || 117122394Sharti (upd->set & UPD_BCAST)) { 118122394Sharti if (upd->set & UPD_MASK) 119122394Sharti ifa->inmask = upd->mask; 120122394Sharti if (upd->set & UPD_BCAST) { 121122394Sharti ifa->inbcast.s_addr = ifa->inaddr.s_addr 122122394Sharti & ifa->inmask.s_addr; 123122394Sharti if (upd->bcast) 124122394Sharti ifa->inbcast.s_addr |= 0xffffffff 125122394Sharti & ~ifa->inmask.s_addr; 126122394Sharti } 127122394Sharti if (mib_modify_ifa(ifa)) { 128122394Sharti syslog(LOG_ERR, "set netmask/bcast: %m"); 129122394Sharti ifa->inmask = upd->rb_mask; 130122394Sharti ifa->inbcast = upd->rb_bcast; 131122394Sharti mib_unmodify_ifa(ifa); 132122394Sharti return (SNMP_ERR_GENERR); 133122394Sharti } 134122394Sharti upd->rb |= RB_MODIFY; 135122394Sharti } 136122394Sharti return (SNMP_ERR_NOERROR); 137122394Sharti} 138122394Sharti 139122394Sharti/* 140122394Sharti * Destroy the given row in the table. We remove the address from the 141122394Sharti * system, but keep the structure around for the COMMIT. It's deleted 142128237Sharti * only in the FINISH operation. 143122394Sharti */ 144122394Shartistatic int 145128237Shartidestroy(struct snmp_context *ctx __unused, struct update *upd, 146128237Sharti struct mibifa *ifa) 147122394Sharti{ 148122394Sharti if (mib_destroy_ifa(ifa)) 149122394Sharti return (SNMP_ERR_GENERR); 150122394Sharti upd->rb |= RB_DESTROY; 151122394Sharti return (SNMP_ERR_NOERROR); 152122394Sharti} 153122394Sharti 154122394Sharti/* 155122394Sharti * This function is called to commit/rollback a SET on an IpAddrEntry 156122394Sharti */ 157122394Shartistatic int 158122394Shartiupdate_func(struct snmp_context *ctx, struct snmp_dependency *dep, 159122394Sharti enum snmp_depop op) 160122394Sharti{ 161122394Sharti struct update *upd = (struct update *)dep; 162122394Sharti struct mibifa *ifa; 163122394Sharti 164122394Sharti switch (op) { 165122394Sharti 166122394Sharti case SNMP_DEPOP_COMMIT: 167122394Sharti if ((ifa = mib_find_ifa(upd->addr)) == NULL) { 168122394Sharti /* non existing entry - must have ifindex */ 169122394Sharti if (!(upd->set & UPD_IFINDEX)) 170122394Sharti return (SNMP_ERR_INCONS_NAME); 171122394Sharti return (create(upd)); 172122394Sharti } 173122394Sharti /* existing entry */ 174122394Sharti if ((upd->set & UPD_IFINDEX) && upd->ifindex == 0) { 175122394Sharti /* delete */ 176122394Sharti return (destroy(ctx, upd, ifa)); 177122394Sharti } 178122394Sharti /* modify entry */ 179122394Sharti return (modify(upd, ifa)); 180122394Sharti 181122394Sharti case SNMP_DEPOP_ROLLBACK: 182122394Sharti if ((ifa = mib_find_ifa(upd->addr)) == NULL) { 183122394Sharti /* ups */ 184122394Sharti mib_iflist_bad = 1; 185122394Sharti return (SNMP_ERR_NOERROR); 186122394Sharti } 187122394Sharti if (upd->rb & RB_CREATE) { 188122394Sharti mib_uncreate_ifa(ifa); 189122394Sharti return (SNMP_ERR_NOERROR); 190122394Sharti } 191122394Sharti if (upd->rb & RB_DESTROY) { 192122394Sharti mib_undestroy_ifa(ifa); 193122394Sharti return (SNMP_ERR_NOERROR); 194122394Sharti } 195122394Sharti if (upd->rb & RB_MODIFY) { 196122394Sharti ifa->inmask = upd->rb_mask; 197122394Sharti ifa->inbcast = upd->rb_bcast; 198122394Sharti mib_unmodify_ifa(ifa); 199122394Sharti return (SNMP_ERR_NOERROR); 200122394Sharti } 201122394Sharti return (SNMP_ERR_NOERROR); 202128237Sharti 203128237Sharti case SNMP_DEPOP_FINISH: 204128237Sharti if ((upd->rb & RB_DESTROY) && 205128237Sharti (ifa = mib_find_ifa(upd->addr)) != NULL && 206128237Sharti (ifa->flags & MIBIFA_DESTROYED)) { 207128237Sharti TAILQ_REMOVE(&mibifa_list, ifa, link); 208128237Sharti free(ifa); 209128237Sharti } 210128237Sharti return (SNMP_ERR_NOERROR); 211122394Sharti } 212122394Sharti abort(); 213122394Sharti} 214122394Sharti 215122394Sharti/**********************************************************************/ 216122394Sharti/* 217122394Sharti * ACTION 218122394Sharti */ 219122394Shartiint 220122394Shartiop_ipaddr(struct snmp_context *ctx, struct snmp_value *value, 221122394Sharti u_int sub, u_int iidx, enum snmp_op op) 222122394Sharti{ 223122394Sharti asn_subid_t which; 224122394Sharti struct mibifa *ifa; 225122394Sharti struct update *upd; 226122394Sharti struct asn_oid idx; 227122394Sharti u_char ipaddr[4]; 228122394Sharti 229122394Sharti which = value->var.subs[sub - 1]; 230122394Sharti 231122394Sharti ifa = NULL; 232122394Sharti 233122394Sharti switch (op) { 234122394Sharti 235122394Sharti case SNMP_OP_GETNEXT: 236122394Sharti if ((ifa = NEXT_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL) 237122394Sharti return (SNMP_ERR_NOSUCHNAME); 238122394Sharti index_append(&value->var, sub, &ifa->index); 239122394Sharti break; 240122394Sharti 241122394Sharti case SNMP_OP_GET: 242122394Sharti if ((ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL) 243122394Sharti return (SNMP_ERR_NOSUCHNAME); 244122394Sharti break; 245122394Sharti 246122394Sharti case SNMP_OP_SET: 247122394Sharti if (index_decode(&value->var, sub, iidx, ipaddr)) 248122394Sharti return (SNMP_ERR_NO_CREATION); 249122394Sharti ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub); 250122394Sharti idx.len = 4; 251122394Sharti idx.subs[0] = ipaddr[0]; 252122394Sharti idx.subs[1] = ipaddr[1]; 253122394Sharti idx.subs[2] = ipaddr[2]; 254122394Sharti idx.subs[3] = ipaddr[3]; 255122394Sharti 256122394Sharti if ((upd = (struct update *)snmp_dep_lookup(ctx, 257122394Sharti &oid_ipAddrTable, &idx, sizeof(*upd), update_func)) == NULL) 258122394Sharti return (SNMP_ERR_RES_UNAVAIL); 259122394Sharti 260122394Sharti upd->addr.s_addr = htonl((ipaddr[0] << 24) | (ipaddr[1] << 16) | 261122394Sharti (ipaddr[2] << 8) | (ipaddr[3] << 0)); 262122394Sharti 263122394Sharti switch (which) { 264122394Sharti 265122394Sharti case LEAF_ipAdEntIfIndex: 266122394Sharti if (upd->set & UPD_IFINDEX) 267122394Sharti return (SNMP_ERR_INCONS_VALUE); 268122394Sharti if (value->v.integer < 0 || 269122394Sharti value->v.integer > 0x07fffffff) 270122394Sharti return (SNMP_ERR_WRONG_VALUE); 271122394Sharti if (ifa != NULL) { 272122394Sharti if (ifa->ifindex != (u_int)value->v.integer && 273122394Sharti value->v.integer != 0) 274122394Sharti return (SNMP_ERR_INCONS_VALUE); 275122394Sharti } 276122394Sharti upd->set |= UPD_IFINDEX; 277122394Sharti upd->ifindex = (u_int)value->v.integer; 278122394Sharti break; 279122394Sharti 280122394Sharti case LEAF_ipAdEntNetMask: 281122394Sharti if (upd->set & UPD_MASK) 282122394Sharti return (SNMP_ERR_INCONS_VALUE); 283122394Sharti upd->mask.s_addr = htonl((value->v.ipaddress[0] << 24) 284122394Sharti | (value->v.ipaddress[1] << 16) 285122394Sharti | (value->v.ipaddress[2] << 8) 286122394Sharti | (value->v.ipaddress[3] << 0)); 287122394Sharti upd->set |= UPD_MASK; 288122394Sharti break; 289122394Sharti 290122394Sharti case LEAF_ipAdEntBcastAddr: 291122394Sharti if (upd->set & UPD_BCAST) 292122394Sharti return (SNMP_ERR_INCONS_VALUE); 293122394Sharti if (value->v.integer != 0 && value->v.integer != 1) 294122394Sharti return (SNMP_ERR_WRONG_VALUE); 295122394Sharti upd->bcast = value->v.integer; 296122394Sharti upd->set |= UPD_BCAST; 297122394Sharti break; 298122394Sharti 299122394Sharti } 300122394Sharti return (SNMP_ERR_NOERROR); 301122394Sharti 302122394Sharti case SNMP_OP_ROLLBACK: 303122394Sharti case SNMP_OP_COMMIT: 304122394Sharti return (SNMP_ERR_NOERROR); 305122394Sharti } 306122394Sharti 307122394Sharti switch (which) { 308122394Sharti 309122394Sharti case LEAF_ipAdEntAddr: 310122394Sharti value->v.ipaddress[0] = ifa->index.subs[0]; 311122394Sharti value->v.ipaddress[1] = ifa->index.subs[1]; 312122394Sharti value->v.ipaddress[2] = ifa->index.subs[2]; 313122394Sharti value->v.ipaddress[3] = ifa->index.subs[3]; 314122394Sharti break; 315122394Sharti 316122394Sharti case LEAF_ipAdEntIfIndex: 317122394Sharti if (ifa->flags & MIBIFA_DESTROYED) 318122394Sharti value->v.integer = 0; 319122394Sharti else 320122394Sharti value->v.integer = ifa->ifindex; 321122394Sharti break; 322122394Sharti 323122394Sharti case LEAF_ipAdEntNetMask: 324122394Sharti value->v.ipaddress[0] = (ntohl(ifa->inmask.s_addr) >> 24) & 0xff; 325122394Sharti value->v.ipaddress[1] = (ntohl(ifa->inmask.s_addr) >> 16) & 0xff; 326122394Sharti value->v.ipaddress[2] = (ntohl(ifa->inmask.s_addr) >> 8) & 0xff; 327122394Sharti value->v.ipaddress[3] = (ntohl(ifa->inmask.s_addr) >> 0) & 0xff; 328122394Sharti break; 329122394Sharti 330122394Sharti case LEAF_ipAdEntBcastAddr: 331122394Sharti value->v.integer = ntohl(ifa->inbcast.s_addr) & 1; 332122394Sharti break; 333122394Sharti 334122394Sharti 335122394Sharti case LEAF_ipAdEntReasmMaxSize: 336122394Sharti value->v.integer = 65535; 337122394Sharti break; 338122394Sharti } 339122394Sharti return (SNMP_ERR_NOERROR); 340122394Sharti} 341