17297a2ffSMikolaj Golub /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
47297a2ffSMikolaj Golub  * Copyright (c) 2013 Mikolaj Golub <trociny@FreeBSD.org>
57297a2ffSMikolaj Golub  * All rights reserved.
67297a2ffSMikolaj Golub  *
77297a2ffSMikolaj Golub  * Redistribution and use in source and binary forms, with or without
87297a2ffSMikolaj Golub  * modification, are permitted provided that the following conditions
97297a2ffSMikolaj Golub  * are met:
107297a2ffSMikolaj Golub  * 1. Redistributions of source code must retain the above copyright
117297a2ffSMikolaj Golub  *    notice, this list of conditions and the following disclaimer.
127297a2ffSMikolaj Golub  * 2. Redistributions in binary form must reproduce the above copyright
137297a2ffSMikolaj Golub  *    notice, this list of conditions and the following disclaimer in the
147297a2ffSMikolaj Golub  *    documentation and/or other materials provided with the distribution.
157297a2ffSMikolaj Golub  *
167297a2ffSMikolaj Golub  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
177297a2ffSMikolaj Golub  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
187297a2ffSMikolaj Golub  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
197297a2ffSMikolaj Golub  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
207297a2ffSMikolaj Golub  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
217297a2ffSMikolaj Golub  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
227297a2ffSMikolaj Golub  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
237297a2ffSMikolaj Golub  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
247297a2ffSMikolaj Golub  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
257297a2ffSMikolaj Golub  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
267297a2ffSMikolaj Golub  * SUCH DAMAGE.
277297a2ffSMikolaj Golub  */
287297a2ffSMikolaj Golub 
297297a2ffSMikolaj Golub #include <sys/param.h>
307297a2ffSMikolaj Golub #include <sys/queue.h>
317297a2ffSMikolaj Golub 
327297a2ffSMikolaj Golub #include <bsnmp/snmpmod.h>
337297a2ffSMikolaj Golub 
347297a2ffSMikolaj Golub #include <string.h>
357297a2ffSMikolaj Golub 
367297a2ffSMikolaj Golub #include "hast.h"
377297a2ffSMikolaj Golub #include "hast_oid.h"
387297a2ffSMikolaj Golub #include "hast_proto.h"
397297a2ffSMikolaj Golub #include "hast_tree.h"
407297a2ffSMikolaj Golub #include "nv.h"
417297a2ffSMikolaj Golub #include "pjdlog.h"
427297a2ffSMikolaj Golub #include "proto.h"
437297a2ffSMikolaj Golub 
447297a2ffSMikolaj Golub #define UPDATE_INTERVAL	500	/* update interval in ticks */
457297a2ffSMikolaj Golub 
467297a2ffSMikolaj Golub static struct lmodule *module;
477297a2ffSMikolaj Golub 
487297a2ffSMikolaj Golub static const struct asn_oid oid_hast = OIDX_begemotHast;
497297a2ffSMikolaj Golub 
507297a2ffSMikolaj Golub /* the Object Resource registration index */
517297a2ffSMikolaj Golub static u_int hast_index = 0;
527297a2ffSMikolaj Golub 
537297a2ffSMikolaj Golub /*
547297a2ffSMikolaj Golub  * Structure that describes single resource.
557297a2ffSMikolaj Golub  */
567297a2ffSMikolaj Golub struct hast_snmp_resource {
577297a2ffSMikolaj Golub 	TAILQ_ENTRY(hast_snmp_resource) link;
587297a2ffSMikolaj Golub 	int32_t		index;
597297a2ffSMikolaj Golub 	char		name[NAME_MAX];
607297a2ffSMikolaj Golub 	int		error;
617297a2ffSMikolaj Golub 	int		role;
627297a2ffSMikolaj Golub 	char		provname[NAME_MAX];
637297a2ffSMikolaj Golub 	char		localpath[PATH_MAX];
647297a2ffSMikolaj Golub 	int32_t		extentsize;
657297a2ffSMikolaj Golub 	int32_t		keepdirty;
667297a2ffSMikolaj Golub 	char		remoteaddr[HAST_ADDRSIZE];
677297a2ffSMikolaj Golub 	char		sourceaddr[HAST_ADDRSIZE];
687297a2ffSMikolaj Golub 	int		replication;
697297a2ffSMikolaj Golub 	int		status;
707297a2ffSMikolaj Golub 	uint64_t	dirty;
717297a2ffSMikolaj Golub 	uint64_t	reads;
727297a2ffSMikolaj Golub 	uint64_t	writes;
737297a2ffSMikolaj Golub 	uint64_t	deletes;
747297a2ffSMikolaj Golub 	uint64_t	flushes;
757297a2ffSMikolaj Golub 	uint64_t	activemap_updates;
767297a2ffSMikolaj Golub 	uint64_t	read_errors;
777297a2ffSMikolaj Golub 	uint64_t	write_errors;
787297a2ffSMikolaj Golub 	uint64_t	delete_errors;
797297a2ffSMikolaj Golub 	uint64_t	flush_errors;
80e338dbe4SMikolaj Golub 	pid_t		workerpid;
81bcfa7a86SMikolaj Golub 	uint32_t	local_queue;
82bcfa7a86SMikolaj Golub 	uint32_t	send_queue;
83bcfa7a86SMikolaj Golub 	uint32_t	recv_queue;
84bcfa7a86SMikolaj Golub 	uint32_t	done_queue;
85bcfa7a86SMikolaj Golub 	uint32_t	idle_queue;
867297a2ffSMikolaj Golub };
877297a2ffSMikolaj Golub 
887297a2ffSMikolaj Golub static TAILQ_HEAD(, hast_snmp_resource) resources =
897297a2ffSMikolaj Golub     TAILQ_HEAD_INITIALIZER(resources);
907297a2ffSMikolaj Golub 
917297a2ffSMikolaj Golub /* Path to configuration file. */
927297a2ffSMikolaj Golub static u_char *cfgpath;
937297a2ffSMikolaj Golub /* Ticks of the last hast resources update. */
947297a2ffSMikolaj Golub static uint64_t last_resources_update;
957297a2ffSMikolaj Golub 
967297a2ffSMikolaj Golub static void free_resources(void);
977297a2ffSMikolaj Golub static int hastctl(struct nv *nvin, struct nv **nvout);
987297a2ffSMikolaj Golub static int hast_fini(void);
997297a2ffSMikolaj Golub static int hast_init(struct lmodule *mod, int argc, char *argv[]);
1007297a2ffSMikolaj Golub static void hast_start(void);
1017297a2ffSMikolaj Golub static int set_role(const char *resource, int role);
1027297a2ffSMikolaj Golub static int str2role(const char *str);
1037297a2ffSMikolaj Golub static int str2replication(const char *str);
1047297a2ffSMikolaj Golub static int str2status(const char *str);
1057297a2ffSMikolaj Golub static int update_resources(void);
1067297a2ffSMikolaj Golub 
1077297a2ffSMikolaj Golub const struct snmp_module config = {
1087297a2ffSMikolaj Golub     .comment   = "This module implements the BEGEMOT MIB for HAST.",
1097297a2ffSMikolaj Golub     .init      = hast_init,
1107297a2ffSMikolaj Golub     .start     = hast_start,
1117297a2ffSMikolaj Golub     .fini      = hast_fini,
1127297a2ffSMikolaj Golub     .tree      = hast_ctree,
1137297a2ffSMikolaj Golub     .tree_size = hast_CTREE_SIZE,
1147297a2ffSMikolaj Golub };
1157297a2ffSMikolaj Golub 
1167297a2ffSMikolaj Golub static int
hast_init(struct lmodule * mod,int argc __unused,char * argv[]__unused)1177297a2ffSMikolaj Golub hast_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
1187297a2ffSMikolaj Golub {
1197297a2ffSMikolaj Golub 
1207297a2ffSMikolaj Golub 	module = mod;
1217297a2ffSMikolaj Golub 
1227297a2ffSMikolaj Golub 	pjdlog_init(PJDLOG_MODE_SYSLOG);
1237297a2ffSMikolaj Golub 	pjdlog_debug_set(0);
1247297a2ffSMikolaj Golub 
1257297a2ffSMikolaj Golub 	cfgpath = malloc(sizeof(HAST_CONFIG));
1267297a2ffSMikolaj Golub 	if (cfgpath == NULL) {
1277297a2ffSMikolaj Golub 		pjdlog_error("Unable to allocate %zu bytes for cfgpath",
1287297a2ffSMikolaj Golub 		    sizeof(HAST_CONFIG));
1297297a2ffSMikolaj Golub 		return (-1);
1307297a2ffSMikolaj Golub 	}
1317297a2ffSMikolaj Golub 	strcpy(cfgpath, HAST_CONFIG);
1327297a2ffSMikolaj Golub 	return(0);
1337297a2ffSMikolaj Golub }
1347297a2ffSMikolaj Golub 
1357297a2ffSMikolaj Golub static void
hast_start(void)1367297a2ffSMikolaj Golub hast_start(void)
1377297a2ffSMikolaj Golub {
1387297a2ffSMikolaj Golub 	hast_index = or_register(&oid_hast,
1397297a2ffSMikolaj Golub 	    "The MIB module for BEGEMOT-HAST-MIB.", module);
1407297a2ffSMikolaj Golub }
1417297a2ffSMikolaj Golub 
1427297a2ffSMikolaj Golub static int
hast_fini(void)1437297a2ffSMikolaj Golub hast_fini(void)
1447297a2ffSMikolaj Golub {
1457297a2ffSMikolaj Golub 
1467297a2ffSMikolaj Golub 	or_unregister(hast_index);
1477297a2ffSMikolaj Golub 	free_resources();
1487297a2ffSMikolaj Golub 	free(cfgpath);
1497297a2ffSMikolaj Golub 	return (0);
1507297a2ffSMikolaj Golub }
1517297a2ffSMikolaj Golub 
1527297a2ffSMikolaj Golub static void
free_resources(void)1537297a2ffSMikolaj Golub free_resources(void)
1547297a2ffSMikolaj Golub {
1557297a2ffSMikolaj Golub 	struct hast_snmp_resource *res;
1567297a2ffSMikolaj Golub 
1577297a2ffSMikolaj Golub 	while ((res = TAILQ_FIRST(&resources)) != NULL) {
1587297a2ffSMikolaj Golub 		TAILQ_REMOVE(&resources, res, link);
1597297a2ffSMikolaj Golub 		free(res);
1607297a2ffSMikolaj Golub 	}
1617297a2ffSMikolaj Golub }
1627297a2ffSMikolaj Golub 
1637297a2ffSMikolaj Golub static int
str2role(const char * str)1647297a2ffSMikolaj Golub str2role(const char *str)
1657297a2ffSMikolaj Golub {
1667297a2ffSMikolaj Golub 
1677297a2ffSMikolaj Golub 	if (strcmp(str, "init") == 0)
1687297a2ffSMikolaj Golub 		return (HAST_ROLE_INIT);
1697297a2ffSMikolaj Golub 	if (strcmp(str, "primary") == 0)
1707297a2ffSMikolaj Golub 		return (HAST_ROLE_PRIMARY);
1717297a2ffSMikolaj Golub 	if (strcmp(str, "secondary") == 0)
1727297a2ffSMikolaj Golub 		return (HAST_ROLE_SECONDARY);
1737297a2ffSMikolaj Golub 	return (HAST_ROLE_UNDEF);
1747297a2ffSMikolaj Golub }
1757297a2ffSMikolaj Golub 
1767297a2ffSMikolaj Golub static int
str2replication(const char * str)1777297a2ffSMikolaj Golub str2replication(const char *str)
1787297a2ffSMikolaj Golub {
1797297a2ffSMikolaj Golub 
1807297a2ffSMikolaj Golub 	if (strcmp(str, "fullsync") == 0)
1817297a2ffSMikolaj Golub 		return (HAST_REPLICATION_FULLSYNC);
1827297a2ffSMikolaj Golub 	if (strcmp(str, "memsync") == 0)
1837297a2ffSMikolaj Golub 		return (HAST_REPLICATION_MEMSYNC);
1847297a2ffSMikolaj Golub 	if (strcmp(str, "async") == 0)
1857297a2ffSMikolaj Golub 		return (HAST_REPLICATION_ASYNC);
1867297a2ffSMikolaj Golub 	return (-1);
1877297a2ffSMikolaj Golub }
1887297a2ffSMikolaj Golub 
1897297a2ffSMikolaj Golub static int
str2status(const char * str)1907297a2ffSMikolaj Golub str2status(const char *str)
1917297a2ffSMikolaj Golub {
1927297a2ffSMikolaj Golub 
1937297a2ffSMikolaj Golub 	if (strcmp(str, "complete") == 0)
1947297a2ffSMikolaj Golub 		return (0);
1957297a2ffSMikolaj Golub 	if (strcmp(str, "degraded") == 0)
1967297a2ffSMikolaj Golub 		return (1);
1977297a2ffSMikolaj Golub 	return (-1);
1987297a2ffSMikolaj Golub }
1997297a2ffSMikolaj Golub 
2007297a2ffSMikolaj Golub static int
hastctl(struct nv * nvin,struct nv ** nvout)2017297a2ffSMikolaj Golub hastctl(struct nv *nvin, struct nv **nvout)
2027297a2ffSMikolaj Golub {
2037297a2ffSMikolaj Golub 	struct hastd_config *cfg;
2047297a2ffSMikolaj Golub 	struct proto_conn *conn;
2057297a2ffSMikolaj Golub 	struct nv *nv;
2067297a2ffSMikolaj Golub 	int error;
2077297a2ffSMikolaj Golub 
2087297a2ffSMikolaj Golub 	cfg = yy_config_parse(cfgpath, true);
2097297a2ffSMikolaj Golub 	if (cfg == NULL)
2107297a2ffSMikolaj Golub 		return (-1);
2117297a2ffSMikolaj Golub 
2127297a2ffSMikolaj Golub 	/* Setup control connection... */
2137297a2ffSMikolaj Golub 	if (proto_client(NULL, cfg->hc_controladdr, &conn) == -1) {
2147297a2ffSMikolaj Golub 		pjdlog_error("Unable to setup control connection to %s",
2157297a2ffSMikolaj Golub 		    cfg->hc_controladdr);
2167297a2ffSMikolaj Golub 		return (-1);
2177297a2ffSMikolaj Golub 	}
2187297a2ffSMikolaj Golub 	/* ...and connect to hastd. */
2197297a2ffSMikolaj Golub 	if (proto_connect(conn, HAST_TIMEOUT) == -1) {
2207297a2ffSMikolaj Golub 		pjdlog_error("Unable to connect to hastd via %s",
2217297a2ffSMikolaj Golub 		    cfg->hc_controladdr);
2227297a2ffSMikolaj Golub 		proto_close(conn);
2237297a2ffSMikolaj Golub 		return (-1);
2247297a2ffSMikolaj Golub 	}
2257297a2ffSMikolaj Golub 	/* Send the command to the server... */
2267297a2ffSMikolaj Golub 	if (hast_proto_send(NULL, conn, nvin, NULL, 0) == -1) {
2277297a2ffSMikolaj Golub 		pjdlog_error("Unable to send command to hastd via %s",
2287297a2ffSMikolaj Golub 		    cfg->hc_controladdr);
2297297a2ffSMikolaj Golub 		proto_close(conn);
2307297a2ffSMikolaj Golub 		return (-1);
2317297a2ffSMikolaj Golub 	}
2327297a2ffSMikolaj Golub 	/* ...and receive reply. */
2337297a2ffSMikolaj Golub 	if (hast_proto_recv_hdr(conn, &nv) == -1) {
2347297a2ffSMikolaj Golub 		pjdlog_error("cannot receive reply from hastd via %s",
2357297a2ffSMikolaj Golub 		    cfg->hc_controladdr);
2367297a2ffSMikolaj Golub 		proto_close(conn);
2377297a2ffSMikolaj Golub 		return (-1);
2387297a2ffSMikolaj Golub 	}
2397297a2ffSMikolaj Golub 	proto_close(conn);
2407297a2ffSMikolaj Golub 	error = nv_get_int16(nv, "error");
2417297a2ffSMikolaj Golub 	if (error != 0) {
2427297a2ffSMikolaj Golub 		pjdlog_error("Error %d received from hastd.", error);
2437297a2ffSMikolaj Golub 		nv_free(nv);
2447297a2ffSMikolaj Golub 		return (-1);
2457297a2ffSMikolaj Golub 	}
2467297a2ffSMikolaj Golub 	nv_set_error(nv, 0);
2477297a2ffSMikolaj Golub 	*nvout = nv;
2487297a2ffSMikolaj Golub 	return (0);
2497297a2ffSMikolaj Golub }
2507297a2ffSMikolaj Golub 
2517297a2ffSMikolaj Golub static int
set_role(const char * resource,int role)2527297a2ffSMikolaj Golub set_role(const char *resource, int role)
2537297a2ffSMikolaj Golub {
2547297a2ffSMikolaj Golub 	struct nv *nvin, *nvout;
2557297a2ffSMikolaj Golub 	int error;
2567297a2ffSMikolaj Golub 
2577297a2ffSMikolaj Golub 	nvin = nv_alloc();
2587297a2ffSMikolaj Golub 	nv_add_string(nvin, resource, "resource%d", 0);
2597297a2ffSMikolaj Golub 	nv_add_uint8(nvin, HASTCTL_CMD_SETROLE, "cmd");
2607297a2ffSMikolaj Golub 	nv_add_uint8(nvin, role, "role");
2617297a2ffSMikolaj Golub 	error = hastctl(nvin, &nvout);
2627297a2ffSMikolaj Golub 	nv_free(nvin);
2637297a2ffSMikolaj Golub 	if (error != 0)
2647297a2ffSMikolaj Golub 		return (-1);
2657297a2ffSMikolaj Golub 	nv_free(nvout);
2667297a2ffSMikolaj Golub 	return (SNMP_ERR_NOERROR);
2677297a2ffSMikolaj Golub }
2687297a2ffSMikolaj Golub 
2697297a2ffSMikolaj Golub static int
update_resources(void)2707297a2ffSMikolaj Golub update_resources(void)
2717297a2ffSMikolaj Golub {
2727297a2ffSMikolaj Golub 	struct hast_snmp_resource *res;
2737297a2ffSMikolaj Golub 	struct nv *nvin, *nvout;
2747297a2ffSMikolaj Golub 	static uint64_t now;
2757297a2ffSMikolaj Golub 	unsigned int i;
2767297a2ffSMikolaj Golub 	const char *str;
2777297a2ffSMikolaj Golub 	int error;
2787297a2ffSMikolaj Golub 
2797297a2ffSMikolaj Golub 	now = get_ticks();
2807297a2ffSMikolaj Golub 	if (now - last_resources_update < UPDATE_INTERVAL)
2817297a2ffSMikolaj Golub 		return (0);
2827297a2ffSMikolaj Golub 
2837297a2ffSMikolaj Golub 	last_resources_update = now;
2847297a2ffSMikolaj Golub 
2857297a2ffSMikolaj Golub 	free_resources();
2867297a2ffSMikolaj Golub 
2877297a2ffSMikolaj Golub 	nvin = nv_alloc();
2887297a2ffSMikolaj Golub 	nv_add_uint8(nvin, HASTCTL_CMD_STATUS, "cmd");
2897297a2ffSMikolaj Golub 	nv_add_string(nvin, "all", "resource%d", 0);
2907297a2ffSMikolaj Golub 	error = hastctl(nvin, &nvout);
2917297a2ffSMikolaj Golub 	nv_free(nvin);
2927297a2ffSMikolaj Golub 	if (error != 0)
2937297a2ffSMikolaj Golub 		return (-1);
2947297a2ffSMikolaj Golub 
2957297a2ffSMikolaj Golub 	for (i = 0; ; i++) {
2967297a2ffSMikolaj Golub 		str = nv_get_string(nvout, "resource%u", i);
2977297a2ffSMikolaj Golub 		if (str == NULL)
2987297a2ffSMikolaj Golub 			break;
2997297a2ffSMikolaj Golub 		res = calloc(1, sizeof(*res));
3007297a2ffSMikolaj Golub 		if (res == NULL) {
3017297a2ffSMikolaj Golub 			pjdlog_error("Unable to allocate %zu bytes for "
3027297a2ffSMikolaj Golub 			    "resource", sizeof(*res));
3037297a2ffSMikolaj Golub 			return (-1);
3047297a2ffSMikolaj Golub 		}
3057297a2ffSMikolaj Golub 		res->index = i + 1;
3067297a2ffSMikolaj Golub 		strncpy(res->name, str, sizeof(res->name) - 1);
3077297a2ffSMikolaj Golub 		error = nv_get_int16(nvout, "error%u", i);
3087297a2ffSMikolaj Golub 		if (error != 0)
3097297a2ffSMikolaj Golub 			continue;
3107297a2ffSMikolaj Golub 		str = nv_get_string(nvout, "role%u", i);
3117297a2ffSMikolaj Golub 		res->role = str != NULL ? str2role(str) : HAST_ROLE_UNDEF;
3127297a2ffSMikolaj Golub 		str = nv_get_string(nvout, "provname%u", i);
3137297a2ffSMikolaj Golub 		if (str != NULL)
3147297a2ffSMikolaj Golub 			strncpy(res->provname, str, sizeof(res->provname) - 1);
3157297a2ffSMikolaj Golub 		str = nv_get_string(nvout, "localpath%u", i);
3167297a2ffSMikolaj Golub 		if (str != NULL) {
3177297a2ffSMikolaj Golub 			strncpy(res->localpath, str,
3187297a2ffSMikolaj Golub 			    sizeof(res->localpath) - 1);
3197297a2ffSMikolaj Golub 		}
3207297a2ffSMikolaj Golub 		res->extentsize = nv_get_uint32(nvout, "extentsize%u", i);
3217297a2ffSMikolaj Golub 		res->keepdirty = nv_get_uint32(nvout, "keepdirty%u", i);
3227297a2ffSMikolaj Golub 		str = nv_get_string(nvout, "remoteaddr%u", i);
3237297a2ffSMikolaj Golub 		if (str != NULL) {
3247297a2ffSMikolaj Golub 			strncpy(res->remoteaddr, str,
3257297a2ffSMikolaj Golub 			    sizeof(res->remoteaddr) - 1);
3267297a2ffSMikolaj Golub 		}
3277297a2ffSMikolaj Golub 		str = nv_get_string(nvout, "sourceaddr%u", i);
3287297a2ffSMikolaj Golub 		if (str != NULL) {
3297297a2ffSMikolaj Golub 			strncpy(res->sourceaddr, str,
3307297a2ffSMikolaj Golub 			    sizeof(res->sourceaddr) - 1);
3317297a2ffSMikolaj Golub 		}
3327297a2ffSMikolaj Golub 		str = nv_get_string(nvout, "replication%u", i);
3337297a2ffSMikolaj Golub 		res->replication = str != NULL ? str2replication(str) : -1;
3347297a2ffSMikolaj Golub 		str = nv_get_string(nvout, "status%u", i);
3357297a2ffSMikolaj Golub 		res->status = str != NULL ? str2status(str) : -1;
3367297a2ffSMikolaj Golub 		res->dirty = nv_get_uint64(nvout, "dirty%u", i);
3377297a2ffSMikolaj Golub 		res->reads = nv_get_uint64(nvout, "stat_read%u", i);
3387297a2ffSMikolaj Golub 		res->writes = nv_get_uint64(nvout, "stat_write%u", i);
3397297a2ffSMikolaj Golub 		res->deletes = nv_get_uint64(nvout, "stat_delete%u", i);
3407297a2ffSMikolaj Golub 		res->flushes = nv_get_uint64(nvout, "stat_flush%u", i);
3417297a2ffSMikolaj Golub 		res->activemap_updates =
3427297a2ffSMikolaj Golub 		    nv_get_uint64(nvout, "stat_activemap_update%u", i);
3437297a2ffSMikolaj Golub 		res->read_errors =
3447297a2ffSMikolaj Golub 		    nv_get_uint64(nvout, "stat_read_error%u", i);
3457297a2ffSMikolaj Golub 		res->write_errors =
3467297a2ffSMikolaj Golub 		    nv_get_uint64(nvout, "stat_write_error%u", i);
3477297a2ffSMikolaj Golub 		res->delete_errors =
3487297a2ffSMikolaj Golub 		    nv_get_uint64(nvout, "stat_delete_error%u", i);
3497297a2ffSMikolaj Golub 		res->flush_errors =
3507297a2ffSMikolaj Golub 		    nv_get_uint64(nvout, "stat_flush_error%u", i);
351e338dbe4SMikolaj Golub 		res->workerpid = nv_get_int32(nvout, "workerpid%u", i);
352bcfa7a86SMikolaj Golub 		res->local_queue =
353bcfa7a86SMikolaj Golub 		    nv_get_uint64(nvout, "local_queue_size%u", i);
354bcfa7a86SMikolaj Golub 		res->send_queue =
355bcfa7a86SMikolaj Golub 		    nv_get_uint64(nvout, "send_queue_size%u", i);
356bcfa7a86SMikolaj Golub 		res->recv_queue =
357bcfa7a86SMikolaj Golub 		    nv_get_uint64(nvout, "recv_queue_size%u", i);
358bcfa7a86SMikolaj Golub 		res->done_queue =
359bcfa7a86SMikolaj Golub 		    nv_get_uint64(nvout, "done_queue_size%u", i);
360bcfa7a86SMikolaj Golub 		res->idle_queue =
361bcfa7a86SMikolaj Golub 		    nv_get_uint64(nvout, "idle_queue_size%u", i);
3627297a2ffSMikolaj Golub 		TAILQ_INSERT_TAIL(&resources, res, link);
3637297a2ffSMikolaj Golub 	}
3647297a2ffSMikolaj Golub 	nv_free(nvout);
3657297a2ffSMikolaj Golub 	return (0);
3667297a2ffSMikolaj Golub }
3677297a2ffSMikolaj Golub 
3687297a2ffSMikolaj Golub int
op_hastConfig(struct snmp_context * context,struct snmp_value * value,u_int sub,u_int iidx __unused,enum snmp_op op)3697297a2ffSMikolaj Golub op_hastConfig(struct snmp_context *context, struct snmp_value *value,
3707297a2ffSMikolaj Golub     u_int sub, u_int iidx __unused, enum snmp_op op)
3717297a2ffSMikolaj Golub {
3727297a2ffSMikolaj Golub 	asn_subid_t which;
3737297a2ffSMikolaj Golub 
3747297a2ffSMikolaj Golub 	which = value->var.subs[sub - 1];
3757297a2ffSMikolaj Golub 
3767297a2ffSMikolaj Golub 	switch (op) {
3777297a2ffSMikolaj Golub 	case SNMP_OP_GET:
3787297a2ffSMikolaj Golub 		switch (which) {
3797297a2ffSMikolaj Golub 		case LEAF_hastConfigFile:
3807297a2ffSMikolaj Golub 			return (string_get(value, cfgpath, -1));
3817297a2ffSMikolaj Golub 		default:
3827297a2ffSMikolaj Golub 			return (SNMP_ERR_RES_UNAVAIL);
3837297a2ffSMikolaj Golub 		}
3847297a2ffSMikolaj Golub 	case SNMP_OP_SET:
3857297a2ffSMikolaj Golub 		switch (which) {
3867297a2ffSMikolaj Golub 		case LEAF_hastConfigFile:
3877297a2ffSMikolaj Golub 			return (string_save(value, context, -1,
3887297a2ffSMikolaj Golub 			    (u_char **)&cfgpath));
3897297a2ffSMikolaj Golub 		default:
3907297a2ffSMikolaj Golub 			return (SNMP_ERR_RES_UNAVAIL);
3917297a2ffSMikolaj Golub 		}
3927297a2ffSMikolaj Golub 	case SNMP_OP_GETNEXT:
3937297a2ffSMikolaj Golub 	case SNMP_OP_ROLLBACK:
3947297a2ffSMikolaj Golub 	case SNMP_OP_COMMIT:
3957297a2ffSMikolaj Golub 		return (SNMP_ERR_NOERROR);
3967297a2ffSMikolaj Golub 	default:
3977297a2ffSMikolaj Golub 		return (SNMP_ERR_RES_UNAVAIL);
3987297a2ffSMikolaj Golub 	}
3997297a2ffSMikolaj Golub }
4007297a2ffSMikolaj Golub 
4017297a2ffSMikolaj Golub int
op_hastResourceTable(struct snmp_context * context __unused,struct snmp_value * value,u_int sub,u_int iidx __unused,enum snmp_op op)4027297a2ffSMikolaj Golub op_hastResourceTable(struct snmp_context *context __unused,
4037297a2ffSMikolaj Golub     struct snmp_value *value, u_int sub, u_int iidx __unused, enum snmp_op op)
4047297a2ffSMikolaj Golub {
4057297a2ffSMikolaj Golub 	struct hast_snmp_resource *res;
4067297a2ffSMikolaj Golub 	asn_subid_t which;
4077297a2ffSMikolaj Golub 	int ret;
4087297a2ffSMikolaj Golub 
4097297a2ffSMikolaj Golub 	if (update_resources() == -1)
4107297a2ffSMikolaj Golub 		return (SNMP_ERR_RES_UNAVAIL);
4117297a2ffSMikolaj Golub 
4127297a2ffSMikolaj Golub 	which = value->var.subs[sub - 1];
4137297a2ffSMikolaj Golub 
4147297a2ffSMikolaj Golub 	switch (op) {
4157297a2ffSMikolaj Golub 	case SNMP_OP_GETNEXT:
4167297a2ffSMikolaj Golub 		res = NEXT_OBJECT_INT(&resources, &value->var, sub);
4177297a2ffSMikolaj Golub 		if (res == NULL)
4187297a2ffSMikolaj Golub 			return (SNMP_ERR_NOSUCHNAME);
4197297a2ffSMikolaj Golub 		value->var.len = sub + 1;
4207297a2ffSMikolaj Golub 		value->var.subs[sub] = res->index;
4217297a2ffSMikolaj Golub 		break;
4227297a2ffSMikolaj Golub 	case SNMP_OP_GET:
4237297a2ffSMikolaj Golub 		if (value->var.len - sub != 1)
4247297a2ffSMikolaj Golub 			return (SNMP_ERR_NOSUCHNAME);
4257297a2ffSMikolaj Golub 		res = FIND_OBJECT_INT(&resources, &value->var, sub);
4267297a2ffSMikolaj Golub 		if (res == NULL)
4277297a2ffSMikolaj Golub 			return (SNMP_ERR_NOSUCHNAME);
4287297a2ffSMikolaj Golub 		break;
4297297a2ffSMikolaj Golub 	case SNMP_OP_SET:
4307297a2ffSMikolaj Golub 		res = FIND_OBJECT_INT(&resources, &value->var, sub);
4317297a2ffSMikolaj Golub 		if (res == NULL)
4327297a2ffSMikolaj Golub 			return (SNMP_ERR_NOSUCHNAME);
4337297a2ffSMikolaj Golub 		switch (which) {
4347297a2ffSMikolaj Golub 		case LEAF_hastResourceRole:
4357297a2ffSMikolaj Golub 			ret = set_role(res->name, value->v.integer);
4367297a2ffSMikolaj Golub 			/* force update on next run */
4377297a2ffSMikolaj Golub 			last_resources_update = 0;
4387297a2ffSMikolaj Golub 			break;
4397297a2ffSMikolaj Golub 		default:
4407297a2ffSMikolaj Golub 			ret = SNMP_ERR_NOT_WRITEABLE;
4417297a2ffSMikolaj Golub 			break;
4427297a2ffSMikolaj Golub 		}
4437297a2ffSMikolaj Golub 		return ret;
4447297a2ffSMikolaj Golub 	case SNMP_OP_ROLLBACK:
4457297a2ffSMikolaj Golub 	case SNMP_OP_COMMIT:
4467297a2ffSMikolaj Golub 		return (SNMP_ERR_NOERROR);
4477297a2ffSMikolaj Golub 	default:
4487297a2ffSMikolaj Golub 		return (SNMP_ERR_RES_UNAVAIL);
4497297a2ffSMikolaj Golub 	}
4507297a2ffSMikolaj Golub 
4517297a2ffSMikolaj Golub 	ret = SNMP_ERR_NOERROR;
4527297a2ffSMikolaj Golub 
4537297a2ffSMikolaj Golub 	switch (which) {
4547297a2ffSMikolaj Golub 	case LEAF_hastResourceIndex:
4557297a2ffSMikolaj Golub 		value->v.integer = res->index;
4567297a2ffSMikolaj Golub 		break;
4577297a2ffSMikolaj Golub 	case LEAF_hastResourceName:
4587297a2ffSMikolaj Golub 		ret = string_get(value, res->name, -1);
4597297a2ffSMikolaj Golub 		break;
4607297a2ffSMikolaj Golub 	case LEAF_hastResourceRole:
4617297a2ffSMikolaj Golub 		value->v.integer = res->role;
4627297a2ffSMikolaj Golub 		break;
4637297a2ffSMikolaj Golub 	case LEAF_hastResourceProvName:
4647297a2ffSMikolaj Golub 		ret = string_get(value, res->provname, -1);
4657297a2ffSMikolaj Golub 		break;
4667297a2ffSMikolaj Golub 	case LEAF_hastResourceLocalPath:
4677297a2ffSMikolaj Golub 		ret = string_get(value, res->localpath, -1);
4687297a2ffSMikolaj Golub 		break;
4697297a2ffSMikolaj Golub 	case LEAF_hastResourceExtentSize:
4707297a2ffSMikolaj Golub 		value->v.integer = res->extentsize;
4717297a2ffSMikolaj Golub 		break;
4727297a2ffSMikolaj Golub 	case LEAF_hastResourceKeepDirty:
4737297a2ffSMikolaj Golub 		value->v.integer = res->keepdirty;
4747297a2ffSMikolaj Golub 		break;
4757297a2ffSMikolaj Golub 	case LEAF_hastResourceRemoteAddr:
4767297a2ffSMikolaj Golub 		ret = string_get(value, res->remoteaddr, -1);
4777297a2ffSMikolaj Golub 		break;
4787297a2ffSMikolaj Golub 	case LEAF_hastResourceSourceAddr:
4797297a2ffSMikolaj Golub 		ret = string_get(value, res->sourceaddr, -1);
4807297a2ffSMikolaj Golub 		break;
4817297a2ffSMikolaj Golub 	case LEAF_hastResourceReplication:
4827297a2ffSMikolaj Golub 		value->v.integer = res->replication;
4837297a2ffSMikolaj Golub 		break;
4847297a2ffSMikolaj Golub 	case LEAF_hastResourceStatus:
4857297a2ffSMikolaj Golub 		value->v.integer = res->status;
4867297a2ffSMikolaj Golub 		break;
4877297a2ffSMikolaj Golub 	case LEAF_hastResourceDirty:
4887297a2ffSMikolaj Golub 		value->v.counter64 = res->dirty;
4897297a2ffSMikolaj Golub 		break;
4907297a2ffSMikolaj Golub 	case LEAF_hastResourceReads:
4917297a2ffSMikolaj Golub 		value->v.counter64 = res->reads;
4927297a2ffSMikolaj Golub 		break;
4937297a2ffSMikolaj Golub 	case LEAF_hastResourceWrites:
4947297a2ffSMikolaj Golub 		value->v.counter64 = res->writes;
4957297a2ffSMikolaj Golub 		break;
4967297a2ffSMikolaj Golub 	case LEAF_hastResourceDeletes:
4977297a2ffSMikolaj Golub 		value->v.counter64 = res->deletes;
4987297a2ffSMikolaj Golub 		break;
4997297a2ffSMikolaj Golub 	case LEAF_hastResourceFlushes:
5007297a2ffSMikolaj Golub 		value->v.counter64 = res->flushes;
5017297a2ffSMikolaj Golub 		break;
5027297a2ffSMikolaj Golub 	case LEAF_hastResourceActivemapUpdates:
5037297a2ffSMikolaj Golub 		value->v.counter64 = res->activemap_updates;
5047297a2ffSMikolaj Golub 		break;
5057297a2ffSMikolaj Golub 	case LEAF_hastResourceReadErrors:
5067297a2ffSMikolaj Golub 		value->v.counter64 = res->read_errors;
5077297a2ffSMikolaj Golub 		break;
5087297a2ffSMikolaj Golub 	case LEAF_hastResourceWriteErrors:
5097297a2ffSMikolaj Golub 		value->v.counter64 = res->write_errors;
5107297a2ffSMikolaj Golub 		break;
5117297a2ffSMikolaj Golub 	case LEAF_hastResourceDeleteErrors:
5127297a2ffSMikolaj Golub 		value->v.counter64 = res->delete_errors;
5137297a2ffSMikolaj Golub 		break;
5147297a2ffSMikolaj Golub 	case LEAF_hastResourceFlushErrors:
5157297a2ffSMikolaj Golub 		value->v.counter64 = res->flush_errors;
5167297a2ffSMikolaj Golub 		break;
517e338dbe4SMikolaj Golub 	case LEAF_hastResourceWorkerPid:
518e338dbe4SMikolaj Golub 		value->v.integer = res->workerpid;
519e338dbe4SMikolaj Golub 		break;
520bcfa7a86SMikolaj Golub 	case LEAF_hastResourceLocalQueue:
521bcfa7a86SMikolaj Golub 		value->v.uint32 = res->local_queue;
522bcfa7a86SMikolaj Golub 		break;
523bcfa7a86SMikolaj Golub 	case LEAF_hastResourceSendQueue:
524bcfa7a86SMikolaj Golub 		value->v.uint32 = res->send_queue;
525bcfa7a86SMikolaj Golub 		break;
526bcfa7a86SMikolaj Golub 	case LEAF_hastResourceRecvQueue:
527bcfa7a86SMikolaj Golub 		value->v.uint32 = res->recv_queue;
528bcfa7a86SMikolaj Golub 		break;
529bcfa7a86SMikolaj Golub 	case LEAF_hastResourceDoneQueue:
530bcfa7a86SMikolaj Golub 		value->v.uint32 = res->done_queue;
531bcfa7a86SMikolaj Golub 		break;
532bcfa7a86SMikolaj Golub 	case LEAF_hastResourceIdleQueue:
533bcfa7a86SMikolaj Golub 		value->v.uint32 = res->idle_queue;
534bcfa7a86SMikolaj Golub 		break;
5357297a2ffSMikolaj Golub 	default:
5367297a2ffSMikolaj Golub 		ret = SNMP_ERR_RES_UNAVAIL;
5377297a2ffSMikolaj Golub 		break;
5387297a2ffSMikolaj Golub 	}
5397297a2ffSMikolaj Golub 	return (ret);
5407297a2ffSMikolaj Golub }
541