Commit Diff


commit - fe4b71bd3d51e9a1ebb71c357e2bd451c482f86a
commit + 189a23326dc4bc1df675c433b38ff4eef27e817f
blob - a9e28a278fc62f3ea9a08703ed06e1717430cd27
blob + 2e1ef449b045f960e336d64eb66fb6a8b3a51c93
--- Makefile
+++ Makefile
@@ -1,16 +1,15 @@
-#	$OpenBSD: Makefile,v 1.34 2020/09/14 11:30:25 martijn Exp $
+#	$OpenBSD: Makefile,v 1.35 2020/10/26 16:52:06 martijn Exp $
 
 PROG=		relayd
 SRCS=		parse.y
-SRCS+=		agentx.c agentx_control.c ca.c carp.c check_icmp.c \
-		check_script.c check_tcp.c check_tls.c config.c control.c \
-		hce.c log.c name2id.c pfe.c pfe_filter.c pfe_route.c proc.c \
-		relay.c relay_http.c relay_udp.c relayd.c \
-		shuffle.c ssl.c subagentx.c subagentx_log.c util.c
+SRCS+=		agentx_control.c ca.c carp.c check_icmp.c check_script.c \
+		check_tcp.c check_tls.c config.c control.c hce.c log.c \
+		name2id.c pfe.c pfe_filter.c pfe_route.c proc.c relay.c \
+		relay_http.c relay_udp.c relayd.c shuffle.c ssl.c util.c
 MAN=		relayd.8 relayd.conf.5
 
-LDADD=		-levent -ltls -lssl -lcrypto -lutil
-DPADD=		${LIBEVENT} ${LIBSSL} ${LIBCRYPTO} ${LIBUTIL}
+LDADD=		-lagentx -levent -ltls -lssl -lcrypto -lutil
+DPADD=		${LIBAGENTX} ${LIBEVENT} ${LIBSSL} ${LIBCRYPTO} ${LIBUTIL}
 CFLAGS+=	-Wall -I${.CURDIR}
 CFLAGS+=	-Wstrict-prototypes -Wmissing-prototypes
 CFLAGS+=	-Wmissing-declarations
blob - b3a746ce61c5a226c8416124e1b9e327267bb7e0 (mode 644)
blob + /dev/null
--- agentx.c
+++ /dev/null
@@ -1,1359 +0,0 @@
-/*
- * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <sys/socket.h>
-
-#include <arpa/inet.h>
-
-#include <ctype.h>
-#include <endian.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-
-#include "agentx.h"
-
-#define AGENTX_PDU_HEADER 20
-
-static int agentx_pdu_need(struct agentx *, size_t);
-static int agentx_pdu_header(struct agentx *,
-    enum agentx_pdu_type, uint8_t, uint32_t, uint32_t, uint32_t,
-    struct agentx_ostring *);
-static uint32_t agentx_packetid(struct agentx *);
-static uint32_t agentx_pdu_queue(struct agentx *);
-static int agentx_pdu_add_uint16(struct agentx *, uint16_t);
-static int agentx_pdu_add_uint32(struct agentx *, uint32_t);
-static int agentx_pdu_add_uint64(struct agentx *, uint64_t);
-static int agentx_pdu_add_oid(struct agentx *, struct agentx_oid *, int);
-static int agentx_pdu_add_str(struct agentx *, struct agentx_ostring *);
-static int agentx_pdu_add_varbindlist( struct agentx *, struct agentx_varbind *,
-    size_t);
-static uint16_t agentx_pdutoh16(struct agentx_pdu_header *, uint8_t *);
-static uint32_t agentx_pdutoh32(struct agentx_pdu_header *, uint8_t *);
-static uint64_t agentx_pdutoh64(struct agentx_pdu_header *, uint8_t *);
-static ssize_t agentx_pdutooid(struct agentx_pdu_header *, struct agentx_oid *,
-    uint8_t *, size_t);
-static ssize_t agentx_pdutoostring(struct agentx_pdu_header *,
-    struct agentx_ostring *, uint8_t *, size_t);
-static ssize_t agentx_pdutovarbind(struct agentx_pdu_header *,
-    struct agentx_varbind *, uint8_t *, size_t);
-
-struct agentx *
-agentx_new(int fd)
-{
-	struct agentx *ax;
-
-	if (fd == -1) {
-		errno = EINVAL;
-		return NULL;
-	}
-
-	if ((ax = calloc(1, sizeof(*ax))) == NULL)
-		return NULL;
-	ax->ax_fd = fd;
-	if ((ax->ax_rbuf = malloc(512)) == NULL)
-		goto fail;
-	ax->ax_rbsize = 512;
-	ax->ax_byteorder = AGENTX_BYTE_ORDER_NATIVE;
-
-	return ax;
-
-fail:
-	free(ax);
-	return NULL;
-}
-
-void
-agentx_free(struct agentx *ax)
-{
-	if (ax == NULL)
-		return;
-	close(ax->ax_fd);
-	free(ax->ax_rbuf);
-	free(ax->ax_wbuf);
-	free(ax->ax_packetids);
-	free(ax);
-}
-
-struct agentx_pdu *
-agentx_recv(struct agentx *ax)
-{
-	struct agentx_pdu *pdu;
-	struct agentx_pdu_header header;
-	struct agentx_pdu_response *response;
-	struct agentx_varbind *varbind;
-	struct agentx_pdu_searchrangelist *srl;
-	struct agentx_pdu_varbindlist *vbl;
-	struct agentx_searchrange *sr;
-	size_t rbsize, packetidx = 0, i, rawlen;
-	ssize_t nread;
-	uint8_t *u8;
-	uint8_t *rbuf;
-	int found;
-
-	/* Only read a single packet at a time to make sure libevent triggers */
-	if (ax->ax_rblen < AGENTX_PDU_HEADER) {
-		if ((nread = read(ax->ax_fd, ax->ax_rbuf + ax->ax_rblen,
-		    AGENTX_PDU_HEADER - ax->ax_rblen)) == 0) {
-			errno = ECONNRESET;
-			return NULL;
-		}
-		if (nread == -1)
-			return NULL;
-		ax->ax_rblen += nread;
-		if (ax->ax_rblen < AGENTX_PDU_HEADER) {
-			errno = EAGAIN;
-			return NULL;
-		}
-	}
-	u8 = ax->ax_rbuf;
-	header.aph_version = *u8++;
-	header.aph_type = *u8++;
-	header.aph_flags = *u8++;
-	u8++;
-	header.aph_sessionid = agentx_pdutoh32(&header, u8);
-	u8 += 4;
-	header.aph_transactionid = agentx_pdutoh32(&header, u8);
-	u8 += 4;
-	header.aph_packetid = agentx_pdutoh32(&header, u8);
-	u8 += 4;
-	header.aph_plength = agentx_pdutoh32(&header, u8);
-
-	if (header.aph_version != 1) {
-		errno = EPROTO;
-		return NULL;
-	}
-	if (ax->ax_rblen < AGENTX_PDU_HEADER + header.aph_plength) {
-		if (AGENTX_PDU_HEADER + header.aph_plength > ax->ax_rbsize) {
-			rbsize = (((AGENTX_PDU_HEADER + header.aph_plength)
-			    / 512) + 1) * 512;
-			if ((rbuf = recallocarray(ax->ax_rbuf, ax->ax_rbsize,
-			    rbsize, sizeof(*rbuf))) == NULL)
-				return NULL;
-			ax->ax_rbsize = rbsize;
-			ax->ax_rbuf = rbuf;
-		}
-		nread = read(ax->ax_fd, ax->ax_rbuf + ax->ax_rblen,
-		    header.aph_plength - (ax->ax_rblen - AGENTX_PDU_HEADER));
-		if (nread == 0)
-			errno = ECONNRESET;
-		if (nread <= 0)
-			return NULL;
-		ax->ax_rblen += nread;
-		if (ax->ax_rblen < AGENTX_PDU_HEADER + header.aph_plength) {
-			errno = EAGAIN;
-			return NULL;
-		}
-	}
-
-	if ((pdu = calloc(1, sizeof(*pdu))) == NULL)
-		return NULL;
-
-	memcpy(&(pdu->ap_header), &header, sizeof(header));
-
-#if defined(AGENTX_DEBUG) && defined(AGENTX_DEBUG_VERBOSE)
-	{
-		char chars[4];
-		int print = 1;
-
-		fprintf(stderr, "received packet:\n");
-		for (i = 0; i < pdu->ap_header.aph_plength + AGENTX_PDU_HEADER;
-		    i++) {
-			fprintf(stderr, "%02hhx ", ax->ax_rbuf[i]);
-			chars[i % 4] = ax->ax_rbuf[i];
-			if (!isprint(ax->ax_rbuf[i]))
-				print = 0;
-			if (i % 4 == 3) {
-				if (print)
-					fprintf(stderr, "%.4s", chars);
-				fprintf(stderr, "\n");
-				print = 1;
-			}
-		}
-	}
-#endif
-
-	u8 = (ax->ax_rbuf) + AGENTX_PDU_HEADER;
-	rawlen = pdu->ap_header.aph_plength;
-	if (pdu->ap_header.aph_flags & AGENTX_PDU_FLAG_NON_DEFAULT_CONTEXT) {
-		nread = agentx_pdutoostring(&header, &(pdu->ap_context), u8,
-		    rawlen);
-		if (nread == -1)
-			goto fail;
-		rawlen -= nread;
-		u8 += nread;
-	}
-
-	switch (pdu->ap_header.aph_type) {
-	case AGENTX_PDU_TYPE_GETBULK:
-		if (rawlen < 4) {
-			errno = EPROTO;
-			goto fail;
-		}
-		pdu->ap_payload.ap_getbulk.ap_nonrep =
-		    agentx_pdutoh16(&header, u8);
-		u8 += 2;
-		pdu->ap_payload.ap_getbulk.ap_maxrep =
-		    agentx_pdutoh16(&header, u8);
-		u8 += 2;
-		srl = &(pdu->ap_payload.ap_getbulk.ap_srl);
-		rawlen -= 4;
-		/* FALLTHROUGH */
-	case AGENTX_PDU_TYPE_GET:
-	case AGENTX_PDU_TYPE_GETNEXT:
-		if (pdu->ap_header.aph_type != AGENTX_PDU_TYPE_GETBULK)
-			srl = &(pdu->ap_payload.ap_srl);
-		while (rawlen > 0 ) {
-			srl->ap_nsr++;
-			sr = reallocarray(srl->ap_sr, srl->ap_nsr, sizeof(*sr));
-			if (sr == NULL)
-				goto fail;
-			srl->ap_sr = sr;
-			sr += (srl->ap_nsr - 1);
-			if ((nread = agentx_pdutooid(&header, &(sr->asr_start),
-			    u8, rawlen)) == -1)
-				goto fail;
-			rawlen -= nread;
-			u8 += nread;
-			if ((nread = agentx_pdutooid(&header, &(sr->asr_stop),
-			    u8, rawlen)) == -1)
-				goto fail;
-			rawlen -= nread;
-			u8 += nread;
-		}
-		break;
-	case AGENTX_PDU_TYPE_TESTSET:
-		vbl = &(pdu->ap_payload.ap_vbl);
-		while (rawlen > 0) {
-			varbind = recallocarray(vbl->ap_varbind,
-			    vbl->ap_nvarbind, vbl->ap_nvarbind + 1,
-			    sizeof(*(vbl->ap_varbind)));
-			if (varbind == NULL)
-				goto fail;
-			vbl->ap_varbind = varbind;
-			nread = agentx_pdutovarbind(&header,
-			    &(vbl->ap_varbind[vbl->ap_nvarbind]), u8, rawlen);
-			if (nread == -1)
-				goto fail;
-			vbl->ap_nvarbind++;
-			u8 += nread;
-			rawlen -= nread;
-		}
-		break;
-	case AGENTX_PDU_TYPE_COMMITSET:
-	case AGENTX_PDU_TYPE_UNDOSET:
-	case AGENTX_PDU_TYPE_CLEANUPSET:
-		if (rawlen != 0) {
-			errno = EPROTO;
-			goto fail;
-		}
-		break;
-	case AGENTX_PDU_TYPE_RESPONSE:
-		if (ax->ax_packetids != NULL) {
-			found = 0;
-			for (i = 0; ax->ax_packetids[i] != 0; i++) {
-				if (ax->ax_packetids[i] ==
-				    pdu->ap_header.aph_packetid) {
-					packetidx = i;
-					found = 1;
-				}
-			}
-			if (found) {
-				ax->ax_packetids[packetidx] =
-				    ax->ax_packetids[i - 1];
-				ax->ax_packetids[i - 1] = 0;
-			} else {
-				errno = EPROTO;
-				goto fail;
-			}
-		}
-		if (rawlen < 8) {
-			errno = EPROTO;
-			goto fail;
-		}
-		response = &(pdu->ap_payload.ap_response);
-		response->ap_uptime = agentx_pdutoh32(&header, u8);
-		u8 += 4;
-		response->ap_error = agentx_pdutoh16(&header, u8);
-		u8 += 2;
-		response->ap_index = agentx_pdutoh16(&header, u8);
-		u8 += 2;
-		rawlen -= 8;
-		while (rawlen > 0) {
-			varbind = recallocarray(response->ap_varbindlist,
-			    response->ap_nvarbind, response->ap_nvarbind + 1,
-			    sizeof(*(response->ap_varbindlist)));
-			if (varbind == NULL)
-				goto fail;
-			response->ap_varbindlist = varbind;
-			nread = agentx_pdutovarbind(&header,
-			    &(response->ap_varbindlist[response->ap_nvarbind]),
-			    u8, rawlen);
-			if (nread == -1)
-				goto fail;
-			response->ap_nvarbind++;
-			u8 += nread;
-			rawlen -= nread;
-		}
-		break;
-	default:
-		pdu->ap_payload.ap_raw = malloc(pdu->ap_header.aph_plength);
-		if (pdu == NULL)
-			goto fail;
-		memcpy(pdu->ap_payload.ap_raw, ax->ax_rbuf + AGENTX_PDU_HEADER,
-		    pdu->ap_header.aph_plength);
-		break;
-	}
-
-	ax->ax_rblen = 0;
-
-	return pdu;
-fail:
-	agentx_pdu_free(pdu);
-	return NULL;
-}
-
-static int
-agentx_pdu_need(struct agentx *ax, size_t need)
-{
-	uint8_t *wbuf;
-	size_t wbsize;
-
-	if (ax->ax_wbtlen >= ax->ax_wbsize) {
-		wbsize = ((ax->ax_wbtlen / 512) + 1) * 512;
-		wbuf = recallocarray(ax->ax_wbuf, ax->ax_wbsize, wbsize, 1);
-		if (wbuf == NULL) {
-			ax->ax_wbtlen = ax->ax_wblen;
-			return -1;
-		}
-		ax->ax_wbsize = wbsize;
-		ax->ax_wbuf = wbuf;
-	}
-
-	return 0;
-}
-
-ssize_t
-agentx_send(struct agentx *ax)
-{
-	ssize_t nwrite;
-
-	if (ax->ax_wblen != ax->ax_wbtlen) {
-		errno = EALREADY;
-		return -1;
-	}
-
-	if (ax->ax_wblen == 0)
-		return 0;
-
-#if defined(AGENTX_DEBUG) && defined(AGENTX_DEBUG_VERBOSE)
-	{
-		size_t i;
-		char chars[4];
-		int print = 1;
-
-		fprintf(stderr, "sending packet:\n");
-		for (i = 0; i < ax->ax_wblen; i++) {
-			fprintf(stderr, "%02hhx ", ax->ax_wbuf[i]);
-			chars[i % 4] = ax->ax_wbuf[i];
-			if (!isprint(ax->ax_wbuf[i]))
-				print = 0;
-			if (i % 4 == 3) {
-				if (print)
-					fprintf(stderr, "%.4s", chars);
-				fprintf(stderr, "\n");
-				print = 1;
-			}
-		}
-	}
-#endif
-
-	if ((nwrite = send(ax->ax_fd, ax->ax_wbuf, ax->ax_wblen,
-	    MSG_NOSIGNAL | MSG_DONTWAIT)) == -1)
-		return -1;
-
-	memmove(ax->ax_wbuf, ax->ax_wbuf + nwrite, ax->ax_wblen - nwrite);
-	ax->ax_wblen -= nwrite;
-	ax->ax_wbtlen = ax->ax_wblen;
-
-	return ax->ax_wblen;
-}
-
-uint32_t
-agentx_open(struct agentx *ax, uint8_t timeout, struct agentx_oid *oid,
-    struct agentx_ostring *descr)
-{
-	if (agentx_pdu_header(ax, AGENTX_PDU_TYPE_OPEN, 0, 0, 0, 0,
-	    NULL) == -1)
-		return 0;
-	agentx_pdu_need(ax, 4);
-	ax->ax_wbuf[ax->ax_wbtlen++] = timeout;
-	memset(&(ax->ax_wbuf[ax->ax_wbtlen]), 0, 3);
-	ax->ax_wbtlen += 3;
-	if (agentx_pdu_add_oid(ax, oid, 0) == -1)
-		return 0;
-	if (agentx_pdu_add_str(ax, descr) == -1)
-		return 0;
-
-	return agentx_pdu_queue(ax);
-}
-
-uint32_t
-agentx_close(struct agentx *ax, uint32_t sessionid,
-    enum agentx_close_reason reason)
-{
-	if (agentx_pdu_header(ax, AGENTX_PDU_TYPE_CLOSE, 0, sessionid, 0, 0,
-	    NULL) == -1)
-		return 0;
-
-	if (agentx_pdu_need(ax, 4) == -1)
-		return 0;
-	ax->ax_wbuf[ax->ax_wbtlen++] = (uint8_t)reason;
-	memset(&(ax->ax_wbuf[ax->ax_wbtlen]), 0, 3);
-	ax->ax_wbtlen += 3;
-
-	return agentx_pdu_queue(ax);
-}
-
-uint32_t
-agentx_indexallocate(struct agentx *ax, uint8_t flags, uint32_t sessionid,
-    struct agentx_ostring *context, struct agentx_varbind *vblist, size_t nvb)
-{
-	if (flags & ~(AGENTX_PDU_FLAG_NEW_INDEX | AGENTX_PDU_FLAG_ANY_INDEX)) {
-		errno = EINVAL;
-		return 0;
-	}
-
-	if (agentx_pdu_header(ax, AGENTX_PDU_TYPE_INDEXALLOCATE, flags,
-	    sessionid, 0, 0, context) == -1)
-		return 0;
-
-	if (agentx_pdu_add_varbindlist(ax, vblist, nvb) == -1)
-		return 0;
-
-	return agentx_pdu_queue(ax);
-}
-
-uint32_t
-agentx_indexdeallocate(struct agentx *ax, uint32_t sessionid,
-    struct agentx_ostring *context, struct agentx_varbind *vblist, size_t nvb)
-{
-	if (agentx_pdu_header(ax, AGENTX_PDU_TYPE_INDEXDEALLOCATE, 0,
-	    sessionid, 0, 0, context) == -1)
-		return 0;
-
-	if (agentx_pdu_add_varbindlist(ax, vblist, nvb) == -1)
-		return 0;
-
-	return agentx_pdu_queue(ax);
-}
-
-uint32_t
-agentx_addagentcaps(struct agentx *ax, uint32_t sessionid,
-    struct agentx_ostring *context, struct agentx_oid *id,
-    struct agentx_ostring *descr)
-{
-	if (agentx_pdu_header(ax, AGENTX_PDU_TYPE_ADDAGENTCAPS, 0,
-	    sessionid, 0, 0, context) == -1)
-		return 0;
-	if (agentx_pdu_add_oid(ax, id, 0) == -1)
-		return 0;
-	if (agentx_pdu_add_str(ax, descr) == -1)
-		return 0;
-
-	return agentx_pdu_queue(ax);
-}
-
-uint32_t
-agentx_removeagentcaps(struct agentx *ax, uint32_t sessionid,
-    struct agentx_ostring *context, struct agentx_oid *id)
-{
-	if (agentx_pdu_header(ax, AGENTX_PDU_TYPE_REMOVEAGENTCAPS, 0,
-	    sessionid, 0, 0, context) == -1)
-		return 0;
-	if (agentx_pdu_add_oid(ax, id, 0) == -1)
-		return 0;
-
-	return agentx_pdu_queue(ax);
-
-}
-
-uint32_t
-agentx_register(struct agentx *ax, uint8_t flags, uint32_t sessionid,
-    struct agentx_ostring *context, uint8_t timeout, uint8_t priority,
-    uint8_t range_subid, struct agentx_oid *subtree, uint32_t upperbound)
-{
-	if (flags & ~(AGENTX_PDU_FLAG_INSTANCE_REGISTRATION)) {
-		errno = EINVAL;
-		return 0;
-	}
-
-	if (agentx_pdu_header(ax, AGENTX_PDU_TYPE_REGISTER, flags,
-	    sessionid, 0, 0, context) == -1)
-		return 0;
-
-	if (agentx_pdu_need(ax, 4) == -1)
-		return 0;
-	ax->ax_wbuf[ax->ax_wbtlen++] = timeout;
-	ax->ax_wbuf[ax->ax_wbtlen++] = priority;
-	ax->ax_wbuf[ax->ax_wbtlen++] = range_subid;
-	ax->ax_wbuf[ax->ax_wbtlen++] = 0;
-	if (agentx_pdu_add_oid(ax, subtree, 0) == -1)
-		return 0;
-	if (range_subid != 0) {
-		if (agentx_pdu_add_uint32(ax, upperbound) == -1)
-			return 0;
-	}
-
-	return agentx_pdu_queue(ax);
-}
-
-uint32_t
-agentx_unregister(struct agentx *ax, uint32_t sessionid,
-    struct agentx_ostring *context, uint8_t priority, uint8_t range_subid,
-    struct agentx_oid *subtree, uint32_t upperbound)
-{
-	if (agentx_pdu_header(ax, AGENTX_PDU_TYPE_UNREGISTER, 0,
-	    sessionid, 0, 0, context) == -1)
-		return 0;
-
-	if (agentx_pdu_need(ax, 4) == -1)
-		return 0;
-	ax->ax_wbuf[ax->ax_wbtlen++] = 0;
-	ax->ax_wbuf[ax->ax_wbtlen++] = priority;
-	ax->ax_wbuf[ax->ax_wbtlen++] = range_subid;
-	ax->ax_wbuf[ax->ax_wbtlen++] = 0;
-	if (agentx_pdu_add_oid(ax, subtree, 0) == -1)
-		return 0;
-	if (range_subid != 0) {
-		if (agentx_pdu_add_uint32(ax, upperbound) == -1)
-			return 0;
-	}
-
-	return agentx_pdu_queue(ax);
-}
-
-int
-agentx_response(struct agentx *ax, uint32_t sessionid, uint32_t transactionid,
-    uint32_t packetid, struct agentx_ostring *context, uint32_t sysuptime,
-    uint16_t error, uint16_t index, struct agentx_varbind *vblist, size_t nvb)
-{
-	if (agentx_pdu_header(ax, AGENTX_PDU_TYPE_RESPONSE, 0, sessionid,
-	    transactionid, packetid, context) == -1)
-		return -1;
-
-	if (agentx_pdu_add_uint32(ax, sysuptime) == -1 ||
-	    agentx_pdu_add_uint16(ax, error) == -1 ||
-	    agentx_pdu_add_uint16(ax, index) == -1)
-		return -1;
-
-	if (agentx_pdu_add_varbindlist(ax, vblist, nvb) == -1)
-		return -1;
-	if (agentx_pdu_queue(ax) == 0)
-		return -1;
-	return 0;
-}
-
-void
-agentx_pdu_free(struct agentx_pdu *pdu)
-{
-	size_t i;
-	struct agentx_pdu_response *response;
-
-	if (pdu->ap_header.aph_flags & AGENTX_PDU_FLAG_NON_DEFAULT_CONTEXT)
-		free(pdu->ap_context.aos_string);
-
-	switch (pdu->ap_header.aph_type) {
-	case AGENTX_PDU_TYPE_GET:
-	case AGENTX_PDU_TYPE_GETNEXT:
-	case AGENTX_PDU_TYPE_GETBULK:
-		free(pdu->ap_payload.ap_srl.ap_sr);
-		break;
-	case AGENTX_PDU_TYPE_RESPONSE:
-		response = &(pdu->ap_payload.ap_response);
-		for (i = 0; i < response->ap_nvarbind; i++)
-			agentx_varbind_free(&(response->ap_varbindlist[i]));
-		free(response->ap_varbindlist);
-		break;
-	default:
-		free(pdu->ap_payload.ap_raw);
-		break;
-	}
-	free(pdu);
-}
-
-void
-agentx_varbind_free(struct agentx_varbind *varbind)
-{
-	switch (varbind->avb_type) {
-	case AGENTX_DATA_TYPE_OCTETSTRING:
-	case AGENTX_DATA_TYPE_IPADDRESS:
-	case AGENTX_DATA_TYPE_OPAQUE:
-		free(varbind->avb_data.avb_ostring.aos_string);
-		break;
-	default:
-		break;
-	}
-}
-
-const char *
-agentx_error2string(enum agentx_pdu_error error)
-{
-	static char buffer[64];
-	switch (error) {
-	case AGENTX_PDU_ERROR_NOERROR:
-		return "No error";
-	case AGENTX_PDU_ERROR_GENERR:
-		return "Generic error";
-	case AGENTX_PDU_ERROR_NOACCESS:
-		return "No access";
-	case AGENTX_PDU_ERROR_WRONGTYPE:
-		return "Wrong type";
-	case AGENTX_PDU_ERROR_WRONGLENGTH:
-		return "Wrong length";
-	case AGENTX_PDU_ERROR_WRONGENCODING:
-		return "Wrong encoding";
-	case AGENTX_PDU_ERROR_WRONGVALUE:
-		return "Wrong value";
-	case AGENTX_PDU_ERROR_NOCREATION:
-		return "No creation";
-	case AGENTX_PDU_ERROR_INCONSISTENTVALUE:
-		return "Inconsistent value";
-	case AGENTX_PDU_ERROR_RESOURCEUNAVAILABLE:
-		return "Resource unavailable";
-	case AGENTX_PDU_ERROR_COMMITFAILED:
-		return "Commit failed";
-	case AGENTX_PDU_ERROR_UNDOFAILED:
-		return "Undo failed";
-	case AGENTX_PDU_ERROR_NOTWRITABLE:
-		return "Not writable";
-	case AGENTX_PDU_ERROR_INCONSISTENTNAME:
-		return "Inconsistent name";
-	case AGENTX_PDU_ERROR_OPENFAILED:
-		return "Open Failed";
-	case AGENTX_PDU_ERROR_NOTOPEN:
-		return "Not open";
-	case AGENTX_PDU_ERROR_INDEXWRONGTYPE:
-		return "Index wrong type";
-	case AGENTX_PDU_ERROR_INDEXALREADYALLOCATED:
-		return "Index already allocated";
-	case AGENTX_PDU_ERROR_INDEXNONEAVAILABLE:
-		return "Index none available";
-	case AGENTX_PDU_ERROR_INDEXNOTALLOCATED:
-		return "Index not allocated";
-	case AGENTX_PDU_ERROR_UNSUPPORTEDCONETXT:
-		return "Unsupported context";
-	case AGENTX_PDU_ERROR_DUPLICATEREGISTRATION:
-		return "Duplicate registration";
-	case AGENTX_PDU_ERROR_UNKNOWNREGISTRATION:
-		return "Unkown registration";
-	case AGENTX_PDU_ERROR_UNKNOWNAGENTCAPS:
-		return "Unknown agent capabilities";
-	case AGENTX_PDU_ERROR_PARSEERROR:
-		return "Parse error";
-	case AGENTX_PDU_ERROR_REQUESTDENIED:
-		return "Request denied";
-	case AGENTX_PDU_ERROR_PROCESSINGERROR:
-		return "Processing error";
-	}
-	snprintf(buffer, sizeof(buffer), "Unknown error: %d", error);
-	return buffer;
-}
-
-const char *
-agentx_pdutype2string(enum agentx_pdu_type type)
-{
-	static char buffer[64];
-	switch(type) {
-	case AGENTX_PDU_TYPE_OPEN:
-		return "agentx-Open-PDU";
-	case AGENTX_PDU_TYPE_CLOSE:
-		return "agentx-Close-PDU";
-	case AGENTX_PDU_TYPE_REGISTER:
-		return "agentx-Register-PDU";
-	case AGENTX_PDU_TYPE_UNREGISTER:
-		return "agentx-Unregister-PDU";
-	case AGENTX_PDU_TYPE_GET:
-		return "agentx-Get-PDU";
-	case AGENTX_PDU_TYPE_GETNEXT:
-		return "agentx-GetNext-PDU";
-	case AGENTX_PDU_TYPE_GETBULK:
-		return "agentx-GetBulk-PDU";
-	case AGENTX_PDU_TYPE_TESTSET:
-		return "agentx-TestSet-PDU";
-	case AGENTX_PDU_TYPE_COMMITSET:
-		return "agentx-CommitSet-PDU";
-	case AGENTX_PDU_TYPE_UNDOSET:
-		return "agentx-UndoSet-PDU";
-	case AGENTX_PDU_TYPE_CLEANUPSET:
-		return "agentx-CleanupSet-PDU";
-	case AGENTX_PDU_TYPE_NOTIFY:
-		return "agentx-Notify-PDU";
-	case AGENTX_PDU_TYPE_PING:
-		return "agentx-Ping-PDU";
-	case AGENTX_PDU_TYPE_INDEXALLOCATE:
-		return "agentx-IndexAllocate-PDU";
-	case AGENTX_PDU_TYPE_INDEXDEALLOCATE:
-		return "agentx-IndexDeallocate-PDU";
-	case AGENTX_PDU_TYPE_ADDAGENTCAPS:
-		return "agentx-AddAgentCaps-PDU";
-	case AGENTX_PDU_TYPE_REMOVEAGENTCAPS:
-		return "agentx-RemoveAgentCaps-PDU";
-	case AGENTX_PDU_TYPE_RESPONSE:
-		return "agentx-Response-PDU";
-	}
-	snprintf(buffer, sizeof(buffer), "Unknown type: %d", type);
-	return buffer;
-}
-
-const char *
-agentx_closereason2string(enum agentx_close_reason reason)
-{
-	static char buffer[64];
-
-	switch (reason) {
-	case AGENTX_CLOSE_OTHER:
-		return "Undefined reason";
-	case AGENTX_CLOSEN_PARSEERROR:
-		return "Too many AgentX parse errors from peer";
-	case AGENTX_CLOSE_PROTOCOLERROR:
-		return "Too many AgentX protocol errors from peer";
-	case AGENTX_CLOSE_TIMEOUTS:
-		return "Too many timeouts waiting for peer";
-	case AGENTX_CLOSE_SHUTDOWN:
-		return "shutting down";
-	case AGENTX_CLOSE_BYMANAGER:
-		return "Manager shuts down";
-	}
-	snprintf(buffer, sizeof(buffer), "Unknown reason: %d", reason);
-	return buffer;
-}
-
-const char *
-agentx_oid2string(struct agentx_oid *oid)
-{
-	return agentx_oidrange2string(oid, 0, 0);
-}
-
-const char *
-agentx_oidrange2string(struct agentx_oid *oid, uint8_t range_subid,
-    uint32_t upperbound)
-{
-	static char buf[1024];
-	char *p;
-	size_t i, rest;
-	int ret;
-
-	rest = sizeof(buf);
-	p = buf;
-	for (i = 0; i < oid->aoi_idlen; i++) {
-		if (range_subid != 0 && range_subid - 1 == (uint8_t)i)
-			ret = snprintf(p, rest, ".[%u-%u]", oid->aoi_id[i],
-			    upperbound);
-		else
-			ret = snprintf(p, rest, ".%u", oid->aoi_id[i]);
-		if ((size_t) ret >= rest) {
-			snprintf(buf, sizeof(buf), "Couldn't parse oid");
-			return buf;
-		}
-		p += ret;
-		rest -= (size_t) ret;
-	}
-	return buf;
-}
-
-const char *
-agentx_varbind2string(struct agentx_varbind *vb)
-{
-	static char buf[1024];
-	char tmpbuf[1024];
-	size_t i, bufleft;
-	int ishex = 0;
-	char *p;
-	int ret;
-
-	switch (vb->avb_type) {
-	case AGENTX_DATA_TYPE_INTEGER:
-		(void) snprintf(buf, sizeof(buf), "%s: (int)%u",
-		    agentx_oid2string(&(vb->avb_oid)), vb->avb_data.avb_uint32);
-		break;
-	case AGENTX_DATA_TYPE_OCTETSTRING:
-		for (i = 0;
-		    i < vb->avb_data.avb_ostring.aos_slen && !ishex; i++) {
-			if (!isprint(vb->avb_data.avb_ostring.aos_string[i]))
-				ishex = 1;
-		}
-		if (ishex) {
-			p = tmpbuf;
-			bufleft = sizeof(tmpbuf);
-			for (i = 0;
-			    i < vb->avb_data.avb_ostring.aos_slen; i++) {
-				ret = snprintf(p, bufleft, " %02hhX",
-				    vb->avb_data.avb_ostring.aos_string[i]);
-				if (ret >= (int) bufleft) {
-					p = strrchr(p, ' ');
-					strlcpy(p, "...", 4);
-					break;
-				}
-				p += 3;
-				bufleft -= 3;
-			}
-			ret = snprintf(buf, sizeof(buf), "%s: (hex-string)%s",
-			    agentx_oid2string(&(vb->avb_oid)), tmpbuf);
-			if (ret >= (int) sizeof(buf)) {
-				p  = strrchr(buf, ' ');
-				strlcpy(p, "...", 4);
-			}
-		} else {
-			ret = snprintf(buf, sizeof(buf), "%s: (string)",
-			    agentx_oid2string(&(vb->avb_oid)));
-			if (ret >= (int) sizeof(buf)) {
-				snprintf(buf, sizeof(buf), "<too large OID>: "
-				    "(string)<too large string>");
-				break;
-			}
-			p = buf + ret;
-			bufleft = (int) sizeof(buf) - ret;
-			if (snprintf(p, bufleft, "%.*s",
-			    vb->avb_data.avb_ostring.aos_slen,
-			    vb->avb_data.avb_ostring.aos_string) >=
-			    (int) bufleft) {
-				p = buf + sizeof(buf) - 4;
-				(void) strlcpy(p, "...", 4);
-			}
-		}
-		break;
-	case AGENTX_DATA_TYPE_NULL:
-		(void) snprintf(buf, sizeof(buf), "%s: <null>",
-		    agentx_oid2string(&(vb->avb_oid)));
-		break;
-	case AGENTX_DATA_TYPE_OID:
-		(void) strlcpy(tmpbuf,
-		    agentx_oid2string(&(vb->avb_data.avb_oid)), sizeof(tmpbuf));
-		snprintf(buf, sizeof(buf), "%s: (oid)%s",
-		    agentx_oid2string(&(vb->avb_oid)), tmpbuf);
-		break;
-	case AGENTX_DATA_TYPE_IPADDRESS:
-		if (vb->avb_data.avb_ostring.aos_slen != 4) {
-			snprintf(buf, sizeof(buf), "%s: (ipaddress)<invalid>",
-			    agentx_oid2string(&(vb->avb_oid)));
-			break;
-		}
-		if (inet_ntop(PF_INET, vb->avb_data.avb_ostring.aos_string,
-		    tmpbuf, sizeof(tmpbuf)) == NULL) {
-			snprintf(buf, sizeof(buf), "%s: (ipaddress)"
-			    "<unparseable>: %s",
-			    agentx_oid2string(&(vb->avb_oid)),
-			    strerror(errno));
-			break;
-		}
-		snprintf(buf, sizeof(buf), "%s: (ipaddress)%s",
-		    agentx_oid2string(&(vb->avb_oid)), tmpbuf);
-		break;
-	case AGENTX_DATA_TYPE_COUNTER32:
-		(void) snprintf(buf, sizeof(buf), "%s: (counter32)%u",
-		    agentx_oid2string(&(vb->avb_oid)), vb->avb_data.avb_uint32);
-		break;
-	case AGENTX_DATA_TYPE_GAUGE32:
-		(void) snprintf(buf, sizeof(buf), "%s: (gauge32)%u",
-		    agentx_oid2string(&(vb->avb_oid)), vb->avb_data.avb_uint32);
-		break;
-	case AGENTX_DATA_TYPE_TIMETICKS:
-		(void) snprintf(buf, sizeof(buf), "%s: (timeticks)%u",
-		    agentx_oid2string(&(vb->avb_oid)), vb->avb_data.avb_uint32);
-		break;
-	case AGENTX_DATA_TYPE_OPAQUE:
-		p = tmpbuf;
-		bufleft = sizeof(tmpbuf);
-		for (i = 0;
-		    i < vb->avb_data.avb_ostring.aos_slen; i++) {
-			ret = snprintf(p, bufleft, " %02hhX",
-			    vb->avb_data.avb_ostring.aos_string[i]);
-			if (ret >= (int) bufleft) {
-				p = strrchr(p, ' ');
-				strlcpy(p, "...", 4);
-				break;
-			}
-			p += 3;
-			bufleft -= 3;
-		}
-		ret = snprintf(buf, sizeof(buf), "%s: (opaque)%s",
-		    agentx_oid2string(&(vb->avb_oid)), tmpbuf);
-		if (ret >= (int) sizeof(buf)) {
-			p  = strrchr(buf, ' ');
-			strlcpy(p, "...", 4);
-		}
-		break;
-	case AGENTX_DATA_TYPE_COUNTER64:
-		(void) snprintf(buf, sizeof(buf), "%s: (counter64)%"PRIu64,
-		    agentx_oid2string(&(vb->avb_oid)), vb->avb_data.avb_uint64);
-		break;
-	case AGENTX_DATA_TYPE_NOSUCHOBJECT:
-		(void) snprintf(buf, sizeof(buf), "%s: <noSuchObject>",
-		    agentx_oid2string(&(vb->avb_oid)));
-		break;
-	case AGENTX_DATA_TYPE_NOSUCHINSTANCE:
-		(void) snprintf(buf, sizeof(buf), "%s: <noSuchInstance>",
-		    agentx_oid2string(&(vb->avb_oid)));
-		break;
-	case AGENTX_DATA_TYPE_ENDOFMIBVIEW:
-		(void) snprintf(buf, sizeof(buf), "%s: <endOfMibView>",
-		    agentx_oid2string(&(vb->avb_oid)));
-		break;
-	}
-	return buf;
-}
-
-int
-agentx_oid_cmp(struct agentx_oid *o1, struct agentx_oid *o2)
-{
-	size_t i, min;
-
-	min = o1->aoi_idlen < o2->aoi_idlen ? o1->aoi_idlen : o2->aoi_idlen;
-	for (i = 0; i < min; i++) {
-		if (o1->aoi_id[i] < o2->aoi_id[i])
-			return -1;
-		if (o1->aoi_id[i] > o2->aoi_id[i])
-			return 1;
-	}
-	/* o1 is parent of o2 */
-	if (o1->aoi_idlen < o2->aoi_idlen)
-		return -2;
-	/* o1 is child of o2 */
-	if (o1->aoi_idlen > o2->aoi_idlen)
-		return 2;
-	return 0;
-}
-
-int
-agentx_oid_add(struct agentx_oid *oid, uint32_t value)
-{
-	if (oid->aoi_idlen == AGENTX_OID_MAX_LEN)
-		return -1;
-	oid->aoi_id[oid->aoi_idlen++] = value;
-	return 0;
-}
-
-static uint32_t
-agentx_pdu_queue(struct agentx *ax)
-{
-	struct agentx_pdu_header header;
-	uint32_t packetid, plength;
-	size_t wbtlen = ax->ax_wbtlen;
-
-	header.aph_flags = ax->ax_byteorder == AGENTX_BYTE_ORDER_BE ?
-	    AGENTX_PDU_FLAG_NETWORK_BYTE_ORDER : 0;
-	packetid = agentx_pdutoh32(&header, &(ax->ax_wbuf[ax->ax_wblen + 12]));
-	plength = (ax->ax_wbtlen - ax->ax_wblen) - AGENTX_PDU_HEADER;
-	ax->ax_wbtlen = ax->ax_wblen + 16;
-	(void)agentx_pdu_add_uint32(ax, plength);
-
-	ax->ax_wblen = ax->ax_wbtlen = wbtlen;
-
-	return packetid;
-}
-
-static int
-agentx_pdu_header(struct agentx *ax, enum agentx_pdu_type type, uint8_t flags,
-    uint32_t sessionid, uint32_t transactionid, uint32_t packetid,
-    struct agentx_ostring *context)
-{
-	if (ax->ax_wblen != ax->ax_wbtlen) {
-		errno = EALREADY;
-		return -1;
-	}
-
-	ax->ax_wbtlen = ax->ax_wblen;
-	if (agentx_pdu_need(ax, 4) == -1)
-		return -1;
-	ax->ax_wbuf[ax->ax_wbtlen++] = 1;
-	ax->ax_wbuf[ax->ax_wbtlen++] = (uint8_t) type;
-	if (context != NULL)
-		flags |= AGENTX_PDU_FLAG_NON_DEFAULT_CONTEXT;
-	if (ax->ax_byteorder == AGENTX_BYTE_ORDER_BE)
-		flags |= AGENTX_PDU_FLAG_NETWORK_BYTE_ORDER;
-	ax->ax_wbuf[ax->ax_wbtlen++] = flags;
-	ax->ax_wbuf[ax->ax_wbtlen++] = 0;
-	if (packetid == 0)
-		packetid = agentx_packetid(ax);
-	if (agentx_pdu_add_uint32(ax, sessionid) == -1 ||
-	    agentx_pdu_add_uint32(ax, transactionid) == -1 ||
-	    agentx_pdu_add_uint32(ax, packetid) == -1 ||
-	    agentx_pdu_need(ax, 4) == -1)
-		return -1;
-	ax->ax_wbtlen += 4;
-	if (context != NULL) {
-		if (agentx_pdu_add_str(ax, context) == -1)
-			return -1;
-	}
-
-	return 0;
-}
-
-static uint32_t
-agentx_packetid(struct agentx *ax)
-{
-	uint32_t packetid, *packetids;
-	size_t npackets = 0, i;
-	int found;
-
-	if (ax->ax_packetids != NULL) {
-		for (npackets = 0; ax->ax_packetids[npackets] != 0; npackets++)
-			continue;
-	}
-	if (ax->ax_packetidsize == 0 || npackets == ax->ax_packetidsize - 1) {
-		packetids = recallocarray(ax->ax_packetids, ax->ax_packetidsize,
-		    ax->ax_packetidsize + 25, sizeof(*packetids));
-		if (packetids == NULL)
-			return 0;
-		ax->ax_packetidsize += 25;
-		ax->ax_packetids = packetids;
-	}
-	do {
-		found = 0;
-		packetid = arc4random();
-		for (i = 0; ax->ax_packetids[i] != 0; i++) {
-			if (ax->ax_packetids[i] == packetid) {
-				found = 1;
-				break;
-			}
-		}
-	} while (packetid == 0 || found);
-	ax->ax_packetids[npackets] = packetid;
-
-	return packetid;
-}
-
-static int
-agentx_pdu_add_uint16(struct agentx *ax, uint16_t value)
-{
-	if (agentx_pdu_need(ax, sizeof(value)) == -1)
-		return -1;
-
-	if (ax->ax_byteorder == AGENTX_BYTE_ORDER_BE)
-		value = htobe16(value);
-	else
-		value = htole16(value);
-	memcpy(ax->ax_wbuf + ax->ax_wbtlen, &value, sizeof(value));
-        ax->ax_wbtlen += sizeof(value);
-        return 0;
-}
-
-static int
-agentx_pdu_add_uint32(struct agentx *ax, uint32_t value)
-{
-	if (agentx_pdu_need(ax, sizeof(value)) == -1)
-		return -1;
-
-	if (ax->ax_byteorder == AGENTX_BYTE_ORDER_BE)
-		value = htobe32(value);
-	else
-		value = htole32(value);
-	memcpy(ax->ax_wbuf + ax->ax_wbtlen, &value, sizeof(value));
-        ax->ax_wbtlen += sizeof(value);
-        return 0;
-}
-
-static int
-agentx_pdu_add_uint64(struct agentx *ax, uint64_t value)
-{
-	if (agentx_pdu_need(ax, sizeof(value)) == -1)
-		return -1;
-
-	if (ax->ax_byteorder == AGENTX_BYTE_ORDER_BE)
-		value = htobe64(value);
-	else
-		value = htole64(value);
-	memcpy(ax->ax_wbuf + ax->ax_wbtlen, &value, sizeof(value));
-        ax->ax_wbtlen += sizeof(value);
-        return 0;
-}
-
-
-static int
-agentx_pdu_add_oid(struct agentx *ax, struct agentx_oid *oid, int include)
-{
-	static struct agentx_oid nulloid = {0};
-	uint8_t prefix = 0, n_subid, i = 0;
-
-	n_subid = oid->aoi_idlen;
-
-	if (oid == NULL)
-		oid = &nulloid;
-
-	if (oid->aoi_idlen > 4 &&
-	    oid->aoi_id[0] == 1 && oid->aoi_id[1] == 3 &&
-	    oid->aoi_id[2] == 6 && oid->aoi_id[3] == 1 &&
-	    oid->aoi_id[4] <= UINT8_MAX) {
-		prefix = oid->aoi_id[4];
-		i = 5;
-	}
-
-	if (agentx_pdu_need(ax, 4) == -1)
-		return -1;
-	ax->ax_wbuf[ax->ax_wbtlen++] = n_subid - i;
-	ax->ax_wbuf[ax->ax_wbtlen++] = prefix;
-	ax->ax_wbuf[ax->ax_wbtlen++] = !!include;
-	ax->ax_wbuf[ax->ax_wbtlen++] = 0;
-
-	for (; i < n_subid; i++) {
-		if (agentx_pdu_add_uint32(ax, oid->aoi_id[i]) == -1)
-			return -1;
-	}
-
-	return 0;
-}
-
-static int
-agentx_pdu_add_str(struct agentx *ax, struct agentx_ostring *str)
-{
-	size_t length, zeroes;
-
-	if (agentx_pdu_add_uint32(ax, str->aos_slen) == -1)
-		return -1;
-
-	if ((zeroes = (4 - (str->aos_slen % 4))) == 4)
-		zeroes = 0;
-	length = str->aos_slen + zeroes;
-	if (agentx_pdu_need(ax, length) == -1)
-		return -1;
-
-	memcpy(&(ax->ax_wbuf[ax->ax_wbtlen]), str->aos_string, str->aos_slen);
-	ax->ax_wbtlen += str->aos_slen;
-	memset(&(ax->ax_wbuf[ax->ax_wbtlen]), 0, zeroes);
-	ax->ax_wbtlen += zeroes;
-	return 0;
-}
-
-static int
-agentx_pdu_add_varbindlist(struct agentx *ax,
-    struct agentx_varbind *vblist, size_t nvb)
-{
-	size_t i;
-	uint16_t temp;
-
-	for (i = 0; i < nvb; i++) {
-		temp = (uint16_t) vblist[i].avb_type;
-		if (agentx_pdu_add_uint16(ax, temp) == -1 ||
-		    agentx_pdu_need(ax, 2))
-			return -1;
-		memset(&(ax->ax_wbuf[ax->ax_wbtlen]), 0, 2);
-		ax->ax_wbtlen += 2;
-		if (agentx_pdu_add_oid(ax, &(vblist[i].avb_oid), 0) == -1)
-			return -1;
-		switch (vblist[i].avb_type) {
-		case AGENTX_DATA_TYPE_INTEGER:
-		case AGENTX_DATA_TYPE_COUNTER32:
-		case AGENTX_DATA_TYPE_GAUGE32:
-		case AGENTX_DATA_TYPE_TIMETICKS:
-			if (agentx_pdu_add_uint32(ax,
-			    vblist[i].avb_data.avb_uint32) == -1)
-				return -1;
-			break;
-		case AGENTX_DATA_TYPE_COUNTER64:
-			if (agentx_pdu_add_uint64(ax,
-			    vblist[i].avb_data.avb_uint64) == -1)
-				return -1;
-			break;
-		case AGENTX_DATA_TYPE_OCTETSTRING:
-		case AGENTX_DATA_TYPE_IPADDRESS:
-		case AGENTX_DATA_TYPE_OPAQUE:
-			if (agentx_pdu_add_str(ax,
-			    &(vblist[i].avb_data.avb_ostring)) == -1)
-				return -1;
-			break;
-		case AGENTX_DATA_TYPE_OID:
-			if (agentx_pdu_add_oid(ax,
-			    &(vblist[i].avb_data.avb_oid), 1) == -1)
-				return -1;
-			break;
-		case AGENTX_DATA_TYPE_NULL:
-		case AGENTX_DATA_TYPE_NOSUCHOBJECT:
-		case AGENTX_DATA_TYPE_NOSUCHINSTANCE:
-		case AGENTX_DATA_TYPE_ENDOFMIBVIEW:
-			break;
-		default:
-			errno = EINVAL;
-			return -1;
-		}
-	}
-	return 0;
-}
-
-static uint16_t
-agentx_pdutoh16(struct agentx_pdu_header *header, uint8_t *buf)
-{
-	uint16_t value;
-
-	memcpy(&value, buf, sizeof(value));
-	if (header->aph_flags & AGENTX_PDU_FLAG_NETWORK_BYTE_ORDER)
-		return be16toh(value);
-	return le16toh(value);
-}
-
-static uint32_t
-agentx_pdutoh32(struct agentx_pdu_header *header, uint8_t *buf)
-{
-	uint32_t value;
-
-	memcpy(&value, buf, sizeof(value));
-	if (header->aph_flags & AGENTX_PDU_FLAG_NETWORK_BYTE_ORDER)
-		return be32toh(value);
-	return le32toh(value);
-}
-
-static uint64_t
-agentx_pdutoh64(struct agentx_pdu_header *header, uint8_t *buf)
-{
-	uint64_t value;
-
-	memcpy(&value, buf, sizeof(value));
-	if (header->aph_flags & AGENTX_PDU_FLAG_NETWORK_BYTE_ORDER)
-		return be64toh(value);
-	return le64toh(value);
-}
-
-static ssize_t
-agentx_pdutooid(struct agentx_pdu_header *header, struct agentx_oid *oid,
-    uint8_t *buf, size_t rawlen)
-{
-	size_t i = 0;
-	ssize_t nread;
-
-	if (rawlen < 4)
-		goto fail;
-	rawlen -= 4;
-	nread = 4;
-	oid->aoi_idlen = *buf++;
-	if (rawlen < (oid->aoi_idlen * 4))
-		goto fail;
-	nread += oid->aoi_idlen * 4;
-	if (*buf != 0) {
-		oid->aoi_id[0] = 1;
-		oid->aoi_id[1] = 3;
-		oid->aoi_id[2] = 6;
-		oid->aoi_id[3] = 1;
-		oid->aoi_id[4] = *buf;
-		oid->aoi_idlen += 5;
-		i = 5;
-	}
-	buf++;
-	oid->aoi_include = *buf;
-	for (buf += 2; i < oid->aoi_idlen; i++, buf += 4)
-		oid->aoi_id[i] = agentx_pdutoh32(header, buf);
-
-	return nread;
-
-fail:
-	errno = EPROTO;
-	return -1;
-}
-
-static ssize_t
-agentx_pdutoostring(struct agentx_pdu_header *header,
-    struct agentx_ostring *ostring, uint8_t *buf, size_t rawlen)
-{
-	ssize_t nread;
-
-	if (rawlen < 4)
-		goto fail;
-
-	ostring->aos_slen = agentx_pdutoh32(header, buf);
-	rawlen -= 4;
-	buf += 4;
-	if (ostring->aos_slen > rawlen)
-		goto fail;
-	if ((ostring->aos_string = malloc(ostring->aos_slen + 1)) == NULL)
-		return -1;
-	memcpy(ostring->aos_string, buf, ostring->aos_slen);
-	ostring->aos_string[ostring->aos_slen] = '\0';
-
-	nread = 4 + ostring->aos_slen;
-	if (ostring->aos_slen % 4 != 0)
-		nread += 4 - (ostring->aos_slen % 4);
-
-	return nread;
-
-fail:
-	errno = EPROTO;
-	return -1;
-}
-
-static ssize_t
-agentx_pdutovarbind(struct agentx_pdu_header *header,
-    struct agentx_varbind *varbind, uint8_t *buf, size_t rawlen)
-{
-	ssize_t nread, rread = 4;
-
-	if (rawlen == 0)
-		return 0;
-
-	if (rawlen < 8)
-		goto fail;
-	varbind->avb_type = agentx_pdutoh16(header, buf);
-
-	buf += 4;
-	rawlen -= 4;
-	nread = agentx_pdutooid(header, &(varbind->avb_oid), buf, rawlen);
-	if (nread == -1)
-		return -1;
-	rread += nread;
-	buf += nread;
-	rawlen -= nread;
-
-	switch(varbind->avb_type) {
-	case AGENTX_DATA_TYPE_INTEGER:
-	case AGENTX_DATA_TYPE_COUNTER32:
-	case AGENTX_DATA_TYPE_GAUGE32:
-	case AGENTX_DATA_TYPE_TIMETICKS:
-		if (rawlen < 4)
-			goto fail;
-		varbind->avb_data.avb_uint32 = agentx_pdutoh32(header, buf);
-		return rread + 4;
-	case AGENTX_DATA_TYPE_COUNTER64:
-		if (rawlen < 8)
-			goto fail;
-		varbind->avb_data.avb_uint64 = agentx_pdutoh64(header, buf);
-		return rread + 8;
-	case AGENTX_DATA_TYPE_OCTETSTRING:
-	case AGENTX_DATA_TYPE_IPADDRESS:
-	case AGENTX_DATA_TYPE_OPAQUE:
-		nread = agentx_pdutoostring(header,
-		    &(varbind->avb_data.avb_ostring), buf, rawlen);
-		if (rread == -1)
-			return -1;
-		return nread + rread;
-	case AGENTX_DATA_TYPE_OID:
-		nread = agentx_pdutooid(header, &(varbind->avb_data.avb_oid),
-		    buf, rawlen);
-		if (rread == -1)
-			return -1;
-		return nread + rread;
-	case AGENTX_DATA_TYPE_NULL:
-	case AGENTX_DATA_TYPE_NOSUCHOBJECT:
-	case AGENTX_DATA_TYPE_NOSUCHINSTANCE:
-	case AGENTX_DATA_TYPE_ENDOFMIBVIEW:
-		return rread;
-	}
-
-fail:
-	errno = EPROTO;
-	return -1;
-}
blob - 8adde286a9b15ab3fd8761510830edb5af4a9403 (mode 644)
blob + /dev/null
--- agentx.h
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdint.h>
-
-#define AGENTX_PDU_FLAG_INSTANCE_REGISTRATION (1 << 0)
-#define AGENTX_PDU_FLAG_NEW_INDEX (1 << 1)
-#define AGENTX_PDU_FLAG_ANY_INDEX (1 << 2)
-#define AGENTX_PDU_FLAG_NON_DEFAULT_CONTEXT (1 << 3)
-#define AGENTX_PDU_FLAG_NETWORK_BYTE_ORDER (1 << 4)
-
-#define AGENTX_PRIORITY_DEFAULT 127
-
-enum agentx_byte_order {
-	AGENTX_BYTE_ORDER_BE,
-	AGENTX_BYTE_ORDER_LE
-};
-
-#if BYTE_ORDER == BIG_ENDIAN
-#define AGENTX_BYTE_ORDER_NATIVE AGENTX_BYTE_ORDER_BE
-#else
-#define AGENTX_BYTE_ORDER_NATIVE AGENTX_BYTE_ORDER_LE
-#endif
-
-enum agentx_pdu_type {
-	AGENTX_PDU_TYPE_OPEN		= 1,
-	AGENTX_PDU_TYPE_CLOSE		= 2,
-	AGENTX_PDU_TYPE_REGISTER	= 3,
-	AGENTX_PDU_TYPE_UNREGISTER	= 4,
-	AGENTX_PDU_TYPE_GET		= 5,
-	AGENTX_PDU_TYPE_GETNEXT		= 6,
-	AGENTX_PDU_TYPE_GETBULK		= 7,
-	AGENTX_PDU_TYPE_TESTSET		= 8,
-	AGENTX_PDU_TYPE_COMMITSET	= 9,
-	AGENTX_PDU_TYPE_UNDOSET		= 10,
-	AGENTX_PDU_TYPE_CLEANUPSET	= 11,
-	AGENTX_PDU_TYPE_NOTIFY		= 12,
-	AGENTX_PDU_TYPE_PING		= 13,
-	AGENTX_PDU_TYPE_INDEXALLOCATE	= 14,
-	AGENTX_PDU_TYPE_INDEXDEALLOCATE	= 15,
-	AGENTX_PDU_TYPE_ADDAGENTCAPS	= 16,
-	AGENTX_PDU_TYPE_REMOVEAGENTCAPS	= 17,
-	AGENTX_PDU_TYPE_RESPONSE	= 18
-};
-
-enum agentx_pdu_error {
-	AGENTX_PDU_ERROR_NOERROR		= 0,
-	AGENTX_PDU_ERROR_GENERR			= 5,
-	AGENTX_PDU_ERROR_NOACCESS		= 6,
-	AGENTX_PDU_ERROR_WRONGTYPE		= 7,
-	AGENTX_PDU_ERROR_WRONGLENGTH		= 8,
-	AGENTX_PDU_ERROR_WRONGENCODING		= 9,
-	AGENTX_PDU_ERROR_WRONGVALUE		= 10,
-	AGENTX_PDU_ERROR_NOCREATION		= 11,
-	AGENTX_PDU_ERROR_INCONSISTENTVALUE	= 12,
-	AGENTX_PDU_ERROR_RESOURCEUNAVAILABLE	= 13,
-	AGENTX_PDU_ERROR_COMMITFAILED		= 14,
-	AGENTX_PDU_ERROR_UNDOFAILED		= 15,
-	AGENTX_PDU_ERROR_NOTWRITABLE		= 17,
-	AGENTX_PDU_ERROR_INCONSISTENTNAME	= 18,
-	AGENTX_PDU_ERROR_OPENFAILED		= 256,
-	AGENTX_PDU_ERROR_NOTOPEN		= 257,
-	AGENTX_PDU_ERROR_INDEXWRONGTYPE		= 258,
-	AGENTX_PDU_ERROR_INDEXALREADYALLOCATED	= 259,
-	AGENTX_PDU_ERROR_INDEXNONEAVAILABLE	= 260,
-	AGENTX_PDU_ERROR_INDEXNOTALLOCATED	= 261,
-	AGENTX_PDU_ERROR_UNSUPPORTEDCONETXT	= 262,
-	AGENTX_PDU_ERROR_DUPLICATEREGISTRATION	= 263,
-	AGENTX_PDU_ERROR_UNKNOWNREGISTRATION	= 264,
-	AGENTX_PDU_ERROR_UNKNOWNAGENTCAPS	= 265,
-	AGENTX_PDU_ERROR_PARSEERROR		= 266,
-	AGENTX_PDU_ERROR_REQUESTDENIED		= 267,
-	AGENTX_PDU_ERROR_PROCESSINGERROR	= 268
-};
-
-enum agentx_data_type {
-	AGENTX_DATA_TYPE_INTEGER	= 2,
-	AGENTX_DATA_TYPE_OCTETSTRING	= 4,
-	AGENTX_DATA_TYPE_NULL		= 5,
-	AGENTX_DATA_TYPE_OID		= 6,
-	AGENTX_DATA_TYPE_IPADDRESS	= 64,
-	AGENTX_DATA_TYPE_COUNTER32	= 65,
-	AGENTX_DATA_TYPE_GAUGE32	= 66,
-	AGENTX_DATA_TYPE_TIMETICKS	= 67,
-	AGENTX_DATA_TYPE_OPAQUE		= 68,
-	AGENTX_DATA_TYPE_COUNTER64	= 70,
-	AGENTX_DATA_TYPE_NOSUCHOBJECT	= 128,
-	AGENTX_DATA_TYPE_NOSUCHINSTANCE	= 129,
-	AGENTX_DATA_TYPE_ENDOFMIBVIEW	= 130
-};
-
-enum agentx_close_reason {
-	AGENTX_CLOSE_OTHER		= 1,
-	AGENTX_CLOSEN_PARSEERROR	= 2,
-	AGENTX_CLOSE_PROTOCOLERROR	= 3,
-	AGENTX_CLOSE_TIMEOUTS		= 4,
-	AGENTX_CLOSE_SHUTDOWN		= 5,
-	AGENTX_CLOSE_BYMANAGER		= 6
-};
-
-struct agentx {
-	int ax_fd;
-	enum agentx_byte_order ax_byteorder;
-	uint8_t *ax_rbuf;
-	size_t ax_rblen;
-	size_t ax_rbsize;
-	uint8_t *ax_wbuf;
-	size_t ax_wblen;
-	size_t ax_wbtlen;
-	size_t ax_wbsize;
-	uint32_t *ax_packetids;
-	size_t ax_packetidsize;
-};
-
-#ifndef AGENTX_PRIMITIVE
-#define AGENTX_PRIMITIVE
-
-#define AGENTX_OID_MAX_LEN 128
-
-struct agentx_oid {
-	uint8_t aoi_include;
-	uint32_t aoi_id[AGENTX_OID_MAX_LEN];
-	size_t aoi_idlen;
-};
-
-struct agentx_ostring {
-	unsigned char *aos_string;
-	uint32_t aos_slen;
-};
-#endif
-
-struct agentx_searchrange {
-	struct agentx_oid asr_start;
-	struct agentx_oid asr_stop;
-};
-
-struct agentx_pdu_header {
-	uint8_t	aph_version;
-	uint8_t	aph_type;
-	uint8_t	aph_flags;
-	uint8_t	aph_reserved;
-	uint32_t aph_sessionid;
-	uint32_t aph_transactionid;
-	uint32_t aph_packetid;
-	uint32_t aph_plength;
-} __packed;
-
-struct agentx_varbind {
-	enum agentx_data_type avb_type;
-	struct agentx_oid avb_oid;
-	union agentx_data {
-		uint32_t avb_uint32;
-		uint64_t avb_uint64;
-		struct agentx_ostring avb_ostring;
-		struct agentx_oid avb_oid;
-	} avb_data;
-};
-
-struct agentx_pdu {
-	struct agentx_pdu_header ap_header;
-	struct agentx_ostring ap_context;
-	union {
-		struct agentx_pdu_searchrangelist {
-			size_t ap_nsr;
-			struct agentx_searchrange *ap_sr;
-		} ap_srl;
-		struct agentx_pdu_getbulk {
-			uint16_t ap_nonrep;
-			uint16_t ap_maxrep;
-			struct agentx_pdu_searchrangelist ap_srl;
-		} ap_getbulk;
-		struct agentx_pdu_varbindlist {
-			struct agentx_varbind *ap_varbind;
-			size_t ap_nvarbind;
-		} ap_vbl;
-		struct agentx_pdu_response {
-			uint32_t ap_uptime;
-			enum agentx_pdu_error ap_error;
-			uint16_t ap_index;
-			struct agentx_varbind *ap_varbindlist;
-			size_t ap_nvarbind;
-		} ap_response;
-		void *ap_raw;
-	} ap_payload;
-};
-
-struct agentx *agentx_new(int);
-void agentx_free(struct agentx *);
-struct agentx_pdu *agentx_recv(struct agentx *);
-ssize_t agentx_send(struct agentx *);
-uint32_t agentx_open(struct agentx *, uint8_t, struct agentx_oid *,
-    struct agentx_ostring *);
-uint32_t agentx_close(struct agentx *, uint32_t, enum agentx_close_reason);
-uint32_t agentx_indexallocate(struct agentx *, uint8_t, uint32_t,
-    struct agentx_ostring *, struct agentx_varbind *, size_t);
-uint32_t agentx_indexdeallocate(struct agentx *, uint32_t,
-    struct agentx_ostring *, struct agentx_varbind *, size_t);
-uint32_t agentx_addagentcaps(struct agentx *, uint32_t, struct agentx_ostring *,
-    struct agentx_oid *, struct agentx_ostring *);
-uint32_t agentx_removeagentcaps(struct agentx *, uint32_t,
-    struct agentx_ostring *, struct agentx_oid *);
-uint32_t agentx_register(struct agentx *, uint8_t, uint32_t,
-    struct agentx_ostring *, uint8_t, uint8_t, uint8_t, struct agentx_oid *,
-    uint32_t);
-uint32_t agentx_unregister(struct agentx *, uint32_t, struct agentx_ostring *,
-    uint8_t, uint8_t, struct agentx_oid *, uint32_t);
-int agentx_response(struct agentx *, uint32_t, uint32_t, uint32_t,
-    struct agentx_ostring *, uint32_t, uint16_t, uint16_t,
-    struct agentx_varbind *, size_t);
-void agentx_pdu_free(struct agentx_pdu *);
-void agentx_varbind_free(struct agentx_varbind *);
-const char *agentx_error2string(enum agentx_pdu_error);
-const char *agentx_pdutype2string(enum agentx_pdu_type);
-const char *agentx_oid2string(struct agentx_oid *);
-const char *agentx_oidrange2string(struct agentx_oid *, uint8_t, uint32_t);
-const char *agentx_varbind2string(struct agentx_varbind *);
-const char *agentx_closereason2string(enum agentx_close_reason);
-int agentx_oid_cmp(struct agentx_oid *, struct agentx_oid *);
-int agentx_oid_add(struct agentx_oid *, uint32_t);
blob - edb7667c910c5398da7c6f2e95a34fe254eb0e89
blob + ccc5aa162dd11ebe3c1d4e71fc3f67c17171613c
--- agentx_control.c
+++ agentx_control.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: agentx_control.c,v 1.2 2020/10/25 10:17:49 denis Exp $	*/
+/*	$OpenBSD: agentx_control.c,v 1.3 2020/10/26 16:52:06 martijn Exp $	*/
 
 /*
  * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org>
@@ -25,6 +25,7 @@
 
 #include <netinet/in.h>
 
+#include <agentx.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,7 +38,6 @@
 #include <imsg.h>
 
 #include "relayd.h"
-#include "subagentx.h"
 
 #define RELAYD_MIB	"1.3.6.1.4.1.30155.3"
 #define SNMP_ELEMENT(x...)	do {				\
@@ -52,7 +52,7 @@ static struct snmp_oid	hosttrapoid = {
 };
 */
 
