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 an integer value from the KERN sysctl subtree.
64122394Sharti */
65122394Shartistatic char *
66122394Shartiact_getkernint(int id)
67122394Sharti{
68122394Sharti	int mib[2];
69122394Sharti	size_t len;
70122394Sharti	u_long value;
71122394Sharti	char *string;
72122394Sharti
73122394Sharti	mib[0] = CTL_KERN;
74122394Sharti	mib[1] = id;
75122394Sharti	len = sizeof(value);
76122394Sharti	if (sysctl(mib, 2, &value, &len, NULL, 0) != 0)
77122394Sharti		return (NULL);
78122394Sharti
79122394Sharti	if ((string = malloc(20)) == NULL)
80122394Sharti		return (NULL);
81122394Sharti	sprintf(string, "%lu", value);
82122394Sharti	return (string);
83122394Sharti}
84122394Sharti
85122394Sharti/*
86122394Sharti * Initialize global variables of the system group.
87122394Sharti */
88122394Shartiint
89122394Shartiinit_actvals(void)
90122394Sharti{
91163820Sharti	struct utsname uts;
92163820Sharti	char *hostid;
93122394Sharti	size_t len;
94163820Sharti#ifdef __FreeBSD__
95163820Sharti	char *rel, *p, *end;
96163820Sharti	u_long num;
97163820Sharti#endif
98122394Sharti
99163820Sharti	if (uname(&uts) == -1)
100122394Sharti		return (-1);
101122394Sharti
102163820Sharti	if ((systemg.name = strdup(uts.nodename)) == NULL)
103163820Sharti		return (-1);
104122394Sharti
105163820Sharti	if ((hostid = act_getkernint(KERN_HOSTID)) == NULL)
106163820Sharti		return (-1);
107122394Sharti
108163820Sharti	len = strlen(uts.nodename) + 1;
109163820Sharti	len += strlen(hostid) + 1;
110163820Sharti	len += strlen(uts.sysname) + 1;
111163820Sharti	len += strlen(uts.release) + 1;
112122394Sharti
113163820Sharti	if ((systemg.descr = malloc(len)) == NULL) {
114163820Sharti		free(hostid);
115163820Sharti		return (-1);
116163820Sharti	}
117163820Sharti	sprintf(systemg.descr, "%s %s %s %s", uts.nodename, hostid, uts.sysname,
118163820Sharti	    uts.release);
119122394Sharti
120163820Sharti#ifdef __FreeBSD__
121163820Sharti	/*
122163820Sharti	 * Construct a FreeBSD oid
123163820Sharti	 */
124163820Sharti	systemg.object_id = oid_freeBSDVersion;
125163820Sharti	rel = uts.release;
126163820Sharti	while ((p = strsep(&rel, ".")) != NULL &&
127163820Sharti	    systemg.object_id.len < ASN_MAXOIDLEN) {
128163820Sharti		systemg.object_id.subs[systemg.object_id.len] = 0;
129163820Sharti		if (*p != '\0') {
130163820Sharti			num = strtoul(p, &end, 10);
131163820Sharti			if (end == p)
132163820Sharti				break;
133163820Sharti			systemg.object_id.subs[systemg.object_id.len] = num;
134163820Sharti		}
135163820Sharti		systemg.object_id.len++;
136163820Sharti	}
137163820Sharti#endif
138163820Sharti
139163820Sharti	free(hostid);
140163820Sharti
141122394Sharti	return (0);
142122394Sharti}
143122394Sharti
144216294Ssyrinx/*
145216294Ssyrinx * Initialize global variables of the snmpEngine group.
146216294Ssyrinx */
147216294Ssyrinxint
148216294Ssyrinxinit_snmpd_engine(void)
149216294Ssyrinx{
150216294Ssyrinx	char *hostid;
151122394Sharti
152216294Ssyrinx	snmpd_engine.engine_boots = 1;
153216294Ssyrinx	snmpd_engine.engine_time = 1;
154216294Ssyrinx	snmpd_engine.max_msg_size = 1500; /* XXX */
155122394Sharti
156216294Ssyrinx	snmpd_engine.engine_id[0] = ((OID_freeBSD & 0xff000000) >> 24) | 0x80;
157216294Ssyrinx	snmpd_engine.engine_id[1] = (OID_freeBSD & 0xff0000) >> 16;
158216294Ssyrinx	snmpd_engine.engine_id[2] = (OID_freeBSD & 0xff00) >> 8;
159216294Ssyrinx	snmpd_engine.engine_id[3] = OID_freeBSD & 0xff;
160216294Ssyrinx	snmpd_engine.engine_id[4] = 128;
161216294Ssyrinx	snmpd_engine.engine_len = 5;
162216294Ssyrinx
163216294Ssyrinx	if ((hostid = act_getkernint(KERN_HOSTID)) == NULL)
164216294Ssyrinx		return (-1);
165216294Ssyrinx
166216294Ssyrinx	if (strlen(hostid) > SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len) {
167216294Ssyrinx		memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len,
168216294Ssyrinx		    hostid, SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len);
169216294Ssyrinx		snmpd_engine.engine_len = SNMP_ENGINE_ID_SIZ;
170216294Ssyrinx	} else {
171216294Ssyrinx		memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len,
172216294Ssyrinx		    hostid, strlen(hostid));
173216294Ssyrinx		snmpd_engine.engine_len += strlen(hostid);
174216294Ssyrinx	}
175216294Ssyrinx
176216294Ssyrinx	free(hostid);
177216294Ssyrinx
178216294Ssyrinx	return (0);
179216294Ssyrinx}
180216294Ssyrinx
181216294Ssyrinxint
182216294Ssyrinxset_snmpd_engine(void)
183216294Ssyrinx{
184216294Ssyrinx	FILE *fp;
185216294Ssyrinx	uint32_t i;
186216294Ssyrinx	uint8_t *cptr, engine[2 * SNMP_ENGINE_ID_SIZ + 2];
187216294Ssyrinx	uint8_t myengine[2 * SNMP_ENGINE_ID_SIZ + 2];
188216294Ssyrinx
189216294Ssyrinx	if (engine_file[0] == '\0')
190216294Ssyrinx		return (-1);
191216294Ssyrinx
192216294Ssyrinx	cptr = myengine;
193216294Ssyrinx	for (i = 0; i < snmpd_engine.engine_len; i++)
194216294Ssyrinx		cptr += sprintf(cptr, "%.2x", snmpd_engine.engine_id[i]);
195216294Ssyrinx	*cptr++ = '\n';
196216294Ssyrinx	*cptr++ = '\0';
197216294Ssyrinx
198216294Ssyrinx	if ((fp = fopen(engine_file, "r+")) != NULL) {
199216294Ssyrinx		if (fgets(engine, sizeof(engine) - 1, fp) == NULL ||
200216294Ssyrinx		    fscanf(fp, "%u",  &snmpd_engine.engine_boots) <= 0) {
201216294Ssyrinx			fclose(fp);
202216294Ssyrinx			goto save_boots;
203216294Ssyrinx		}
204216294Ssyrinx
205216294Ssyrinx		fclose(fp);
206216294Ssyrinx		if (strcmp(myengine, engine) != 0)
207216294Ssyrinx			snmpd_engine.engine_boots = 1;
208216294Ssyrinx		else
209216294Ssyrinx			snmpd_engine.engine_boots++;
210216294Ssyrinx	} else if (errno != ENOENT)
211216294Ssyrinx		return (-1);
212216294Ssyrinx
213216294Ssyrinxsave_boots:
214216294Ssyrinx	if ((fp = fopen(engine_file, "w+")) == NULL)
215216294Ssyrinx		return (-1);
216216294Ssyrinx	fprintf(fp, "%s%u\n", myengine, snmpd_engine.engine_boots);
217216294Ssyrinx	fclose(fp);
218216294Ssyrinx
219216294Ssyrinx	return (0);
220216294Ssyrinx}
221216294Ssyrinx
222122394Sharti/*************************************************************
223122394Sharti *
224122394Sharti * System group
225122394Sharti */
226122394Shartiint
227122394Shartiop_system_group(struct snmp_context *ctx, struct snmp_value *value,
228122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
229122394Sharti{
230122394Sharti	asn_subid_t which = value->var.subs[sub - 1];
231122394Sharti
232122394Sharti	switch (op) {
233122394Sharti
234122394Sharti	  case SNMP_OP_GETNEXT:
235122394Sharti		abort();
236122394Sharti
237122394Sharti	  case SNMP_OP_GET:
238122394Sharti		break;
239122394Sharti
240122394Sharti	  case SNMP_OP_SET:
241122394Sharti		switch (which) {
242122394Sharti
243122394Sharti		  case LEAF_sysDescr:
244122394Sharti			if (community != COMM_INITIALIZE)
245122394Sharti				return (SNMP_ERR_NOT_WRITEABLE);
246122394Sharti			return (string_save(value, ctx, -1, &systemg.descr));
247122394Sharti
248122394Sharti		  case LEAF_sysObjectId:
249122394Sharti			if (community != COMM_INITIALIZE)
250122394Sharti				return (SNMP_ERR_NOT_WRITEABLE);
251122394Sharti			return (oid_save(value, ctx, &systemg.object_id));
252122394Sharti
253122394Sharti		  case LEAF_sysContact:
254122394Sharti			return (string_save(value, ctx, -1, &systemg.contact));
255122394Sharti
256122394Sharti		  case LEAF_sysName:
257122394Sharti			return (string_save(value, ctx, -1, &systemg.name));
258122394Sharti
259122394Sharti		  case LEAF_sysLocation:
260122394Sharti			return (string_save(value, ctx, -1, &systemg.location));
261122394Sharti		}
262122394Sharti		return (SNMP_ERR_NO_CREATION);
263122394Sharti
264122394Sharti	  case SNMP_OP_ROLLBACK:
265122394Sharti		switch (which) {
266122394Sharti
267122394Sharti		  case LEAF_sysDescr:
268122394Sharti			string_rollback(ctx, &systemg.descr);
269122394Sharti			return (SNMP_ERR_NOERROR);
270122394Sharti		  case LEAF_sysObjectId:
271122394Sharti			oid_rollback(ctx, &systemg.object_id);
272122394Sharti			return (SNMP_ERR_NOERROR);
273122394Sharti		  case LEAF_sysContact:
274122394Sharti			string_rollback(ctx, &systemg.contact);
275122394Sharti			return (SNMP_ERR_NOERROR);
276122394Sharti		  case LEAF_sysName:
277122394Sharti			string_rollback(ctx, &systemg.name);
278122394Sharti			return (SNMP_ERR_NOERROR);
279122394Sharti		  case LEAF_sysLocation:
280122394Sharti			string_rollback(ctx, &systemg.location);
281122394Sharti			return (SNMP_ERR_NOERROR);
282122394Sharti		}
283122394Sharti		abort();
284122394Sharti
285122394Sharti	  case SNMP_OP_COMMIT:
286122394Sharti		switch (which) {
287122394Sharti
288122394Sharti		  case LEAF_sysDescr:
289122394Sharti			string_commit(ctx);
290122394Sharti			return (SNMP_ERR_NOERROR);
291122394Sharti		  case LEAF_sysObjectId:
292122394Sharti			oid_commit(ctx);
293122394Sharti			return (SNMP_ERR_NOERROR);
294122394Sharti		  case LEAF_sysContact:
295122394Sharti			string_commit(ctx);
296122394Sharti			return (SNMP_ERR_NOERROR);
297122394Sharti		  case LEAF_sysName:
298122394Sharti			string_commit(ctx);
299122394Sharti			return (SNMP_ERR_NOERROR);
300122394Sharti		  case LEAF_sysLocation:
301122394Sharti			string_commit(ctx);
302122394Sharti			return (SNMP_ERR_NOERROR);
303122394Sharti		}
304122394Sharti		abort();
305122394Sharti	}
306122394Sharti
307122394Sharti	/*
308122394Sharti	 * Come here for GET.
309122394Sharti	 */
310122394Sharti	switch (which) {
311122394Sharti
312122394Sharti	  case LEAF_sysDescr:
313122394Sharti		return (string_get(value, systemg.descr, -1));
314122394Sharti	  case LEAF_sysObjectId:
315122394Sharti		return (oid_get(value, &systemg.object_id));
316122394Sharti	  case LEAF_sysUpTime:
317122394Sharti		value->v.uint32 = get_ticks() - start_tick;
318122394Sharti		break;
319122394Sharti	  case LEAF_sysContact:
320122394Sharti		return (string_get(value, systemg.contact, -1));
321122394Sharti	  case LEAF_sysName:
322122394Sharti		return (string_get(value, systemg.name, -1));
323122394Sharti	  case LEAF_sysLocation:
324122394Sharti		return (string_get(value, systemg.location, -1));
325122394Sharti	  case LEAF_sysServices:
326122394Sharti		value->v.integer = systemg.services;
327122394Sharti		break;
328122394Sharti	  case LEAF_sysORLastChange:
329122394Sharti		value->v.uint32 = systemg.or_last_change;
330122394Sharti		break;
331122394Sharti	}
332122394Sharti	return (SNMP_ERR_NOERROR);
333122394Sharti}
334122394Sharti
335122394Sharti/*************************************************************
336122394Sharti *
337122394Sharti * Debug group
338122394Sharti */
339122394Shartiint
340122394Shartiop_debug(struct snmp_context *ctx, struct snmp_value *value, u_int sub,
341122394Sharti    u_int iidx __unused, enum snmp_op op)
342122394Sharti{
343122394Sharti	asn_subid_t which = value->var.subs[sub - 1];
344122394Sharti
345122394Sharti	switch (op) {
346122394Sharti
347122394Sharti	  case SNMP_OP_GETNEXT:
348122394Sharti		abort();
349122394Sharti
350122394Sharti	  case SNMP_OP_GET:
351122394Sharti		switch (which) {
352122394Sharti
353122394Sharti		  case LEAF_begemotSnmpdDebugDumpPdus:
354122394Sharti			value->v.integer = TRUTH_MK(debug.dump_pdus);
355122394Sharti			break;
356122394Sharti
357122394Sharti		  case LEAF_begemotSnmpdDebugSnmpTrace:
358122394Sharti			value->v.uint32 = snmp_trace;
359122394Sharti			break;
360122394Sharti
361122394Sharti		  case LEAF_begemotSnmpdDebugSyslogPri:
362122394Sharti			value->v.integer = debug.logpri;
363122394Sharti			break;
364122394Sharti		}
365122394Sharti		return (SNMP_ERR_NOERROR);
366122394Sharti
367122394Sharti	  case SNMP_OP_SET:
368122394Sharti		switch (which) {
369122394Sharti
370122394Sharti		  case LEAF_begemotSnmpdDebugDumpPdus:
371122394Sharti			if (!TRUTH_OK(value->v.integer))
372122394Sharti				return (SNMP_ERR_WRONG_VALUE);
373122394Sharti			ctx->scratch->int1 = debug.dump_pdus;
374122394Sharti			debug.dump_pdus = TRUTH_GET(value->v.integer);
375122394Sharti			return (SNMP_ERR_NOERROR);
376122394Sharti
377122394Sharti		  case LEAF_begemotSnmpdDebugSnmpTrace:
378122394Sharti			ctx->scratch->int1 = snmp_trace;
379122394Sharti			snmp_trace = value->v.uint32;
380122394Sharti			return (SNMP_ERR_NOERROR);
381122394Sharti
382122394Sharti		  case LEAF_begemotSnmpdDebugSyslogPri:
383122394Sharti			if (value->v.integer < 0 || value->v.integer > 8)
384122394Sharti				return (SNMP_ERR_WRONG_VALUE);
385122394Sharti			ctx->scratch->int1 = debug.logpri;
386122394Sharti			debug.logpri = (u_int)value->v.integer;
387122394Sharti			return (SNMP_ERR_NOERROR);
388122394Sharti		}
389122394Sharti		return (SNMP_ERR_NO_CREATION);
390122394Sharti
391122394Sharti	  case SNMP_OP_ROLLBACK:
392122394Sharti		switch (which) {
393122394Sharti
394122394Sharti		  case LEAF_begemotSnmpdDebugDumpPdus:
395122394Sharti			debug.dump_pdus = ctx->scratch->int1;
396122394Sharti			return (SNMP_ERR_NOERROR);
397122394Sharti
398122394Sharti		  case LEAF_begemotSnmpdDebugSnmpTrace:
399122394Sharti			snmp_trace = ctx->scratch->int1;
400122394Sharti			return (SNMP_ERR_NOERROR);
401122394Sharti
402122394Sharti		  case LEAF_begemotSnmpdDebugSyslogPri:
403122394Sharti			debug.logpri = ctx->scratch->int1;
404122394Sharti			return (SNMP_ERR_NOERROR);
405122394Sharti		}
406122394Sharti		abort();
407122394Sharti
408122394Sharti	  case SNMP_OP_COMMIT:
409122394Sharti		switch (which) {
410122394Sharti
411122394Sharti		  case LEAF_begemotSnmpdDebugDumpPdus:
412122394Sharti		  case LEAF_begemotSnmpdDebugSnmpTrace:
413122394Sharti			return (SNMP_ERR_NOERROR);
414122394Sharti
415122394Sharti		  case LEAF_begemotSnmpdDebugSyslogPri:
416122394Sharti			if (debug.logpri == 0)
417122394Sharti				setlogmask(0);
418122394Sharti			else
419122394Sharti				setlogmask(LOG_UPTO(debug.logpri - 1));
420122394Sharti			return (SNMP_ERR_NOERROR);
421122394Sharti		}
422122394Sharti		abort();
423122394Sharti	}
424122394Sharti	abort();
425122394Sharti}
426122394Sharti
427122394Sharti/*************************************************************
428122394Sharti *
429122394Sharti * OR Table
430122394Sharti */
431122394Shartiint
432122394Shartiop_or_table(struct snmp_context *ctx __unused, struct snmp_value *value,
433122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
434122394Sharti{
435122394Sharti	struct objres *objres;
436122394Sharti
437122394Sharti	switch (op) {
438122394Sharti
439122394Sharti	  case SNMP_OP_GETNEXT:
440122394Sharti		if ((objres = NEXT_OBJECT_INT(&objres_list, &value->var, sub))
441122394Sharti		    == NULL)
442122394Sharti			return (SNMP_ERR_NOSUCHNAME);
443122394Sharti		value->var.subs[sub] = objres->index;
444122394Sharti		value->var.len = sub + 1;
445122394Sharti		break;
446122394Sharti
447122394Sharti	  case SNMP_OP_GET:
448122394Sharti		if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub))
449122394Sharti		    == NULL)
450122394Sharti			return (SNMP_ERR_NOSUCHNAME);
451122394Sharti		break;
452122394Sharti
453122394Sharti	  case SNMP_OP_SET:
454122394Sharti		if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub))
455122394Sharti		    == NULL)
456122394Sharti			return (SNMP_ERR_NO_CREATION);
457122394Sharti		return (SNMP_ERR_NOT_WRITEABLE);
458122394Sharti
459122394Sharti	  case SNMP_OP_ROLLBACK:
460122394Sharti	  case SNMP_OP_COMMIT:
461122394Sharti	  default:
462122394Sharti		abort();
463122394Sharti	}
464122394Sharti
465122394Sharti	/*
466122394Sharti	 * Come here for GET, GETNEXT.
467122394Sharti	 */
468122394Sharti	switch (value->var.subs[sub - 1]) {
469122394Sharti
470122394Sharti	  case LEAF_sysORID:
471122394Sharti		value->v.oid = objres->oid;
472122394Sharti		break;
473122394Sharti
474122394Sharti	  case LEAF_sysORDescr:
475122394Sharti		return (string_get(value, objres->descr, -1));
476122394Sharti
477122394Sharti	  case LEAF_sysORUpTime:
478122394Sharti		value->v.uint32 = objres->uptime;
479122394Sharti		break;
480122394Sharti	}
481122394Sharti	return (SNMP_ERR_NOERROR);
482122394Sharti}
483122394Sharti
484122394Sharti/*************************************************************
485122394Sharti *
486122394Sharti * mib-2 snmp
487122394Sharti */
488122394Shartiint
489122394Shartiop_snmp(struct snmp_context *ctx, struct snmp_value *value,
490122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
491122394Sharti{
492122394Sharti	switch (op) {
493122394Sharti
494122394Sharti	  case SNMP_OP_GETNEXT:
495122394Sharti		abort();
496122394Sharti
497122394Sharti	  case SNMP_OP_GET:
498122394Sharti		switch (value->var.subs[sub - 1]) {
499122394Sharti
500122394Sharti		  case LEAF_snmpInPkts:
501122394Sharti			value->v.uint32 = snmpd_stats.inPkts;
502122394Sharti			break;
503122394Sharti
504122394Sharti		  case LEAF_snmpInBadVersions:
505122394Sharti			value->v.uint32 = snmpd_stats.inBadVersions;
506122394Sharti			break;
507122394Sharti
508122394Sharti		  case LEAF_snmpInBadCommunityNames:
509122394Sharti			value->v.uint32 = snmpd_stats.inBadCommunityNames;
510122394Sharti			break;
511122394Sharti
512122394Sharti		  case LEAF_snmpInBadCommunityUses:
513122394Sharti			value->v.uint32 = snmpd_stats.inBadCommunityUses;
514122394Sharti			break;
515122394Sharti
516122394Sharti		  case LEAF_snmpInASNParseErrs:
517122394Sharti			value->v.uint32 = snmpd_stats.inASNParseErrs;
518122394Sharti			break;
519122394Sharti
520122394Sharti		  case LEAF_snmpEnableAuthenTraps:
521122394Sharti			value->v.integer = TRUTH_MK(snmpd.auth_traps);
522122394Sharti			break;
523122394Sharti
524122394Sharti		  case LEAF_snmpSilentDrops:
525122394Sharti			value->v.uint32 = snmpd_stats.silentDrops;
526122394Sharti			break;
527122394Sharti
528122394Sharti		  case LEAF_snmpProxyDrops:
529122394Sharti			value->v.uint32 = snmpd_stats.proxyDrops;
530122394Sharti			break;
531122394Sharti
532122394Sharti		  default:
533122394Sharti			return (SNMP_ERR_NOSUCHNAME);
534122394Sharti
535122394Sharti		}
536122394Sharti		return (SNMP_ERR_NOERROR);
537122394Sharti
538122394Sharti	  case SNMP_OP_SET:
539122394Sharti		switch (value->var.subs[sub - 1]) {
540122394Sharti		  case LEAF_snmpEnableAuthenTraps:
541122394Sharti			if (!TRUTH_OK(value->v.integer))
542122394Sharti				return (SNMP_ERR_WRONG_VALUE);
543122394Sharti			ctx->scratch->int1 = value->v.integer;
544122394Sharti			snmpd.auth_traps = TRUTH_GET(value->v.integer);
545122394Sharti			return (SNMP_ERR_NOERROR);
546122394Sharti		}
547122394Sharti		abort();
548122394Sharti
549122394Sharti	  case SNMP_OP_ROLLBACK:
550122394Sharti		switch (value->var.subs[sub - 1]) {
551122394Sharti		  case LEAF_snmpEnableAuthenTraps:
552122394Sharti			snmpd.auth_traps = ctx->scratch->int1;
553122394Sharti			return (SNMP_ERR_NOERROR);
554122394Sharti		}
555122394Sharti		abort();
556122394Sharti
557122394Sharti	  case SNMP_OP_COMMIT:
558122394Sharti		switch (value->var.subs[sub - 1]) {
559122394Sharti		  case LEAF_snmpEnableAuthenTraps:
560122394Sharti			return (SNMP_ERR_NOERROR);
561122394Sharti		}
562122394Sharti		abort();
563122394Sharti	}
564122394Sharti	abort();
565122394Sharti}
566122394Sharti
567122394Sharti/*************************************************************
568122394Sharti *
569122394Sharti * SNMPd statistics group
570122394Sharti */
571122394Shartiint
572122394Shartiop_snmpd_stats(struct snmp_context *ctx __unused, struct snmp_value *value,
573122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
574122394Sharti{
575122394Sharti	switch (op) {
576122394Sharti
577122394Sharti	  case SNMP_OP_GET:
578122394Sharti		switch (value->var.subs[sub - 1]) {
579122394Sharti
580122394Sharti		  case LEAF_begemotSnmpdStatsNoRxBufs:
581122394Sharti			value->v.uint32 = snmpd_stats.noRxbuf;
582122394Sharti			break;
583122394Sharti
584122394Sharti		  case LEAF_begemotSnmpdStatsNoTxBufs:
585122394Sharti			value->v.uint32 = snmpd_stats.noTxbuf;
586122394Sharti			break;
587122394Sharti
588122394Sharti		  case LEAF_begemotSnmpdStatsInTooLongPkts:
589122394Sharti			value->v.uint32 = snmpd_stats.inTooLong;
590122394Sharti			break;
591122394Sharti
592122394Sharti		  case LEAF_begemotSnmpdStatsInBadPduTypes:
593122394Sharti			value->v.uint32 = snmpd_stats.inBadPduTypes;
594122394Sharti			break;
595122394Sharti
596122394Sharti		  default:
597122394Sharti			return (SNMP_ERR_NOSUCHNAME);
598122394Sharti		}
599122394Sharti		return (SNMP_ERR_NOERROR);
600122394Sharti
601122394Sharti	  case SNMP_OP_SET:
602122394Sharti	  case SNMP_OP_ROLLBACK:
603122394Sharti	  case SNMP_OP_COMMIT:
604122394Sharti	  case SNMP_OP_GETNEXT:
605122394Sharti		abort();
606122394Sharti	}
607122394Sharti	abort();
608122394Sharti}
609122394Sharti
610122394Sharti/*
611122394Sharti * SNMPd configuration scalars
612122394Sharti */
613122394Shartiint
614122394Shartiop_snmpd_config(struct snmp_context *ctx, struct snmp_value *value,
615122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
616122394Sharti{
617122394Sharti	asn_subid_t which = value->var.subs[sub - 1];
618122394Sharti
619122394Sharti	switch (op) {
620122394Sharti
621122394Sharti	  case SNMP_OP_GETNEXT:
622122394Sharti		abort();
623122394Sharti
624122394Sharti	  case SNMP_OP_GET:
625122394Sharti		switch (which) {
626122394Sharti
627122394Sharti		  case LEAF_begemotSnmpdTransmitBuffer:
628122394Sharti			value->v.integer = snmpd.txbuf;
629122394Sharti			break;
630122394Sharti		  case LEAF_begemotSnmpdReceiveBuffer:
631122394Sharti			value->v.integer = snmpd.rxbuf;
632122394Sharti			break;
633122394Sharti		  case LEAF_begemotSnmpdCommunityDisable:
634122394Sharti			value->v.integer = TRUTH_MK(snmpd.comm_dis);
635122394Sharti			break;
636122394Sharti		  case LEAF_begemotSnmpdTrap1Addr:
637122394Sharti			return (ip_get(value, snmpd.trap1addr));
638124861Sharti		  case LEAF_begemotSnmpdVersionEnable:
639124861Sharti			value->v.uint32 = snmpd.version_enable;
640124861Sharti			break;
641122394Sharti		  default:
642122394Sharti			return (SNMP_ERR_NOSUCHNAME);
643122394Sharti		}
644122394Sharti		return (SNMP_ERR_NOERROR);
645122394Sharti
646122394Sharti	  case SNMP_OP_SET:
647122394Sharti		switch (which) {
648122394Sharti
649122394Sharti		  case LEAF_begemotSnmpdTransmitBuffer:
650122394Sharti			ctx->scratch->int1 = snmpd.txbuf;
651122394Sharti			if (value->v.integer < 484 ||
652122394Sharti			    value->v.integer > 65535)
653122394Sharti				return (SNMP_ERR_WRONG_VALUE);
654122394Sharti			snmpd.txbuf = value->v.integer;
655122394Sharti			return (SNMP_ERR_NOERROR);
656122394Sharti
657122394Sharti		  case LEAF_begemotSnmpdReceiveBuffer:
658122394Sharti			ctx->scratch->int1 = snmpd.rxbuf;
659122394Sharti			if (value->v.integer < 484 ||
660122394Sharti			    value->v.integer > 65535)
661122394Sharti				return (SNMP_ERR_WRONG_VALUE);
662122394Sharti			snmpd.rxbuf = value->v.integer;
663122394Sharti			return (SNMP_ERR_NOERROR);
664122394Sharti
665122394Sharti		  case LEAF_begemotSnmpdCommunityDisable:
666122394Sharti			ctx->scratch->int1 = snmpd.comm_dis;
667122394Sharti			if (!TRUTH_OK(value->v.integer))
668122394Sharti				return (SNMP_ERR_WRONG_VALUE);
669122394Sharti			if (TRUTH_GET(value->v.integer)) {
670122394Sharti				snmpd.comm_dis = 1;
671122394Sharti			} else {
672122394Sharti				if (snmpd.comm_dis)
673122394Sharti					return (SNMP_ERR_WRONG_VALUE);
674122394Sharti			}
675122394Sharti			return (SNMP_ERR_NOERROR);
676122394Sharti
677122394Sharti		  case LEAF_begemotSnmpdTrap1Addr:
678122394Sharti			return (ip_save(value, ctx, snmpd.trap1addr));
679124861Sharti
680124861Sharti		  case LEAF_begemotSnmpdVersionEnable:
681124861Sharti			if (community != COMM_INITIALIZE)
682124861Sharti				return (SNMP_ERR_NOT_WRITEABLE);
683124861Sharti			ctx->scratch->int1 = snmpd.version_enable;
684124861Sharti			if (value->v.uint32 == 0 ||
685124861Sharti			    (value->v.uint32 & ~VERS_ENABLE_ALL))
686124861Sharti				return (SNMP_ERR_WRONG_VALUE);
687124861Sharti			snmpd.version_enable = value->v.uint32;
688124861Sharti			return (SNMP_ERR_NOERROR);
689122394Sharti		}
690122394Sharti		abort();
691122394Sharti
692122394Sharti	  case SNMP_OP_ROLLBACK:
693122394Sharti		switch (which) {
694122394Sharti
695122394Sharti		  case LEAF_begemotSnmpdTransmitBuffer:
696122394Sharti			snmpd.rxbuf = ctx->scratch->int1;
697122394Sharti			return (SNMP_ERR_NOERROR);
698122394Sharti		  case LEAF_begemotSnmpdReceiveBuffer:
699122394Sharti			snmpd.txbuf = ctx->scratch->int1;
700122394Sharti			return (SNMP_ERR_NOERROR);
701122394Sharti		  case LEAF_begemotSnmpdCommunityDisable:
702122394Sharti			snmpd.comm_dis = ctx->scratch->int1;
703122394Sharti			return (SNMP_ERR_NOERROR);
704122394Sharti		  case LEAF_begemotSnmpdTrap1Addr:
705122394Sharti			ip_rollback(ctx, snmpd.trap1addr);
706122394Sharti			return (SNMP_ERR_NOERROR);
707124861Sharti		  case LEAF_begemotSnmpdVersionEnable:
708124861Sharti			snmpd.version_enable = ctx->scratch->int1;
709124861Sharti			return (SNMP_ERR_NOERROR);
710122394Sharti		}
711122394Sharti		abort();
712122394Sharti
713122394Sharti	  case SNMP_OP_COMMIT:
714122394Sharti		switch (which) {
715122394Sharti
716122394Sharti		  case LEAF_begemotSnmpdTransmitBuffer:
717122394Sharti		  case LEAF_begemotSnmpdReceiveBuffer:
718122394Sharti		  case LEAF_begemotSnmpdCommunityDisable:
719122394Sharti			return (SNMP_ERR_NOERROR);
720122394Sharti		  case LEAF_begemotSnmpdTrap1Addr:
721122394Sharti			ip_commit(ctx);
722122394Sharti			return (SNMP_ERR_NOERROR);
723124861Sharti		  case LEAF_begemotSnmpdVersionEnable:
724124861Sharti			return (SNMP_ERR_NOERROR);
725122394Sharti		}
726122394Sharti		abort();
727122394Sharti	}
728122394Sharti	abort();
729122394Sharti}
730122394Sharti
731122394Sharti/*
732122394Sharti * The community table
733122394Sharti */
734122394Shartiint
735122394Shartiop_community(struct snmp_context *ctx, struct snmp_value *value,
736122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
737122394Sharti{
738122394Sharti	asn_subid_t which = value->var.subs[sub - 1];
739122394Sharti	struct community *c;
740122394Sharti
741122394Sharti	switch (op) {
742122394Sharti
743122394Sharti	  case SNMP_OP_GETNEXT:
744122394Sharti		if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
745122394Sharti		    (c = NEXT_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
746122394Sharti			return (SNMP_ERR_NOSUCHNAME);
747122394Sharti		index_append(&value->var, sub, &c->index);
748122394Sharti		break;
749122394Sharti
750122394Sharti	  case SNMP_OP_GET:
751122394Sharti		if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
752122394Sharti		    (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
753122394Sharti			return (SNMP_ERR_NOSUCHNAME);
754122394Sharti		break;
755122394Sharti
756122394Sharti	  case SNMP_OP_SET:
757122394Sharti		if ((community != COMM_INITIALIZE && snmpd.comm_dis) ||
758122394Sharti		    (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL)
759122394Sharti			return (SNMP_ERR_NO_CREATION);
760122394Sharti		if (which != LEAF_begemotSnmpdCommunityString)
761122394Sharti			return (SNMP_ERR_NOT_WRITEABLE);
762122394Sharti		return (string_save(value, ctx, -1, &c->string));
763122394Sharti
764122394Sharti	  case SNMP_OP_ROLLBACK:
765122394Sharti		if (which == LEAF_begemotSnmpdCommunityString) {
766122394Sharti			if ((c = FIND_OBJECT_OID(&community_list, &value->var,
767122394Sharti			    sub)) == NULL)
768122394Sharti				string_free(ctx);
769122394Sharti			else
770122394Sharti				string_rollback(ctx, &c->string);
771122394Sharti			return (SNMP_ERR_NOERROR);
772122394Sharti		}
773122394Sharti		abort();
774122394Sharti
775122394Sharti	  case SNMP_OP_COMMIT:
776122394Sharti		if (which == LEAF_begemotSnmpdCommunityString) {
777122394Sharti			if ((c = FIND_OBJECT_OID(&community_list, &value->var,
778122394Sharti			    sub)) == NULL)
779122394Sharti				string_free(ctx);
780122394Sharti			else
781122394Sharti				string_commit(ctx);
782122394Sharti			return (SNMP_ERR_NOERROR);
783122394Sharti		}
784122394Sharti		abort();
785122394Sharti
786122394Sharti	  default:
787122394Sharti		abort();
788122394Sharti	}
789122394Sharti
790122394Sharti	switch (which) {
791122394Sharti
792122394Sharti	  case LEAF_begemotSnmpdCommunityString:
793122394Sharti		return (string_get(value, c->string, -1));
794122394Sharti
795122394Sharti	  case LEAF_begemotSnmpdCommunityDescr:
796122394Sharti		return (string_get(value, c->descr, -1));
797122394Sharti	}
798122394Sharti	abort();
799122394Sharti}
800122394Sharti
801122394Sharti/*
802122394Sharti * Module table.
803122394Sharti */
804122394Shartistruct module_dep {
805122394Sharti	struct snmp_dependency dep;
806122394Sharti	u_char	section[LM_SECTION_MAX + 1];
807122394Sharti	u_char	*path;
808122394Sharti	struct lmodule *m;
809122394Sharti};
810122394Sharti
811122394Shartistatic int
812122394Shartidep_modules(struct snmp_context *ctx, struct snmp_dependency *dep,
813122394Sharti    enum snmp_depop op)
814122394Sharti{
815122394Sharti	struct module_dep *mdep = (struct module_dep *)(void *)dep;
816122394Sharti
817122394Sharti	switch (op) {
818122394Sharti
819122394Sharti	  case SNMP_DEPOP_COMMIT:
820122394Sharti		if (mdep->path == NULL) {
821122394Sharti			/* unload - find the module */
822122394Sharti			TAILQ_FOREACH(mdep->m, &lmodules, link)
823128237Sharti				if (strcmp(mdep->m->section,
824128237Sharti				    mdep->section) == 0)
825122394Sharti					break;
826122394Sharti			if (mdep->m == NULL)
827128237Sharti				/* no such module - that's ok */
828122394Sharti				return (SNMP_ERR_NOERROR);
829128237Sharti
830128237Sharti			/* handle unloading in the finalizer */
831122394Sharti			return (SNMP_ERR_NOERROR);
832122394Sharti		}
833122394Sharti		/* load */
834128237Sharti		if ((mdep->m = lm_load(mdep->path, mdep->section)) == NULL) {
835128237Sharti			/* could not load */
836122394Sharti			return (SNMP_ERR_RES_UNAVAIL);
837122394Sharti		}
838128237Sharti		/* start in finalizer */
839122394Sharti		return (SNMP_ERR_NOERROR);
840122394Sharti
841122394Sharti	  case SNMP_DEPOP_ROLLBACK:
842122394Sharti		if (mdep->path == NULL) {
843128237Sharti			/* rollback unload - the finalizer takes care */
844122394Sharti			return (SNMP_ERR_NOERROR);
845122394Sharti		}
846122394Sharti		/* rollback load */
847122394Sharti		lm_unload(mdep->m);
848122394Sharti		return (SNMP_ERR_NOERROR);
849128237Sharti
850128237Sharti	  case SNMP_DEPOP_FINISH:
851128237Sharti		if (mdep->path == NULL) {
852128237Sharti			if (mdep->m != NULL && ctx->code == SNMP_RET_OK)
853128237Sharti				lm_unload(mdep->m);
854128237Sharti		} else {
855128237Sharti			if (mdep->m != NULL && ctx->code == SNMP_RET_OK &&
856128237Sharti			    community != COMM_INITIALIZE)
857128237Sharti				lm_start(mdep->m);
858128237Sharti			free(mdep->path);
859128237Sharti		}
860128237Sharti		return (SNMP_ERR_NOERROR);
861122394Sharti	}
862122394Sharti	abort();
863122394Sharti}
864122394Sharti
865122394Shartiint
866122394Shartiop_modules(struct snmp_context *ctx, struct snmp_value *value,
867122394Sharti    u_int sub, u_int iidx, enum snmp_op op)
868122394Sharti{
869122394Sharti	asn_subid_t which = value->var.subs[sub - 1];
870122394Sharti	struct lmodule *m;
871122394Sharti	u_char *section, *ptr;
872122394Sharti	size_t seclen;
873122394Sharti	struct module_dep *mdep;
874122394Sharti	struct asn_oid idx;
875122394Sharti
876122394Sharti	switch (op) {
877122394Sharti
878122394Sharti	  case SNMP_OP_GETNEXT:
879122394Sharti		if ((m = NEXT_OBJECT_OID(&lmodules, &value->var, sub)) == NULL)
880122394Sharti			return (SNMP_ERR_NOSUCHNAME);
881122394Sharti		index_append(&value->var, sub, &m->index);
882122394Sharti		break;
883122394Sharti
884122394Sharti	  case SNMP_OP_GET:
885122394Sharti		if ((m = FIND_OBJECT_OID(&lmodules, &value->var, sub)) == NULL)
886122394Sharti			return (SNMP_ERR_NOSUCHNAME);
887122394Sharti		break;
888122394Sharti
889122394Sharti	  case SNMP_OP_SET:
890122394Sharti		m = FIND_OBJECT_OID(&lmodules, &value->var, sub);
891122394Sharti		if (which != LEAF_begemotSnmpdModulePath) {
892122394Sharti			if (m == NULL)
893122394Sharti				return (SNMP_ERR_NO_CREATION);
894122394Sharti			return (SNMP_ERR_NOT_WRITEABLE);
895122394Sharti		}
896122394Sharti
897122394Sharti		/* the errors in the next few statements can only happen when
898122394Sharti		 * m is NULL, hence the NO_CREATION error. */
899122394Sharti		if (index_decode(&value->var, sub, iidx,
900122394Sharti		    &section, &seclen))
901122394Sharti			return (SNMP_ERR_NO_CREATION);
902122394Sharti
903122394Sharti		/* check the section name */
904122394Sharti		if (seclen > LM_SECTION_MAX || seclen == 0) {
905122394Sharti			free(section);
906122394Sharti			return (SNMP_ERR_NO_CREATION);
907122394Sharti		}
908122394Sharti		for (ptr = section; ptr < section + seclen; ptr++)
909122394Sharti			if (!isascii(*ptr) || !isalnum(*ptr)) {
910122394Sharti				free(section);
911122394Sharti				return (SNMP_ERR_NO_CREATION);
912122394Sharti			}
913122394Sharti		if (!isalpha(section[0])) {
914122394Sharti			free(section);
915122394Sharti			return (SNMP_ERR_NO_CREATION);
916122394Sharti		}
917122394Sharti
918122394Sharti		/* check the path */
919122394Sharti		for (ptr = value->v.octetstring.octets;
920122394Sharti		     ptr < value->v.octetstring.octets + value->v.octetstring.len;
921122394Sharti		     ptr++) {
922122394Sharti			if (*ptr == '\0') {
923122394Sharti				free(section);
924122394Sharti				return (SNMP_ERR_WRONG_VALUE);
925122394Sharti			}
926122394Sharti		}
927122394Sharti
928122394Sharti		if (m == NULL) {
929122394Sharti			if (value->v.octetstring.len == 0) {
930122394Sharti				free(section);
931122394Sharti				return (SNMP_ERR_INCONS_VALUE);
932122394Sharti			}
933122394Sharti		} else {
934122394Sharti			if (value->v.octetstring.len != 0) {
935122394Sharti				free(section);
936122394Sharti				return (SNMP_ERR_INCONS_VALUE);
937122394Sharti			}
938122394Sharti		}
939122394Sharti
940122394Sharti		asn_slice_oid(&idx, &value->var, sub, value->var.len);
941122394Sharti
942122394Sharti		/* so far, so good */
943122394Sharti		mdep = (struct module_dep *)(void *)snmp_dep_lookup(ctx,
944122394Sharti		    &oid_begemotSnmpdModuleTable, &idx,
945122394Sharti		    sizeof(*mdep), dep_modules);
946122394Sharti		if (mdep == NULL) {
947122394Sharti			free(section);
948122394Sharti			return (SNMP_ERR_RES_UNAVAIL);
949122394Sharti		}
950122394Sharti
951122394Sharti		if (mdep->section[0] != '\0') {
952122394Sharti			/* two writes to the same entry - bad */
953122394Sharti			free(section);
954122394Sharti			return (SNMP_ERR_INCONS_VALUE);
955122394Sharti		}
956122394Sharti
957122394Sharti		strncpy(mdep->section, section, seclen);
958122394Sharti		mdep->section[seclen] = '\0';
959122394Sharti		free(section);
960122394Sharti
961122394Sharti		if (value->v.octetstring.len == 0)
962122394Sharti			mdep->path = NULL;
963122394Sharti		else {
964122394Sharti			if ((mdep->path = malloc(value->v.octetstring.len + 1)) == NULL)
965122394Sharti				return (SNMP_ERR_RES_UNAVAIL);
966122394Sharti			strncpy(mdep->path, value->v.octetstring.octets,
967122394Sharti			    value->v.octetstring.len);
968122394Sharti			mdep->path[value->v.octetstring.len] = '\0';
969122394Sharti		}
970122394Sharti		ctx->scratch->ptr1 = mdep;
971122394Sharti		return (SNMP_ERR_NOERROR);
972122394Sharti
973122394Sharti	  case SNMP_OP_ROLLBACK:
974122394Sharti	  case SNMP_OP_COMMIT:
975122394Sharti		return (SNMP_ERR_NOERROR);
976122394Sharti
977122394Sharti	  default:
978122394Sharti		abort();
979122394Sharti	}
980122394Sharti
981122394Sharti	switch (which) {
982122394Sharti
983122394Sharti	  case LEAF_begemotSnmpdModulePath:
984122394Sharti		return (string_get(value, m->path, -1));
985122394Sharti
986122394Sharti	  case LEAF_begemotSnmpdModuleComment:
987122394Sharti		return (string_get(value, m->config->comment, -1));
988122394Sharti	}
989122394Sharti	abort();
990122394Sharti}
991122394Sharti
992122394Shartiint
993122394Shartiop_snmp_set(struct snmp_context *ctx __unused, struct snmp_value *value,
994122394Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
995122394Sharti{
996122394Sharti	switch (op) {
997122394Sharti
998122394Sharti	  case SNMP_OP_GETNEXT:
999122394Sharti		abort();
1000122394Sharti
1001122394Sharti	  case SNMP_OP_GET:
1002122394Sharti		switch (value->var.subs[sub - 1]) {
1003122394Sharti
1004122394Sharti		  case LEAF_snmpSetSerialNo:
1005122394Sharti			value->v.integer = snmp_serial_no;
1006122394Sharti			break;
1007122394Sharti
1008122394Sharti		  default:
1009122394Sharti			abort();
1010122394Sharti		}
1011122394Sharti		return (SNMP_ERR_NOERROR);
1012122394Sharti
1013122394Sharti	  case SNMP_OP_SET:
1014122394Sharti		switch (value->var.subs[sub - 1]) {
1015122394Sharti
1016122394Sharti		  case LEAF_snmpSetSerialNo:
1017122394Sharti			if (value->v.integer != snmp_serial_no)
1018122394Sharti				return (SNMP_ERR_INCONS_VALUE);
1019122394Sharti			break;
1020122394Sharti
1021122394Sharti		  default:
1022122394Sharti			abort();
1023122394Sharti		}
1024122394Sharti		return (SNMP_ERR_NOERROR);
1025122394Sharti
1026122394Sharti	  case SNMP_OP_ROLLBACK:
1027122394Sharti		return (SNMP_ERR_NOERROR);
1028122394Sharti
1029122394Sharti	  case SNMP_OP_COMMIT:
1030122394Sharti		if (snmp_serial_no++ == 2147483647)
1031122394Sharti			snmp_serial_no = 0;
1032122394Sharti		return (SNMP_ERR_NOERROR);
1033122394Sharti	}
1034122394Sharti	abort();
1035122394Sharti}
1036124861Sharti
1037124861Sharti/*
1038216294Ssyrinx * SNMP Engine
1039216294Ssyrinx */
1040216294Ssyrinxint
1041216294Ssyrinxop_snmp_engine(struct snmp_context *ctx __unused, struct snmp_value *value,
1042216294Ssyrinx    u_int sub, u_int iidx __unused, enum snmp_op op)
1043216294Ssyrinx{
1044216294Ssyrinx	asn_subid_t which = value->var.subs[sub - 1];
1045216294Ssyrinx
1046216294Ssyrinx	switch (op) {
1047216294Ssyrinx	case SNMP_OP_GETNEXT:
1048216294Ssyrinx		abort();
1049216294Ssyrinx
1050216294Ssyrinx	case SNMP_OP_GET:
1051216294Ssyrinx		break;
1052216294Ssyrinx
1053216294Ssyrinx	case SNMP_OP_SET:
1054216294Ssyrinx		if (community != COMM_INITIALIZE)
1055216294Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
1056216294Ssyrinx		switch (which) {
1057216294Ssyrinx		case LEAF_snmpEngineID:
1058216294Ssyrinx			if (value->v.octetstring.len > SNMP_ENGINE_ID_SIZ)
1059216294Ssyrinx				return (SNMP_ERR_WRONG_VALUE);
1060216294Ssyrinx			ctx->scratch->ptr1 = malloc(snmpd_engine.engine_len);
1061216294Ssyrinx			if (ctx->scratch->ptr1 == NULL)
1062216294Ssyrinx				return (SNMP_ERR_GENERR);
1063216294Ssyrinx			memcpy(ctx->scratch->ptr1, snmpd_engine.engine_id,
1064216294Ssyrinx			    snmpd_engine.engine_len);
1065216294Ssyrinx			ctx->scratch->int1 = snmpd_engine.engine_len;
1066216294Ssyrinx			snmpd_engine.engine_len = value->v.octetstring.len;
1067216294Ssyrinx			memcpy(snmpd_engine.engine_id,
1068216294Ssyrinx			    value->v.octetstring.octets,
1069216294Ssyrinx			    value->v.octetstring.len);
1070216294Ssyrinx			break;
1071216294Ssyrinx
1072216294Ssyrinx		case LEAF_snmpEngineMaxMessageSize:
1073216294Ssyrinx			ctx->scratch->int1 = snmpd_engine.max_msg_size;
1074216294Ssyrinx			snmpd_engine.max_msg_size = value->v.integer;
1075216294Ssyrinx			break;
1076216294Ssyrinx
1077216294Ssyrinx		default:
1078216294Ssyrinx			return (SNMP_ERR_NOT_WRITEABLE);
1079216294Ssyrinx		}
1080216294Ssyrinx		return (SNMP_ERR_NOERROR);
1081216294Ssyrinx
1082216294Ssyrinx	case SNMP_OP_ROLLBACK:
1083216294Ssyrinx		switch (which) {
1084216294Ssyrinx		case LEAF_snmpEngineID:
1085216294Ssyrinx			snmpd_engine.engine_len = ctx->scratch->int1;
1086216294Ssyrinx			memcpy(snmpd_engine.engine_id, ctx->scratch->ptr1,
1087216294Ssyrinx			    snmpd_engine.engine_len);
1088216294Ssyrinx			free(ctx->scratch->ptr1);
1089216294Ssyrinx			break;
1090216294Ssyrinx
1091216294Ssyrinx		case LEAF_snmpEngineMaxMessageSize:
1092216294Ssyrinx			snmpd_engine.max_msg_size = ctx->scratch->int1;
1093216294Ssyrinx			break;
1094216294Ssyrinx
1095216294Ssyrinx		default:
1096216294Ssyrinx			abort();
1097216294Ssyrinx		}
1098216294Ssyrinx		return (SNMP_ERR_NOERROR);
1099216294Ssyrinx
1100216294Ssyrinx	case SNMP_OP_COMMIT:
1101216294Ssyrinx		if (which == LEAF_snmpEngineID) {
1102216294Ssyrinx			if (set_snmpd_engine() < 0) {
1103216294Ssyrinx				snmpd_engine.engine_len = ctx->scratch->int1;
1104216294Ssyrinx				memcpy(snmpd_engine.engine_id,
1105216294Ssyrinx				    ctx->scratch->ptr1, ctx->scratch->int1);
1106216294Ssyrinx			}
1107216294Ssyrinx			free(ctx->scratch->ptr1);
1108216294Ssyrinx		}
1109216294Ssyrinx		return (SNMP_ERR_NOERROR);
1110216294Ssyrinx	}
1111216294Ssyrinx
1112216294Ssyrinx
1113216294Ssyrinx	switch (which) {
1114216294Ssyrinx	case LEAF_snmpEngineID:
1115216294Ssyrinx		return (string_get(value, snmpd_engine.engine_id,
1116216294Ssyrinx		    snmpd_engine.engine_len));
1117216294Ssyrinx	case LEAF_snmpEngineBoots:
1118216294Ssyrinx		value->v.integer = snmpd_engine.engine_boots;
1119216294Ssyrinx		break;
1120216294Ssyrinx	case LEAF_snmpEngineTime:
1121216294Ssyrinx		snmpd_engine.engine_time = (get_ticks() - start_tick) / 100ULL;
1122216294Ssyrinx		value->v.integer = snmpd_engine.engine_time;
1123216294Ssyrinx		break;
1124216294Ssyrinx	case LEAF_snmpEngineMaxMessageSize:
1125216294Ssyrinx		value->v.integer = snmpd_engine.max_msg_size;
1126216294Ssyrinx		break;
1127216294Ssyrinx	default:
1128216294Ssyrinx		return (SNMP_ERR_NOSUCHNAME);
1129216294Ssyrinx	}
1130216294Ssyrinx
1131216294Ssyrinx	return (SNMP_ERR_NOERROR);
1132216294Ssyrinx}
1133216294Ssyrinx
1134216294Ssyrinx/*
1135124861Sharti * Transport table
1136124861Sharti */
1137124861Shartiint
1138124861Shartiop_transport_table(struct snmp_context *ctx __unused, struct snmp_value *value,
1139124861Sharti    u_int sub, u_int iidx, enum snmp_op op)
1140124861Sharti{
1141124861Sharti	asn_subid_t which = value->var.subs[sub - 1];
1142124861Sharti	struct transport *t;
1143124861Sharti	u_char *tname, *ptr;
1144124861Sharti	size_t tnamelen;
1145124861Sharti
1146124861Sharti	switch (op) {
1147124861Sharti
1148124861Sharti	  case SNMP_OP_GETNEXT:
1149124861Sharti		if ((t = NEXT_OBJECT_OID(&transport_list, &value->var, sub))
1150124861Sharti		    == NULL)
1151124861Sharti			return (SNMP_ERR_NOSUCHNAME);
1152124861Sharti		index_append(&value->var, sub, &t->index);
1153124861Sharti		break;
1154124861Sharti
1155124861Sharti	  case SNMP_OP_GET:
1156124861Sharti		if ((t = FIND_OBJECT_OID(&transport_list, &value->var, sub))
1157124861Sharti		    == NULL)
1158124861Sharti			return (SNMP_ERR_NOSUCHNAME);
1159124861Sharti		break;
1160124861Sharti
1161124861Sharti	  case SNMP_OP_SET:
1162124861Sharti		t = FIND_OBJECT_OID(&transport_list, &value->var, sub);
1163124861Sharti		if (which != LEAF_begemotSnmpdTransportStatus) {
1164124861Sharti			if (t == NULL)
1165124861Sharti				return (SNMP_ERR_NO_CREATION);
1166124861Sharti			return (SNMP_ERR_NOT_WRITEABLE);
1167124861Sharti		}
1168124861Sharti
1169124861Sharti		/* the errors in the next few statements can only happen when
1170124861Sharti		 * t is NULL, hence the NO_CREATION error. */
1171124861Sharti		if (index_decode(&value->var, sub, iidx,
1172124861Sharti		    &tname, &tnamelen))
1173124861Sharti			return (SNMP_ERR_NO_CREATION);
1174124861Sharti
1175124861Sharti		/* check the section name */
1176124861Sharti		if (tnamelen >= TRANS_NAMELEN || tnamelen == 0) {
1177124861Sharti			free(tname);
1178124861Sharti			return (SNMP_ERR_NO_CREATION);
1179124861Sharti		}
1180124861Sharti		for (ptr = tname; ptr < tname + tnamelen; ptr++) {
1181124861Sharti			if (!isascii(*ptr) || !isalnum(*ptr)) {
1182124861Sharti				free(tname);
1183124861Sharti				return (SNMP_ERR_NO_CREATION);
1184124861Sharti			}
1185124861Sharti		}
1186124861Sharti
1187124861Sharti		/* for now */
1188124861Sharti		return (SNMP_ERR_NOT_WRITEABLE);
1189124861Sharti
1190124861Sharti	  case SNMP_OP_ROLLBACK:
1191124861Sharti	  case SNMP_OP_COMMIT:
1192124861Sharti		return (SNMP_ERR_NOERROR);
1193124861Sharti	  default:
1194124861Sharti		abort();
1195124861Sharti	}
1196124861Sharti
1197124861Sharti	switch (which) {
1198124861Sharti
1199124861Sharti	    case LEAF_begemotSnmpdTransportStatus:
1200124861Sharti		value->v.integer = 1;
1201124861Sharti		break;
1202124861Sharti
1203124861Sharti	    case LEAF_begemotSnmpdTransportOid:
1204124861Sharti		memcpy(&value->v.oid, &t->vtab->id, sizeof(t->vtab->id));
1205124861Sharti		break;
1206124861Sharti	}
1207124861Sharti	return (SNMP_ERR_NOERROR);
1208124861Sharti}
1209