1122394Sharti/*
2122394Sharti * Copyright (c) 2001-2003
3122394Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4122394Sharti *	All rights reserved.
5163820Sharti * Copyright (c) 2004-2006
6163820Sharti *	Hartmut Brandt.
7163820Sharti *	All rights reserved.
8122394Sharti *
9122394Sharti * Author: Harti Brandt <harti@freebsd.org>
10133211Sharti *
11133211Sharti * Redistribution and use in source and binary forms, with or without
12133211Sharti * modification, are permitted provided that the following conditions
13133211Sharti * are met:
14133211Sharti * 1. Redistributions of source code must retain the above copyright
15133211Sharti *    notice, this list of conditions and the following disclaimer.
16122394Sharti * 2. Redistributions in binary form must reproduce the above copyright
17122394Sharti *    notice, this list of conditions and the following disclaimer in the
18122394Sharti *    documentation and/or other materials provided with the distribution.
19133211Sharti *
20133211Sharti * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21133211Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22133211Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23133211Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
24133211Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25133211Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26133211Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27133211Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28133211Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29133211Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30133211Sharti * SUCH DAMAGE.
31122394Sharti *
32163820Sharti * $Begemot: action.c 517 2006-10-31 08:52:04Z brandt_h $
33122394Sharti *
34122394Sharti * Variable access for SNMPd
35122394Sharti */
36122394Sharti#include <sys/types.h>
37216294Ssyrinx#include <sys/queue.h>
38122394Sharti#include <sys/sysctl.h>
39122394Sharti#include <sys/un.h>
40163820Sharti#include <sys/utsname.h>
41122394Sharti#include <stdio.h>
42122394Sharti#include <stdlib.h>
43122394Sharti#include <stdarg.h>
44122394Sharti#include <string.h>
45122394Sharti#include <ctype.h>
46216294Ssyrinx#include <errno.h>
47122394Sharti#include <syslog.h>
48122394Sharti
49122394Sharti#include "snmpmod.h"
50122394Sharti#include "snmpd.h"
51122394Sharti#include "tree.h"
52122394Sharti#include "oid.h"
53122394Sharti
54122394Shartistatic const struct asn_oid
55122394Sharti	oid_begemotSnmpdModuleTable = OIDX_begemotSnmpdModuleTable;
56122394Sharti
57163820Sharti#ifdef __FreeBSD__
58163820Shartistatic const struct asn_oid
59163820Sharti	oid_freeBSDVersion = OIDX_freeBSDVersion;
60163820Sharti#endif
61163820Sharti
62122394Sharti/*
63122394Sharti * Get a string value from the KERN sysctl subtree.
64122394Sharti */
65122394Shartistatic char *
66122394Shartiact_getkernstring(int id)
67122394Sharti{
68122394Sharti	int mib[2];
69122394Sharti	size_t len;
70122394Sharti	char *string;
71122394Sharti
72122394Sharti	mib[0] = CTL_KERN;
73122394Sharti	mib[1] = id;
74122394Sharti	if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0)
75122394Sharti		return (NULL);
76122394Sharti	if ((string = malloc(len)) == NULL)
77122394Sharti		return (NULL);
78122394Sharti	if (sysctl(mib, 2, string, &len, NULL, 0) != 0) {
79122394Sharti		free(string);
80122394Sharti		return (NULL);
81122394Sharti	}
82122394Sharti	return (string);
83122394Sharti}
84122394Sharti
85122394Sharti/*
86122394Sharti * Get an integer value from the KERN sysctl subtree.
87122394Sharti */
88122394Shartistatic char *
89122394Shartiact_getkernint(int id)
90122394Sharti{
91122394Sharti	int mib[2];
92122394Sharti	size_t len;
93122394Sharti	u_long value;
94122394Sharti	char *string;
95122394Sharti
96122394Sharti	mib[0] = CTL_KERN;
97122394Sharti	mib[1] = id;
98122394Sharti	len = sizeof(value);
99122394Sharti	if (sysctl(mib, 2, &value, &len, NULL, 0) != 0)
100122394Sharti		return (NULL);
101122394Sharti
102122394Sharti	if ((string = malloc(20)) == NULL)
103122394Sharti		return (NULL);
104122394Sharti	sprintf(string, "%lu", value);
105122394Sharti	return (string);
106122394Sharti}
107122394Sharti
108122394Sharti/*
109122394Sharti * Initialize global variables of the system group.
110122394Sharti */
111122394Shartiint
112122394Shartiinit_actvals(void)
113122394Sharti{
114163820Sharti	struct utsname uts;
115163820Sharti	char *hostid;
116122394Sharti	size_t len;
117163820Sharti#ifdef __FreeBSD__
118163820Sharti	char *rel, *p, *end;
119163820Sharti	u_long num;
120163820Sharti#endif
121122394Sharti
122163820Sharti	if (uname(&uts) == -1)
123122394Sharti		return (-1);
124122394Sharti
125163820Sharti	if ((systemg.name = strdup(uts.nodename)) == NULL)
126163820Sharti		return (-1);
127122394Sharti
128163820Sharti	if ((hostid = act_getkernint(KERN_HOSTID)) == NULL)
129163820Sharti		return (-1);
130122394Sharti
131163820Sharti	len = strlen(uts.nodename) + 1;
132163820Sharti	len += strlen(hostid) + 1;
133163820Sharti	len += strlen(uts.sysname) + 1;
134163820Sharti	len += strlen(uts.release) + 1;
135122394Sharti
136163820Sharti	if ((systemg.descr = malloc(len)) == NULL) {
137163820Sharti		free(hostid);
138163820Sharti		return (-1);
139163820Sharti	}
140163820Sharti	sprintf(systemg.descr, "%s %s %s %s", uts.nodename, hostid, uts.sysname,
141163820Sharti	    uts.release);
142122394Sharti
143163820Sharti#ifdef __FreeBSD__
144163820Sharti	/*
145163820Sharti	 * Construct a FreeBSD oid
146163820Sharti	 */
147163820Sharti	systemg.object_id = oid_freeBSDVersion;
148163820Sharti	rel = uts.release;
149163820Sharti	while ((p = strsep(&rel, ".")) != NULL &&
150163820Sharti	    systemg.object_id.len < ASN_MAXOIDLEN) {
151163820Sharti		systemg.object_id.subs[systemg.object_id.len] = 0;
152163820Sharti		if (*p != '\0') {
153163820Sharti			num = strtoul(p, &end, 10);
154163820Sharti			if (end == p)
155163820Sharti				break;
156163820Sharti			systemg.object_id.subs[systemg.object_id.len] = num;
157163820Sharti		}
158163820Sharti		systemg.object_id.len++;
159163820Sharti	}
160163820Sharti#endif
161163820Sharti
162163820Sharti	free(hostid);
163163820Sharti
164122394Sharti	return (0);
165122394Sharti}
166122394Sharti
167216294Ssyrinx/*
168216294Ssyrinx * Initialize global variables of the snmpEngine group.
169216294Ssyrinx */
170216294Ssyrinxint
171216294Ssyrinxinit_snmpd_engine(void)
172216294Ssyrinx{
173216294Ssyrinx	char *hostid;
174122394Sharti
175216294Ssyrinx	snmpd_engine.engine_boots = 1;
176216294Ssyrinx	snmpd_engine.engine_time = 1;
177216294Ssyrinx	snmpd_engine.max_msg_size = 1500; /* XXX */
178122394Sharti
179216294Ssyrinx	snmpd_engine.engine_id[0] = ((OID_freeBSD & 0xff000000) >> 24) | 0x80;
180216294Ssyrinx	snmpd_engine.engine_id[1] = (OID_freeBSD & 0xff0000) >> 16;
181216294Ssyrinx	snmpd_engine.engine_id[2] = (OID_freeBSD & 0xff00) >> 8;
182216294Ssyrinx	snmpd_engine.engine_id[3] = OID_freeBSD & 0xff;
183216294Ssyrinx	snmpd_engine.engine_id[4] = 128;
184216294Ssyrinx	snmpd_engine.engine_len = 5;
185216294Ssyrinx
186216294Ssyrinx	if ((hostid = act_getkernint(KERN_HOSTID)) == NULL)
187216294Ssyrinx		return (-1);
188216294Ssyrinx
189216294Ssyrinx	if (strlen(hostid) > SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len) {
190216294Ssyrinx		memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len,
191216294Ssyrinx		    hostid, SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len);
192216294Ssyrinx		snmpd_engine.engine_len = SNMP_ENGINE_ID_SIZ;
193216294Ssyrinx	} else {
194216294Ssyrinx		memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len,
195216294Ssyrinx		    hostid, strlen(hostid));
196216294Ssyrinx		snmpd_engine.engine_len += strlen(hostid);
197216294Ssyrinx	}
198216294Ssyrinx
199216294Ssyrinx	free(hostid);
200216294Ssyrinx
201216294Ssyrinx	return (0);
202216294Ssyrinx}
203216294Ssyrinx
204216294Ssyrinxint
205216294Ssyrinxset_snmpd_engine(void)
206216294Ssyrinx{
207216294Ssyrinx	FILE *fp;
208216294Ssyrinx	uint32_t i;
209216294Ssyrinx	uint8_t *cptr, engine[2 * SNMP_ENGINE_ID_SIZ + 2];
210216294Ssyrinx	uint8_t myengine[2 * SNMP_ENGINE_ID_SIZ + 2];
211216294Ssyrinx
212216294Ssyrinx	if (engine_file[0] == '\0')
213216294Ssyrinx		return (-1);
214216294Ssyrinx
215216294Ssyrinx	cptr = myengine;
216216294Ssyrinx	for (i = 0; i < snmpd_engine.engine_len; i++)
217216294Ssyrinx		cptr += sprintf(cptr, "%.2x", snmpd_engine.engine_id[i]);
218216294Ssyrinx	*cptr++ = '\n';
219216294Ssyrinx	*cptr++ = '\0';
220216294Ssyrinx
221216294Ssyrinx	if ((fp = fopen(engine_file, "r+")) != NULL) {
222216294Ssyrinx		if (fgets(engine, sizeof(engine) - 1, fp) == NULL ||
223216294Ssyrinx		    fscanf(fp, "%u",  &snmpd_engine.engine_boots) <= 0) {
224216294Ssyrinx			fclose(fp);
225216294Ssyrinx			goto save_boots;
226216294Ssyrinx		}
227216294Ssyrinx
228216294Ssyrinx		fclose(fp);
229216294Ssyrinx		if (strcmp(myengine, engine) != 0)
230216294Ssyrinx			snmpd_engine.engine_boots = 1;
231216294Ssyrinx		else
232216294Ssyrinx			snmpd_engine.engine_boots++;
233216294Ssyrinx	} else if (errno != ENOENT)
234216294Ssyrinx		return (-1);
235216294Ssyrinx
236216294Ssyrinxsave_boots:
237216294Ssyrinx	if ((fp = fopen(engine_file, "w+")) == NULL)
238216294Ssyrinx		return (-1);
239216294Ssyrinx	fprintf(fp, "%s%u\n", myengine, snmpd_engine.engine_boots);
240216294Ssyrinx	fclose(fp);
241216294Ssyrinx
242216294Ssyrinx	return (0);
243216294Ssyrinx}
244216294Ssyrinx
245122394Sharti/*************************************************************
246122394Sharti *
247122394Sharti * System group
248122394Sharti */
249122394Shartiint
250122394Shartiop_system_group(struct snmp_context *ctx, struct snmp_value *value,
251122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
252122394Sharti{
253122394Sharti	asn_subid_t which = value->var.subs[sub - 1];
254122394Sharti
255122394Sharti	switch (op) {
256122394Sharti
257122394Sharti	  case SNMP_OP_GETNEXT:
258122394Sharti		abort();
259122394Sharti
260122394Sharti	  case SNMP_OP_GET:
261122394Sharti		break;
262122394Sharti
263122394Sharti	  case SNMP_OP_SET:
264122394Sharti		switch (which) {
265122394Sharti
266122394Sharti		  case LEAF_sysDescr:
267122394Sharti			if (community != COMM_INITIALIZE)
268122394Sharti				return (SNMP_ERR_NOT_WRITEABLE);
269122394Sharti			return (string_save(value, ctx, -1, &systemg.descr));
270122394Sharti
271122394Sharti		  case LEAF_sysObjectId:
272122394Sharti			if (community != COMM_INITIALIZE)
273122394Sharti				return (SNMP_ERR_NOT_WRITEABLE);
274122394Sharti			return (oid_save(value, ctx, &systemg.object_id));
275122394Sharti
276122394Sharti		  case LEAF_sysContact:
277122394Sharti			return (string_save(value, ctx, -1, &systemg.contact));
278122394Sharti
279122394Sharti		  case LEAF_sysName:
280122394Sharti			return (string_save(value, ctx, -1, &systemg.name));
281122394Sharti
282122394Sharti		  case LEAF_sysLocation:
283122394Sharti			return (string_save(value, ctx, -1, &systemg.location));
284122394Sharti		}
285122394Sharti		return (SNMP_ERR_NO_CREATION);
286122394Sharti
287122394Sharti	  case SNMP_OP_ROLLBACK:
288122394Sharti		switch (which) {
289122394Sharti
290122394Sharti		  case LEAF_sysDescr:
291122394Sharti			string_rollback(ctx, &systemg.descr);
292122394Sharti			return (SNMP_ERR_NOERROR);
293122394Sharti		  case LEAF_sysObjectId:
294122394Sharti			oid_rollback(ctx, &systemg.object_id);
295122394Sharti			return (SNMP_ERR_NOERROR);
296122394Sharti		  case LEAF_sysContact:
297122394Sharti			string_rollback(ctx, &systemg.contact);
298122394Sharti			return (SNMP_ERR_NOERROR);
299122394Sharti		  case LEAF_sysName:
300122394Sharti			string_rollback(ctx, &systemg.name);
301122394Sharti			return (SNMP_ERR_NOERROR);
302122394Sharti		  case LEAF_sysLocation:
303122394Sharti			string_rollback(ctx, &systemg.location);
304122394Sharti			return (SNMP_ERR_NOERROR);
305122394Sharti		}
306122394Sharti		abort();
307122394Sharti
308122394Sharti	  case SNMP_OP_COMMIT:
309122394Sharti		switch (which) {
310122394Sharti
311122394Sharti		  case LEAF_sysDescr:
312122394Sharti			string_commit(ctx);
313122394Sharti			return (SNMP_ERR_NOERROR);
314122394Sharti		  case LEAF_sysObjectId:
315122394Sharti			oid_commit(ctx);
316122394Sharti			return (SNMP_ERR_NOERROR);
317122394Sharti		  case LEAF_sysContact:
318122394Sharti			string_commit(ctx);
319122394Sharti			return (SNMP_ERR_NOERROR);
320122394Sharti		  case LEAF_sysName:
321122394Sharti			string_commit(ctx);
322122394Sharti			return (SNMP_ERR_NOERROR);
323122394Sharti		  case LEAF_sysLocation:
324122394Sharti			string_commit(ctx);
325122394Sharti			return (SNMP_ERR_NOERROR);
326122394Sharti		}
327122394Sharti		abort();
328122394Sharti	}
329122394Sharti
330122394Sharti	/*
331122394Sharti	 * Come here for GET.
332122394Sharti	 */
333122394Sharti	switch (which) {
334122394Sharti
335122394Sharti	  case LEAF_sysDescr:
336122394Sharti		return (string_get(value, systemg.descr, -1));
337122394Sharti	  case LEAF_sysObjectId:
338122394Sharti		return (oid_get(value, &systemg.object_id));
339122394Sharti	  case LEAF_sysUpTime:
340122394Sharti		value->v.uint32 = get_ticks() - start_tick;
341122394Sharti		break;
342122394Sharti	  case LEAF_sysContact:
343122394Sharti		return (string_get(value, systemg.contact, -1));
344122394Sharti	  case LEAF_sysName:
345122394Sharti		return (string_get(value, systemg.name, -1));
346122394Sharti	  case LEAF_sysLocation:
347122394Sharti		return (string_get(value, systemg.location, -1));
348122394Sharti	  case LEAF_sysServices:
349122394Sharti		value->v.integer = systemg.services;
350122394Sharti		break;
351122394Sharti	  case LEAF_sysORLastChange:
352122394Sharti		value->v.uint32 = systemg.or_last_change;
353122394Sharti		break;
354122394Sharti	}
355122394Sharti	return (SNMP_ERR_NOERROR);
356122394Sharti}
357122394Sharti
358122394Sharti/*************************************************************
359122394Sharti *
360122394Sharti * Debug group
361122394Sharti */
362122394Shartiint
363122394Shartiop_debug(struct snmp_context *ctx, struct snmp_value *value, u_int sub,
364122394Sharti    u_int iidx __unused, enum snmp_op op)
365122394Sharti{
366122394Sharti	asn_subid_t which = value->var.subs[sub - 1];
367122394Sharti
368122394Sharti	switch (op) {
369122394Sharti
370122394Sharti	  case SNMP_OP_GETNEXT:
371122394Sharti		abort();
372122394Sharti
373122394Sharti	  case SNMP_OP_GET:
374122394Sharti		switch (which) {
375122394Sharti
376122394Sharti		  case LEAF_begemotSnmpdDebugDumpPdus:
377122394Sharti			value->v.integer = TRUTH_MK(debug.dump_pdus);
378122394Sharti			break;
379122394Sharti
380122394Sharti		  case LEAF_begemotSnmpdDebugSnmpTrace:
381122394Sharti			value->v.uint32 = snmp_trace;
382122394Sharti			break;
383122394Sharti
384122394Sharti		  case LEAF_begemotSnmpdDebugSyslogPri:
385122394Sharti			value->v.integer = debug.logpri;
386122394Sharti			break;
387122394Sharti		}
388122394Sharti		return (SNMP_ERR_NOERROR);
389122394Sharti
390122394Sharti	  case SNMP_OP_SET:
391122394Sharti		switch (which) {
392122394Sharti
393122394Sharti		  case LEAF_begemotSnmpdDebugDumpPdus:
394122394Sharti			if (!TRUTH_OK(value->v.integer))
395122394Sharti				return (SNMP_ERR_WRONG_VALUE);
396122394Sharti			ctx->scratch->int1 = debug.dump_pdus;
397122394Sharti			debug.dump_pdus = TRUTH_GET(value->v.integer);
398122394Sharti			return (SNMP_ERR_NOERROR);
399122394Sharti
400122394Sharti		  case LEAF_begemotSnmpdDebugSnmpTrace:
401122394Sharti			ctx->scratch->int1 = snmp_trace;
402122394Sharti			snmp_trace = value->v.uint32;
403122394Sharti			return (SNMP_ERR_NOERROR);
404122394Sharti
405122394Sharti		  case LEAF_begemotSnmpdDebugSyslogPri:
406122394Sharti			if (value->v.integer < 0 || value->v.integer > 8)
407122394Sharti				return (SNMP_ERR_WRONG_VALUE);
408122394Sharti			ctx->scratch->int1 = debug.logpri;
409122394Sharti			debug.logpri = (u_int)value->v.integer;
410122394Sharti			return (SNMP_ERR_NOERROR);
411122394Sharti		}
412122394Sharti		return (SNMP_ERR_NO_CREATION);
413122394Sharti
414122394Sharti	  case SNMP_OP_ROLLBACK:
415122394Sharti		switch (which) {
416122394Sharti
417122394Sharti		  case LEAF_begemotSnmpdDebugDumpPdus:
418122394Sharti			debug.dump_pdus = ctx->scratch->int1;
419122394Sharti			return (SNMP_ERR_NOERROR);
420122394Sharti
421122394Sharti		  case LEAF_begemotSnmpdDebugSnmpTrace:
422122394Sharti			snmp_trace = ctx->scratch->int1;
423122394Sharti			return (SNMP_ERR_NOERROR);
424122394Sharti
425122394Sharti		  case LEAF_begemotSnmpdDebugSyslogPri:
426122394Sharti			debug.logpri = ctx->scratch->int1;
427122394Sharti			return (SNMP_ERR_NOERROR);
428122394Sharti		}
429122394Sharti		abort();
430122394Sharti
431122394Sharti	  case SNMP_OP_COMMIT:
432122394Sharti		switch (which) {
433122394Sharti
434122394Sharti		  case LEAF_begemotSnmpdDebugDumpPdus:
435122394Sharti		  case LEAF_begemotSnmpdDebugSnmpTrace:
436122394Sharti			return (SNMP_ERR_NOERROR);
437122394Sharti
438122394Sharti		  case LEAF_begemotSnmpdDebugSyslogPri:
439122394Sharti			if (debug.logpri == 0)
440122394Sharti				setlogmask(0);
441122394Sharti			else
442122394Sharti				setlogmask(LOG_UPTO(debug.logpri - 1));
443122394Sharti			return (SNMP_ERR_NOERROR);
444122394Sharti		}
445122394Sharti		abort();
446122394Sharti	}
447122394Sharti	abort();
448122394Sharti}
449122394Sharti
450122394Sharti/*************************************************************
451122394Sharti *
452122394Sharti * OR Table
453122394Sharti */
454122394Shartiint
455122394Shartiop_or_table(struct snmp_context *ctx __unused, struct snmp_value *value,
456122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
457122394Sharti{
458122394Sharti	struct objres *objres;
459122394Sharti
460122394Sharti	switch (op) {
461122394Sharti
462122394Sharti	  case SNMP_OP_GETNEXT:
463122394Sharti		if ((objres = NEXT_OBJECT_INT(&objres_list, &value->var, sub))
464122394Sharti		    == NULL)
465122394Sharti			return (SNMP_ERR_NOSUCHNAME);
466122394Sharti		value->var.subs[sub] = objres->index;
467122394Sharti		value->var.len = sub + 1;
468122394Sharti		break;
469122394Sharti
470122394Sharti	  case SNMP_OP_GET:
471122394Sharti		if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub))
472122394Sharti		    == NULL)
473122394Sharti			return (SNMP_ERR_NOSUCHNAME);
474122394Sharti		break;
475122394Sharti
476122394Sharti	  case SNMP_OP_SET:
477122394Sharti		if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub))
478122394Sharti		    == NULL)
479122394Sharti			return (SNMP_ERR_NO_CREATION);
480122394Sharti		return (SNMP_ERR_NOT_WRITEABLE);
481122394Sharti
482122394Sharti	  case SNMP_OP_ROLLBACK:
483122394Sharti	  case SNMP_OP_COMMIT:
484122394Sharti	  default:
485122394Sharti		abort();
486122394Sharti	}
487122394Sharti
488122394Sharti	/*
489122394Sharti	 * Come here for GET, GETNEXT.
490122394Sharti	 */
491122394Sharti	switch (value->var.subs[sub - 1]) {
492122394Sharti
493122394Sharti	  case LEAF_sysORID:
494122394Sharti		value->v.oid = objres->oid;
495122394Sharti		break;
496122394Sharti
497122394Sharti	  case LEAF_sysORDescr:
498122394Sharti		return (string_get(value, objres->descr, -1));
499122394Sharti
500122394Sharti	  case LEAF_sysORUpTime:
501122394Sharti		value->v.uint32 = objres->uptime;
502122394Sharti		break;
503122394Sharti	}
504122394Sharti	return (SNMP_ERR_NOERROR);
505122394Sharti}
506122394Sharti
507122394Sharti/*************************************************************
508122394Sharti *
509122394Sharti * mib-2 snmp
510122394Sharti */
511122394Shartiint
512122394Shartiop_snmp(struct snmp_context *ctx, struct snmp_value *value,
513122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
514122394Sharti{
515122394Sharti	switch (op) {
516122394Sharti
517122394Sharti	  case SNMP_OP_GETNEXT:
518122394Sharti		abort();
519122394Sharti
520122394Sharti	  case SNMP_OP_GET:
521122394Sharti		switch (value->var.subs[sub - 1]) {
522122394Sharti
523122394Sharti		  case LEAF_snmpInPkts:
524122394Sharti			value->v.uint32 = snmpd_stats.inPkts;
525122394Sharti			break;
526122394Sharti
527122394Sharti		  case LEAF_snmpInBadVersions:
528122394Sharti			value->v.uint32 = snmpd_stats.inBadVersions;
529122394Sharti			break;
530122394Sharti
531122394Sharti		  case LEAF_snmpInBadCommunityNames:
532122394Sharti			value->v.uint32 = snmpd_stats.inBadCommunityNames;
533122394Sharti			break;
534122394Sharti
535122394Sharti		  case LEAF_snmpInBadCommunityUses:
536122394Sharti			value->v.uint32 = snmpd_stats.inBadCommunityUses;
537122394Sharti			break;
538122394Sharti
539122394Sharti		  case LEAF_snmpInASNParseErrs:
540122394Sharti			value->v.uint32 = snmpd_stats.inASNParseErrs;
541122394Sharti			break;
542122394Sharti
543122394Sharti		  case LEAF_snmpEnableAuthenTraps:
544122394Sharti			value->v.integer = TRUTH_MK(snmpd.auth_traps);
545122394Sharti			break;
546122394Sharti
547122394Sharti		  case LEAF_snmpSilentDrops:
548122394Sharti			value->v.uint32 = snmpd_stats.silentDrops;
549122394Sharti			break;
550122394Sharti
551122394Sharti		  case LEAF_snmpProxyDrops:
552122394Sharti			value->v.uint32 = snmpd_stats.proxyDrops;
553122394Sharti			break;
554122394Sharti
555122394Sharti		  default:
556122394Sharti			return (SNMP_ERR_NOSUCHNAME);
557122394Sharti
558122394Sharti		}
559122394Sharti		return (SNMP_ERR_NOERROR);
560122394Sharti
561122394Sharti	  case SNMP_OP_SET:
562122394Sharti		switch (value->var.subs[sub - 1]) {
563122394Sharti		  case LEAF_snmpEnableAuthenTraps:
564122394Sharti			if (!TRUTH_OK(value->v.integer))
565122394Sharti				return (SNMP_ERR_WRONG_VALUE);
566122394Sharti			ctx->scratch->int1 = value->v.integer;
567122394Sharti			snmpd.auth_traps = TRUTH_GET(value->v.integer);
568122394Sharti			return (SNMP_ERR_NOERROR);
569122394Sharti		}
570122394Sharti		abort();
571122394Sharti
572122394Sharti	  case SNMP_OP_ROLLBACK:
573122394Sharti		switch (value->var.subs[sub - 1]) {
574122394Sharti		  case LEAF_snmpEnableAuthenTraps:
575122394Sharti			snmpd.auth_traps = ctx->scratch->int1;
576122394Sharti			return (SNMP_ERR_NOERROR);
577122394Sharti		}
578122394Sharti		abort();
579122394Sharti
580122394Sharti	  case SNMP_OP_COMMIT:
581122394Sharti		switch (value->var.subs[sub - 1]) {
582122394Sharti		  case LEAF_snmpEnableAuthenTraps:
583122394Sharti			return (SNMP_ERR_NOERROR);
584122394Sharti		}
585122394Sharti		abort();
586122394Sharti	}
587122394Sharti	abort();
588122394Sharti}
589122394Sharti
590122394Sharti/*************************************************************
591122394Sharti *
592122394Sharti * SNMPd statistics group
593122394Sharti */
594122394Shartiint
595122394Shartiop_snmpd_stats(struct snmp_context *ctx __unused, struct snmp_value *value,
596122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
597122394Sharti{
598122394Sharti	switch (op) {
599122394Sharti
600122394Sharti	  case SNMP_OP_GET:
601122394Sharti		switch (value->var.subs[sub - 1]) {
602122394Sharti
603122394Sharti		  case LEAF_begemotSnmpdStatsNoRxBufs:
604122394Sharti			value->v.uint32 = snmpd_stats.noRxbuf;
605122394Sharti			break;
606122394Sharti
607122394Sharti		  case LEAF_begemotSnmpdStatsNoTxBufs:
608122394Sharti			value->v.uint32 = snmpd_stats.noTxbuf;
609122394Sharti			break;
610122394Sharti
611122394Sharti		  case LEAF_begemotSnmpdStatsInTooLongPkts:
612122394Sharti			value->v.uint32 = snmpd_stats.inTooLong;
613122394Sharti			break;
614122394Sharti
615122394Sharti		  case LEAF_begemotSnmpdStatsInBadPduTypes:
616122394Sharti			value->v.uint32 = snmpd_stats.inBadPduTypes;
617122394Sharti			break;
618122394Sharti
619122394Sharti		  default:
620122394Sharti			return (SNMP_ERR_NOSUCHNAME);
621122394Sharti		}
622122394Sharti		return (SNMP_ERR_NOERROR);
623122394Sharti
624122394Sharti	  case SNMP_OP_SET:
625122394Sharti	  case SNMP_OP_ROLLBACK:
626122394Sharti	  case SNMP_OP_COMMIT:
627122394Sharti	  case SNMP_OP_GETNEXT:
628122394Sharti		abort();
629122394Sharti	}
630122394Sharti	abort();
631122394Sharti}
632122394Sharti
633122394Sharti/*
634122394Sharti * SNMPd configuration scalars
635122394Sharti */
636122394Shartiint
637122394Shartiop_snmpd_config(struct snmp_context *ctx, struct snmp_value *value,
638122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
639122394Sharti{
640122394Sharti	asn_subid_t which = value->var.subs[sub - 1];
641122394Sharti
642122394Sharti	switch (op) {
643122394Sharti
644122394Sharti	  case SNMP_OP_GETNEXT:
645122394Sharti		abort();
646122394Sharti
647122394Sharti	  case SNMP_OP_GET:
648122394Sharti		switch (which) {
649122394Sharti
650122394Sharti		  case LEAF_begemotSnmpdTransmitBuffer:
651122394Sharti			value->v.integer = snmpd.txbuf;
652122394Sharti			break;
653122394Sharti		  case LEAF_begemotSnmpdReceiveBuffer:
654122394Sharti			value->v.integer = snmpd.rxbuf;
655122394Sharti			break;
656122394Sharti		  case LEAF_begemotSnmpdCommunityDisable:
657122394Sharti			value->v.integer = TRUTH_MK(snmpd.comm_dis);
658122394Sharti			break;
659122394Sharti		  case LEAF_begemotSnmpdTrap1Addr:
660122394Sharti			return (ip_get(value, snmpd.trap1addr));
661124861Sharti		  case LEAF_begemotSnmpdVersionEnable:
662124861Sharti			value->v.uint32 = snmpd.version_enable;
663124861Sharti			break;
664122394Sharti		  default:
665122394Sharti			return (SNMP_ERR_NOSUCHNAME);
666122394Sharti		}
667122394Sharti		return (SNMP_ERR_NOERROR);
668122394Sharti
669122394Sharti	  case SNMP_OP_SET:
670122394Sharti		switch (which) {
671122394Sharti
672122394Sharti		  case LEAF_begemotSnmpdTransmitBuffer:
673122394Sharti			ctx->scratch->int1 = snmpd.txbuf;
674122394Sharti			if (value->v.integer < 484 ||
675122394Sharti			    value->v.integer > 65535)
676122394Sharti				return (SNMP_ERR_WRONG_VALUE);
677122394Sharti			snmpd.txbuf = value->v.integer;
678122394Sharti			return (SNMP_ERR_NOERROR);
679122394Sharti
680122394Sharti		  case LEAF_begemotSnmpdReceiveBuffer:
681122394Sharti			ctx->scratch->int1 = snmpd.rxbuf;
682122394Sharti			if (value->v.integer < 484 ||
683122394Sharti			    value->v.integer > 65535)
684122394Sharti				return (SNMP_ERR_WRONG_VALUE);
685122394Sharti			snmpd.rxbuf = value->v.integer;
686122394Sharti			return (SNMP_ERR_NOERROR);
687122394Sharti
688122394Sharti		  case LEAF_begemotSnmpdCommunityDisable:
689122394Sharti			ctx->scratch->int1 = snmpd.comm_dis;
690122394Sharti			if (!TRUTH_OK(value->v.integer))
691122394Sharti				return (SNMP_ERR_WRONG_VALUE);
692122394Sharti			if (TRUTH_GET(value->v.integer)) {
693122394Sharti				snmpd.comm_dis = 1;
694122394Sharti			} else {
695122394Sharti				if (snmpd.comm_dis)
696122394Sharti					return (SNMP_ERR_WRONG_VALUE);
697122394Sharti			}
698122394Sharti			return (SNMP_ERR_NOERROR);
699122394Sharti
700122394Sharti		  case LEAF_begemotSnmpdTrap1Addr:
701122394Sharti			return (ip_save(value, ctx, snmpd.trap1addr));
702124861Sharti
703124861Sharti		  case LEAF_begemotSnmpdVersionEnable:
704124861Sharti			if (community != COMM_INITIALIZE)
705124861Sharti				return (SNMP_ERR_NOT_WRITEABLE);
706124861Sharti			ctx->scratch->int1 = snmpd.version_enable;
707124861Sharti			if (value->v.uint32 == 0 ||
708124861Sharti			    (value->v.uint32 & ~VERS_ENABLE_ALL))
709124861Sharti				return (SNMP_ERR_WRONG_VALUE);
710124861Sharti			snmpd.version_enable = value->v.uint32;
711124861Sharti			return (SNMP_ERR_NOERROR);
712122394Sharti		}
713122394Sharti		abort();
714122394Sharti
715122394Sharti	  case SNMP_OP_ROLLBACK:
716122394Sharti		switch (which) {
717122394Sharti
718122394Sharti		  case LEAF_begemotSnmpdTransmitBuffer:
719122394Sharti			snmpd.rxbuf = ctx->scratch->int1;
720122394Sharti			return (SNMP_ERR_NOERROR);
721122394Sharti		  case LEAF_begemotSnmpdReceiveBuffer:
722122394Sharti			snmpd.txbuf = ctx->scratch->int1;
723122394Sharti			return (SNMP_ERR_NOERROR);
724122394Sharti		  case LEAF_begemotSnmpdCommunityDisable:
725122394Sharti			snmpd.comm_dis = ctx->scratch->int1;
726122394Sharti			return (SNMP_ERR_NOERROR);
727122394Sharti		  case LEAF_begemotSnmpdTrap1Addr:
728122394Sharti			ip_rollback(ctx, snmpd.trap1addr);
729122394Sharti			return (SNMP_ERR_NOERROR);
730124861Sharti		  case LEAF_begemotSnmpdVersionEnable:
731124861Sharti			snmpd.version_enable = ctx->scratch->int1;
732124861Sharti			return (SNMP_ERR_NOERROR);
733122394Sharti		}
734122394Sharti		abort();
735122394Sharti
736122394Sharti	  case SNMP_OP_COMMIT:
737122394Sharti		switch (which) {
738122394Sharti
739122394Sharti		  case LEAF_begemotSnmpdTransmitBuffer:
740122394Sharti		  case LEAF_begemotSnmpdReceiveBuffer:
741122394Sharti		  case LEAF_begemotSnmpdCommunityDisable:
742122394Sharti			return (SNMP_ERR_NOERROR);
743122394Sharti		  case LEAF_begemotSnmpdTrap1Addr:
744122394Sharti			ip_commit(ctx);
745122394Sharti			return (SNMP_ERR_NOERROR);
746124861Sharti		  case LEAF_begemotSnmpdVersionEnable:
747124861Sharti			return (SNMP_ERR_NOERROR);
748122394Sharti		}
749122394Sharti		abort();
750122394Sharti	}
751122394Sharti	abort();
752122394Sharti}
753122394Sharti
754122394Sharti/*
755122394Sharti * The community table
756122394Sharti */
757122394Shartiint
758122394Shartiop_community(struct snmp_context *ctx, struct snmp_value *value,
759122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
760122394Sharti{
761122394Sharti	asn_subid_t which = value->var.subs[sub - 1];
762122394Sharti	struct community *c;
763122394Sharti
764122394Sharti	switch (op) {
765122394Sharti
766122394Sharti	  case SNMP_OP_GETNEXT:
767122394Sharti		if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
768122394Sharti		    (c = NEXT_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
769122394Sharti			return (SNMP_ERR_NOSUCHNAME);
770122394Sharti		index_append(&value->var, sub, &c->index);
771122394Sharti		break;
772122394Sharti
773122394Sharti	  case SNMP_OP_GET:
774122394Sharti		if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
775122394Sharti		    (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
776122394Sharti			return (SNMP_ERR_NOSUCHNAME);
777122394Sharti		break;
778122394Sharti
779122394Sharti	  case SNMP_OP_SET:
780122394Sharti		if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
781122394Sharti		    (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
782122394Sharti			return (SNMP_ERR_NO_CREATION);
783122394Sharti		if (which != LEAF_begemotSnmpdCommunityString)
784122394Sharti			return (SNMP_ERR_NOT_WRITEABLE);
785122394Sharti		return (string_save(value, ctx, -1, &c->string));
786122394Sharti
787122394Sharti	  case SNMP_OP_ROLLBACK:
788122394Sharti		if (which == LEAF_begemotSnmpdCommunityString) {
789122394Sharti			if ((c = FIND_OBJECT_OID(&community_list, &value->var,
790122394Sharti			    sub)) == NULL)
791122394Sharti				string_free(ctx);
792122394Sharti			else
793122394Sharti				string_rollback(ctx, &c->string);
794122394Sharti			return (SNMP_ERR_NOERROR);
795122394Sharti		}
796122394Sharti		abort();
797122394Sharti
798122394Sharti	  case SNMP_OP_COMMIT:
799122394Sharti		if (which == LEAF_begemotSnmpdCommunityString) {
800122394Sharti			if ((c = FIND_OBJECT_OID(&community_list, &value->var,
801122394Sharti			    sub)) == NULL)
802122394Sharti				string_free(ctx);
803122394Sharti			else
804122394Sharti				string_commit(ctx);
805122394Sharti			return (SNMP_ERR_NOERROR);
806122394Sharti		}
807122394Sharti		abort();
808122394Sharti
809122394Sharti	  default:
810122394Sharti		abort();
811122394Sharti	}
812122394Sharti
813122394Sharti	switch (which) {
814122394Sharti
815122394Sharti	  case LEAF_begemotSnmpdCommunityString:
816122394Sharti		return (string_get(value, c->string, -1));
817122394Sharti
818122394Sharti	  case LEAF_begemotSnmpdCommunityDescr:
819122394Sharti		return (string_get(value, c->descr, -1));
820122394Sharti	}
821122394Sharti	abort();
822122394Sharti}
823122394Sharti
824122394Sharti/*
825122394Sharti * Module table.
826122394Sharti */
827122394Shartistruct module_dep {
828122394Sharti	struct snmp_dependency dep;
829122394Sharti	u_char	section[LM_SECTION_MAX + 1];
830122394Sharti	u_char	*path;
831122394Sharti	struct lmodule *m;
832122394Sharti};
833122394Sharti
834122394Shartistatic int
835122394Shartidep_modules(struct snmp_context *ctx, struct snmp_dependency *dep,
836122394Sharti    enum snmp_depop op)
837122394Sharti{
838122394Sharti	struct module_dep *mdep = (struct module_dep *)(void *)dep;
839122394Sharti
840122394Sharti	switch (op) {
841122394Sharti
842122394Sharti	  case SNMP_DEPOP_COMMIT:
843122394Sharti		if (mdep->path == NULL) {
844122394Sharti			/* unload - find the module */
845122394Sharti			TAILQ_FOREACH(mdep->m, &lmodules, link)
846128237Sharti				if (strcmp(mdep->m->section,
847128237Sharti				    mdep->section) == 0)
848122394Sharti					break;
849122394Sharti			if (mdep->m == NULL)
850128237Sharti				/* no such module - that's ok */
851122394Sharti				return (SNMP_ERR_NOERROR);
852128237Sharti
853128237Sharti			/* handle unloading in the finalizer */
854122394Sharti			return (SNMP_ERR_NOERROR);
855122394Sharti		}
856122394Sharti		/* load */
857128237Sharti		if ((mdep->m = lm_load(mdep->path, mdep->section)) == NULL) {
858128237Sharti			/* could not load */
859122394Sharti			return (SNMP_ERR_RES_UNAVAIL);
860122394Sharti		}
861128237Sharti		/* start in finalizer */
862122394Sharti		return (SNMP_ERR_NOERROR);
863122394Sharti
864122394Sharti	  case SNMP_DEPOP_ROLLBACK:
865122394Sharti		if (mdep->path == NULL) {
866128237Sharti			/* rollback unload - the finalizer takes care */
867122394Sharti			return (SNMP_ERR_NOERROR);
868122394Sharti		}
869122394Sharti		/* rollback load */
870122394Sharti		lm_unload(mdep->m);
871122394Sharti		return (SNMP_ERR_NOERROR);
872128237Sharti
873128237Sharti	  case SNMP_DEPOP_FINISH:
874128237Sharti		if (mdep->path == NULL) {
875128237Sharti			if (mdep->m != NULL && ctx->code == SNMP_RET_OK)
876128237Sharti				lm_unload(mdep->m);
877128237Sharti		} else {
878128237Sharti			if (mdep->m != NULL && ctx->code == SNMP_RET_OK &&
879128237Sharti			    community != COMM_INITIALIZE)
880128237Sharti				lm_start(mdep->m);
881128237Sharti			free(mdep->path);
882128237Sharti		}
883128237Sharti		return (SNMP_ERR_NOERROR);
884122394Sharti	}
885122394Sharti	abort();
886122394Sharti}
887122394Sharti
888122394Shartiint
889122394Shartiop_modules(struct snmp_context *ctx, struct snmp_value *value,
890122394Sharti    u_int sub, u_int iidx, enum snmp_op op)
891122394Sharti{
892122394Sharti	asn_subid_t which = value->var.subs[sub - 1];
893122394Sharti	struct lmodule *m;
894122394Sharti	u_char *section, *ptr;
895122394Sharti	size_t seclen;
896122394Sharti	struct module_dep *mdep;
897122394Sharti	struct asn_oid idx;
898122394Sharti
899122394Sharti	switch (op) {
900122394Sharti
901122394Sharti	  case SNMP_OP_GETNEXT:
902122394Sharti		if ((m = NEXT_OBJECT_OID(&lmodules, &value->var, sub)) == NULL)
903122394Sharti			return (SNMP_ERR_NOSUCHNAME);
904122394Sharti		index_append(&value->var, sub, &m->index);
905122394Sharti		break;
906122394Sharti
907122394Sharti	  case SNMP_OP_GET:
908122394Sharti		if ((m = FIND_OBJECT_OID(&lmodules, &value->var, sub)) == NULL)
909122394Sharti			return (SNMP_ERR_NOSUCHNAME);
910122394Sharti		break;
911122394Sharti
912122394Sharti	  case SNMP_OP_SET:
913122394Sharti		m = FIND_OBJECT_OID(&lmodules, &value->var, sub);
914122394Sharti		if (which != LEAF_begemotSnmpdModulePath) {
915122394Sharti			if (m == NULL)
916122394Sharti				return (SNMP_ERR_NO_CREATION);
917122394Sharti			return (SNMP_ERR_NOT_WRITEABLE);
918122394Sharti		}
919122394Sharti
920122394Sharti		/* the errors in the next few statements can only happen when
921122394Sharti		 * m is NULL, hence the NO_CREATION error. */
922122394Sharti		if (index_decode(&value->var, sub, iidx,
923122394Sharti		    &section, &seclen))
924122394Sharti			return (SNMP_ERR_NO_CREATION);
925122394Sharti
926122394Sharti		/* check the section name */
927122394Sharti		if (seclen > LM_SECTION_MAX || seclen == 0) {
928122394Sharti			free(section);
929122394Sharti			return (SNMP_ERR_NO_CREATION);
930122394Sharti		}
931122394Sharti		for (ptr = section; ptr < section + seclen; ptr++)
932122394Sharti			if (!isascii(*ptr) || !isalnum(*ptr)) {
933122394Sharti				free(section);
934122394Sharti				return (SNMP_ERR_NO_CREATION);
935122394Sharti			}
936122394Sharti		if (!isalpha(section[0])) {
937122394Sharti			free(section);
938122394Sharti			return (SNMP_ERR_NO_CREATION);
939122394Sharti		}
940122394Sharti
941122394Sharti		/* check the path */
942122394Sharti		for (ptr = value->v.octetstring.octets;
943122394Sharti		     ptr < value->v.octetstring.octets + value->v.octetstring.len;
944122394Sharti		     ptr++) {
945122394Sharti			if (*ptr == '\0') {
946122394Sharti				free(section);
947122394Sharti				return (SNMP_ERR_WRONG_VALUE);
948122394Sharti			}
949122394Sharti		}
950122394Sharti
951122394Sharti		if (m == NULL) {
952122394Sharti			if (value->v.octetstring.len == 0) {
953122394Sharti				free(section);
954122394Sharti				return (SNMP_ERR_INCONS_VALUE);
955122394Sharti			}
956122394Sharti		} else {
957122394Sharti			if (value->v.octetstring.len != 0) {
958122394Sharti				free(section);
959122394Sharti				return (SNMP_ERR_INCONS_VALUE);
960122394Sharti			}
961122394Sharti		}
962122394Sharti
963122394Sharti		asn_slice_oid(&idx, &value->var, sub, value->var.len);
964122394Sharti
965122394Sharti		/* so far, so good */
966122394Sharti		mdep = (struct module_dep *)(void *)snmp_dep_lookup(ctx,
967122394Sharti		    &oid_begemotSnmpdModuleTable, &idx,
968122394Sharti		    sizeof(*mdep), dep_modules);
969122394Sharti		if (mdep == NULL) {
970122394Sharti			free(section);
971122394Sharti			return (SNMP_ERR_RES_UNAVAIL);
972122394Sharti		}
973122394Sharti
974122394Sharti		if (mdep->section[0] != '\0') {
975122394Sharti			/* two writes to the same entry - bad */
976122394Sharti			free(section);
977122394Sharti			return (SNMP_ERR_INCONS_VALUE);
978122394Sharti		}
979122394Sharti
980122394Sharti		strncpy(mdep->section, section, seclen);
981122394Sharti		mdep->section[seclen] = '\0';
982122394Sharti		free(section);
983122394Sharti
984122394Sharti		if (value->v.octetstring.len == 0)
985122394Sharti			mdep->path = NULL;
986122394Sharti		else {
987122394Sharti			if ((mdep->path = malloc(value->v.octetstring.len + 1)) == NULL)
988122394Sharti				return (SNMP_ERR_RES_UNAVAIL);
989122394Sharti			strncpy(mdep->path, value->v.octetstring.octets,
990122394Sharti			    value->v.octetstring.len);
991122394Sharti			mdep->path[value->v.octetstring.len] = '\0';
992122394Sharti		}
993122394Sharti		ctx->scratch->ptr1 = mdep;
994122394Sharti		return (SNMP_ERR_NOERROR);
995122394Sharti
996122394Sharti	  case SNMP_OP_ROLLBACK:
997122394Sharti	  case SNMP_OP_COMMIT:
998122394Sharti		return (SNMP_ERR_NOERROR);
999122394Sharti
1000122394Sharti	  default:
1001122394Sharti		abort();
1002122394Sharti	}
1003122394Sharti
1004122394Sharti	switch (which) {
1005122394Sharti
1006122394Sharti	  case LEAF_begemotSnmpdModulePath:
1007122394Sharti		return (string_get(value, m->path, -1));
1008122394Sharti
1009122394Sharti	  case LEAF_begemotSnmpdModuleComment:
1010122394Sharti		return (string_get(value, m->config->comment, -1));
1011122394Sharti	}
1012122394Sharti	abort();
1013122394Sharti}
1014122394Sharti
1015122394Shartiint
1016122394Shartiop_snmp_set(struct snmp_context *ctx __unused, struct snmp_value *value,
1017122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
1018122394Sharti{
1019122394Sharti	switch (op) {
1020122394Sharti
1021122394Sharti	  case SNMP_OP_GETNEXT:
1022122394Sharti		abort();
1023122394Sharti
1024122394Sharti	  case SNMP_OP_GET:
1025122394Sharti		switch (value->var.subs[sub - 1]) {
1026122394Sharti
1027122394Sharti		  case LEAF_snmpSetSerialNo:
1028122394Sharti			value->v.integer = snmp_serial_no;
1029122394Sharti			break;
1030122394Sharti
1031122394Sharti		  default:
1032122394Sharti			abort();
1033122394Sharti		}
1034122394Sharti		return (SNMP_ERR_NOERROR);
1035122394Sharti
1036122394Sharti	  case SNMP_OP_SET:
1037122394Sharti		switch (value->var.subs[sub - 1]) {
1038122394Sharti
1039122394Sharti		  case LEAF_snmpSetSerialNo:
1040122394Sharti			if (value->v.integer != snmp_serial_no)
1041122394Sharti				return (SNMP_ERR_INCONS_VALUE);
1042122394Sharti			break;
1043122394Sharti
1044122394Sharti		  default:
1045122394Sharti			abort();
1046122394Sharti		}
1047122394Sharti		return (SNMP_ERR_NOERROR);
1048122394Sharti
1049122394Sharti	  case SNMP_OP_ROLLBACK:
1050122394Sharti		return (SNMP_ERR_NOERROR);
1051122394Sharti
1052122394Sharti	  case SNMP_OP_COMMIT:
1053122394Sharti		if (snmp_serial_no++ == 2147483647)
1054122394Sharti			snmp_serial_no = 0;
1055122394Sharti		return (SNMP_ERR_NOERROR);
1056122394Sharti	}
1057122394Sharti	abort();
1058122394Sharti}
1059124861Sharti
1060124861Sharti/*
1061216294Ssyrinx * SNMP Engine
1062216294Ssyrinx */
1063216294Ssyrinxint
1064216294Ssyrinxop_snmp_engine(struct snmp_context *ctx __unused, struct snmp_value *value,
1065216294Ssyrinx    u_int sub, u_int iidx __unused, enum snmp_op op)
1066216294Ssyrinx{
1067216294Ssyrinx	asn_subid_t which = value->var.subs[sub - 1];
1068216294Ssyrinx
1069216294Ssyrinx	switch (op) {
1070216294Ssyrinx	case SNMP_OP_GETNEXT:
1071216294Ssyrinx		abort();
1072216294Ssyrinx
1073216294Ssyrinx	case SNMP_OP_GET:
1074216294Ssyrinx		break;
1075216294Ssyrinx
1076216294Ssyrinx	case SNMP_OP_SET:
1077216294Ssyrinx		if (community != COMM_INITIALIZE)
1078216294Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
1079216294Ssyrinx		switch (which) {
1080216294Ssyrinx		case LEAF_snmpEngineID:
1081216294Ssyrinx			if (value->v.octetstring.len > SNMP_ENGINE_ID_SIZ)
1082216294Ssyrinx				return (SNMP_ERR_WRONG_VALUE);
1083216294Ssyrinx			ctx->scratch->ptr1 = malloc(snmpd_engine.engine_len);
1084216294Ssyrinx			if (ctx->scratch->ptr1 == NULL)
1085216294Ssyrinx				return (SNMP_ERR_GENERR);
1086216294Ssyrinx			memcpy(ctx->scratch->ptr1, snmpd_engine.engine_id,
1087216294Ssyrinx			    snmpd_engine.engine_len);
1088216294Ssyrinx			ctx->scratch->int1 = snmpd_engine.engine_len;
1089216294Ssyrinx			snmpd_engine.engine_len = value->v.octetstring.len;
1090216294Ssyrinx			memcpy(snmpd_engine.engine_id,
1091216294Ssyrinx			    value->v.octetstring.octets,
1092216294Ssyrinx			    value->v.octetstring.len);
1093216294Ssyrinx			break;
1094216294Ssyrinx
1095216294Ssyrinx		case LEAF_snmpEngineMaxMessageSize:
1096216294Ssyrinx			ctx->scratch->int1 = snmpd_engine.max_msg_size;
1097216294Ssyrinx			snmpd_engine.max_msg_size = value->v.integer;
1098216294Ssyrinx			break;
1099216294Ssyrinx
1100216294Ssyrinx		default:
1101216294Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
1102216294Ssyrinx		}
1103216294Ssyrinx		return (SNMP_ERR_NOERROR);
1104216294Ssyrinx
1105216294Ssyrinx	case SNMP_OP_ROLLBACK:
1106216294Ssyrinx		switch (which) {
1107216294Ssyrinx		case LEAF_snmpEngineID:
1108216294Ssyrinx			snmpd_engine.engine_len = ctx->scratch->int1;
1109216294Ssyrinx			memcpy(snmpd_engine.engine_id, ctx->scratch->ptr1,
1110216294Ssyrinx			    snmpd_engine.engine_len);
1111216294Ssyrinx			free(ctx->scratch->ptr1);
1112216294Ssyrinx			break;
1113216294Ssyrinx
1114216294Ssyrinx		case LEAF_snmpEngineMaxMessageSize:
1115216294Ssyrinx			snmpd_engine.max_msg_size = ctx->scratch->int1;
1116216294Ssyrinx			break;
1117216294Ssyrinx
1118216294Ssyrinx		default:
1119216294Ssyrinx			abort();
1120216294Ssyrinx		}
1121216294Ssyrinx		return (SNMP_ERR_NOERROR);
1122216294Ssyrinx
1123216294Ssyrinx	case SNMP_OP_COMMIT:
1124216294Ssyrinx		if (which == LEAF_snmpEngineID) {
1125216294Ssyrinx			if (set_snmpd_engine() < 0) {
1126216294Ssyrinx				snmpd_engine.engine_len = ctx->scratch->int1;
1127216294Ssyrinx				memcpy(snmpd_engine.engine_id,
1128216294Ssyrinx				    ctx->scratch->ptr1, ctx->scratch->int1);
1129216294Ssyrinx			}
1130216294Ssyrinx			free(ctx->scratch->ptr1);
1131216294Ssyrinx		}
1132216294Ssyrinx		return (SNMP_ERR_NOERROR);
1133216294Ssyrinx	}
1134216294Ssyrinx
1135216294Ssyrinx
1136216294Ssyrinx	switch (which) {
1137216294Ssyrinx	case LEAF_snmpEngineID:
1138216294Ssyrinx		return (string_get(value, snmpd_engine.engine_id,
1139216294Ssyrinx		    snmpd_engine.engine_len));
1140216294Ssyrinx	case LEAF_snmpEngineBoots:
1141216294Ssyrinx		value->v.integer = snmpd_engine.engine_boots;
1142216294Ssyrinx		break;
1143216294Ssyrinx	case LEAF_snmpEngineTime:
1144216294Ssyrinx		snmpd_engine.engine_time = (get_ticks() - start_tick) / 100ULL;
1145216294Ssyrinx		value->v.integer = snmpd_engine.engine_time;
1146216294Ssyrinx		break;
1147216294Ssyrinx	case LEAF_snmpEngineMaxMessageSize:
1148216294Ssyrinx		value->v.integer = snmpd_engine.max_msg_size;
1149216294Ssyrinx		break;
1150216294Ssyrinx	default:
1151216294Ssyrinx		return (SNMP_ERR_NOSUCHNAME);
1152216294Ssyrinx	}
1153216294Ssyrinx
1154216294Ssyrinx	return (SNMP_ERR_NOERROR);
1155216294Ssyrinx}
1156216294Ssyrinx
1157216294Ssyrinx/*
1158124861Sharti * Transport table
1159124861Sharti */
1160124861Shartiint
1161124861Shartiop_transport_table(struct snmp_context *ctx __unused, struct snmp_value *value,
1162124861Sharti    u_int sub, u_int iidx, enum snmp_op op)
1163124861Sharti{
1164124861Sharti	asn_subid_t which = value->var.subs[sub - 1];
1165124861Sharti	struct transport *t;
1166124861Sharti	u_char *tname, *ptr;
1167124861Sharti	size_t tnamelen;
1168124861Sharti
1169124861Sharti	switch (op) {
1170124861Sharti
1171124861Sharti	  case SNMP_OP_GETNEXT:
1172124861Sharti		if ((t = NEXT_OBJECT_OID(&transport_list, &value->var, sub))
1173124861Sharti		    == NULL)
1174124861Sharti			return (SNMP_ERR_NOSUCHNAME);
1175124861Sharti		index_append(&value->var, sub, &t->index);
1176124861Sharti		break;
1177124861Sharti
1178124861Sharti	  case SNMP_OP_GET:
1179124861Sharti		if ((t = FIND_OBJECT_OID(&transport_list, &value->var, sub))
1180124861Sharti		    == NULL)
1181124861Sharti			return (SNMP_ERR_NOSUCHNAME);
1182124861Sharti		break;
1183124861Sharti
1184124861Sharti	  case SNMP_OP_SET:
1185124861Sharti		t = FIND_OBJECT_OID(&transport_list, &value->var, sub);
1186124861Sharti		if (which != LEAF_begemotSnmpdTransportStatus) {
1187124861Sharti			if (t == NULL)
1188124861Sharti				return (SNMP_ERR_NO_CREATION);
1189124861Sharti			return (SNMP_ERR_NOT_WRITEABLE);
1190124861Sharti		}
1191124861Sharti
1192124861Sharti		/* the errors in the next few statements can only happen when
1193124861Sharti		 * t is NULL, hence the NO_CREATION error. */
1194124861Sharti		if (index_decode(&value->var, sub, iidx,
1195124861Sharti		    &tname, &tnamelen))
1196124861Sharti			return (SNMP_ERR_NO_CREATION);
1197124861Sharti
1198124861Sharti		/* check the section name */
1199124861Sharti		if (tnamelen >= TRANS_NAMELEN || tnamelen == 0) {
1200124861Sharti			free(tname);
1201124861Sharti			return (SNMP_ERR_NO_CREATION);
1202124861Sharti		}
1203124861Sharti		for (ptr = tname; ptr < tname + tnamelen; ptr++) {
1204124861Sharti			if (!isascii(*ptr) || !isalnum(*ptr)) {
1205124861Sharti				free(tname);
1206124861Sharti				return (SNMP_ERR_NO_CREATION);
1207124861Sharti			}
1208124861Sharti		}
1209124861Sharti
1210124861Sharti		/* for now */
1211124861Sharti		return (SNMP_ERR_NOT_WRITEABLE);
1212124861Sharti
1213124861Sharti	  case SNMP_OP_ROLLBACK:
1214124861Sharti	  case SNMP_OP_COMMIT:
1215124861Sharti		return (SNMP_ERR_NOERROR);
1216124861Sharti	  default:
1217124861Sharti		abort();
1218124861Sharti	}
1219124861Sharti
1220124861Sharti	switch (which) {
1221124861Sharti
1222124861Sharti	    case LEAF_begemotSnmpdTransportStatus:
1223124861Sharti		value->v.integer = 1;
1224124861Sharti		break;
1225124861Sharti
1226124861Sharti	    case LEAF_begemotSnmpdTransportOid:
1227124861Sharti		memcpy(&value->v.oid, &t->vtab->id, sizeof(t->vtab->id));
1228124861Sharti		break;
1229124861Sharti	}
1230124861Sharti	return (SNMP_ERR_NOERROR);
1231124861Sharti}
1232