-#define RELAYDINFO		SUBAGENTX_ENTERPRISES, 30155, 3, 2
+#define RELAYDINFO		AGENTX_ENTERPRISES, 30155, 3, 2
 #define RELAYDREDIRECTS		RELAYDINFO, 1
 #define RELAYDREDIRECTENTRY	RELAYDREDIRECTS, 1
 #define RELAYDREDIRECTINDEX	RELAYDREDIRECTENTRY, 1
@@ -124,69 +124,69 @@ static struct snmp_oid	hosttrapoid = {
 #define RELAYDTABLENAME		RELAYDTABLEENTRY, 2
 #define RELAYDTABLESTATUS	RELAYDTABLEENTRY, 3
 
-void agentx_needsock(struct subagentx *, void *, int);
+void agentx_needsock(struct agentx *, void *, int);
 
 struct relayd *env;
 
-struct subagentx *sa = NULL;
-struct subagentx_index *relaydRedirectIdx, *relaydRelayIdx;
-struct subagentx_index *relaydRouterIdx, *relaydNetRouteIdx;
-struct subagentx_index *relaydHostIdx, *relaydSessionRelayIdx;
-struct subagentx_index *relaydSessionIdx, *relaydTableIdx;
+struct agentx *sa = NULL;
+struct agentx_index *relaydRedirectIdx, *relaydRelayIdx;
+struct agentx_index *relaydRouterIdx, *relaydNetRouteIdx;
+struct agentx_index *relaydHostIdx, *relaydSessionRelayIdx;
+struct agentx_index *relaydSessionIdx, *relaydTableIdx;
 
-struct subagentx_object *relaydRedirectIndex, *relaydRedirectStatus;
-struct subagentx_object *relaydRedirectName, *relaydRedirectCnt;
-struct subagentx_object *relaydRedirectAvg, *relaydRedirectLast;
-struct subagentx_object *relaydRedirectAvgHour, *relaydRedirectLastHour;
-struct subagentx_object *relaydRedirectAvgDay, *relaydRedirectLastDay;
+struct agentx_object *relaydRedirectIndex, *relaydRedirectStatus;
+struct agentx_object *relaydRedirectName, *relaydRedirectCnt;
+struct agentx_object *relaydRedirectAvg, *relaydRedirectLast;
+struct agentx_object *relaydRedirectAvgHour, *relaydRedirectLastHour;
+struct agentx_object *relaydRedirectAvgDay, *relaydRedirectLastDay;
 
-struct subagentx_object *relaydRelayIndex, *relaydRelayStatus;
-struct subagentx_object *relaydRelayName, *relaydRelayCnt;
-struct subagentx_object *relaydRelayAvg, *relaydRelayLast;
-struct subagentx_object *relaydRelayAvgHour, *relaydRelayLastHour;
-struct subagentx_object *relaydRelayAvgDay, *relaydRelayLastDay;
+struct agentx_object *relaydRelayIndex, *relaydRelayStatus;
+struct agentx_object *relaydRelayName, *relaydRelayCnt;
+struct agentx_object *relaydRelayAvg, *relaydRelayLast;
+struct agentx_object *relaydRelayAvgHour, *relaydRelayLastHour;
+struct agentx_object *relaydRelayAvgDay, *relaydRelayLastDay;
 
-struct subagentx_object *relaydRouterIndex, *relaydRouterTableIndex;
-struct subagentx_object *relaydRouterStatus, *relaydRouterName;
-struct subagentx_object *relaydRouterLabel, *relaydRouterRtable;
+struct agentx_object *relaydRouterIndex, *relaydRouterTableIndex;
+struct agentx_object *relaydRouterStatus, *relaydRouterName;
+struct agentx_object *relaydRouterLabel, *relaydRouterRtable;
 
-struct subagentx_object *relaydNetRouteIndex, *relaydNetRouteAddr;
-struct subagentx_object *relaydNetRouteAddrType, *relaydNetRoutePrefixLen;
-struct subagentx_object *relaydNetRouteRouterIndex;
+struct agentx_object *relaydNetRouteIndex, *relaydNetRouteAddr;
+struct agentx_object *relaydNetRouteAddrType, *relaydNetRoutePrefixLen;
+struct agentx_object *relaydNetRouteRouterIndex;
 
-struct subagentx_object *relaydHostIndex, *relaydHostParentIndex;
-struct subagentx_object *relaydHostTableIndex, *relaydHostName;
-struct subagentx_object *relaydHostAddress, *relaydHostAddressType;
-struct subagentx_object *relaydHostStatus, *relaydHostCheckCnt;
-struct subagentx_object *relaydHostUpCnt, *relaydHostErrno;
+struct agentx_object *relaydHostIndex, *relaydHostParentIndex;
+struct agentx_object *relaydHostTableIndex, *relaydHostName;
+struct agentx_object *relaydHostAddress, *relaydHostAddressType;
+struct agentx_object *relaydHostStatus, *relaydHostCheckCnt;
+struct agentx_object *relaydHostUpCnt, *relaydHostErrno;
 
-struct subagentx_object *relaydSessionIndex, *relaydSessionRelayIndex;
-struct subagentx_object *relaydSessionInAddr, *relaydSessionInAddrType;
-struct subagentx_object *relaydSessionOutAddr, *relaydSessionOutAddrType;
-struct subagentx_object *relaydSessionPortIn, *relaydSessionPortOut;
-struct subagentx_object *relaydSessionAge, *relaydSessionIdle;
-struct subagentx_object *relaydSessionStatus, *relaydSessionPid;
+struct agentx_object *relaydSessionIndex, *relaydSessionRelayIndex;
+struct agentx_object *relaydSessionInAddr, *relaydSessionInAddrType;
+struct agentx_object *relaydSessionOutAddr, *relaydSessionOutAddrType;
+struct agentx_object *relaydSessionPortIn, *relaydSessionPortOut;
+struct agentx_object *relaydSessionAge, *relaydSessionIdle;
+struct agentx_object *relaydSessionStatus, *relaydSessionPid;
 
-struct subagentx_object *relaydTableIndex, *relaydTableName, *relaydTableStatus;
+struct agentx_object *relaydTableIndex, *relaydTableName, *relaydTableStatus;
 
 void	*sstodata(struct sockaddr_storage *);
 size_t	 sstolen(struct sockaddr_storage *);
 
-struct rdr *agentx_rdr_byidx(uint32_t, enum subagentx_request_type);
-void agentx_redirect(struct subagentx_varbind *);
-struct relay *agentx_relay_byidx(uint32_t, enum subagentx_request_type);
-void agentx_relay(struct subagentx_varbind *);
-struct router *agentx_router_byidx(uint32_t, enum subagentx_request_type);
-void agentx_router(struct subagentx_varbind *);
-struct netroute *agentx_netroute_byidx(uint32_t, enum subagentx_request_type);
-void agentx_netroute(struct subagentx_varbind *);
-struct host *agentx_host_byidx(uint32_t, enum subagentx_request_type);
-void agentx_host(struct subagentx_varbind *);
-struct rsession *agentx_session_byidx(uint32_t, uint32_t,
-    enum subagentx_request_type);
-void agentx_session(struct subagentx_varbind *);
-struct table *agentx_table_byidx(uint32_t, enum subagentx_request_type);
-void agentx_table(struct subagentx_varbind *);
+struct rdr *agentxctl_rdr_byidx(uint32_t, enum agentx_request_type);
+void agentxctl_redirect(struct agentx_varbind *);
+struct relay *agentxctl_relay_byidx(uint32_t, enum agentx_request_type);
+void agentxctl_relay(struct agentx_varbind *);
+struct router *agentxctl_router_byidx(uint32_t, enum agentx_request_type);
+void agentxctl_router(struct agentx_varbind *);
+struct netroute *agentxctl_netroute_byidx(uint32_t, enum agentx_request_type);
+void agentxctl_netroute(struct agentx_varbind *);
+struct host *agentxctl_host_byidx(uint32_t, enum agentx_request_type);
+void agentxctl_host(struct agentx_varbind *);
+struct rsession *agentxctl_session_byidx(uint32_t, uint32_t,
+    enum agentx_request_type);
+void agentxctl_session(struct agentx_varbind *);
+struct table *agentxctl_table_byidx(uint32_t, enum agentx_request_type);
+void agentxctl_table(struct agentx_varbind *);
 
 void	 agentx_sock(int, short, void *);
 #if 0
@@ -198,229 +198,229 @@ int	 snmp_string2oid(const char *, struct snmp_oid *);
 void
 agentx_init(struct relayd *nenv)
 {
-	struct subagentx_session *sas;
-	struct subagentx_context *sac;
-	struct subagentx_region *sar;
-	struct subagentx_index *session_idxs[2];
+	struct agentx_session *sas;
+	struct agentx_context *sac;
+	struct agentx_region *sar;
+	struct agentx_index *session_idxs[2];
 
-	subagentx_log_fatal = fatalx;
-	subagentx_log_warn = log_warnx;
-	subagentx_log_info = log_info;
-	subagentx_log_debug = log_debug;
+	agentx_log_fatal = fatalx;
+	agentx_log_warn = log_warnx;
+	agentx_log_info = log_info;
+	agentx_log_debug = log_debug;
 
 	env = nenv;
 
 	if ((env->sc_conf.flags & F_AGENTX) == 0) {
 		if (sa != NULL)
-			subagentx_free(sa);
+			agentx_free(sa);
 		return;
 	}
 	if (sa != NULL)
 		return;
 
-	if ((sa = subagentx(agentx_needsock, NULL)) == NULL)
+	if ((sa = agentx(agentx_needsock, NULL)) == NULL)
 		fatal("%s: agentx alloc", __func__);
-	if ((sas = subagentx_session(sa, NULL, 0, "relayd", 0)) == NULL)
+	if ((sas = agentx_session(sa, NULL, 0, "relayd", 0)) == NULL)
 		fatal("%s: agentx session alloc", __func__);
-	if ((sac = subagentx_context(sas,
+	if ((sac = agentx_context(sas,
 		env->sc_conf.agentx_context[0] == '\0' ? NULL :
 		env->sc_conf.agentx_context)) == NULL)
 		fatal("%s: agentx context alloc", __func__);
-	sar = subagentx_region(sac, SUBAGENTX_OID(RELAYDINFO), 0);
+	sar = agentx_region(sac, AGENTX_OID(RELAYDINFO), 0);
 	if (sar == NULL)
 		fatal("%s: agentx region alloc", __func__);
-	if ((relaydRedirectIdx = subagentx_index_integer_dynamic(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTINDEX))) == NULL ||
-	    (relaydRelayIdx = subagentx_index_integer_dynamic(sar,
-	    SUBAGENTX_OID(RELAYDRELAYINDEX))) == NULL ||
-	    (relaydRouterIdx = subagentx_index_integer_dynamic(sar,
-	    SUBAGENTX_OID(RELAYDROUTERINDEX))) == NULL ||
-	    (relaydNetRouteIdx = subagentx_index_integer_dynamic(sar,
-	    SUBAGENTX_OID(RELAYDNETROUTEINDEX))) == NULL ||
-	    (relaydHostIdx = subagentx_index_integer_dynamic(sar,
-	    SUBAGENTX_OID(RELAYDHOSTINDEX))) == NULL ||
-	    (relaydSessionIdx = subagentx_index_integer_dynamic(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONINDEX))) == NULL ||
-	    (relaydSessionRelayIdx = subagentx_index_integer_dynamic(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONRELAYINDEX))) == NULL ||
-	    (relaydTableIdx = subagentx_index_integer_dynamic(sar,
-	    SUBAGENTX_OID(RELAYDTABLEINDEX))) == NULL)
+	if ((relaydRedirectIdx = agentx_index_integer_dynamic(sar,
+	    AGENTX_OID(RELAYDREDIRECTINDEX))) == NULL ||
+	    (relaydRelayIdx = agentx_index_integer_dynamic(sar,
+	    AGENTX_OID(RELAYDRELAYINDEX))) == NULL ||
+	    (relaydRouterIdx = agentx_index_integer_dynamic(sar,
+	    AGENTX_OID(RELAYDROUTERINDEX))) == NULL ||
+	    (relaydNetRouteIdx = agentx_index_integer_dynamic(sar,
+	    AGENTX_OID(RELAYDNETROUTEINDEX))) == NULL ||
+	    (relaydHostIdx = agentx_index_integer_dynamic(sar,
+	    AGENTX_OID(RELAYDHOSTINDEX))) == NULL ||
+	    (relaydSessionIdx = agentx_index_integer_dynamic(sar,
+	    AGENTX_OID(RELAYDSESSIONINDEX))) == NULL ||
+	    (relaydSessionRelayIdx = agentx_index_integer_dynamic(sar,
+	    AGENTX_OID(RELAYDSESSIONRELAYINDEX))) == NULL ||
+	    (relaydTableIdx = agentx_index_integer_dynamic(sar,
+	    AGENTX_OID(RELAYDTABLEINDEX))) == NULL)
 		fatal("%s: agentx index alloc", __func__);
 	session_idxs[0] = relaydSessionRelayIdx;
 	session_idxs[1] = relaydSessionIdx;
-	if ((relaydRedirectIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTINDEX), &relaydRedirectIdx, 1, 0,
-	    agentx_redirect)) == NULL ||
-	    (relaydRedirectStatus = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTSTATUS), &relaydRedirectIdx, 1, 0,
-	    agentx_redirect)) == NULL ||
-	    (relaydRedirectName = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTNAME), &relaydRedirectIdx, 1, 0,
-	    agentx_redirect)) == NULL ||
-	    (relaydRedirectCnt = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTCNT), &relaydRedirectIdx, 1, 0,
-	    agentx_redirect)) == NULL ||
-	    (relaydRedirectAvg = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTAVG), &relaydRedirectIdx, 1, 0,
-	    agentx_redirect)) == NULL ||
-	    (relaydRedirectLast = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTLAST), &relaydRedirectIdx, 1, 0,
-	    agentx_redirect)) == NULL ||
-	    (relaydRedirectAvgHour = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTAVGHOUR), &relaydRedirectIdx, 1, 0,
-	    agentx_redirect)) == NULL ||
-	    (relaydRedirectLastHour = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTLASTHOUR), &relaydRedirectIdx, 1, 0,
-	    agentx_redirect)) == NULL ||
-	    (relaydRedirectAvgDay = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTAVGDAY), &relaydRedirectIdx, 1, 0,
-	    agentx_redirect)) == NULL ||
-	    (relaydRedirectLastDay = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDREDIRECTLASTDAY), &relaydRedirectIdx, 1, 0,
-	    agentx_redirect)) == NULL ||
-	    (relaydRelayIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDRELAYINDEX), &relaydRelayIdx, 1, 0,
-	    agentx_relay)) == NULL ||
-	    (relaydRelayStatus = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDRELAYSTATUS), &relaydRelayIdx, 1, 0,
-	    agentx_relay)) == NULL ||
-	    (relaydRelayName = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDRELAYNAME), &relaydRelayIdx, 1, 0,
-	    agentx_relay)) == NULL ||
-	    (relaydRelayCnt = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDRELAYCNT), &relaydRelayIdx, 1, 0,
-	    agentx_relay)) == NULL ||
-	    (relaydRelayAvg = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDRELAYAVG), &relaydRelayIdx, 1, 0,
-	    agentx_relay)) == NULL ||
-	    (relaydRelayLast = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDRELAYLAST), &relaydRelayIdx, 1, 0,
-	    agentx_relay)) == NULL ||
-	    (relaydRelayAvgHour = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDRELAYAVGHOUR), &relaydRelayIdx, 1, 0,
-	    agentx_relay)) == NULL ||
-	    (relaydRelayLastHour = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDRELAYLASTHOUR), &relaydRelayIdx, 1, 0,
-	    agentx_relay)) == NULL ||
-	    (relaydRelayAvgDay = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDRELAYAVGDAY), &relaydRelayIdx, 1, 0,
-	    agentx_relay)) == NULL ||
-	    (relaydRelayLastDay = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDRELAYLASTDAY), &relaydRelayIdx, 1, 0,
-	    agentx_relay)) == NULL ||
-	    (relaydRouterIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDROUTERINDEX), &relaydRouterIdx, 1, 0,
-	    agentx_router)) == NULL ||
-	    (relaydRouterTableIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDROUTERTABLEINDEX), &relaydRouterIdx, 1, 0,
-	    agentx_router)) == NULL ||
-	    (relaydRouterStatus = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDROUTERSTATUS), &relaydRouterIdx, 1, 0,
-	    agentx_router)) == NULL ||
-	    (relaydRouterName = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDROUTERNAME), &relaydRouterIdx, 1, 0,
-	    agentx_router)) == NULL ||
-	    (relaydRouterLabel = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDROUTERLABEL), &relaydRouterIdx, 1, 0,
-	    agentx_router)) == NULL ||
-	    (relaydRouterRtable = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDROUTERRTABLE), &relaydRouterIdx, 1, 0,
-	    agentx_router)) == NULL ||
-	    (relaydNetRouteIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDNETROUTEINDEX), &relaydNetRouteIdx, 1, 0,
-	    agentx_netroute)) == NULL ||
-	    (relaydNetRouteAddr = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDNETROUTEADDR), &relaydNetRouteIdx, 1, 0,
-	    agentx_netroute)) == NULL ||
-	    (relaydNetRouteAddrType = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDNETROUTEADDRTYPE), &relaydNetRouteIdx, 1, 0,
-	    agentx_netroute)) == NULL ||
-	    (relaydNetRoutePrefixLen = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDNETROUTEPREFIXLEN), &relaydNetRouteIdx, 1, 0,
-	    agentx_netroute)) == NULL ||
-	    (relaydNetRouteRouterIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDNETROUTEROUTERINDEX), &relaydNetRouteIdx, 1, 0,
-	    agentx_netroute)) == NULL ||
-	    (relaydHostIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDHOSTINDEX), &relaydHostIdx, 1, 0,
-	    agentx_host)) == NULL ||
-	    (relaydHostParentIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDHOSTPARENTINDEX), &relaydHostIdx, 1, 0,
-	    agentx_host)) == NULL ||
-	    (relaydHostTableIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDHOSTTABLEINDEX), &relaydHostIdx, 1, 0,
-	    agentx_host)) == NULL ||
-	    (relaydHostName = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDHOSTNAME), &relaydHostIdx, 1, 0,
-	    agentx_host)) == NULL ||
-	    (relaydHostAddress = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDHOSTADDRESS), &relaydHostIdx, 1, 0,
-	    agentx_host)) == NULL ||
-	    (relaydHostAddressType = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDHOSTADDRESSTYPE), &relaydHostIdx, 1, 0,
-	    agentx_host)) == NULL ||
-	    (relaydHostStatus = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDHOSTSTATUS), &relaydHostIdx, 1, 0,
-	    agentx_host)) == NULL ||
-	    (relaydHostCheckCnt = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDHOSTCHECKCNT), &relaydHostIdx, 1, 0,
-	    agentx_host)) == NULL ||
-	    (relaydHostUpCnt = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDHOSTUPCNT), &relaydHostIdx, 1, 0,
-	    agentx_host)) == NULL ||
-	    (relaydHostErrno = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDHOSTERRNO), &relaydHostIdx, 1, 0,
-	    agentx_host)) == NULL ||
-	    (relaydSessionIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONINDEX), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionRelayIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONRELAYINDEX), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionInAddr = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONINADDR), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionInAddrType = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONINADDRTYPE), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionOutAddr = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONOUTADDR), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionOutAddrType = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONOUTADDRTYPE), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionPortIn = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONPORTIN), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionPortOut = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONPORTOUT), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionAge = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONAGE), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionIdle = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONIDLE), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionStatus = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONSTATUS), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydSessionPid = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDSESSIONPID), session_idxs, 2, 0,
-	    agentx_session)) == NULL ||
-	    (relaydTableIndex = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDTABLEINDEX), &relaydTableIdx, 1, 0,
-	    agentx_table)) == NULL ||
-	    (relaydTableName = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDTABLENAME), &relaydTableIdx, 1, 0,
-	    agentx_table)) == NULL ||
-	    (relaydTableStatus = subagentx_object(sar,
-	    SUBAGENTX_OID(RELAYDTABLESTATUS), &relaydTableIdx, 1, 0,
-	    agentx_table)) == NULL)
+	if ((relaydRedirectIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDREDIRECTINDEX), &relaydRedirectIdx, 1, 0,
+	    agentxctl_redirect)) == NULL ||
+	    (relaydRedirectStatus = agentx_object(sar,
+	    AGENTX_OID(RELAYDREDIRECTSTATUS), &relaydRedirectIdx, 1, 0,
+	    agentxctl_redirect)) == NULL ||
+	    (relaydRedirectName = agentx_object(sar,
+	    AGENTX_OID(RELAYDREDIRECTNAME), &relaydRedirectIdx, 1, 0,
+	    agentxctl_redirect)) == NULL ||
+	    (relaydRedirectCnt = agentx_object(sar,
+	    AGENTX_OID(RELAYDREDIRECTCNT), &relaydRedirectIdx, 1, 0,
+	    agentxctl_redirect)) == NULL ||
+	    (relaydRedirectAvg = agentx_object(sar,
+	    AGENTX_OID(RELAYDREDIRECTAVG), &relaydRedirectIdx, 1, 0,
+	    agentxctl_redirect)) == NULL ||
+	    (relaydRedirectLast = agentx_object(sar,
+	    AGENTX_OID(RELAYDREDIRECTLAST), &relaydRedirectIdx, 1, 0,
+	    agentxctl_redirect)) == NULL ||
+	    (relaydRedirectAvgHour = agentx_object(sar,
+	    AGENTX_OID(RELAYDREDIRECTAVGHOUR), &relaydRedirectIdx, 1, 0,
+	    agentxctl_redirect)) == NULL ||
+	    (relaydRedirectLastHour = agentx_object(sar,
+	    AGENTX_OID(RELAYDREDIRECTLASTHOUR), &relaydRedirectIdx, 1, 0,
+	    agentxctl_redirect)) == NULL ||
+	    (relaydRedirectAvgDay = agentx_object(sar,
+	    AGENTX_OID(RELAYDREDIRECTAVGDAY), &relaydRedirectIdx, 1, 0,
+	    agentxctl_redirect)) == NULL ||
+	    (relaydRedirectLastDay = agentx_object(sar,
+	    AGENTX_OID(RELAYDREDIRECTLASTDAY), &relaydRedirectIdx, 1, 0,
+	    agentxctl_redirect)) == NULL ||
+	    (relaydRelayIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDRELAYINDEX), &relaydRelayIdx, 1, 0,
+	    agentxctl_relay)) == NULL ||
+	    (relaydRelayStatus = agentx_object(sar,
+	    AGENTX_OID(RELAYDRELAYSTATUS), &relaydRelayIdx, 1, 0,
+	    agentxctl_relay)) == NULL ||
+	    (relaydRelayName = agentx_object(sar,
+	    AGENTX_OID(RELAYDRELAYNAME), &relaydRelayIdx, 1, 0,
+	    agentxctl_relay)) == NULL ||
+	    (relaydRelayCnt = agentx_object(sar,
+	    AGENTX_OID(RELAYDRELAYCNT), &relaydRelayIdx, 1, 0,
+	    agentxctl_relay)) == NULL ||
+	    (relaydRelayAvg = agentx_object(sar,
+	    AGENTX_OID(RELAYDRELAYAVG), &relaydRelayIdx, 1, 0,
+	    agentxctl_relay)) == NULL ||
+	    (relaydRelayLast = agentx_object(sar,
+	    AGENTX_OID(RELAYDRELAYLAST), &relaydRelayIdx, 1, 0,
+	    agentxctl_relay)) == NULL ||
+	    (relaydRelayAvgHour = agentx_object(sar,
+	    AGENTX_OID(RELAYDRELAYAVGHOUR), &relaydRelayIdx, 1, 0,
+	    agentxctl_relay)) == NULL ||
+	    (relaydRelayLastHour = agentx_object(sar,
+	    AGENTX_OID(RELAYDRELAYLASTHOUR), &relaydRelayIdx, 1, 0,
+	    agentxctl_relay)) == NULL ||
+	    (relaydRelayAvgDay = agentx_object(sar,
+	    AGENTX_OID(RELAYDRELAYAVGDAY), &relaydRelayIdx, 1, 0,
+	    agentxctl_relay)) == NULL ||
+	    (relaydRelayLastDay = agentx_object(sar,
+	    AGENTX_OID(RELAYDRELAYLASTDAY), &relaydRelayIdx, 1, 0,
+	    agentxctl_relay)) == NULL ||
+	    (relaydRouterIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDROUTERINDEX), &relaydRouterIdx, 1, 0,
+	    agentxctl_router)) == NULL ||
+	    (relaydRouterTableIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDROUTERTABLEINDEX), &relaydRouterIdx, 1, 0,
+	    agentxctl_router)) == NULL ||
+	    (relaydRouterStatus = agentx_object(sar,
+	    AGENTX_OID(RELAYDROUTERSTATUS), &relaydRouterIdx, 1, 0,
+	    agentxctl_router)) == NULL ||
+	    (relaydRouterName = agentx_object(sar,
+	    AGENTX_OID(RELAYDROUTERNAME), &relaydRouterIdx, 1, 0,
+	    agentxctl_router)) == NULL ||
+	    (relaydRouterLabel = agentx_object(sar,
+	    AGENTX_OID(RELAYDROUTERLABEL), &relaydRouterIdx, 1, 0,
+	    agentxctl_router)) == NULL ||
+	    (relaydRouterRtable = agentx_object(sar,
+	    AGENTX_OID(RELAYDROUTERRTABLE), &relaydRouterIdx, 1, 0,
+	    agentxctl_router)) == NULL ||
+	    (relaydNetRouteIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDNETROUTEINDEX), &relaydNetRouteIdx, 1, 0,
+	    agentxctl_netroute)) == NULL ||
+	    (relaydNetRouteAddr = agentx_object(sar,
+	    AGENTX_OID(RELAYDNETROUTEADDR), &relaydNetRouteIdx, 1, 0,
+	    agentxctl_netroute)) == NULL ||
+	    (relaydNetRouteAddrType = agentx_object(sar,
+	    AGENTX_OID(RELAYDNETROUTEADDRTYPE), &relaydNetRouteIdx, 1, 0,
+	    agentxctl_netroute)) == NULL ||
+	    (relaydNetRoutePrefixLen = agentx_object(sar,
+	    AGENTX_OID(RELAYDNETROUTEPREFIXLEN), &relaydNetRouteIdx, 1, 0,
+	    agentxctl_netroute)) == NULL ||
+	    (relaydNetRouteRouterIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDNETROUTEROUTERINDEX), &relaydNetRouteIdx, 1, 0,
+	    agentxctl_netroute)) == NULL ||
+	    (relaydHostIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDHOSTINDEX), &relaydHostIdx, 1, 0,
+	    agentxctl_host)) == NULL ||
+	    (relaydHostParentIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDHOSTPARENTINDEX), &relaydHostIdx, 1, 0,
+	    agentxctl_host)) == NULL ||
+	    (relaydHostTableIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDHOSTTABLEINDEX), &relaydHostIdx, 1, 0,
+	    agentxctl_host)) == NULL ||
+	    (relaydHostName = agentx_object(sar,
+	    AGENTX_OID(RELAYDHOSTNAME), &relaydHostIdx, 1, 0,
+	    agentxctl_host)) == NULL ||
+	    (relaydHostAddress = agentx_object(sar,
+	    AGENTX_OID(RELAYDHOSTADDRESS), &relaydHostIdx, 1, 0,
+	    agentxctl_host)) == NULL ||
+	    (relaydHostAddressType = agentx_object(sar,
+	    AGENTX_OID(RELAYDHOSTADDRESSTYPE), &relaydHostIdx, 1, 0,
+	    agentxctl_host)) == NULL ||
+	    (relaydHostStatus = agentx_object(sar,
+	    AGENTX_OID(RELAYDHOSTSTATUS), &relaydHostIdx, 1, 0,
+	    agentxctl_host)) == NULL ||
+	    (relaydHostCheckCnt = agentx_object(sar,
+	    AGENTX_OID(RELAYDHOSTCHECKCNT), &relaydHostIdx, 1, 0,
+	    agentxctl_host)) == NULL ||
+	    (relaydHostUpCnt = agentx_object(sar,
+	    AGENTX_OID(RELAYDHOSTUPCNT), &relaydHostIdx, 1, 0,
+	    agentxctl_host)) == NULL ||
+	    (relaydHostErrno = agentx_object(sar,
+	    AGENTX_OID(RELAYDHOSTERRNO), &relaydHostIdx, 1, 0,
+	    agentxctl_host)) == NULL ||
+	    (relaydSessionIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONINDEX), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionRelayIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONRELAYINDEX), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionInAddr = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONINADDR), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionInAddrType = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONINADDRTYPE), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionOutAddr = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONOUTADDR), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionOutAddrType = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONOUTADDRTYPE), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionPortIn = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONPORTIN), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionPortOut = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONPORTOUT), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionAge = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONAGE), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionIdle = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONIDLE), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionStatus = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONSTATUS), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydSessionPid = agentx_object(sar,
+	    AGENTX_OID(RELAYDSESSIONPID), session_idxs, 2, 0,
+	    agentxctl_session)) == NULL ||
+	    (relaydTableIndex = agentx_object(sar,
+	    AGENTX_OID(RELAYDTABLEINDEX), &relaydTableIdx, 1, 0,
+	    agentxctl_table)) == NULL ||
+	    (relaydTableName = agentx_object(sar,
+	    AGENTX_OID(RELAYDTABLENAME), &relaydTableIdx, 1, 0,
+	    agentxctl_table)) == NULL ||
+	    (relaydTableStatus = agentx_object(sar,
+	    AGENTX_OID(RELAYDTABLESTATUS), &relaydTableIdx, 1, 0,
+	    agentxctl_table)) == NULL)
 		fatal("%s: agentx object alloc", __func__);
 }
 
 void
