2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
5 * Copyright (c) 2004-2006
9 * Author: Harti Brandt <harti@freebsd.org>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $Begemot: action.c 517 2006-10-31 08:52:04Z brandt_h $
34 * Variable access for SNMPd
36 #include <sys/types.h>
37 #include <sys/queue.h>
38 #include <sys/sysctl.h>
40 #include <sys/utsname.h>
54 static const struct asn_oid
55 oid_begemotSnmpdModuleTable = OIDX_begemotSnmpdModuleTable;
58 static const struct asn_oid
59 oid_freeBSDVersion = OIDX_freeBSDVersion;
63 * Get a string value from the KERN sysctl subtree.
66 act_getkernstring(int id)
74 if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0)
76 if ((string = malloc(len)) == NULL)
78 if (sysctl(mib, 2, string, &len, NULL, 0) != 0) {
86 * Get an integer value from the KERN sysctl subtree.
89 act_getkernint(int id)
99 if (sysctl(mib, 2, &value, &len, NULL, 0) != 0)
102 if ((string = malloc(20)) == NULL)
104 sprintf(string, "%lu", value);
109 * Initialize global variables of the system group.
122 if (uname(&uts) == -1)
125 if ((systemg.name = strdup(uts.nodename)) == NULL)
128 if ((hostid = act_getkernint(KERN_HOSTID)) == NULL)
131 len = strlen(uts.nodename) + 1;
132 len += strlen(hostid) + 1;
133 len += strlen(uts.sysname) + 1;
134 len += strlen(uts.release) + 1;
136 if ((systemg.descr = malloc(len)) == NULL) {
140 sprintf(systemg.descr, "%s %s %s %s", uts.nodename, hostid, uts.sysname,
145 * Construct a FreeBSD oid
147 systemg.object_id = oid_freeBSDVersion;
149 while ((p = strsep(&rel, ".")) != NULL &&
150 systemg.object_id.len < ASN_MAXOIDLEN) {
151 systemg.object_id.subs[systemg.object_id.len] = 0;
153 num = strtoul(p, &end, 10);
156 systemg.object_id.subs[systemg.object_id.len] = num;
158 systemg.object_id.len++;
168 * Initialize global variables of the snmpEngine group.
171 init_snmpd_engine(void)
175 snmpd_engine.engine_boots = 1;
176 snmpd_engine.engine_time = 1;
177 snmpd_engine.max_msg_size = 1500; /* XXX */
179 snmpd_engine.engine_id[0] = ((OID_freeBSD & 0xff000000) >> 24) | 0x80;
180 snmpd_engine.engine_id[1] = (OID_freeBSD & 0xff0000) >> 16;
181 snmpd_engine.engine_id[2] = (OID_freeBSD & 0xff00) >> 8;
182 snmpd_engine.engine_id[3] = OID_freeBSD & 0xff;
183 snmpd_engine.engine_id[4] = 128;
184 snmpd_engine.engine_len = 5;
186 if ((hostid = act_getkernint(KERN_HOSTID)) == NULL)
189 if (strlen(hostid) > SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len) {
190 memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len,
191 hostid, SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len);
192 snmpd_engine.engine_len = SNMP_ENGINE_ID_SIZ;
194 memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len,
195 hostid, strlen(hostid));
196 snmpd_engine.engine_len += strlen(hostid);
205 set_snmpd_engine(void)
209 uint8_t *cptr, engine[2 * SNMP_ENGINE_ID_SIZ + 2];
210 uint8_t myengine[2 * SNMP_ENGINE_ID_SIZ + 2];
212 if (engine_file[0] == '\0')
216 for (i = 0; i < snmpd_engine.engine_len; i++)
217 cptr += sprintf(cptr, "%.2x", snmpd_engine.engine_id[i]);
221 if ((fp = fopen(engine_file, "r+")) != NULL) {
222 if (fgets(engine, sizeof(engine) - 1, fp) == NULL ||
223 fscanf(fp, "%u", &snmpd_engine.engine_boots) <= 0) {
229 if (strcmp(myengine, engine) != 0)
230 snmpd_engine.engine_boots = 1;
232 snmpd_engine.engine_boots++;
233 } else if (errno != ENOENT)
237 if ((fp = fopen(engine_file, "w+")) == NULL)
239 fprintf(fp, "%s%u\n", myengine, snmpd_engine.engine_boots);
245 /*************************************************************
250 op_system_group(struct snmp_context *ctx, struct snmp_value *value,
251 u_int sub, u_int iidx __unused, enum snmp_op op)
253 asn_subid_t which = value->var.subs[sub - 1];
257 case SNMP_OP_GETNEXT:
267 if (community != COMM_INITIALIZE)
268 return (SNMP_ERR_NOT_WRITEABLE);
269 return (string_save(value, ctx, -1, &systemg.descr));
271 case LEAF_sysObjectId:
272 if (community != COMM_INITIALIZE)
273 return (SNMP_ERR_NOT_WRITEABLE);
274 return (oid_save(value, ctx, &systemg.object_id));
276 case LEAF_sysContact:
277 return (string_save(value, ctx, -1, &systemg.contact));
280 return (string_save(value, ctx, -1, &systemg.name));
282 case LEAF_sysLocation:
283 return (string_save(value, ctx, -1, &systemg.location));
285 return (SNMP_ERR_NO_CREATION);
287 case SNMP_OP_ROLLBACK:
291 string_rollback(ctx, &systemg.descr);
292 return (SNMP_ERR_NOERROR);
293 case LEAF_sysObjectId:
294 oid_rollback(ctx, &systemg.object_id);
295 return (SNMP_ERR_NOERROR);
296 case LEAF_sysContact:
297 string_rollback(ctx, &systemg.contact);
298 return (SNMP_ERR_NOERROR);
300 string_rollback(ctx, &systemg.name);
301 return (SNMP_ERR_NOERROR);
302 case LEAF_sysLocation:
303 string_rollback(ctx, &systemg.location);
304 return (SNMP_ERR_NOERROR);
313 return (SNMP_ERR_NOERROR);
314 case LEAF_sysObjectId:
316 return (SNMP_ERR_NOERROR);
317 case LEAF_sysContact:
319 return (SNMP_ERR_NOERROR);
322 return (SNMP_ERR_NOERROR);
323 case LEAF_sysLocation:
325 return (SNMP_ERR_NOERROR);
336 return (string_get(value, systemg.descr, -1));
337 case LEAF_sysObjectId:
338 return (oid_get(value, &systemg.object_id));
340 value->v.uint32 = get_ticks() - start_tick;
342 case LEAF_sysContact:
343 return (string_get(value, systemg.contact, -1));
345 return (string_get(value, systemg.name, -1));
346 case LEAF_sysLocation:
347 return (string_get(value, systemg.location, -1));
348 case LEAF_sysServices:
349 value->v.integer = systemg.services;
351 case LEAF_sysORLastChange:
352 value->v.uint32 = systemg.or_last_change;
355 return (SNMP_ERR_NOERROR);
358 /*************************************************************
363 op_debug(struct snmp_context *ctx, struct snmp_value *value, u_int sub,
364 u_int iidx __unused, enum snmp_op op)
366 asn_subid_t which = value->var.subs[sub - 1];
370 case SNMP_OP_GETNEXT:
376 case LEAF_begemotSnmpdDebugDumpPdus:
377 value->v.integer = TRUTH_MK(debug.dump_pdus);
380 case LEAF_begemotSnmpdDebugSnmpTrace:
381 value->v.uint32 = snmp_trace;
384 case LEAF_begemotSnmpdDebugSyslogPri:
385 value->v.integer = debug.logpri;
388 return (SNMP_ERR_NOERROR);
393 case LEAF_begemotSnmpdDebugDumpPdus:
394 if (!TRUTH_OK(value->v.integer))
395 return (SNMP_ERR_WRONG_VALUE);
396 ctx->scratch->int1 = debug.dump_pdus;
397 debug.dump_pdus = TRUTH_GET(value->v.integer);
398 return (SNMP_ERR_NOERROR);
400 case LEAF_begemotSnmpdDebugSnmpTrace:
401 ctx->scratch->int1 = snmp_trace;
402 snmp_trace = value->v.uint32;
403 return (SNMP_ERR_NOERROR);
405 case LEAF_begemotSnmpdDebugSyslogPri:
406 if (value->v.integer < 0 || value->v.integer > 8)
407 return (SNMP_ERR_WRONG_VALUE);
408 ctx->scratch->int1 = debug.logpri;
409 debug.logpri = (u_int)value->v.integer;
410 return (SNMP_ERR_NOERROR);
412 return (SNMP_ERR_NO_CREATION);
414 case SNMP_OP_ROLLBACK:
417 case LEAF_begemotSnmpdDebugDumpPdus:
418 debug.dump_pdus = ctx->scratch->int1;
419 return (SNMP_ERR_NOERROR);
421 case LEAF_begemotSnmpdDebugSnmpTrace:
422 snmp_trace = ctx->scratch->int1;
423 return (SNMP_ERR_NOERROR);
425 case LEAF_begemotSnmpdDebugSyslogPri:
426 debug.logpri = ctx->scratch->int1;
427 return (SNMP_ERR_NOERROR);
434 case LEAF_begemotSnmpdDebugDumpPdus:
435 case LEAF_begemotSnmpdDebugSnmpTrace:
436 return (SNMP_ERR_NOERROR);
438 case LEAF_begemotSnmpdDebugSyslogPri:
439 if (debug.logpri == 0)
442 setlogmask(LOG_UPTO(debug.logpri - 1));
443 return (SNMP_ERR_NOERROR);
450 /*************************************************************
455 op_or_table(struct snmp_context *ctx __unused, struct snmp_value *value,
456 u_int sub, u_int iidx __unused, enum snmp_op op)
458 struct objres *objres;
462 case SNMP_OP_GETNEXT:
463 if ((objres = NEXT_OBJECT_INT(&objres_list, &value->var, sub))
465 return (SNMP_ERR_NOSUCHNAME);
466 value->var.subs[sub] = objres->index;
467 value->var.len = sub + 1;
471 if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub))
473 return (SNMP_ERR_NOSUCHNAME);
477 if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub))
479 return (SNMP_ERR_NO_CREATION);
480 return (SNMP_ERR_NOT_WRITEABLE);
482 case SNMP_OP_ROLLBACK:
489 * Come here for GET, GETNEXT.
491 switch (value->var.subs[sub - 1]) {
494 value->v.oid = objres->oid;
497 case LEAF_sysORDescr:
498 return (string_get(value, objres->descr, -1));
500 case LEAF_sysORUpTime:
501 value->v.uint32 = objres->uptime;
504 return (SNMP_ERR_NOERROR);
507 /*************************************************************
512 op_snmp(struct snmp_context *ctx, struct snmp_value *value,
513 u_int sub, u_int iidx __unused, enum snmp_op op)
517 case SNMP_OP_GETNEXT:
521 switch (value->var.subs[sub - 1]) {
523 case LEAF_snmpInPkts:
524 value->v.uint32 = snmpd_stats.inPkts;
527 case LEAF_snmpInBadVersions:
528 value->v.uint32 = snmpd_stats.inBadVersions;
531 case LEAF_snmpInBadCommunityNames:
532 value->v.uint32 = snmpd_stats.inBadCommunityNames;
535 case LEAF_snmpInBadCommunityUses:
536 value->v.uint32 = snmpd_stats.inBadCommunityUses;
539 case LEAF_snmpInASNParseErrs:
540 value->v.uint32 = snmpd_stats.inASNParseErrs;
543 case LEAF_snmpEnableAuthenTraps:
544 value->v.integer = TRUTH_MK(snmpd.auth_traps);
547 case LEAF_snmpSilentDrops:
548 value->v.uint32 = snmpd_stats.silentDrops;
551 case LEAF_snmpProxyDrops:
552 value->v.uint32 = snmpd_stats.proxyDrops;
556 return (SNMP_ERR_NOSUCHNAME);
559 return (SNMP_ERR_NOERROR);
562 switch (value->var.subs[sub - 1]) {
563 case LEAF_snmpEnableAuthenTraps:
564 if (!TRUTH_OK(value->v.integer))
565 return (SNMP_ERR_WRONG_VALUE);
566 ctx->scratch->int1 = value->v.integer;
567 snmpd.auth_traps = TRUTH_GET(value->v.integer);
568 return (SNMP_ERR_NOERROR);
572 case SNMP_OP_ROLLBACK:
573 switch (value->var.subs[sub - 1]) {
574 case LEAF_snmpEnableAuthenTraps:
575 snmpd.auth_traps = ctx->scratch->int1;
576 return (SNMP_ERR_NOERROR);
581 switch (value->var.subs[sub - 1]) {
582 case LEAF_snmpEnableAuthenTraps:
583 return (SNMP_ERR_NOERROR);
590 /*************************************************************
592 * SNMPd statistics group
595 op_snmpd_stats(struct snmp_context *ctx __unused, struct snmp_value *value,
596 u_int sub, u_int iidx __unused, enum snmp_op op)
601 switch (value->var.subs[sub - 1]) {
603 case LEAF_begemotSnmpdStatsNoRxBufs:
604 value->v.uint32 = snmpd_stats.noRxbuf;
607 case LEAF_begemotSnmpdStatsNoTxBufs:
608 value->v.uint32 = snmpd_stats.noTxbuf;
611 case LEAF_begemotSnmpdStatsInTooLongPkts:
612 value->v.uint32 = snmpd_stats.inTooLong;
615 case LEAF_begemotSnmpdStatsInBadPduTypes:
616 value->v.uint32 = snmpd_stats.inBadPduTypes;
620 return (SNMP_ERR_NOSUCHNAME);
622 return (SNMP_ERR_NOERROR);
625 case SNMP_OP_ROLLBACK:
627 case SNMP_OP_GETNEXT:
634 * SNMPd configuration scalars
637 op_snmpd_config(struct snmp_context *ctx, struct snmp_value *value,
638 u_int sub, u_int iidx __unused, enum snmp_op op)
640 asn_subid_t which = value->var.subs[sub - 1];
644 case SNMP_OP_GETNEXT:
650 case LEAF_begemotSnmpdTransmitBuffer:
651 value->v.integer = snmpd.txbuf;
653 case LEAF_begemotSnmpdReceiveBuffer:
654 value->v.integer = snmpd.rxbuf;
656 case LEAF_begemotSnmpdCommunityDisable:
657 value->v.integer = TRUTH_MK(snmpd.comm_dis);
659 case LEAF_begemotSnmpdTrap1Addr:
660 return (ip_get(value, snmpd.trap1addr));
661 case LEAF_begemotSnmpdVersionEnable:
662 value->v.uint32 = snmpd.version_enable;
665 return (SNMP_ERR_NOSUCHNAME);
667 return (SNMP_ERR_NOERROR);
672 case LEAF_begemotSnmpdTransmitBuffer:
673 ctx->scratch->int1 = snmpd.txbuf;
674 if (value->v.integer < 484 ||
675 value->v.integer > 65535)
676 return (SNMP_ERR_WRONG_VALUE);
677 snmpd.txbuf = value->v.integer;
678 return (SNMP_ERR_NOERROR);
680 case LEAF_begemotSnmpdReceiveBuffer:
681 ctx->scratch->int1 = snmpd.rxbuf;
682 if (value->v.integer < 484 ||
683 value->v.integer > 65535)
684 return (SNMP_ERR_WRONG_VALUE);
685 snmpd.rxbuf = value->v.integer;
686 return (SNMP_ERR_NOERROR);
688 case LEAF_begemotSnmpdCommunityDisable:
689 ctx->scratch->int1 = snmpd.comm_dis;
690 if (!TRUTH_OK(value->v.integer))
691 return (SNMP_ERR_WRONG_VALUE);
692 if (TRUTH_GET(value->v.integer)) {
696 return (SNMP_ERR_WRONG_VALUE);
698 return (SNMP_ERR_NOERROR);
700 case LEAF_begemotSnmpdTrap1Addr:
701 return (ip_save(value, ctx, snmpd.trap1addr));
703 case LEAF_begemotSnmpdVersionEnable:
704 if (community != COMM_INITIALIZE)
705 return (SNMP_ERR_NOT_WRITEABLE);
706 ctx->scratch->int1 = snmpd.version_enable;
707 if (value->v.uint32 == 0 ||
708 (value->v.uint32 & ~VERS_ENABLE_ALL))
709 return (SNMP_ERR_WRONG_VALUE);
710 snmpd.version_enable = value->v.uint32;
711 return (SNMP_ERR_NOERROR);
715 case SNMP_OP_ROLLBACK:
718 case LEAF_begemotSnmpdTransmitBuffer:
719 snmpd.rxbuf = ctx->scratch->int1;
720 return (SNMP_ERR_NOERROR);
721 case LEAF_begemotSnmpdReceiveBuffer:
722 snmpd.txbuf = ctx->scratch->int1;
723 return (SNMP_ERR_NOERROR);
724 case LEAF_begemotSnmpdCommunityDisable:
725 snmpd.comm_dis = ctx->scratch->int1;
726 return (SNMP_ERR_NOERROR);
727 case LEAF_begemotSnmpdTrap1Addr:
728 ip_rollback(ctx, snmpd.trap1addr);
729 return (SNMP_ERR_NOERROR);
730 case LEAF_begemotSnmpdVersionEnable:
731 snmpd.version_enable = ctx->scratch->int1;
732 return (SNMP_ERR_NOERROR);
739 case LEAF_begemotSnmpdTransmitBuffer:
740 case LEAF_begemotSnmpdReceiveBuffer:
741 case LEAF_begemotSnmpdCommunityDisable:
742 return (SNMP_ERR_NOERROR);
743 case LEAF_begemotSnmpdTrap1Addr:
745 return (SNMP_ERR_NOERROR);
746 case LEAF_begemotSnmpdVersionEnable:
747 return (SNMP_ERR_NOERROR);
755 * The community table
758 op_community(struct snmp_context *ctx, struct snmp_value *value,
759 u_int sub, u_int iidx __unused, enum snmp_op op)
761 asn_subid_t which = value->var.subs[sub - 1];
766 case SNMP_OP_GETNEXT:
767 if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
768 (c = NEXT_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
769 return (SNMP_ERR_NOSUCHNAME);
770 index_append(&value->var, sub, &c->index);
774 if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
775 (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
776 return (SNMP_ERR_NOSUCHNAME);
780 if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
781 (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
782 return (SNMP_ERR_NO_CREATION);
783 if (which != LEAF_begemotSnmpdCommunityString)
784 return (SNMP_ERR_NOT_WRITEABLE);
785 return (string_save(value, ctx, -1, &c->string));
787 case SNMP_OP_ROLLBACK:
788 if (which == LEAF_begemotSnmpdCommunityString) {
789 if ((c = FIND_OBJECT_OID(&community_list, &value->var,
793 string_rollback(ctx, &c->string);
794 return (SNMP_ERR_NOERROR);
799 if (which == LEAF_begemotSnmpdCommunityString) {
800 if ((c = FIND_OBJECT_OID(&community_list, &value->var,
805 return (SNMP_ERR_NOERROR);
815 case LEAF_begemotSnmpdCommunityString:
816 return (string_get(value, c->string, -1));
818 case LEAF_begemotSnmpdCommunityDescr:
819 return (string_get(value, c->descr, -1));
828 struct snmp_dependency dep;
829 u_char section[LM_SECTION_MAX + 1];
835 dep_modules(struct snmp_context *ctx, struct snmp_dependency *dep,
838 struct module_dep *mdep = (struct module_dep *)(void *)dep;
842 case SNMP_DEPOP_COMMIT:
843 if (mdep->path == NULL) {
844 /* unload - find the module */
845 TAILQ_FOREACH(mdep->m, &lmodules, link)
846 if (strcmp(mdep->m->section,
850 /* no such module - that's ok */
851 return (SNMP_ERR_NOERROR);
853 /* handle unloading in the finalizer */
854 return (SNMP_ERR_NOERROR);
857 if ((mdep->m = lm_load(mdep->path, mdep->section)) == NULL) {
859 return (SNMP_ERR_RES_UNAVAIL);
861 /* start in finalizer */
862 return (SNMP_ERR_NOERROR);
864 case SNMP_DEPOP_ROLLBACK:
865 if (mdep->path == NULL) {
866 /* rollback unload - the finalizer takes care */
867 return (SNMP_ERR_NOERROR);
871 return (SNMP_ERR_NOERROR);
873 case SNMP_DEPOP_FINISH:
874 if (mdep->path == NULL) {
875 if (mdep->m != NULL && ctx->code == SNMP_RET_OK)
878 if (mdep->m != NULL && ctx->code == SNMP_RET_OK &&
879 community != COMM_INITIALIZE)
883 return (SNMP_ERR_NOERROR);
889 op_modules(struct snmp_context *ctx, struct snmp_value *value,
890 u_int sub, u_int iidx, enum snmp_op op)
892 asn_subid_t which = value->var.subs[sub - 1];
894 u_char *section, *ptr;
896 struct module_dep *mdep;
901 case SNMP_OP_GETNEXT:
902 if ((m = NEXT_OBJECT_OID(&lmodules, &value->var, sub)) == NULL)
903 return (SNMP_ERR_NOSUCHNAME);
904 index_append(&value->var, sub, &m->index);
908 if ((m = FIND_OBJECT_OID(&lmodules, &value->var, sub)) == NULL)
909 return (SNMP_ERR_NOSUCHNAME);
913 m = FIND_OBJECT_OID(&lmodules, &value->var, sub);
914 if (which != LEAF_begemotSnmpdModulePath) {
916 return (SNMP_ERR_NO_CREATION);
917 return (SNMP_ERR_NOT_WRITEABLE);
920 /* the errors in the next few statements can only happen when
921 * m is NULL, hence the NO_CREATION error. */
922 if (index_decode(&value->var, sub, iidx,
924 return (SNMP_ERR_NO_CREATION);
926 /* check the section name */
927 if (seclen > LM_SECTION_MAX || seclen == 0) {
929 return (SNMP_ERR_NO_CREATION);
931 for (ptr = section; ptr < section + seclen; ptr++)
932 if (!isascii(*ptr) || !isalnum(*ptr)) {
934 return (SNMP_ERR_NO_CREATION);
936 if (!isalpha(section[0])) {
938 return (SNMP_ERR_NO_CREATION);
942 for (ptr = value->v.octetstring.octets;
943 ptr < value->v.octetstring.octets + value->v.octetstring.len;
947 return (SNMP_ERR_WRONG_VALUE);
952 if (value->v.octetstring.len == 0) {
954 return (SNMP_ERR_INCONS_VALUE);
957 if (value->v.octetstring.len != 0) {
959 return (SNMP_ERR_INCONS_VALUE);
963 asn_slice_oid(&idx, &value->var, sub, value->var.len);
965 /* so far, so good */
966 mdep = (struct module_dep *)(void *)snmp_dep_lookup(ctx,
967 &oid_begemotSnmpdModuleTable, &idx,
968 sizeof(*mdep), dep_modules);
971 return (SNMP_ERR_RES_UNAVAIL);
974 if (mdep->section[0] != '\0') {
975 /* two writes to the same entry - bad */
977 return (SNMP_ERR_INCONS_VALUE);
980 strncpy(mdep->section, section, seclen);
981 mdep->section[seclen] = '\0';
984 if (value->v.octetstring.len == 0)
987 if ((mdep->path = malloc(value->v.octetstring.len + 1)) == NULL)
988 return (SNMP_ERR_RES_UNAVAIL);
989 strncpy(mdep->path, value->v.octetstring.octets,
990 value->v.octetstring.len);
991 mdep->path[value->v.octetstring.len] = '\0';
993 ctx->scratch->ptr1 = mdep;
994 return (SNMP_ERR_NOERROR);
996 case SNMP_OP_ROLLBACK:
998 return (SNMP_ERR_NOERROR);
1006 case LEAF_begemotSnmpdModulePath:
1007 return (string_get(value, m->path, -1));
1009 case LEAF_begemotSnmpdModuleComment:
1010 return (string_get(value, m->config->comment, -1));
1016 op_snmp_set(struct snmp_context *ctx __unused, struct snmp_value *value,
1017 u_int sub, u_int iidx __unused, enum snmp_op op)
1021 case SNMP_OP_GETNEXT:
1025 switch (value->var.subs[sub - 1]) {
1027 case LEAF_snmpSetSerialNo:
1028 value->v.integer = snmp_serial_no;
1034 return (SNMP_ERR_NOERROR);
1037 switch (value->var.subs[sub - 1]) {
1039 case LEAF_snmpSetSerialNo:
1040 if (value->v.integer != snmp_serial_no)
1041 return (SNMP_ERR_INCONS_VALUE);
1047 return (SNMP_ERR_NOERROR);
1049 case SNMP_OP_ROLLBACK:
1050 return (SNMP_ERR_NOERROR);
1052 case SNMP_OP_COMMIT:
1053 if (snmp_serial_no++ == 2147483647)
1055 return (SNMP_ERR_NOERROR);
1064 op_snmp_engine(struct snmp_context *ctx __unused, struct snmp_value *value,
1065 u_int sub, u_int iidx __unused, enum snmp_op op)
1067 asn_subid_t which = value->var.subs[sub - 1];
1070 case SNMP_OP_GETNEXT:
1077 if (community != COMM_INITIALIZE)
1078 return (SNMP_ERR_NOT_WRITEABLE);
1080 case LEAF_snmpEngineID:
1081 if (value->v.octetstring.len > SNMP_ENGINE_ID_SIZ)
1082 return (SNMP_ERR_WRONG_VALUE);
1083 ctx->scratch->ptr1 = malloc(snmpd_engine.engine_len);
1084 if (ctx->scratch->ptr1 == NULL)
1085 return (SNMP_ERR_GENERR);
1086 memcpy(ctx->scratch->ptr1, snmpd_engine.engine_id,
1087 snmpd_engine.engine_len);
1088 ctx->scratch->int1 = snmpd_engine.engine_len;
1089 snmpd_engine.engine_len = value->v.octetstring.len;
1090 memcpy(snmpd_engine.engine_id,
1091 value->v.octetstring.octets,
1092 value->v.octetstring.len);
1095 case LEAF_snmpEngineMaxMessageSize:
1096 ctx->scratch->int1 = snmpd_engine.max_msg_size;
1097 snmpd_engine.max_msg_size = value->v.integer;
1101 return (SNMP_ERR_NOT_WRITEABLE);
1103 return (SNMP_ERR_NOERROR);
1105 case SNMP_OP_ROLLBACK:
1107 case LEAF_snmpEngineID:
1108 snmpd_engine.engine_len = ctx->scratch->int1;
1109 memcpy(snmpd_engine.engine_id, ctx->scratch->ptr1,
1110 snmpd_engine.engine_len);
1111 free(ctx->scratch->ptr1);
1114 case LEAF_snmpEngineMaxMessageSize:
1115 snmpd_engine.max_msg_size = ctx->scratch->int1;
1121 return (SNMP_ERR_NOERROR);
1123 case SNMP_OP_COMMIT:
1124 if (which == LEAF_snmpEngineID) {
1125 if (set_snmpd_engine() < 0) {
1126 snmpd_engine.engine_len = ctx->scratch->int1;
1127 memcpy(snmpd_engine.engine_id,
1128 ctx->scratch->ptr1, ctx->scratch->int1);
1130 free(ctx->scratch->ptr1);
1132 return (SNMP_ERR_NOERROR);
1137 case LEAF_snmpEngineID:
1138 return (string_get(value, snmpd_engine.engine_id,
1139 snmpd_engine.engine_len));
1140 case LEAF_snmpEngineBoots:
1141 value->v.integer = snmpd_engine.engine_boots;
1143 case LEAF_snmpEngineTime:
1144 snmpd_engine.engine_time = (get_ticks() - start_tick) / 100ULL;
1145 value->v.integer = snmpd_engine.engine_time;
1147 case LEAF_snmpEngineMaxMessageSize:
1148 value->v.integer = snmpd_engine.max_msg_size;
1151 return (SNMP_ERR_NOSUCHNAME);
1154 return (SNMP_ERR_NOERROR);
1161 op_transport_table(struct snmp_context *ctx __unused, struct snmp_value *value,
1162 u_int sub, u_int iidx, enum snmp_op op)
1164 asn_subid_t which = value->var.subs[sub - 1];
1165 struct transport *t;
1166 u_char *tname, *ptr;
1171 case SNMP_OP_GETNEXT:
1172 if ((t = NEXT_OBJECT_OID(&transport_list, &value->var, sub))
1174 return (SNMP_ERR_NOSUCHNAME);
1175 index_append(&value->var, sub, &t->index);
1179 if ((t = FIND_OBJECT_OID(&transport_list, &value->var, sub))
1181 return (SNMP_ERR_NOSUCHNAME);
1185 t = FIND_OBJECT_OID(&transport_list, &value->var, sub);
1186 if (which != LEAF_begemotSnmpdTransportStatus) {
1188 return (SNMP_ERR_NO_CREATION);
1189 return (SNMP_ERR_NOT_WRITEABLE);
1192 /* the errors in the next few statements can only happen when
1193 * t is NULL, hence the NO_CREATION error. */
1194 if (index_decode(&value->var, sub, iidx,
1196 return (SNMP_ERR_NO_CREATION);
1198 /* check the section name */
1199 if (tnamelen >= TRANS_NAMELEN || tnamelen == 0) {
1201 return (SNMP_ERR_NO_CREATION);
1203 for (ptr = tname; ptr < tname + tnamelen; ptr++) {
1204 if (!isascii(*ptr) || !isalnum(*ptr)) {
1206 return (SNMP_ERR_NO_CREATION);
1211 return (SNMP_ERR_NOT_WRITEABLE);
1213 case SNMP_OP_ROLLBACK:
1214 case SNMP_OP_COMMIT:
1215 return (SNMP_ERR_NOERROR);
1222 case LEAF_begemotSnmpdTransportStatus:
1223 value->v.integer = 1;
1226 case LEAF_begemotSnmpdTransportOid:
1227 memcpy(&value->v.oid, &t->vtab->id, sizeof(t->vtab->id));
1230 return (SNMP_ERR_NOERROR);