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