-agentx_needsock(struct subagentx *usa, void *cookie, int fd)
+agentx_needsock(struct agentx *usa, void *cookie, int fd)
 {
 	proc_compose(env->sc_ps, PROC_PARENT, IMSG_AGENTXSOCK, NULL, 0);
 }
@@ -461,7 +461,7 @@ agentx_getsock(struct imsg *imsg)
 	    agentx_sock, env);
 	event_add(&(env->sc_agentxev), NULL);
 
-	subagentx_connect(sa, imsg->fd);
+	agentx_connect(sa, imsg->fd);
 
 	return 0;
  retry:
@@ -482,10 +482,10 @@ agentx_sock(int fd, short event, void *arg)
 		event_set(&(env->sc_agentxev), fd, EV_READ | EV_PERSIST,
 		    agentx_sock, NULL);
 		event_add(&(env->sc_agentxev), NULL);
-		subagentx_write(sa);
+		agentx_write(sa);
 	}
 	if (event & EV_READ)
-		subagentx_read(sa);
+		agentx_read(sa);
 	return;
 }
 
@@ -510,19 +510,19 @@ sstolen(struct sockaddr_storage *ss)
 }
 
 struct rdr *
-agentx_rdr_byidx(uint32_t instanceidx, enum subagentx_request_type type)
+agentxctl_rdr_byidx(uint32_t instanceidx, enum agentx_request_type type)
 {
 	struct rdr	*rdr;
 
 	TAILQ_FOREACH(rdr, env->sc_rdrs, entry) {
 		if (rdr->conf.id == instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET ||
-			    type == SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
+			if (type == AGENTX_REQUEST_TYPE_GET ||
+			    type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
 				return rdr;
 			else
 				return TAILQ_NEXT(rdr, entry);
 		} else if (rdr->conf.id > instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET)
+			if (type == AGENTX_REQUEST_TYPE_GET)
 				return NULL;
 			return rdr;
 		}
@@ -533,61 +533,61 @@ agentx_rdr_byidx(uint32_t instanceidx, enum subagentx_
 
 
 void
-agentx_redirect(struct subagentx_varbind *sav)
+agentxctl_redirect(struct agentx_varbind *sav)
 {
 	struct rdr	*rdr;
 
-	rdr = agentx_rdr_byidx(subagentx_varbind_get_index_integer(sav,
-	    relaydRedirectIdx), subagentx_varbind_request(sav));
+	rdr = agentxctl_rdr_byidx(agentx_varbind_get_index_integer(sav,
+	    relaydRedirectIdx), agentx_varbind_request(sav));
 	if (rdr == NULL) {
-		subagentx_varbind_notfound(sav);
+		agentx_varbind_notfound(sav);
 		return;
 	}
-	subagentx_varbind_set_index_integer(sav, relaydRedirectIdx,
+	agentx_varbind_set_index_integer(sav, relaydRedirectIdx,
 	    rdr->conf.id);
-	if (subagentx_varbind_get_object(sav) == relaydRedirectIndex)
-		subagentx_varbind_integer(sav, rdr->conf.id);
-	else if (subagentx_varbind_get_object(sav) == relaydRedirectStatus) {
+	if (agentx_varbind_get_object(sav) == relaydRedirectIndex)
+		agentx_varbind_integer(sav, rdr->conf.id);
+	else if (agentx_varbind_get_object(sav) == relaydRedirectStatus) {
 		if (rdr->conf.flags & F_DISABLE)
-			subagentx_varbind_integer(sav, 1);
+			agentx_varbind_integer(sav, 1);
 		else if (rdr->conf.flags & F_DOWN)
-			subagentx_varbind_integer(sav, 2);
+			agentx_varbind_integer(sav, 2);
 		else if (rdr->conf.flags & F_BACKUP)
-			subagentx_varbind_integer(sav, 3);
+			agentx_varbind_integer(sav, 3);
 		else
-			subagentx_varbind_integer(sav, 0);
-	} else if (subagentx_varbind_get_object(sav) == relaydRedirectName)
-		subagentx_varbind_string(sav, rdr->conf.name);
-	else if (subagentx_varbind_get_object(sav) == relaydRedirectCnt)
-		subagentx_varbind_counter64(sav, rdr->stats.cnt);
-	else if (subagentx_varbind_get_object(sav) == relaydRedirectAvg)
-		subagentx_varbind_gauge32(sav, rdr->stats.avg);
-	else if (subagentx_varbind_get_object(sav) == relaydRedirectLast)
-		subagentx_varbind_gauge32(sav, rdr->stats.last);
-	else if (subagentx_varbind_get_object(sav) == relaydRedirectAvgHour)
-		subagentx_varbind_gauge32(sav, rdr->stats.avg_hour);
-	else if (subagentx_varbind_get_object(sav) == relaydRedirectLastHour)
-		subagentx_varbind_gauge32(sav, rdr->stats.last_hour);
-	else if (subagentx_varbind_get_object(sav) == relaydRedirectAvgDay)
-		subagentx_varbind_gauge32(sav, rdr->stats.avg_day);
-	else if (subagentx_varbind_get_object(sav) == relaydRedirectLastDay)
-		subagentx_varbind_gauge32(sav, rdr->stats.last_day);
+			agentx_varbind_integer(sav, 0);
+	} else if (agentx_varbind_get_object(sav) == relaydRedirectName)
+		agentx_varbind_string(sav, rdr->conf.name);
+	else if (agentx_varbind_get_object(sav) == relaydRedirectCnt)
+		agentx_varbind_counter64(sav, rdr->stats.cnt);
+	else if (agentx_varbind_get_object(sav) == relaydRedirectAvg)
+		agentx_varbind_gauge32(sav, rdr->stats.avg);
+	else if (agentx_varbind_get_object(sav) == relaydRedirectLast)
+		agentx_varbind_gauge32(sav, rdr->stats.last);
+	else if (agentx_varbind_get_object(sav) == relaydRedirectAvgHour)
+		agentx_varbind_gauge32(sav, rdr->stats.avg_hour);
+	else if (agentx_varbind_get_object(sav) == relaydRedirectLastHour)
+		agentx_varbind_gauge32(sav, rdr->stats.last_hour);
+	else if (agentx_varbind_get_object(sav) == relaydRedirectAvgDay)
+		agentx_varbind_gauge32(sav, rdr->stats.avg_day);
+	else if (agentx_varbind_get_object(sav) == relaydRedirectLastDay)
+		agentx_varbind_gauge32(sav, rdr->stats.last_day);
 }
 
 struct relay *
-agentx_relay_byidx(uint32_t instanceidx, enum subagentx_request_type type)
+agentxctl_relay_byidx(uint32_t instanceidx, enum agentx_request_type type)
 {
 	struct relay	*rly;
 
 	TAILQ_FOREACH(rly, env->sc_relays, rl_entry) {
 		if (rly->rl_conf.id == instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET ||
-			    type == SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
+			if (type == AGENTX_REQUEST_TYPE_GET ||
+			    type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
 				return rly;
 			else
 				return TAILQ_NEXT(rly, rl_entry);
 		} else if (rly->rl_conf.id > instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET)
+			if (type == AGENTX_REQUEST_TYPE_GET)
 				return NULL;
 			return rly;
 		}
@@ -597,74 +597,74 @@ agentx_relay_byidx(uint32_t instanceidx, enum subagent
 }
 
 void
-agentx_relay(struct subagentx_varbind *sav)
+agentxctl_relay(struct agentx_varbind *sav)
 {
 	struct relay	*rly;
 	uint64_t	 value = 0;
 	int		 i, nrelay = env->sc_conf.prefork_relay;
 
-	rly = agentx_relay_byidx(subagentx_varbind_get_index_integer(sav,
-	    relaydRelayIdx), subagentx_varbind_request(sav));
+	rly = agentxctl_relay_byidx(agentx_varbind_get_index_integer(sav,
+	    relaydRelayIdx), agentx_varbind_request(sav));
 	if (rly == NULL) {
-		subagentx_varbind_notfound(sav);
+		agentx_varbind_notfound(sav);
 		return;
 	}
-	subagentx_varbind_set_index_integer(sav, relaydRelayIdx,
+	agentx_varbind_set_index_integer(sav, relaydRelayIdx,
 	    rly->rl_conf.id);
-	if (subagentx_varbind_get_object(sav) == relaydRelayIndex)
-		subagentx_varbind_integer(sav, rly->rl_conf.id);
-	else if (subagentx_varbind_get_object(sav) == relaydRelayStatus) {
+	if (agentx_varbind_get_object(sav) == relaydRelayIndex)
+		agentx_varbind_integer(sav, rly->rl_conf.id);
+	else if (agentx_varbind_get_object(sav) == relaydRelayStatus) {
 		if (rly->rl_up == HOST_UP)
-			subagentx_varbind_integer(sav, 1);
+			agentx_varbind_integer(sav, 1);
 		else
-			subagentx_varbind_integer(sav, 0);
-	} else if (subagentx_varbind_get_object(sav) == relaydRelayName)
-		subagentx_varbind_string(sav, rly->rl_conf.name);
-	else if (subagentx_varbind_get_object(sav) == relaydRelayCnt) {
+			agentx_varbind_integer(sav, 0);
+	} else if (agentx_varbind_get_object(sav) == relaydRelayName)
+		agentx_varbind_string(sav, rly->rl_conf.name);
+	else if (agentx_varbind_get_object(sav) == relaydRelayCnt) {
 		for (i = 0; i < nrelay; i++)
 			value += rly->rl_stats[i].cnt;
-		subagentx_varbind_counter64(sav, value);
-	} else if (subagentx_varbind_get_object(sav) == relaydRelayAvg) {
+		agentx_varbind_counter64(sav, value);
+	} else if (agentx_varbind_get_object(sav) == relaydRelayAvg) {
 		for (i = 0; i < nrelay; i++)
 			value += rly->rl_stats[i].avg;
-		subagentx_varbind_gauge32(sav, (uint32_t)value);
-	} else if (subagentx_varbind_get_object(sav) == relaydRelayLast) {
+		agentx_varbind_gauge32(sav, (uint32_t)value);
+	} else if (agentx_varbind_get_object(sav) == relaydRelayLast) {
 		for (i = 0; i < nrelay; i++)
 			value += rly->rl_stats[i].last;
-		subagentx_varbind_gauge32(sav, (uint32_t)value);
-	} else if (subagentx_varbind_get_object(sav) == relaydRelayAvgHour) {
+		agentx_varbind_gauge32(sav, (uint32_t)value);
+	} else if (agentx_varbind_get_object(sav) == relaydRelayAvgHour) {
 		for (i = 0; i < nrelay; i++)
 			value += rly->rl_stats[i].avg_hour;
-		subagentx_varbind_gauge32(sav, (uint32_t)value);
-	} else if (subagentx_varbind_get_object(sav) == relaydRelayLastHour) {
+		agentx_varbind_gauge32(sav, (uint32_t)value);
+	} else if (agentx_varbind_get_object(sav) == relaydRelayLastHour) {
 		for (i = 0; i < nrelay; i++)
 			value += rly->rl_stats[i].last_hour;
-		subagentx_varbind_gauge32(sav, (uint32_t)value);
-	} else if (subagentx_varbind_get_object(sav) == relaydRelayAvgDay) {
+		agentx_varbind_gauge32(sav, (uint32_t)value);
+	} else if (agentx_varbind_get_object(sav) == relaydRelayAvgDay) {
 		for (i = 0; i < nrelay; i++)
 			value += rly->rl_stats[i].avg_day;
-		subagentx_varbind_gauge32(sav, (uint32_t)value);
-	} else if (subagentx_varbind_get_object(sav) == relaydRelayLastDay) {
+		agentx_varbind_gauge32(sav, (uint32_t)value);
+	} else if (agentx_varbind_get_object(sav) == relaydRelayLastDay) {
 		for (i = 0; i < nrelay; i++)
 			value += rly->rl_stats[i].last_day;
-		subagentx_varbind_gauge32(sav, (uint32_t)value);
+		agentx_varbind_gauge32(sav, (uint32_t)value);
 	}
 }
 
 struct router *
-agentx_router_byidx(uint32_t instanceidx, enum subagentx_request_type type)
+agentxctl_router_byidx(uint32_t instanceidx, enum agentx_request_type type)
 {
 	struct router	*router;
 
 	TAILQ_FOREACH(router, env->sc_rts, rt_entry) {
 		if (router->rt_conf.id == instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET ||
-			    type == SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
+			if (type == AGENTX_REQUEST_TYPE_GET ||
+			    type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
 				return router;
 			else
 				return TAILQ_NEXT(router, rt_entry);
 		} else if (router->rt_conf.id > instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET)
+			if (type == AGENTX_REQUEST_TYPE_GET)
 				return NULL;
 			return router;
 		}
@@ -674,49 +674,49 @@ agentx_router_byidx(uint32_t instanceidx, enum subagen
 }
 
 void
-agentx_router(struct subagentx_varbind *sav)
+agentxctl_router(struct agentx_varbind *sav)
 {
 	struct router	*router;
 
-	router = agentx_router_byidx(subagentx_varbind_get_index_integer(sav,
-	    relaydRouterIdx), subagentx_varbind_request(sav));
+	router = agentxctl_router_byidx(agentx_varbind_get_index_integer(sav,
+	    relaydRouterIdx), agentx_varbind_request(sav));
 	if (router == NULL) {
-		subagentx_varbind_notfound(sav);
+		agentx_varbind_notfound(sav);
 		return;
 	}
-	subagentx_varbind_set_index_integer(sav, relaydRouterIdx,
+	agentx_varbind_set_index_integer(sav, relaydRouterIdx,
 	    router->rt_conf.id);
-	if (subagentx_varbind_get_object(sav) == relaydRouterIndex)
-		subagentx_varbind_integer(sav, router->rt_conf.id);
-	else if (subagentx_varbind_get_object(sav) == relaydRouterTableIndex)
-		subagentx_varbind_integer(sav, router->rt_conf.gwtable);
-	else if (subagentx_varbind_get_object(sav) == relaydRouterStatus) {
+	if (agentx_varbind_get_object(sav) == relaydRouterIndex)
+		agentx_varbind_integer(sav, router->rt_conf.id);
+	else if (agentx_varbind_get_object(sav) == relaydRouterTableIndex)
+		agentx_varbind_integer(sav, router->rt_conf.gwtable);
+	else if (agentx_varbind_get_object(sav) == relaydRouterStatus) {
 		if (router->rt_conf.flags & F_DISABLE)
-			subagentx_varbind_integer(sav, 1);
+			agentx_varbind_integer(sav, 1);
 		else
-			subagentx_varbind_integer(sav, 0);
-	} else if (subagentx_varbind_get_object(sav) == relaydRouterName)
-		subagentx_varbind_string(sav, router->rt_conf.name);
-	else if (subagentx_varbind_get_object(sav) == relaydRouterLabel)
-		subagentx_varbind_string(sav, router->rt_conf.label);
-	else if (subagentx_varbind_get_object(sav) == relaydRouterRtable)
-		subagentx_varbind_integer(sav, router->rt_conf.rtable);
+			agentx_varbind_integer(sav, 0);
+	} else if (agentx_varbind_get_object(sav) == relaydRouterName)
+		agentx_varbind_string(sav, router->rt_conf.name);
+	else if (agentx_varbind_get_object(sav) == relaydRouterLabel)
+		agentx_varbind_string(sav, router->rt_conf.label);
+	else if (agentx_varbind_get_object(sav) == relaydRouterRtable)
+		agentx_varbind_integer(sav, router->rt_conf.rtable);
 }
 
 struct netroute *
-agentx_netroute_byidx(uint32_t instanceidx, enum subagentx_request_type type)
+agentxctl_netroute_byidx(uint32_t instanceidx, enum agentx_request_type type)
 {
 	struct netroute		*nr;
 
 	TAILQ_FOREACH(nr, env->sc_routes, nr_route) {
 		if (nr->nr_conf.id == instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET ||
-			    type == SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
+			if (type == AGENTX_REQUEST_TYPE_GET ||
+			    type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
 				return nr;
 			else
 				return TAILQ_NEXT(nr, nr_entry);
 		} else if (nr->nr_conf.id > instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET)
+			if (type == AGENTX_REQUEST_TYPE_GET)
 				return NULL;
 			return nr;
 		}
@@ -726,48 +726,48 @@ agentx_netroute_byidx(uint32_t instanceidx, enum subag
 }
 
 void
-agentx_netroute(struct subagentx_varbind *sav)
+agentxctl_netroute(struct agentx_varbind *sav)
 {
 	struct netroute	*nr;
 
-	nr = agentx_netroute_byidx(subagentx_varbind_get_index_integer(sav,
-	    relaydNetRouteIdx), subagentx_varbind_request(sav));
+	nr = agentxctl_netroute_byidx(agentx_varbind_get_index_integer(sav,
+	    relaydNetRouteIdx), agentx_varbind_request(sav));
 	if (nr == NULL) {
-		subagentx_varbind_notfound(sav);
+		agentx_varbind_notfound(sav);
 		return;
 	}
-	subagentx_varbind_set_index_integer(sav, relaydNetRouteIdx,
+	agentx_varbind_set_index_integer(sav, relaydNetRouteIdx,
 	    nr->nr_conf.id);
-	if (subagentx_varbind_get_object(sav) == relaydNetRouteIndex)
-		subagentx_varbind_integer(sav, nr->nr_conf.id);
-	else if (subagentx_varbind_get_object(sav) == relaydNetRouteAddr)
-		subagentx_varbind_nstring(sav, sstodata(&nr->nr_conf.ss),
+	if (agentx_varbind_get_object(sav) == relaydNetRouteIndex)
+		agentx_varbind_integer(sav, nr->nr_conf.id);
+	else if (agentx_varbind_get_object(sav) == relaydNetRouteAddr)
+		agentx_varbind_nstring(sav, sstodata(&nr->nr_conf.ss),
 		    sstolen(&nr->nr_conf.ss));
-	else if (subagentx_varbind_get_object(sav) == relaydNetRouteAddrType) {
+	else if (agentx_varbind_get_object(sav) == relaydNetRouteAddrType) {
 		if (nr->nr_conf.ss.ss_family == AF_INET)
-			subagentx_varbind_integer(sav, 1);
+			agentx_varbind_integer(sav, 1);
 		else if (nr->nr_conf.ss.ss_family == AF_INET6)
-			subagentx_varbind_integer(sav, 2);
-	} else if (subagentx_varbind_get_object(sav) == relaydNetRoutePrefixLen)
-		subagentx_varbind_integer(sav, nr->nr_conf.prefixlen);
-	else if (subagentx_varbind_get_object(sav) == relaydNetRouteRouterIndex)
-		subagentx_varbind_integer(sav, nr->nr_conf.routerid);
+			agentx_varbind_integer(sav, 2);
+	} else if (agentx_varbind_get_object(sav) == relaydNetRoutePrefixLen)
+		agentx_varbind_integer(sav, nr->nr_conf.prefixlen);
+	else if (agentx_varbind_get_object(sav) == relaydNetRouteRouterIndex)
+		agentx_varbind_integer(sav, nr->nr_conf.routerid);
 }
 
 struct host *
-agentx_host_byidx(uint32_t instanceidx, enum subagentx_request_type type)
+agentxctl_host_byidx(uint32_t instanceidx, enum agentx_request_type type)
 {
 	struct host		*host;
 
 	TAILQ_FOREACH(host, &(env->sc_hosts), globalentry) {
 		if (host->conf.id == instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET ||
-			    type == SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
+			if (type == AGENTX_REQUEST_TYPE_GET ||
+			    type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
 				return host;
 			else
 				return TAILQ_NEXT(host, globalentry);
 		} else if (host->conf.id > instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET)
+			if (type == AGENTX_REQUEST_TYPE_GET)
 				return NULL;
 			return host;
 		}
@@ -777,49 +777,49 @@ agentx_host_byidx(uint32_t instanceidx, enum subagentx
 }
 
 void
-agentx_host(struct subagentx_varbind *sav)
+agentxctl_host(struct agentx_varbind *sav)
 {
 	struct host	*host;
 
-	host = agentx_host_byidx(subagentx_varbind_get_index_integer(sav,
-	    relaydHostIdx), subagentx_varbind_request(sav));
+	host = agentxctl_host_byidx(agentx_varbind_get_index_integer(sav,
+	    relaydHostIdx), agentx_varbind_request(sav));
 	if (host == NULL) {
-		subagentx_varbind_notfound(sav);
+		agentx_varbind_notfound(sav);
 		return;
 	}
-	subagentx_varbind_set_index_integer(sav, relaydHostIdx,
+	agentx_varbind_set_index_integer(sav, relaydHostIdx,
 	    host->conf.id);
-	if (subagentx_varbind_get_object(sav) == relaydHostIndex)
-		subagentx_varbind_integer(sav, host->conf.id);
-	else if (subagentx_varbind_get_object(sav) == relaydHostParentIndex)
-		subagentx_varbind_integer(sav, host->conf.parentid);
-	else if (subagentx_varbind_get_object(sav) == relaydHostTableIndex)
-		subagentx_varbind_integer(sav, host->conf.tableid);
-	else if (subagentx_varbind_get_object(sav) == relaydHostName)
-		subagentx_varbind_string(sav, host->conf.name);
-	else if (subagentx_varbind_get_object(sav) == relaydHostAddress)
-		subagentx_varbind_nstring(sav, sstodata(&host->conf.ss),
+	if (agentx_varbind_get_object(sav) == relaydHostIndex)
+		agentx_varbind_integer(sav, host->conf.id);
+	else if (agentx_varbind_get_object(sav) == relaydHostParentIndex)
+		agentx_varbind_integer(sav, host->conf.parentid);
+	else if (agentx_varbind_get_object(sav) == relaydHostTableIndex)
+		agentx_varbind_integer(sav, host->conf.tableid);
+	else if (agentx_varbind_get_object(sav) == relaydHostName)
+		agentx_varbind_string(sav, host->conf.name);
+	else if (agentx_varbind_get_object(sav) == relaydHostAddress)
+		agentx_varbind_nstring(sav, sstodata(&host->conf.ss),
 		    sstolen(&host->conf.ss));
-	else if (subagentx_varbind_get_object(sav) == relaydHostAddressType) {
+	else if (agentx_varbind_get_object(sav) == relaydHostAddressType) {
 		if (host->conf.ss.ss_family == AF_INET)
-			subagentx_varbind_integer(sav, 1);
+			agentx_varbind_integer(sav, 1);
 		else if (host->conf.ss.ss_family == AF_INET6)
-			subagentx_varbind_integer(sav, 2);
-	} else if (subagentx_varbind_get_object(sav) == relaydHostStatus) {
+			agentx_varbind_integer(sav, 2);
+	} else if (agentx_varbind_get_object(sav) == relaydHostStatus) {
 		if (host->flags & F_DISABLE)
-			subagentx_varbind_integer(sav, 1);
+			agentx_varbind_integer(sav, 1);
 		else if (host->up == HOST_UP)
-			subagentx_varbind_integer(sav, 0);
+			agentx_varbind_integer(sav, 0);
 		else if (host->up == HOST_DOWN)
-			subagentx_varbind_integer(sav, 2);
+			agentx_varbind_integer(sav, 2);
 		else
-			subagentx_varbind_integer(sav, 3);
-	} else if (subagentx_varbind_get_object(sav) == relaydHostCheckCnt)
-		subagentx_varbind_counter64(sav, host->check_cnt);
-	else if (subagentx_varbind_get_object(sav) == relaydHostUpCnt)
-		subagentx_varbind_counter64(sav, host->up_cnt);
-	else if (subagentx_varbind_get_object(sav) == relaydHostErrno)
-		subagentx_varbind_integer(sav, host->he);
+			agentx_varbind_integer(sav, 3);
+	} else if (agentx_varbind_get_object(sav) == relaydHostCheckCnt)
+		agentx_varbind_counter64(sav, host->check_cnt);
+	else if (agentx_varbind_get_object(sav) == relaydHostUpCnt)
+		agentx_varbind_counter64(sav, host->up_cnt);
+	else if (agentx_varbind_get_object(sav) == relaydHostErrno)
+		agentx_varbind_integer(sav, host->he);
 }
 
 /*
@@ -828,19 +828,19 @@ agentx_host(struct subagentx_varbind *sav)
  * is shown here
  */
 struct rsession *
-agentx_session_byidx(uint32_t sessidx, uint32_t relayidx,
-    enum subagentx_request_type type)
+agentxctl_session_byidx(uint32_t sessidx, uint32_t relayidx,
+    enum agentx_request_type type)
 {
 	struct rsession		*session;
 
 	TAILQ_FOREACH(session, &(env->sc_sessions), se_entry) {
 		if (session->se_id == sessidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET) {
+			if (type == AGENTX_REQUEST_TYPE_GET) {
 				if (relayidx != session->se_relayid)
 					return NULL;
 				return session;
 			}
-			if (type == SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) {
+			if (type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) {
 				if (relayidx <= session->se_relayid)
 					return session;
 				return TAILQ_NEXT(session, se_entry);
@@ -849,7 +849,7 @@ agentx_session_byidx(uint32_t sessidx, uint32_t relayi
 				return session;
 			return TAILQ_NEXT(session, se_entry);
 		} else if (session->se_id > sessidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET)
+			if (type == AGENTX_REQUEST_TYPE_GET)
 				return NULL;
 			return session;
 		}
@@ -859,82 +859,82 @@ agentx_session_byidx(uint32_t sessidx, uint32_t relayi
 }
 
 void
-agentx_session(struct subagentx_varbind *sav)
+agentxctl_session(struct agentx_varbind *sav)
 {
 	struct timeval	 tv, now;
 	struct rsession	*session;
 
-	session = agentx_session_byidx(subagentx_varbind_get_index_integer(sav,
-	    relaydSessionIdx), subagentx_varbind_get_index_integer(sav,
-	    relaydSessionRelayIdx), subagentx_varbind_request(sav));
+	session = agentxctl_session_byidx(agentx_varbind_get_index_integer(sav,
+	    relaydSessionIdx), agentx_varbind_get_index_integer(sav,
+	    relaydSessionRelayIdx), agentx_varbind_request(sav));
 	if (session == NULL) {
-		subagentx_varbind_notfound(sav);
+		agentx_varbind_notfound(sav);
 		return;
 	}
 
-	subagentx_varbind_set_index_integer(sav, relaydSessionIdx,
+	agentx_varbind_set_index_integer(sav, relaydSessionIdx,
 	    session->se_id);
-	subagentx_varbind_set_index_integer(sav, relaydSessionRelayIdx,
+	agentx_varbind_set_index_integer(sav, relaydSessionRelayIdx,
 	    session->se_relayid);
-	if (subagentx_varbind_get_object(sav) == relaydSessionIndex)
-		subagentx_varbind_integer(sav, session->se_id);
-	else if (subagentx_varbind_get_object(sav) == relaydSessionRelayIndex)
-		subagentx_varbind_integer(sav, session->se_relayid);
-	else if (subagentx_varbind_get_object(sav) == relaydSessionInAddr)
-		subagentx_varbind_nstring(sav, sstodata(&(session->se_in.ss)),
+	if (agentx_varbind_get_object(sav) == relaydSessionIndex)
+		agentx_varbind_integer(sav, session->se_id);
+	else if (agentx_varbind_get_object(sav) == relaydSessionRelayIndex)
+		agentx_varbind_integer(sav, session->se_relayid);
+	else if (agentx_varbind_get_object(sav) == relaydSessionInAddr)
+		agentx_varbind_nstring(sav, sstodata(&(session->se_in.ss)),
 		    sstolen(&(session->se_in.ss)));
-	else if (subagentx_varbind_get_object(sav) == relaydSessionInAddrType) {
+	else if (agentx_varbind_get_object(sav) == relaydSessionInAddrType) {
 		if (session->se_in.ss.ss_family == AF_INET)
-			subagentx_varbind_integer(sav, 1);
+			agentx_varbind_integer(sav, 1);
 		else if (session->se_in.ss.ss_family == AF_INET6)
-			subagentx_varbind_integer(sav, 2);
-	} else if (subagentx_varbind_get_object(sav) == relaydSessionOutAddr)
-		subagentx_varbind_nstring(sav, sstodata(&(session->se_out.ss)),
+			agentx_varbind_integer(sav, 2);
+	} else if (agentx_varbind_get_object(sav) == relaydSessionOutAddr)
+		agentx_varbind_nstring(sav, sstodata(&(session->se_out.ss)),
 		    sstolen(&(session->se_out.ss)));
-	else if (subagentx_varbind_get_object(sav) == relaydSessionOutAddrType) {
+	else if (agentx_varbind_get_object(sav) == relaydSessionOutAddrType) {
 		if (session->se_out.ss.ss_family == AF_INET)
-			subagentx_varbind_integer(sav, 1);
+			agentx_varbind_integer(sav, 1);
 		else if (session->se_out.ss.ss_family == AF_INET6)
-			subagentx_varbind_integer(sav, 2);
+			agentx_varbind_integer(sav, 2);
 		else
-			subagentx_varbind_integer(sav, 0);
-	} else if (subagentx_varbind_get_object(sav) == relaydSessionPortIn)
-		subagentx_varbind_integer(sav, session->se_in.port);
-	else if (subagentx_varbind_get_object(sav) == relaydSessionPortOut)
-		subagentx_varbind_integer(sav, session->se_out.port);
-	else if (subagentx_varbind_get_object(sav) == relaydSessionAge) {
+			agentx_varbind_integer(sav, 0);
+	} else if (agentx_varbind_get_object(sav) == relaydSessionPortIn)
+		agentx_varbind_integer(sav, session->se_in.port);
+	else if (agentx_varbind_get_object(sav) == relaydSessionPortOut)
+		agentx_varbind_integer(sav, session->se_out.port);
+	else if (agentx_varbind_get_object(sav) == relaydSessionAge) {
 		getmonotime(&now);
 		timersub(&now, &session->se_tv_start, &tv);
-		subagentx_varbind_timeticks(sav,
+		agentx_varbind_timeticks(sav,
 		    tv.tv_sec * 100 + tv.tv_usec / 10000);
-	} else if (subagentx_varbind_get_object(sav) == relaydSessionIdle) {
+	} else if (agentx_varbind_get_object(sav) == relaydSessionIdle) {
 		getmonotime(&now);
 		timersub(&now, &session->se_tv_last, &tv);
-		subagentx_varbind_timeticks(sav,
+		agentx_varbind_timeticks(sav,
 		    tv.tv_sec * 100 + tv.tv_usec / 10000);
-	} else if (subagentx_varbind_get_object(sav) == relaydSessionStatus) {
+	} else if (agentx_varbind_get_object(sav) == relaydSessionStatus) {
 		if (session->se_done)
-			subagentx_varbind_integer(sav, 1);
+			agentx_varbind_integer(sav, 1);
 		else
-			subagentx_varbind_integer(sav, 0);
-	} else if (subagentx_varbind_get_object(sav) == relaydSessionPid)
-		subagentx_varbind_integer(sav, session->se_pid);
+			agentx_varbind_integer(sav, 0);
+	} else if (agentx_varbind_get_object(sav) == relaydSessionPid)
+		agentx_varbind_integer(sav, session->se_pid);
 }
 
 struct table *
-agentx_table_byidx(uint32_t instanceidx, enum subagentx_request_type type)
+agentxctl_table_byidx(uint32_t instanceidx, enum agentx_request_type type)
 {
 	struct table		*table;
 
 	TAILQ_FOREACH(table, env->sc_tables, entry) {
 		if (table->conf.id == instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET ||
-			    type == SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
+			if (type == AGENTX_REQUEST_TYPE_GET ||
+			    type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
 				return table;
 			else
 				return TAILQ_NEXT(table, entry);
 		} else if (table->conf.id > instanceidx) {
-			if (type == SUBAGENTX_REQUEST_TYPE_GET)
+			if (type == AGENTX_REQUEST_TYPE_GET)
 				return NULL;
 			return table;
 		}
@@ -944,29 +944,29 @@ agentx_table_byidx(uint32_t instanceidx, enum subagent
 }
 
 void
-agentx_table(struct subagentx_varbind *sav)
+agentxctl_table(struct agentx_varbind *sav)
 {
 	struct table	*table;
 
-	table = agentx_table_byidx(subagentx_varbind_get_index_integer(sav,
-	    relaydTableIdx), subagentx_varbind_request(sav));
+	table = agentxctl_table_byidx(agentx_varbind_get_index_integer(sav,
+	    relaydTableIdx), agentx_varbind_request(sav));
 	if (table == NULL) {
-		subagentx_varbind_notfound(sav);
+		agentx_varbind_notfound(sav);
 		return;
 	}
-	subagentx_varbind_set_index_integer(sav, relaydTableIdx,
+	agentx_varbind_set_index_integer(sav, relaydTableIdx,
 	    table->conf.id);
-	if (subagentx_varbind_get_object(sav) == relaydTableIndex)
-		subagentx_varbind_integer(sav, table->conf.id);
-	else if (subagentx_varbind_get_object(sav) == relaydTableName)
-		subagentx_varbind_string(sav, table->conf.name);
-	else if (subagentx_varbind_get_object(sav) == relaydTableStatus) {
+	if (agentx_varbind_get_object(sav) == relaydTableIndex)
+		agentx_varbind_integer(sav, table->conf.id);
+	else if (agentx_varbind_get_object(sav) == relaydTableName)
+		agentx_varbind_string(sav, table->conf.name);
+	else if (agentx_varbind_get_object(sav) == relaydTableStatus) {
 		if (TAILQ_EMPTY(&table->hosts))
-			subagentx_varbind_integer(sav, 1);
+			agentx_varbind_integer(sav, 1);
 		else if (table->conf.flags & F_DISABLE)
-			subagentx_varbind_integer(sav, 2);
+			agentx_varbind_integer(sav, 2);
 		else
-			subagentx_varbind_integer(sav, 0);
+			agentx_varbind_integer(sav, 0);
 	}
 
 }
blob - 0b75d4781cc2d75985b6a91a9a74a95b57d1bbe1
blob + 4dde64f225255d828062bf6a3a23364a290e8d9e
--- parse.y
+++ parse.y
@@ -1,4 +1,4 @@
-/*	$OpenBSD: parse.y,v 1.247 2020/10/25 10:17:49 denis Exp $	*/
+/*	$OpenBSD: parse.y,v 1.248 2020/10/26 16:52:06 martijn Exp $	*/
 
 /*
  * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -39,6 +39,7 @@
 #include <net/pfvar.h>
 #include <net/route.h>
 
+#include <agentx.h>
 #include <stdint.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -56,7 +57,6 @@
 
 #include "relayd.h"
 #include "http.h"
-#include "subagentx.h"
 
 TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
 static struct file {
@@ -454,7 +454,7 @@ main		: INTERVAL NUMBER	{
 				free($3);
 			} else
 				(void)strlcpy(conf->sc_conf.agentx_path,
-				    SUBAGENTX_AGENTX_MASTER,
+				    AGENTX_MASTER_PATH,
 				    sizeof(conf->sc_conf.agentx_path));
 		}
 		| SNMP trap optstring	{
blob - 4d34b28304dbf0a814f9b60bd8ace3ba85d85126 (mode 644)
blob + /dev/null
--- subagentx.c
+++ /dev/null
@@ -1,4003 +0,0 @@
-/*
- * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <netinet/in.h>
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "subagentx_internal.h"
-#include "subagentx.h"
-
-enum subagentx_index_type {
-	SAI_TYPE_NEW,
-	SAI_TYPE_ANY,
-	SAI_TYPE_VALUE,
-	SAI_TYPE_DYNAMIC
-};
-
-#define SUBAGENTX_CONTEXT_CTX(sac) (sac->sac_name_default ? NULL : \
-    &(sac->sac_name))
-
-struct subagentx_agentcaps {
-	struct subagentx_context *saa_sac;
-	struct agentx_oid saa_oid;
-	struct agentx_ostring saa_descr;
-	enum subagentx_cstate saa_cstate;
-	enum subagentx_dstate saa_dstate;
-	TAILQ_ENTRY(subagentx_agentcaps) saa_sac_agentcaps;
-};
-
-struct subagentx_region {
-	struct subagentx_context *sar_sac;
-	struct agentx_oid sar_oid;
-	uint8_t sar_timeout;
-	uint8_t sar_priority;
-	enum subagentx_cstate sar_cstate;
-	enum subagentx_dstate sar_dstate;
-	TAILQ_HEAD(, subagentx_index) sar_indices;
-	TAILQ_HEAD(, subagentx_object) sar_objects;
-	TAILQ_ENTRY(subagentx_region) sar_sac_regions;
-};
-
-struct subagentx_index {
-	struct subagentx_region *sai_sar;
-	enum subagentx_index_type sai_type;
-	struct agentx_varbind sai_vb;
-	struct subagentx_object **sai_object;
-	size_t sai_objectlen;
-	size_t sai_objectsize;
-	enum subagentx_cstate sai_cstate;
-	enum subagentx_dstate sai_dstate;
-	TAILQ_ENTRY(subagentx_index) sai_sar_indices;
-};
-
-struct subagentx_object {
-	struct subagentx_region *sao_sar;
-	struct agentx_oid sao_oid;
-	struct subagentx_index *sao_index[SUBAGENTX_OID_INDEX_MAX_LEN];
-	size_t sao_indexlen;
-	int sao_implied;
-	uint8_t sao_timeout;
-	/* Prevent freeing object while in use by get and set requesets */
-	uint32_t sao_lock;
-	void (*sao_get)(struct subagentx_varbind *);
-	enum subagentx_cstate sao_cstate;
-	enum subagentx_dstate sao_dstate;
-	RB_ENTRY(subagentx_object) sao_sac_objects;
-	TAILQ_ENTRY(subagentx_object) sao_sar_objects;
-};
-
-struct subagentx_varbind {
-	struct subagentx_get *sav_sag;
-	struct subagentx_object *sav_sao;
-	struct subagentx_varbind_index {
-		struct subagentx_index *sav_sai;
-		union agentx_data sav_idata;
-		uint8_t sav_idatacomplete;
-	} sav_index[SUBAGENTX_OID_INDEX_MAX_LEN];
-	size_t sav_indexlen;
-	int sav_initialized;
-	int sav_include;
-	struct agentx_varbind sav_vb;
-	struct agentx_oid sav_start;
-	struct agentx_oid sav_end;
-	enum agentx_pdu_error sav_error;
-};
-
-#define SUBAGENTX_GET_CTX(sag) (sag->sag_context_default ? NULL : \
-    &(sag->sag_context))
-struct subagentx_request {
-	uint32_t sar_packetid;
-	int (*sar_cb)(struct agentx_pdu *, void *);
-	void *sar_cookie;
-	RB_ENTRY(subagentx_request) sar_sa_requests;
-};
-
-static void subagentx_start(struct subagentx *);
-static void subagentx_finalize(struct subagentx *, int);
-static void subagentx_wantwritenow(struct subagentx *, int);
-void (*subagentx_wantwrite)(struct subagentx *, int) =
-    subagentx_wantwritenow;
-static void subagentx_reset(struct subagentx *);
-static void subagentx_free_finalize(struct subagentx *);
-static int subagentx_session_start(struct subagentx_session *);
-static int subagentx_session_finalize(struct agentx_pdu *, void *);
-static int subagentx_session_close(struct subagentx_session *,
-    enum agentx_close_reason);
-static int subagentx_session_close_finalize(struct agentx_pdu *, void *);
-static void subagentx_session_free_finalize(struct subagentx_session *);
-static void subagentx_session_reset(struct subagentx_session *);
-static void subagentx_context_start(struct subagentx_context *);
-static void subagentx_context_free_finalize(struct subagentx_context *);
-static void subagentx_context_reset(struct subagentx_context *);
-static int subagentx_agentcaps_start(struct subagentx_agentcaps *);
-static int subagentx_agentcaps_finalize(struct agentx_pdu *, void *);
-static int subagentx_agentcaps_close(struct subagentx_agentcaps *);
-static int subagentx_agentcaps_close_finalize(struct agentx_pdu *, void *);
-static void subagentx_agentcaps_free_finalize(struct subagentx_agentcaps *);
-static void subagentx_agentcaps_reset(struct subagentx_agentcaps *);
-static int subagentx_region_start(struct subagentx_region *);
-static int subagentx_region_finalize(struct agentx_pdu *, void *);
-static int subagentx_region_close(struct subagentx_region *);
-static int subagentx_region_close_finalize(struct agentx_pdu *, void *);
-static void subagentx_region_free_finalize(struct subagentx_region *);
-static void subagentx_region_reset(struct subagentx_region *);
-static struct subagentx_index *subagentx_index(struct subagentx_region *,
-    struct agentx_varbind *, enum subagentx_index_type);
-static int subagentx_index_start(struct subagentx_index *);
-static int subagentx_index_finalize(struct agentx_pdu *, void *);
-static void subagentx_index_free_finalize(struct subagentx_index *);
-static void subagentx_index_reset(struct subagentx_index *);
-static int subagentx_index_close(struct subagentx_index *);
-static int subagentx_index_close_finalize(struct agentx_pdu *, void *);
-static int subagentx_object_start(struct subagentx_object *);
-static int subagentx_object_finalize(struct agentx_pdu *, void *);
-static int subagentx_object_lock(struct subagentx_object *);
-static void subagentx_object_unlock(struct subagentx_object *);
-static int subagentx_object_close(struct subagentx_object *);
-static int subagentx_object_close_finalize(struct agentx_pdu *, void *);
-static void subagentx_object_free_finalize(struct subagentx_object *);
-static void subagentx_object_reset(struct subagentx_object *);
-static int subagentx_object_cmp(struct subagentx_object *,
-    struct subagentx_object *);
-static void subagentx_get_start(struct subagentx_context *,
-    struct agentx_pdu *);
-static void subagentx_get_finalize(struct subagentx_get *);
-static void subagentx_get_free(struct subagentx_get *);
-static void subagentx_varbind_start(struct subagentx_varbind *);
-static void subagentx_varbind_finalize(struct subagentx_varbind *);
-static void subagentx_varbind_nosuchobject(struct subagentx_varbind *);
-static void subagentx_varbind_nosuchinstance(struct subagentx_varbind *);
-static void subagentx_varbind_endofmibview(struct subagentx_varbind *);
-static void subagentx_varbind_error_type(struct subagentx_varbind *,
-    enum agentx_pdu_error, int);
-static int subagentx_request(struct subagentx *, uint32_t,
-    int (*)(struct agentx_pdu *, void *), void *);
-static int subagentx_request_cmp(struct subagentx_request *,
-    struct subagentx_request *);
-static int subagentx_strcat(char **, const char *);
-
-RB_PROTOTYPE_STATIC(sa_requests, subagentx_request, sar_sa_requests,
-    subagentx_request_cmp)
-RB_PROTOTYPE_STATIC(sac_objects, subagentx_object, sao_sac_objects,
-    subagentx_object_cmp)
-
-struct subagentx *
-subagentx(void (*nofd)(struct subagentx *, void *, int), void *cookie)
-{
-	struct subagentx *sa;
-
-	if ((sa = calloc(1, sizeof(*sa))) == NULL)
-		return NULL;
-
-	sa->sa_nofd = nofd;
-	sa->sa_cookie = cookie;
-	sa->sa_fd = -1;
-	sa->sa_cstate = SA_CSTATE_CLOSE;
-	sa->sa_dstate = SA_DSTATE_OPEN;
-	TAILQ_INIT(&(sa->sa_sessions));
-	TAILQ_INIT(&(sa->sa_getreqs));
-	RB_INIT(&(sa->sa_requests));
-
-	subagentx_start(sa);
-
-	return sa;
-}
-
-/*
- * subagentx_finalize is not a suitable name for a public API,
- * but use it internally for consistency
- */
-void
-subagentx_connect(struct subagentx *sa, int fd)
-{
-	subagentx_finalize(sa, fd);
-}
-
-static void
-subagentx_start(struct subagentx *sa)
-{
-#ifdef AGENTX_DEBUG
-	if (sa->sa_cstate != SA_CSTATE_CLOSE ||
-	    sa->sa_dstate != SA_DSTATE_OPEN)
-		subagentx_log_sa_fatalx(sa, "%s: unexpected connect", __func__);
-#endif
-	sa->sa_cstate = SA_CSTATE_WAITOPEN;
-	sa->sa_nofd(sa, sa->sa_cookie, 0);
-}
-
-static void
-subagentx_finalize(struct subagentx *sa, int fd)
-{
-	struct subagentx_session *sas;
-
-	if (sa->sa_cstate != SA_CSTATE_WAITOPEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sa_fatalx(sa, "%s: subagentx unexpected connect",
-		    __func__);
-#else
-		subagentx_log_sa_warnx(sa,
-		    "%s: subagentx unexpected connect: ignoring", __func__);
-		return;
-#endif
-	}
-	if ((sa->sa_ax = agentx_new(fd)) == NULL) {
-		subagentx_log_sa_warn(sa, "failed to initialize");
-		close(fd);
-		subagentx_reset(sa);
-		return;
-	}
-
-	subagentx_log_sa_info(sa, "new connection: %d", fd);
-
-	sa->sa_fd = fd;
-	sa->sa_cstate = SA_CSTATE_OPEN;
-
-	TAILQ_FOREACH(sas, &(sa->sa_sessions), sas_sa_sessions) {
-		if (subagentx_session_start(sas) == -1)
-			break;
-	}
-}
-
-static void
-subagentx_wantwritenow(struct subagentx *sa, int fd)
-{
-	subagentx_write(sa);
-}
-
-static void
-subagentx_reset(struct subagentx *sa)
-{
-	struct subagentx_session *sas, *tsas;
-	struct subagentx_request *sar;
-	struct subagentx_get *sag;
-
-	agentx_free(sa->sa_ax);
-	sa->sa_ax = NULL;
-	sa->sa_fd = -1;
-
-	sa->sa_cstate = SA_CSTATE_CLOSE;
-
-	while ((sar = RB_MIN(sa_requests, &(sa->sa_requests))) != NULL) {
-		RB_REMOVE(sa_requests, &(sa->sa_requests), sar);
-		free(sar);
-	}
-	TAILQ_FOREACH_SAFE(sas, &(sa->sa_sessions), sas_sa_sessions, tsas)
-		subagentx_session_reset(sas);
-	while (!TAILQ_EMPTY(&(sa->sa_getreqs))) {
-		sag = TAILQ_FIRST(&(sa->sa_getreqs));
-		sag->sag_sac = NULL;
-		TAILQ_REMOVE(&(sa->sa_getreqs), sag, sag_sa_getreqs);
-	}
-
-	if (sa->sa_dstate == SA_DSTATE_CLOSE) {
-		subagentx_free_finalize(sa);
-		return;
-	}
-
-	subagentx_start(sa);
-}
-
-void
-subagentx_free(struct subagentx *sa)
-{
-	struct subagentx_session *sas, *tsas;
-
-	if (sa == NULL)
-		return;
-
-	if (sa->sa_dstate == SA_DSTATE_CLOSE) {
-/* Malloc throws abort on invalid pointers as well */
-		subagentx_log_sa_fatalx(sa, "%s: double free", __func__);
-	}
-	sa->sa_dstate = SA_DSTATE_CLOSE;
-
-	if (!TAILQ_EMPTY(&(sa->sa_sessions))) {
-		TAILQ_FOREACH_SAFE(sas, &(sa->sa_sessions), sas_sa_sessions,
-		    tsas) {
-			if (sas->sas_dstate != SA_DSTATE_CLOSE)
-				subagentx_session_free(sas);
-		}
-	} else
-		subagentx_free_finalize(sa);
-}
-
-static void
-subagentx_free_finalize(struct subagentx *sa)
-{
-#ifdef AGENTX_DEBUG
-	if (sa->sa_dstate != SA_DSTATE_CLOSE)
-		subagentx_log_sa_fatalx(sa, "%s: subagentx not closing",
-		    __func__);
-	if (!TAILQ_EMPTY(&(sa->sa_sessions)))
-		subagentx_log_sa_fatalx(sa, "%s: subagentx still has sessions",
-		    __func__);
-	if (!RB_EMPTY(&(sa->sa_requests)))
-		subagentx_log_sa_fatalx(sa,
-		    "%s: subagentx still has pending requests", __func__);
-#endif
-
-	agentx_free(sa->sa_ax);
-	sa->sa_nofd(sa, sa->sa_cookie, 1);
-	free(sa);
-}
-
-struct subagentx_session *
-subagentx_session(struct subagentx *sa, uint32_t oid[],
-    size_t oidlen, const char *descr, uint8_t timeout)
-{
-	struct subagentx_session *sas;
-	size_t i;
-
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sa_fatalx(sa, "%s: oidlen > %d", __func__,
-		    SUBAGENTX_OID_MAX_LEN);
-#else
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-	if ((sas = calloc(1, sizeof(*sas))) == NULL)
-		return NULL;
-
-	sas->sas_sa = sa;
-	sas->sas_timeout = timeout;
-	for (i = 0; i < oidlen; i++)
-		sas->sas_oid.aoi_id[i] = oid[i];
-	sas->sas_oid.aoi_idlen = oidlen;
-	sas->sas_descr.aos_string = (unsigned char *)strdup(descr);
-	if (sas->sas_descr.aos_string == NULL) {
-		free(sas);
-		return NULL;
-	}
-	sas->sas_descr.aos_slen = strlen(descr);
-	sas->sas_cstate = SA_CSTATE_CLOSE;
-	sas->sas_dstate = SA_DSTATE_OPEN;
-	TAILQ_INIT(&(sas->sas_contexts));
-	TAILQ_INSERT_HEAD(&(sa->sa_sessions), sas, sas_sa_sessions);
-
-	if (sa->sa_cstate == SA_CSTATE_OPEN)
-		(void) subagentx_session_start(sas);
-
-	return sas;
-}
-
-static int
-subagentx_session_start(struct subagentx_session *sas)
-{
-	struct subagentx *sa = sas->sas_sa;
-	uint32_t packetid;
-
-#ifdef AGENTX_DEBUG
-	if (sa->sa_cstate != SA_CSTATE_OPEN ||
-	    sas->sas_cstate != SA_CSTATE_CLOSE ||
-	    sas->sas_dstate != SA_DSTATE_OPEN)
-		subagentx_log_sa_fatalx(sa, "%s: unexpected session open",
-		    __func__);
-#endif
-	packetid = agentx_open(sa->sa_ax, sas->sas_timeout, &(sas->sas_oid),
-	    &(sas->sas_descr));
-	if (packetid == 0) {
-		subagentx_log_sa_warn(sa, "couldn't generate %s",
-		    agentx_pdutype2string(AGENTX_PDU_TYPE_OPEN));
-		subagentx_reset(sa);
-		return -1;
-	}
-	sas->sas_packetid = packetid;
-	subagentx_log_sa_info(sa, "opening session");
-	sas->sas_cstate = SA_CSTATE_WAITOPEN;
-	return subagentx_request(sa, packetid, subagentx_session_finalize, sas);
-}
-
-static int
-subagentx_session_finalize(struct agentx_pdu *pdu, void *cookie)
-{
-	struct subagentx_session *sas = cookie;
-	struct subagentx *sa = sas->sas_sa;
-	struct subagentx_context *sac;
-
-#ifdef AGENTX_DEBUG
-	if (sas->sas_cstate != SA_CSTATE_WAITOPEN)
-		subagentx_log_sa_fatalx(sa, "%s: not expecting new session",
-		    __func__);
-#endif
-
-	if (pdu->ap_payload.ap_response.ap_error != AGENTX_PDU_ERROR_NOERROR) {
-		subagentx_log_sa_warnx(sa, "failed to open session: %s",
-		    agentx_error2string(pdu->ap_payload.ap_response.ap_error));
-		subagentx_reset(sa);
-		return -1;
-	}
-
-	sas->sas_id = pdu->ap_header.aph_sessionid;
-	sas->sas_cstate = SA_CSTATE_OPEN;
-
-	if (sas->sas_dstate == SA_DSTATE_CLOSE) {
-		subagentx_session_close(sas, AGENTX_CLOSE_SHUTDOWN);
-		return 0;
-	}
-
-	subagentx_log_sas_info(sas, "open");
-
-	TAILQ_FOREACH(sac, &(sas->sas_contexts), sac_sas_contexts)
-		subagentx_context_start(sac);
-	return 0;
-}
-
-static int
-subagentx_session_close(struct subagentx_session *sas,
-    enum agentx_close_reason reason)
-{
-	struct subagentx *sa = sas->sas_sa;
-	uint32_t packetid;
-
-#ifdef AGENTX_DEBUG
-	if (sas->sas_cstate != SA_CSTATE_OPEN)
-		subagentx_log_sa_fatalx(sa, "%s: unexpected session close",
-		    __func__);
-#endif
-	if ((packetid = agentx_close(sa->sa_ax, sas->sas_id, reason)) == 0) {
-		subagentx_log_sas_warn(sas, "couldn't generate %s",
-		    agentx_pdutype2string(AGENTX_PDU_TYPE_CLOSE));
-		subagentx_reset(sa);
-		return -1;
-	}
-
-	subagentx_log_sas_info(sas, "closing session: %s",
-	    agentx_closereason2string(reason));
-
-	sas->sas_cstate = SA_CSTATE_WAITCLOSE;
-	return subagentx_request(sa, packetid, subagentx_session_close_finalize,
-	    sas);
-}
-
-static int
-subagentx_session_close_finalize(struct agentx_pdu *pdu, void *cookie)
-{
-	struct subagentx_session *sas = cookie;
-	struct subagentx *sa = sas->sas_sa;
-	struct subagentx_context *sac, *tsac;
-
-#ifdef AGENTX_DEBUG
-	if (sas->sas_cstate != SA_CSTATE_WAITCLOSE)
-		subagentx_log_sas_fatalx(sas, "%s: not expecting session close",
-		    __func__);
-#endif
-
-	if (pdu->ap_payload.ap_response.ap_error != AGENTX_PDU_ERROR_NOERROR) {
-		subagentx_log_sas_warnx(sas, "failed to close session: %s",
-		    agentx_error2string(pdu->ap_payload.ap_response.ap_error));
-		subagentx_reset(sa);
-		return -1;
-	}
-
-	sas->sas_cstate = SA_CSTATE_CLOSE;
-
-	subagentx_log_sas_info(sas, "closed");
-
-	TAILQ_FOREACH_SAFE(sac, &(sas->sas_contexts), sac_sas_contexts, tsac)
-		subagentx_context_reset(sac);
-
-	if (sas->sas_dstate == SA_DSTATE_CLOSE)
-		subagentx_session_free_finalize(sas);
-	else {
-		if (sa->sa_cstate == SA_CSTATE_OPEN)
-			if (subagentx_session_start(sas) == -1)
-				return -1;
-	}
-	return 0;
-}
-
-void
-subagentx_session_free(struct subagentx_session *sas)
-{
-	struct subagentx_context *sac, *tsac;
-
-	if (sas == NULL)
-		return;
-
-	if (sas->sas_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sas_fatalx(sas, "%s: double free", __func__);
-
-	sas->sas_dstate = SA_DSTATE_CLOSE;
-
-	if (sas->sas_cstate == SA_CSTATE_OPEN)
-		(void) subagentx_session_close(sas, AGENTX_CLOSE_SHUTDOWN);
-
-	TAILQ_FOREACH_SAFE(sac, &(sas->sas_contexts), sac_sas_contexts, tsac) {
-		if (sac->sac_dstate != SA_DSTATE_CLOSE)
-			subagentx_context_free(sac);
-	}
-
-	if (sas->sas_cstate == SA_CSTATE_CLOSE)
-		subagentx_session_free_finalize(sas);
-}
-
-static void
-subagentx_session_free_finalize(struct subagentx_session *sas)
-{
-	struct subagentx *sa = sas->sas_sa;
-
-#ifdef AGENTX_DEBUG
-	if (sas->sas_cstate != SA_CSTATE_CLOSE)
-		subagentx_log_sas_fatalx(sas, "%s: free without closing",
-		    __func__);
-	if (!TAILQ_EMPTY(&(sas->sas_contexts)))
-		subagentx_log_sas_fatalx(sas,
-		    "%s: subagentx still has contexts", __func__);
-#endif
-
-	TAILQ_REMOVE(&(sa->sa_sessions), sas, sas_sa_sessions);
-	free(sas->sas_descr.aos_string);
-	free(sas);
-
-	if (TAILQ_EMPTY(&(sa->sa_sessions)) && sa->sa_dstate == SA_DSTATE_CLOSE)
-		subagentx_free_finalize(sa);
-}
-
-static void
-subagentx_session_reset(struct subagentx_session *sas)
-{
-	struct subagentx_context *sac, *tsac;
-
-	sas->sas_cstate = SA_CSTATE_CLOSE;
-
-	TAILQ_FOREACH_SAFE(sac, &(sas->sas_contexts), sac_sas_contexts, tsac)
-		subagentx_context_reset(sac);
-
-	if (sas->sas_dstate == SA_DSTATE_CLOSE)
-		subagentx_session_free_finalize(sas);
-}
-
-struct subagentx_context *
-subagentx_context(struct subagentx_session *sas, const char *name)
-{
-	struct subagentx_context *sac;
-
-	if (sas->sas_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sas_fatalx(sas, "%s: use after free", __func__);
-
-	if ((sac = calloc(1, sizeof(*sac))) == NULL)
-		return NULL;
-
-	sac->sac_sas = sas;
-	sac->sac_name_default = (name == NULL);
-	if (name != NULL) {
-		sac->sac_name.aos_string = (unsigned char *)strdup(name);
-		if (sac->sac_name.aos_string == NULL) {
-			free(sac);
-			return NULL;
-		}
-		sac->sac_name.aos_slen = strlen(name);
-	}
-	sac->sac_cstate = sas->sas_cstate == SA_CSTATE_OPEN ?
-	    SA_CSTATE_OPEN : SA_CSTATE_CLOSE;
-	sac->sac_dstate = SA_DSTATE_OPEN;
-	TAILQ_INIT(&(sac->sac_agentcaps));
-	TAILQ_INIT(&(sac->sac_regions));
-
-	TAILQ_INSERT_HEAD(&(sas->sas_contexts), sac, sac_sas_contexts);
-
-	return sac;
-}
-
-static void
-subagentx_context_start(struct subagentx_context *sac)
-{
-	struct subagentx_agentcaps *saa;
-	struct subagentx_region *sar;
-
-#ifdef AGENTX_DEBUG
-	if (sac->sac_cstate != SA_CSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected context start",
-		    __func__);
-#endif
-	sac->sac_cstate = SA_CSTATE_OPEN;
-
-	TAILQ_FOREACH(saa, &(sac->sac_agentcaps), saa_sac_agentcaps) {
-		if (subagentx_agentcaps_start(saa) == -1)
-			return;
-	}
-	TAILQ_FOREACH(sar, &(sac->sac_regions), sar_sac_regions) {
-		if (subagentx_region_start(sar) == -1)
-			return;
-	}
-}
-
-uint32_t
-subagentx_context_uptime(struct subagentx_context *sac)
-{
-	struct timespec cur, res;
-
-	if (sac->sac_sysuptimespec.tv_sec == 0 &&
-	    sac->sac_sysuptimespec.tv_nsec == 0)
-		return 0;
-
-	(void) clock_gettime(CLOCK_MONOTONIC, &cur);
-
-	timespecsub(&cur, &(sac->sac_sysuptimespec), &res);
-
-	return sac->sac_sysuptime +
-	    (uint32_t) ((res.tv_sec * 100) + (res.tv_nsec / 10000000));
-}
-
-struct subagentx_object *
-subagentx_context_object_find(struct subagentx_context *sac,
-    const uint32_t oid[], size_t oidlen, int active, int instance)
-{
-	struct subagentx_object *sao, sao_search;
-	size_t i;
-
-	for (i = 0; i < oidlen; i++)
-		sao_search.sao_oid.aoi_id[i] = oid[i];
-	sao_search.sao_oid.aoi_idlen = oidlen;
-
-	sao = RB_FIND(sac_objects, &(sac->sac_objects), &sao_search);
-	while (sao == NULL && !instance && sao_search.sao_oid.aoi_idlen > 0) {
-		sao = RB_FIND(sac_objects, &(sac->sac_objects), &sao_search);
-		sao_search.sao_oid.aoi_idlen--;
-	}
-	if (active && sao != NULL && sao->sao_cstate != SA_CSTATE_OPEN)
-		return NULL;
-	return sao;
-}
-
-struct subagentx_object *
-subagentx_context_object_nfind(struct subagentx_context *sac,
-    const uint32_t oid[], size_t oidlen, int active, int inclusive)
-{
-	struct subagentx_object *sao, sao_search;
-	size_t i;
-
-	for (i = 0; i < oidlen; i++)
-		sao_search.sao_oid.aoi_id[i] = oid[i];
-	sao_search.sao_oid.aoi_idlen = oidlen;
-
-	sao = RB_NFIND(sac_objects, &(sac->sac_objects), &sao_search);
-	if (!inclusive && sao != NULL &&
-	    agentx_oid_cmp(&(sao_search.sao_oid), &(sao->sao_oid)) <= 0) {
-		sao = RB_NEXT(sac_objects, &(sac->sac_objects), sao);
-	}
-
-	while (active && sao != NULL && sao->sao_cstate != SA_CSTATE_OPEN)
-		sao = RB_NEXT(sac_objects, &(sac->sac_objects), sao);
-	return sao;
-}
-
-void
-subagentx_context_free(struct subagentx_context *sac)
-{
-	struct subagentx_agentcaps *saa, *tsaa;
-	struct subagentx_region *sar, *tsar;
-
-	if (sac == NULL)
-		return;
-
-#ifdef AGENTX_DEBUG
-	if (sac->sac_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sac, "%s: double free", __func__);
-#endif
-	sac->sac_dstate = SA_DSTATE_CLOSE;
-
-	TAILQ_FOREACH_SAFE(saa, &(sac->sac_agentcaps), saa_sac_agentcaps,
-	    tsaa) {
-		if (saa->saa_dstate != SA_DSTATE_CLOSE)
-			subagentx_agentcaps_free(saa);
-	}
-	TAILQ_FOREACH_SAFE(sar, &(sac->sac_regions), sar_sac_regions, tsar) {
-		if (sar->sar_dstate != SA_DSTATE_CLOSE)
-			subagentx_region_free(sar);
-	}
-}
-
-static void
-subagentx_context_free_finalize(struct subagentx_context *sac)
-{
-	struct subagentx_session *sas = sac->sac_sas;
-
-#ifdef AGENTX_DEBUG
-	if (sac->sac_dstate != SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected context free",
-		    __func__);
-#endif
-	if (!TAILQ_EMPTY(&(sac->sac_regions)) ||
-	    !TAILQ_EMPTY(&(sac->sac_agentcaps)))
-		return;
-	TAILQ_REMOVE(&(sas->sas_contexts), sac, sac_sas_contexts);
-	free(sac->sac_name.aos_string);
-	free(sac);
-}
-
-static void
-subagentx_context_reset(struct subagentx_context *sac)
-{
-	struct subagentx_agentcaps *saa, *tsaa;
-	struct subagentx_region *sar, *tsar;
-
-	sac->sac_cstate = SA_CSTATE_CLOSE;
-	sac->sac_sysuptimespec.tv_sec = 0;
-	sac->sac_sysuptimespec.tv_nsec = 0;
-
-	TAILQ_FOREACH_SAFE(saa, &(sac->sac_agentcaps), saa_sac_agentcaps, tsaa)
-		subagentx_agentcaps_reset(saa);
-	TAILQ_FOREACH_SAFE(sar, &(sac->sac_regions), sar_sac_regions, tsar)
-		subagentx_region_reset(sar);
-
-	if (sac->sac_dstate == SA_DSTATE_CLOSE)
-		subagentx_context_free_finalize(sac);
-}
-
-struct subagentx_agentcaps *
-subagentx_agentcaps(struct subagentx_context *sac, uint32_t oid[],
-    size_t oidlen, const char *descr)
-{
-	struct subagentx_agentcaps *saa;
-	size_t i;
-
-	if (sac->sac_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sac, "%s: use after free", __func__);
-
-	if ((saa = calloc(1, sizeof(*saa))) == NULL)
-		return NULL;
-
-	saa->saa_sac = sac;
-	for (i = 0; i < oidlen; i++)
-		saa->saa_oid.aoi_id[i] = oid[i];
-	saa->saa_oid.aoi_idlen = oidlen;
-	saa->saa_descr.aos_string = (unsigned char *)strdup(descr);
-	if (saa->saa_descr.aos_string == NULL) {
-		free(saa);
-		return NULL;
-	}
-	saa->saa_descr.aos_slen = strlen(descr);
-	saa->saa_cstate = SA_CSTATE_CLOSE;
-	saa->saa_dstate = SA_DSTATE_OPEN;
-
-	TAILQ_INSERT_TAIL(&(sac->sac_agentcaps), saa, saa_sac_agentcaps);
-
-	if (sac->sac_cstate == SA_CSTATE_OPEN)
-		subagentx_agentcaps_start(saa);
-
-	return saa;
-}
-
-static int
-subagentx_agentcaps_start(struct subagentx_agentcaps *saa)
-{
-	struct subagentx_context *sac = saa->saa_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	uint32_t packetid;
-
-#ifdef AGENTX_DEBUG
-	if (sac->sac_cstate != SA_CSTATE_OPEN ||
-	    saa->saa_cstate != SA_CSTATE_CLOSE ||
-	    saa->saa_dstate != SA_DSTATE_OPEN)
-		subagentx_log_sac_fatalx(sac,
-		    "%s: unexpected region registration", __func__);
-#endif
-
-	packetid = agentx_addagentcaps(sa->sa_ax, sas->sas_id,
-	    SUBAGENTX_CONTEXT_CTX(sac), &(saa->saa_oid), &(saa->saa_descr));
-	if (packetid == 0) {
-		subagentx_log_sac_warn(sac, "couldn't generate %s",
-		    agentx_pdutype2string(AGENTX_PDU_TYPE_ADDAGENTCAPS));
-		subagentx_reset(sa);
-		return -1;
-	}
-	subagentx_log_sac_info(sac, "agentcaps %s: opening",
-	    agentx_oid2string(&(saa->saa_oid)));
-	saa->saa_cstate = SA_CSTATE_WAITOPEN;
-	return subagentx_request(sa, packetid, subagentx_agentcaps_finalize,
-	    saa);
-}
-
-static int
-subagentx_agentcaps_finalize(struct agentx_pdu *pdu, void *cookie)
-{
-	struct subagentx_agentcaps *saa = cookie;
-	struct subagentx_context *sac = saa->saa_sac;
-
-#ifdef AGENTX_DEBUG
-	if (saa->saa_cstate != SA_CSTATE_WAITOPEN)
-		subagentx_log_sac_fatalx(sac,
-		    "%s: not expecting agentcaps open", __func__);
-#endif
-
-	if (pdu->ap_payload.ap_response.ap_error != AGENTX_PDU_ERROR_NOERROR) {
-		/* Agentcaps failing is nothing too serious */
-		subagentx_log_sac_warn(sac, "agentcaps %s: %s",
-		    agentx_oid2string(&(saa->saa_oid)),
-		    agentx_error2string(pdu->ap_payload.ap_response.ap_error));
-		saa->saa_cstate = SA_CSTATE_CLOSE;
-		return 0;
-	}
-
-	saa->saa_cstate = SA_CSTATE_OPEN;
-
-	subagentx_log_sac_info(sac, "agentcaps %s: open",
-	    agentx_oid2string(&(saa->saa_oid)));
-
-	if (saa->saa_dstate == SA_DSTATE_CLOSE)
-		subagentx_agentcaps_close(saa);
-
-	return 0;
-}
-
-static int
-subagentx_agentcaps_close(struct subagentx_agentcaps *saa)
-{
-	struct subagentx_context *sac = saa->saa_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	uint32_t packetid;
-
-#ifdef AGENTX_DEBUG
-	if (saa->saa_cstate != SA_CSTATE_OPEN)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected agentcaps close",
-		    __func__);
-#endif
-
-	saa->saa_cstate = SA_CSTATE_WAITCLOSE;
-	if (sas->sas_cstate == SA_CSTATE_WAITCLOSE)
-		return 0;
-
-	packetid = agentx_removeagentcaps(sa->sa_ax, sas->sas_id,
-	    SUBAGENTX_CONTEXT_CTX(sac), &(saa->saa_oid));
-	if (packetid == 0) {
-		subagentx_log_sac_warn(sac, "couldn't generate %s",
-		    agentx_pdutype2string(AGENTX_PDU_TYPE_REMOVEAGENTCAPS));
-		subagentx_reset(sa);
-		return -1;
-	}
-	subagentx_log_sac_info(sac, "agentcaps %s: closing",
-	    agentx_oid2string(&(saa->saa_oid)));
-	return subagentx_request(sa, packetid,
-	    subagentx_agentcaps_close_finalize, saa);
-}
-
-static int
-subagentx_agentcaps_close_finalize(struct agentx_pdu *pdu, void *cookie)
-{
-	struct subagentx_agentcaps *saa = cookie;
-	struct subagentx_context *sac = saa->saa_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-
-#ifdef AGENTX_DEBUG
-	if (saa->saa_cstate != SA_CSTATE_WAITCLOSE)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected agentcaps close",
-		    __func__);
-#endif
-
-	if (pdu->ap_payload.ap_response.ap_error != AGENTX_PDU_ERROR_NOERROR) {
-		subagentx_log_sac_warnx(sac, "agentcaps %s: %s",
-		    agentx_oid2string(&(saa->saa_oid)),
-		    agentx_error2string(pdu->ap_payload.ap_response.ap_error));
-		subagentx_reset(sa);
-		return -1;
-	}
-
-	saa->saa_cstate = SA_CSTATE_CLOSE;
-
-	subagentx_log_sac_info(sac, "agentcaps %s: closed",
-	    agentx_oid2string(&(saa->saa_oid)));
-
-	if (saa->saa_dstate == SA_DSTATE_CLOSE) {
-		subagentx_agentcaps_free_finalize(saa);
-		return 0;
-	} else {
-		if (sac->sac_cstate == SA_CSTATE_OPEN) {
-			if (subagentx_agentcaps_start(saa) == -1)
-				return -1;
-		}
-	}
-	return 0;
-}
-
-void
-subagentx_agentcaps_free(struct subagentx_agentcaps *saa)
-{
-	if (saa == NULL)
-		return;
-
-	if (saa->saa_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(saa->saa_sac, "%s: double free",
-		    __func__);
-
-	saa->saa_dstate = SA_DSTATE_CLOSE;
-
-	if (saa->saa_cstate == SA_CSTATE_OPEN) {
-		if (subagentx_agentcaps_close(saa) == -1)
-			return;
-	}
-
-	if (saa->saa_cstate == SA_CSTATE_CLOSE)
-		subagentx_agentcaps_free_finalize(saa);
-}
-
-static void
-subagentx_agentcaps_free_finalize(struct subagentx_agentcaps *saa)
-{
-	struct subagentx_context *sac = saa->saa_sac;
-
-#ifdef AGENTX_DEBUG
-	if (saa->saa_dstate != SA_DSTATE_CLOSE ||
-	    saa->saa_cstate != SA_CSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected free", __func__);
-#endif
-
-	TAILQ_REMOVE(&(sac->sac_agentcaps), saa, saa_sac_agentcaps);
-	free(saa->saa_descr.aos_string);
-	free(saa);
-
-	if (sac->sac_dstate == SA_DSTATE_CLOSE)
-		subagentx_context_free_finalize(sac);
-}
-
-static void
-subagentx_agentcaps_reset(struct subagentx_agentcaps *saa)
-{
-	saa->saa_cstate = SA_CSTATE_CLOSE;
-
-	if (saa->saa_dstate == SA_DSTATE_CLOSE)
-		subagentx_agentcaps_free_finalize(saa);
-}
-
-struct subagentx_region *
-subagentx_region(struct subagentx_context *sac, uint32_t oid[],
-    size_t oidlen, uint8_t timeout)
-{
-	struct subagentx_region *sar;
-	struct agentx_oid tmpoid;
-	size_t i;
-
-	if (sac->sac_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sac, "%s: use after free", __func__);
-	if (oidlen < 1) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sac, "%s: oidlen == 0", __func__);
-#else
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sac, "%s: oidlen > %d", __func__,
-		    SUBAGENTX_OID_MAX_LEN);
-#else
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	for (i = 0; i < oidlen; i++)
-		tmpoid.aoi_id[i] = oid[i];
-	tmpoid.aoi_idlen = oidlen;
-	TAILQ_FOREACH(sar, &(sac->sac_regions), sar_sac_regions) {
-		if (agentx_oid_cmp(&(sar->sar_oid), &tmpoid) == 0) {
-#ifdef AGENTX_DEBUG
-			subagentx_log_sac_fatalx(sac,
-			    "%s: duplicate region registration", __func__);
-#else
-			errno = EINVAL;
-			return NULL;
-#endif
-		}
-	}
-
-	if ((sar = calloc(1, sizeof(*sar))) == NULL)
-		return NULL;
-
-	sar->sar_sac = sac;
-	sar->sar_timeout = timeout;
-	sar->sar_priority = AGENTX_PRIORITY_DEFAULT;
-	bcopy(&tmpoid, &(sar->sar_oid), sizeof(sar->sar_oid));
-	sar->sar_cstate = SA_CSTATE_CLOSE;
-	sar->sar_dstate = SA_DSTATE_OPEN;
-	TAILQ_INIT(&(sar->sar_indices));
-	TAILQ_INIT(&(sar->sar_objects));
-
-	TAILQ_INSERT_HEAD(&(sac->sac_regions), sar, sar_sac_regions);
-
-	if (sac->sac_cstate == SA_CSTATE_OPEN)
-		(void) subagentx_region_start(sar);
-
-	return sar;
-}
-
-static int
-subagentx_region_start(struct subagentx_region *sar)
-{
-	struct subagentx_context *sac = sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	uint32_t packetid;
-
-#ifdef AGENTX_DEBUG
-	if (sac->sac_cstate != SA_CSTATE_OPEN ||
-	    sar->sar_cstate != SA_CSTATE_CLOSE ||
-	    sar->sar_dstate != SA_DSTATE_OPEN)
-		subagentx_log_sac_fatalx(sac,
-		    "%s: unexpected region registration", __func__);
-#endif
-
-	packetid = agentx_register(sa->sa_ax, 0, sas->sas_id,
-	    SUBAGENTX_CONTEXT_CTX(sac), sar->sar_timeout, sar->sar_priority,
-	    0, &(sar->sar_oid), 0);
-	if (packetid == 0) {
-		subagentx_log_sac_warn(sac, "couldn't generate %s",
-		    agentx_pdutype2string(AGENTX_PDU_TYPE_REGISTER));
-		subagentx_reset(sa);
-		return -1;
-	}
-	subagentx_log_sac_info(sac, "region %s: opening",
-	    agentx_oid2string(&(sar->sar_oid)));
-	sar->sar_cstate = SA_CSTATE_WAITOPEN;
-	return subagentx_request(sa, packetid, subagentx_region_finalize, sar);
-}
-
-static int
-subagentx_region_finalize(struct agentx_pdu *pdu, void *cookie)
-{
-	struct subagentx_region *sar = cookie;
-	struct subagentx_context *sac = sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	struct subagentx_index *sai;
-	struct subagentx_object *sao;
-
-#ifdef AGENTX_DEBUG
-	if (sar->sar_cstate != SA_CSTATE_WAITOPEN)
-		subagentx_log_sac_fatalx(sac, "%s: not expecting region open",
-		    __func__);
-#endif
-
-	if (pdu->ap_payload.ap_response.ap_error == AGENTX_PDU_ERROR_NOERROR) {
-		sar->sar_cstate = SA_CSTATE_OPEN;
-		subagentx_log_sac_info(sac, "region %s: open",
-		    agentx_oid2string(&(sar->sar_oid)));
-	} else if (pdu->ap_payload.ap_response.ap_error ==
-	    AGENTX_PDU_ERROR_DUPLICATEREGISTRATION) {
-		sar->sar_cstate = SA_CSTATE_CLOSE;
-		/* Try at lower priority: first come first serve */
-		if ((++sar->sar_priority) != 0) {
-			subagentx_log_sac_warnx(sac, "region %s: duplicate, "
-			    "reducing priority",
-			    agentx_oid2string(&(sar->sar_oid)));
-			return subagentx_region_start(sar);
-		}
-		subagentx_log_sac_info(sac, "region %s: duplicate, can't "
-		    "reduce priority, ignoring",
-		    agentx_oid2string(&(sar->sar_oid)));
-	} else if (pdu->ap_payload.ap_response.ap_error ==
-	    AGENTX_PDU_ERROR_REQUESTDENIED) {
-		sar->sar_cstate = SA_CSTATE_CLOSE;
-		subagentx_log_sac_warnx(sac, "region %s: %s",
-		     agentx_oid2string(&(sar->sar_oid)),
-		     agentx_error2string(pdu->ap_payload.ap_response.ap_error));
-		/*
-		 * If we can't register a region, related objects are useless.
-		 * But no need to retry.
-		 */
-		return 0;
-	} else {
-		subagentx_log_sac_info(sac, "region %s: %s",
-		    agentx_oid2string(&(sar->sar_oid)),
-		    agentx_error2string(pdu->ap_payload.ap_response.ap_error));
-		subagentx_reset(sa);
-		return -1;
-	}
-
-	if (sar->sar_dstate == SA_DSTATE_CLOSE) {
-		if (subagentx_region_close(sar) == -1)
-			return -1;
-	} else {
-		TAILQ_FOREACH(sai, &(sar->sar_indices), sai_sar_indices) {
-			if (subagentx_index_start(sai) == -1)
-				return -1;
-		}
-		TAILQ_FOREACH(sao, &(sar->sar_objects), sao_sar_objects) {
-			if (subagentx_object_start(sao) == -1)
-				return -1;
-		}
-	}
-	return 0;
-}
-
-static int
-subagentx_region_close(struct subagentx_region *sar)
-{
-	struct subagentx_context *sac = sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	uint32_t packetid;
-
-#ifdef AGENTX_DEBUG
-	if (sar->sar_cstate != SA_CSTATE_OPEN)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected region close",
-		    __func__);
-#endif
-
-	sar->sar_cstate = SA_CSTATE_WAITCLOSE;
-	if (sas->sas_cstate == SA_CSTATE_WAITCLOSE)
-		return 0;
-
-	packetid = agentx_unregister(sa->sa_ax, sas->sas_id,
-	    SUBAGENTX_CONTEXT_CTX(sac), sar->sar_priority, 0, &(sar->sar_oid),
-	    0);
-	if (packetid == 0) {
-		subagentx_log_sac_warn(sac, "couldn't generate %s",
-		    agentx_pdutype2string(AGENTX_PDU_TYPE_UNREGISTER));
-		subagentx_reset(sa);
-		return -1;
-	}
-	subagentx_log_sac_info(sac, "region %s: closing",
-	    agentx_oid2string(&(sar->sar_oid)));
-	return subagentx_request(sa, packetid, subagentx_region_close_finalize,
-	    sar);
-}
-
-static int
-subagentx_region_close_finalize(struct agentx_pdu *pdu, void *cookie)
-{
-	struct subagentx_region *sar = cookie;
-	struct subagentx_context *sac = sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-
-#ifdef AGENTX_DEBUG
-	if (sar->sar_cstate != SA_CSTATE_WAITCLOSE)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected region close",
-		    __func__);
-#endif
-
-	if (pdu->ap_payload.ap_response.ap_error != AGENTX_PDU_ERROR_NOERROR) {
-		subagentx_log_sac_warnx(sac, "closing %s: %s",
-		    agentx_oid2string(&(sar->sar_oid)),
-		    agentx_error2string(pdu->ap_payload.ap_response.ap_error));
-		subagentx_reset(sa);
-		return -1;
-	}
-
-	sar->sar_priority = AGENTX_PRIORITY_DEFAULT;
-	sar->sar_cstate = SA_CSTATE_CLOSE;
-
-	subagentx_log_sac_info(sac, "region %s: closed",
-	    agentx_oid2string(&(sar->sar_oid)));
-
-	if (sar->sar_dstate == SA_DSTATE_CLOSE) {
-		subagentx_region_free_finalize(sar);
-		return 0;
-	} else {
-		if (sac->sac_cstate == SA_CSTATE_OPEN) {
-			if (subagentx_region_start(sar) == -1)
-				return -1;
-		}
-	}
-	return 0;
-}
-
-void
-subagentx_region_free(struct subagentx_region *sar)
-{
-	struct subagentx_index *sai, *tsai;
-	struct subagentx_object *sao, *tsao;
-
-	if (sar == NULL)
-		return;
-
-	if (sar->sar_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: double free",
-		    __func__);
-
-	sar->sar_dstate = SA_DSTATE_CLOSE;
-
-	TAILQ_FOREACH_SAFE(sai, &(sar->sar_indices), sai_sar_indices, tsai) {
-		if (sai->sai_dstate != SA_DSTATE_CLOSE)
-			subagentx_index_free(sai);
-	}
-
-	TAILQ_FOREACH_SAFE(sao, &(sar->sar_objects), sao_sar_objects, tsao) {
-		if (sao->sao_dstate != SA_DSTATE_CLOSE)
-			subagentx_object_free(sao);
-	}
-
-	if (sar->sar_cstate == SA_CSTATE_OPEN) {
-		if (subagentx_region_close(sar) == -1)
-			return;
-	}
-
-	if (sar->sar_cstate == SA_CSTATE_CLOSE)
-		subagentx_region_free_finalize(sar);
-}
-
-static void
-subagentx_region_free_finalize(struct subagentx_region *sar)
-{
-	struct subagentx_context *sac = sar->sar_sac;
-
-#ifdef AGENTX_DEBUG
-	if (sar->sar_dstate != SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected free", __func__);
-#endif
-
-	if (!TAILQ_EMPTY(&(sar->sar_indices)) ||
-	    !TAILQ_EMPTY(&(sar->sar_objects)))
-		return;
-
-	if (sar->sar_cstate != SA_CSTATE_CLOSE)
-		return;
-
-	TAILQ_REMOVE(&(sac->sac_regions), sar, sar_sac_regions);
-	free(sar);
-
-	if (sac->sac_dstate == SA_DSTATE_CLOSE)
-		subagentx_context_free_finalize(sac);
-}
-
-static void
-subagentx_region_reset(struct subagentx_region *sar)
-{
-	struct subagentx_index *sai, *tsai;
-	struct subagentx_object *sao, *tsao;
-
-	sar->sar_cstate = SA_CSTATE_CLOSE;
-	sar->sar_priority = AGENTX_PRIORITY_DEFAULT;
-
-	TAILQ_FOREACH_SAFE(sai, &(sar->sar_indices), sai_sar_indices, tsai)
-		subagentx_index_reset(sai);
-	TAILQ_FOREACH_SAFE(sao, &(sar->sar_objects), sao_sar_objects, tsao)
-		subagentx_object_reset(sao);
-
-	if (sar->sar_dstate == SA_DSTATE_CLOSE)
-		subagentx_region_free_finalize(sar);
-}
-
-struct subagentx_index *
-subagentx_index_integer_new(struct subagentx_region *sar, uint32_t oid[],
-    size_t oidlen)
-{
-	struct agentx_varbind vb;
-	size_t i;
-
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	vb.avb_type = AGENTX_DATA_TYPE_INTEGER;
-	for (i = 0; i < oidlen; i++)
-		vb.avb_oid.aoi_id[i] = oid[i];
-	vb.avb_oid.aoi_idlen = oidlen;
-	vb.avb_data.avb_uint32 = 0;
-
-	return subagentx_index(sar, &vb, SAI_TYPE_NEW);
-}
-
-struct subagentx_index *
-subagentx_index_integer_any(struct subagentx_region *sar, uint32_t oid[],
-    size_t oidlen)
-{
-	struct agentx_varbind vb;
-	size_t i;
-
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	vb.avb_type = AGENTX_DATA_TYPE_INTEGER;
-	for (i = 0; i < oidlen; i++)
-		vb.avb_oid.aoi_id[i] = oid[i];
-	vb.avb_oid.aoi_idlen = oidlen;
-	vb.avb_data.avb_uint32 = 0;
-
-	return subagentx_index(sar, &vb, SAI_TYPE_ANY);
-}
-
-struct subagentx_index *
-subagentx_index_integer_value(struct subagentx_region *sar, uint32_t oid[],
-    size_t oidlen, uint32_t value)
-{
-	struct agentx_varbind vb;
-	size_t i;
-
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	vb.avb_type = AGENTX_DATA_TYPE_INTEGER;
-	for (i = 0; i < oidlen; i++)
-		vb.avb_oid.aoi_id[i] = oid[i];
-	vb.avb_oid.aoi_idlen = oidlen;
-	vb.avb_data.avb_uint32 = value;
-
-	return subagentx_index(sar, &vb, SAI_TYPE_VALUE);
-}
-
-struct subagentx_index *
-subagentx_index_integer_dynamic(struct subagentx_region *sar, uint32_t oid[],
-    size_t oidlen)
-{
-	struct agentx_varbind vb;
-	size_t i;
-
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	vb.avb_type = AGENTX_DATA_TYPE_INTEGER;
-	for (i = 0; i < oidlen; i++)
-		vb.avb_oid.aoi_id[i] = oid[i];
-	vb.avb_oid.aoi_idlen = oidlen;
-
-	return subagentx_index(sar, &vb, SAI_TYPE_DYNAMIC);
-}
-
-struct subagentx_index *
-subagentx_index_string_dynamic(struct subagentx_region *sar, uint32_t oid[],
-    size_t oidlen)
-{
-	struct agentx_varbind vb;
-	size_t i;
-
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	vb.avb_type = AGENTX_DATA_TYPE_OCTETSTRING;
-	for (i = 0; i < oidlen; i++)
-		vb.avb_oid.aoi_id[i] = oid[i];
-	vb.avb_oid.aoi_idlen = oidlen;
-	vb.avb_data.avb_ostring.aos_slen = 0;
-	vb.avb_data.avb_ostring.aos_string = NULL;
-
-	return subagentx_index(sar, &vb, SAI_TYPE_DYNAMIC);
-}
-
-struct subagentx_index *
-subagentx_index_nstring_dynamic(struct subagentx_region *sar, uint32_t oid[],
-    size_t oidlen, size_t vlen)
-{
-	struct agentx_varbind vb;
-	size_t i;
-
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-	if (vlen == 0 || vlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: invalid string "
-		    "length: %zu\n", __func__, vlen);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: invalid string "
-		    "length: %zu\n", __func__, vlen);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	vb.avb_type = AGENTX_DATA_TYPE_OCTETSTRING;
-	for (i = 0; i < oidlen; i++)
-		vb.avb_oid.aoi_id[i] = oid[i];
-	vb.avb_oid.aoi_idlen = oidlen;
-	vb.avb_data.avb_ostring.aos_slen = vlen;
-	vb.avb_data.avb_ostring.aos_string = NULL;
-
-	return subagentx_index(sar, &vb, SAI_TYPE_DYNAMIC);
-}
-
-struct subagentx_index *
-subagentx_index_oid_dynamic(struct subagentx_region *sar, uint32_t oid[],
-    size_t oidlen)
-{
-	struct agentx_varbind vb;
-	size_t i;
-
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	vb.avb_type = AGENTX_DATA_TYPE_OID;
-	for (i = 0; i < oidlen; i++)
-		vb.avb_oid.aoi_id[i] = oid[i];
-	vb.avb_oid.aoi_idlen = oidlen;
-	vb.avb_data.avb_oid.aoi_idlen = 0;
-
-	return subagentx_index(sar, &vb, SAI_TYPE_DYNAMIC);
-}
-
-struct subagentx_index *
-subagentx_index_noid_dynamic(struct subagentx_region *sar, uint32_t oid[],
-    size_t oidlen, size_t vlen)
-{
-	struct agentx_varbind vb;
-	size_t i;
-
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-	if (vlen == 0 || vlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: invalid string "
-		    "length: %zu\n", __func__, vlen);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: invalid string "
-		    "length: %zu\n", __func__, vlen);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	vb.avb_type = AGENTX_DATA_TYPE_OID;
-	for (i = 0; i < oidlen; i++)
-		vb.avb_oid.aoi_id[i] = oid[i];
-	vb.avb_oid.aoi_idlen = oidlen;
-	vb.avb_data.avb_oid.aoi_idlen = vlen;
-
-	return subagentx_index(sar, &vb, SAI_TYPE_DYNAMIC);
-}
-
-struct subagentx_index *
-subagentx_index_ipaddress_dynamic(struct subagentx_region *sar, uint32_t oid[],
-    size_t oidlen)
-{
-	struct agentx_varbind vb;
-	size_t i;
-
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	vb.avb_type = AGENTX_DATA_TYPE_IPADDRESS;
-	for (i = 0; i < oidlen; i++)
-		vb.avb_oid.aoi_id[i] = oid[i];
-	vb.avb_data.avb_ostring.aos_string = NULL;
-	vb.avb_oid.aoi_idlen = oidlen;
-
-	return subagentx_index(sar, &vb, SAI_TYPE_DYNAMIC);
-}
-
-static struct subagentx_index *
-subagentx_index(struct subagentx_region *sar, struct agentx_varbind *vb,
-    enum subagentx_index_type type)
-{
-	struct subagentx_index *sai;
-
-	if (sar->sar_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: use after free",
-		    __func__);
-	if (agentx_oid_cmp(&(sar->sar_oid), &(vb->avb_oid)) != -2) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oid is not child "
-		    "of region %s", __func__,
-		    agentx_oid2string(&(vb->avb_oid)));
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oid is not child of "
-		    "region %s", __func__, agentx_oid2string(&(vb->avb_oid)));
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	if ((sai = calloc(1, sizeof(*sai))) == NULL)
-		return NULL;
-
-	sai->sai_sar = sar;
-	sai->sai_type = type;
-	bcopy(vb, &(sai->sai_vb), sizeof(*vb));
-	sai->sai_cstate = SA_CSTATE_CLOSE;
-	sai->sai_dstate = SA_DSTATE_OPEN;
-	TAILQ_INSERT_HEAD(&(sar->sar_indices), sai, sai_sar_indices);
-
-	if (sar->sar_cstate == SA_CSTATE_OPEN)
-		subagentx_index_start(sai);
-
-	return sai;
-}
-
-static int
-subagentx_index_start(struct subagentx_index *sai)
-{
-	struct subagentx_region *sar = sai->sai_sar;
-	struct subagentx_context *sac = sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	uint32_t packetid;
-	int flags = 0;
-
-#ifdef AGENTX_DEBUG
-	if (sar->sar_cstate != SA_CSTATE_OPEN ||
-	    sai->sai_cstate != SA_CSTATE_CLOSE ||
-	    sai->sai_dstate != SA_DSTATE_OPEN)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected index allocation",
-		    __func__);
-#endif
-
-	sai->sai_cstate = SA_CSTATE_WAITOPEN;
-
-	if (sai->sai_type == SAI_TYPE_NEW)
-		flags = AGENTX_PDU_FLAG_NEW_INDEX;
-	else if (sai->sai_type == SAI_TYPE_ANY)
-		flags = AGENTX_PDU_FLAG_ANY_INDEX;
-	else if (sai->sai_type == SAI_TYPE_DYNAMIC) {
-		subagentx_index_finalize(NULL, sai);
-		return 0;
-	}
-
-	/* We might be able to bundle, but if we fail we'd have to reorganise */
-	packetid = agentx_indexallocate(sa->sa_ax, flags, sas->sas_id,
-	    SUBAGENTX_CONTEXT_CTX(sac), &(sai->sai_vb), 1);
-	if (packetid == 0) {
-		subagentx_log_sac_warn(sac, "couldn't generate %s",
-		    agentx_pdutype2string(AGENTX_PDU_TYPE_INDEXDEALLOCATE));
-		subagentx_reset(sa);
-		return -1;
-	}
-	if (sai->sai_type == SAI_TYPE_VALUE)
-		subagentx_log_sac_info(sac, "index %s: allocating '%u'",
-		    agentx_oid2string(&(sai->sai_vb.avb_oid)),
-		    sai->sai_vb.avb_data.avb_uint32);
-	else if (sai->sai_type == SAI_TYPE_ANY)
-		subagentx_log_sac_info(sac, "index %s: allocating any index",
-		    agentx_oid2string(&(sai->sai_vb.avb_oid)));
-	else if (sai->sai_type == SAI_TYPE_NEW)
-		subagentx_log_sac_info(sac, "index %s: allocating new index",
-		    agentx_oid2string(&(sai->sai_vb.avb_oid)));
-
-	return subagentx_request(sa, packetid, subagentx_index_finalize, sai);
-}
-
-static int
-subagentx_index_finalize(struct agentx_pdu *pdu, void *cookie)
-{
-	struct subagentx_index *sai = cookie;
-	struct subagentx_region *sar = sai->sai_sar;
-	struct subagentx_context *sac = sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	struct agentx_pdu_response *resp;
-	size_t i;
-
-#ifdef AGENTX_DEBUG
-	if (sai->sai_cstate != SA_CSTATE_WAITOPEN)
-		subagentx_log_sac_fatalx(sac,
-		    "%s: not expecting index allocate", __func__);
-#endif
-	if (sai->sai_type == SAI_TYPE_DYNAMIC) {
-		sai->sai_cstate = SA_CSTATE_OPEN;
-		return 0;
-	}
-
-	resp = &(pdu->ap_payload.ap_response);
-	if (resp->ap_error != AGENTX_PDU_ERROR_NOERROR) {
-		sai->sai_cstate = SA_CSTATE_CLOSE;
-		subagentx_log_sac_warnx(sac, "index %s: %s",
-		    agentx_oid2string(&(sar->sar_oid)),
-		    agentx_error2string(resp->ap_error));
-		return 0;
-	}
-	sai->sai_cstate = SA_CSTATE_OPEN;
-	if (resp->ap_nvarbind != 1) {
-		subagentx_log_sac_warnx(sac, "index %s: unexpected number of "
-		    "indices", agentx_oid2string(&(sar->sar_oid)));
-		subagentx_reset(sa);
-		return -1;
-	}
-	if (resp->ap_varbindlist[0].avb_type != sai->sai_vb.avb_type) {
-		subagentx_log_sac_warnx(sac, "index %s: unexpected index type",
-		    agentx_oid2string(&(sar->sar_oid)));
-		subagentx_reset(sa);
-		return -1;
-	}
-	if (agentx_oid_cmp(&(resp->ap_varbindlist[0].avb_oid),
-	    &(sai->sai_vb.avb_oid)) != 0) {
-		subagentx_log_sac_warnx(sac, "index %s: unexpected oid",
-		    agentx_oid2string(&(sar->sar_oid)));
-		subagentx_reset(sa);
-		return -1;
-	}
-
-	switch (sai->sai_vb.avb_type) {
-	case AGENTX_DATA_TYPE_INTEGER:
-		if (sai->sai_type == SAI_TYPE_NEW ||
-		    sai->sai_type == SAI_TYPE_ANY)
-			sai->sai_vb.avb_data.avb_uint32 =
-			    resp->ap_varbindlist[0].avb_data.avb_uint32;
-		else if (sai->sai_vb.avb_data.avb_uint32 !=
-		    resp->ap_varbindlist[0].avb_data.avb_uint32) {
-			subagentx_log_sac_warnx(sac, "index %s: unexpected "
-			    "index value", agentx_oid2string(&(sar->sar_oid)));
-			subagentx_reset(sa);
-			return -1;
-		}
-		subagentx_log_sac_info(sac, "index %s: allocated '%u'",
-		    agentx_oid2string(&(sai->sai_vb.avb_oid)),
-		    sai->sai_vb.avb_data.avb_uint32);
-		break;
-	default:
-		subagentx_log_sac_fatalx(sac, "%s: Unsupported index type",
-		    __func__);
-	}
-
-	if (sai->sai_dstate == SA_DSTATE_CLOSE)
-		return subagentx_index_close(sai);
-
-	/* TODO Make use of range_subid register */
-	for (i = 0; i < sai->sai_objectlen; i++) {
-		if (sai->sai_object[i]->sao_dstate == SA_DSTATE_OPEN) {
-			if (subagentx_object_start(sai->sai_object[i]) == -1)
-				return -1;
-		}
-	}
-	return 0;
-}
-
-void
-subagentx_index_free(struct subagentx_index *sai)
-{
-	size_t i;
-	struct subagentx_object *sao;
-
-	if (sai == NULL)
-		return;
-
-	if (sai->sai_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sai->sai_sar->sar_sac,
-		    "%s: double free", __func__);
-
-	/* TODO Do a range_subid unregister before freeing */
-	for (i = 0; i < sai->sai_objectlen; i++) {
-		sao = sai->sai_object[i];
-		if (sao->sao_dstate != SA_DSTATE_CLOSE) {
-			subagentx_object_free(sao);
-			if (sai->sai_object[i] != sao)
-				i--;
-		}
-	}
-
-	sai->sai_dstate = SA_DSTATE_CLOSE;
-
-	if (sai->sai_cstate == SA_CSTATE_OPEN)
-		(void) subagentx_index_close(sai);
-	else if (sai->sai_cstate == SA_CSTATE_CLOSE)
-		subagentx_index_free_finalize(sai);
-}
-
-static void
-subagentx_index_free_finalize(struct subagentx_index *sai)
-{
-	struct subagentx_region *sar = sai->sai_sar;
-
-#ifdef AGENTX_DEBUG
-	if (sai->sai_dstate != SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: unexpected free",
-		    __func__);
-	if (sai->sai_cstate != SA_CSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sar->sar_sac,
-		    "%s: free without deallocating", __func__);
-#endif
-
-	if (sai->sai_objectlen != 0)
-		return;
-
-	TAILQ_REMOVE(&(sar->sar_indices), sai, sai_sar_indices);
-	agentx_varbind_free(&(sai->sai_vb));
-	free(sai->sai_object);
-	free(sai);
-	if (sar->sar_dstate == SA_DSTATE_CLOSE)
-		subagentx_region_free_finalize(sar);
-}
-
-static void
-subagentx_index_reset(struct subagentx_index *sai)
-{
-	sai->sai_cstate = SA_CSTATE_CLOSE;
-
-	if (sai->sai_dstate == SA_DSTATE_CLOSE)
-		subagentx_index_free_finalize(sai);
-}
-
-static int
-subagentx_index_close(struct subagentx_index *sai)
-{
-	struct subagentx_region *sar = sai->sai_sar;
-	struct subagentx_context *sac = sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	uint32_t packetid;
-
-#ifdef AGENTX_DEBUG
-	if (sai->sai_cstate != SA_CSTATE_OPEN)
-		subagentx_log_sac_fatalx(sac,
-		    "%s: unexpected index deallocation", __func__);
-#endif
-
-	sai->sai_cstate = SA_CSTATE_WAITCLOSE;
-	if (sas->sas_cstate == SA_CSTATE_WAITCLOSE)
-		return 0;
-
-	/* We might be able to bundle, but if we fail we'd have to reorganise */
-	packetid = agentx_indexdeallocate(sa->sa_ax, sas->sas_id,
-	    SUBAGENTX_CONTEXT_CTX(sac), &(sai->sai_vb), 1);
-	if (packetid == 0) {
-		subagentx_log_sac_warn(sac, "couldn't generate %s",
-		    agentx_pdutype2string(AGENTX_PDU_TYPE_INDEXDEALLOCATE));
-		subagentx_reset(sa);
-		return -1;
-	}
-	subagentx_log_sac_info(sac, "index %s: deallocating",
-	    agentx_oid2string(&(sai->sai_vb.avb_oid)));
-	return subagentx_request(sa, packetid, subagentx_index_close_finalize,
-	    sai);
-}
-
-static int
-subagentx_index_close_finalize(struct agentx_pdu *pdu, void *cookie)
-{
-	struct subagentx_index *sai = cookie;
-	struct subagentx_region *sar = sai->sai_sar;
-	struct subagentx_context *sac = sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	struct agentx_pdu_response *resp = &(pdu->ap_payload.ap_response);
-
-#ifdef AGENTX_DEBUG
-	if (sai->sai_cstate != SA_CSTATE_WAITCLOSE)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected indexdeallocate",
-		    __func__);
-#endif
-
-	if (pdu->ap_payload.ap_response.ap_error != AGENTX_PDU_ERROR_NOERROR) {
-		subagentx_log_sac_warnx(sac,
-		    "index %s: couldn't deallocate: %s",
-		    agentx_oid2string(&(sai->sai_vb.avb_oid)),
-		    agentx_error2string(resp->ap_error));
-		subagentx_reset(sa);
-		return -1;
-	}
-
-	if (resp->ap_nvarbind != 1) {
-		subagentx_log_sac_warnx(sac,
-		    "index %s: unexpected number of indices",
-		    agentx_oid2string(&(sar->sar_oid)));
-		subagentx_reset(sa);
-		return -1;
-	}
-	if (resp->ap_varbindlist[0].avb_type != sai->sai_vb.avb_type) {
-		subagentx_log_sac_warnx(sac, "index %s: unexpected index type",
-		    agentx_oid2string(&(sar->sar_oid)));
-		subagentx_reset(sa);
-		return -1;
-	}
-	if (agentx_oid_cmp(&(resp->ap_varbindlist[0].avb_oid),
-	    &(sai->sai_vb.avb_oid)) != 0) {
-		subagentx_log_sac_warnx(sac, "index %s: unexpected oid",
-		    agentx_oid2string(&(sar->sar_oid)));
-		subagentx_reset(sa);
-		return -1;
-	}
-	switch (sai->sai_vb.avb_type) {
-	case AGENTX_DATA_TYPE_INTEGER:
-		if (sai->sai_vb.avb_data.avb_uint32 !=
-		    resp->ap_varbindlist[0].avb_data.avb_uint32) {
-			subagentx_log_sac_warnx(sac,
-			    "index %s: unexpected index value",
-			    agentx_oid2string(&(sar->sar_oid)));
-			subagentx_reset(sa);
-			return -1;
-		}
-		break;
-	default:
-		subagentx_log_sac_fatalx(sac, "%s: Unsupported index type",
-		    __func__);
-	}
-
-	sai->sai_cstate = SA_CSTATE_CLOSE;
-
-	subagentx_log_sac_info(sac, "index %s: deallocated",
-	    agentx_oid2string(&(sai->sai_vb.avb_oid)));
-
-	if (sai->sai_dstate == SA_DSTATE_CLOSE) {
-		subagentx_index_free_finalize(sai);
-	} else if (sar->sar_cstate == SA_CSTATE_OPEN) {
-		if (subagentx_index_start(sai) == -1)
-			return -1;
-	}
-	return 0;
-}
-
-struct subagentx_object *
-subagentx_object(struct subagentx_region *sar, uint32_t oid[], size_t oidlen,
-    struct subagentx_index *sai[], size_t sailen, int implied,
-    void (*get)(struct subagentx_varbind *))
-{
-	struct subagentx_object *sao, **tsao, sao_search;
-	struct subagentx_index *lsai;
-	int ready = 1;
-	size_t i, j;
-
-	if (sar->sar_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: use after free",
-		    __func__);
-	if (oidlen < 1) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen == 0",
-		    __func__);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen == 0",
-		    __func__);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-	if (oidlen > SUBAGENTX_OID_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: oidlen > %d",
-		    __func__, SUBAGENTX_OID_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-	if (sailen > SUBAGENTX_OID_INDEX_MAX_LEN) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: indexlen > %d",
-		    __func__, SUBAGENTX_OID_INDEX_MAX_LEN);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: indexlen > %d",
-		    __func__, SUBAGENTX_OID_INDEX_MAX_LEN);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-
-	for (i = 0; i < oidlen; i++)
-		sao_search.sao_oid.aoi_id[i] = oid[i];
-	sao_search.sao_oid.aoi_idlen = oidlen;
-
-	do {
-		if (RB_FIND(sac_objects, &(sar->sar_sac->sac_objects),
-		    &sao_search) != NULL) {
-#ifdef AGENTX_DEBUG
-			subagentx_log_sac_fatalx(sar->sar_sac, "%s: invalid "
-			    "parent child object relationship", __func__);
-#else
-			subagentx_log_sac_warnx(sar->sar_sac, "%s: invalid "
-			    "parent child object relationship", __func__);
-			errno = EINVAL;
-			return NULL;
-#endif
-		}
-		sao_search.sao_oid.aoi_idlen--;
-	} while (sao_search.sao_oid.aoi_idlen > 0);
-	sao_search.sao_oid.aoi_idlen = oidlen;
-	sao = RB_NFIND(sac_objects, &(sar->sar_sac->sac_objects), &sao_search);
-	if (sao != NULL &&
-	    agentx_oid_cmp(&(sao->sao_oid), &(sao_search.sao_oid)) == 2) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sac_fatalx(sar->sar_sac, "%s: invalid parent "
-		    "child object relationship", __func__);
-#else
-		subagentx_log_sac_warnx(sar->sar_sac, "%s: invalid parent "
-		    "child object relationship", __func__);
-		errno = EINVAL;
-		return NULL;
-#endif
-	}
-	if (implied == 1) {
-		lsai = sai[sailen - 1];
-		if (lsai->sai_vb.avb_type == AGENTX_DATA_TYPE_OCTETSTRING) {
-			if (lsai->sai_vb.avb_data.avb_ostring.aos_slen != 0) {
-#ifdef AGENTX_DEBUG
-				subagentx_log_sac_fatalx(sar->sar_sac,
-				    "%s: implied can only be used on strings "
-				    "of dynamic length", __func__);
-#else
-				subagentx_log_sac_warnx(sar->sar_sac,
-				    "%s: implied can only be used on strings "
-				    "of dynamic length", __func__);
-				errno = EINVAL;
-				return NULL;
-#endif
-			}
-		} else if (lsai->sai_vb.avb_type == AGENTX_DATA_TYPE_OID) {
-			if (lsai->sai_vb.avb_data.avb_oid.aoi_idlen != 0) {
-#ifdef AGENTX_DEBUG
-				subagentx_log_sac_fatalx(sar->sar_sac,
-				    "%s: implied can only be used on oids of "
-				    "dynamic length", __func__);
-#else
-				subagentx_log_sac_warnx(sar->sar_sac,
-				    "%s: implied can only be used on oids of "
-				    "dynamic length", __func__);
-				errno = EINVAL;
-				return NULL;
-#endif
-			}
-		} else {
-#ifdef AGENTX_DEBUG
-			subagentx_log_sac_fatalx(sar->sar_sac, "%s: implied "
-			    "can only be set on oid and string indices",
-			    __func__);
-#else
-			subagentx_log_sac_warnx(sar->sar_sac, "%s: implied can "
-			    "only be set on oid and string indices", __func__);
-			errno = EINVAL;
-			return NULL;
-#endif
-		}
-	}
-
-	ready = sar->sar_cstate == SA_CSTATE_OPEN;
-	if ((sao = calloc(1, sizeof(*sao))) == NULL)
-		return NULL;
-	sao->sao_sar = sar;
-	bcopy(&(sao_search.sao_oid), &(sao->sao_oid), sizeof(sao->sao_oid));
-	for (i = 0; i < sailen; i++) {
-		sao->sao_index[i] = sai[i];
-		if (sai[i]->sai_objectlen == sai[i]->sai_objectsize) {
-			tsao = recallocarray(sai[i]->sai_object,
-			    sai[i]->sai_objectlen, sai[i]->sai_objectlen + 1,
-			    sizeof(*sai[i]->sai_object));
-			if (tsao == NULL) {
-				free(sao);
-				return NULL;
-			}
-			sai[i]->sai_object = tsao;
-			sai[i]->sai_objectsize = sai[i]->sai_objectlen + 1;
-		}
-		for (j = 0; j < sai[i]->sai_objectlen; j++) {
-			if (agentx_oid_cmp(&(sao->sao_oid),
-			    &(sai[i]->sai_object[j]->sao_oid)) < 0) {
-				memmove(&(sai[i]->sai_object[j + 1]),
-				    &(sai[i]->sai_object[j]),
-				    sizeof(*(sai[i]->sai_object)) *
-				    (sai[i]->sai_objectlen - j));
-				break;
-			}
-		}
-		sai[i]->sai_object[j] = sao;
-		sai[i]->sai_objectlen++;
-		if (sai[i]->sai_cstate != SA_CSTATE_OPEN)
-			ready = 0;
-	}
-	sao->sao_indexlen = sailen;
-	sao->sao_implied = implied;
-	sao->sao_timeout = 0;
-	sao->sao_lock = 0;
-	sao->sao_get = get;
-	sao->sao_cstate = SA_CSTATE_CLOSE;
-	sao->sao_dstate = SA_DSTATE_OPEN;
-
-	TAILQ_INSERT_TAIL(&(sar->sar_objects), sao, sao_sar_objects);
-	RB_INSERT(sac_objects, &(sar->sar_sac->sac_objects), sao);
-
-	if (ready)
-		subagentx_object_start(sao);
-
-	return sao;
-}
-
-static int
-subagentx_object_start(struct subagentx_object *sao)
-{
-	struct subagentx_region *sar = sao->sao_sar;
-	struct subagentx_context *sac = sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	struct agentx_oid oid;
-	char oids[1024];
-	size_t i;
-	int needregister = 0;
-	uint32_t packetid;
-	uint8_t flags = AGENTX_PDU_FLAG_INSTANCE_REGISTRATION;
-
-#ifdef AGENTX_DEBUG
-	if (sar->sar_cstate != SA_CSTATE_OPEN ||
-	    sao->sao_cstate != SA_CSTATE_CLOSE ||
-	    sao->sao_dstate != SA_DSTATE_OPEN)
-		subagentx_log_sac_fatalx(sac,
-		    "%s: unexpected object registration", __func__);
-#endif
-
-	if (sao->sao_timeout != 0)
-		needregister = 1;
-	for (i = 0; i < sao->sao_indexlen; i++) {
-		if (sao->sao_index[i]->sai_cstate != SA_CSTATE_OPEN)
-			return 0;
-		if (sao->sao_index[i]->sai_type != SAI_TYPE_DYNAMIC)
-			needregister = 1;
-	}
-	if (!needregister) {
-		sao->sao_cstate = SA_CSTATE_WAITOPEN;
-		subagentx_object_finalize(NULL, sao);
-		return 0;
-	}
-
-	bcopy(&(sao->sao_oid), &(oid), sizeof(oid));
-	for (i = 0; i < sao->sao_indexlen; i++) {
-		if (sao->sao_index[i]->sai_type == SAI_TYPE_DYNAMIC) {
-			flags = 0;
-			break;
-		}
-#ifdef AGENTX_DEBUG
-		if (sao->sao_index[i]->sai_vb.avb_type !=
-		    AGENTX_DATA_TYPE_INTEGER)
-			subagentx_log_sac_fatalx(sac,
-			    "%s: Unsupported allocated index type", __func__);
-#endif
-		oid.aoi_id[oid.aoi_idlen++] =
-		    sao->sao_index[i]->sai_vb.avb_data.avb_uint32;
-	}
-	packetid = agentx_register(sa->sa_ax, flags, sas->sas_id,
-	    SUBAGENTX_CONTEXT_CTX(sac), sao->sao_timeout,
-	    AGENTX_PRIORITY_DEFAULT, 0, &oid, 0);
-	if (packetid == 0) {
-		subagentx_log_sac_warn(sac, "couldn't generate %s",
-		    agentx_pdutype2string(AGENTX_PDU_TYPE_REGISTER));
-		subagentx_reset(sa);
-		return -1;
-	}
-	strlcpy(oids, agentx_oid2string(&(sao->sao_oid)), sizeof(oids));
-	subagentx_log_sac_info(sac, "object %s (%s %s): opening",
-	    oids, flags ? "instance" : "region", agentx_oid2string(&(oid)));
-	sao->sao_cstate = SA_CSTATE_WAITOPEN;
-	return subagentx_request(sa, packetid, subagentx_object_finalize, sao);
-}
-
-static int
-subagentx_object_finalize(struct agentx_pdu *pdu, void *cookie)
-{
-	struct subagentx_object *sao = cookie;
-	struct subagentx_context *sac = sao->sao_sar->sar_sac;
-	struct agentx_oid oid;
-	char oids[1024];
-	size_t i;
-	uint8_t flags = 1;
-
-#ifdef AGENTX_DEBUG
-	if (sao->sao_cstate != SA_CSTATE_WAITOPEN)
-		subagentx_log_sac_fatalx(sac, "%s: not expecting object open",
-		    __func__);
-#endif
-
-	if (pdu == NULL) {
-		sao->sao_cstate = SA_CSTATE_OPEN;
-		return 0;
-	}
-
-	bcopy(&(sao->sao_oid), &oid, sizeof(oid));
-	for (i = 0; i < sao->sao_indexlen; i++) {
-		if (sao->sao_index[i]->sai_type == SAI_TYPE_DYNAMIC) {
-			flags = 0;
-			break;
-		}
-#ifdef AGENTX_DEBUG
-		if (sao->sao_index[i]->sai_vb.avb_type !=
-		    AGENTX_DATA_TYPE_INTEGER)
-			subagentx_log_sac_fatalx(sac,
-			    "%s: Unsupported allocated index type", __func__);
-#endif
-
-		oid.aoi_id[oid.aoi_idlen++] =
-		    sao->sao_index[i]->sai_vb.avb_data.avb_uint32;
-	}
-	strlcpy(oids, agentx_oid2string(&(sao->sao_oid)), sizeof(oids));
-
-	/*
-	 * We should only be here for table objects with registered indices.
-	 * If we fail here something is misconfigured and the admin should fix
-	 * it.
-	 */
-	if (pdu->ap_payload.ap_response.ap_error != AGENTX_PDU_ERROR_NOERROR) {
-		sao->sao_cstate = SA_CSTATE_CLOSE;
-		subagentx_log_sac_info(sac, "object %s (%s %s): %s",
-		    oids, flags ? "instance" : "region", agentx_oid2string(&oid),
-		    agentx_error2string(pdu->ap_payload.ap_response.ap_error));
-		if (sao->sao_dstate == SA_DSTATE_CLOSE)
-			return subagentx_object_close_finalize(NULL, sao);
-		return 0;
-	}
-	sao->sao_cstate = SA_CSTATE_OPEN;
-	subagentx_log_sac_info(sac, "object %s (%s %s): open", oids,
-	    flags ? "instance" : "region", agentx_oid2string(&oid));
-
-	if (sao->sao_dstate == SA_DSTATE_CLOSE)
-		return subagentx_object_close(sao);
-
-	return 0;
-}
-
-static int
-subagentx_object_lock(struct subagentx_object *sao)
-{
-	if (sao->sao_lock == UINT32_MAX) {
-		subagentx_log_sac_warnx(sao->sao_sar->sar_sac,
-		    "%s: sao_lock == %u", __func__, UINT32_MAX);
-		return -1;
-	}
-	sao->sao_lock++;
-	return 0;
-}
-
-static void
-subagentx_object_unlock(struct subagentx_object *sao)
-{
-#ifdef AGENTX_DEBUG
-	if (sao->sao_lock == 0)
-		subagentx_log_sac_fatalx(sao->sao_sar->sar_sac,
-		    "%s: sao_lock == 0", __func__);
-#endif
-	sao->sao_lock--;
-	if (sao->sao_lock == 0 && sao->sao_dstate == SA_DSTATE_CLOSE &&
-	    sao->sao_cstate == SA_CSTATE_CLOSE)
-		subagentx_object_free_finalize(sao);
-}
-
-static int
-subagentx_object_close(struct subagentx_object *sao)
-{
-	struct subagentx_context *sac = sao->sao_sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	struct agentx_oid oid;
-	char oids[1024];
-	size_t i;
-	int needclose = 0;
-	uint32_t packetid;
-	uint8_t flags = 1;
-
-#ifdef AGENTX_DEBUG
-	if (sao->sao_cstate != SA_CSTATE_OPEN)
-		subagentx_log_sac_fatalx(sac, "%s: unexpected object close",
-		    __func__);
-#endif
-
-	for (i = 0; i < sao->sao_indexlen; i++) {
-#ifdef AGENTX_DEBUG
-		if (sao->sao_index[i]->sai_cstate != SA_CSTATE_OPEN)
-			subagentx_log_sac_fatalx(sac,
-			    "%s: Object open while index closed", __func__);
-#endif
-		if (sao->sao_index[i]->sai_type != SAI_TYPE_DYNAMIC)
-			needclose = 1;
-	}
-	sao->sao_cstate = SA_CSTATE_WAITCLOSE;
-	if (sas->sas_cstate == SA_CSTATE_WAITCLOSE)
-		return 0;
-	if (!needclose) {
-		subagentx_object_close_finalize(NULL, sao);
-		return 0;
-	}
-
-	bcopy(&(sao->sao_oid), &(oid), sizeof(oid));
-	for (i = 0; i < sao->sao_indexlen; i++) {
-		if (sao->sao_index[i]->sai_type == SAI_TYPE_DYNAMIC) {
-			flags = 0;
-			break;
-		}
-#ifdef AGENTX_DEBUG
-		if (sao->sao_index[i]->sai_vb.avb_type !=
-		    AGENTX_DATA_TYPE_INTEGER)
-			subagentx_log_sac_fatalx(sac,
-			    "%s: Unsupported allocated index type", __func__);
-#endif
-		oid.aoi_id[oid.aoi_idlen++] =
-		    sao->sao_index[i]->sai_vb.avb_data.avb_uint32;
-	}
-	packetid = agentx_unregister(sa->sa_ax, sas->sas_id,
-	    SUBAGENTX_CONTEXT_CTX(sac), AGENTX_PRIORITY_DEFAULT, 0, &oid, 0);
-	if (packetid == 0) {
-		subagentx_log_sac_warn(sac, "couldn't generate %s",
-		    agentx_pdutype2string(AGENTX_PDU_TYPE_UNREGISTER));
-		subagentx_reset(sa);
-		return -1;
-	}
-	strlcpy(oids, agentx_oid2string(&(sao->sao_oid)), sizeof(oids));
-	subagentx_log_sac_info(sac, "object %s (%s %s): closing",
-	    oids, flags ? "instance" : "region", agentx_oid2string(&(oid)));
-	return subagentx_request(sa, packetid, subagentx_object_close_finalize,
-	    sao);
-}
-
-static int
-subagentx_object_close_finalize(struct agentx_pdu *pdu, void *cookie)
-{
-	struct subagentx_object *sao = cookie;
-	struct subagentx_region *sar = sao->sao_sar;
-	struct subagentx_context *sac = sar->sar_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	struct agentx_oid oid;
-	char oids[1024];
-	uint8_t flags = 1;
-	size_t i;
-
-#ifdef AGENTX_DEBUG
-	if (sao->sao_cstate != SA_CSTATE_WAITCLOSE)
-		subagentx_log_sac_fatalx(sac,
-		    "%s: unexpected object unregister", __func__);
-#endif
-
-	if (pdu != NULL) {
-		bcopy(&(sao->sao_oid), &(oid), sizeof(oid));
-		for (i = 0; i < sao->sao_indexlen; i++) {
-			if (sao->sao_index[i]->sai_type == SAI_TYPE_DYNAMIC) {
-				flags = 0;
-				break;
-			}
-#ifdef AGENTX_DEBUG
-			if (sao->sao_index[i]->sai_vb.avb_type !=
-			    AGENTX_DATA_TYPE_INTEGER)
-				subagentx_log_sac_fatalx(sac,
-				    "%s: Unsupported allocated index type",
-				    __func__);
-#endif
-			oid.aoi_id[oid.aoi_idlen++] =
-			    sao->sao_index[i]->sai_vb.avb_data.avb_uint32;
-		}
-		strlcpy(oids, agentx_oid2string(&(sao->sao_oid)), sizeof(oids));
-		if (pdu->ap_payload.ap_response.ap_error !=
-		    AGENTX_PDU_ERROR_NOERROR) {
-			subagentx_log_sac_warnx(sac,
-			    "closing object %s (%s %s): %s", oids,
-			    flags ? "instance" : "region",
-			    agentx_oid2string(&oid), agentx_error2string(
-			    pdu->ap_payload.ap_response.ap_error));
-			subagentx_reset(sa);
-			return -1;
-		}
-		subagentx_log_sac_info(sac, "object %s (%s %s): closed", oids,
-		    flags ? "instance" : "region", agentx_oid2string(&oid));
-	}
-
-	if (sao->sao_dstate == SA_DSTATE_CLOSE)
-		subagentx_object_free_finalize(sao);
-	else {
-		if (sar->sar_cstate == SA_CSTATE_OPEN)
-			if (subagentx_object_start(sao) == -1)
-				return -1;
-	}
-
-	return 0;
-}
-
-void
-subagentx_object_free(struct subagentx_object *sao)
-{
-	if (sao == NULL)
-		return;
-
-	if (sao->sao_dstate == SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sao->sao_sar->sar_sac,
-		    "%s: double free", __func__);
-
-	sao->sao_dstate = SA_DSTATE_CLOSE;
-
-	if (sao->sao_cstate == SA_CSTATE_OPEN) {
-		if (subagentx_object_close(sao) == -1)
-			return;
-	}
-	if (sao->sao_cstate == SA_CSTATE_CLOSE)
-		subagentx_object_free_finalize(sao);
-}
-
-static void
-subagentx_object_free_finalize(struct subagentx_object *sao)
-{
-#ifdef AGENTX_DEBUG
-	struct subagentx *sa = sao->sao_sar->sar_sac->sac_sas->sas_sa;
-#endif
-	size_t i, j;
-	int found;
-
-#ifdef AGENTX_DEBUG
-	if (sao->sao_dstate != SA_DSTATE_CLOSE)
-		subagentx_log_sac_fatalx(sao->sao_sar->sar_sac,
-		    "%s: unexpected free", __func__);
-#endif
-
-	if (sao->sao_lock != 0) {
-#ifdef AGENTX_DEBUG
-		if (TAILQ_EMPTY(&(sa->sa_getreqs)))
-			subagentx_log_sac_fatalx(sao->sao_sar->sar_sac,
-			    "%s: %s sao_lock == %u", __func__,
-			    agentx_oid2string(&(sao->sao_oid)), sao->sao_lock);
-#endif
-		return;
-	}
-
-	RB_REMOVE(sac_objects, &(sao->sao_sar->sar_sac->sac_objects), sao);
-	TAILQ_REMOVE(&(sao->sao_sar->sar_objects), sao, sao_sar_objects);
-
-	for (i = 0; i < sao->sao_indexlen; i++) {
-		found = 0;
-		for (j = 0; j < sao->sao_index[i]->sai_objectlen; j++) {
-			if (sao->sao_index[i]->sai_object[j] == sao)
-				found = 1;
-			if (found && j + 1 != sao->sao_index[i]->sai_objectlen)
-				sao->sao_index[i]->sai_object[j] =
-				    sao->sao_index[i]->sai_object[j + 1];
-		}
-#ifdef AGENTX_DEBUG
-		if (!found)
-			subagentx_log_sac_fatalx(sao->sao_sar->sar_sac,
-			    "%s: object not found in index", __func__);
-#endif
-		sao->sao_index[i]->sai_objectlen--;
-		if (sao->sao_index[i]->sai_dstate == SA_DSTATE_CLOSE &&
-		    sao->sao_index[i]->sai_cstate == SA_CSTATE_CLOSE)
-			subagentx_index_free_finalize(sao->sao_index[i]);
-	}
-
-	free(sao);
-}
-
-static void
-subagentx_object_reset(struct subagentx_object *sao)
-{
-	sao->sao_cstate = SA_CSTATE_CLOSE;
-
-	if (sao->sao_dstate == SA_DSTATE_CLOSE)
-		subagentx_object_free_finalize(sao);
-}
-
-static int
-subagentx_object_cmp(struct subagentx_object *o1, struct subagentx_object *o2)
-{
-	return agentx_oid_cmp(&(o1->sao_oid), &(o2->sao_oid));
-}
-
-static int
-subagentx_object_implied(struct subagentx_object *sao,
-    struct subagentx_index *sai)
-{
-	size_t i = 0;
-
-	for (i = 0; i < sao->sao_indexlen; i++) {
-		if (sao->sao_index[i] == sai) {
-			if (sai->sai_vb.avb_data.avb_ostring.aos_slen != 0)
-				return 1;
-			else if (i == sao->sao_indexlen - 1)
-				return sao->sao_implied;
-			return 0;
-		}
-	}
-#ifdef AGENTX_DEBUG
-	subagentx_log_sac_fatalx(sao->sao_sar->sar_sac, "%s: unsupported index",
-	    __func__);
-#endif
-	return 0;
-}
-
-static void
-subagentx_get_start(struct subagentx_context *sac, struct agentx_pdu *pdu)
-{
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	struct subagentx_get *sag, tsag;
-	struct agentx_pdu_searchrangelist *srl;
-	char *logmsg = NULL;
-	size_t i, j;
-	int fail = 0;
-
-	if ((sag = calloc(1, sizeof(*sag))) == NULL) {
-		tsag.sag_sessionid = pdu->ap_header.aph_sessionid;
-		tsag.sag_transactionid = pdu->ap_header.aph_transactionid;
-		tsag.sag_packetid = pdu->ap_header.aph_packetid;
-		tsag.sag_context_default = sac->sac_name_default;
-		tsag.sag_fd = sac->sac_sas->sas_sa->sa_fd;
-		subagentx_log_sag_warn(&tsag, "Couldn't parse request");
-		subagentx_reset(sa);
-		return;
-	}
-
-	sag->sag_sessionid = pdu->ap_header.aph_sessionid;
-	sag->sag_transactionid = pdu->ap_header.aph_transactionid;
-	sag->sag_packetid = pdu->ap_header.aph_packetid;
-	sag->sag_context_default = sac->sac_name_default;
-	sag->sag_fd = sac->sac_sas->sas_sa->sa_fd;
-	if (!sac->sac_name_default) {
-		sag->sag_context.aos_string =
-		    (unsigned char *)strdup((char *)sac->sac_name.aos_string);
-		if (sag->sag_context.aos_string == NULL) {
-			subagentx_log_sag_warn(sag, "Couldn't parse request");
-			free(sag);
-			subagentx_reset(sa);
-			return;
-		}
-	}
-	sag->sag_context.aos_slen = sac->sac_name.aos_slen;
-	sag->sag_type = pdu->ap_header.aph_type;
-	sag->sag_sac = sac;
-	TAILQ_INSERT_TAIL(&(sa->sa_getreqs), sag, sag_sa_getreqs);
-	if (sag->sag_type == AGENTX_PDU_TYPE_GET ||
-	    sag->sag_type == AGENTX_PDU_TYPE_GETNEXT) {
-		srl = &(pdu->ap_payload.ap_srl);
-		sag->sag_nvarbind = srl->ap_nsr;
-	} else {
-		sag->sag_nonrep = pdu->ap_payload.ap_getbulk.ap_nonrep;
-		sag->sag_maxrep = pdu->ap_payload.ap_getbulk.ap_maxrep;
-		srl = &(pdu->ap_payload.ap_getbulk.ap_srl);
-		sag->sag_nvarbind = ((srl->ap_nsr - sag->sag_nonrep) *
-		    sag->sag_maxrep) + sag->sag_nonrep;
-	}
-
-	if ((sag->sag_varbind = calloc(sag->sag_nvarbind,
-	    sizeof(*(sag->sag_varbind)))) == NULL) {
-		subagentx_log_sag_warn(sag, "Couldn't parse request");
-		subagentx_get_free(sag);
-		subagentx_reset(sa);
-		return;
-	}
-
-	/* XXX net-snmp doesn't use getbulk, so untested */
-	/* Two loops: varbind after needs to be initialized */
-	for (i = 0; i < srl->ap_nsr; i++) {
-		if (i < sag->sag_nonrep ||
-		    sag->sag_type != AGENTX_PDU_TYPE_GETBULK)
-			j = i;
-		else if (sag->sag_maxrep == 0)
-			break;
-		else
-			j = (sag->sag_maxrep * i) + sag->sag_nonrep;
-		bcopy(&(srl->ap_sr[i].asr_start),
-		    &(sag->sag_varbind[j].sav_vb.avb_oid),
-		    sizeof(srl->ap_sr[i].asr_start));
-		bcopy(&(srl->ap_sr[i].asr_start),
-		    &(sag->sag_varbind[j].sav_start),
-		    sizeof(srl->ap_sr[i].asr_start));
-		bcopy(&(srl->ap_sr[i].asr_stop),
-		    &(sag->sag_varbind[j].sav_end),
-		    sizeof(srl->ap_sr[i].asr_stop));
-		sag->sag_varbind[j].sav_initialized = 1;
-		sag->sag_varbind[j].sav_sag = sag;
-		sag->sag_varbind[j].sav_include =
-		    srl->ap_sr[i].asr_start.aoi_include;
-		if (j == 0)
-			fail |= subagentx_strcat(&logmsg, " {");
-		else
-			fail |= subagentx_strcat(&logmsg, ",{");
-		fail |= subagentx_strcat(&logmsg,
-		    agentx_oid2string(&(srl->ap_sr[i].asr_start)));
-		if (srl->ap_sr[i].asr_start.aoi_include)
-			fail |= subagentx_strcat(&logmsg, " (inclusive)");
-		if (srl->ap_sr[i].asr_stop.aoi_idlen != 0) {
-			fail |= subagentx_strcat(&logmsg, " - ");
-			fail |= subagentx_strcat(&logmsg,
-			    agentx_oid2string(&(srl->ap_sr[i].asr_stop)));
-		}
-		fail |= subagentx_strcat(&logmsg, "}");
-		if (fail) {
-			subagentx_log_sag_warn(sag, "Couldn't parse request");
-			free(logmsg);
-			subagentx_get_free(sag);
-			subagentx_reset(sa);
-			return;
-		}
-	}
-
-	subagentx_log_sag_debug(sag, "%s:%s",
-	    agentx_pdutype2string(sag->sag_type), logmsg);
-	free(logmsg);
-
-	for (i = 0; i < srl->ap_nsr; i++) {
-		if (i < sag->sag_nonrep ||
-		    sag->sag_type != AGENTX_PDU_TYPE_GETBULK)
-			j = i;
-		else if (sag->sag_maxrep == 0)
-			break;
-		else
-			j = (sag->sag_maxrep * i) + sag->sag_nonrep;
-		subagentx_varbind_start(&(sag->sag_varbind[j]));
-	}
-}
-
-static void
-subagentx_get_finalize(struct subagentx_get *sag)
-{
-	struct subagentx_context *sac = sag->sag_sac;
-	struct subagentx_session *sas = sac->sac_sas;
-	struct subagentx *sa = sas->sas_sa;
-	size_t i, j, nvarbind = 0;
-	uint16_t error = 0, index = 0;
-	struct agentx_varbind *vbl;
-	char *logmsg = NULL;
-	int fail = 0;
-
-	for (i = 0; i < sag->sag_nvarbind; i++) {
-		if (sag->sag_varbind[i].sav_initialized) {
-			if (sag->sag_varbind[i].sav_vb.avb_type == 0)
-				return;
-			nvarbind++;
-		}
-	}
-
-	if (sag->sag_sac == NULL) {
-		subagentx_get_free(sag);
-		return;
-	}
-
-	if ((vbl = calloc(nvarbind, sizeof(*vbl))) == NULL) {
-		subagentx_log_sag_warn(sag, "Couldn't parse request");
-		subagentx_get_free(sag);
-		subagentx_reset(sa);
-		return;
-	}
-	for (i = 0, j = 0; i < sag->sag_nvarbind; i++) {
-		if (sag->sag_varbind[i].sav_initialized) {
-			memcpy(&(vbl[j]), &(sag->sag_varbind[i].sav_vb),
-			    sizeof(*vbl));
-			if (error == 0 && sag->sag_varbind[i].sav_error !=
-			    AGENTX_PDU_ERROR_NOERROR) {
-				error = sag->sag_varbind[i].sav_error;
-				index = j + 1;
-			}
-			if (j == 0)
-				fail |= subagentx_strcat(&logmsg, " {");
-			else
-				fail |= subagentx_strcat(&logmsg, ",{");
-			fail |= subagentx_strcat(&logmsg,
-			    agentx_varbind2string(&(vbl[j])));
-			if (sag->sag_varbind[i].sav_error !=
-			    AGENTX_PDU_ERROR_NOERROR) {
-				fail |= subagentx_strcat(&logmsg, "(");
-				fail |= subagentx_strcat(&logmsg,
-				    agentx_error2string(
-				    sag->sag_varbind[i].sav_error));
-				fail |= subagentx_strcat(&logmsg, ")");
-			}
-			fail |= subagentx_strcat(&logmsg, "}");
-			if (fail) {
-				subagentx_log_sag_warn(sag,
-				    "Couldn't parse request");
-				free(logmsg);
-				subagentx_get_free(sag);
-				return;
-			}
-			j++;
-		}
-	}
-	subagentx_log_sag_debug(sag, "response:%s", logmsg);
-	free(logmsg);
-
-	if (agentx_response(sa->sa_ax, sas->sas_id, sag->sag_transactionid,
-	    sag->sag_packetid, SUBAGENTX_CONTEXT_CTX(sac), 0, error, index,
-	    vbl, nvarbind) == -1) {
-		subagentx_log_sag_warn(sag, "Couldn't parse request");
-		subagentx_reset(sa);
-	} else
-		subagentx_wantwrite(sa, sa->sa_fd);
-	free(vbl);
-	subagentx_get_free(sag);
-}
-
-void
-subagentx_get_free(struct subagentx_get *sag)
-{
-	struct subagentx_varbind *sav;
-	struct subagentx_object *sao;
-	struct subagentx *sa = sag->sag_sac->sac_sas->sas_sa;
-	struct subagentx_varbind_index *index;
-	size_t i, j;
-
-	if (sag->sag_sac != NULL)
-		TAILQ_REMOVE(&(sa->sa_getreqs), sag, sag_sa_getreqs);
-
-	for (i = 0; i < sag->sag_nvarbind; i++) {
-		sav = &(sag->sag_varbind[i]);
-		for (j = 0; sav->sav_sao != NULL &&
-		    j < sav->sav_sao->sao_indexlen; j++) {
-			sao = sav->sav_sao;
-			index = &(sav->sav_index[j]);
-			if (sao->sao_index[j]->sai_vb.avb_type ==
-			    AGENTX_DATA_TYPE_OCTETSTRING ||
-			    sao->sao_index[j]->sai_vb.avb_type ==
-			    AGENTX_DATA_TYPE_IPADDRESS)
-				free(index->sav_idata.avb_ostring.aos_string);
-		}
-		agentx_varbind_free(&(sag->sag_varbind[i].sav_vb));
-	}
-
-	free(sag->sag_context.aos_string);
-	free(sag->sag_varbind);
-	free(sag);
-}
-
-static void
-subagentx_varbind_start(struct subagentx_varbind *sav)
-{
-	struct subagentx_get *sag = sav->sav_sag;
-	struct subagentx_context *sac = sag->sag_sac;
-	struct subagentx_object *sao, sao_search;
-	struct subagentx_varbind_index *index;
-	struct subagentx_index *sai;
-	struct agentx_oid *oid;
-	union agentx_data *data;
-	struct in_addr *ipaddress;
-	unsigned char *ipbytes;
-	size_t i, j, k;
-	int overflow = 0, dynamic;
-
-#ifdef AGENTX_DEBUG
-	if (!sav->sav_initialized)
-		subagentx_log_sag_fatalx(sav->sav_sag,
-		    "%s: sav_initialized not set", __func__);
-#endif
-
-	bcopy(&(sav->sav_vb.avb_oid), &(sao_search.sao_oid),
-	    sizeof(sao_search.sao_oid));
-
-	do {
-		sao = RB_FIND(sac_objects, &(sac->sac_objects), &sao_search);
-		if (sao_search.sao_oid.aoi_idlen > 0)
-			sao_search.sao_oid.aoi_idlen--;
-	} while (sao == NULL && sao_search.sao_oid.aoi_idlen > 0);
-	if (sao == NULL || sao->sao_cstate != SA_CSTATE_OPEN) {
-		sav->sav_include = 1;
-		if (sav->sav_sag->sag_type == AGENTX_PDU_TYPE_GET) {
-			subagentx_varbind_nosuchobject(sav);
-			return;
-		}
-		bcopy(&(sav->sav_vb.avb_oid), &(sao_search.sao_oid),
-		    sizeof(sao_search.sao_oid));
-		sao = RB_NFIND(sac_objects, &(sac->sac_objects), &sao_search);
-getnext:
-		while (sao != NULL && sao->sao_cstate != SA_CSTATE_OPEN)
-			sao = RB_NEXT(sac_objects, &(sac->sac_objects), sao);
-		if (sao == NULL) {
-			subagentx_varbind_endofmibview(sav);
-			return;
-		}
-		bcopy(&(sao->sao_oid), &(sav->sav_vb.avb_oid),
-		    sizeof(sao->sao_oid));
-	}
-	sav->sav_sao = sao;
-	sav->sav_indexlen = sao->sao_indexlen;
-	if (subagentx_object_lock(sao) == -1) {
-		subagentx_varbind_error_type(sav,
-		    AGENTX_PDU_ERROR_PROCESSINGERROR, 1);
-		return;
-	}
-
-	oid = &(sav->sav_vb.avb_oid);
-	if (sao->sao_indexlen == 0) {
-		if (sav->sav_sag->sag_type == AGENTX_PDU_TYPE_GET) {
-			if (oid->aoi_idlen != sao->sao_oid.aoi_idlen + 1 ||
-			    oid->aoi_id[oid->aoi_idlen - 1] != 0) {
-				subagentx_varbind_nosuchinstance(sav);
-				return;
-			}
-		} else {
-			if (oid->aoi_idlen == sao->sao_oid.aoi_idlen) {
-				oid->aoi_id[oid->aoi_idlen++] = 0;
-				sav->sav_include = 1;
-			} else {
-				sav->sav_sao = NULL;
-				subagentx_object_unlock(sao);
-				sao = RB_NEXT(sac_objects, &(sac->sac_objects),
-				    sao);
-				goto getnext;
-			}
-		}
-	}
-	j = sao->sao_oid.aoi_idlen;
-/*
- * We can't trust what the client gives us, so sometimes we need to map it to
- * index type.
- * - AGENTX_PDU_TYPE_GET: we always return AGENTX_DATA_TYPE_NOSUCHINSTANCE
- * - AGENTX_PDU_TYPE_GETNEXT:
- *   - Missing OID digits to match indices will result in the indices to be NUL-
- *     initialized and the request type will be set to
- *     SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE
- *   - An overflow can happen on AGENTX_DATA_TYPE_OCTETSTRING and
- *     AGENTX_DATA_TYPE_IPADDRESS. This results in request type being set to
- *     SUBAGENTX_REQUEST_TYPE_GETNEXT and will set the index to its maximum
- *     value:
- *     - AGENTX_DATA_TYPE_INTEGER: UINT32_MAX
- *     - AGENTX_DATA_TYPE_OCTETSTRING: aos_slen = UINT32_MAX and
- *       aos_string = NULL
- *     - AGENTX_DATA_TYPE_OID: aoi_idlen = UINT32_MAX and aoi_id[x] = UINT32_MAX
- *     - AGENTX_DATA_TYPE_IPADDRESS: 255.255.255.255
- */
-	for (dynamic = 0, i = 0; i < sao->sao_indexlen; i++) {
-		index = &(sav->sav_index[i]);
-		index->sav_sai = sao->sao_index[i];
-		data = &(index->sav_idata);
-		if (sao->sao_index[i]->sai_type == SAI_TYPE_DYNAMIC)
-			dynamic = 1;
-		if (j >= sav->sav_vb.avb_oid.aoi_idlen && !overflow &&
-		    sao->sao_index[i]->sai_type == SAI_TYPE_DYNAMIC)
-			continue;
-		switch (sao->sao_index[i]->sai_vb.avb_type) {
-		case AGENTX_DATA_TYPE_INTEGER:
-/* Dynamic index: normal copy paste */
-			if (sao->sao_index[i]->sai_type == SAI_TYPE_DYNAMIC) {
-				data->avb_uint32 = overflow ?
-				    UINT32_MAX : sav->sav_vb.avb_oid.aoi_id[j];
-				j++;
-				index->sav_idatacomplete = 1;
-				break;
-			}
-			sai = sao->sao_index[i];
-/* With a GET-request we need an exact match */
-			if (sav->sav_sag->sag_type == AGENTX_PDU_TYPE_GET) {
-				if (sai->sai_vb.avb_data.avb_uint32 !=
-				    sav->sav_vb.avb_oid.aoi_id[j]) {
-					subagentx_varbind_nosuchinstance(sav);
-					return;
-				}
-				index->sav_idatacomplete = 1;
-				j++;
-				break;
-			}
-/* A higher value automatically moves us to the next value */
-			if (overflow ||
-			    sav->sav_vb.avb_oid.aoi_id[j] >
-			    sai->sai_vb.avb_data.avb_uint32) {
-/* If we're !dynamic up until now the rest of the oid doesn't matter */
-				if (!dynamic) {
-					subagentx_varbind_endofmibview(sav);
-					return;
-				}
-/*
- * Else we just pick the max value and make sure we don't return
- * SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE
- */
-				data->avb_uint32 = UINT32_MAX;
-				index->sav_idatacomplete = 1;
-				overflow = 1;
-				j++;
-				break;
-/*
- * A lower value automatically moves to the set value and counts as a short oid
- */
-			} else if (sav->sav_vb.avb_oid.aoi_id[j] <
-			    sai->sai_vb.avb_data.avb_uint32) {
-				data->avb_uint32 =
-				    sai->sai_vb.avb_data.avb_uint32;
-				j = sav->sav_vb.avb_oid.aoi_idlen;
-				break;
-			}
-/* Normal match, except we already matched overflow at higher value */
-			data->avb_uint32 = sav->sav_vb.avb_oid.aoi_id[j];
-			j++;
-			index->sav_idatacomplete = 1;
-			break;
-		case AGENTX_DATA_TYPE_OCTETSTRING:
-			if (!subagentx_object_implied(sao, index->sav_sai)) {
-				if (overflow || sav->sav_vb.avb_oid.aoi_id[j] >
-				    SUBAGENTX_OID_MAX_LEN -
-				    sav->sav_vb.avb_oid.aoi_idlen) {
-					overflow = 1;
-					data->avb_ostring.aos_slen = UINT32_MAX;
-					index->sav_idatacomplete = 1;
-					continue;
-				}
-				data->avb_ostring.aos_slen =
-				    sav->sav_vb.avb_oid.aoi_id[j++];
-			} else {
-				if (overflow) {
-					data->avb_ostring.aos_slen = UINT32_MAX;
-					index->sav_idatacomplete = 1;
-					continue;
-				}
-				data->avb_ostring.aos_slen =
-				    sav->sav_vb.avb_oid.aoi_idlen - j;
-			}
-			data->avb_ostring.aos_string =
-			    calloc(data->avb_ostring.aos_slen + 1, 1);
-			if (data->avb_ostring.aos_string == NULL) {
-				subagentx_log_sag_warn(sag,
-				    "Failed to bind string index");
-				subagentx_varbind_error_type(sav,
-				    AGENTX_PDU_ERROR_PROCESSINGERROR, 1);
-				return;
-			}
-			for (k = 0; k < data->avb_ostring.aos_slen; k++, j++) {
-				if (!overflow &&
-				    j == sav->sav_vb.avb_oid.aoi_idlen)
-					break;
-
-				if (sav->sav_vb.avb_oid.aoi_id[j] > 255)
-					overflow = 1;
-
-				data->avb_ostring.aos_string[k] = overflow ?
-				    0xff : sav->sav_vb.avb_oid.aoi_id[j];
-			}
-			if (k == data->avb_ostring.aos_slen)
-				index->sav_idatacomplete = 1;
-			break;
-		case AGENTX_DATA_TYPE_OID:
-			if (!subagentx_object_implied(sao, index->sav_sai)) {
-				if (overflow || sav->sav_vb.avb_oid.aoi_id[j] >
-				    SUBAGENTX_OID_MAX_LEN -
-				    sav->sav_vb.avb_oid.aoi_idlen) {
-					overflow = 1;
-					data->avb_oid.aoi_idlen = UINT32_MAX;
-					index->sav_idatacomplete = 1;
-					continue;
-				}
-				data->avb_oid.aoi_idlen =
-				    sav->sav_vb.avb_oid.aoi_id[j++];
-			} else {
-				if (overflow) {
-					data->avb_oid.aoi_idlen = UINT32_MAX;
-					index->sav_idatacomplete = 1;
-					continue;
-				}
-				data->avb_oid.aoi_idlen =
-				    sav->sav_vb.avb_oid.aoi_idlen - j;
-			}
-			for (k = 0; k < data->avb_oid.aoi_idlen; k++, j++) {
-				if (!overflow &&
-				    j == sav->sav_vb.avb_oid.aoi_idlen) {
-					data->avb_oid.aoi_id[k] = 0;
-					continue;
-				}
-				data->avb_oid.aoi_id[k] = overflow ?
-				    UINT32_MAX : sav->sav_vb.avb_oid.aoi_id[j];
-			}
-			if (j <= sav->sav_vb.avb_oid.aoi_idlen)
-				index->sav_idatacomplete = 1;
-			break;
-		case AGENTX_DATA_TYPE_IPADDRESS:
-			ipaddress = calloc(1, sizeof(*ipaddress));
-			if (ipaddress == NULL) {
-				subagentx_log_sag_warn(sag,
-				    "Failed to bind ipaddress index");
-				subagentx_varbind_error_type(sav,
-				    AGENTX_PDU_ERROR_PROCESSINGERROR, 1);
-				return;
-			}
-			ipbytes = (unsigned char *)ipaddress;
-			for (k = 0; k < 4; k++, j++) {
-				if (!overflow &&
-				    j == sav->sav_vb.avb_oid.aoi_idlen)
-					break;
-
-				if (sav->sav_vb.avb_oid.aoi_id[j] > 255)
-					overflow = 1;
-
-				ipbytes[k] = overflow ? 255 :
-				    sav->sav_vb.avb_oid.aoi_id[j];
-			}
-			if (j <= sav->sav_vb.avb_oid.aoi_idlen)
-				index->sav_idatacomplete = 1;
-			data->avb_ostring.aos_slen = sizeof(*ipaddress);
-			data->avb_ostring.aos_string =
-			    (unsigned char *)ipaddress;
-			break;
-		default:
-#ifdef AGENTX_DEBUG
-			subagentx_log_sag_fatalx(sag,
-			    "%s: unexpected index type", __func__);
-#else
-			subagentx_log_sag_warnx(sag,
-			    "%s: unexpected index type", __func__);
-			subagentx_varbind_error_type(sav,
-			    AGENTX_PDU_ERROR_PROCESSINGERROR, 1);
-			return;
-#endif
-		}
-	}
-	if (sav->sav_sag->sag_type == AGENTX_PDU_TYPE_GET) {
-		if ((sao->sao_indexlen > 0 &&
-		    !sav->sav_index[sao->sao_indexlen - 1].sav_idatacomplete) ||
-		    j != sav->sav_vb.avb_oid.aoi_idlen || overflow) {
-			subagentx_varbind_nosuchinstance(sav);
-			return;
-		}
-	}
-
-	if (overflow || j > sav->sav_vb.avb_oid.aoi_idlen)
-		sav->sav_include = 0;
-
-/*
- * SUBAGENTX_REQUEST_TYPE_GETNEXT request can !dynamic objects can just move to
- * the next object
- */
-	if (subagentx_varbind_request(sav) == SUBAGENTX_REQUEST_TYPE_GETNEXT &&
-	    !dynamic) {
-		subagentx_varbind_endofmibview(sav);
-		return;
-	}
-
-	sao->sao_get(sav);
-}
-
-void
-subagentx_varbind_integer(struct subagentx_varbind *sav, uint32_t value)
-{
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_INTEGER;
-	sav->sav_vb.avb_data.avb_uint32 = value;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_string(struct subagentx_varbind *sav, const char *value)
-{
-	subagentx_varbind_nstring(sav, (const unsigned char *)value,
-	    strlen(value));
-}
-
-void
-subagentx_varbind_nstring(struct subagentx_varbind *sav,
-    const unsigned char *value, size_t slen)
-{
-	sav->sav_vb.avb_data.avb_ostring.aos_string = malloc(slen);
-	if (sav->sav_vb.avb_data.avb_ostring.aos_string == NULL) {
-		subagentx_log_sag_warn(sav->sav_sag, "Couldn't bind string");
-		subagentx_varbind_error_type(sav,
-		    AGENTX_PDU_ERROR_PROCESSINGERROR, 1);
-		return;
-	}
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_OCTETSTRING;
-	memcpy(sav->sav_vb.avb_data.avb_ostring.aos_string, value, slen);
-	sav->sav_vb.avb_data.avb_ostring.aos_slen = slen;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_printf(struct subagentx_varbind *sav, const char *fmt, ...)
-{
-	va_list ap;
-	int r;
-
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_OCTETSTRING;
-	va_start(ap, fmt);
-	r = vasprintf((char **)&(sav->sav_vb.avb_data.avb_ostring.aos_string),
-	    fmt, ap);
-	va_end(ap);
-	if (r == -1) {
-		sav->sav_vb.avb_data.avb_ostring.aos_string = NULL;
-		subagentx_log_sag_warn(sav->sav_sag, "Couldn't bind string");
-		subagentx_varbind_error_type(sav,
-		    AGENTX_PDU_ERROR_PROCESSINGERROR, 1);
-		return;
-	}
-	sav->sav_vb.avb_data.avb_ostring.aos_slen = r;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_null(struct subagentx_varbind *sav)
-{
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_NULL;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_oid(struct subagentx_varbind *sav, const uint32_t oid[],
-    size_t oidlen)
-{
-	size_t i;
-
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_OID;
-
-	for (i = 0; i < oidlen; i++)
-		sav->sav_vb.avb_data.avb_oid.aoi_id[i] = oid[i];
-	sav->sav_vb.avb_data.avb_oid.aoi_idlen = oidlen;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_object(struct subagentx_varbind *sav,
-    struct subagentx_object *sao)
-{
-	subagentx_varbind_oid(sav, sao->sao_oid.aoi_id,
-	    sao->sao_oid.aoi_idlen);
-}
-
-void
-subagentx_varbind_index(struct subagentx_varbind *sav,
-    struct subagentx_index *sai)
-{
-	subagentx_varbind_oid(sav, sai->sai_vb.avb_oid.aoi_id,
-	    sai->sai_vb.avb_oid.aoi_idlen);
-}
-
-
-void
-subagentx_varbind_ipaddress(struct subagentx_varbind *sav,
-    const struct in_addr *value)
-{
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_IPADDRESS;
-	sav->sav_vb.avb_data.avb_ostring.aos_string = malloc(4);
-	if (sav->sav_vb.avb_data.avb_ostring.aos_string == NULL) {
-		subagentx_log_sag_warn(sav->sav_sag, "Couldn't bind ipaddress");
-		subagentx_varbind_error_type(sav,
-		    AGENTX_PDU_ERROR_PROCESSINGERROR, 1);
-		return;
-	}
-	memcpy(sav->sav_vb.avb_data.avb_ostring.aos_string, value, 4);
-	sav->sav_vb.avb_data.avb_ostring.aos_slen = 4;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_counter32(struct subagentx_varbind *sav, uint32_t value)
-{
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_COUNTER32;
-	sav->sav_vb.avb_data.avb_uint32 = value;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_gauge32(struct subagentx_varbind *sav, uint32_t value)
-{
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_GAUGE32;
-	sav->sav_vb.avb_data.avb_uint32 = value;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_timeticks(struct subagentx_varbind *sav, uint32_t value)
-{
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_TIMETICKS;
-	sav->sav_vb.avb_data.avb_uint32 = value;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_opaque(struct subagentx_varbind *sav, const char *string,
-    size_t strlen)
-{
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_OPAQUE;
-	sav->sav_vb.avb_data.avb_ostring.aos_string = malloc(strlen);
-	if (sav->sav_vb.avb_data.avb_ostring.aos_string == NULL) {
-		subagentx_log_sag_warn(sav->sav_sag, "Couldn't bind opaque");
-		subagentx_varbind_error_type(sav,
-		    AGENTX_PDU_ERROR_PROCESSINGERROR, 1);
-		return;
-	}
-	memcpy(sav->sav_vb.avb_data.avb_ostring.aos_string, string, strlen);
-	sav->sav_vb.avb_data.avb_ostring.aos_slen = strlen;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_counter64(struct subagentx_varbind *sav, uint64_t value)
-{
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_COUNTER64;
-	sav->sav_vb.avb_data.avb_uint64 = value;
-
-	subagentx_varbind_finalize(sav);
-}
-
-void
-subagentx_varbind_notfound(struct subagentx_varbind *sav)
-{
-	if (sav->sav_indexlen == 0) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sag_fatalx(sav->sav_sag, "%s invalid call",
-		    __func__);
-#else
-		subagentx_log_sag_warnx(sav->sav_sag, "%s invalid call",
-		    __func__);
-		subagentx_varbind_error_type(sav,
-		    AGENTX_PDU_ERROR_GENERR, 1);
-#endif
-	} else if (sav->sav_sag->sag_type == AGENTX_PDU_TYPE_GET)
-		subagentx_varbind_nosuchinstance(sav);
-	else
-		subagentx_varbind_endofmibview(sav);
-}
-
-void
-subagentx_varbind_error(struct subagentx_varbind *sav)
-{
-	subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 1);
-}
-
-static void
-subagentx_varbind_error_type(struct subagentx_varbind *sav,
-    enum agentx_pdu_error error, int done)
-{
-	if (sav->sav_error == AGENTX_PDU_ERROR_NOERROR) {
-		sav->sav_error = error;
-	}
-
-	if (done) {
-		sav->sav_vb.avb_type = AGENTX_DATA_TYPE_NULL;
-
-		subagentx_varbind_finalize(sav);
-	}
-}
-
-static void
-subagentx_varbind_finalize(struct subagentx_varbind *sav)
-{
-	struct subagentx_get *sag = sav->sav_sag;
-	struct agentx_oid oid;
-	union agentx_data *data;
-	size_t i, j;
-	int cmp;
-
-	if (sav->sav_error != AGENTX_PDU_ERROR_NOERROR) {
-		bcopy(&(sav->sav_start), &(sav->sav_vb.avb_oid),
-		    sizeof(sav->sav_start));
-		goto done;
-	}
-	bcopy(&(sav->sav_sao->sao_oid), &oid, sizeof(oid));
-	if (sav->sav_indexlen == 0)
-		agentx_oid_add(&oid, 0);
-	for (i = 0; i < sav->sav_indexlen; i++) {
-		data = &(sav->sav_index[i].sav_idata);
-		switch (sav->sav_index[i].sav_sai->sai_vb.avb_type) {
-		case AGENTX_DATA_TYPE_INTEGER:
-			if (agentx_oid_add(&oid, data->avb_uint32) == -1)
-				goto fail;
-			break;
-		case AGENTX_DATA_TYPE_OCTETSTRING:
-			if (!subagentx_object_implied(sav->sav_sao,
-			    sav->sav_index[i].sav_sai)) {
-				if (agentx_oid_add(&oid,
-				    data->avb_ostring.aos_slen) == -1)
-					goto fail;
-			}
-			for (j = 0; j < data->avb_ostring.aos_slen; j++) {
-				if (agentx_oid_add(&oid,
-				    (uint8_t)data->avb_ostring.aos_string[j]) ==
-				    -1)
-					goto fail;
-			}
-			break;
-		case AGENTX_DATA_TYPE_OID:
-			if (!subagentx_object_implied(sav->sav_sao,
-			    sav->sav_index[i].sav_sai)) {
-				if (agentx_oid_add(&oid,
-				    data->avb_oid.aoi_idlen) == -1)
-					goto fail;
-			}
-			for (j = 0; j < data->avb_oid.aoi_idlen; j++) {
-				if (agentx_oid_add(&oid,
-				    data->avb_oid.aoi_id[j]) == -1)
-					goto fail;
-			}
-			break;
-		case AGENTX_DATA_TYPE_IPADDRESS:
-			for (j = 0; j < 4; j++) {
-				if (agentx_oid_add(&oid,
-				    data->avb_ostring.aos_string == NULL ? 0 :
-				    (uint8_t)data->avb_ostring.aos_string[j]) ==
-				    -1)
-					goto fail;
-			}
-			break;
-		default:
-#ifdef AGENTX_DEBUG
-			subagentx_log_sag_fatalx(sag,
-			    "%s: unsupported index type", __func__);
-#else
-			bcopy(&(sav->sav_start), &(sav->sav_vb.avb_oid),
-			    sizeof(sav->sav_start));
-			sav->sav_error = AGENTX_PDU_ERROR_PROCESSINGERROR;
-			subagentx_object_unlock(sav->sav_sao);
-			subagentx_get_finalize(sav->sav_sag);
-			return;
-#endif
-		}
-	}
-	cmp = agentx_oid_cmp(&(sav->sav_vb.avb_oid), &oid);
-	if ((subagentx_varbind_request(sav) == SUBAGENTX_REQUEST_TYPE_GETNEXT &&
-	    cmp >= 0) || cmp > 0) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sag_fatalx(sag, "indices not incremented");
-#else
-		subagentx_log_sag_warnx(sag, "indices not incremented");
-		bcopy(&(sav->sav_start), &(sav->sav_vb.avb_oid),
-		    sizeof(sav->sav_start));
-		sav->sav_error = AGENTX_PDU_ERROR_GENERR;
-#endif
-	} else
-		bcopy(&oid, &(sav->sav_vb.avb_oid), sizeof(oid));
-done:
-	subagentx_object_unlock(sav->sav_sao);
-	subagentx_get_finalize(sav->sav_sag);
-	return;
-
-fail:
-	subagentx_log_sag_warnx(sag, "oid too large");
-	bcopy(&(sav->sav_start), &(sav->sav_vb.avb_oid),
-	    sizeof(sav->sav_start));
-	sav->sav_error = AGENTX_PDU_ERROR_GENERR;
-	subagentx_object_unlock(sav->sav_sao);
-	subagentx_get_finalize(sav->sav_sag);
-}
-
-static void
-subagentx_varbind_nosuchobject(struct subagentx_varbind *sav)
-{
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_NOSUCHOBJECT;
-
-	if (sav->sav_sao != NULL)
-		subagentx_object_unlock(sav->sav_sao);
-	subagentx_get_finalize(sav->sav_sag);
-}
-
-static void
-subagentx_varbind_nosuchinstance(struct subagentx_varbind *sav)
-{
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_NOSUCHINSTANCE;
-
-	if (sav->sav_sao != NULL)
-		subagentx_object_unlock(sav->sav_sao);
-	subagentx_get_finalize(sav->sav_sag);
-}
-
-static void
-subagentx_varbind_endofmibview(struct subagentx_varbind *sav)
-{
-	struct subagentx_object *sao;
-	struct agentx_varbind *vb;
-	struct subagentx_varbind_index *index;
-	size_t i;
-
-#ifdef AGENTX_DEBUG
-	if (sav->sav_sag->sag_type != AGENTX_PDU_TYPE_GETNEXT &&
-	    sav->sav_sag->sag_type != AGENTX_PDU_TYPE_GETBULK)
-		subagentx_log_sag_fatalx(sav->sav_sag,
-		    "%s: invalid request type", __func__);
-#endif
-
-	if (sav->sav_sao != NULL &&
-	    (sao = RB_NEXT(sac_objects, &(sac->sac_objects),
-	    sav->sav_sao)) != NULL &&
-	    agentx_oid_cmp(&(sao->sao_oid), &(sav->sav_end)) < 0) {
-		bcopy(&(sao->sao_oid), &(sav->sav_vb.avb_oid),
-		    sizeof(sao->sao_oid));
-		sav->sav_include = 1;
-		for (i = 0; i < sav->sav_indexlen; i++) {
-			index = &(sav->sav_index[i]);
-			vb = &(index->sav_sai->sai_vb);
-			if (vb->avb_type == AGENTX_DATA_TYPE_OCTETSTRING ||
-			    vb->avb_type == AGENTX_DATA_TYPE_IPADDRESS)
-				free(index->sav_idata.avb_ostring.aos_string);
-		}
-		bzero(&(sav->sav_index), sizeof(sav->sav_index));
-		subagentx_object_unlock(sav->sav_sao);
-		subagentx_varbind_start(sav);
-		return;
-	}
-
-	sav->sav_vb.avb_type = AGENTX_DATA_TYPE_ENDOFMIBVIEW;
-
-	if (sav->sav_sao != NULL)
-		subagentx_object_unlock(sav->sav_sao);
-	subagentx_get_finalize(sav->sav_sag);
-}
-
-enum subagentx_request_type
-subagentx_varbind_request(struct subagentx_varbind *sav)
-{
-	if (sav->sav_sag->sag_type == AGENTX_PDU_TYPE_GET)
-		return SUBAGENTX_REQUEST_TYPE_GET;
-	if (sav->sav_include ||
-	    (sav->sav_indexlen > 0 &&
-	    !sav->sav_index[sav->sav_indexlen - 1].sav_idatacomplete))
-		return SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE;
-	return SUBAGENTX_REQUEST_TYPE_GETNEXT;
-}
-
-struct subagentx_object *
-subagentx_varbind_get_object(struct subagentx_varbind *sav)
-{
-	return sav->sav_sao;
-}
-
-uint32_t
-subagentx_varbind_get_index_integer(struct subagentx_varbind *sav,
-    struct subagentx_index *sai)
-{
-	size_t i;
-
-	if (sai->sai_vb.avb_type != AGENTX_DATA_TYPE_INTEGER) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sag_fatalx(sav->sav_sag, "invalid index type");
-#else
-		subagentx_log_sag_warnx(sav->sav_sag, "invalid index type");
-		subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-		return 0;
-#endif
-	}
-
-	for (i = 0; i < sav->sav_indexlen; i++) {
-		if (sav->sav_index[i].sav_sai == sai)
-			return sav->sav_index[i].sav_idata.avb_uint32;
-	}
-#ifdef AGENTX_DEBUG
-	subagentx_log_sag_fatalx(sav->sav_sag, "invalid index");
-#else
-	subagentx_log_sag_warnx(sav->sav_sag, "invalid index");
-	subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-	return 0;
-#endif
-}
-
-const unsigned char *
-subagentx_varbind_get_index_string(struct subagentx_varbind *sav,
-    struct subagentx_index *sai, size_t *slen, int *implied)
-{
-	struct subagentx_varbind_index *index;
-	size_t i;
-
-	if (sai->sai_vb.avb_type != AGENTX_DATA_TYPE_OCTETSTRING) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sag_fatalx(sav->sav_sag, "invalid index type");
-#else
-		subagentx_log_sag_warnx(sav->sav_sag, "invalid index type");
-		subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-		*slen = 0;
-		*implied = 0;
-		return NULL;
-#endif
-	}
-
-	for (i = 0; i < sav->sav_indexlen; i++) {
-		if (sav->sav_index[i].sav_sai == sai) {
-			index = &(sav->sav_index[i]);
-			*slen = index->sav_idata.avb_ostring.aos_slen;
-			*implied = subagentx_object_implied(sav->sav_sao, sai);
-			return index->sav_idata.avb_ostring.aos_string;
-		}
-	}
-
-#ifdef AGENTX_DEBUG
-	subagentx_log_sag_fatalx(sav->sav_sag, "invalid index");
-#else
-	subagentx_log_sag_warnx(sav->sav_sag, "invalid index");
-	subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-	*slen = 0;
-	*implied = 0;
-	return NULL;
-#endif
-}
-
-const uint32_t *
-subagentx_varbind_get_index_oid(struct subagentx_varbind *sav,
-    struct subagentx_index *sai, size_t *oidlen, int *implied)
-{
-	struct subagentx_varbind_index *index;
-	size_t i;
-
-	if (sai->sai_vb.avb_type != AGENTX_DATA_TYPE_OID) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sag_fatalx(sav->sav_sag, "invalid index type");
-#else
-		subagentx_log_sag_warnx(sav->sav_sag, "invalid index type");
-		subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-		*oidlen = 0;
-		*implied = 0;
-		return NULL;
-#endif
-	}
-
-	for (i = 0; i < sav->sav_indexlen; i++) {
-		if (sav->sav_index[i].sav_sai == sai) {
-			index = &(sav->sav_index[i]);
-			*oidlen = index->sav_idata.avb_oid.aoi_idlen;
-			*implied = subagentx_object_implied(sav->sav_sao, sai);
-			return index->sav_idata.avb_oid.aoi_id;
-		}
-	}
-
-#ifdef AGENTX_DEBUG
-	subagentx_log_sag_fatalx(sav->sav_sag, "invalid index");
-#else
-	subagentx_log_sag_warnx(sav->sav_sag, "invalid index");
-	subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-	*oidlen = 0;
-	*implied = 0;
-	return NULL;
-#endif
-}
-
-const struct in_addr *
-subagentx_varbind_get_index_ipaddress(struct subagentx_varbind *sav,
-    struct subagentx_index *sai)
-{
-	static struct in_addr nuladdr = {0};
-	struct subagentx_varbind_index *index;
-	size_t i;
-
-	if (sai->sai_vb.avb_type != AGENTX_DATA_TYPE_IPADDRESS) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sag_fatalx(sav->sav_sag, "invalid index type");
-#else
-		subagentx_log_sag_warnx(sav->sav_sag, "invalid index type");
-		subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-		return NULL;
-#endif
-	}
-
-	for (i = 0; i < sav->sav_indexlen; i++) {
-		if (sav->sav_index[i].sav_sai == sai) {
-			index = &(sav->sav_index[i]);
-			if (index->sav_idata.avb_ostring.aos_string == NULL)
-				return &nuladdr;
-			return (struct in_addr *)
-			    index->sav_idata.avb_ostring.aos_string;
-		}
-	}
-
-#ifdef AGENTX_DEBUG
-	subagentx_log_sag_fatalx(sav->sav_sag, "invalid index");
-#else
-	subagentx_log_sag_warnx(sav->sav_sag, "invalid index");
-	subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-	return NULL;
-#endif
-}
-
-void
-subagentx_varbind_set_index_integer(struct subagentx_varbind *sav,
-    struct subagentx_index *sai, uint32_t value)
-{
-	size_t i;
-
-	if (sai->sai_vb.avb_type != AGENTX_DATA_TYPE_INTEGER) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sag_fatalx(sav->sav_sag, "invalid index type");
-#else
-		subagentx_log_sag_warnx(sav->sav_sag, "invalid index type");
-		subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-		return;
-#endif
-	}
-
-	for (i = 0; i < sav->sav_indexlen; i++) {
-		if (sav->sav_index[i].sav_sai == sai) {
-			if (sav->sav_sag->sag_type == AGENTX_PDU_TYPE_GET &&
-			    sav->sav_index[i].sav_idata.avb_uint32 != value) {
-#ifdef AGENTX_DEBUG
-				subagentx_log_sag_fatalx(sav->sav_sag,
-				    "can't change index on GET");
-#else
-				subagentx_log_sag_warnx(sav->sav_sag,
-				    "can't change index on GET");
-				subagentx_varbind_error_type(sav,
-				    AGENTX_PDU_ERROR_GENERR, 0);
-				return;
-#endif
-			}
-			sav->sav_index[i].sav_idata.avb_uint32 = value;
-			return;
-		}
-	}
-#ifdef AGENTX_DEBUG
-	subagentx_log_sag_fatalx(sav->sav_sag, "invalid index");
-#else
-	subagentx_log_sag_warnx(sav->sav_sag, "invalid index");
-	subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-#endif
-}
-
-void
-subagentx_varbind_set_index_string(struct subagentx_varbind *sav,
-    struct subagentx_index *sai, const char *value)
-{
-	subagentx_varbind_set_index_nstring(sav, sai,
-	    (const unsigned char *)value, strlen(value));
-}
-
-void
-subagentx_varbind_set_index_nstring(struct subagentx_varbind *sav,
-    struct subagentx_index *sai, const unsigned char *value, size_t slen)
-{
-	struct agentx_ostring *curvalue;
-	unsigned char *nstring;
-	size_t i;
-
-	if (sai->sai_vb.avb_type != AGENTX_DATA_TYPE_OCTETSTRING) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sag_fatalx(sav->sav_sag, "invalid index type");
-#else
-		subagentx_log_sag_warnx(sav->sav_sag, "invalid index type");
-		subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-		return;
-#endif
-	}
-
-	for (i = 0; i < sav->sav_indexlen; i++) {
-		if (sav->sav_index[i].sav_sai == sai) {
-			if (sai->sai_vb.avb_data.avb_ostring.aos_slen != 0 &&
-			    sai->sai_vb.avb_data.avb_ostring.aos_slen != slen) {
-#ifdef AGENTX_DEBUG
-				subagentx_log_sag_fatalx(sav->sav_sag,
-				    "invalid string length on explicit length "
-				    "string");
-#else
-				subagentx_log_sag_warnx(sav->sav_sag,
-				    "invalid string length on explicit length "
-				    "string");
-				subagentx_varbind_error_type(sav,
-				    AGENTX_PDU_ERROR_GENERR, 0);
-				return;
-#endif
-			}
-			curvalue = &(sav->sav_index[i].sav_idata.avb_ostring);
-			if (sav->sav_sag->sag_type == AGENTX_PDU_TYPE_GET &&
-			    (curvalue->aos_slen != slen ||
-			    memcmp(curvalue->aos_string, value, slen) != 0)) {
-#ifdef AGENTX_DEBUG
-				subagentx_log_sag_fatalx(sav->sav_sag,
-				    "can't change index on GET");
-#else
-				subagentx_log_sag_warnx(sav->sav_sag,
-				    "can't change index on GET");
-				subagentx_varbind_error_type(sav,
-				    AGENTX_PDU_ERROR_GENERR, 0);
-				return;
-#endif
-			}
-			if ((nstring = recallocarray(curvalue->aos_string,
-			    curvalue->aos_slen + 1, slen + 1, 1)) == NULL) {
-				subagentx_log_sag_warn(sav->sav_sag,
-				    "Failed to bind string index");
-				subagentx_varbind_error_type(sav,
-				    AGENTX_PDU_ERROR_PROCESSINGERROR, 0);
-				return;
-			}
-			curvalue->aos_string = nstring;
-			memcpy(nstring, value, slen);
-			curvalue->aos_slen = slen;
-			return;
-		}
-	}
-#ifdef AGENTX_DEBUG
-	subagentx_log_sag_fatalx(sav->sav_sag, "invalid index");
-#else
-	subagentx_log_sag_warnx(sav->sav_sag, "invalid index");
-	subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-#endif
-}
-
-void
-subagentx_varbind_set_index_oid(struct subagentx_varbind *sav,
-    struct subagentx_index *sai, const uint32_t *value, size_t oidlen)
-{
-	struct agentx_oid *curvalue, oid;
-	size_t i;
-
-	if (sai->sai_vb.avb_type != AGENTX_DATA_TYPE_OID) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sag_fatalx(sav->sav_sag, "invalid index type");
-#else
-		subagentx_log_sag_warnx(sav->sav_sag, "invalid index type");
-		subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-		return;
-#endif
-	}
-
-	for (i = 0; i < sav->sav_indexlen; i++) {
-		if (sav->sav_index[i].sav_sai == sai) {
-			if (sai->sai_vb.avb_data.avb_oid.aoi_idlen != 0 &&
-			    sai->sai_vb.avb_data.avb_oid.aoi_idlen != oidlen) {
-#ifdef AGENTX_DEBUG
-				subagentx_log_sag_fatalx(sav->sav_sag,
-				    "invalid oid length on explicit length "
-				    "oid");
-#else
-				subagentx_log_sag_warnx(sav->sav_sag,
-				    "invalid oid length on explicit length "
-				    "oid");
-				subagentx_varbind_error_type(sav,
-				    AGENTX_PDU_ERROR_GENERR, 0);
-				return;
-#endif
-			}
-			curvalue = &(sav->sav_index[i].sav_idata.avb_oid);
-			for (i = 0; i < oidlen; i++)
-				oid.aoi_id[i] = value[i];
-			oid.aoi_idlen = oidlen;
-			if (sav->sav_sag->sag_type == AGENTX_PDU_TYPE_GET &&
-			    agentx_oid_cmp(&oid, curvalue) != 0) {
-#ifdef AGENTX_DEBUG
-				subagentx_log_sag_fatalx(sav->sav_sag,
-				    "can't change index on GET");
-#else
-				subagentx_log_sag_warnx(sav->sav_sag,
-				    "can't change index on GET");
-				subagentx_varbind_error_type(sav,
-				    AGENTX_PDU_ERROR_GENERR, 0);
-				return;
-#endif
-			}
-			for (i = 0; i < oidlen; i++)
-				curvalue->aoi_id[i] = value[i];
-			curvalue->aoi_idlen = oidlen;
-			return;
-		}
-	}
-#ifdef AGENTX_DEBUG
-	subagentx_log_sag_fatalx(sav->sav_sag, "invalid index");
-#else
-	subagentx_log_sag_warnx(sav->sav_sag, "invalid index");
-	subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-#endif
-}
-
-void
-subagentx_varbind_set_index_object(struct subagentx_varbind *sav,
-    struct subagentx_index *sai, struct subagentx_object *sao)
-{
-	subagentx_varbind_set_index_oid(sav, sai, sao->sao_oid.aoi_id,
-	    sao->sao_oid.aoi_idlen);
-}
-
-void
-subagentx_varbind_set_index_ipaddress(struct subagentx_varbind *sav,
-    struct subagentx_index *sai, const struct in_addr *addr)
-{
-	struct agentx_ostring *curvalue;
-	size_t i;
-
-	if (sai->sai_vb.avb_type != AGENTX_DATA_TYPE_IPADDRESS) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sag_fatalx(sav->sav_sag, "invalid index type");
-#else
-		subagentx_log_sag_warnx(sav->sav_sag, "invalid index type");
-		subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-		return;
-#endif
-	}
-
-	for (i = 0; i < sav->sav_indexlen; i++) {
-		if (sav->sav_index[i].sav_sai == sai) {
-			curvalue = &(sav->sav_index[i].sav_idata.avb_ostring);
-			if (curvalue->aos_string == NULL)
-				curvalue->aos_string = calloc(1, sizeof(*addr));
-			if (curvalue->aos_string == NULL) {
-				subagentx_log_sag_warn(sav->sav_sag,
-				    "Failed to bind ipaddress index");
-				subagentx_varbind_error_type(sav,
-				    AGENTX_PDU_ERROR_PROCESSINGERROR, 0);
-				return;
-			}
-			if (sav->sav_sag->sag_type == AGENTX_PDU_TYPE_GET &&
-			    memcmp(addr, curvalue->aos_string,
-			    sizeof(*addr)) != 0) {
-#ifdef AGENTX_DEBUG
-				subagentx_log_sag_fatalx(sav->sav_sag,
-				    "can't change index on GET");
-#else
-				subagentx_log_sag_warnx(sav->sav_sag,
-				    "can't change index on GET");
-				subagentx_varbind_error_type(sav,
-				    AGENTX_PDU_ERROR_GENERR, 0);
-				return;
-#endif
-			}
-			bcopy(addr, curvalue->aos_string, sizeof(*addr));
-			return;
-		}
-	}
-#ifdef AGENTX_DEBUG
-	subagentx_log_sag_fatalx(sav->sav_sag, "invalid index");
-#else
-	subagentx_log_sag_warnx(sav->sav_sag, "invalid index");
-	subagentx_varbind_error_type(sav, AGENTX_PDU_ERROR_GENERR, 0);
-#endif
-}
-
-static int
-subagentx_request(struct subagentx *sa, uint32_t packetid,
-    int (*cb)(struct agentx_pdu *, void *), void *cookie)
-{
-	struct subagentx_request *sar;
-
-#ifdef AGENTX_DEBUG
-	if (sa->sa_ax->ax_wblen == 0)
-		subagentx_log_sa_fatalx(sa, "%s: no data to be written",
-		    __func__);
-#endif
-
-	if ((sar = calloc(1, sizeof(*sar))) == NULL) {
-		subagentx_log_sa_warn(sa, "couldn't create request context");
-		subagentx_reset(sa);
-		return -1;
-	}
-
-	sar->sar_packetid = packetid;
-	sar->sar_cb = cb;
-	sar->sar_cookie = cookie;
-	if (RB_INSERT(sa_requests, &(sa->sa_requests), sar) != NULL) {
-#ifdef AGENTX_DEBUG
-		subagentx_log_sa_fatalx(sa, "%s: duplicate packetid", __func__);
-#else
-		subagentx_log_sa_warnx(sa, "%s: duplicate packetid", __func__);
-		free(sar);
-		subagentx_reset(sa);
-		return -1;
-#endif
-	}
-
-	subagentx_wantwrite(sa, sa->sa_fd);
-	return 0;
-}
-
-static int
-subagentx_request_cmp(struct subagentx_request *r1,
-    struct subagentx_request *r2)
-{
-	return r1->sar_packetid < r2->sar_packetid ? -1 :
-	    r1->sar_packetid > r2->sar_packetid;
-}
-
-static int
-subagentx_strcat(char **dst, const char *src)
-{
-	char *tmp;
-	size_t dstlen = 0, buflen = 0, srclen, nbuflen;
-
-	if (*dst != NULL) {
-		dstlen = strlen(*dst);
-		buflen = ((dstlen / 512) + 1) * 512;
-	}
-
-	srclen = strlen(src);
-	if (*dst == NULL || dstlen + srclen > buflen) {
-		nbuflen = (((dstlen + srclen) / 512) + 1) * 512;
-		tmp = recallocarray(*dst, buflen, nbuflen, sizeof(*tmp));
-		if (tmp == NULL)
-			return -1;
-		*dst = tmp;
-		buflen = nbuflen;
-	}
-
-	(void)strlcat(*dst, src, buflen);
-	return 0;
-}
-
-void
-subagentx_read(struct subagentx *sa)
-{
-	struct subagentx_session *sas;
-	struct subagentx_context *sac;
-	struct subagentx_request sar_search, *sar;
-	struct agentx_pdu *pdu;
-	int error;
-
-	if ((pdu = agentx_recv(sa->sa_ax)) == NULL) {
-		if (errno == EAGAIN)
-			return;
-		subagentx_log_sa_warn(sa, "lost connection");
-		subagentx_reset(sa);
-		return;
-	}
-
-	TAILQ_FOREACH(sas, &(sa->sa_sessions), sas_sa_sessions) {
-		if (sas->sas_id == pdu->ap_header.aph_sessionid)
-			break;
-		if (sas->sas_cstate == SA_CSTATE_WAITOPEN &&
-		    sas->sas_packetid == pdu->ap_header.aph_packetid)
-			break;
-	}
-	if (sas == NULL) {
-		subagentx_log_sa_warnx(sa, "received unexpected session: %d",
-		    pdu->ap_header.aph_sessionid);
-		agentx_pdu_free(pdu);
-		subagentx_reset(sa);
-		return;
-	}
-	TAILQ_FOREACH(sac, &(sas->sas_contexts), sac_sas_contexts) {
-		if ((pdu->ap_header.aph_flags &
-		    AGENTX_PDU_FLAG_NON_DEFAULT_CONTEXT) == 0 &&
-		    sac->sac_name_default == 1)
-			break;
-		if (pdu->ap_header.aph_flags &
-		    AGENTX_PDU_FLAG_NON_DEFAULT_CONTEXT &&
-		    sac->sac_name_default == 0 &&
-		    pdu->ap_context.aos_slen == sac->sac_name.aos_slen &&
-		    memcmp(pdu->ap_context.aos_string,
-		    sac->sac_name.aos_string, sac->sac_name.aos_slen) == 0)
-			break;
-	}
-	if (pdu->ap_header.aph_type != AGENTX_PDU_TYPE_RESPONSE) {
-		if (sac == NULL) {
-			subagentx_log_sa_warnx(sa, "%s: invalid context",
-			    pdu->ap_context.aos_string);
-			agentx_pdu_free(pdu);
-			subagentx_reset(sa);
-			return;
-		}
-	}
-
-	switch (pdu->ap_header.aph_type) {
-	case AGENTX_PDU_TYPE_GET:
-	case AGENTX_PDU_TYPE_GETNEXT:
-	case AGENTX_PDU_TYPE_GETBULK:
-		subagentx_get_start(sac, pdu);
-		break;
-	/* Add stubs for set functions */
-	case AGENTX_PDU_TYPE_TESTSET:
-	case AGENTX_PDU_TYPE_COMMITSET:
-	case AGENTX_PDU_TYPE_UNDOSET:
-		if (pdu->ap_header.aph_type == AGENTX_PDU_TYPE_TESTSET)
-			error = AGENTX_PDU_ERROR_NOTWRITABLE;
-		else if (pdu->ap_header.aph_type == AGENTX_PDU_TYPE_COMMITSET)
-			error = AGENTX_PDU_ERROR_COMMITFAILED;
-		else
-			error = AGENTX_PDU_ERROR_UNDOFAILED;
-
-		subagentx_log_sac_debug(sac, "unsupported call: %s",
-		    agentx_pdutype2string(pdu->ap_header.aph_type));
-		if (agentx_response(sa->sa_ax, sas->sas_id,
-		    pdu->ap_header.aph_transactionid,
-		    pdu->ap_header.aph_packetid,
-		    sac == NULL ? NULL : SUBAGENTX_CONTEXT_CTX(sac),
-		    0, error, 1, NULL, 0) == -1)
-			subagentx_log_sac_warn(sac,
-			    "transaction: %u packetid: %u: failed to send "
-			    "reply", pdu->ap_header.aph_transactionid,
-			    pdu->ap_header.aph_packetid);
-		if (sa->sa_ax->ax_wblen > 0)
-			subagentx_wantwrite(sa, sa->sa_fd);
-		break;
-	case AGENTX_PDU_TYPE_CLEANUPSET:
-		subagentx_log_sa_debug(sa, "unsupported call: %s",
-		    agentx_pdutype2string(pdu->ap_header.aph_type));
-		break;
-	case AGENTX_PDU_TYPE_RESPONSE:
-		sar_search.sar_packetid = pdu->ap_header.aph_packetid;
-		sar = RB_FIND(sa_requests, &(sa->sa_requests), &sar_search);
-		if (sar == NULL) {
-			if (sac == NULL)
-				subagentx_log_sa_warnx(sa, "received "
-				    "response on non-request");
-			else
-				subagentx_log_sac_warnx(sac, "received "
-				    "response on non-request");
-			break;
-		}
-		if (sac != NULL && pdu->ap_payload.ap_response.ap_error == 0) {
-			sac->sac_sysuptime =
-			    pdu->ap_payload.ap_response.ap_uptime;
-			(void) clock_gettime(CLOCK_MONOTONIC,
-			    &(sac->sac_sysuptimespec));
-		}
-		RB_REMOVE(sa_requests, &(sa->sa_requests), sar);
-		(void) sar->sar_cb(pdu, sar->sar_cookie);
-		free(sar);
-		break;
-	default:
-		if (sac == NULL)
-			subagentx_log_sa_warnx(sa, "unsupported call: %s",
-			    agentx_pdutype2string(pdu->ap_header.aph_type));
-		else
-			subagentx_log_sac_warnx(sac, "unsupported call: %s",
-			    agentx_pdutype2string(pdu->ap_header.aph_type));
-		subagentx_reset(sa);
-		break;
-	}
-	agentx_pdu_free(pdu);
-}
-
-void
-subagentx_write(struct subagentx *sa)
-{
-	ssize_t send;
-
-	if ((send = agentx_send(sa->sa_ax)) == -1) {
-		if (errno == EAGAIN) {
-			subagentx_wantwrite(sa, sa->sa_fd);
-			return;
-		}
-		subagentx_log_sa_warn(sa, "lost connection");
-		subagentx_reset(sa);
-		return;
-	}
-	if (send > 0)
-		subagentx_wantwrite(sa, sa->sa_fd);
-}
-
-RB_GENERATE_STATIC(sa_requests, subagentx_request, sar_sa_requests,
-    subagentx_request_cmp)
-RB_GENERATE_STATIC(sac_objects, subagentx_object, sao_sac_objects,
-    subagentx_object_cmp)
blob - 418b86a78c1f8c9c2753017d88e24bfac2e7cd4a (mode 644)
blob + /dev/null
--- subagentx.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <netinet/in.h>
-
-#include <stdint.h>
-#include <stddef.h>
-
-struct subagentx;
-struct subagentx_session;
-struct subagentx_context;
-struct subagentx_agentcaps;
-struct subagentx_region;
-struct subagentx_index;
-struct subagentx_object;
-struct subagentx_varbind;
-
-enum subagentx_request_type {
-	SUBAGENTX_REQUEST_TYPE_GET,
-	SUBAGENTX_REQUEST_TYPE_GETNEXT,
-	SUBAGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE
-};
-
-#define SUBAGENTX_AGENTX_MASTER "/var/agentx/master"
-#define SUBAGENTX_OID_MAX_LEN 128
-#define SUBAGENTX_OID_INDEX_MAX_LEN 10
-#define SUBAGENTX_MIB2 1, 3, 6, 1, 2, 1
-#define SUBAGENTX_ENTERPRISES 1, 3, 6, 1, 4, 1
-#define SUBAGENTX_OID(...) (uint32_t []) { __VA_ARGS__ }, \
-    (sizeof((uint32_t []) { __VA_ARGS__ }) / sizeof(uint32_t))
-
-extern void (*subagentx_log_fatal)(const char *, ...)
-    __attribute__((__format__ (printf, 1, 2)));
-extern void (*subagentx_log_warn)(const char *, ...)
-    __attribute__((__format__ (printf, 1, 2)));
-extern void (*subagentx_log_info)(const char *, ...)
-    __attribute__((__format__ (printf, 1, 2)));
-extern void (*subagentx_log_debug)(const char *, ...)
-    __attribute__((__format__ (printf, 1, 2)));
-
-struct subagentx *subagentx(void (*)(struct subagentx *, void *, int), void *);
-void subagentx_connect(struct subagentx *, int);
-void subagentx_read(struct subagentx *);
-void subagentx_write(struct subagentx *);
-extern void (*subagentx_wantwrite)(struct subagentx *, int);
-void subagentx_free(struct subagentx *);
-struct subagentx_session *subagentx_session(struct subagentx *,
-    uint32_t[], size_t, const char *, uint8_t);
-void subagentx_session_free(struct subagentx_session *);
-struct subagentx_context *subagentx_context(struct subagentx_session *,
-    const char *);
-struct subagentx_object *subagentx_context_object_find(
-    struct subagentx_context *, const uint32_t[], size_t, int, int);
-struct subagentx_object *subagentx_context_object_nfind(
-    struct subagentx_context *, const uint32_t[], size_t, int, int);
-uint32_t subagentx_context_uptime(struct subagentx_context *);
-void subagentx_context_free(struct subagentx_context *);
-struct subagentx_agentcaps *subagentx_agentcaps(struct subagentx_context *,
-    uint32_t[], size_t, const char *);
-void subagentx_agentcaps_free(struct subagentx_agentcaps *);
-struct subagentx_region *subagentx_region(struct subagentx_context *,
-    uint32_t[], size_t, uint8_t);
-void subagentx_region_free(struct subagentx_region *);
-struct subagentx_index *subagentx_index_integer_new(struct subagentx_region *,
-    uint32_t[], size_t);
-struct subagentx_index *subagentx_index_integer_any(struct subagentx_region *,
-    uint32_t[], size_t);
-struct subagentx_index *subagentx_index_integer_value(struct subagentx_region *,
-    uint32_t[], size_t, uint32_t);
-struct subagentx_index *subagentx_index_integer_dynamic(
-    struct subagentx_region *, uint32_t[], size_t);
-struct subagentx_index *subagentx_index_string_dynamic(
-    struct subagentx_region *, uint32_t[], size_t);
-struct subagentx_index *subagentx_index_nstring_dynamic(
-    struct subagentx_region *, uint32_t[], size_t, size_t);
-struct subagentx_index *subagentx_index_oid_dynamic(struct subagentx_region *,
-    uint32_t[], size_t);
-struct subagentx_index *subagentx_index_noid_dynamic(struct subagentx_region *,
-    uint32_t[], size_t, size_t);
-struct subagentx_index *subagentx_index_ipaddress_dynamic(
-    struct subagentx_region *, uint32_t[], size_t);
-void subagentx_index_free(struct subagentx_index *);
-struct subagentx_object *subagentx_object(struct subagentx_region *, uint32_t[],
-    size_t, struct subagentx_index *[], size_t, int,
-    void (*)(struct subagentx_varbind *));
-void subagentx_object_free(struct subagentx_object *);
-
-void subagentx_varbind_integer(struct subagentx_varbind *, uint32_t);
-void subagentx_varbind_string(struct subagentx_varbind *, const char *);
-void subagentx_varbind_nstring(struct subagentx_varbind *,
-    const unsigned char *, size_t);
-void subagentx_varbind_printf(struct subagentx_varbind *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_varbind_null(struct subagentx_varbind *);
-void subagentx_varbind_oid(struct subagentx_varbind *, const uint32_t[],
-    size_t);
-void subagentx_varbind_object(struct subagentx_varbind *,
-    struct subagentx_object *);
-void subagentx_varbind_index(struct subagentx_varbind *,
-    struct subagentx_index *);
-void subagentx_varbind_ipaddress(struct subagentx_varbind *,
-    const struct in_addr *);
-void subagentx_varbind_counter32(struct subagentx_varbind *, uint32_t);
-void subagentx_varbind_gauge32(struct subagentx_varbind *, uint32_t);
-void subagentx_varbind_timeticks(struct subagentx_varbind *, uint32_t);
-void subagentx_varbind_opaque(struct subagentx_varbind *, const char *, size_t);
-void subagentx_varbind_counter64(struct subagentx_varbind *, uint64_t);
-void subagentx_varbind_notfound(struct subagentx_varbind *);
-void subagentx_varbind_error(struct subagentx_varbind *);
-
-enum subagentx_request_type subagentx_varbind_request(
-    struct subagentx_varbind *);
-struct subagentx_object *
-    subagentx_varbind_get_object(struct subagentx_varbind *);
-uint32_t subagentx_varbind_get_index_integer(struct subagentx_varbind *,
-    struct subagentx_index *);
-const unsigned char *subagentx_varbind_get_index_string(
-    struct subagentx_varbind *, struct subagentx_index *, size_t *, int *);
-const uint32_t *subagentx_varbind_get_index_oid(struct subagentx_varbind *,
-    struct subagentx_index *, size_t *, int *);
-const struct in_addr *subagentx_varbind_get_index_ipaddress(
-    struct subagentx_varbind *, struct subagentx_index *);
-void subagentx_varbind_set_index_integer(struct subagentx_varbind *,
-    struct subagentx_index *, uint32_t);
-void subagentx_varbind_set_index_string(struct subagentx_varbind *,
-    struct subagentx_index *, const char *);
-void subagentx_varbind_set_index_nstring(struct subagentx_varbind *,
-    struct subagentx_index *, const unsigned char *, size_t);
-void subagentx_varbind_set_index_oid(struct subagentx_varbind *,
-    struct subagentx_index *, const uint32_t *, size_t);
-void subagentx_varbind_set_index_object(struct subagentx_varbind *,
-    struct subagentx_index *, struct subagentx_object *);
-void subagentx_varbind_set_index_ipaddress(struct subagentx_varbind *,
-    struct subagentx_index *, const struct in_addr *);
blob - 4dafcf373a4fb8f4157234d0d30e0af4cbcaed65 (mode 644)
blob + /dev/null
--- subagentx_internal.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <sys/queue.h>
-#include <sys/time.h>
-#include <sys/tree.h>
-
-#include "agentx.h"
-
-enum subagentx_cstate {		/* Current state */
-	SA_CSTATE_CLOSE,	/* Closed */
-	SA_CSTATE_WAITOPEN,	/* Connection requested */
-	SA_CSTATE_OPEN,		/* Open */
-	SA_CSTATE_WAITCLOSE	/* Close requested */
-};
-
-enum subagentx_dstate {		/* Desired state */
-	SA_DSTATE_OPEN,		/* Open */
-	SA_DSTATE_CLOSE		/* Close/free */
-};
-
-struct subagentx {
-	void (*sa_nofd)(struct subagentx *, void *, int);
-	void *sa_cookie;
-	int sa_fd;
-	enum subagentx_cstate sa_cstate;
-	enum subagentx_dstate sa_dstate;
-	struct agentx *sa_ax;
-	TAILQ_HEAD(, subagentx_session) sa_sessions;
-	TAILQ_HEAD(, subagentx_get) sa_getreqs;
-	RB_HEAD(sa_requests, subagentx_request) sa_requests;
-};
-
-struct subagentx_session {
-	struct subagentx *sas_sa;
-	uint32_t sas_id;
-	uint32_t sas_timeout;
-	struct agentx_oid sas_oid;
-	struct agentx_ostring sas_descr;
-	enum subagentx_cstate sas_cstate;
-	enum subagentx_dstate sas_dstate;
-	uint32_t sas_packetid;
-	TAILQ_HEAD(, subagentx_context) sas_contexts;
-	TAILQ_ENTRY(subagentx_session) sas_sa_sessions;
-};
-
-struct subagentx_context {
-	struct subagentx_session *sac_sas;
-	int sac_name_default;
-	struct agentx_ostring sac_name;
-	uint32_t sac_sysuptime;
-	struct timespec sac_sysuptimespec;
-	enum subagentx_cstate sac_cstate;
-	enum subagentx_dstate sac_dstate;
-	TAILQ_HEAD(, subagentx_agentcaps) sac_agentcaps;
-	TAILQ_HEAD(, subagentx_region) sac_regions;
-	RB_HEAD(sac_objects, subagentx_object) sac_objects;
-	TAILQ_ENTRY(subagentx_context) sac_sas_contexts;
-};
-
-struct subagentx_get {
-	struct subagentx_context *sag_sac;
-	int sag_fd;				/* Only used for logging */
-	uint32_t sag_sessionid;
-	uint32_t sag_transactionid;
-	uint32_t sag_packetid;
-	int sag_context_default;
-	struct agentx_ostring sag_context;
-	enum agentx_pdu_type sag_type;
-	uint16_t sag_nonrep;
-	uint16_t sag_maxrep;
-	size_t sag_nvarbind;
-	struct subagentx_varbind *sag_varbind;
-	TAILQ_ENTRY(subagentx_get) sag_sa_getreqs;
-};
-
-__dead void subagentx_log_sa_fatalx(struct subagentx *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sa_warn(struct subagentx *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sa_warnx(struct subagentx *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sa_info(struct subagentx *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sa_debug(struct subagentx *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-__dead void subagentx_log_sas_fatalx(struct subagentx_session *, const char *,
-    ...) __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sas_warnx(struct subagentx_session *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sas_warn(struct subagentx_session *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sas_info(struct subagentx_session *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-__dead void subagentx_log_sac_fatalx(struct subagentx_context *, const char *,
-    ...) __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sac_warnx(struct subagentx_context *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sac_warn(struct subagentx_context *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sac_info(struct subagentx_context *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sac_debug(struct subagentx_context *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-__dead void subagentx_log_sag_fatalx(struct subagentx_get *, const char *,
-    ...) __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sag_warnx(struct subagentx_get *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sag_warn(struct subagentx_get *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
-void subagentx_log_sag_debug(struct subagentx_get *, const char *, ...)
-    __attribute__((__format__ (printf, 2, 3)));
blob - d9dcca8e856116a62defc09cba4fbd0123a68e95 (mode 644)
blob + /dev/null
--- subagentx_log.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "subagentx_internal.h"
-
-#define SUBAGENTX_CONTEXT_NAME(sac) (sac->sac_name_default ? "<default>" : \
-    (char *)sac->sac_name.aos_string)
-#define SUBAGENTX_GET_CTXNAME(sag) (sag->sag_context_default ? "<default>" : \
-    (char *)sag->sag_context.aos_string)
-
-enum subagentx_log_type {
-	SUBAGENTX_LOG_TYPE_FATAL,
-	SUBAGENTX_LOG_TYPE_WARN,
-	SUBAGENTX_LOG_TYPE_INFO,
-	SUBAGENTX_LOG_TYPE_DEBUG
-};
-
-void (*subagentx_log_fatal)(const char *, ...)
-    __attribute__((__format__ (printf, 1, 2))) = NULL;
-void (*subagentx_log_warn)(const char *, ...)
-    __attribute__((__format__ (printf, 1, 2))) = NULL;
-void (*subagentx_log_info)(const char *, ...)
-    __attribute__((__format__ (printf, 1, 2))) = NULL;
-void (*subagentx_log_debug)(const char *, ...)
-    __attribute__((__format__ (printf, 1, 2))) = NULL;
-
-
-static void
-subagentx_log_do(enum subagentx_log_type, const char *, va_list, int,
-    struct subagentx *, struct subagentx_session *, struct subagentx_context *,
-    struct subagentx_get *);
-
-void
-subagentx_log_sa_fatalx(struct subagentx *sa, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_FATAL, fmt, ap, 0, sa, NULL, NULL,
-	    NULL);
-	va_end(ap);
-	abort();
-}
-
-void
-subagentx_log_sa_warn(struct subagentx *sa, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_WARN, fmt, ap, 1, sa, NULL, NULL,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sa_warnx(struct subagentx *sa, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_WARN, fmt, ap, 0, sa, NULL, NULL,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sa_info(struct subagentx *sa, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_INFO, fmt, ap, 0, sa, NULL, NULL,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sa_debug(struct subagentx *sa, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_DEBUG, fmt, ap, 0, sa, NULL, NULL,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sas_fatalx(struct subagentx_session *sas, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_FATAL, fmt, ap, 0, NULL, sas, NULL,
-	    NULL);
-	va_end(ap);
-	abort();
-}
-
-void
-subagentx_log_sas_warnx(struct subagentx_session *sas, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_WARN, fmt, ap, 0, NULL, sas, NULL,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sas_warn(struct subagentx_session *sas, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_WARN, fmt, ap, 1, NULL, sas, NULL,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sas_info(struct subagentx_session *sas, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_INFO, fmt, ap, 0, NULL, sas, NULL,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sac_fatalx(struct subagentx_context *sac, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_FATAL, fmt, ap, 0, NULL, NULL, sac,
-	    NULL);
-	va_end(ap);
-	abort();
-}
-
-void
-subagentx_log_sac_warnx(struct subagentx_context *sac, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_WARN, fmt, ap, 0, NULL, NULL, sac,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sac_warn(struct subagentx_context *sac, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_WARN, fmt, ap, 1, NULL, NULL, sac,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sac_info(struct subagentx_context *sac, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_INFO, fmt, ap, 0, NULL, NULL, sac,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sac_debug(struct subagentx_context *sac, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_DEBUG, fmt, ap, 0, NULL, NULL, sac,
-	    NULL);
-	va_end(ap);
-}
-
-void
-subagentx_log_sag_fatalx(struct subagentx_get *sag, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_FATAL, fmt, ap, 0, NULL, NULL, NULL,
-	    sag);
-	va_end(ap);
-	abort();
-}
-
-void
-subagentx_log_sag_warnx(struct subagentx_get *sag, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_WARN, fmt, ap, 0, NULL, NULL, NULL,
-	    sag);
-	va_end(ap);
-}
-
-void
-subagentx_log_sag_warn(struct subagentx_get *sag, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_WARN, fmt, ap, 1, NULL, NULL, NULL,
-	    sag);
-	va_end(ap);
-}
-
-void
-subagentx_log_sag_debug(struct subagentx_get *sag, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	subagentx_log_do(SUBAGENTX_LOG_TYPE_DEBUG, fmt, ap, 0, NULL, NULL, NULL,
-	    sag);
-	va_end(ap);
-}
-
-static void
-subagentx_log_do(enum subagentx_log_type type, const char *fmt, va_list ap,
-    int useerrno, struct subagentx *sa, struct subagentx_session *sas,
-    struct subagentx_context *sac, struct subagentx_get *sag)
-{
-	void (*subagentx_log)(const char *, ...);
-	char buf[1500];
-
-	if (type == SUBAGENTX_LOG_TYPE_FATAL)
-		subagentx_log = subagentx_log_fatal;
-	else if (type == SUBAGENTX_LOG_TYPE_WARN)
-		subagentx_log = subagentx_log_warn;
-	else if (type == SUBAGENTX_LOG_TYPE_INFO)
-		subagentx_log = subagentx_log_info;
-	else
-		subagentx_log = subagentx_log_debug;
-	if (subagentx_log == NULL)
-		return;
-
-	vsnprintf(buf, sizeof(buf), fmt, ap);
-
-	if (sag != NULL) {
-		if (useerrno)
-			subagentx_log("[fd:%d sess:%u ctx:%s trid:%u pid:%u]: "
-			    "%s: %s", sag->sag_fd, sag->sag_sessionid,
-			    SUBAGENTX_GET_CTXNAME(sag), sag->sag_transactionid,
-			    sag->sag_packetid, buf, strerror(errno));
-		else
-			subagentx_log("[fd:%d sess:%u ctx:%s trid:%u pid:%u]: "
-			    "%s", sag->sag_fd, sag->sag_sessionid,
-			    SUBAGENTX_GET_CTXNAME(sag), sag->sag_transactionid,
-			    sag->sag_packetid, buf);
-	} else if (sac != NULL) {
-		sas = sac->sac_sas;
-		sa = sas->sas_sa;
-		if (useerrno)
-			subagentx_log("[fd:%d sess:%u ctx:%s]: %s: %s",
-			    sa->sa_fd, sas->sas_id, SUBAGENTX_CONTEXT_NAME(sac),
-			    buf, strerror(errno));
-		else
-			subagentx_log("[fd:%d sess:%u ctx:%s]: %s", sa->sa_fd,
-			    sas->sas_id, SUBAGENTX_CONTEXT_NAME(sac), buf);
-	} else if (sas != NULL) {
-		sa = sas->sas_sa;
-		if (useerrno)
-			subagentx_log("[fd:%d sess:%u]: %s: %s", sa->sa_fd,
-			    sas->sas_id, buf, strerror(errno));
-		else
-			subagentx_log("[fd:%d sess:%u]: %s", sa->sa_fd,
-			    sas->sas_id, buf);
-	} else if (sa->sa_fd == -1) {
-		if (useerrno)
-			subagentx_log("%s: %s", buf, strerror(errno));
-		else
-			subagentx_log("%s", buf);
-	} else {
-		if (useerrno)
-			subagentx_log("[fd:%d]: %s: %s", sa->sa_fd, buf,
-			    strerror(errno));
-		else
-			subagentx_log("[fd:%d]: %s", sa->sa_fd, buf);
-	}
-}