1250379Strociny/*-
2250379Strociny * Copyright (c) 2013 Mikolaj Golub <trociny@FreeBSD.org>
3250379Strociny * All rights reserved.
4250379Strociny *
5250379Strociny * Redistribution and use in source and binary forms, with or without
6250379Strociny * modification, are permitted provided that the following conditions
7250379Strociny * are met:
8250379Strociny * 1. Redistributions of source code must retain the above copyright
9250379Strociny *    notice, this list of conditions and the following disclaimer.
10250379Strociny * 2. Redistributions in binary form must reproduce the above copyright
11250379Strociny *    notice, this list of conditions and the following disclaimer in the
12250379Strociny *    documentation and/or other materials provided with the distribution.
13250379Strociny *
14250379Strociny * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
15250379Strociny * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16250379Strociny * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17250379Strociny * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18250379Strociny * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19250379Strociny * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20250379Strociny * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21250379Strociny * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22250379Strociny * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23250379Strociny * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24250379Strociny * SUCH DAMAGE.
25250379Strociny */
26250379Strociny
27250379Strociny#include <sys/cdefs.h>
28250379Strociny__FBSDID("$FreeBSD: releng/10.3/usr.sbin/bsnmpd/modules/snmp_hast/hast_snmp.c 260412 2014-01-07 21:23:41Z trociny $");
29250379Strociny
30250379Strociny#include <sys/param.h>
31250379Strociny#include <sys/queue.h>
32250379Strociny
33250379Strociny#include <bsnmp/snmpmod.h>
34250379Strociny
35250379Strociny#include <string.h>
36250379Strociny
37250379Strociny#include "hast.h"
38250379Strociny#include "hast_oid.h"
39250379Strociny#include "hast_proto.h"
40250379Strociny#include "hast_tree.h"
41250379Strociny#include "nv.h"
42250379Strociny#include "pjdlog.h"
43250379Strociny#include "proto.h"
44250379Strociny
45250379Strociny#define UPDATE_INTERVAL	500	/* update interval in ticks */
46250379Strociny
47250379Strocinystatic struct lmodule *module;
48250379Strociny
49250379Strocinystatic const struct asn_oid oid_hast = OIDX_begemotHast;
50250379Strociny
51250379Strociny/* the Object Resource registration index */
52250379Strocinystatic u_int hast_index = 0;
53250379Strociny
54250379Strociny/*
55250379Strociny * Structure that describes single resource.
56250379Strociny */
57250379Strocinystruct hast_snmp_resource {
58250379Strociny	TAILQ_ENTRY(hast_snmp_resource) link;
59250379Strociny	int32_t		index;
60250379Strociny	char		name[NAME_MAX];
61250379Strociny	int		error;
62250379Strociny	int		role;
63250379Strociny	char		provname[NAME_MAX];
64250379Strociny	char		localpath[PATH_MAX];
65250379Strociny	int32_t		extentsize;
66250379Strociny	int32_t		keepdirty;
67250379Strociny	char		remoteaddr[HAST_ADDRSIZE];
68250379Strociny	char		sourceaddr[HAST_ADDRSIZE];
69250379Strociny	int		replication;
70250379Strociny	int		status;
71250379Strociny	uint64_t	dirty;
72250379Strociny	uint64_t	reads;
73250379Strociny	uint64_t	writes;
74250379Strociny	uint64_t	deletes;
75250379Strociny	uint64_t	flushes;
76250379Strociny	uint64_t	activemap_updates;
77250379Strociny	uint64_t	read_errors;
78250379Strociny	uint64_t	write_errors;
79250379Strociny	uint64_t	delete_errors;
80250379Strociny	uint64_t	flush_errors;
81252516Strociny	pid_t		workerpid;
82260412Strociny	uint32_t	local_queue;
83260412Strociny	uint32_t	send_queue;
84260412Strociny	uint32_t	recv_queue;
85260412Strociny	uint32_t	done_queue;
86260412Strociny	uint32_t	idle_queue;
87250379Strociny};
88250379Strociny
89250379Strocinystatic TAILQ_HEAD(, hast_snmp_resource) resources =
90250379Strociny    TAILQ_HEAD_INITIALIZER(resources);
91250379Strociny
92250379Strociny/* Path to configuration file. */
93250379Strocinystatic u_char *cfgpath;
94250379Strociny/* Ticks of the last hast resources update. */
95250379Strocinystatic uint64_t last_resources_update;
96250379Strociny
97250379Strocinystatic void free_resources(void);
98250379Strocinystatic int hastctl(struct nv *nvin, struct nv **nvout);
99250379Strocinystatic int hast_fini(void);
100250379Strocinystatic int hast_init(struct lmodule *mod, int argc, char *argv[]);
101250379Strocinystatic void hast_start(void);
102250379Strocinystatic int set_role(const char *resource, int role);
103250379Strocinystatic int str2role(const char *str);
104250379Strocinystatic int str2replication(const char *str);
105250379Strocinystatic int str2status(const char *str);
106250379Strocinystatic int update_resources(void);
107250379Strociny
108250379Strocinyconst struct snmp_module config = {
109250379Strociny    .comment   = "This module implements the BEGEMOT MIB for HAST.",
110250379Strociny    .init      = hast_init,
111250379Strociny    .start     = hast_start,
112250379Strociny    .fini      = hast_fini,
113250379Strociny    .tree      = hast_ctree,
114250379Strociny    .tree_size = hast_CTREE_SIZE,
115250379Strociny};
116250379Strociny
117250379Strocinystatic int
118250379Strocinyhast_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
119250379Strociny{
120250379Strociny
121250379Strociny	module = mod;
122250379Strociny
123250379Strociny	pjdlog_init(PJDLOG_MODE_SYSLOG);
124250379Strociny	pjdlog_debug_set(0);
125250379Strociny
126250379Strociny	cfgpath = malloc(sizeof(HAST_CONFIG));
127250379Strociny	if (cfgpath == NULL) {
128250379Strociny		pjdlog_error("Unable to allocate %zu bytes for cfgpath",
129250379Strociny		    sizeof(HAST_CONFIG));
130250379Strociny		return (-1);
131250379Strociny	}
132250379Strociny	strcpy(cfgpath, HAST_CONFIG);
133250379Strociny	return(0);
134250379Strociny}
135250379Strociny
136250379Strocinystatic void
137250379Strocinyhast_start(void)
138250379Strociny{
139250379Strociny	hast_index = or_register(&oid_hast,
140250379Strociny	    "The MIB module for BEGEMOT-HAST-MIB.", module);
141250379Strociny}
142250379Strociny
143250379Strocinystatic int
144250379Strocinyhast_fini(void)
145250379Strociny{
146250379Strociny
147250379Strociny	or_unregister(hast_index);
148250379Strociny	free_resources();
149250379Strociny	free(cfgpath);
150250379Strociny	return (0);
151250379Strociny}
152250379Strociny
153250379Strocinystatic void
154250379Strocinyfree_resources(void)
155250379Strociny{
156250379Strociny	struct hast_snmp_resource *res;
157250379Strociny
158250379Strociny	while ((res = TAILQ_FIRST(&resources)) != NULL) {
159250379Strociny		TAILQ_REMOVE(&resources, res, link);
160250379Strociny		free(res);
161250379Strociny	}
162250379Strociny}
163250379Strociny
164250379Strocinystatic int
165250379Strocinystr2role(const char *str)
166250379Strociny{
167250379Strociny
168250379Strociny	if (strcmp(str, "init") == 0)
169250379Strociny		return (HAST_ROLE_INIT);
170250379Strociny	if (strcmp(str, "primary") == 0)
171250379Strociny		return (HAST_ROLE_PRIMARY);
172250379Strociny	if (strcmp(str, "secondary") == 0)
173250379Strociny		return (HAST_ROLE_SECONDARY);
174250379Strociny	return (HAST_ROLE_UNDEF);
175250379Strociny}
176250379Strociny
177250379Strocinystatic int
178250379Strocinystr2replication(const char *str)
179250379Strociny{
180250379Strociny
181250379Strociny	if (strcmp(str, "fullsync") == 0)
182250379Strociny		return (HAST_REPLICATION_FULLSYNC);
183250379Strociny	if (strcmp(str, "memsync") == 0)
184250379Strociny		return (HAST_REPLICATION_MEMSYNC);
185250379Strociny	if (strcmp(str, "async") == 0)
186250379Strociny		return (HAST_REPLICATION_ASYNC);
187250379Strociny	return (-1);
188250379Strociny}
189250379Strociny
190250379Strocinystatic int
191250379Strocinystr2status(const char *str)
192250379Strociny{
193250379Strociny
194250379Strociny	if (strcmp(str, "complete") == 0)
195250379Strociny		return (0);
196250379Strociny	if (strcmp(str, "degraded") == 0)
197250379Strociny		return (1);
198250379Strociny	return (-1);
199250379Strociny}
200250379Strociny
201250379Strocinystatic int
202250379Strocinyhastctl(struct nv *nvin, struct nv **nvout)
203250379Strociny{
204250379Strociny	struct hastd_config *cfg;
205250379Strociny	struct proto_conn *conn;
206250379Strociny	struct nv *nv;
207250379Strociny	int error;
208250379Strociny
209250379Strociny	cfg = yy_config_parse(cfgpath, true);
210250379Strociny	if (cfg == NULL)
211250379Strociny		return (-1);
212250379Strociny
213250379Strociny	/* Setup control connection... */
214250379Strociny	if (proto_client(NULL, cfg->hc_controladdr, &conn) == -1) {
215250379Strociny		pjdlog_error("Unable to setup control connection to %s",
216250379Strociny		    cfg->hc_controladdr);
217250379Strociny		return (-1);
218250379Strociny	}
219250379Strociny	/* ...and connect to hastd. */
220250379Strociny	if (proto_connect(conn, HAST_TIMEOUT) == -1) {
221250379Strociny		pjdlog_error("Unable to connect to hastd via %s",
222250379Strociny		    cfg->hc_controladdr);
223250379Strociny		proto_close(conn);
224250379Strociny		return (-1);
225250379Strociny	}
226250379Strociny	/* Send the command to the server... */
227250379Strociny	if (hast_proto_send(NULL, conn, nvin, NULL, 0) == -1) {
228250379Strociny		pjdlog_error("Unable to send command to hastd via %s",
229250379Strociny		    cfg->hc_controladdr);
230250379Strociny		proto_close(conn);
231250379Strociny		return (-1);
232250379Strociny	}
233250379Strociny	/* ...and receive reply. */
234250379Strociny	if (hast_proto_recv_hdr(conn, &nv) == -1) {
235250379Strociny		pjdlog_error("cannot receive reply from hastd via %s",
236250379Strociny		    cfg->hc_controladdr);
237250379Strociny		proto_close(conn);
238250379Strociny		return (-1);
239250379Strociny	}
240250379Strociny	proto_close(conn);
241250379Strociny	error = nv_get_int16(nv, "error");
242250379Strociny	if (error != 0) {
243250379Strociny		pjdlog_error("Error %d received from hastd.", error);
244250379Strociny		nv_free(nv);
245250379Strociny		return (-1);
246250379Strociny	}
247250379Strociny	nv_set_error(nv, 0);
248250379Strociny	*nvout = nv;
249250379Strociny	return (0);
250250379Strociny}
251250379Strociny
252250379Strocinystatic int
253250379Strocinyset_role(const char *resource, int role)
254250379Strociny{
255250379Strociny	struct nv *nvin, *nvout;
256250379Strociny	int error;
257250379Strociny
258250379Strociny	nvin = nv_alloc();
259250379Strociny	nv_add_string(nvin, resource, "resource%d", 0);
260250379Strociny	nv_add_uint8(nvin, HASTCTL_CMD_SETROLE, "cmd");
261250379Strociny	nv_add_uint8(nvin, role, "role");
262250379Strociny	error = hastctl(nvin, &nvout);
263250379Strociny	nv_free(nvin);
264250379Strociny	if (error != 0)
265250379Strociny		return (-1);
266250379Strociny	nv_free(nvout);
267250379Strociny	return (SNMP_ERR_NOERROR);
268250379Strociny}
269250379Strociny
270250379Strocinystatic int
271250379Strocinyupdate_resources(void)
272250379Strociny{
273250379Strociny	struct hast_snmp_resource *res;
274250379Strociny	struct nv *nvin, *nvout;
275250379Strociny	static uint64_t now;
276250379Strociny	unsigned int i;
277250379Strociny	const char *str;
278250379Strociny	int error;
279250379Strociny
280250379Strociny	now = get_ticks();
281250379Strociny	if (now - last_resources_update < UPDATE_INTERVAL)
282250379Strociny		return (0);
283250379Strociny
284250379Strociny	last_resources_update = now;
285250379Strociny
286250379Strociny	free_resources();
287250379Strociny
288250379Strociny	nvin = nv_alloc();
289250379Strociny	nv_add_uint8(nvin, HASTCTL_CMD_STATUS, "cmd");
290250379Strociny	nv_add_string(nvin, "all", "resource%d", 0);
291250379Strociny	error = hastctl(nvin, &nvout);
292250379Strociny	nv_free(nvin);
293250379Strociny	if (error != 0)
294250379Strociny		return (-1);
295250379Strociny
296250379Strociny	for (i = 0; ; i++) {
297250379Strociny		str = nv_get_string(nvout, "resource%u", i);
298250379Strociny		if (str == NULL)
299250379Strociny			break;
300250379Strociny		res = calloc(1, sizeof(*res));
301250379Strociny		if (res == NULL) {
302250379Strociny			pjdlog_error("Unable to allocate %zu bytes for "
303250379Strociny			    "resource", sizeof(*res));
304250379Strociny			return (-1);
305250379Strociny		}
306250379Strociny		res->index = i + 1;
307250379Strociny		strncpy(res->name, str, sizeof(res->name) - 1);
308250379Strociny		error = nv_get_int16(nvout, "error%u", i);
309250379Strociny		if (error != 0)
310250379Strociny			continue;
311250379Strociny		str = nv_get_string(nvout, "role%u", i);
312250379Strociny		res->role = str != NULL ? str2role(str) : HAST_ROLE_UNDEF;
313250379Strociny		str = nv_get_string(nvout, "provname%u", i);
314250379Strociny		if (str != NULL)
315250379Strociny			strncpy(res->provname, str, sizeof(res->provname) - 1);
316250379Strociny		str = nv_get_string(nvout, "localpath%u", i);
317250379Strociny		if (str != NULL) {
318250379Strociny			strncpy(res->localpath, str,
319250379Strociny			    sizeof(res->localpath) - 1);
320250379Strociny		}
321250379Strociny		res->extentsize = nv_get_uint32(nvout, "extentsize%u", i);
322250379Strociny		res->keepdirty = nv_get_uint32(nvout, "keepdirty%u", i);
323250379Strociny		str = nv_get_string(nvout, "remoteaddr%u", i);
324250379Strociny		if (str != NULL) {
325250379Strociny			strncpy(res->remoteaddr, str,
326250379Strociny			    sizeof(res->remoteaddr) - 1);
327250379Strociny		}
328250379Strociny		str = nv_get_string(nvout, "sourceaddr%u", i);
329250379Strociny		if (str != NULL) {
330250379Strociny			strncpy(res->sourceaddr, str,
331250379Strociny			    sizeof(res->sourceaddr) - 1);
332250379Strociny		}
333250379Strociny		str = nv_get_string(nvout, "replication%u", i);
334250379Strociny		res->replication = str != NULL ? str2replication(str) : -1;
335250379Strociny		str = nv_get_string(nvout, "status%u", i);
336250379Strociny		res->status = str != NULL ? str2status(str) : -1;
337250379Strociny		res->dirty = nv_get_uint64(nvout, "dirty%u", i);
338250379Strociny		res->reads = nv_get_uint64(nvout, "stat_read%u", i);
339250379Strociny		res->writes = nv_get_uint64(nvout, "stat_write%u", i);
340250379Strociny		res->deletes = nv_get_uint64(nvout, "stat_delete%u", i);
341250379Strociny		res->flushes = nv_get_uint64(nvout, "stat_flush%u", i);
342250379Strociny		res->activemap_updates =
343250379Strociny		    nv_get_uint64(nvout, "stat_activemap_update%u", i);
344250379Strociny		res->read_errors =
345250379Strociny		    nv_get_uint64(nvout, "stat_read_error%u", i);
346250379Strociny		res->write_errors =
347250379Strociny		    nv_get_uint64(nvout, "stat_write_error%u", i);
348250379Strociny		res->delete_errors =
349250379Strociny		    nv_get_uint64(nvout, "stat_delete_error%u", i);
350250379Strociny		res->flush_errors =
351250379Strociny		    nv_get_uint64(nvout, "stat_flush_error%u", i);
352252516Strociny		res->workerpid = nv_get_int32(nvout, "workerpid%u", i);
353260412Strociny		res->local_queue =
354260412Strociny		    nv_get_uint64(nvout, "local_queue_size%u", i);
355260412Strociny		res->send_queue =
356260412Strociny		    nv_get_uint64(nvout, "send_queue_size%u", i);
357260412Strociny		res->recv_queue =
358260412Strociny		    nv_get_uint64(nvout, "recv_queue_size%u", i);
359260412Strociny		res->done_queue =
360260412Strociny		    nv_get_uint64(nvout, "done_queue_size%u", i);
361260412Strociny		res->idle_queue =
362260412Strociny		    nv_get_uint64(nvout, "idle_queue_size%u", i);
363250379Strociny		TAILQ_INSERT_TAIL(&resources, res, link);
364250379Strociny	}
365250379Strociny	nv_free(nvout);
366250379Strociny	return (0);
367250379Strociny}
368250379Strociny
369250379Strocinyint
370250379Strocinyop_hastConfig(struct snmp_context *context, struct snmp_value *value,
371250379Strociny    u_int sub, u_int iidx __unused, enum snmp_op op)
372250379Strociny{
373250379Strociny	asn_subid_t which;
374250379Strociny
375250379Strociny	which = value->var.subs[sub - 1];
376250379Strociny
377250379Strociny	switch (op) {
378250379Strociny	case SNMP_OP_GET:
379250379Strociny		switch (which) {
380250379Strociny		case LEAF_hastConfigFile:
381250379Strociny			return (string_get(value, cfgpath, -1));
382250379Strociny		default:
383250379Strociny			return (SNMP_ERR_RES_UNAVAIL);
384250379Strociny		}
385250379Strociny	case SNMP_OP_SET:
386250379Strociny		switch (which) {
387250379Strociny		case LEAF_hastConfigFile:
388250379Strociny			return (string_save(value, context, -1,
389250379Strociny			    (u_char **)&cfgpath));
390250379Strociny		default:
391250379Strociny			return (SNMP_ERR_RES_UNAVAIL);
392250379Strociny		}
393250379Strociny	case SNMP_OP_GETNEXT:
394250379Strociny	case SNMP_OP_ROLLBACK:
395250379Strociny	case SNMP_OP_COMMIT:
396250379Strociny		return (SNMP_ERR_NOERROR);
397250379Strociny	default:
398250379Strociny		return (SNMP_ERR_RES_UNAVAIL);
399250379Strociny	}
400250379Strociny}
401250379Strociny
402250379Strocinyint
403250379Strocinyop_hastResourceTable(struct snmp_context *context __unused,
404250379Strociny    struct snmp_value *value, u_int sub, u_int iidx __unused, enum snmp_op op)
405250379Strociny{
406250379Strociny	struct hast_snmp_resource *res;
407250379Strociny	asn_subid_t which;
408250379Strociny	int ret;
409250379Strociny
410250379Strociny	if (update_resources() == -1)
411250379Strociny		return (SNMP_ERR_RES_UNAVAIL);
412250379Strociny
413250379Strociny	which = value->var.subs[sub - 1];
414250379Strociny
415250379Strociny	switch (op) {
416250379Strociny	case SNMP_OP_GETNEXT:
417250379Strociny		res = NEXT_OBJECT_INT(&resources, &value->var, sub);
418250379Strociny		if (res == NULL)
419250379Strociny			return (SNMP_ERR_NOSUCHNAME);
420250379Strociny		value->var.len = sub + 1;
421250379Strociny		value->var.subs[sub] = res->index;
422250379Strociny		break;
423250379Strociny	case SNMP_OP_GET:
424250379Strociny		if (value->var.len - sub != 1)
425250379Strociny			return (SNMP_ERR_NOSUCHNAME);
426250379Strociny		res = FIND_OBJECT_INT(&resources, &value->var, sub);
427250379Strociny		if (res == NULL)
428250379Strociny			return (SNMP_ERR_NOSUCHNAME);
429250379Strociny		break;
430250379Strociny	case SNMP_OP_SET:
431250379Strociny		res = FIND_OBJECT_INT(&resources, &value->var, sub);
432250379Strociny		if (res == NULL)
433250379Strociny			return (SNMP_ERR_NOSUCHNAME);
434250379Strociny		switch (which) {
435250379Strociny		case LEAF_hastResourceRole:
436250379Strociny			ret = set_role(res->name, value->v.integer);
437250379Strociny			/* force update on next run */
438250379Strociny			last_resources_update = 0;
439250379Strociny			break;
440250379Strociny		default:
441250379Strociny			ret = SNMP_ERR_NOT_WRITEABLE;
442250379Strociny			break;
443250379Strociny		}
444250379Strociny		return ret;
445250379Strociny	case SNMP_OP_ROLLBACK:
446250379Strociny	case SNMP_OP_COMMIT:
447250379Strociny		return (SNMP_ERR_NOERROR);
448250379Strociny	default:
449250379Strociny		return (SNMP_ERR_RES_UNAVAIL);
450250379Strociny	}
451250379Strociny
452250379Strociny	ret = SNMP_ERR_NOERROR;
453250379Strociny
454250379Strociny	switch (which) {
455250379Strociny	case LEAF_hastResourceIndex:
456250379Strociny		value->v.integer = res->index;
457250379Strociny		break;
458250379Strociny	case LEAF_hastResourceName:
459250379Strociny		ret = string_get(value, res->name, -1);
460250379Strociny		break;
461250379Strociny	case LEAF_hastResourceRole:
462250379Strociny		value->v.integer = res->role;
463250379Strociny		break;
464250379Strociny	case LEAF_hastResourceProvName:
465250379Strociny		ret = string_get(value, res->provname, -1);
466250379Strociny		break;
467250379Strociny	case LEAF_hastResourceLocalPath:
468250379Strociny		ret = string_get(value, res->localpath, -1);
469250379Strociny		break;
470250379Strociny	case LEAF_hastResourceExtentSize:
471250379Strociny		value->v.integer = res->extentsize;
472250379Strociny		break;
473250379Strociny	case LEAF_hastResourceKeepDirty:
474250379Strociny		value->v.integer = res->keepdirty;
475250379Strociny		break;
476250379Strociny	case LEAF_hastResourceRemoteAddr:
477250379Strociny		ret = string_get(value, res->remoteaddr, -1);
478250379Strociny		break;
479250379Strociny	case LEAF_hastResourceSourceAddr:
480250379Strociny		ret = string_get(value, res->sourceaddr, -1);
481250379Strociny		break;
482250379Strociny	case LEAF_hastResourceReplication:
483250379Strociny		value->v.integer = res->replication;
484250379Strociny		break;
485250379Strociny	case LEAF_hastResourceStatus:
486250379Strociny		value->v.integer = res->status;
487250379Strociny		break;
488250379Strociny	case LEAF_hastResourceDirty:
489250379Strociny		value->v.counter64 = res->dirty;
490250379Strociny		break;
491250379Strociny	case LEAF_hastResourceReads:
492250379Strociny		value->v.counter64 = res->reads;
493250379Strociny		break;
494250379Strociny	case LEAF_hastResourceWrites:
495250379Strociny		value->v.counter64 = res->writes;
496250379Strociny		break;
497250379Strociny	case LEAF_hastResourceDeletes:
498250379Strociny		value->v.counter64 = res->deletes;
499250379Strociny		break;
500250379Strociny	case LEAF_hastResourceFlushes:
501250379Strociny		value->v.counter64 = res->flushes;
502250379Strociny		break;
503250379Strociny	case LEAF_hastResourceActivemapUpdates:
504250379Strociny		value->v.counter64 = res->activemap_updates;
505250379Strociny		break;
506250379Strociny	case LEAF_hastResourceReadErrors:
507250379Strociny		value->v.counter64 = res->read_errors;
508250379Strociny		break;
509250379Strociny	case LEAF_hastResourceWriteErrors:
510250379Strociny		value->v.counter64 = res->write_errors;
511250379Strociny		break;
512250379Strociny	case LEAF_hastResourceDeleteErrors:
513250379Strociny		value->v.counter64 = res->delete_errors;
514250379Strociny		break;
515250379Strociny	case LEAF_hastResourceFlushErrors:
516250379Strociny		value->v.counter64 = res->flush_errors;
517250379Strociny		break;
518252516Strociny	case LEAF_hastResourceWorkerPid:
519252516Strociny		value->v.integer = res->workerpid;
520252516Strociny		break;
521260412Strociny	case LEAF_hastResourceLocalQueue:
522260412Strociny		value->v.uint32 = res->local_queue;
523260412Strociny		break;
524260412Strociny	case LEAF_hastResourceSendQueue:
525260412Strociny		value->v.uint32 = res->send_queue;
526260412Strociny		break;
527260412Strociny	case LEAF_hastResourceRecvQueue:
528260412Strociny		value->v.uint32 = res->recv_queue;
529260412Strociny		break;
530260412Strociny	case LEAF_hastResourceDoneQueue:
531260412Strociny		value->v.uint32 = res->done_queue;
532260412Strociny		break;
533260412Strociny	case LEAF_hastResourceIdleQueue:
534260412Strociny		value->v.uint32 = res->idle_queue;
535260412Strociny		break;
536250379Strociny	default:
537250379Strociny		ret = SNMP_ERR_RES_UNAVAIL;
538250379Strociny		break;
539250379Strociny	}
540250379Strociny	return (ret);
541250379Strociny}
542