1 /* 2 * Copyright (c) 2001-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Author: Harti Brandt <harti@freebsd.org> 7 * 8 * Redistribution of this software and documentation and use in source and 9 * binary forms, with or without modification, are permitted provided that 10 * the following conditions are met: 11 * 12 * 1. Redistributions of source code or documentation must retain the above 13 * copyright notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS 22 * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25 * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $Begemot: bsnmp/snmpd/action.c,v 1.57 2004/04/13 14:58:46 novo Exp $ 34 * 35 * Variable access for SNMPd 36 */ 37 #include <sys/types.h> 38 #include <sys/sysctl.h> 39 #include <sys/un.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <stdarg.h> 43 #include <string.h> 44 #include <ctype.h> 45 #include <syslog.h> 46 47 #include "snmpmod.h" 48 #include "snmpd.h" 49 #include "tree.h" 50 #include "oid.h" 51 52 static const struct asn_oid 53 oid_begemotSnmpdModuleTable = OIDX_begemotSnmpdModuleTable; 54 55 /* 56 * Get a string value from the KERN sysctl subtree. 57 */ 58 static char * 59 act_getkernstring(int id) 60 { 61 int mib[2]; 62 size_t len; 63 char *string; 64 65 mib[0] = CTL_KERN; 66 mib[1] = id; 67 if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0) 68 return (NULL); 69 if ((string = malloc(len)) == NULL) 70 return (NULL); 71 if (sysctl(mib, 2, string, &len, NULL, 0) != 0) { 72 free(string); 73 return (NULL); 74 } 75 return (string); 76 } 77 78 /* 79 * Get an integer value from the KERN sysctl subtree. 80 */ 81 static char * 82 act_getkernint(int id) 83 { 84 int mib[2]; 85 size_t len; 86 u_long value; 87 char *string; 88 89 mib[0] = CTL_KERN; 90 mib[1] = id; 91 len = sizeof(value); 92 if (sysctl(mib, 2, &value, &len, NULL, 0) != 0) 93 return (NULL); 94 95 if ((string = malloc(20)) == NULL) 96 return (NULL); 97 sprintf(string, "%lu", value); 98 return (string); 99 } 100 101 /* 102 * Initialize global variables of the system group. 103 */ 104 int 105 init_actvals(void) 106 { 107 char *v[4]; 108 u_int i; 109 size_t len; 110 111 if ((systemg.name = act_getkernstring(KERN_HOSTNAME)) == NULL) 112 return (-1); 113 114 for (i = 0; i < 4; i++) 115 v[1] = NULL; 116 117 if ((v[0] = act_getkernstring(KERN_HOSTNAME)) == NULL) 118 goto err; 119 if ((v[1] = act_getkernint(KERN_HOSTID)) == NULL) 120 goto err; 121 if ((v[2] = act_getkernstring(KERN_OSTYPE)) == NULL) 122 goto err; 123 if ((v[3] = act_getkernstring(KERN_OSRELEASE)) == NULL) 124 goto err; 125 126 for (i = 0, len = 0; i < 4; i++) 127 len += strlen(v[i]) + 1; 128 129 if ((systemg.descr = malloc(len)) == NULL) 130 goto err; 131 sprintf(systemg.descr, "%s %s %s %s", v[0], v[1], v[2], v[3]); 132 133 return (0); 134 135 err: 136 for (i = 0; i < 4; i++) 137 if (v[i] != NULL) 138 free(v[i]); 139 return (-1); 140 } 141 142 143 144 /************************************************************* 145 * 146 * System group 147 */ 148 int 149 op_system_group(struct snmp_context *ctx, struct snmp_value *value, 150 u_int sub, u_int iidx __unused, enum snmp_op op) 151 { 152 asn_subid_t which = value->var.subs[sub - 1]; 153 154 switch (op) { 155 156 case SNMP_OP_GETNEXT: 157 abort(); 158 159 case SNMP_OP_GET: 160 break; 161 162 case SNMP_OP_SET: 163 switch (which) { 164 165 case LEAF_sysDescr: 166 if (community != COMM_INITIALIZE) 167 return (SNMP_ERR_NOT_WRITEABLE); 168 return (string_save(value, ctx, -1, &systemg.descr)); 169 170 case LEAF_sysObjectId: 171 if (community != COMM_INITIALIZE) 172 return (SNMP_ERR_NOT_WRITEABLE); 173 return (oid_save(value, ctx, &systemg.object_id)); 174 175 case LEAF_sysContact: 176 return (string_save(value, ctx, -1, &systemg.contact)); 177 178 case LEAF_sysName: 179 return (string_save(value, ctx, -1, &systemg.name)); 180 181 case LEAF_sysLocation: 182 return (string_save(value, ctx, -1, &systemg.location)); 183 } 184 return (SNMP_ERR_NO_CREATION); 185 186 case SNMP_OP_ROLLBACK: 187 switch (which) { 188 189 case LEAF_sysDescr: 190 string_rollback(ctx, &systemg.descr); 191 return (SNMP_ERR_NOERROR); 192 case LEAF_sysObjectId: 193 oid_rollback(ctx, &systemg.object_id); 194 return (SNMP_ERR_NOERROR); 195 case LEAF_sysContact: 196 string_rollback(ctx, &systemg.contact); 197 return (SNMP_ERR_NOERROR); 198 case LEAF_sysName: 199 string_rollback(ctx, &systemg.name); 200 return (SNMP_ERR_NOERROR); 201 case LEAF_sysLocation: 202 string_rollback(ctx, &systemg.location); 203 return (SNMP_ERR_NOERROR); 204 } 205 abort(); 206 207 case SNMP_OP_COMMIT: 208 switch (which) { 209 210 case LEAF_sysDescr: 211 string_commit(ctx); 212 return (SNMP_ERR_NOERROR); 213 case LEAF_sysObjectId: 214 oid_commit(ctx); 215 return (SNMP_ERR_NOERROR); 216 case LEAF_sysContact: 217 string_commit(ctx); 218 return (SNMP_ERR_NOERROR); 219 case LEAF_sysName: 220 string_commit(ctx); 221 return (SNMP_ERR_NOERROR); 222 case LEAF_sysLocation: 223 string_commit(ctx); 224 return (SNMP_ERR_NOERROR); 225 } 226 abort(); 227 } 228 229 /* 230 * Come here for GET. 231 */ 232 switch (which) { 233 234 case LEAF_sysDescr: 235 return (string_get(value, systemg.descr, -1)); 236 case LEAF_sysObjectId: 237 return (oid_get(value, &systemg.object_id)); 238 case LEAF_sysUpTime: 239 value->v.uint32 = get_ticks() - start_tick; 240 break; 241 case LEAF_sysContact: 242 return (string_get(value, systemg.contact, -1)); 243 case LEAF_sysName: 244 return (string_get(value, systemg.name, -1)); 245 case LEAF_sysLocation: 246 return (string_get(value, systemg.location, -1)); 247 case LEAF_sysServices: 248 value->v.integer = systemg.services; 249 break; 250 case LEAF_sysORLastChange: 251 value->v.uint32 = systemg.or_last_change; 252 break; 253 } 254 return (SNMP_ERR_NOERROR); 255 } 256 257 /************************************************************* 258 * 259 * Debug group 260 */ 261 int 262 op_debug(struct snmp_context *ctx, struct snmp_value *value, u_int sub, 263 u_int iidx __unused, enum snmp_op op) 264 { 265 asn_subid_t which = value->var.subs[sub - 1]; 266 267 switch (op) { 268 269 case SNMP_OP_GETNEXT: 270 abort(); 271 272 case SNMP_OP_GET: 273 switch (which) { 274 275 case LEAF_begemotSnmpdDebugDumpPdus: 276 value->v.integer = TRUTH_MK(debug.dump_pdus); 277 break; 278 279 case LEAF_begemotSnmpdDebugSnmpTrace: 280 value->v.uint32 = snmp_trace; 281 break; 282 283 case LEAF_begemotSnmpdDebugSyslogPri: 284 value->v.integer = debug.logpri; 285 break; 286 } 287 return (SNMP_ERR_NOERROR); 288 289 case SNMP_OP_SET: 290 switch (which) { 291 292 case LEAF_begemotSnmpdDebugDumpPdus: 293 if (!TRUTH_OK(value->v.integer)) 294 return (SNMP_ERR_WRONG_VALUE); 295 ctx->scratch->int1 = debug.dump_pdus; 296 debug.dump_pdus = TRUTH_GET(value->v.integer); 297 return (SNMP_ERR_NOERROR); 298 299 case LEAF_begemotSnmpdDebugSnmpTrace: 300 ctx->scratch->int1 = snmp_trace; 301 snmp_trace = value->v.uint32; 302 return (SNMP_ERR_NOERROR); 303 304 case LEAF_begemotSnmpdDebugSyslogPri: 305 if (value->v.integer < 0 || value->v.integer > 8) 306 return (SNMP_ERR_WRONG_VALUE); 307 ctx->scratch->int1 = debug.logpri; 308 debug.logpri = (u_int)value->v.integer; 309 return (SNMP_ERR_NOERROR); 310 } 311 return (SNMP_ERR_NO_CREATION); 312 313 case SNMP_OP_ROLLBACK: 314 switch (which) { 315 316 case LEAF_begemotSnmpdDebugDumpPdus: 317 debug.dump_pdus = ctx->scratch->int1; 318 return (SNMP_ERR_NOERROR); 319 320 case LEAF_begemotSnmpdDebugSnmpTrace: 321 snmp_trace = ctx->scratch->int1; 322 return (SNMP_ERR_NOERROR); 323 324 case LEAF_begemotSnmpdDebugSyslogPri: 325 debug.logpri = ctx->scratch->int1; 326 return (SNMP_ERR_NOERROR); 327 } 328 abort(); 329 330 case SNMP_OP_COMMIT: 331 switch (which) { 332 333 case LEAF_begemotSnmpdDebugDumpPdus: 334 case LEAF_begemotSnmpdDebugSnmpTrace: 335 return (SNMP_ERR_NOERROR); 336 337 case LEAF_begemotSnmpdDebugSyslogPri: 338 if (debug.logpri == 0) 339 setlogmask(0); 340 else 341 setlogmask(LOG_UPTO(debug.logpri - 1)); 342 return (SNMP_ERR_NOERROR); 343 } 344 abort(); 345 } 346 abort(); 347 } 348 349 /************************************************************* 350 * 351 * OR Table 352 */ 353 int 354 op_or_table(struct snmp_context *ctx __unused, struct snmp_value *value, 355 u_int sub, u_int iidx __unused, enum snmp_op op) 356 { 357 struct objres *objres; 358 359 switch (op) { 360 361 case SNMP_OP_GETNEXT: 362 if ((objres = NEXT_OBJECT_INT(&objres_list, &value->var, sub)) 363 == NULL) 364 return (SNMP_ERR_NOSUCHNAME); 365 value->var.subs[sub] = objres->index; 366 value->var.len = sub + 1; 367 break; 368 369 case SNMP_OP_GET: 370 if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub)) 371 == NULL) 372 return (SNMP_ERR_NOSUCHNAME); 373 break; 374 375 case SNMP_OP_SET: 376 if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub)) 377 == NULL) 378 return (SNMP_ERR_NO_CREATION); 379 return (SNMP_ERR_NOT_WRITEABLE); 380 381 case SNMP_OP_ROLLBACK: 382 case SNMP_OP_COMMIT: 383 default: 384 abort(); 385 } 386 387 /* 388 * Come here for GET, GETNEXT. 389 */ 390 switch (value->var.subs[sub - 1]) { 391 392 case LEAF_sysORID: 393 value->v.oid = objres->oid; 394 break; 395 396 case LEAF_sysORDescr: 397 return (string_get(value, objres->descr, -1)); 398 399 case LEAF_sysORUpTime: 400 value->v.uint32 = objres->uptime; 401 break; 402 } 403 return (SNMP_ERR_NOERROR); 404 } 405 406 /************************************************************* 407 * 408 * mib-2 snmp 409 */ 410 int 411 op_snmp(struct snmp_context *ctx, struct snmp_value *value, 412 u_int sub, u_int iidx __unused, enum snmp_op op) 413 { 414 switch (op) { 415 416 case SNMP_OP_GETNEXT: 417 abort(); 418 419 case SNMP_OP_GET: 420 switch (value->var.subs[sub - 1]) { 421 422 case LEAF_snmpInPkts: 423 value->v.uint32 = snmpd_stats.inPkts; 424 break; 425 426 case LEAF_snmpInBadVersions: 427 value->v.uint32 = snmpd_stats.inBadVersions; 428 break; 429 430 case LEAF_snmpInBadCommunityNames: 431 value->v.uint32 = snmpd_stats.inBadCommunityNames; 432 break; 433 434 case LEAF_snmpInBadCommunityUses: 435 value->v.uint32 = snmpd_stats.inBadCommunityUses; 436 break; 437 438 case LEAF_snmpInASNParseErrs: 439 value->v.uint32 = snmpd_stats.inASNParseErrs; 440 break; 441 442 case LEAF_snmpEnableAuthenTraps: 443 value->v.integer = TRUTH_MK(snmpd.auth_traps); 444 break; 445 446 case LEAF_snmpSilentDrops: 447 value->v.uint32 = snmpd_stats.silentDrops; 448 break; 449 450 case LEAF_snmpProxyDrops: 451 value->v.uint32 = snmpd_stats.proxyDrops; 452 break; 453 454 default: 455 return (SNMP_ERR_NOSUCHNAME); 456 457 } 458 return (SNMP_ERR_NOERROR); 459 460 case SNMP_OP_SET: 461 switch (value->var.subs[sub - 1]) { 462 case LEAF_snmpEnableAuthenTraps: 463 if (!TRUTH_OK(value->v.integer)) 464 return (SNMP_ERR_WRONG_VALUE); 465 ctx->scratch->int1 = value->v.integer; 466 snmpd.auth_traps = TRUTH_GET(value->v.integer); 467 return (SNMP_ERR_NOERROR); 468 } 469 abort(); 470 471 case SNMP_OP_ROLLBACK: 472 switch (value->var.subs[sub - 1]) { 473 case LEAF_snmpEnableAuthenTraps: 474 snmpd.auth_traps = ctx->scratch->int1; 475 return (SNMP_ERR_NOERROR); 476 } 477 abort(); 478 479 case SNMP_OP_COMMIT: 480 switch (value->var.subs[sub - 1]) { 481 case LEAF_snmpEnableAuthenTraps: 482 return (SNMP_ERR_NOERROR); 483 } 484 abort(); 485 } 486 abort(); 487 } 488 489 /************************************************************* 490 * 491 * SNMPd statistics group 492 */ 493 int 494 op_snmpd_stats(struct snmp_context *ctx __unused, struct snmp_value *value, 495 u_int sub, u_int iidx __unused, enum snmp_op op) 496 { 497 switch (op) { 498 499 case SNMP_OP_GET: 500 switch (value->var.subs[sub - 1]) { 501 502 case LEAF_begemotSnmpdStatsNoRxBufs: 503 value->v.uint32 = snmpd_stats.noRxbuf; 504 break; 505 506 case LEAF_begemotSnmpdStatsNoTxBufs: 507 value->v.uint32 = snmpd_stats.noTxbuf; 508 break; 509 510 case LEAF_begemotSnmpdStatsInTooLongPkts: 511 value->v.uint32 = snmpd_stats.inTooLong; 512 break; 513 514 case LEAF_begemotSnmpdStatsInBadPduTypes: 515 value->v.uint32 = snmpd_stats.inBadPduTypes; 516 break; 517 518 default: 519 return (SNMP_ERR_NOSUCHNAME); 520 } 521 return (SNMP_ERR_NOERROR); 522 523 case SNMP_OP_SET: 524 case SNMP_OP_ROLLBACK: 525 case SNMP_OP_COMMIT: 526 case SNMP_OP_GETNEXT: 527 abort(); 528 } 529 abort(); 530 } 531 532 /* 533 * SNMPd configuration scalars 534 */ 535 int 536 op_snmpd_config(struct snmp_context *ctx, struct snmp_value *value, 537 u_int sub, u_int iidx __unused, enum snmp_op op) 538 { 539 asn_subid_t which = value->var.subs[sub - 1]; 540 541 switch (op) { 542 543 case SNMP_OP_GETNEXT: 544 abort(); 545 546 case SNMP_OP_GET: 547 switch (which) { 548 549 case LEAF_begemotSnmpdTransmitBuffer: 550 value->v.integer = snmpd.txbuf; 551 break; 552 case LEAF_begemotSnmpdReceiveBuffer: 553 value->v.integer = snmpd.rxbuf; 554 break; 555 case LEAF_begemotSnmpdCommunityDisable: 556 value->v.integer = TRUTH_MK(snmpd.comm_dis); 557 break; 558 case LEAF_begemotSnmpdTrap1Addr: 559 return (ip_get(value, snmpd.trap1addr)); 560 case LEAF_begemotSnmpdVersionEnable: 561 value->v.uint32 = snmpd.version_enable; 562 break; 563 default: 564 return (SNMP_ERR_NOSUCHNAME); 565 } 566 return (SNMP_ERR_NOERROR); 567 568 case SNMP_OP_SET: 569 switch (which) { 570 571 case LEAF_begemotSnmpdTransmitBuffer: 572 ctx->scratch->int1 = snmpd.txbuf; 573 if (value->v.integer < 484 || 574 value->v.integer > 65535) 575 return (SNMP_ERR_WRONG_VALUE); 576 snmpd.txbuf = value->v.integer; 577 return (SNMP_ERR_NOERROR); 578 579 case LEAF_begemotSnmpdReceiveBuffer: 580 ctx->scratch->int1 = snmpd.rxbuf; 581 if (value->v.integer < 484 || 582 value->v.integer > 65535) 583 return (SNMP_ERR_WRONG_VALUE); 584 snmpd.rxbuf = value->v.integer; 585 return (SNMP_ERR_NOERROR); 586 587 case LEAF_begemotSnmpdCommunityDisable: 588 ctx->scratch->int1 = snmpd.comm_dis; 589 if (!TRUTH_OK(value->v.integer)) 590 return (SNMP_ERR_WRONG_VALUE); 591 if (TRUTH_GET(value->v.integer)) { 592 snmpd.comm_dis = 1; 593 } else { 594 if (snmpd.comm_dis) 595 return (SNMP_ERR_WRONG_VALUE); 596 } 597 return (SNMP_ERR_NOERROR); 598 599 case LEAF_begemotSnmpdTrap1Addr: 600 return (ip_save(value, ctx, snmpd.trap1addr)); 601 602 case LEAF_begemotSnmpdVersionEnable: 603 if (community != COMM_INITIALIZE) 604 return (SNMP_ERR_NOT_WRITEABLE); 605 ctx->scratch->int1 = snmpd.version_enable; 606 if (value->v.uint32 == 0 || 607 (value->v.uint32 & ~VERS_ENABLE_ALL)) 608 return (SNMP_ERR_WRONG_VALUE); 609 snmpd.version_enable = value->v.uint32; 610 return (SNMP_ERR_NOERROR); 611 } 612 abort(); 613 614 case SNMP_OP_ROLLBACK: 615 switch (which) { 616 617 case LEAF_begemotSnmpdTransmitBuffer: 618 snmpd.rxbuf = ctx->scratch->int1; 619 return (SNMP_ERR_NOERROR); 620 case LEAF_begemotSnmpdReceiveBuffer: 621 snmpd.txbuf = ctx->scratch->int1; 622 return (SNMP_ERR_NOERROR); 623 case LEAF_begemotSnmpdCommunityDisable: 624 snmpd.comm_dis = ctx->scratch->int1; 625 return (SNMP_ERR_NOERROR); 626 case LEAF_begemotSnmpdTrap1Addr: 627 ip_rollback(ctx, snmpd.trap1addr); 628 return (SNMP_ERR_NOERROR); 629 case LEAF_begemotSnmpdVersionEnable: 630 snmpd.version_enable = ctx->scratch->int1; 631 return (SNMP_ERR_NOERROR); 632 } 633 abort(); 634 635 case SNMP_OP_COMMIT: 636 switch (which) { 637 638 case LEAF_begemotSnmpdTransmitBuffer: 639 case LEAF_begemotSnmpdReceiveBuffer: 640 case LEAF_begemotSnmpdCommunityDisable: 641 return (SNMP_ERR_NOERROR); 642 case LEAF_begemotSnmpdTrap1Addr: 643 ip_commit(ctx); 644 return (SNMP_ERR_NOERROR); 645 case LEAF_begemotSnmpdVersionEnable: 646 return (SNMP_ERR_NOERROR); 647 } 648 abort(); 649 } 650 abort(); 651 } 652 653 /* 654 * The community table 655 */ 656 int 657 op_community(struct snmp_context *ctx, struct snmp_value *value, 658 u_int sub, u_int iidx __unused, enum snmp_op op) 659 { 660 asn_subid_t which = value->var.subs[sub - 1]; 661 struct community *c; 662 663 switch (op) { 664 665 case SNMP_OP_GETNEXT: 666 if ((community != COMM_INITIALIZE && snmpd.comm_dis) || 667 (c = NEXT_OBJECT_OID(&community_list, &value->var, sub)) == NULL) 668 return (SNMP_ERR_NOSUCHNAME); 669 index_append(&value->var, sub, &c->index); 670 break; 671 672 case SNMP_OP_GET: 673 if ((community != COMM_INITIALIZE && snmpd.comm_dis) || 674 (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL) 675 return (SNMP_ERR_NOSUCHNAME); 676 break; 677 678 case SNMP_OP_SET: 679 if ((community != COMM_INITIALIZE && snmpd.comm_dis) || 680 (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL) 681 return (SNMP_ERR_NO_CREATION); 682 if (which != LEAF_begemotSnmpdCommunityString) 683 return (SNMP_ERR_NOT_WRITEABLE); 684 return (string_save(value, ctx, -1, &c->string)); 685 686 case SNMP_OP_ROLLBACK: 687 if (which == LEAF_begemotSnmpdCommunityString) { 688 if ((c = FIND_OBJECT_OID(&community_list, &value->var, 689 sub)) == NULL) 690 string_free(ctx); 691 else 692 string_rollback(ctx, &c->string); 693 return (SNMP_ERR_NOERROR); 694 } 695 abort(); 696 697 case SNMP_OP_COMMIT: 698 if (which == LEAF_begemotSnmpdCommunityString) { 699 if ((c = FIND_OBJECT_OID(&community_list, &value->var, 700 sub)) == NULL) 701 string_free(ctx); 702 else 703 string_commit(ctx); 704 return (SNMP_ERR_NOERROR); 705 } 706 abort(); 707 708 default: 709 abort(); 710 } 711 712 switch (which) { 713 714 case LEAF_begemotSnmpdCommunityString: 715 return (string_get(value, c->string, -1)); 716 717 case LEAF_begemotSnmpdCommunityDescr: 718 return (string_get(value, c->descr, -1)); 719 } 720 abort(); 721 } 722 723 /* 724 * Module table. 725 */ 726 struct module_dep { 727 struct snmp_dependency dep; 728 u_char section[LM_SECTION_MAX + 1]; 729 u_char *path; 730 struct lmodule *m; 731 }; 732 733 static int 734 dep_modules(struct snmp_context *ctx, struct snmp_dependency *dep, 735 enum snmp_depop op) 736 { 737 struct module_dep *mdep = (struct module_dep *)(void *)dep; 738 739 switch (op) { 740 741 case SNMP_DEPOP_COMMIT: 742 if (mdep->path == NULL) { 743 /* unload - find the module */ 744 TAILQ_FOREACH(mdep->m, &lmodules, link) 745 if (strcmp(mdep->m->section, 746 mdep->section) == 0) 747 break; 748 if (mdep->m == NULL) 749 /* no such module - that's ok */ 750 return (SNMP_ERR_NOERROR); 751 752 /* handle unloading in the finalizer */ 753 return (SNMP_ERR_NOERROR); 754 } 755 /* load */ 756 if ((mdep->m = lm_load(mdep->path, mdep->section)) == NULL) { 757 /* could not load */ 758 return (SNMP_ERR_RES_UNAVAIL); 759 } 760 /* start in finalizer */ 761 return (SNMP_ERR_NOERROR); 762 763 case SNMP_DEPOP_ROLLBACK: 764 if (mdep->path == NULL) { 765 /* rollback unload - the finalizer takes care */ 766 return (SNMP_ERR_NOERROR); 767 } 768 /* rollback load */ 769 lm_unload(mdep->m); 770 return (SNMP_ERR_NOERROR); 771 772 case SNMP_DEPOP_FINISH: 773 if (mdep->path == NULL) { 774 if (mdep->m != NULL && ctx->code == SNMP_RET_OK) 775 lm_unload(mdep->m); 776 } else { 777 if (mdep->m != NULL && ctx->code == SNMP_RET_OK && 778 community != COMM_INITIALIZE) 779 lm_start(mdep->m); 780 free(mdep->path); 781 } 782 return (SNMP_ERR_NOERROR); 783 } 784 abort(); 785 } 786 787 int 788 op_modules(struct snmp_context *ctx, struct snmp_value *value, 789 u_int sub, u_int iidx, enum snmp_op op) 790 { 791 asn_subid_t which = value->var.subs[sub - 1]; 792 struct lmodule *m; 793 u_char *section, *ptr; 794 size_t seclen; 795 struct module_dep *mdep; 796 struct asn_oid idx; 797 798 switch (op) { 799 800 case SNMP_OP_GETNEXT: 801 if ((m = NEXT_OBJECT_OID(&lmodules, &value->var, sub)) == NULL) 802 return (SNMP_ERR_NOSUCHNAME); 803 index_append(&value->var, sub, &m->index); 804 break; 805 806 case SNMP_OP_GET: 807 if ((m = FIND_OBJECT_OID(&lmodules, &value->var, sub)) == NULL) 808 return (SNMP_ERR_NOSUCHNAME); 809 break; 810 811 case SNMP_OP_SET: 812 m = FIND_OBJECT_OID(&lmodules, &value->var, sub); 813 if (which != LEAF_begemotSnmpdModulePath) { 814 if (m == NULL) 815 return (SNMP_ERR_NO_CREATION); 816 return (SNMP_ERR_NOT_WRITEABLE); 817 } 818 819 /* the errors in the next few statements can only happen when 820 * m is NULL, hence the NO_CREATION error. */ 821 if (index_decode(&value->var, sub, iidx, 822 §ion, &seclen)) 823 return (SNMP_ERR_NO_CREATION); 824 825 /* check the section name */ 826 if (seclen > LM_SECTION_MAX || seclen == 0) { 827 free(section); 828 return (SNMP_ERR_NO_CREATION); 829 } 830 for (ptr = section; ptr < section + seclen; ptr++) 831 if (!isascii(*ptr) || !isalnum(*ptr)) { 832 free(section); 833 return (SNMP_ERR_NO_CREATION); 834 } 835 if (!isalpha(section[0])) { 836 free(section); 837 return (SNMP_ERR_NO_CREATION); 838 } 839 840 /* check the path */ 841 for (ptr = value->v.octetstring.octets; 842 ptr < value->v.octetstring.octets + value->v.octetstring.len; 843 ptr++) { 844 if (*ptr == '\0') { 845 free(section); 846 return (SNMP_ERR_WRONG_VALUE); 847 } 848 } 849 850 if (m == NULL) { 851 if (value->v.octetstring.len == 0) { 852 free(section); 853 return (SNMP_ERR_INCONS_VALUE); 854 } 855 } else { 856 if (value->v.octetstring.len != 0) { 857 free(section); 858 return (SNMP_ERR_INCONS_VALUE); 859 } 860 } 861 862 asn_slice_oid(&idx, &value->var, sub, value->var.len); 863 864 /* so far, so good */ 865 mdep = (struct module_dep *)(void *)snmp_dep_lookup(ctx, 866 &oid_begemotSnmpdModuleTable, &idx, 867 sizeof(*mdep), dep_modules); 868 if (mdep == NULL) { 869 free(section); 870 return (SNMP_ERR_RES_UNAVAIL); 871 } 872 873 if (mdep->section[0] != '\0') { 874 /* two writes to the same entry - bad */ 875 free(section); 876 return (SNMP_ERR_INCONS_VALUE); 877 } 878 879 strncpy(mdep->section, section, seclen); 880 mdep->section[seclen] = '\0'; 881 free(section); 882 883 if (value->v.octetstring.len == 0) 884 mdep->path = NULL; 885 else { 886 if ((mdep->path = malloc(value->v.octetstring.len + 1)) == NULL) 887 return (SNMP_ERR_RES_UNAVAIL); 888 strncpy(mdep->path, value->v.octetstring.octets, 889 value->v.octetstring.len); 890 mdep->path[value->v.octetstring.len] = '\0'; 891 } 892 ctx->scratch->ptr1 = mdep; 893 return (SNMP_ERR_NOERROR); 894 895 case SNMP_OP_ROLLBACK: 896 case SNMP_OP_COMMIT: 897 return (SNMP_ERR_NOERROR); 898 899 default: 900 abort(); 901 } 902 903 switch (which) { 904 905 case LEAF_begemotSnmpdModulePath: 906 return (string_get(value, m->path, -1)); 907 908 case LEAF_begemotSnmpdModuleComment: 909 return (string_get(value, m->config->comment, -1)); 910 } 911 abort(); 912 } 913 914 int 915 op_snmp_set(struct snmp_context *ctx __unused, struct snmp_value *value, 916 u_int sub, u_int iidx __unused, enum snmp_op op) 917 { 918 switch (op) { 919 920 case SNMP_OP_GETNEXT: 921 abort(); 922 923 case SNMP_OP_GET: 924 switch (value->var.subs[sub - 1]) { 925 926 case LEAF_snmpSetSerialNo: 927 value->v.integer = snmp_serial_no; 928 break; 929 930 default: 931 abort(); 932 } 933 return (SNMP_ERR_NOERROR); 934 935 case SNMP_OP_SET: 936 switch (value->var.subs[sub - 1]) { 937 938 case LEAF_snmpSetSerialNo: 939 if (value->v.integer != snmp_serial_no) 940 return (SNMP_ERR_INCONS_VALUE); 941 break; 942 943 default: 944 abort(); 945 } 946 return (SNMP_ERR_NOERROR); 947 948 case SNMP_OP_ROLLBACK: 949 return (SNMP_ERR_NOERROR); 950 951 case SNMP_OP_COMMIT: 952 if (snmp_serial_no++ == 2147483647) 953 snmp_serial_no = 0; 954 return (SNMP_ERR_NOERROR); 955 } 956 abort(); 957 } 958 959 /* 960 * Transport table 961 */ 962 int 963 op_transport_table(struct snmp_context *ctx __unused, struct snmp_value *value, 964 u_int sub, u_int iidx, enum snmp_op op) 965 { 966 asn_subid_t which = value->var.subs[sub - 1]; 967 struct transport *t; 968 u_char *tname, *ptr; 969 size_t tnamelen; 970 971 switch (op) { 972 973 case SNMP_OP_GETNEXT: 974 if ((t = NEXT_OBJECT_OID(&transport_list, &value->var, sub)) 975 == NULL) 976 return (SNMP_ERR_NOSUCHNAME); 977 index_append(&value->var, sub, &t->index); 978 break; 979 980 case SNMP_OP_GET: 981 if ((t = FIND_OBJECT_OID(&transport_list, &value->var, sub)) 982 == NULL) 983 return (SNMP_ERR_NOSUCHNAME); 984 break; 985 986 case SNMP_OP_SET: 987 t = FIND_OBJECT_OID(&transport_list, &value->var, sub); 988 if (which != LEAF_begemotSnmpdTransportStatus) { 989 if (t == NULL) 990 return (SNMP_ERR_NO_CREATION); 991 return (SNMP_ERR_NOT_WRITEABLE); 992 } 993 994 /* the errors in the next few statements can only happen when 995 * t is NULL, hence the NO_CREATION error. */ 996 if (index_decode(&value->var, sub, iidx, 997 &tname, &tnamelen)) 998 return (SNMP_ERR_NO_CREATION); 999 1000 /* check the section name */ 1001 if (tnamelen >= TRANS_NAMELEN || tnamelen == 0) { 1002 free(tname); 1003 return (SNMP_ERR_NO_CREATION); 1004 } 1005 for (ptr = tname; ptr < tname + tnamelen; ptr++) { 1006 if (!isascii(*ptr) || !isalnum(*ptr)) { 1007 free(tname); 1008 return (SNMP_ERR_NO_CREATION); 1009 } 1010 } 1011 1012 /* for now */ 1013 return (SNMP_ERR_NOT_WRITEABLE); 1014 1015 case SNMP_OP_ROLLBACK: 1016 case SNMP_OP_COMMIT: 1017 return (SNMP_ERR_NOERROR); 1018 default: 1019 abort(); 1020 } 1021 1022 switch (which) { 1023 1024 case LEAF_begemotSnmpdTransportStatus: 1025 value->v.integer = 1; 1026 break; 1027 1028 case LEAF_begemotSnmpdTransportOid: 1029 memcpy(&value->v.oid, &t->vtab->id, sizeof(t->vtab->id)); 1030 break; 1031 } 1032 return (SNMP_ERR_NOERROR); 1033 } 1034