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 an integer value from the KERN sysctl subtree.
66 act_getkernint(int id)
76 if (sysctl(mib, 2, &value, &len, NULL, 0) != 0)
79 if ((string = malloc(20)) == NULL)
81 sprintf(string, "%lu", value);
86 * Initialize global variables of the system group.
99 if (uname(&uts) == -1)
102 if ((systemg.name = strdup(uts.nodename)) == NULL)
105 if ((hostid = act_getkernint(KERN_HOSTID)) == NULL)
108 len = strlen(uts.nodename) + 1;
109 len += strlen(hostid) + 1;
110 len += strlen(uts.sysname) + 1;
111 len += strlen(uts.release) + 1;
113 if ((systemg.descr = malloc(len)) == NULL) {
117 sprintf(systemg.descr, "%s %s %s %s", uts.nodename, hostid, uts.sysname,
122 * Construct a FreeBSD oid
124 systemg.object_id = oid_freeBSDVersion;
126 while ((p = strsep(&rel, ".")) != NULL &&
127 systemg.object_id.len < ASN_MAXOIDLEN) {
128 systemg.object_id.subs[systemg.object_id.len] = 0;
130 num = strtoul(p, &end, 10);
133 systemg.object_id.subs[systemg.object_id.len] = num;
135 systemg.object_id.len++;
145 * Initialize global variables of the snmpEngine group.
148 init_snmpd_engine(void)
152 snmpd_engine.engine_boots = 1;
153 snmpd_engine.engine_time = 1;
154 snmpd_engine.max_msg_size = 1500; /* XXX */
156 snmpd_engine.engine_id[0] = ((OID_freeBSD & 0xff000000) >> 24) | 0x80;
157 snmpd_engine.engine_id[1] = (OID_freeBSD & 0xff0000) >> 16;
158 snmpd_engine.engine_id[2] = (OID_freeBSD & 0xff00) >> 8;
159 snmpd_engine.engine_id[3] = OID_freeBSD & 0xff;
160 snmpd_engine.engine_id[4] = 128;
161 snmpd_engine.engine_len = 5;
163 if ((hostid = act_getkernint(KERN_HOSTID)) == NULL)
166 if (strlen(hostid) > SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len) {
167 memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len,
168 hostid, SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len);
169 snmpd_engine.engine_len = SNMP_ENGINE_ID_SIZ;
171 memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len,
172 hostid, strlen(hostid));
173 snmpd_engine.engine_len += strlen(hostid);
182 set_snmpd_engine(void)
186 uint8_t *cptr, engine[2 * SNMP_ENGINE_ID_SIZ + 2];
187 uint8_t myengine[2 * SNMP_ENGINE_ID_SIZ + 2];
189 if (engine_file[0] == '\0')
193 for (i = 0; i < snmpd_engine.engine_len; i++)
194 cptr += sprintf(cptr, "%.2x", snmpd_engine.engine_id[i]);
198 if ((fp = fopen(engine_file, "r+")) != NULL) {
199 if (fgets(engine, sizeof(engine) - 1, fp) == NULL ||
200 fscanf(fp, "%u", &snmpd_engine.engine_boots) <= 0) {
206 if (strcmp(myengine, engine) != 0)
207 snmpd_engine.engine_boots = 1;
209 snmpd_engine.engine_boots++;
210 } else if (errno != ENOENT)
214 if ((fp = fopen(engine_file, "w+")) == NULL)
216 fprintf(fp, "%s%u\n", myengine, snmpd_engine.engine_boots);
222 /*************************************************************
227 op_system_group(struct snmp_context *ctx, struct snmp_value *value,
228 u_int sub, u_int iidx __unused, enum snmp_op op)
230 asn_subid_t which = value->var.subs[sub - 1];
234 case SNMP_OP_GETNEXT:
244 if (community != COMM_INITIALIZE)
245 return (SNMP_ERR_NOT_WRITEABLE);
246 return (string_save(value, ctx, -1, &systemg.descr));
248 case LEAF_sysObjectId:
249 if (community != COMM_INITIALIZE)
250 return (SNMP_ERR_NOT_WRITEABLE);
251 return (oid_save(value, ctx, &systemg.object_id));
253 case LEAF_sysContact:
254 return (string_save(value, ctx, -1, &systemg.contact));
257 return (string_save(value, ctx, -1, &systemg.name));
259 case LEAF_sysLocation:
260 return (string_save(value, ctx, -1, &systemg.location));
262 return (SNMP_ERR_NO_CREATION);
264 case SNMP_OP_ROLLBACK:
268 string_rollback(ctx, &systemg.descr);
269 return (SNMP_ERR_NOERROR);
270 case LEAF_sysObjectId:
271 oid_rollback(ctx, &systemg.object_id);
272 return (SNMP_ERR_NOERROR);
273 case LEAF_sysContact:
274 string_rollback(ctx, &systemg.contact);
275 return (SNMP_ERR_NOERROR);
277 string_rollback(ctx, &systemg.name);
278 return (SNMP_ERR_NOERROR);
279 case LEAF_sysLocation:
280 string_rollback(ctx, &systemg.location);
281 return (SNMP_ERR_NOERROR);
290 return (SNMP_ERR_NOERROR);
291 case LEAF_sysObjectId:
293 return (SNMP_ERR_NOERROR);
294 case LEAF_sysContact:
296 return (SNMP_ERR_NOERROR);
299 return (SNMP_ERR_NOERROR);
300 case LEAF_sysLocation:
302 return (SNMP_ERR_NOERROR);
313 return (string_get(value, systemg.descr, -1));
314 case LEAF_sysObjectId:
315 return (oid_get(value, &systemg.object_id));
317 value->v.uint32 = get_ticks() - start_tick;
319 case LEAF_sysContact:
320 return (string_get(value, systemg.contact, -1));
322 return (string_get(value, systemg.name, -1));
323 case LEAF_sysLocation:
324 return (string_get(value, systemg.location, -1));
325 case LEAF_sysServices:
326 value->v.integer = systemg.services;
328 case LEAF_sysORLastChange:
329 value->v.uint32 = systemg.or_last_change;
332 return (SNMP_ERR_NOERROR);
335 /*************************************************************
340 op_debug(struct snmp_context *ctx, struct snmp_value *value, u_int sub,
341 u_int iidx __unused, enum snmp_op op)
343 asn_subid_t which = value->var.subs[sub - 1];
347 case SNMP_OP_GETNEXT:
353 case LEAF_begemotSnmpdDebugDumpPdus:
354 value->v.integer = TRUTH_MK(debug.dump_pdus);
357 case LEAF_begemotSnmpdDebugSnmpTrace:
358 value->v.uint32 = snmp_trace;
361 case LEAF_begemotSnmpdDebugSyslogPri:
362 value->v.integer = debug.logpri;
365 return (SNMP_ERR_NOERROR);
370 case LEAF_begemotSnmpdDebugDumpPdus:
371 if (!TRUTH_OK(value->v.integer))
372 return (SNMP_ERR_WRONG_VALUE);
373 ctx->scratch->int1 = debug.dump_pdus;
374 debug.dump_pdus = TRUTH_GET(value->v.integer);
375 return (SNMP_ERR_NOERROR);
377 case LEAF_begemotSnmpdDebugSnmpTrace:
378 ctx->scratch->int1 = snmp_trace;
379 snmp_trace = value->v.uint32;
380 return (SNMP_ERR_NOERROR);
382 case LEAF_begemotSnmpdDebugSyslogPri:
383 if (value->v.integer < 0 || value->v.integer > 8)
384 return (SNMP_ERR_WRONG_VALUE);
385 ctx->scratch->int1 = debug.logpri;
386 debug.logpri = (u_int)value->v.integer;
387 return (SNMP_ERR_NOERROR);
389 return (SNMP_ERR_NO_CREATION);
391 case SNMP_OP_ROLLBACK:
394 case LEAF_begemotSnmpdDebugDumpPdus:
395 debug.dump_pdus = ctx->scratch->int1;
396 return (SNMP_ERR_NOERROR);
398 case LEAF_begemotSnmpdDebugSnmpTrace:
399 snmp_trace = ctx->scratch->int1;
400 return (SNMP_ERR_NOERROR);
402 case LEAF_begemotSnmpdDebugSyslogPri:
403 debug.logpri = ctx->scratch->int1;
404 return (SNMP_ERR_NOERROR);
411 case LEAF_begemotSnmpdDebugDumpPdus:
412 case LEAF_begemotSnmpdDebugSnmpTrace:
413 return (SNMP_ERR_NOERROR);
415 case LEAF_begemotSnmpdDebugSyslogPri:
416 if (debug.logpri == 0)
419 setlogmask(LOG_UPTO(debug.logpri - 1));
420 return (SNMP_ERR_NOERROR);
427 /*************************************************************
432 op_or_table(struct snmp_context *ctx __unused, struct snmp_value *value,
433 u_int sub, u_int iidx __unused, enum snmp_op op)
435 struct objres *objres;
439 case SNMP_OP_GETNEXT:
440 if ((objres = NEXT_OBJECT_INT(&objres_list, &value->var, sub))
442 return (SNMP_ERR_NOSUCHNAME);
443 value->var.subs[sub] = objres->index;
444 value->var.len = sub + 1;
448 if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub))
450 return (SNMP_ERR_NOSUCHNAME);
454 if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub))
456 return (SNMP_ERR_NO_CREATION);
457 return (SNMP_ERR_NOT_WRITEABLE);
459 case SNMP_OP_ROLLBACK:
466 * Come here for GET, GETNEXT.
468 switch (value->var.subs[sub - 1]) {
471 value->v.oid = objres->oid;
474 case LEAF_sysORDescr:
475 return (string_get(value, objres->descr, -1));
477 case LEAF_sysORUpTime:
478 value->v.uint32 = objres->uptime;
481 return (SNMP_ERR_NOERROR);
484 /*************************************************************
489 op_snmp(struct snmp_context *ctx, struct snmp_value *value,
490 u_int sub, u_int iidx __unused, enum snmp_op op)
494 case SNMP_OP_GETNEXT:
498 switch (value->var.subs[sub - 1]) {
500 case LEAF_snmpInPkts:
501 value->v.uint32 = snmpd_stats.inPkts;
504 case LEAF_snmpInBadVersions:
505 value->v.uint32 = snmpd_stats.inBadVersions;
508 case LEAF_snmpInBadCommunityNames:
509 value->v.uint32 = snmpd_stats.inBadCommunityNames;
512 case LEAF_snmpInBadCommunityUses:
513 value->v.uint32 = snmpd_stats.inBadCommunityUses;
516 case LEAF_snmpInASNParseErrs:
517 value->v.uint32 = snmpd_stats.inASNParseErrs;
520 case LEAF_snmpEnableAuthenTraps:
521 value->v.integer = TRUTH_MK(snmpd.auth_traps);
524 case LEAF_snmpSilentDrops:
525 value->v.uint32 = snmpd_stats.silentDrops;
528 case LEAF_snmpProxyDrops:
529 value->v.uint32 = snmpd_stats.proxyDrops;
533 return (SNMP_ERR_NOSUCHNAME);
536 return (SNMP_ERR_NOERROR);
539 switch (value->var.subs[sub - 1]) {
540 case LEAF_snmpEnableAuthenTraps:
541 if (!TRUTH_OK(value->v.integer))
542 return (SNMP_ERR_WRONG_VALUE);
543 ctx->scratch->int1 = value->v.integer;
544 snmpd.auth_traps = TRUTH_GET(value->v.integer);
545 return (SNMP_ERR_NOERROR);
549 case SNMP_OP_ROLLBACK:
550 switch (value->var.subs[sub - 1]) {
551 case LEAF_snmpEnableAuthenTraps:
552 snmpd.auth_traps = ctx->scratch->int1;
553 return (SNMP_ERR_NOERROR);
558 switch (value->var.subs[sub - 1]) {
559 case LEAF_snmpEnableAuthenTraps:
560 return (SNMP_ERR_NOERROR);
567 /*************************************************************
569 * SNMPd statistics group
572 op_snmpd_stats(struct snmp_context *ctx __unused, struct snmp_value *value,
573 u_int sub, u_int iidx __unused, enum snmp_op op)
578 switch (value->var.subs[sub - 1]) {
580 case LEAF_begemotSnmpdStatsNoRxBufs:
581 value->v.uint32 = snmpd_stats.noRxbuf;
584 case LEAF_begemotSnmpdStatsNoTxBufs:
585 value->v.uint32 = snmpd_stats.noTxbuf;
588 case LEAF_begemotSnmpdStatsInTooLongPkts:
589 value->v.uint32 = snmpd_stats.inTooLong;
592 case LEAF_begemotSnmpdStatsInBadPduTypes:
593 value->v.uint32 = snmpd_stats.inBadPduTypes;
597 return (SNMP_ERR_NOSUCHNAME);
599 return (SNMP_ERR_NOERROR);
602 case SNMP_OP_ROLLBACK:
604 case SNMP_OP_GETNEXT:
611 * SNMPd configuration scalars
614 op_snmpd_config(struct snmp_context *ctx, struct snmp_value *value,
615 u_int sub, u_int iidx __unused, enum snmp_op op)
617 asn_subid_t which = value->var.subs[sub - 1];
621 case SNMP_OP_GETNEXT:
627 case LEAF_begemotSnmpdTransmitBuffer:
628 value->v.integer = snmpd.txbuf;
630 case LEAF_begemotSnmpdReceiveBuffer:
631 value->v.integer = snmpd.rxbuf;
633 case LEAF_begemotSnmpdCommunityDisable:
634 value->v.integer = TRUTH_MK(snmpd.comm_dis);
636 case LEAF_begemotSnmpdTrap1Addr:
637 return (ip_get(value, snmpd.trap1addr));
638 case LEAF_begemotSnmpdVersionEnable:
639 value->v.uint32 = snmpd.version_enable;
642 return (SNMP_ERR_NOSUCHNAME);
644 return (SNMP_ERR_NOERROR);
649 case LEAF_begemotSnmpdTransmitBuffer:
650 ctx->scratch->int1 = snmpd.txbuf;
651 if (value->v.integer < 484 ||
652 value->v.integer > 65535)
653 return (SNMP_ERR_WRONG_VALUE);
654 snmpd.txbuf = value->v.integer;
655 return (SNMP_ERR_NOERROR);
657 case LEAF_begemotSnmpdReceiveBuffer:
658 ctx->scratch->int1 = snmpd.rxbuf;
659 if (value->v.integer < 484 ||
660 value->v.integer > 65535)
661 return (SNMP_ERR_WRONG_VALUE);
662 snmpd.rxbuf = value->v.integer;
663 return (SNMP_ERR_NOERROR);
665 case LEAF_begemotSnmpdCommunityDisable:
666 ctx->scratch->int1 = snmpd.comm_dis;
667 if (!TRUTH_OK(value->v.integer))
668 return (SNMP_ERR_WRONG_VALUE);
669 if (TRUTH_GET(value->v.integer)) {
673 return (SNMP_ERR_WRONG_VALUE);
675 return (SNMP_ERR_NOERROR);
677 case LEAF_begemotSnmpdTrap1Addr:
678 return (ip_save(value, ctx, snmpd.trap1addr));
680 case LEAF_begemotSnmpdVersionEnable:
681 if (community != COMM_INITIALIZE)
682 return (SNMP_ERR_NOT_WRITEABLE);
683 ctx->scratch->int1 = snmpd.version_enable;
684 if (value->v.uint32 == 0 ||
685 (value->v.uint32 & ~VERS_ENABLE_ALL))
686 return (SNMP_ERR_WRONG_VALUE);
687 snmpd.version_enable = value->v.uint32;
688 return (SNMP_ERR_NOERROR);
692 case SNMP_OP_ROLLBACK:
695 case LEAF_begemotSnmpdTransmitBuffer:
696 snmpd.rxbuf = ctx->scratch->int1;
697 return (SNMP_ERR_NOERROR);
698 case LEAF_begemotSnmpdReceiveBuffer:
699 snmpd.txbuf = ctx->scratch->int1;
700 return (SNMP_ERR_NOERROR);
701 case LEAF_begemotSnmpdCommunityDisable:
702 snmpd.comm_dis = ctx->scratch->int1;
703 return (SNMP_ERR_NOERROR);
704 case LEAF_begemotSnmpdTrap1Addr:
705 ip_rollback(ctx, snmpd.trap1addr);
706 return (SNMP_ERR_NOERROR);
707 case LEAF_begemotSnmpdVersionEnable:
708 snmpd.version_enable = ctx->scratch->int1;
709 return (SNMP_ERR_NOERROR);
716 case LEAF_begemotSnmpdTransmitBuffer:
717 case LEAF_begemotSnmpdReceiveBuffer:
718 case LEAF_begemotSnmpdCommunityDisable:
719 return (SNMP_ERR_NOERROR);
720 case LEAF_begemotSnmpdTrap1Addr:
722 return (SNMP_ERR_NOERROR);
723 case LEAF_begemotSnmpdVersionEnable:
724 return (SNMP_ERR_NOERROR);
732 * The community table
735 op_community(struct snmp_context *ctx, struct snmp_value *value,
736 u_int sub, u_int iidx __unused, enum snmp_op op)
738 asn_subid_t which = value->var.subs[sub - 1];
743 case SNMP_OP_GETNEXT:
744 if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
745 (c = NEXT_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
746 return (SNMP_ERR_NOSUCHNAME);
747 index_append(&value->var, sub, &c->index);
751 if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
752 (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
753 return (SNMP_ERR_NOSUCHNAME);
757 if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
758 (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
759 return (SNMP_ERR_NO_CREATION);
760 if (which != LEAF_begemotSnmpdCommunityString)
761 return (SNMP_ERR_NOT_WRITEABLE);
762 return (string_save(value, ctx, -1, &c->string));
764 case SNMP_OP_ROLLBACK:
765 if (which == LEAF_begemotSnmpdCommunityString) {
766 if ((c = FIND_OBJECT_OID(&community_list, &value->var,
770 string_rollback(ctx, &c->string);
771 return (SNMP_ERR_NOERROR);
776 if (which == LEAF_begemotSnmpdCommunityString) {
777 if ((c = FIND_OBJECT_OID(&community_list, &value->var,
782 return (SNMP_ERR_NOERROR);
792 case LEAF_begemotSnmpdCommunityString:
793 return (string_get(value, c->string, -1));
795 case LEAF_begemotSnmpdCommunityDescr:
796 return (string_get(value, c->descr, -1));
805 struct snmp_dependency dep;
806 u_char section[LM_SECTION_MAX + 1];
812 dep_modules(struct snmp_context *ctx, struct snmp_dependency *dep,
815 struct module_dep *mdep = (struct module_dep *)(void *)dep;
819 case SNMP_DEPOP_COMMIT:
820 if (mdep->path == NULL) {
821 /* unload - find the module */
822 TAILQ_FOREACH(mdep->m, &lmodules, link)
823 if (strcmp(mdep->m->section,
827 /* no such module - that's ok */
828 return (SNMP_ERR_NOERROR);
830 /* handle unloading in the finalizer */
831 return (SNMP_ERR_NOERROR);
834 if ((mdep->m = lm_load(mdep->path, mdep->section)) == NULL) {
836 return (SNMP_ERR_RES_UNAVAIL);
838 /* start in finalizer */
839 return (SNMP_ERR_NOERROR);
841 case SNMP_DEPOP_ROLLBACK:
842 if (mdep->path == NULL) {
843 /* rollback unload - the finalizer takes care */
844 return (SNMP_ERR_NOERROR);
848 return (SNMP_ERR_NOERROR);
850 case SNMP_DEPOP_FINISH:
851 if (mdep->path == NULL) {
852 if (mdep->m != NULL && ctx->code == SNMP_RET_OK)
855 if (mdep->m != NULL && ctx->code == SNMP_RET_OK &&
856 community != COMM_INITIALIZE)
860 return (SNMP_ERR_NOERROR);
866 op_modules(struct snmp_context *ctx, struct snmp_value *value,
867 u_int sub, u_int iidx, enum snmp_op op)
869 asn_subid_t which = value->var.subs[sub - 1];
871 u_char *section, *ptr;
873 struct module_dep *mdep;
878 case SNMP_OP_GETNEXT:
879 if ((m = NEXT_OBJECT_OID(&lmodules, &value->var, sub)) == NULL)
880 return (SNMP_ERR_NOSUCHNAME);
881 index_append(&value->var, sub, &m->index);
885 if ((m = FIND_OBJECT_OID(&lmodules, &value->var, sub)) == NULL)
886 return (SNMP_ERR_NOSUCHNAME);
890 m = FIND_OBJECT_OID(&lmodules, &value->var, sub);
891 if (which != LEAF_begemotSnmpdModulePath) {
893 return (SNMP_ERR_NO_CREATION);
894 return (SNMP_ERR_NOT_WRITEABLE);
897 /* the errors in the next few statements can only happen when
898 * m is NULL, hence the NO_CREATION error. */
899 if (index_decode(&value->var, sub, iidx,
901 return (SNMP_ERR_NO_CREATION);
903 /* check the section name */
904 if (seclen > LM_SECTION_MAX || seclen == 0) {
906 return (SNMP_ERR_NO_CREATION);
908 for (ptr = section; ptr < section + seclen; ptr++)
909 if (!isascii(*ptr) || !isalnum(*ptr)) {
911 return (SNMP_ERR_NO_CREATION);
913 if (!isalpha(section[0])) {
915 return (SNMP_ERR_NO_CREATION);
919 for (ptr = value->v.octetstring.octets;
920 ptr < value->v.octetstring.octets + value->v.octetstring.len;
924 return (SNMP_ERR_WRONG_VALUE);
929 if (value->v.octetstring.len == 0) {
931 return (SNMP_ERR_INCONS_VALUE);
934 if (value->v.octetstring.len != 0) {
936 return (SNMP_ERR_INCONS_VALUE);
940 asn_slice_oid(&idx, &value->var, sub, value->var.len);
942 /* so far, so good */
943 mdep = (struct module_dep *)(void *)snmp_dep_lookup(ctx,
944 &oid_begemotSnmpdModuleTable, &idx,
945 sizeof(*mdep), dep_modules);
948 return (SNMP_ERR_RES_UNAVAIL);
951 if (mdep->section[0] != '\0') {
952 /* two writes to the same entry - bad */
954 return (SNMP_ERR_INCONS_VALUE);
957 strncpy(mdep->section, section, seclen);
958 mdep->section[seclen] = '\0';
961 if (value->v.octetstring.len == 0)
964 if ((mdep->path = malloc(value->v.octetstring.len + 1)) == NULL)
965 return (SNMP_ERR_RES_UNAVAIL);
966 strncpy(mdep->path, value->v.octetstring.octets,
967 value->v.octetstring.len);
968 mdep->path[value->v.octetstring.len] = '\0';
970 ctx->scratch->ptr1 = mdep;
971 return (SNMP_ERR_NOERROR);
973 case SNMP_OP_ROLLBACK:
975 return (SNMP_ERR_NOERROR);
983 case LEAF_begemotSnmpdModulePath:
984 return (string_get(value, m->path, -1));
986 case LEAF_begemotSnmpdModuleComment:
987 return (string_get(value, m->config->comment, -1));
993 op_snmp_set(struct snmp_context *ctx __unused, struct snmp_value *value,
994 u_int sub, u_int iidx __unused, enum snmp_op op)
998 case SNMP_OP_GETNEXT:
1002 switch (value->var.subs[sub - 1]) {
1004 case LEAF_snmpSetSerialNo:
1005 value->v.integer = snmp_serial_no;
1011 return (SNMP_ERR_NOERROR);
1014 switch (value->var.subs[sub - 1]) {
1016 case LEAF_snmpSetSerialNo:
1017 if (value->v.integer != snmp_serial_no)
1018 return (SNMP_ERR_INCONS_VALUE);
1024 return (SNMP_ERR_NOERROR);
1026 case SNMP_OP_ROLLBACK:
1027 return (SNMP_ERR_NOERROR);
1029 case SNMP_OP_COMMIT:
1030 if (snmp_serial_no++ == 2147483647)
1032 return (SNMP_ERR_NOERROR);
1041 op_snmp_engine(struct snmp_context *ctx __unused, struct snmp_value *value,
1042 u_int sub, u_int iidx __unused, enum snmp_op op)
1044 asn_subid_t which = value->var.subs[sub - 1];
1047 case SNMP_OP_GETNEXT:
1054 if (community != COMM_INITIALIZE)
1055 return (SNMP_ERR_NOT_WRITEABLE);
1057 case LEAF_snmpEngineID:
1058 if (value->v.octetstring.len > SNMP_ENGINE_ID_SIZ)
1059 return (SNMP_ERR_WRONG_VALUE);
1060 ctx->scratch->ptr1 = malloc(snmpd_engine.engine_len);
1061 if (ctx->scratch->ptr1 == NULL)
1062 return (SNMP_ERR_GENERR);
1063 memcpy(ctx->scratch->ptr1, snmpd_engine.engine_id,
1064 snmpd_engine.engine_len);
1065 ctx->scratch->int1 = snmpd_engine.engine_len;
1066 snmpd_engine.engine_len = value->v.octetstring.len;
1067 memcpy(snmpd_engine.engine_id,
1068 value->v.octetstring.octets,
1069 value->v.octetstring.len);
1072 case LEAF_snmpEngineMaxMessageSize:
1073 ctx->scratch->int1 = snmpd_engine.max_msg_size;
1074 snmpd_engine.max_msg_size = value->v.integer;
1078 return (SNMP_ERR_NOT_WRITEABLE);
1080 return (SNMP_ERR_NOERROR);
1082 case SNMP_OP_ROLLBACK:
1084 case LEAF_snmpEngineID:
1085 snmpd_engine.engine_len = ctx->scratch->int1;
1086 memcpy(snmpd_engine.engine_id, ctx->scratch->ptr1,
1087 snmpd_engine.engine_len);
1088 free(ctx->scratch->ptr1);
1091 case LEAF_snmpEngineMaxMessageSize:
1092 snmpd_engine.max_msg_size = ctx->scratch->int1;
1098 return (SNMP_ERR_NOERROR);
1100 case SNMP_OP_COMMIT:
1101 if (which == LEAF_snmpEngineID) {
1102 if (set_snmpd_engine() < 0) {
1103 snmpd_engine.engine_len = ctx->scratch->int1;
1104 memcpy(snmpd_engine.engine_id,
1105 ctx->scratch->ptr1, ctx->scratch->int1);
1107 free(ctx->scratch->ptr1);
1109 return (SNMP_ERR_NOERROR);
1114 case LEAF_snmpEngineID:
1115 return (string_get(value, snmpd_engine.engine_id,
1116 snmpd_engine.engine_len));
1117 case LEAF_snmpEngineBoots:
1118 value->v.integer = snmpd_engine.engine_boots;
1120 case LEAF_snmpEngineTime:
1121 snmpd_engine.engine_time = (get_ticks() - start_tick) / 100ULL;
1122 value->v.integer = snmpd_engine.engine_time;
1124 case LEAF_snmpEngineMaxMessageSize:
1125 value->v.integer = snmpd_engine.max_msg_size;
1128 return (SNMP_ERR_NOSUCHNAME);
1131 return (SNMP_ERR_NOERROR);
1138 op_transport_table(struct snmp_context *ctx __unused, struct snmp_value *value,
1139 u_int sub, u_int iidx, enum snmp_op op)
1141 asn_subid_t which = value->var.subs[sub - 1];
1142 struct transport *t;
1143 u_char *tname, *ptr;
1148 case SNMP_OP_GETNEXT:
1149 if ((t = NEXT_OBJECT_OID(&transport_list, &value->var, sub))
1151 return (SNMP_ERR_NOSUCHNAME);
1152 index_append(&value->var, sub, &t->index);
1156 if ((t = FIND_OBJECT_OID(&transport_list, &value->var, sub))
1158 return (SNMP_ERR_NOSUCHNAME);
1162 t = FIND_OBJECT_OID(&transport_list, &value->var, sub);
1163 if (which != LEAF_begemotSnmpdTransportStatus) {
1165 return (SNMP_ERR_NO_CREATION);
1166 return (SNMP_ERR_NOT_WRITEABLE);
1169 /* the errors in the next few statements can only happen when
1170 * t is NULL, hence the NO_CREATION error. */
1171 if (index_decode(&value->var, sub, iidx,
1173 return (SNMP_ERR_NO_CREATION);
1175 /* check the section name */
1176 if (tnamelen >= TRANS_NAMELEN || tnamelen == 0) {
1178 return (SNMP_ERR_NO_CREATION);
1180 for (ptr = tname; ptr < tname + tnamelen; ptr++) {
1181 if (!isascii(*ptr) || !isalnum(*ptr)) {
1183 return (SNMP_ERR_NO_CREATION);
1188 return (SNMP_ERR_NOT_WRITEABLE);
1190 case SNMP_OP_ROLLBACK:
1191 case SNMP_OP_COMMIT:
1192 return (SNMP_ERR_NOERROR);
1199 case LEAF_begemotSnmpdTransportStatus:
1200 value->v.integer = 1;
1203 case LEAF_begemotSnmpdTransportOid:
1204 memcpy(&value->v.oid, &t->vtab->id, sizeof(t->vtab->id));
1207 return (SNMP_ERR_NOERROR);