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>
55 static const struct asn_oid
56 oid_begemotSnmpdModuleTable = OIDX_begemotSnmpdModuleTable;
59 static const struct asn_oid
60 oid_freeBSDVersion = OIDX_freeBSDVersion;
64 * Get an integer value from the KERN sysctl subtree.
67 act_getkernint(int id)
77 if (sysctl(mib, 2, &value, &len, NULL, 0) != 0)
80 if ((string = malloc(20)) == NULL)
82 sprintf(string, "%lu", value);
87 * Initialize global variables of the system group.
100 if (uname(&uts) == -1)
103 if ((systemg.name = strdup(uts.nodename)) == NULL)
106 if ((hostid = act_getkernint(KERN_HOSTID)) == NULL)
109 len = strlen(uts.nodename) + 1;
110 len += strlen(hostid) + 1;
111 len += strlen(uts.sysname) + 1;
112 len += strlen(uts.release) + 1;
114 if ((systemg.descr = malloc(len)) == NULL) {
118 sprintf(systemg.descr, "%s %s %s %s", uts.nodename, hostid, uts.sysname,
123 * Construct a FreeBSD oid
125 systemg.object_id = oid_freeBSDVersion;
127 while ((p = strsep(&rel, ".")) != NULL &&
128 systemg.object_id.len < ASN_MAXOIDLEN) {
129 systemg.object_id.subs[systemg.object_id.len] = 0;
131 num = strtoul(p, &end, 10);
134 systemg.object_id.subs[systemg.object_id.len] = num;
136 systemg.object_id.len++;
146 * Initialize global variables of the snmpEngine group.
149 init_snmpd_engine(void)
153 snmpd_engine.engine_boots = 1;
154 snmpd_engine.engine_time = 1;
155 snmpd_engine.max_msg_size = 1500; /* XXX */
157 snmpd_engine.engine_id[0] = ((OID_freeBSD & 0xff000000) >> 24) | 0x80;
158 snmpd_engine.engine_id[1] = (OID_freeBSD & 0xff0000) >> 16;
159 snmpd_engine.engine_id[2] = (OID_freeBSD & 0xff00) >> 8;
160 snmpd_engine.engine_id[3] = OID_freeBSD & 0xff;
161 snmpd_engine.engine_id[4] = 128;
162 snmpd_engine.engine_len = 5;
164 if ((hostid = act_getkernint(KERN_HOSTID)) == NULL)
167 if (strlen(hostid) > SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len) {
168 memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len,
169 hostid, SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len);
170 snmpd_engine.engine_len = SNMP_ENGINE_ID_SIZ;
172 memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len,
173 hostid, strlen(hostid));
174 snmpd_engine.engine_len += strlen(hostid);
183 set_snmpd_engine(void)
187 uint8_t *cptr, engine[2 * SNMP_ENGINE_ID_SIZ + 2];
188 uint8_t myengine[2 * SNMP_ENGINE_ID_SIZ + 2];
190 if (engine_file[0] == '\0')
194 for (i = 0; i < snmpd_engine.engine_len; i++)
195 cptr += sprintf(cptr, "%.2x", snmpd_engine.engine_id[i]);
199 if ((fp = fopen(engine_file, "r+")) != NULL) {
200 if (fgets(engine, sizeof(engine) - 1, fp) == NULL ||
201 fscanf(fp, "%u", &snmpd_engine.engine_boots) <= 0) {
207 if (strcmp(myengine, engine) != 0)
208 snmpd_engine.engine_boots = 1;
210 snmpd_engine.engine_boots++;
211 } else if (errno != ENOENT)
215 if ((fp = fopen(engine_file, "w+")) == NULL)
217 fprintf(fp, "%s%u\n", myengine, snmpd_engine.engine_boots);
224 update_snmpd_engine_time(void)
228 etime = (get_ticks() - start_tick) / 100ULL;
229 if (etime < INT32_MAX)
230 snmpd_engine.engine_time = etime;
232 start_tick = get_ticks();
233 (void)set_snmpd_engine();
234 snmpd_engine.engine_time = start_tick;
238 /*************************************************************
243 op_system_group(struct snmp_context *ctx, struct snmp_value *value,
244 u_int sub, u_int iidx __unused, enum snmp_op op)
246 asn_subid_t which = value->var.subs[sub - 1];
250 case SNMP_OP_GETNEXT:
260 if (community != COMM_INITIALIZE)
261 return (SNMP_ERR_NOT_WRITEABLE);
262 return (string_save(value, ctx, -1, &systemg.descr));
264 case LEAF_sysObjectId:
265 if (community != COMM_INITIALIZE)
266 return (SNMP_ERR_NOT_WRITEABLE);
267 return (oid_save(value, ctx, &systemg.object_id));
269 case LEAF_sysContact:
270 return (string_save(value, ctx, -1, &systemg.contact));
273 return (string_save(value, ctx, -1, &systemg.name));
275 case LEAF_sysLocation:
276 return (string_save(value, ctx, -1, &systemg.location));
278 return (SNMP_ERR_NO_CREATION);
280 case SNMP_OP_ROLLBACK:
284 string_rollback(ctx, &systemg.descr);
285 return (SNMP_ERR_NOERROR);
286 case LEAF_sysObjectId:
287 oid_rollback(ctx, &systemg.object_id);
288 return (SNMP_ERR_NOERROR);
289 case LEAF_sysContact:
290 string_rollback(ctx, &systemg.contact);
291 return (SNMP_ERR_NOERROR);
293 string_rollback(ctx, &systemg.name);
294 return (SNMP_ERR_NOERROR);
295 case LEAF_sysLocation:
296 string_rollback(ctx, &systemg.location);
297 return (SNMP_ERR_NOERROR);
306 return (SNMP_ERR_NOERROR);
307 case LEAF_sysObjectId:
309 return (SNMP_ERR_NOERROR);
310 case LEAF_sysContact:
312 return (SNMP_ERR_NOERROR);
315 return (SNMP_ERR_NOERROR);
316 case LEAF_sysLocation:
318 return (SNMP_ERR_NOERROR);
329 return (string_get(value, systemg.descr, -1));
330 case LEAF_sysObjectId:
331 return (oid_get(value, &systemg.object_id));
333 value->v.uint32 = get_ticks() - start_tick;
335 case LEAF_sysContact:
336 return (string_get(value, systemg.contact, -1));
338 return (string_get(value, systemg.name, -1));
339 case LEAF_sysLocation:
340 return (string_get(value, systemg.location, -1));
341 case LEAF_sysServices:
342 value->v.integer = systemg.services;
344 case LEAF_sysORLastChange:
345 value->v.uint32 = systemg.or_last_change;
348 return (SNMP_ERR_NOERROR);
351 /*************************************************************
356 op_debug(struct snmp_context *ctx, struct snmp_value *value, u_int sub,
357 u_int iidx __unused, enum snmp_op op)
359 asn_subid_t which = value->var.subs[sub - 1];
363 case SNMP_OP_GETNEXT:
369 case LEAF_begemotSnmpdDebugDumpPdus:
370 value->v.integer = TRUTH_MK(debug.dump_pdus);
373 case LEAF_begemotSnmpdDebugSnmpTrace:
374 value->v.uint32 = snmp_trace;
377 case LEAF_begemotSnmpdDebugSyslogPri:
378 value->v.integer = debug.logpri;
381 return (SNMP_ERR_NOERROR);
386 case LEAF_begemotSnmpdDebugDumpPdus:
387 if (!TRUTH_OK(value->v.integer))
388 return (SNMP_ERR_WRONG_VALUE);
389 ctx->scratch->int1 = debug.dump_pdus;
390 debug.dump_pdus = TRUTH_GET(value->v.integer);
391 return (SNMP_ERR_NOERROR);
393 case LEAF_begemotSnmpdDebugSnmpTrace:
394 ctx->scratch->int1 = snmp_trace;
395 snmp_trace = value->v.uint32;
396 return (SNMP_ERR_NOERROR);
398 case LEAF_begemotSnmpdDebugSyslogPri:
399 if (value->v.integer < 0 || value->v.integer > 8)
400 return (SNMP_ERR_WRONG_VALUE);
401 ctx->scratch->int1 = debug.logpri;
402 debug.logpri = (u_int)value->v.integer;
403 return (SNMP_ERR_NOERROR);
405 return (SNMP_ERR_NO_CREATION);
407 case SNMP_OP_ROLLBACK:
410 case LEAF_begemotSnmpdDebugDumpPdus:
411 debug.dump_pdus = ctx->scratch->int1;
412 return (SNMP_ERR_NOERROR);
414 case LEAF_begemotSnmpdDebugSnmpTrace:
415 snmp_trace = ctx->scratch->int1;
416 return (SNMP_ERR_NOERROR);
418 case LEAF_begemotSnmpdDebugSyslogPri:
419 debug.logpri = ctx->scratch->int1;
420 return (SNMP_ERR_NOERROR);
427 case LEAF_begemotSnmpdDebugDumpPdus:
428 case LEAF_begemotSnmpdDebugSnmpTrace:
429 return (SNMP_ERR_NOERROR);
431 case LEAF_begemotSnmpdDebugSyslogPri:
432 if (debug.logpri == 0)
435 setlogmask(LOG_UPTO(debug.logpri - 1));
436 return (SNMP_ERR_NOERROR);
443 /*************************************************************
448 op_or_table(struct snmp_context *ctx __unused, struct snmp_value *value,
449 u_int sub, u_int iidx __unused, enum snmp_op op)
451 struct objres *objres;
455 case SNMP_OP_GETNEXT:
456 if ((objres = NEXT_OBJECT_INT(&objres_list, &value->var, sub))
458 return (SNMP_ERR_NOSUCHNAME);
459 value->var.subs[sub] = objres->index;
460 value->var.len = sub + 1;
464 if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub))
466 return (SNMP_ERR_NOSUCHNAME);
470 if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub))
472 return (SNMP_ERR_NO_CREATION);
473 return (SNMP_ERR_NOT_WRITEABLE);
475 case SNMP_OP_ROLLBACK:
482 * Come here for GET, GETNEXT.
484 switch (value->var.subs[sub - 1]) {
487 value->v.oid = objres->oid;
490 case LEAF_sysORDescr:
491 return (string_get(value, objres->descr, -1));
493 case LEAF_sysORUpTime:
494 value->v.uint32 = objres->uptime;
497 return (SNMP_ERR_NOERROR);
500 /*************************************************************
505 op_snmp(struct snmp_context *ctx, struct snmp_value *value,
506 u_int sub, u_int iidx __unused, enum snmp_op op)
510 case SNMP_OP_GETNEXT:
514 switch (value->var.subs[sub - 1]) {
516 case LEAF_snmpInPkts:
517 value->v.uint32 = snmpd_stats.inPkts;
520 case LEAF_snmpInBadVersions:
521 value->v.uint32 = snmpd_stats.inBadVersions;
524 case LEAF_snmpInBadCommunityNames:
525 value->v.uint32 = snmpd_stats.inBadCommunityNames;
528 case LEAF_snmpInBadCommunityUses:
529 value->v.uint32 = snmpd_stats.inBadCommunityUses;
532 case LEAF_snmpInASNParseErrs:
533 value->v.uint32 = snmpd_stats.inASNParseErrs;
536 case LEAF_snmpEnableAuthenTraps:
537 value->v.integer = TRUTH_MK(snmpd.auth_traps);
540 case LEAF_snmpSilentDrops:
541 value->v.uint32 = snmpd_stats.silentDrops;
544 case LEAF_snmpProxyDrops:
545 value->v.uint32 = snmpd_stats.proxyDrops;
549 return (SNMP_ERR_NOSUCHNAME);
552 return (SNMP_ERR_NOERROR);
555 switch (value->var.subs[sub - 1]) {
556 case LEAF_snmpEnableAuthenTraps:
557 if (!TRUTH_OK(value->v.integer))
558 return (SNMP_ERR_WRONG_VALUE);
559 ctx->scratch->int1 = value->v.integer;
560 snmpd.auth_traps = TRUTH_GET(value->v.integer);
561 return (SNMP_ERR_NOERROR);
565 case SNMP_OP_ROLLBACK:
566 switch (value->var.subs[sub - 1]) {
567 case LEAF_snmpEnableAuthenTraps:
568 snmpd.auth_traps = ctx->scratch->int1;
569 return (SNMP_ERR_NOERROR);
574 switch (value->var.subs[sub - 1]) {
575 case LEAF_snmpEnableAuthenTraps:
576 return (SNMP_ERR_NOERROR);
583 /*************************************************************
585 * SNMPd statistics group
588 op_snmpd_stats(struct snmp_context *ctx __unused, struct snmp_value *value,
589 u_int sub, u_int iidx __unused, enum snmp_op op)
594 switch (value->var.subs[sub - 1]) {
596 case LEAF_begemotSnmpdStatsNoRxBufs:
597 value->v.uint32 = snmpd_stats.noRxbuf;
600 case LEAF_begemotSnmpdStatsNoTxBufs:
601 value->v.uint32 = snmpd_stats.noTxbuf;
604 case LEAF_begemotSnmpdStatsInTooLongPkts:
605 value->v.uint32 = snmpd_stats.inTooLong;
608 case LEAF_begemotSnmpdStatsInBadPduTypes:
609 value->v.uint32 = snmpd_stats.inBadPduTypes;
613 return (SNMP_ERR_NOSUCHNAME);
615 return (SNMP_ERR_NOERROR);
618 case SNMP_OP_ROLLBACK:
620 case SNMP_OP_GETNEXT:
627 * SNMPd configuration scalars
630 op_snmpd_config(struct snmp_context *ctx, struct snmp_value *value,
631 u_int sub, u_int iidx __unused, enum snmp_op op)
633 asn_subid_t which = value->var.subs[sub - 1];
637 case SNMP_OP_GETNEXT:
643 case LEAF_begemotSnmpdTransmitBuffer:
644 value->v.integer = snmpd.txbuf;
646 case LEAF_begemotSnmpdReceiveBuffer:
647 value->v.integer = snmpd.rxbuf;
649 case LEAF_begemotSnmpdCommunityDisable:
650 value->v.integer = TRUTH_MK(snmpd.comm_dis);
652 case LEAF_begemotSnmpdTrap1Addr:
653 return (ip_get(value, snmpd.trap1addr));
654 case LEAF_begemotSnmpdVersionEnable:
655 value->v.uint32 = snmpd.version_enable;
658 return (SNMP_ERR_NOSUCHNAME);
660 return (SNMP_ERR_NOERROR);
665 case LEAF_begemotSnmpdTransmitBuffer:
666 ctx->scratch->int1 = snmpd.txbuf;
667 if (value->v.integer < 484 ||
668 value->v.integer > 65535)
669 return (SNMP_ERR_WRONG_VALUE);
670 snmpd.txbuf = value->v.integer;
671 return (SNMP_ERR_NOERROR);
673 case LEAF_begemotSnmpdReceiveBuffer:
674 ctx->scratch->int1 = snmpd.rxbuf;
675 if (value->v.integer < 484 ||
676 value->v.integer > 65535)
677 return (SNMP_ERR_WRONG_VALUE);
678 snmpd.rxbuf = value->v.integer;
679 return (SNMP_ERR_NOERROR);
681 case LEAF_begemotSnmpdCommunityDisable:
682 ctx->scratch->int1 = snmpd.comm_dis;
683 if (!TRUTH_OK(value->v.integer))
684 return (SNMP_ERR_WRONG_VALUE);
685 if (TRUTH_GET(value->v.integer)) {
689 return (SNMP_ERR_WRONG_VALUE);
691 return (SNMP_ERR_NOERROR);
693 case LEAF_begemotSnmpdTrap1Addr:
694 return (ip_save(value, ctx, snmpd.trap1addr));
696 case LEAF_begemotSnmpdVersionEnable:
697 if (community != COMM_INITIALIZE)
698 return (SNMP_ERR_NOT_WRITEABLE);
699 ctx->scratch->int1 = snmpd.version_enable;
700 if (value->v.uint32 == 0 ||
701 (value->v.uint32 & ~VERS_ENABLE_ALL))
702 return (SNMP_ERR_WRONG_VALUE);
703 snmpd.version_enable = value->v.uint32;
704 return (SNMP_ERR_NOERROR);
708 case SNMP_OP_ROLLBACK:
711 case LEAF_begemotSnmpdTransmitBuffer:
712 snmpd.rxbuf = ctx->scratch->int1;
713 return (SNMP_ERR_NOERROR);
714 case LEAF_begemotSnmpdReceiveBuffer:
715 snmpd.txbuf = ctx->scratch->int1;
716 return (SNMP_ERR_NOERROR);
717 case LEAF_begemotSnmpdCommunityDisable:
718 snmpd.comm_dis = ctx->scratch->int1;
719 return (SNMP_ERR_NOERROR);
720 case LEAF_begemotSnmpdTrap1Addr:
721 ip_rollback(ctx, snmpd.trap1addr);
722 return (SNMP_ERR_NOERROR);
723 case LEAF_begemotSnmpdVersionEnable:
724 snmpd.version_enable = ctx->scratch->int1;
725 return (SNMP_ERR_NOERROR);
732 case LEAF_begemotSnmpdTransmitBuffer:
733 case LEAF_begemotSnmpdReceiveBuffer:
734 case LEAF_begemotSnmpdCommunityDisable:
735 return (SNMP_ERR_NOERROR);
736 case LEAF_begemotSnmpdTrap1Addr:
738 return (SNMP_ERR_NOERROR);
739 case LEAF_begemotSnmpdVersionEnable:
740 return (SNMP_ERR_NOERROR);
748 * The community table
751 op_community(struct snmp_context *ctx, struct snmp_value *value,
752 u_int sub, u_int iidx __unused, enum snmp_op op)
754 asn_subid_t which = value->var.subs[sub - 1];
759 case SNMP_OP_GETNEXT:
760 if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
761 (c = NEXT_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
762 return (SNMP_ERR_NOSUCHNAME);
763 index_append(&value->var, sub, &c->index);
767 if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
768 (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
769 return (SNMP_ERR_NOSUCHNAME);
773 if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
774 (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
775 return (SNMP_ERR_NO_CREATION);
776 if (which != LEAF_begemotSnmpdCommunityString)
777 return (SNMP_ERR_NOT_WRITEABLE);
778 return (string_save(value, ctx, -1, &c->string));
780 case SNMP_OP_ROLLBACK:
781 if (which == LEAF_begemotSnmpdCommunityString) {
782 if ((c = FIND_OBJECT_OID(&community_list, &value->var,
786 string_rollback(ctx, &c->string);
787 return (SNMP_ERR_NOERROR);
792 if (which == LEAF_begemotSnmpdCommunityString) {
793 if ((c = FIND_OBJECT_OID(&community_list, &value->var,
798 return (SNMP_ERR_NOERROR);
808 case LEAF_begemotSnmpdCommunityString:
809 return (string_get(value, c->string, -1));
811 case LEAF_begemotSnmpdCommunityDescr:
812 return (string_get(value, c->descr, -1));
821 struct snmp_dependency dep;
822 u_char section[LM_SECTION_MAX + 1];
828 dep_modules(struct snmp_context *ctx, struct snmp_dependency *dep,
831 struct module_dep *mdep = (struct module_dep *)(void *)dep;
835 case SNMP_DEPOP_COMMIT:
836 if (mdep->path == NULL) {
837 /* unload - find the module */
838 TAILQ_FOREACH(mdep->m, &lmodules, link)
839 if (strcmp(mdep->m->section,
843 /* no such module - that's ok */
844 return (SNMP_ERR_NOERROR);
846 /* handle unloading in the finalizer */
847 return (SNMP_ERR_NOERROR);
850 if ((mdep->m = lm_load(mdep->path, mdep->section)) == NULL) {
852 return (SNMP_ERR_RES_UNAVAIL);
854 /* start in finalizer */
855 return (SNMP_ERR_NOERROR);
857 case SNMP_DEPOP_ROLLBACK:
858 if (mdep->path == NULL) {
859 /* rollback unload - the finalizer takes care */
860 return (SNMP_ERR_NOERROR);
864 return (SNMP_ERR_NOERROR);
866 case SNMP_DEPOP_FINISH:
867 if (mdep->path == NULL) {
868 if (mdep->m != NULL && ctx->code == SNMP_RET_OK)
871 if (mdep->m != NULL && ctx->code == SNMP_RET_OK &&
872 community != COMM_INITIALIZE)
876 return (SNMP_ERR_NOERROR);
882 op_modules(struct snmp_context *ctx, struct snmp_value *value,
883 u_int sub, u_int iidx, enum snmp_op op)
885 asn_subid_t which = value->var.subs[sub - 1];
887 u_char *section, *ptr;
889 struct module_dep *mdep;
894 case SNMP_OP_GETNEXT:
895 if ((m = NEXT_OBJECT_OID(&lmodules, &value->var, sub)) == NULL)
896 return (SNMP_ERR_NOSUCHNAME);
897 index_append(&value->var, sub, &m->index);
901 if ((m = FIND_OBJECT_OID(&lmodules, &value->var, sub)) == NULL)
902 return (SNMP_ERR_NOSUCHNAME);
906 m = FIND_OBJECT_OID(&lmodules, &value->var, sub);
907 if (which != LEAF_begemotSnmpdModulePath) {
909 return (SNMP_ERR_NO_CREATION);
910 return (SNMP_ERR_NOT_WRITEABLE);
913 /* the errors in the next few statements can only happen when
914 * m is NULL, hence the NO_CREATION error. */
915 if (index_decode(&value->var, sub, iidx,
917 return (SNMP_ERR_NO_CREATION);
919 /* check the section name */
920 if (seclen > LM_SECTION_MAX || seclen == 0) {
922 return (SNMP_ERR_NO_CREATION);
924 for (ptr = section; ptr < section + seclen; ptr++)
925 if (!isascii(*ptr) || !isalnum(*ptr)) {
927 return (SNMP_ERR_NO_CREATION);
929 if (!isalpha(section[0])) {
931 return (SNMP_ERR_NO_CREATION);
935 for (ptr = value->v.octetstring.octets;
936 ptr < value->v.octetstring.octets + value->v.octetstring.len;
940 return (SNMP_ERR_WRONG_VALUE);
945 if (value->v.octetstring.len == 0) {
947 return (SNMP_ERR_INCONS_VALUE);
950 if (value->v.octetstring.len != 0) {
952 return (SNMP_ERR_INCONS_VALUE);
956 asn_slice_oid(&idx, &value->var, sub, value->var.len);
958 /* so far, so good */
959 mdep = (struct module_dep *)(void *)snmp_dep_lookup(ctx,
960 &oid_begemotSnmpdModuleTable, &idx,
961 sizeof(*mdep), dep_modules);
964 return (SNMP_ERR_RES_UNAVAIL);
967 if (mdep->section[0] != '\0') {
968 /* two writes to the same entry - bad */
970 return (SNMP_ERR_INCONS_VALUE);
973 strncpy(mdep->section, section, seclen);
974 mdep->section[seclen] = '\0';
977 if (value->v.octetstring.len == 0)
980 if ((mdep->path = malloc(value->v.octetstring.len + 1)) == NULL)
981 return (SNMP_ERR_RES_UNAVAIL);
982 strncpy(mdep->path, value->v.octetstring.octets,
983 value->v.octetstring.len);
984 mdep->path[value->v.octetstring.len] = '\0';
986 ctx->scratch->ptr1 = mdep;
987 return (SNMP_ERR_NOERROR);
989 case SNMP_OP_ROLLBACK:
991 return (SNMP_ERR_NOERROR);
999 case LEAF_begemotSnmpdModulePath:
1000 return (string_get(value, m->path, -1));
1002 case LEAF_begemotSnmpdModuleComment:
1003 return (string_get(value, m->config->comment, -1));
1009 op_snmp_set(struct snmp_context *ctx __unused, struct snmp_value *value,
1010 u_int sub, u_int iidx __unused, enum snmp_op op)
1014 case SNMP_OP_GETNEXT:
1018 switch (value->var.subs[sub - 1]) {
1020 case LEAF_snmpSetSerialNo:
1021 value->v.integer = snmp_serial_no;
1027 return (SNMP_ERR_NOERROR);
1030 switch (value->var.subs[sub - 1]) {
1032 case LEAF_snmpSetSerialNo:
1033 if (value->v.integer != snmp_serial_no)
1034 return (SNMP_ERR_INCONS_VALUE);
1040 return (SNMP_ERR_NOERROR);
1042 case SNMP_OP_ROLLBACK:
1043 return (SNMP_ERR_NOERROR);
1045 case SNMP_OP_COMMIT:
1046 if (snmp_serial_no++ == 2147483647)
1048 return (SNMP_ERR_NOERROR);
1057 op_snmp_engine(struct snmp_context *ctx __unused, struct snmp_value *value,
1058 u_int sub, u_int iidx __unused, enum snmp_op op)
1060 asn_subid_t which = value->var.subs[sub - 1];
1063 case SNMP_OP_GETNEXT:
1070 if (community != COMM_INITIALIZE)
1071 return (SNMP_ERR_NOT_WRITEABLE);
1073 case LEAF_snmpEngineID:
1074 if (value->v.octetstring.len > SNMP_ENGINE_ID_SIZ)
1075 return (SNMP_ERR_WRONG_VALUE);
1076 ctx->scratch->ptr1 = malloc(snmpd_engine.engine_len);
1077 if (ctx->scratch->ptr1 == NULL)
1078 return (SNMP_ERR_GENERR);
1079 memcpy(ctx->scratch->ptr1, snmpd_engine.engine_id,
1080 snmpd_engine.engine_len);
1081 ctx->scratch->int1 = snmpd_engine.engine_len;
1082 snmpd_engine.engine_len = value->v.octetstring.len;
1083 memcpy(snmpd_engine.engine_id,
1084 value->v.octetstring.octets,
1085 value->v.octetstring.len);
1088 case LEAF_snmpEngineMaxMessageSize:
1089 ctx->scratch->int1 = snmpd_engine.max_msg_size;
1090 snmpd_engine.max_msg_size = value->v.integer;
1094 return (SNMP_ERR_NOT_WRITEABLE);
1096 return (SNMP_ERR_NOERROR);
1098 case SNMP_OP_ROLLBACK:
1100 case LEAF_snmpEngineID:
1101 snmpd_engine.engine_len = ctx->scratch->int1;
1102 memcpy(snmpd_engine.engine_id, ctx->scratch->ptr1,
1103 snmpd_engine.engine_len);
1104 free(ctx->scratch->ptr1);
1107 case LEAF_snmpEngineMaxMessageSize:
1108 snmpd_engine.max_msg_size = ctx->scratch->int1;
1114 return (SNMP_ERR_NOERROR);
1116 case SNMP_OP_COMMIT:
1117 if (which == LEAF_snmpEngineID) {
1118 if (set_snmpd_engine() < 0) {
1119 snmpd_engine.engine_len = ctx->scratch->int1;
1120 memcpy(snmpd_engine.engine_id,
1121 ctx->scratch->ptr1, ctx->scratch->int1);
1123 free(ctx->scratch->ptr1);
1125 return (SNMP_ERR_NOERROR);
1130 case LEAF_snmpEngineID:
1131 return (string_get(value, snmpd_engine.engine_id,
1132 snmpd_engine.engine_len));
1133 case LEAF_snmpEngineBoots:
1134 value->v.integer = snmpd_engine.engine_boots;
1136 case LEAF_snmpEngineTime:
1137 update_snmpd_engine_time();
1138 value->v.integer = snmpd_engine.engine_time;
1140 case LEAF_snmpEngineMaxMessageSize:
1141 value->v.integer = snmpd_engine.max_msg_size;
1144 return (SNMP_ERR_NOSUCHNAME);
1147 return (SNMP_ERR_NOERROR);
1154 op_transport_table(struct snmp_context *ctx __unused, struct snmp_value *value,
1155 u_int sub, u_int iidx, enum snmp_op op)
1157 asn_subid_t which = value->var.subs[sub - 1];
1158 struct transport *t;
1159 u_char *tname, *ptr;
1164 case SNMP_OP_GETNEXT:
1165 if ((t = NEXT_OBJECT_OID(&transport_list, &value->var, sub))
1167 return (SNMP_ERR_NOSUCHNAME);
1168 index_append(&value->var, sub, &t->index);
1172 if ((t = FIND_OBJECT_OID(&transport_list, &value->var, sub))
1174 return (SNMP_ERR_NOSUCHNAME);
1178 t = FIND_OBJECT_OID(&transport_list, &value->var, sub);
1179 if (which != LEAF_begemotSnmpdTransportStatus) {
1181 return (SNMP_ERR_NO_CREATION);
1182 return (SNMP_ERR_NOT_WRITEABLE);
1185 /* the errors in the next few statements can only happen when
1186 * t is NULL, hence the NO_CREATION error. */
1187 if (index_decode(&value->var, sub, iidx,
1189 return (SNMP_ERR_NO_CREATION);
1191 /* check the section name */
1192 if (tnamelen >= TRANS_NAMELEN || tnamelen == 0) {
1194 return (SNMP_ERR_NO_CREATION);
1196 for (ptr = tname; ptr < tname + tnamelen; ptr++) {
1197 if (!isascii(*ptr) || !isalnum(*ptr)) {
1199 return (SNMP_ERR_NO_CREATION);
1204 return (SNMP_ERR_NOT_WRITEABLE);
1206 case SNMP_OP_ROLLBACK:
1207 case SNMP_OP_COMMIT:
1208 return (SNMP_ERR_NOERROR);
1215 case LEAF_begemotSnmpdTransportStatus:
1216 value->v.integer = 1;
1219 case LEAF_begemotSnmpdTransportOid:
1220 memcpy(&value->v.oid, &t->vtab->id, sizeof(t->vtab->id));
1223 return (SNMP_ERR_NOERROR);