mibII_interfaces.c revision 122394
165185Sache/* 265185Sache * Copyright (c) 2001-2003 365185Sache * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 465185Sache * All rights reserved. 565185Sache * 665185Sache * Author: Harti Brandt <harti@freebsd.org> 765185Sache * 865185Sache * Redistribution of this software and documentation and use in source and 965185Sache * binary forms, with or without modification, are permitted provided that 1065185Sache * the following conditions are met: 1165185Sache * 1265185Sache * 1. Redistributions of source code or documentation must retain the above 1365185Sache * copyright notice, this list of conditions and the following disclaimer. 1465185Sache * 2. Redistributions in binary form must reproduce the above copyright 1565185Sache * notice, this list of conditions and the following disclaimer in the 1665185Sache * documentation and/or other materials provided with the distribution. 1765185Sache * 3. Neither the name of the Institute nor the names of its contributors 1865185Sache * may be used to endorse or promote products derived from this software 1965185Sache * without specific prior written permission. 2065185Sache * 2165185Sache * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS 2265185Sache * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 2365185Sache * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 2465185Sache * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 2565185Sache * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2665185Sache * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2765185Sache * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 2865185Sache * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2965185Sache * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3065185Sache * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 3165185Sache * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3265185Sache * 3365185Sache * $Begemot: bsnmp/snmp_mibII/mibII_interfaces.c,v 1.9 2003/01/28 13:44:35 hbb Exp $ 3465185Sache * 3565185Sache * Interfaces group. 3665185Sache */ 3765185Sache#include "mibII.h" 3865185Sache#include "mibII_oid.h" 3965185Sache 4065185Sache/* 4165185Sache * This structure catches all changes to a interface entry 4265185Sache */ 4365185Sachestruct ifchange { 4465185Sache struct snmp_dependency dep; 4565185Sache 4665185Sache u_int ifindex; 4765185Sache 4865185Sache u_int32_t set; 4965185Sache int promisc; 5065185Sache int admin; 5165185Sache int traps; 5265185Sache 5365185Sache u_int32_t rb; 5465185Sache int rb_flags; 5565185Sache int rb_traps; 5665185Sache}; 5765185Sache#define IFC_PROMISC 0x0001 5865185Sache#define IFC_ADMIN 0x0002 5965185Sache#define IFC_TRAPS 0x0004 6065185Sache#define IFRB_FLAGS 0x0001 6165185Sache#define IFRB_TRAPS 0x0002 6265185Sache 6365185Sachestatic const struct asn_oid 6465185Sache oid_ifTable = OIDX_ifTable; 6565185Sache 6665185Sache/* 6765185Sache * This function handles all changes to the interface table and interface 6865185Sache * extension table. 6965185Sache */ 7065185Sachestatic int 7165185Sacheifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep, 7265185Sache enum snmp_depop op) 7365185Sache{ 7465185Sache struct ifchange *ifc = (struct ifchange *)dep; 7565185Sache struct mibif *ifp; 7665185Sache struct ifreq ifr, ifr1; 7765185Sache 7865185Sache if ((ifp = mib_find_if(ifc->ifindex)) == NULL) 7965185Sache return (SNMP_ERR_NO_CREATION); 8065185Sache 8165185Sache switch (op) { 8265185Sache 8365185Sache case SNMP_DEPOP_COMMIT: 8465185Sache strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 8565185Sache if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) { 8665185Sache syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name); 8765185Sache return (SNMP_ERR_GENERR); 8865185Sache } 8965185Sache if (ifc->set & IFC_PROMISC) { 9065185Sache ifr.ifr_flags &= ~IFF_PROMISC; 9165185Sache if (ifc->promisc) 9265185Sache ifr.ifr_flags |= IFF_PROMISC; 9365185Sache ifc->rb |= IFRB_FLAGS; 9465185Sache } 9565185Sache if (ifc->set & IFC_ADMIN) { 9665185Sache ifr.ifr_flags &= ~IFF_UP; 9765185Sache if (ifc->admin) 9874119Sache ifr.ifr_flags |= IFF_UP; 9965185Sache ifc->rb |= IFRB_FLAGS; 10065185Sache } 10165185Sache if (ifc->rb & IFRB_FLAGS) { 10265185Sache strncpy(ifr1.ifr_name, ifp->name, sizeof(ifr1.ifr_name)); 10365185Sache if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr1) == -1) { 10465185Sache syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name); 10565185Sache return (SNMP_ERR_GENERR); 10665185Sache } 10765185Sache ifc->rb_flags = ifr1.ifr_flags; 10874119Sache if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) { 10965185Sache syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name); 11065185Sache return (SNMP_ERR_GENERR); 11165185Sache } 11265185Sache (void)mib_fetch_ifmib(ifp); 11365185Sache } 11465185Sache if (ifc->set & IFC_TRAPS) { 115 ifc->rb |= IFRB_TRAPS; 116 ifc->rb_traps = ifp->trap_enable; 117 ifp->trap_enable = ifc->traps; 118 } 119 return (SNMP_ERR_NOERROR); 120 121 case SNMP_DEPOP_ROLLBACK: 122 if (ifc->rb & IFRB_FLAGS) { 123 strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 124 ifr.ifr_flags = ifc->rb_flags; 125 if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) { 126 syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name); 127 return (SNMP_ERR_UNDO_FAILED); 128 } 129 (void)mib_fetch_ifmib(ifp); 130 } 131 if (ifc->rb & IFRB_TRAPS) 132 ifp->trap_enable = ifc->rb_traps; 133 return (SNMP_ERR_NOERROR); 134 135 } 136 abort(); 137} 138 139static u_int32_t 140ticks_get_timeval(struct timeval *tv) 141{ 142 u_int32_t v; 143 144 if (tv->tv_sec != 0 || tv->tv_usec != 0) { 145 v = 100 * tv->tv_sec + tv->tv_usec / 10000; 146 if (v > start_tick) 147 return (v - start_tick); 148 } 149 return (0); 150} 151 152/* 153 * Scalars 154 */ 155int 156op_interfaces(struct snmp_context *ctx __unused, struct snmp_value *value, 157 u_int sub, u_int idx __unused, enum snmp_op op) 158{ 159 switch (op) { 160 161 case SNMP_OP_GETNEXT: 162 abort(); 163 164 case SNMP_OP_GET: 165 break; 166 167 case SNMP_OP_SET: 168 return (SNMP_ERR_NOT_WRITEABLE); 169 170 case SNMP_OP_ROLLBACK: 171 case SNMP_OP_COMMIT: 172 abort(); 173 } 174 175 switch (value->var.subs[sub - 1]) { 176 177 case LEAF_ifNumber: 178 value->v.integer = mib_if_number; 179 break; 180 } 181 return (SNMP_ERR_NOERROR); 182} 183 184/* 185 * Iftable entry 186 */ 187int 188op_ifentry(struct snmp_context *ctx, struct snmp_value *value, 189 u_int sub, u_int iidx __unused, enum snmp_op op) 190{ 191 struct mibif *ifp = NULL; 192 int ret; 193 struct ifchange *ifc; 194 struct asn_oid idx; 195 196 switch (op) { 197 198 case SNMP_OP_GETNEXT: 199 if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL) 200 return (SNMP_ERR_NOSUCHNAME); 201 value->var.len = sub + 1; 202 value->var.subs[sub] = ifp->index; 203 break; 204 205 case SNMP_OP_GET: 206 if (value->var.len - sub != 1) 207 return (SNMP_ERR_NOSUCHNAME); 208 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL) 209 return (SNMP_ERR_NOSUCHNAME); 210 break; 211 212 case SNMP_OP_SET: 213 if (value->var.len - sub != 1) 214 return (SNMP_ERR_NO_CREATION); 215 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL) 216 return (SNMP_ERR_NO_CREATION); 217 if (value->var.subs[sub - 1] != LEAF_ifAdminStatus) 218 return (SNMP_ERR_NOT_WRITEABLE); 219 220 idx.len = 1; 221 idx.subs[0] = ifp->index; 222 223 if (value->v.integer != 1 && value->v.integer != 2) 224 return (SNMP_ERR_WRONG_VALUE); 225 226 if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx, 227 &oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL) 228 return (SNMP_ERR_RES_UNAVAIL); 229 ifc->ifindex = ifp->index; 230 231 if (ifc->set & IFC_ADMIN) 232 return (SNMP_ERR_INCONS_VALUE); 233 ifc->set |= IFC_ADMIN; 234 ifc->admin = (value->v.integer == 1) ? 1 : 0; 235 236 return (SNMP_ERR_NOERROR); 237 238 case SNMP_OP_ROLLBACK: 239 case SNMP_OP_COMMIT: 240 return (SNMP_ERR_NOERROR); 241 } 242 243 if (ifp->mibtick < this_tick) 244 (void)mib_fetch_ifmib(ifp); 245 246 ret = SNMP_ERR_NOERROR; 247 switch (value->var.subs[sub - 1]) { 248 249 case LEAF_ifIndex: 250 value->v.integer = ifp->index; 251 break; 252 253 case LEAF_ifDescr: 254 ret = string_get(value, ifp->descr, -1); 255 break; 256 257 case LEAF_ifType: 258 value->v.integer = ifp->mib.ifmd_data.ifi_type; 259 break; 260 261 case LEAF_ifMtu: 262 value->v.integer = ifp->mib.ifmd_data.ifi_mtu; 263 break; 264 265 case LEAF_ifSpeed: 266 value->v.integer = ifp->mib.ifmd_data.ifi_baudrate; 267 break; 268 269 case LEAF_ifPhysAddress: 270 ret = string_get(value, ifp->physaddr, 271 ifp->physaddrlen); 272 break; 273 274 case LEAF_ifAdminStatus: 275 value->v.integer = 276 (ifp->mib.ifmd_flags & IFF_UP) ? 1 : 2; 277 break; 278 279 case LEAF_ifOperStatus: 280 value->v.integer = 281 (ifp->mib.ifmd_flags & IFF_RUNNING) ? 1 : 2; 282 break; 283 284 case LEAF_ifLastChange: 285 value->v.uint32 = 286 ticks_get_timeval(&ifp->mib.ifmd_data.ifi_lastchange); 287 break; 288 289 case LEAF_ifInOctets: 290 value->v.uint32 = ifp->mib.ifmd_data.ifi_ibytes; 291 break; 292 293 case LEAF_ifInUcastPkts: 294 value->v.uint32 = ifp->mib.ifmd_data.ifi_ipackets - 295 ifp->mib.ifmd_data.ifi_imcasts; 296 break; 297 298 case LEAF_ifInNUcastPkts: 299 value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts; 300 break; 301 302 case LEAF_ifInDiscards: 303 value->v.uint32 = ifp->mib.ifmd_data.ifi_iqdrops; 304 break; 305 306 case LEAF_ifInErrors: 307 value->v.uint32 = ifp->mib.ifmd_data.ifi_ierrors; 308 break; 309 310 case LEAF_ifInUnknownProtos: 311 value->v.uint32 = ifp->mib.ifmd_data.ifi_noproto; 312 break; 313 314 case LEAF_ifOutOctets: 315 value->v.uint32 = ifp->mib.ifmd_data.ifi_obytes; 316 break; 317 318 case LEAF_ifOutUcastPkts: 319 value->v.uint32 = ifp->mib.ifmd_data.ifi_opackets - 320 ifp->mib.ifmd_data.ifi_omcasts; 321 break; 322 323 case LEAF_ifOutNUcastPkts: 324 value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts; 325 break; 326 327 case LEAF_ifOutDiscards: 328 value->v.uint32 = ifp->mib.ifmd_snd_drops; 329 break; 330 331 case LEAF_ifOutErrors: 332 value->v.uint32 = ifp->mib.ifmd_data.ifi_oerrors; 333 break; 334 335 case LEAF_ifOutQLen: 336 value->v.uint32 = ifp->mib.ifmd_snd_len; 337 break; 338 339 case LEAF_ifSpecific: 340 value->v.oid = oid_zeroDotZero; 341 break; 342 } 343 return (SNMP_ERR_NOERROR); 344} 345 346/* 347 * IfXtable entry 348 */ 349int 350op_ifxtable(struct snmp_context *ctx, struct snmp_value *value, 351 u_int sub, u_int iidx __unused, enum snmp_op op) 352{ 353 struct mibif *ifp = NULL; 354 int ret; 355 struct ifchange *ifc; 356 struct asn_oid idx; 357 358 switch (op) { 359 360 again: 361 if (op != SNMP_OP_GETNEXT) 362 return (SNMP_ERR_NOSUCHNAME); 363 /* FALLTHROUGH */ 364 365 case SNMP_OP_GETNEXT: 366 if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL) 367 return (SNMP_ERR_NOSUCHNAME); 368 value->var.len = sub + 1; 369 value->var.subs[sub] = ifp->index; 370 break; 371 372 case SNMP_OP_GET: 373 if (value->var.len - sub != 1) 374 return (SNMP_ERR_NOSUCHNAME); 375 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL) 376 return (SNMP_ERR_NOSUCHNAME); 377 break; 378 379 case SNMP_OP_SET: 380 if (value->var.len - sub != 1) 381 return (SNMP_ERR_NO_CREATION); 382 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL) 383 return (SNMP_ERR_NO_CREATION); 384 385 idx.len = 1; 386 idx.subs[0] = ifp->index; 387 388 if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx, 389 &oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL) 390 return (SNMP_ERR_RES_UNAVAIL); 391 ifc->ifindex = ifp->index; 392 393 switch (value->var.subs[sub - 1]) { 394 395 case LEAF_ifLinkUpDownTrapEnable: 396 if (value->v.integer != 1 && value->v.integer != 2) 397 return (SNMP_ERR_WRONG_VALUE); 398 if (ifc->set & IFC_TRAPS) 399 return (SNMP_ERR_INCONS_VALUE); 400 ifc->set |= IFC_TRAPS; 401 ifc->traps = (value->v.integer == 1) ? 1 : 0; 402 return (SNMP_ERR_NOERROR); 403 404 case LEAF_ifPromiscuousMode: 405 if (value->v.integer != 1 && value->v.integer != 2) 406 return (SNMP_ERR_WRONG_VALUE); 407 if (ifc->set & IFC_PROMISC) 408 return (SNMP_ERR_INCONS_VALUE); 409 ifc->set |= IFC_PROMISC; 410 ifc->promisc = (value->v.integer == 1) ? 1 : 0; 411 return (SNMP_ERR_NOERROR); 412 } 413 return (SNMP_ERR_NOT_WRITEABLE); 414 415 case SNMP_OP_ROLLBACK: 416 case SNMP_OP_COMMIT: 417 return (SNMP_ERR_NOERROR); 418 } 419 420 if (ifp->mibtick < this_tick) 421 (void)mib_fetch_ifmib(ifp); 422 423 ret = SNMP_ERR_NOERROR; 424 switch (value->var.subs[sub - 1]) { 425 426 case LEAF_ifName: 427 ret = string_get(value, ifp->name, -1); 428 break; 429 430 case LEAF_ifInMulticastPkts: 431 value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts; 432 break; 433 434 case LEAF_ifInBroadcastPkts: 435 value->v.uint32 = 0; 436 break; 437 438 case LEAF_ifOutMulticastPkts: 439 value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts; 440 break; 441 442 case LEAF_ifOutBroadcastPkts: 443 value->v.uint32 = 0; 444 break; 445 446 case LEAF_ifHCInOctets: 447 if (!(ifp->flags & MIBIF_HIGHSPEED)) 448 goto again; 449 value->v.counter64 = ifp->hc_inoctets; 450 break; 451 452 case LEAF_ifHCInUcastPkts: 453 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) 454 goto again; 455 value->v.counter64 = ifp->hc_ipackets - ifp->hc_imcasts; 456 break; 457 458 case LEAF_ifHCInMulticastPkts: 459 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) 460 goto again; 461 value->v.counter64 = ifp->hc_imcasts; 462 break; 463 464 case LEAF_ifHCInBroadcastPkts: 465 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) 466 goto again; 467 value->v.counter64 = 0; 468 break; 469 470 case LEAF_ifHCOutOctets: 471 if (!(ifp->flags & MIBIF_HIGHSPEED)) 472 goto again; 473 value->v.counter64 = ifp->hc_inoctets; 474 break; 475 476 case LEAF_ifHCOutUcastPkts: 477 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) 478 goto again; 479 value->v.counter64 = ifp->hc_opackets - ifp->hc_omcasts; 480 break; 481 482 case LEAF_ifHCOutMulticastPkts: 483 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) 484 goto again; 485 value->v.counter64 = ifp->hc_omcasts; 486 break; 487 488 case LEAF_ifHCOutBroadcastPkts: 489 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) 490 goto again; 491 value->v.counter64 = 0; 492 break; 493 494 case LEAF_ifLinkUpDownTrapEnable: 495 value->v.integer = ifp->trap_enable ? 1 : 2; 496 break; 497 498 case LEAF_ifHighSpeed: 499 value->v.integer = 500 (ifp->mib.ifmd_data.ifi_baudrate + 499999) / 1000000; 501 break; 502 503 case LEAF_ifPromiscuousMode: 504 value->v.integer = 505 (ifp->mib.ifmd_flags & IFF_PROMISC) ? 1 : 2; 506 break; 507 508 case LEAF_ifConnectorPresent: 509 value->v.integer = ifp->has_connector ? 1 : 2; 510 break; 511 512 case LEAF_ifAlias: 513 ret = string_get(value, "", -1); 514 break; 515 516 case LEAF_ifCounterDiscontinuityTime: 517 if (ifp->counter_disc > start_tick) 518 value->v.uint32 = ifp->counter_disc - start_tick; 519 else 520 value->v.uint32 = 0; 521 break; 522 } 523 return (ret); 524} 525