Add a new regression framework for snmpd.
authormartijn <martijn@openbsd.org>
Tue, 24 Oct 2023 14:34:40 +0000 (14:34 +0000)
committermartijn <martijn@openbsd.org>
Tue, 24 Oct 2023 14:34:40 +0000 (14:34 +0000)
There are still many test cases left to write, so leave snmpd.sh in place
to test for cases not yet implemented by the new code.

regress/usr.sbin/snmpd/Makefile
regress/usr.sbin/snmpd/agentx.c [new file with mode: 0644]
regress/usr.sbin/snmpd/backend.c [new file with mode: 0644]
regress/usr.sbin/snmpd/regress.h [new file with mode: 0644]
regress/usr.sbin/snmpd/snmp.c [new file with mode: 0644]
regress/usr.sbin/snmpd/snmpd.conf [new file with mode: 0644]
regress/usr.sbin/snmpd/snmpd_regress.c [new file with mode: 0644]

index c8c575e..dfdb717 100644 (file)
-# $OpenBSD: Makefile,v 1.4 2021/10/23 17:56:31 bluhm Exp $
+# $OpenBSD: Makefile,v 1.5 2023/10/24 14:34:40 martijn Exp $
 # Regress tests for snmpd
 
-REGRESS_SETUP_ONCE =   setup
-REGRESS_CLEANUP =      cleanup
-REGRESS_TARGETS =      run-snmpd
+PROG =                         snmpd_regress
+SRCS =                         snmpd_regress.c agentx.c backend.c snmp.c
+
+LDADD=                         -lutil
+DPADD=                         ${LIBUTIL}
+
+SNMPD ?=                       /usr/sbin/snmpd
+SNMPD_START =                  ${SUDO} ${SNMPD} -Nvvdf ${.CURDIR}/snmpd.conf >> snmpd.log 2>&1 &
+
+REGRESS_CLEANUP =              cleanup
+REGRESS_SETUP_ONCE =           setup
+CLEANFILES =                   snmpd.log
 
 setup:
-       ${SUDO} /etc/rc.d/snmpd stop
+       -${SUDO} /etc/rc.d/snmpd stop
+       > snmpd.log
 
 cleanup:
-       -${SUDO} /etc/rc.d/snmpd restart || true
+       -${SUDO} pkill -f ${SNMPD}
+       @sleep 1
+       -${SUDO} rcctl restart snmpd
 
+REGRESS_TARGETS +=      run-snmpd
 run-snmpd:
+       -${SUDO} pkill -f ${SNMPD}
+       @sleep 1
        ${SUDO} env OBJDIR=${.OBJDIR} sh ${.CURDIR}/snmpd.sh
 
+# AgentX administrative commands: application_agentx.c
+AGENTX_TARGETS =               agentx_open_nnbo
+AGENTX_TARGETS+=               agentx_open_nbo
+AGENTX_TARGETS+=               agentx_open_invalidversion
+AGENTX_TARGETS+=               agentx_open_ignore_sessionid
+AGENTX_TARGETS+=               agentx_open_invalid_oid
+AGENTX_TARGETS+=               agentx_open_descr_too_long
+AGENTX_TARGETS+=               agentx_open_descr_invalid
+AGENTX_TARGETS+=               agentx_open_context
+AGENTX_TARGETS+=               agentx_open_instance_registration
+AGENTX_TARGETS+=               agentx_open_new_index
+AGENTX_TARGETS+=               agentx_open_any_index
+AGENTX_TARGETS+=               agentx_ping_notopen
+AGENTX_TARGETS+=               agentx_ping_invalid_sessionid
+AGENTX_TARGETS+=               agentx_ping_default
+AGENTX_TARGETS+=               agentx_ping_context
+AGENTX_TARGETS+=               agentx_ping_invalid_version
+AGENTX_TARGETS+=               agentx_ping_instance_registration
+AGENTX_TARGETS+=               agentx_ping_new_index
+AGENTX_TARGETS+=               agentx_ping_any_index
+AGENTX_TARGETS+=               agentx_ping_nbo_nnbo
+AGENTX_TARGETS+=               agentx_ping_nnbo_nbo
+AGENTX_TARGETS+=               agentx_close_notopen
+AGENTX_TARGETS+=               agentx_close_reasonother
+AGENTX_TARGETS+=               agentx_close_reasonparseerror
+AGENTX_TARGETS+=               agentx_close_reasonprotocolerror
+AGENTX_TARGETS+=               agentx_close_reasontimouts
+AGENTX_TARGETS+=               agentx_close_reasonshutdown
+AGENTX_TARGETS+=               agentx_close_reasonbymanager
+AGENTX_TARGETS+=               agentx_close_reasoninvalid
+AGENTX_TARGETS+=               agentx_close_single
+AGENTX_TARGETS+=               agentx_close_notowned
+AGENTX_TARGETS+=               agentx_close_invalid_sessionid
+AGENTX_TARGETS+=               agentx_close_context
+AGENTX_TARGETS+=               agentx_close_invalid_version
+AGENTX_TARGETS+=               agentx_close_instance_registration
+AGENTX_TARGETS+=               agentx_close_new_index
+AGENTX_TARGETS+=               agentx_close_any_index
+AGENTX_TARGETS+=               agentx_close_nnbo_nbo
+AGENTX_TARGETS+=               agentx_register_notopen
+AGENTX_TARGETS+=               agentx_register_invalid_sessionid
+AGENTX_TARGETS+=               agentx_register_default
+AGENTX_TARGETS+=               agentx_register_context
+AGENTX_TARGETS+=               agentx_register_invalid_version
+AGENTX_TARGETS+=               agentx_register_instance_registration
+AGENTX_TARGETS+=               agentx_register_new_index
+AGENTX_TARGETS+=               agentx_register_duplicate_self
+AGENTX_TARGETS+=               agentx_register_duplicate_twocon
+AGENTX_TARGETS+=               agentx_register_duplicate_priority
+AGENTX_TARGETS+=               agentx_register_range
+AGENTX_TARGETS+=               agentx_register_range_invalidupperbound
+AGENTX_TARGETS+=               agentx_register_range_single
+AGENTX_TARGETS+=               agentx_register_range_overlap_single
+AGENTX_TARGETS+=               agentx_register_single_overlap_range
+AGENTX_TARGETS+=               agentx_register_range_overlap_range
+AGENTX_TARGETS+=               agentx_register_below
+AGENTX_TARGETS+=               agentx_register_above
+AGENTX_TARGETS+=               agentx_register_restricted
+AGENTX_TARGETS+=               agentx_unregister_notopen
+AGENTX_TARGETS+=               agentx_unregister_invalid_sessionid
+AGENTX_TARGETS+=               agentx_unregister_notregistered
+AGENTX_TARGETS+=               agentx_unregister_notregistered
+AGENTX_TARGETS+=               agentx_unregister_single
+AGENTX_TARGETS+=               agentx_unregister_single_notowned
+AGENTX_TARGETS+=               agentx_unregister_range
+AGENTX_TARGETS+=               agentx_unregister_range_single
+# Final choice on if this is the desired behaviour pending on tech@
+REGRESS_EXPECTED_FAILURES+=    agentx_unregister_range_subset
+AGENTX_TARGETS+=               agentx_unregister_range_subset
+AGENTX_TARGETS+=               agentx_unregister_range_extra
+AGENTX_TARGETS+=               agentx_unregister_range_priority
+AGENTX_TARGETS+=               agentx_unregister_range_notowned
+
+REGRESS_TARGETS+=              ${AGENTX_TARGETS}
+agentx: ${AGENTX_TARGETS}
+
+# SNMP application core logic: application.c
+BACKEND_TARGETS+=              backend_get_integer
+BACKEND_TARGETS+=              backend_get_octetstring
+BACKEND_TARGETS+=              backend_get_objectidentifier
+BACKEND_TARGETS+=              backend_get_ipaddress
+BACKEND_TARGETS+=              backend_get_counter32
+BACKEND_TARGETS+=              backend_get_gauge32
+BACKEND_TARGETS+=              backend_get_timeticks
+BACKEND_TARGETS+=              backend_get_opaque
+BACKEND_TARGETS+=              backend_get_counter64
+BACKEND_TARGETS+=              backend_get_nosuchobject
+BACKEND_TARGETS+=              backend_get_nosuchinstance
+BACKEND_TARGETS+=              backend_get_endofmibview
+BACKEND_TARGETS+=              backend_get_two_single_backend
+BACKEND_TARGETS+=              backend_get_two_double_backend
+BACKEND_TARGETS+=              backend_get_wrongorder
+BACKEND_TARGETS+=              backend_get_toofew
+BACKEND_TARGETS+=              backend_get_toomany
+BACKEND_TARGETS+=              backend_get_instance
+BACKEND_TARGETS+=              backend_get_instance_below
+BACKEND_TARGETS+=              backend_get_timeout_default
+REGRESS_SLOW_TARGETS+=         backend_get_timeout_default
+BACKEND_TARGETS+=              backend_get_timeout_session_lower
+REGRESS_SLOW_TARGETS+=         backend_get_timeout_session_lower
+BACKEND_TARGETS+=              backend_get_timeout_session_higher
+REGRESS_SLOW_TARGETS+=         backend_get_timeout_session_higher
+BACKEND_TARGETS+=              backend_get_timeout_region_lower
+REGRESS_SLOW_TARGETS+=         backend_get_timeout_region_lower
+BACKEND_TARGETS+=              backend_get_timeout_region_higher
+REGRESS_SLOW_TARGETS+=         backend_get_timeout_region_higher
+BACKEND_TARGETS+=              backend_get_priority_lower
+BACKEND_TARGETS+=              backend_get_priority_higher
+BACKEND_TARGETS+=              backend_get_priority_below_lower
+BACKEND_TARGETS+=              backend_get_priority_below_higher
+BACKEND_TARGETS+=              backend_get_close
+BACKEND_TARGETS+=              backend_get_close_overlap
+BACKEND_TARGETS+=              backend_get_disappear
+BACKEND_TARGETS+=              backend_get_disappear_overlap
+BACKEND_TARGETS+=              backend_get_disappear_doublesession
+BACKEND_TARGETS+=              backend_getnext_selfbound
+BACKEND_TARGETS+=              backend_getnext_lowerbound
+BACKEND_TARGETS+=              backend_getnext_lowerbound_self
+BACKEND_TARGETS+=              backend_getnext_lowerbound_highprio
+BACKEND_TARGETS+=              backend_getnext_lowerbound_lowprio
+BACKEND_TARGETS+=              backend_getnext_sibling
+BACKEND_TARGETS+=              backend_getnext_child_gap
+BACKEND_TARGETS+=              backend_getnext_nosuchobject
+BACKEND_TARGETS+=              backend_getnext_nosuchinstance
+BACKEND_TARGETS+=              backend_getnext_endofmibview
+BACKEND_TARGETS+=              backend_getnext_inclusive
+BACKEND_TARGETS+=              backend_getnext_jumpnext
+BACKEND_TARGETS+=              backend_getnext_jumpnext_endofmibview
+BACKEND_TARGETS+=              backend_getnext_jump_up
+BACKEND_TARGETS+=              backend_getnext_two_single_backend
+BACKEND_TARGETS+=              backend_getnext_two_double_backend
+BACKEND_TARGETS+=              backend_getnext_instance_below
+BACKEND_TARGETS+=              backend_getnext_instance
+BACKEND_TARGETS+=              backend_getnext_instance_exact
+BACKEND_TARGETS+=              backend_getnext_instance_ignore
+BACKEND_TARGETS+=              backend_getnext_backwards
+BACKEND_TARGETS+=              backend_getnext_stale
+BACKEND_TARGETS+=              backend_getnext_inclusive_backwards
+BACKEND_TARGETS+=              backend_getnext_toofew
+BACKEND_TARGETS+=              backend_getnext_toomany
+BACKEND_TARGETS+=              backend_getbulk_nonrep_zero_maxrep_one
+BACKEND_TARGETS+=              backend_getbulk_nonrep_zero_maxrep_two
+BACKEND_TARGETS+=              backend_getbulk_nonrep_one_maxrep_one
+BACKEND_TARGETS+=              backend_getbulk_nonrep_one_maxrep_two
+BACKEND_TARGETS+=              backend_getbulk_nonrep_two_maxrep_two
+BACKEND_TARGETS+=              backend_getbulk_nonrep_negative
+BACKEND_TARGETS+=              backend_error_get_toobig
+BACKEND_TARGETS+=              backend_error_get_nosuchname
+BACKEND_TARGETS+=              backend_error_get_badvalue
+BACKEND_TARGETS+=              backend_error_get_readonly
+BACKEND_TARGETS+=              backend_error_get_generr
+BACKEND_TARGETS+=              backend_error_get_wrongtype
+BACKEND_TARGETS+=              backend_error_get_wronglength
+BACKEND_TARGETS+=              backend_error_get_wrongvalue
+BACKEND_TARGETS+=              backend_error_get_nocreation
+BACKEND_TARGETS+=              backend_error_get_inconsistentvalue
+BACKEND_TARGETS+=              backend_error_get_commitfailed
+BACKEND_TARGETS+=              backend_error_get_undofailed
+BACKEND_TARGETS+=              backend_error_get_authorizationerror
+BACKEND_TARGETS+=              backend_error_get_notwritable
+BACKEND_TARGETS+=              backend_error_get_inconsistentname
+BACKEND_TARGETS+=              backend_error_get_openfailed
+BACKEND_TARGETS+=              backend_error_get_notopen
+BACKEND_TARGETS+=              backend_error_get_indexwrongtype
+BACKEND_TARGETS+=              backend_error_get_indexalreadyallocated
+BACKEND_TARGETS+=              backend_error_get_indexnonavailable
+BACKEND_TARGETS+=              backend_error_get_indexnotallocated
+BACKEND_TARGETS+=              backend_error_get_duplicateregistration
+BACKEND_TARGETS+=              backend_error_get_requestdenied
+BACKEND_TARGETS+=              backend_error_get_processingerror
+BACKEND_TARGETS+=              backend_error_get_nonstandard
+BACKEND_TARGETS+=              backend_error_getnext_toobig
+BACKEND_TARGETS+=              backend_error_getnext_nosuchname
+BACKEND_TARGETS+=              backend_error_getnext_badvalue
+BACKEND_TARGETS+=              backend_error_getnext_readonly
+BACKEND_TARGETS+=              backend_error_getnext_generr
+BACKEND_TARGETS+=              backend_error_getnext_noaccess
+BACKEND_TARGETS+=              backend_error_getnext_wrongtype
+BACKEND_TARGETS+=              backend_error_getnext_wronglength
+BACKEND_TARGETS+=              backend_error_getnext_wrongencoding
+BACKEND_TARGETS+=              backend_error_getnext_wrongvalue
+BACKEND_TARGETS+=              backend_error_getnext_nocreation
+BACKEND_TARGETS+=              backend_error_getnext_inconsistentvalue
+BACKEND_TARGETS+=              backend_error_getnext_resourceunavailable
+BACKEND_TARGETS+=              backend_error_getnext_commitfailed
+BACKEND_TARGETS+=              backend_error_getnext_undofailed
+BACKEND_TARGETS+=              backend_error_getnext_notwritable
+BACKEND_TARGETS+=              backend_error_getnext_inconsistentname
+BACKEND_TARGETS+=              backend_error_getnext_openfailed
+BACKEND_TARGETS+=              backend_error_getnext_notopen
+BACKEND_TARGETS+=              backend_error_getnext_indexwrongtype
+BACKEND_TARGETS+=              backend_error_getnext_indexalreadyallocated
+BACKEND_TARGETS+=              backend_error_getnext_indexnonavailable
+BACKEND_TARGETS+=              backend_error_getnext_indexnotallocated
+BACKEND_TARGETS+=              backend_error_getnext_unsupportedcontext
+BACKEND_TARGETS+=              backend_error_getnext_duplicateregistration
+BACKEND_TARGETS+=              backend_error_getnext_unknownregistration
+BACKEND_TARGETS+=              backend_error_getnext_parseerror
+BACKEND_TARGETS+=              backend_error_getnext_requestdenied
+BACKEND_TARGETS+=              backend_error_getnext_processingerror
+BACKEND_TARGETS+=              backend_error_getnext_nonstandard
+
+REGRESS_TARGETS+=              ${BACKEND_TARGETS}
+backend: ${BACKEND_TARGETS}
+
+.PHONY:                                agentx backend
+
+${REGRESS_TARGETS}: snmpd_regress
+# Always start snmpd if it's not running
+       @pgrep -q snmpd || \
+           (printf "%s\n" "${SNMPD_START}"; ${SNMPD_START} sleep 0.5)
+       ./snmpd_regress ${SNMPD_REGRESS_FLAGS} $@
+# Make sure that snmpd hasn't crashed in the meantime.
+       @sleep 0.01
+       @pgrep -q snmpd
+
 .include <bsd.regress.mk>
diff --git a/regress/usr.sbin/snmpd/agentx.c b/regress/usr.sbin/snmpd/agentx.c
new file mode 100644 (file)
index 0000000..ade5dd8
--- /dev/null
@@ -0,0 +1,3146 @@
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include <endian.h>
+#include <err.h>
+#include <poll.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "regress.h"
+
+#define AGENTX_SOCKET "/tmp/agentx"
+
+#define SUBAGENT_DESCR(name) name, strlen(name)
+
+#define AGENTX_OPEN_PDU 1
+#define AGENTX_CLOSE_PDU 2
+#define AGENTX_REGISTER_PDU 3
+#define AGENTX_UNREGISTER_PDU 4
+#define AGENTX_GET_PDU 5
+#define AGENTX_GETNEXT_PDU 6
+#define AGENTX_GETBULK_PDU 7
+#define AGENTX_TESTSET_PDU 8
+#define AGENTX_COMMITSET_PDU 9
+#define AGENTX_UNDOSET_PDU 10
+#define AGENTX_CLEANUPSET_PDU 11
+#define AGENTX_NOTIFY_PDU 12
+#define AGENTX_PING_PDU 13
+#define AGENTX_INDEXALLOCATE_PDU 14
+#define AGENTX_INDEXDEALLOCATE_PDU 15
+#define AGENTX_ADDAGENTCAPS_PDU 16
+#define AGENTX_REMOVEAGENTCAPS_PDU 17
+#define AGENTX_RESPONSE_PDU 18
+
+#define NOAGENTXERROR 0
+#define OPENFAILED 256
+#define NOTOPEN 257
+#define INDEXWRONGTYPE 258
+#define INDEXALREADYALLOCATED 259
+#define INDEXNONEAVAILABLE 260
+#define INDEXNOTALLOCATED 261
+#define UNSUPPORTEDCONTEXT 262
+#define DUPLICATEREGISTRATION 263
+#define UNKNOWNREGISTRATION 264
+#define UNKNOWNAGENTCAPS 265
+#define PARSEERROR 266
+#define REQUESTDENIED 267
+#define PROCESSINGERROR 268
+
+#define INSTANCE_REGISTRATION (1 << 0)
+#define NEW_INDEX (1 << 1)
+#define ANY_INDEX (1 << 2)
+#define NON_DEFAULT_CONTEXT (1 << 3)
+#define NETWORK_BYTE_ORDER (1 << 4)
+
+#define INTEGER 2
+#define OCTETSTRING 4
+#define AXNULL 5
+#define OBJECTIDENTIFIER 6
+#define IPADDRESS 64
+#define COUNTER32 65
+#define GAUGE32 66
+#define TIMETICKS 67
+#define OPAQUE 68
+#define COUNTER64 70
+#define NOSUCHOBJECT 128
+#define NOSUCHINSTANCE 129
+#define ENDOFMIBVIEW 130
+
+#define MESSAGE_NBO(msg) (((const char *)msg->buf)[2] & NETWORK_BYTE_ORDER)
+
+#define p16toh(header, value) (uint16_t)(header->flags & NETWORK_BYTE_ORDER ? \
+    be16toh(value) : le16toh(value))
+#define p32toh(header, value) (uint32_t)(header->flags & NETWORK_BYTE_ORDER ? \
+    be32toh(value) : le32toh(value))
+#define p64toh(header, value) (uint64_t)(header->flags & NETWORK_BYTE_ORDER ? \
+    be64toh(value) : le64toh(value))
+
+struct header {
+       uint8_t          version;
+       uint8_t          type;
+       uint8_t          flags;
+       uint8_t          reserved;
+       uint32_t         sessionid;
+       uint32_t         transactionid;
+       uint32_t         packetid;
+       uint32_t         payload_length;
+} __attribute__ ((packed));
+
+struct message {
+       void            *buf;
+       size_t           len;
+       size_t           size;
+};
+
+void agentx_close_validate(const char *, const void *,
+    size_t, uint8_t, uint8_t);
+static void agentx_response_validate(const char *, const void *, size_t,
+    uint8_t, uint32_t, enum error, uint16_t, struct varbind *, size_t);
+static void message_add_uint8(struct message *, uint8_t);
+static void message_add_uint16(struct message *, uint16_t);
+static void message_add_uint32(struct message *, uint32_t);
+static void message_add_uint64(struct message *, uint64_t);
+static void message_add_nstring(struct message *, const void *, uint32_t);
+static void message_add_oid(struct message *, const uint32_t[], uint8_t,
+    uint8_t);
+static void message_add_varbind(struct message *, struct varbind *);
+static void message_add_header(struct message *, uint8_t, uint8_t, uint8_t,
+    uint32_t, uint32_t, uint32_t);
+static void message_add(struct message *, const void *, size_t);
+static void message_release(struct message *);
+static size_t poid(const char *, const struct header *, const uint8_t *, size_t,
+    struct oid *);
+
+void agentx_write(int, struct message *);
+
+void
+agentx_open_nnbo(void)
+{
+       int s;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, 0, 0, 0, packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 1), 0);
+       message_add_nstring(&msg, SUBAGENT_DESCR(__func__));
+
+       agentx_write(s, &msg);
+       
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR,
+           0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_open_nbo(void)
+{
+       int s;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, NETWORK_BYTE_ORDER, 0, 0,
+           packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 2), 0);
+       message_add_nstring(&msg, SUBAGENT_DESCR(__func__));
+
+       agentx_write(s, &msg);
+       
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, NETWORK_BYTE_ORDER,
+           packetid, NOAGENTXERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+/*
+ * The version byte is the only identifier we have to determine if we can
+ * "trust" the rest of the packet structure. If this doesn't match the server
+ * can't return a parseError message, because it doesn't know the packetid.
+ */
+void
+agentx_open_invalidversion(void)
+{
+       int s;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 0xFF, AGENTX_OPEN_PDU, 0, 0, 0, packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 3), 0);
+       message_add_nstring(&msg, SUBAGENT_DESCR(__func__));
+
+       agentx_write(s, &msg);
+       
+       if (agentx_read(s, repl, sizeof(repl), 1000) != 0)
+               errx(1, "%s: Unexpected reply", __func__);
+       close(s);
+}
+
+void
+agentx_open_ignore_sessionid(void)
+{
+       int s1, s2;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       struct header *header = (struct header *)repl;
+
+       s1 = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, 0, 0, 0, packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 4, 1), 0);
+       message_add_nstring(&msg,
+           SUBAGENT_DESCR("agentx_open_ignore_sessionid.1"));
+
+       agentx_write(s1, &msg);
+       
+       n = agentx_read(s1, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR,
+           0, NULL, 0);
+
+       sessionid = le32toh(header->sessionid);
+
+       s2 = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, 0, sessionid, 0, packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 4, 2), 0);
+       message_add_nstring(&msg,
+           SUBAGENT_DESCR("agentx_open_ignore_sessionid.2"));
+
+       agentx_write(s2, &msg);
+       
+       n = agentx_read(s2, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR,
+           0, NULL, 0);
+       if (sessionid == le32toh(header->sessionid))
+               errx(1, "%s: sessionid not ignored", __func__);
+
+       message_release(&msg);
+       close(s1);
+       close(s2);
+}
+
+void
+agentx_open_invalid_oid(void)
+{
+       int s;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t oid[129];
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, 0, 0, 0, packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, oid, 129, 0);
+       message_add_nstring(&msg, SUBAGENT_DESCR(__func__));
+
+       agentx_write(s, &msg);
+       
+       if ((n = agentx_read(s, repl, sizeof(repl), 1000)) != 0)
+               errx(1, "unexpected reply");
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_open_descr_too_long(void)
+{
+       int s;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       char descr[256];
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, 0, 0, 0, packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 6), 0);
+       memset(descr, 'a', sizeof(descr));
+       message_add_nstring(&msg, descr, sizeof(descr));
+
+       agentx_write(s, &msg);
+       
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, PARSEERROR, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_open_descr_invalid(void)
+{
+       int s;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, 0, 0, 0, packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 7), 0);
+       /* Too long start-byte (5 ones instead of max 4) followed by ascii */
+       message_add_nstring(&msg, SUBAGENT_DESCR("a\373a"));
+
+       agentx_write(s, &msg);
+       
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, PARSEERROR, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_open_context(void)
+{
+       int s;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, NON_DEFAULT_CONTEXT, 0, 0,
+           packetid);
+       message_add_nstring(&msg, "ctx", 3);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 8), 0);
+       message_add_nstring(&msg, SUBAGENT_DESCR(__func__));
+
+       agentx_write(s, &msg);
+       
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, PARSEERROR, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_open_instance_registration(void)
+{
+       int s;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, INSTANCE_REGISTRATION, 0,
+           0, packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 9), 0);
+       message_add_nstring(&msg, SUBAGENT_DESCR(__func__));
+
+       agentx_write(s, &msg);
+       
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, PARSEERROR, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_open_new_index(void)
+{
+       int s;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, NEW_INDEX, 0,
+           0, packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 10), 0);
+       message_add_nstring(&msg, SUBAGENT_DESCR(__func__));
+
+       agentx_write(s, &msg);
+       
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, PARSEERROR, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_open_any_index(void)
+{
+       int s;
+       struct message msg = {};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU, ANY_INDEX, 0,
+           0, packetid);
+       message_add_uint8(&msg, 0);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, OID_ARG(MIB_SUBAGENT_OPEN, 11), 0);
+       message_add_nstring(&msg, SUBAGENT_DESCR(__func__));
+
+       agentx_write(s, &msg);
+       
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, PARSEERROR, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_ping_notopen(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_PING_PDU, 0, 0, 0, packetid);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOTOPEN, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_ping_invalid_sessionid(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_PING, 2), __func__);
+       message_add_header(&msg, 1, AGENTX_PING_PDU, 0,
+           sessionid + 1, 0, packetid);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOTOPEN, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_ping_default(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_PING, 3), __func__);
+       message_add_header(&msg, 1, AGENTX_PING_PDU, 0,
+           sessionid, 0, packetid);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, NOAGENTXERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_ping_context(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_PING, 4), __func__);
+       message_add_header(&msg, 1, AGENTX_PING_PDU, NON_DEFAULT_CONTEXT,
+           sessionid, 0, packetid);
+       message_add_nstring(&msg, "ctx", 3);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, UNSUPPORTEDCONTEXT, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_ping_invalid_version(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_PING, 5), __func__);
+       message_add_header(&msg, 0xFF, AGENTX_PING_PDU, INSTANCE_REGISTRATION,
+           sessionid, 0, packetid);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_close_validate(__func__, repl, n, 0, REASONPROTOCOLERROR);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_ping_instance_registration(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_PING, 6), __func__);
+       message_add_header(&msg, 1, AGENTX_PING_PDU, INSTANCE_REGISTRATION,
+           sessionid, 0, packetid);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, PARSEERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_ping_new_index(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_PING, 7), __func__);
+       message_add_header(&msg, 1, AGENTX_PING_PDU, NEW_INDEX,
+           sessionid, 0, packetid);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, PARSEERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_ping_any_index(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_PING, 8), __func__);
+       message_add_header(&msg, 1, AGENTX_PING_PDU, ANY_INDEX,
+           sessionid, 0, packetid);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, PARSEERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_ping_nbo_nnbo(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_PING, 9), __func__);
+       message_add_header(&msg, 1, AGENTX_PING_PDU, 0,
+           sessionid, 0, packetid);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, NOAGENTXERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_ping_nnbo_nbo(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_PING, 9), __func__);
+       message_add_header(&msg, 1, AGENTX_PING_PDU, NETWORK_BYTE_ORDER,
+           sessionid, 0, packetid);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, NETWORK_BYTE_ORDER,
+           packetid, NOAGENTXERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_notopen(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, 0, 0, packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOTOPEN, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_reasonother(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 2), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR,
+           0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_reasonparseerror(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONPARSEERROR, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 3), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR,
+           0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_reasonprotocolerror(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONPROTOCOLERROR, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 4), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR,
+           0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_reasontimouts(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONTIMEOUTS, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 5), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR,
+           0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_reasonshutdown(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONSHUTDOWN, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 6), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR,
+           0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_reasonbymanager(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONBYMANAGER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 7), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, PARSEERROR,
+           0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_reasoninvalid(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = 0xFF, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 8), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_close_validate(__func__, repl, n, 0, REASONPROTOCOLERROR);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_single(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid1, sessionid2;
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       
+       sessionid1 = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 9, 1), "agentx_close_single.1");
+       sessionid2 = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 9, 2), "agentx_close_single.2");
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid1, 0, packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR,
+           0, NULL, 0);
+
+       /* Test that only the second session is still open */
+       packetid = arc4random();
+       message_add_header(&msg, 1, AGENTX_PING_PDU, 0, sessionid2, 0, packetid);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, NOAGENTXERROR, 0, NULL, 0);
+
+       packetid = arc4random();
+       message_add_header(&msg, 1, AGENTX_PING_PDU, 0, sessionid1, 0, packetid);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, NOTOPEN, 0, NULL, 0);
+       
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_notowned(void)
+{
+       int s1, s2;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid1, sessionid2;
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s1 = agentx_connect(axsocket);
+       s2 = agentx_connect(axsocket);
+       
+       sessionid1 = agentx_open(s1, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 10, 1), "agentx_close_notowned.1");
+       sessionid2 = agentx_open(s2, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 10, 2), "agentx_close_notowned.2");
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid1, 0, packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s2, &msg);
+
+       n = agentx_read(s2, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOTOPEN,
+           0, NULL, 0);
+
+       /* Test that both sessions are still open */
+       packetid = arc4random();
+       message_add_header(&msg, 1, AGENTX_PING_PDU, 0, sessionid1, 0, packetid);
+       agentx_write(s1, &msg);
+       n = agentx_read(s1, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, NOAGENTXERROR, 0, NULL, 0);
+
+       packetid = arc4random();
+       message_add_header(&msg, 1, AGENTX_PING_PDU, 0, sessionid2, 0, packetid);
+       agentx_write(s2, &msg);
+       n = agentx_read(s2, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, NOAGENTXERROR, 0, NULL, 0);
+       
+       message_release(&msg);
+       close(s1);
+       close(s2);
+}
+
+void
+agentx_close_invalid_sessionid(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 11), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid + 1, 0, packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOTOPEN, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_context(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 12), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, NON_DEFAULT_CONTEXT,
+           sessionid, 0, packetid);
+       message_add_nstring(&msg, "ctx", 3);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, PARSEERROR, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_invalid_version(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 13), __func__);
+       message_add_header(&msg, 0xFF, AGENTX_CLOSE_PDU, 0, sessionid, 0, packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_close_validate(__func__, repl, n, 0, REASONPROTOCOLERROR);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_instance_registration(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 14), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, INSTANCE_REGISTRATION,
+           sessionid, 0, packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, PARSEERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_new_index(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 15), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, NEW_INDEX,
+           sessionid, 0, packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, PARSEERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_any_index(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 16), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, ANY_INDEX,
+           sessionid, 0, packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0,
+           packetid, PARSEERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_close_nnbo_nbo(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       const uint8_t reason = REASONOTHER, zero[3] = {0};
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_CLOSE, 17), __func__);
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, NETWORK_BYTE_ORDER,
+           sessionid, 0, packetid);
+       message_add(&msg, &reason, sizeof(reason));
+       message_add(&msg, zero, sizeof(zero));
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, NETWORK_BYTE_ORDER,
+           packetid, NOAGENTXERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_notopen(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, 0, 0, packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 1, 0), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOTOPEN, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_invalid_sessionid(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 2), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid + 1, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 2, 0), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOTOPEN, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_default(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 3), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 3, 0), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_context(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 4), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, NON_DEFAULT_CONTEXT,
+           sessionid, 0, packetid);
+       message_add_nstring(&msg, "ctx", 3);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 4, 0), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           UNSUPPORTEDCONTEXT, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_invalid_version(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 5), __func__);
+       message_add_header(&msg, 0xFF, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 5, 0), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_close_validate(__func__, repl, n, 0, REASONPROTOCOLERROR);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_instance_registration(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 6), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, INSTANCE_REGISTRATION,
+           sessionid, 0, packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 6, 0), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_new_index(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 7), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, NEW_INDEX,
+           sessionid, 0, packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 7, 0), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           PARSEERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_any_index(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 8), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, NEW_INDEX,
+           sessionid, 0, packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 8, 0), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           PARSEERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_duplicate_self(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 9), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 9, 0), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       packetid = arc4random();
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 9, 0), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           DUPLICATEREGISTRATION, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_duplicate_twocon(void)
+{
+       int s1, s2;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid1, sessionid2;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s1 = agentx_connect(axsocket);
+       s2 = agentx_connect(axsocket);
+       sessionid1 = agentx_open(s1, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 10, 1),
+           "agentx_register_duplicate_twocon.1");
+       sessionid2 = agentx_open(s2, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 10, 2),
+           "agentx_register_duplicate_twocon.2");
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid1, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 10, 0), 0);
+       agentx_write(s1, &msg);
+       n = agentx_read(s1, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       packetid = arc4random();
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid2, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 10, 0), 0);
+       agentx_write(s2, &msg);
+       n = agentx_read(s2, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           DUPLICATEREGISTRATION, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s1);
+       close(s2);
+}
+
+void
+agentx_register_duplicate_priority(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 11), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 11, 0), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       packetid = arc4random();
+       priority = 1;
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 11, 0), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_range(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid, upperbound = 10;
+       uint8_t timeout = 0, priority = 127, range_subid = 11, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 12), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 12, 1), 0);
+       message_add_uint32(&msg, upperbound);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_range_invalidupperbound(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid, upperbound = 1;
+       uint8_t timeout = 0, priority = 127, range_subid = 11, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 13), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 13, 2), 0);
+       message_add_uint32(&msg, upperbound);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           PARSEERROR, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_range_single(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid, upperbound = 1;
+       uint8_t timeout = 0, priority = 127, range_subid = 11, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 14), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 14, 1), 0);
+       message_add_uint32(&msg, upperbound);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_range_overlap_single(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid, upperbound = 10;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 15), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 15, 1), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       packetid = arc4random();
+       range_subid = 11;
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 15, 1), 0);
+       message_add_uint32(&msg, upperbound);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           DUPLICATEREGISTRATION, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_single_overlap_range(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid, upperbound = 10;
+       uint8_t timeout = 0, priority = 127, range_subid = 11, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 16), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 16, 1), 0);
+       message_add_uint32(&msg, upperbound);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       packetid = arc4random();
+       range_subid = 0;
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 16, 1), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           DUPLICATEREGISTRATION, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_range_overlap_range(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid, upperbound = 10;
+       uint8_t timeout = 0, priority = 127, range_subid = 11, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 17), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 17, 1), 0);
+       message_add_uint32(&msg, upperbound);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       packetid = arc4random();
+       upperbound = 15;
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 17, 6), 0);
+       message_add_uint32(&msg, upperbound);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           DUPLICATEREGISTRATION, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_below(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 18), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 18, 1), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       packetid = arc4random();
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 18, 1, 0), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_above(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 19), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 19, 1, 1), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       packetid = arc4random();
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_REGISTER, 19, 1), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_register_restricted(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t timeout = 0, priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_REGISTER, 20), __func__);
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(SYSORTABLE, 1, 1), 0);
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           REQUESTDENIED, 0, NULL, 0);
+
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_notopen(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint8_t priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, 0, 0, packetid);
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 1, 0), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOTOPEN, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_invalid_sessionid(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 2), __func__);
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, sessionid + 1, 0,
+           packetid);
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 2, 0), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOTOPEN, 0,
+           NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_notregistered(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 3), __func__);
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 3), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           UNKNOWNREGISTRATION, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_single(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 4), __func__);
+       agentx_register(s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_UNREGISTER, 4), 0);
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 4), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_single_notowned(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid1, sessionid2;
+       uint8_t priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 5, 1),
+           "agentx_unregister_single_notowned.1");
+       sessionid2 = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 5, 2),
+           "agentx_unregister_single_notowned.2");
+       agentx_register(s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_UNREGISTER, 5, 1), 0);
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, sessionid2, 0,
+           packetid);
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 5, 1), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           UNKNOWNREGISTRATION, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_range(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t priority = 127, range_subid = 11, reserved = 0;
+       uint32_t upperbound = 10;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 6), __func__);
+       agentx_register(s, sessionid, 0, 0, 127, 11,
+           OID_ARG(MIB_UNREGISTER, 6, 1), 10);
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 6, 1), 0);
+       message_add_uint32(&msg, upperbound);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           NOAGENTXERROR, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_range_single(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t priority = 127, range_subid = 0, reserved = 0;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 7), __func__);
+       agentx_register(s, sessionid, 0, 0, 127, 11,
+           OID_ARG(MIB_UNREGISTER, 6, 1), 10);
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 7, 1), 0);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           UNKNOWNREGISTRATION, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_range_subset(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t priority = 127, range_subid = 11, reserved = 0;
+       uint32_t upperbound = 5;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 8), __func__);
+       agentx_register(s, sessionid, 0, 0, 127, 11,
+           OID_ARG(MIB_UNREGISTER, 8, 1), 10);
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 8, 1), 0);
+       message_add_uint32(&msg, upperbound);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           UNKNOWNREGISTRATION, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_range_extra(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t priority = 127, range_subid = 11, reserved = 0;
+       uint32_t upperbound = 10;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 9), __func__);
+       agentx_register(s, sessionid, 0, 0, 127, 11,
+           OID_ARG(MIB_UNREGISTER, 9, 1), upperbound);
+       upperbound = 15;
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 9, 1), 0);
+       message_add_uint32(&msg, upperbound);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           UNKNOWNREGISTRATION, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_range_priority(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid;
+       uint8_t priority = 127, range_subid = 11, reserved = 0;
+       uint32_t upperbound = 10;
+
+       s = agentx_connect(axsocket);
+       sessionid = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 10), __func__);
+       agentx_register(s, sessionid, 0, 0, priority, 11,
+           OID_ARG(MIB_UNREGISTER, 10, 1), upperbound);
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, sessionid, 0,
+           packetid);
+       priority = 128;
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 10, 1), 0);
+       message_add_uint32(&msg, upperbound);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           UNKNOWNREGISTRATION, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_unregister_range_notowned(void)
+{
+       int s;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint32_t sessionid1, sessionid2;
+       uint8_t priority = 127, range_subid = 11, reserved = 0;
+       uint32_t upperbound = 10;
+
+       s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 11, 1),
+           "agentx_unregister_range_notowned.1");
+       sessionid2 = agentx_open(s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_UNREGISTER, 11, 2),
+           "agentx_unregister_range_notowned.2");
+       agentx_register(s, sessionid1, 0, 0, priority, 11,
+           OID_ARG(MIB_UNREGISTER, 11, 1), upperbound);
+       message_add_header(&msg, 1, AGENTX_UNREGISTER_PDU, 0, sessionid2, 0,
+           packetid);
+       priority = 128;
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, OID_ARG(MIB_UNREGISTER, 10, 1), 0);
+       message_add_uint32(&msg, upperbound);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid,
+           UNKNOWNREGISTRATION, 0, NULL, 0);
+       message_release(&msg);
+       close(s);
+}
+
+void
+agentx_get_handle(const char *test, const void *buf, size_t len,
+    uint8_t flags, uint32_t sessionid, struct varbind *varbind,
+    size_t nvarbind)
+{
+       const struct header *header = buf;
+       struct oid start, end, zero = {0};
+       const uint8_t *u8;
+       uint32_t u32;
+       uint16_t u16;
+       size_t sublen, i, j;
+       char oid1[512], oid2[512];
+       struct varbind *pool;
+
+       if (len < sizeof(*header))
+               errx(1, "%s: unexpected pdu message size received: %zu", test, len);
+       if (header->version != 1)
+               errx(1, "%s: invalid pdu version", test);
+       if (header->type != AGENTX_GET_PDU)
+               errx(1, "%s: invalid pdu type received (%hhu/5)", test, header->type);
+       if (header->flags != flags)
+               errx(1, "%s: invalid get pdu flags received (%hhu/%hhu)",
+                   test, header->flags, flags);
+       if (header->reserved != 0)
+               errx(1, "%s: invalid get pdu reserved received", test);
+       if (p32toh(header, header->sessionid) != sessionid)
+               errx(1, "%s: unexpected get pdu sessionid (%u/%u)", test,
+                   p32toh(header, header->sessionid), sessionid);
+       if (p32toh(header, header->payload_length) > len - sizeof(*header))
+               errx(1, "%s: unexpected get pdu payload length received",
+                   test);
+
+       buf += sizeof(*header);
+       len = p32toh(header, header->payload_length);
+
+       if ((pool = calloc(nvarbind, sizeof(*pool))) == NULL)
+               err(1, NULL);
+       memcpy(pool, varbind, nvarbind * sizeof(*pool));
+
+       for (i = 0; len > 0; i++) {
+               sublen = poid(test, header, buf, len, &start);
+               buf += sublen;
+               len -= sublen;
+               sublen = poid(test, header, buf, len, &end);
+               buf += sublen;
+               len -= sublen;
+
+               if (oid_cmp(&end, &zero) != 0)
+                       errx(1, "%s: unexpected searchrange end: (%s/%s)", test,
+                           oid_print(&end, oid1, sizeof(oid1)),
+                           oid_print(&zero, oid2, sizeof(oid2)));
+               if (start.include != 0 || end.include != 0)
+                       errx(1, "%s: unexpected searchrange include: (%s)",
+                           test, oid_print(&start, oid1, sizeof(oid1)));
+               for (j = 0; j < nvarbind; j++) {
+                       if (oid_cmp(&pool[j].name, &start) == 0)
+                               break;
+               }
+               if (j == nvarbind)
+                       warnx("%s: unexpected searchrange start: " "(%s)", test,
+                           oid_print(&start, oid1, sizeof(oid1)));
+
+               varbind[i] = pool[j];
+               pool[j].name.n_subid = 0;
+       }
+       free(pool);
+}
+
+void
+agentx_getnext_handle(const char *test, const void *buf, size_t len,
+    uint8_t flags, uint32_t sessionid, struct searchrange *searchrange,
+    struct varbind *varbind, size_t nvarbind)
+{
+       const struct header *header = buf;
+       struct oid start, end, zero = {0};
+       const uint8_t *u8;
+       uint32_t u32;
+       uint16_t u16;
+       size_t sublen, i, j, match;
+       char oid1[512], oid2[512], oid3[512], oid4[512];
+       struct varbind *pool;
+
+       if (len < sizeof(*header))
+               errx(1, "%s: unexpected pdu message size received: %zu", test, len);
+       if (header->version != 1)
+               errx(1, "%s: invalid pdu version", test);
+       if (header->type != AGENTX_GETNEXT_PDU)
+               errx(1, "%s: invalid pdu type received (%hhu/6)", test, header->type);
+       if (header->flags != flags)
+               errx(1, "%s: invalid get pdu flags received (%hhu/%hhu)",
+                   test, header->flags, flags);
+       if (header->reserved != 0)
+               errx(1, "%s: invalid get pdu reserved received", test);
+       if (p32toh(header, header->sessionid) != sessionid)
+               errx(1, "%s: unexpected get pdu sessionid (%u/%u)", test,
+                   p32toh(header, header->sessionid), sessionid);
+       if (p32toh(header, header->payload_length) > len - sizeof(*header))
+               errx(1, "%s: unexpected get pdu payload length received",
+                   test);
+
+       buf += sizeof(*header);
+       len = p32toh(header, header->payload_length);
+
+       if ((pool = calloc(nvarbind, sizeof(*pool))) == NULL)
+               err(1, NULL);
+       memcpy(pool, varbind, nvarbind * sizeof(*pool));
+
+       for (i = 0; len > 0; i++) {
+               sublen = poid(test, header, buf, len, &start);
+               buf += sublen;
+               len -= sublen;
+               sublen = poid(test, header, buf, len, &end);
+               buf += sublen;
+               len -= sublen;
+
+               if ((start.include != 1 && start.include != 0) ||
+                   end.include != 0)
+                       errx(1, "%s: unexpected searchrange include: (%s-%s)",
+                           test, oid_print(&start, oid1, sizeof(oid1)),
+                           oid_print(&end, oid2, sizeof(oid2)));
+
+               match = (size_t)-1;
+               for (j = 0; j < nvarbind; j++) {
+                       if (oid_cmp(&pool[j].name, &start) == 0 &&
+                           pool[j].type == TYPE_ENDOFMIBVIEW) {
+                               match = j;
+                       } else if (oid_cmp(&pool[j].name, &start) < 0 ||
+                           (!start.include &&
+                           oid_cmp(&pool[j].name, &start) == 0) ||
+                           oid_cmp(&pool[j].name, &end) >= 0)
+                               continue;
+                       if (match == (size_t)-1)
+                               match = j;
+                       else {
+                               if (oid_cmp(&pool[j].name,
+                                   &pool[match].name) < 0)
+                                       match = j;
+                       }
+               }
+               if (match == (size_t)-1)
+                       errx(1, "%s: unexpected searchrange start: " "(%s-%s)",
+                           test,
+                           oid_print(&start, oid1, sizeof(oid1)),
+                           oid_print(&end, oid2, sizeof(oid2)));
+               if (searchrange != NULL) {
+                       if (oid_cmp(&searchrange[match].start, &start) != 0 ||
+                           oid_cmp(&searchrange[match].end, &end) != 0 ||
+                           searchrange[match].end.include != end.include ||
+                           searchrange[match].start.include != start.include)
+                               errx(1, "%s: searchrange did not match "
+                                   "(%s-%s/%s-%s)", test,
+                                   oid_print(&start, oid1, sizeof(oid1)),
+                                   oid_print(&end, oid2, sizeof(oid2)),
+                                   oid_print(&searchrange[match].start, oid3,
+                                   sizeof(oid3)),
+                                   oid_print(&searchrange[match].end, oid4,
+                                   sizeof(oid4)));
+               }
+
+               varbind[i] = pool[match];
+               pool[match].name.n_subid = 0;
+       }
+       free(pool);
+}
+
+/*
+ * Don't assume a specific sequence of requests here so we can more easily
+ * migrate to getbulk in agentx.
+ */
+size_t
+agentx_getbulk_handle(const char *test, const void *buf, size_t len,
+    uint8_t flags, int32_t sessionid, struct varbind *varbind, size_t nvarbind,
+    struct varbind *outvarbind)
+{
+       const struct header *header = buf;
+       struct oid start, end, zero = {0};
+       const uint8_t *u8;
+       uint16_t nonrep, maxrep;
+       uint32_t u32;
+       uint16_t u16;
+       size_t sublen, i, j, match;
+       size_t nout = 0;
+       char oid1[512], oid2[512], oid3[512], oid4[512];
+
+       if (len < sizeof(*header))
+               errx(1, "%s: unexpected pdu message size received: %zu", test, len);
+       if (header->version != 1)
+               errx(1, "%s: invalid pdu version", test);
+       if (header->type != AGENTX_GETNEXT_PDU &&
+           header->type != AGENTX_GETBULK_PDU)
+               errx(1, "%s: invalid pdu type received (%hhu/[67])",
+                   test, header->type);
+       if (header->flags != flags)
+               errx(1, "%s: invalid get pdu flags received (%hhu/%hhu)",
+                   test, header->flags, flags);
+       if (header->reserved != 0)
+               errx(1, "%s: invalid get pdu reserved received", test);
+       if (p32toh(header, header->sessionid) != sessionid)
+               errx(1, "%s: unexpected get pdu sessionid (%u/%u)", test,
+                   p32toh(header, header->sessionid), sessionid);
+       if (p32toh(header, header->payload_length) > len - sizeof(*header))
+               errx(1, "%s: unexpected get pdu payload length received",
+                   test);
+
+       buf += sizeof(*header);
+       len = p32toh(header, header->payload_length);
+
+       if (header->type == AGENTX_GETBULK_PDU) {
+               if (len < 4)
+                       errx(1, "%s: missing non_repeaters/max_repititions",
+                           __func__);
+               memcpy(&u16, buf, sizeof(u16));
+               nonrep = p16toh(header, u16);
+               memcpy(&u16, buf + sizeof(u16), sizeof(u16));
+               maxrep = p16toh(header, u16);
+               buf += 4;
+       } else {
+               nonrep = 0;
+               maxrep = 1;
+       }
+       for (i = 0; len > 0; i++) {
+               sublen = poid(test, header, buf, len, &start);
+               buf += sublen;
+               len -= sublen;
+               sublen = poid(test, header, buf, len, &end);
+               buf += sublen;
+               len -= sublen;
+
+               if ((start.include != 1 && start.include != 0) ||
+                   end.include != 0)
+                       errx(1, "%s: unexpected searchrange include: (%s-%s)",
+                           test, oid_print(&start, oid1, sizeof(oid1)),
+                           oid_print(&end, oid2, sizeof(oid2)));
+
+               match = (size_t)-1;
+               for (j = 0; j < nvarbind; j++) {
+                       if (oid_cmp(&varbind[j].name, &start) == 0 &&
+                           varbind[j].type == TYPE_ENDOFMIBVIEW) {
+                               match = j;
+                       } else if (oid_cmp(&varbind[j].name, &start) < 0 ||
+                           (!start.include &&
+                           oid_cmp(&varbind[j].name, &start) == 0) ||
+                           oid_cmp(&varbind[j].name, &end) >= 0)
+                               continue;
+                       if (match == (size_t)-1)
+                               match = j;
+                       else {
+                               if (oid_cmp(&varbind[j].name,
+                                   &varbind[match].name) < 0)
+                                       match = j;
+                       }
+               }
+               if (match == (size_t)-1)
+                       errx(1, "%s: unexpected searchrange start: " "(%s-%s)",
+                           test,
+                           oid_print(&start, oid1, sizeof(oid1)),
+                           oid_print(&end, oid2, sizeof(oid2)));
+               outvarbind[nout++] = varbind[match];
+               varbind[match] = varbind[--nvarbind];
+               varbind[nvarbind] = (struct varbind){};
+       }
+       return nout;
+}
+
+void
+agentx_close_validate(const char *test, const void *buf, size_t len,
+    uint8_t flags, uint8_t reason)
+{
+       const struct header *header = buf;
+       const uint8_t *u8;
+       uint32_t u32;
+       uint16_t u16;
+
+       if (len != sizeof(*header) + 4)
+               errx(1, "%s: unexpected pdu message size received: %zu", test, len);
+       if (header->version != 1)
+               errx(1, "%s: invalid pdu version", test);
+       if (header->type != AGENTX_CLOSE_PDU)
+               errx(1, "%s: invalid pdu type received (%hhu/2)", test, header->type);
+       if (header->flags != flags)
+               errx(1, "%s: invalid close pdu flags received (%hhu/%hhu)",
+                   test, header->flags, flags);
+       if (header->reserved != 0)
+               errx(1, "%s: invalid close pdu reserved received", test);
+       if (p32toh(header, header->payload_length) != 4)
+               errx(1, "%s: unexpected response pdu payload length received",
+                   test);
+
+       u8 = buf + sizeof(*header);
+       if (u8[0] != reason)
+               errx(1, "%s: unexpected close reason (%hhu/%hhu)",
+                   test, u8[0], reason);
+       if (u8[1] != 0 || u8[2] != 0 || u8[3] != 0)
+               errx(1, "%s: invalid close pdu reserved received", test);
+}
+
+void
+agentx_response_validate(const char *test, const void *buf, size_t len,
+    uint8_t flags, uint32_t packetid, enum error error, uint16_t index,
+    struct varbind *varbindlist, size_t nvarbind)
+{
+       const struct header *header = buf;
+       struct oid name, oid;
+       int32_t i32;
+       uint32_t u32;
+       uint16_t u16, type;
+       size_t i, sublen;
+
+       if (len < sizeof(*header) + 8)
+               errx(1, "%s: unexpected pdu message size received: %zu", test, len);
+       if (header->version != 1)
+               errx(1, "%s: invalid pdu version", test);
+       if (header->type != AGENTX_RESPONSE_PDU)
+               errx(1, "%s: invalid pdu type received (%hhu/18)", test, header->type);
+       if (header->flags != flags)
+               errx(1, "%s: invalid response pdu flags received (%hhu/%hhu)",
+                   test, header->flags, flags);
+       if (header->reserved != 0)
+               errx(1, "%s: invalid response pdu reserved received", test);
+       if (p32toh(header, header->packetid) != packetid)
+               errx(1, "%s: invalid response pdu packetid received", test);
+       /*
+        * Needs to be changed once we start validating responses with varbinds.
+        */
+       if (p32toh(header, header->payload_length) < 8 ||
+           p32toh(header, header->payload_length) > len - sizeof(*header))
+               errx(1, "%s: unexpected response pdu payload length received",
+                   test);
+
+       buf += sizeof(*header);
+       len = p32toh(header, header->payload_length);
+       memcpy(&u32, buf, sizeof(u32));
+       if ((p32toh(header, u32) & 0xF0000000) != 0)
+               errx(1, "%s: unexpected response pdu sysUptime received",
+                   test);
+       buf += sizeof(u32);
+       memcpy(&u16, buf, sizeof(u16));
+       if (p16toh(header, u16) != error)
+               errx(1, "%s: unexpected response pdu error (%hu/%u)",
+                   test, p16toh(header, u16), error);
+       buf += sizeof(u16);
+       memcpy(&u16, buf, sizeof(u16));
+       if (p16toh(header, u16) != index)
+               errx(1, "%s: unexpected response pdu index (%hu/%hu)",
+                   test, p16toh(header, u16), index);
+       buf += sizeof(u16);
+       len -= 8;
+
+       for (i = 0; len > 0; i++) {
+               if (len < 4)
+                       errx(1,
+                           "%s: invalid response pdu varbind length", test);
+               memcpy(&type, buf, sizeof(type));
+               type = p16toh(header, type);
+               if (i < nvarbind && type != varbindlist[i].type % 1000)
+                       errx(1, "%s: invalid response pdu varbind type", test);
+               buf += sizeof(type);
+               len -= sizeof(type);
+               memcpy(&u16, buf, sizeof(u16));
+               if (u16 != 0)
+                       errx(1, "%s: invalid response pdu varbind reserved",
+                           test);
+               buf += sizeof(u16);
+               len -= sizeof(u16);
+               sublen = poid(test, header, buf, len, &name);
+               if (i < nvarbind && oid_cmp(&varbindlist[i].name, &name) != 0)
+                       errx(1, "%s: invalid response pdu varbind name", test);
+               buf += sublen;
+               len -= sublen;
+               switch (type % 1000) {
+               case TYPE_INTEGER:
+                       if (len < sizeof(i32))
+                               errx(1,
+                                   "%s: invalid response pdu varbind length",
+                                   test);
+                       if (i < nvarbind && varbindlist[i].type / 1000 == 0) {
+                               memcpy(&i32, buf, sizeof(i32));
+                               i32 = p32toh(header, i32);
+                               if (i32 != varbindlist[i].data.int32)
+                                       errx(1, "%s: invalid response pdu "
+                                           "varbind integer", test);
+                       }
+                       break;
+               default:
+                       errx(1, "%s: Regress test not implemented: %d", test, type);
+               }
+       }
+
+       if (i != nvarbind)
+               errx(1, "%s: unexpected response pdu nvarbind: (%zu/%zu)",
+                   test, i, nvarbind);
+}
+
+int
+agentx_connect(const char *path)
+{
+       struct sockaddr_un sun;
+       int s;
+
+       if (path == NULL)
+               path = AGENTX_SOCKET;
+
+       sun.sun_len = sizeof(sun);
+       sun.sun_family = AF_UNIX;
+       strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
+
+       if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+               err(1, "%s: socket", __func__);
+       if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) == -1)
+               err(1, "%s: connect", __func__);
+
+       return s;
+}
+
+uint32_t
+agentx_open(int s, int nbo, uint8_t timeout, uint32_t oid[], size_t oidlen,
+     const char *descr)
+{
+       struct message msg ={};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       struct header *header = (struct header *)repl;
+
+       message_add_header(&msg, 1, AGENTX_OPEN_PDU,
+           nbo ? NETWORK_BYTE_ORDER : 0, 0, 0, packetid);
+       message_add_uint8(&msg, timeout);
+       message_add(&msg, zero, 3);
+       message_add_oid(&msg, oid, oidlen, 0);
+       message_add_nstring(&msg, descr, strlen(descr));
+
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n,
+           nbo ? NETWORK_BYTE_ORDER : 0, packetid, 0, 0, NULL, 0);
+
+       message_release(&msg);
+
+       return p32toh(header, header->sessionid);
+}
+
+void
+agentx_close(int s, uint32_t sessionid, enum close_reason reason)
+{
+       struct message msg ={};
+       char zero[3] = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       struct header *header = (struct header *)repl;
+
+       message_add_header(&msg, 1, AGENTX_CLOSE_PDU, 0, sessionid, 0,
+           packetid);
+       message_add_uint8(&msg, reason);
+       message_add(&msg, zero, 3);
+
+       agentx_write(s, &msg);
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, 0, 0, NULL, 0);
+
+       message_release(&msg);
+}
+
+void
+agentx_register(int s, uint32_t sessionid, uint8_t instance, uint8_t timeout,
+    uint8_t priority, uint8_t range_subid, uint32_t oid[], size_t oidlen,
+    uint32_t upperbound)
+{
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t packetid = arc4random();
+       uint8_t reserved = 0;
+
+       message_add_header(&msg, 1, AGENTX_REGISTER_PDU,
+           instance ? INSTANCE_REGISTRATION : 0, sessionid, 0, packetid);
+       message_add(&msg, &timeout, sizeof(timeout));
+       message_add(&msg, &priority, sizeof(priority));
+       message_add(&msg, &range_subid, sizeof(range_subid));
+       message_add(&msg, &reserved, sizeof(reserved));
+       message_add_oid(&msg, oid, oidlen, 0);
+       if (range_subid != 0)
+               message_add_uint32(&msg, upperbound);
+
+       agentx_write(s, &msg);
+
+       n = agentx_read(s, repl, sizeof(repl), 1000);
+
+       agentx_response_validate(__func__, repl, n, 0, packetid, NOAGENTXERROR, 0,
+           NULL, 0);
+       message_release(&msg);
+}
+
+void
+agentx_response(int s, void *buf, enum error error, uint16_t index,
+    struct varbind *varbindlist, size_t nvarbind)
+{
+       struct header *header = buf;
+       struct message msg = {};
+       char repl[1024];
+       size_t n;
+       uint32_t sysuptime = 0;
+       uint16_t reserved = 0;
+       size_t i;
+
+       message_add_header(&msg, 1, AGENTX_RESPONSE_PDU, 0,
+           p32toh(header, header->sessionid),
+           p32toh(header, header->transactionid),
+           p32toh(header, header->packetid));
+       message_add_uint32(&msg, sysuptime);
+       message_add_uint16(&msg, error);
+       message_add_uint16(&msg, index);
+
+       for (i = 0; i < nvarbind; i++)
+               message_add_varbind(&msg, varbindlist + i);
+
+       agentx_write(s, &msg);
+       message_release(&msg);
+}
+
+static void
+message_add_uint8(struct message *msg, uint8_t n)
+{
+       message_add(msg, &n, 1);
+}
+
+static void
+message_add_uint16(struct message *msg, uint16_t n)
+{
+       if (MESSAGE_NBO(msg))
+               n = htobe16(n);
+       else
+               n = htole16(n);
+
+       message_add(msg, &n, sizeof(n));
+}
+
+static void
+message_add_uint32(struct message *msg, uint32_t n)
+{
+       if (MESSAGE_NBO(msg))
+               n = htobe32(n);
+       else
+               n = htole32(n);
+
+       message_add(msg, &n, sizeof(n));
+}
+
+static void
+message_add_uint64(struct message *msg, uint64_t n)
+{
+       if (MESSAGE_NBO(msg))
+               n = htobe64(n);
+       else
+               n = htole64(n);
+
+       message_add(msg, &n, sizeof(n));
+}
+
+static void
+message_add_nstring(struct message *msg, const void *src, uint32_t len)
+{
+       char zero[3] = {};
+
+       message_add_uint32(msg, len);
+       if (len == 0)
+               return;
+       message_add(msg, src, len);
+       message_add(msg, zero, (4 - (len % 4)) % 4);
+}
+
+static void
+message_add_oid(struct message *msg, const uint32_t oid[], uint8_t n_subid,
+    uint8_t include)
+{
+       uint8_t prefix = 0;
+       uint8_t i;
+
+       if (n_subid > 5 && oid[0] == 1 && oid[1] == 3 && oid[2] == 6 &&
+           oid[3] == 1 && oid[4] < UINT8_MAX) {
+               prefix = oid[4];
+               oid += 5;
+               n_subid -= 5;
+       }
+
+       message_add_uint8(msg, n_subid);
+       message_add_uint8(msg, prefix);
+       message_add_uint8(msg, include);
+       message_add_uint8(msg, 0);
+       for (i = 0; i < n_subid; i++)
+               message_add_uint32(msg, oid[i]);
+}
+
+static void
+message_add_varbind(struct message *msg, struct varbind *varbind)
+{
+       uint64_t u64;
+       uint32_t u32;
+       size_t len;
+       va_list ap;
+
+       message_add_uint16(msg, varbind->type);
+       message_add_uint16(msg, 0);
+       message_add_oid(msg, varbind->name.subid, varbind->name.n_subid, 0);
+       switch (varbind->type) {
+       case INTEGER:
+               message_add_uint32(msg, varbind->data.int32);
+               break;
+       case COUNTER32:
+       case GAUGE32:
+       case TIMETICKS:
+               message_add_uint32(msg, varbind->data.uint32);
+               break;
+       case OCTETSTRING:
+       case IPADDRESS:
+       case OPAQUE:
+               message_add_nstring(msg, varbind->data.octetstring.string,
+                   varbind->data.octetstring.len);
+               break;
+       case OBJECTIDENTIFIER:
+               message_add_oid(msg, varbind->data.oid.subid,
+                   varbind->data.oid.n_subid, 0);
+               break;
+       case COUNTER64:
+               message_add_uint64(msg, varbind->data.uint64);
+               break;
+       case AXNULL:
+       case NOSUCHOBJECT:
+       case NOSUCHINSTANCE:
+       case ENDOFMIBVIEW:
+               break;
+       default:
+               errx(1, "%s: unsupported data type: %d", __func__,
+                   varbind->type);
+       }
+}
+
+static void
+message_add_header(struct message *msg, uint8_t version, uint8_t type,
+    uint8_t flags, uint32_t sessionid, uint32_t transactionid,
+    uint32_t packetid)
+{
+       if (msg->len != 0)
+               errx(1, "%s: message not new", __func__);
+       message_add_uint8(msg, version);
+       message_add_uint8(msg, type);
+       message_add_uint8(msg, flags);
+       message_add_uint8(msg, 0);
+       message_add_uint32(msg, sessionid);
+       message_add_uint32(msg, transactionid);
+       message_add_uint32(msg, packetid);
+       message_add_uint32(msg, 0); /* payload_length tbt */
+}
+
+static void
+message_add(struct message *msg, const void *src, size_t len)
+{
+       if (len == 0)
+               return;
+       if (msg->len + len > msg->size) {
+               if ((msg->buf = recallocarray(msg->buf, msg->size,
+                   (((msg->len + len) % 4096) + 1) * 4096, 1)) == NULL)
+                       err(1, NULL);
+               msg->size = (((msg->len + len) % 4096) + 1) * 4096;
+       }
+       memcpy(msg->buf + msg->len, src, len);
+       msg->len += len;
+}
+
+static void
+message_release(struct message *msg)
+{
+       free(msg->buf);
+}
+
+static size_t
+poid(const char *test, const struct header *header, const uint8_t *buf, size_t len,
+    struct oid *oid)
+{
+       uint8_t n_subid, i;
+       uint32_t subid;
+
+       if (len < 4)
+               errx(1, "%s: incomplete oid", test);
+       n_subid = buf[0];
+       if (buf[1] != 0) {
+               *oid = OID_STRUCT(1, 3, 6, 1, buf[1]);
+       } else
+               *oid = OID_STRUCT();
+       oid->include = buf[2];
+       if (buf[3] != 0)
+               errx(1, "%s: invalid oid reserved (%hhx)", test, buf[3]);
+       buf += 4;
+       len -= 4;
+       if (oid->n_subid + n_subid > 128)
+               errx(1, "%s: too many n_subid in oid", test);
+       if (len < n_subid * sizeof(oid->subid[0]))
+               errx(1, "%s: incomplete oid: (%zu/%zu)", test,
+                   n_subid * sizeof(oid->subid[0]), len);
+       for (i = 0; i < n_subid; i++) {
+               memcpy(&subid, buf, sizeof(subid));
+               buf += 4;
+               oid->subid[oid->n_subid++] = p32toh(header, subid);
+       }
+
+       return 4 * (n_subid + 1);
+}
+
+size_t
+agentx_read(int s, void *buf, size_t len, int timeout)
+{
+       ssize_t n;
+       size_t i;
+       int ret;
+       struct pollfd pfd = {
+               .fd = s,
+               .events = POLLIN
+       };
+
+       if ((ret = poll(&pfd, 1, timeout)) == -1)
+               err(1, "poll");
+       if (ret == 0)
+               errx(1, "%s: timeout", __func__);
+       if ((n = read(s, buf, len)) == -1)
+               err(1, "agentx read");
+
+       if (verbose && n != 0) {
+               printf("AgentX received(%d):\n", s);
+               for (i = 0; i < n; i++) {
+                       printf("%s%02hhx", i % 4 == 0 ? "" : " ",
+                           ((char *)buf)[i]);
+                       if (i % 4 == 3)
+                               printf("\n");
+               }
+               if (i % 4 != 0)
+                       printf("\n");
+       }
+       return n;
+}
+
+void
+agentx_timeout(int s, int timeout)
+{
+       int ret;
+       struct pollfd pfd = {
+               .fd = s,
+               .events = POLLIN
+       };
+       
+       if ((ret = poll(&pfd, 1, timeout)) == -1)
+               err(1, "poll");
+       if (ret != 0)
+               errx(1, "%s: unexpected agentx data", __func__);
+}
+
+void
+agentx_write(int s, struct message *msg)
+{
+       ssize_t n;
+       char *buf = msg->buf;
+       size_t len = msg->len;
+       struct header *header = msg->buf;
+       size_t i;
+
+       msg->len = 16;
+       message_add_uint32(msg, len - sizeof(*header));
+
+       if (verbose) {
+               printf("AgentX sending(%d):\n", s);
+               for (i = 0; i < len; i++) {
+                       printf("%s%02hhx", i % 4 == 0 ? "" : " ", buf[i]);
+                       if (i % 4 == 3)
+                               printf("\n");
+               }
+               if (i % 4 != 0)
+                       printf("\n");
+       }
+
+       while (len > 0) {
+               if ((n = write(s, buf, len)) == -1)
+                       err(1, "agentx write");
+               buf += n;
+               len -= n;
+       }
+       msg->len = 0;
+}
diff --git a/regress/usr.sbin/snmpd/backend.c b/regress/usr.sbin/snmpd/backend.c
new file mode 100644 (file)
index 0000000..52f19e4
--- /dev/null
@@ -0,0 +1,5152 @@
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "regress.h"
+
+#define MIB_BACKEND_GET MIB_BACKEND, 1
+#define MIB_BACKEND_GETNEXT MIB_BACKEND, 2
+#define MIB_BACKEND_GETBULK MIB_BACKEND, 3
+#define MIB_BACKEND_ERROR MIB_BACKEND, 4
+
+#define MIB_SUBAGENT_BACKEND_GET MIB_SUBAGENT_BACKEND, 1
+#define MIB_SUBAGENT_BACKEND_GETNEXT MIB_SUBAGENT_BACKEND, 2
+#define MIB_SUBAGENT_BACKEND_GETBULK MIB_SUBAGENT_BACKEND, 3
+#define MIB_SUBAGENT_BACKEND_ERROR MIB_SUBAGENT_BACKEND, 4
+
+#define nitems(_a)     (sizeof((_a)) / sizeof((_a)[0]))
+
+void
+backend_get_integer(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 1, 0),
+               .data.int32 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 1), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_octetstring(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 2, 0),
+               .data.octetstring.string = "test",
+               .data.octetstring.len = 4
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 2), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 2), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_OCTETSTRING;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_objectidentifier(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 3, 0),
+               .data.oid = OID_STRUCT(MIB_BACKEND_GET, 3, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 3), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 3), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_OBJECTIDENTIFIER;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_ipaddress(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 4, 0),
+               .data.octetstring.string = "\0\0\0\0",
+               .data.octetstring.len = 4
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 4), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 4), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_IPADDRESS;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_counter32(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 5, 0),
+               .data.uint32 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 5), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 5), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_COUNTER32;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_gauge32(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 6, 0),
+               .data.uint32 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 6), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 6), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_GAUGE32;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_timeticks(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 7, 0),
+               .data.uint32 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 7), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 7), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_TIMETICKS;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_opaque(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 8, 0),
+               .data.octetstring.string = "\1",
+               .data.octetstring.len = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 8), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 8), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_OPAQUE;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_counter64(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 9, 0),
+               .data.uint64 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 9), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 9), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_COUNTER64;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_nosuchobject(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 10, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 10), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 10), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_NOSUCHOBJECT;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_nosuchinstance(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 11, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 11), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 11), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_NOSUCHINSTANCE;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_endofmibview(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 12, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 12), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 12), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_ENDOFMIBVIEW;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       varbind.type = TYPE_NULL;
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_get_two_single_backend(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 13, 1),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 13, 2),
+                       .data.int32 = 2
+               }
+       };
+       struct varbind varbind_ax[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 13, 1),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 13, 2),
+                       .data.int32 = 2
+               }
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 13), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 13), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, varbind, 2);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, varbind_ax, 2);
+
+       agentx_response(ax_s, buf, NOERROR, 0, varbind_ax, 2);
+
+       varbind[0].type = varbind[1].type = TYPE_INTEGER;
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           varbind, 2);
+}
+
+void
+backend_get_two_double_backend(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s1, ax_s2;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 14, 1),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 14, 2),
+                       .data.int32 = 2
+               }
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s1 = agentx_connect(axsocket);
+       ax_s2 = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s1, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 14, 1),
+           "backend_get_two_double_backend.1");
+       sessionid2 = agentx_open(ax_s2, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 14, 2),
+           "backend_get_two_double_backend.2");
+       agentx_register(ax_s1, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 14, 1), 0);
+       agentx_register(ax_s2, sessionid2, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 14, 2), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, varbind, 2);
+
+       varbind[0].type = varbind[1].type = TYPE_INTEGER;
+       n = agentx_read(ax_s1, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid1, varbind, 1);
+       agentx_response(ax_s1, buf, NOERROR, 0, varbind, 1);
+
+       n = agentx_read(ax_s2, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid2, varbind + 1, 1);
+       agentx_response(ax_s2, buf, NOERROR, 0, varbind + 1, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           varbind, 2);
+}
+
+void
+backend_get_wrongorder(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 15, 1),
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 15, 2),
+               }
+       };
+       struct varbind varbind_ax[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 15, 1),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 15, 2),
+                       .data.int32 = 2
+               }
+       }, tmpvarbind;
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 15), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 15), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, varbind, 2);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, varbind_ax, 2);
+       tmpvarbind = varbind_ax[0];
+       varbind_ax[0] = varbind_ax[1];
+       varbind_ax[1] = tmpvarbind;
+
+       agentx_response(ax_s, buf, NOERROR, 0, varbind_ax, 2);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 2,
+           varbind, 2);
+}
+
+void
+backend_get_toofew(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 16, 1),
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 16, 2),
+               }
+       };
+       struct varbind varbind_ax[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 16, 1),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 16, 2),
+                       .data.int32 = 2
+               }
+       }, tmpvarbind;
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 16), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 16), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, varbind, 2);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, varbind_ax, 2);
+
+       agentx_response(ax_s, buf, NOERROR, 0, varbind_ax, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 2,
+           varbind, 2);
+}
+
+void
+backend_get_toomany(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 17, 1),
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 17, 2),
+               }
+       };
+       struct varbind varbind_ax[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 17, 1),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 17, 2),
+                       .data.int32 = 2
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GET, 17, 3),
+                       .data.int32 = 3
+               }
+       }, tmpvarbind;
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 17), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 17), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, varbind, 2);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, varbind_ax, 2);
+
+       agentx_response(ax_s, buf, NOERROR, 0, varbind_ax, 3);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 2,
+           varbind, 2);
+}
+
+void
+backend_get_instance(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 18, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 18), __func__);
+       agentx_register(ax_s, sessionid, 1, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 18, 0), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_instance_below(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 19, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 19), __func__);
+       agentx_register(ax_s, sessionid, 1, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 19), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       varbind.type = TYPE_NOSUCHINSTANCE;
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_timeout_default(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 20, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+       struct timespec start, end, diff;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 20), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 20), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
+               err(1, "clock_gettime");
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 6000, community, requestid, GENERR, 1,
+           &varbind, 1);
+       if (clock_gettime(CLOCK_MONOTONIC, &end) == -1)
+               err(1, "clock_gettime");
+       timespecsub(&end, &start, &diff);
+       if (diff.tv_sec != 5)
+               errx(1, "%s: unexpected timeout (%lld.%09ld/5)", __func__,
+                   diff.tv_sec, diff.tv_nsec);
+}
+
+void
+backend_get_timeout_session_lower(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 21, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+       struct timespec start, end, diff;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 1,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 21), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 21), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
+               err(1, "clock_gettime");
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 6000, community, requestid, GENERR, 1,
+           &varbind, 1);
+       if (clock_gettime(CLOCK_MONOTONIC, &end) == -1)
+               err(1, "clock_gettime");
+       timespecsub(&end, &start, &diff);
+       if (diff.tv_sec != 1)
+               errx(1, "%s: unexpected timeout (%lld.%09ld/1)", __func__,
+                   diff.tv_sec, diff.tv_nsec);
+}
+
+void
+backend_get_timeout_session_higher(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 22, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+       struct timespec start, end, diff;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 6,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 22), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 22), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
+               err(1, "clock_gettime");
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 7000, community, requestid, GENERR, 1,
+           &varbind, 1);
+       if (clock_gettime(CLOCK_MONOTONIC, &end) == -1)
+               err(1, "clock_gettime");
+       timespecsub(&end, &start, &diff);
+       if (diff.tv_sec != 6)
+               errx(1, "%s: unexpected timeout (%lld.%09ld/6)", __func__,
+                   diff.tv_sec, diff.tv_nsec);
+}
+
+void
+backend_get_timeout_region_lower(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 23, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+       struct timespec start, end, diff;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 4,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 23), __func__);
+       agentx_register(ax_s, sessionid, 0, 1, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 23), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
+               err(1, "clock_gettime");
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 6000, community, requestid, GENERR, 1,
+           &varbind, 1);
+       if (clock_gettime(CLOCK_MONOTONIC, &end) == -1)
+               err(1, "clock_gettime");
+       timespecsub(&end, &start, &diff);
+       if (diff.tv_sec != 1)
+               errx(1, "%s: unexpected timeout (%lld.%09ld/1)", __func__,
+                   diff.tv_sec, diff.tv_nsec);
+}
+
+void
+backend_get_timeout_region_higher(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 24, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+       struct timespec start, end, diff;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 7,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 24), __func__);
+       agentx_register(ax_s, sessionid, 0, 6, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 24), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
+               err(1, "clock_gettime");
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 8000, community, requestid, GENERR, 1,
+           &varbind, 1);
+       if (clock_gettime(CLOCK_MONOTONIC, &end) == -1)
+               err(1, "clock_gettime");
+       timespecsub(&end, &start, &diff);
+       if (diff.tv_sec != 6)
+               errx(1, "%s: unexpected timeout (%lld.%09ld/6)", __func__,
+                   diff.tv_sec, diff.tv_nsec);
+}
+
+void
+backend_get_priority_lower(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 25, 0),
+               .data.int32 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 25, 1), "backend_get_priority.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 25, 2), "backend_get_priority.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 25), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 126, 0,
+           OID_ARG(MIB_BACKEND_GET, 25), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid2, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_priority_higher(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 26, 0),
+               .data.int32 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 26, 1),
+           "backend_get_priority_higher.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 26, 2),
+           "backend_get_priority_higher.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 126, 0,
+           OID_ARG(MIB_BACKEND_GET, 26), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 26), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid1, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_priority_below_lower(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 27, 0),
+               .data.int32 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 27, 1),
+           "backend_get_priority_below_lower.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 27, 2),
+           "backend_get_priority_below_lower.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 27), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 126, 0,
+           OID_ARG(MIB_BACKEND_GET, 27, 0), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid2, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_priority_below_higher(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 28, 0),
+               .data.int32 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 28, 1),
+           "backend_get_priority_below_higher.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 28, 2),
+           "backend_get_priority_below_higher.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 28), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 128, 0,
+           OID_ARG(MIB_BACKEND_GET, 28, 0), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid2, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_close(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 29, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 29), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 29), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_close(ax_s, sessionid, REASONOTHER);
+
+       varbind.type = TYPE_NOSUCHOBJECT;
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_close_overlap(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s1, ax_s2;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 30, 0),
+               .data.int32 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s1 = agentx_connect(axsocket);
+       ax_s2 = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s1, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 30, 1),
+           "backend_get_close_overlap.1");
+       sessionid2 = agentx_open(ax_s2, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 30, 1),
+           "backend_get_close_overlap.2");
+       agentx_register(ax_s1, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 30), 0);
+       agentx_register(ax_s2, sessionid2, 0, 0, 128, 0,
+           OID_ARG(MIB_BACKEND_GET, 30), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s1, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid1, &varbind, 1);
+       agentx_close(ax_s1, sessionid1, REASONOTHER);
+
+       varbind.type = TYPE_INTEGER;
+       n = agentx_read(ax_s2, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid2, &varbind, 1);
+       agentx_response(ax_s2, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_disappear(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 31, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 31), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 31), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+       close(ax_s);
+
+       varbind.type = TYPE_NOSUCHOBJECT;
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_disappear_overlap(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s1, ax_s2;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 32, 0),
+               .data.int32 = 1
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s1 = agentx_connect(axsocket);
+       ax_s2 = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s1, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 32, 1),
+           "backend_get_close_overlap.1");
+       sessionid2 = agentx_open(ax_s2, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 32, 1),
+           "backend_get_close_overlap.2");
+       agentx_register(ax_s1, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 32), 0);
+       agentx_register(ax_s2, sessionid2, 0, 0, 128, 0,
+           OID_ARG(MIB_BACKEND_GET, 32), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s1, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid1, &varbind, 1);
+       close(ax_s1);
+
+       varbind.type = TYPE_INTEGER;
+       n = agentx_read(ax_s2, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid2, &varbind, 1);
+       agentx_response(ax_s2, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_get_disappear_doublesession(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GET, 33, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 33, 1),
+           "backend_get_disappear_doublesession.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GET, 33, 2),
+           "backend_get_disappear_doublesession.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GET, 33), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 128, 0,
+           OID_ARG(MIB_BACKEND_GET, 33), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid1, &varbind, 1);
+       close(ax_s);
+
+       varbind.type = TYPE_NOSUCHOBJECT;
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_selfbound(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 1),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 1),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 2)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 1), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_lowerbound(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 2),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 2),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 2, 1)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 2, 1),
+           "backend_getnext_lowerbound.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 2, 2),
+           "backend_getnext_lowerbound.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 2), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 2, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, &searchrange,
+           &varbind, 1);
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_lowerbound_self(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 3),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 3),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 4)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 3), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 3), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_lowerbound_highprio(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 4),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 4),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 4, 1)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 4, 1),
+           "backend_getnext_lowerbound_highprio.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 4, 2),
+           "backend_getnext_lowerbound_highprio.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 4), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 128, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 4, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, &searchrange,
+           &varbind, 1);
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_lowerbound_lowprio(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 5),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 5),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 5, 1)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 5, 1),
+           "backend_getnext_lowerbound_lowprio.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 5, 2),
+           "backend_getnext_lowerbound_lowprio.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 5), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 128, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 5, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, &searchrange,
+           &varbind, 1);
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_sibling(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 6),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 6),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 8)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 6), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 6), 0);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 7), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_child_gap(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 7),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 7),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 7, 2)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 6, 1),
+           "backend_getnext_child_gap.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 6, 2),
+           "backend_getnext_child_gap.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 7), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 7, 2), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, &searchrange,
+           &varbind, 1);
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_nosuchobject(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 8),
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 8),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 9)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 8), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 8), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_NOSUCHOBJECT;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+       varbind.name.n_subid--;
+       varbind.type = TYPE_NULL;
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_getnext_nosuchinstance(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 9),
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 9),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 10)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 9), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 9), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_NOSUCHINSTANCE;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+       varbind.name.n_subid--;
+       varbind.type = TYPE_NULL;
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+/* Assume that everything is registered under 1.3.* */
+void
+backend_getnext_endofmibview(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(2, 0),
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(2, 0),
+               .end = OID_STRUCT(2, 1)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 10), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(2, 0), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_ENDOFMIBVIEW;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+       varbind.name.n_subid--;
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_inclusive(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 11),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 11, 0),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 11, 1)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       searchrange.start.include = 1;
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 11), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 11, 0), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       varbind.type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_jumpnext(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind1 = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 12)
+       }, varbind2 = {
+               .type = TYPE_INTEGER,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 12, 1),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange1 = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 12),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 12, 1)
+       }, searchrange2 = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 12, 1),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 12, 2)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 12, 1),
+           "backend_getnext_jumpnext.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 12, 2),
+           "backend_getnext_jumpnext.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 12), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 12, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind1, 1);
+
+       varbind1.type = TYPE_ENDOFMIBVIEW;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, &searchrange1,
+           &varbind1, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind1, 1);
+
+       searchrange2.start.include = 1;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid2, &searchrange2,
+           &varbind2, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind2, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind2, 1);
+}
+
+/* Assume that everything is registered under 1.3.* */
+void
+backend_getnext_jumpnext_endofmibview(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind1 = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(2, 0)
+       }, varbind2 = {
+               .type = TYPE_ENDOFMIBVIEW,
+               .name = OID_STRUCT(2, 1),
+       };
+       struct searchrange searchrange1 = {
+               .start = OID_STRUCT(2, 0),
+               .end = OID_STRUCT(2, 1)
+       }, searchrange2 = {
+               .start = OID_STRUCT(2, 1),
+               .end = OID_STRUCT(2, 2)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 13, 1),
+           "backend_getnext_jumpnext_endofmibview.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 13, 2),
+           "backend_getnext_jumpnext_endofmibview.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(2, 0), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 127, 0,
+           OID_ARG(2, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind1, 1);
+
+       varbind1.type = TYPE_ENDOFMIBVIEW;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, &searchrange1,
+           &varbind1, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind1, 1);
+
+       searchrange2.start.include = 1;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid2, &searchrange2,
+           &varbind2, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind2, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind1, 1);
+}
+
+void
+backend_getnext_jump_up(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind1 = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 14, 1)
+       }, varbind2 = {
+               .type = TYPE_INTEGER,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 14, 2),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange1 = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 14, 1),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 14, 2)
+       }, searchrange2 = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 14, 2),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 15)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 14, 1),
+           "backend_getnext_jump_up.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 14, 2),
+           "backend_getnext_jump_up.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 14), 0);
+       agentx_register(ax_s, sessionid2, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 14, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind1, 1);
+
+       varbind1.type = TYPE_ENDOFMIBVIEW;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid2, &searchrange1,
+           &varbind1, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind1, 1);
+
+       searchrange2.start.include = 1;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, &searchrange2,
+           &varbind2, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind2, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0,
+           &varbind2, 1);
+}
+
+void
+backend_getnext_two_single_backend(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 15, 0),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 15, 1),
+                       .data.int32 = 2
+               }
+       };
+       struct varbind varbind_ax[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 15, 1),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 15, 2),
+                       .data.int32 = 2
+               }
+       };
+       struct searchrange searchrange[] = {
+               {
+                       .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 15, 0),
+                       .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 16)
+               },
+               {
+                       .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 15, 1),
+                       .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 16)
+               }
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 15), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 15), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, varbind, 2);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, searchrange,
+           varbind_ax, 2);
+
+       agentx_response(ax_s, buf, NOERROR, 0, varbind_ax, 2);
+
+       varbind[0].type = varbind[1].type = TYPE_INTEGER;
+       varbind[0].name.subid[varbind[0].name.n_subid -1]++;
+       varbind[1].name.subid[varbind[1].name.n_subid - 1]++;
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           varbind, 2);
+}
+
+void
+backend_getnext_two_double_backend(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s1, ax_s2;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 16, 1),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 16, 2),
+                       .data.int32 = 2
+               }
+       };
+       struct searchrange searchrange1 = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 16, 1),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 16, 2)
+       }, searchrange2 = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 16, 2),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 16, 3)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s1 = agentx_connect(axsocket);
+       ax_s2 = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s1, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 16, 1),
+           "backend_getnext_two_double_backend.1");
+       sessionid2 = agentx_open(ax_s2, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 16, 2),
+           "backend_getnext_two_double_backend.2");
+       agentx_register(ax_s1, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 16, 1), 0);
+       agentx_register(ax_s2, sessionid2, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 16, 2), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, varbind, 2);
+
+       varbind[0].name.subid[varbind[0].name.n_subid++] = 0;
+       varbind[1].name.subid[varbind[1].name.n_subid++] = 0;
+       varbind[0].type = varbind[1].type = TYPE_INTEGER;
+       n = agentx_read(ax_s1, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, &searchrange1,
+           varbind + 0, 1);
+       agentx_response(ax_s1, buf, NOERROR, 0, varbind + 0, 1);
+
+       n = agentx_read(ax_s2, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid2, &searchrange2,
+           varbind + 1, 1);
+       agentx_response(ax_s2, buf, NOERROR, 0, varbind + 1, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           varbind, 2);
+}
+
+void
+backend_getnext_instance_below(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 17, 1, 1),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 17, 2),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 17, 3)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 17), __func__);
+       agentx_register(ax_s, sessionid, 1, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 17, 1), 0);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 17, 2), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 17, 2);
+       searchrange.start.include = 1;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_instance(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 18),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 18, 1),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 18, 2)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 18), __func__);
+       agentx_register(ax_s, sessionid, 1, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 18, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 18, 1);
+       searchrange.start.include = 1;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_instance_exact(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 19, 1),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 19, 2),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 19, 3)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 19), __func__);
+       agentx_register(ax_s, sessionid, 1, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 19, 1), 0);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 19, 2), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 19, 2);
+       searchrange.start.include = 1;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           &varbind, 1);
+}
+
+void
+backend_getnext_instance_ignore(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 20),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 20, 1),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 20, 2)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 20), __func__);
+       agentx_register(ax_s, sessionid, 1, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 20, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 20, 1, 0);
+       searchrange.start.include = 1;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+       varbind.type = TYPE_NULL;
+       varbind.name.n_subid -= 2;
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_getnext_backwards(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 21),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 21),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 22)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 21), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 21), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 21, 1);
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 20);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+       varbind.type = TYPE_NULL;
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 21);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_getnext_stale(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 22),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 22),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 23)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 22), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 22), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 22, 1);
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 22);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+       varbind.type = TYPE_NULL;
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_getnext_inclusive_backwards(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 23),
+               .data.int32 = 1
+       };
+       struct searchrange searchrange = {
+               .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 23, 1),
+               .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 23, 2)
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 23), __func__);
+       agentx_register(ax_s, sessionid, 1, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 23, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.type = TYPE_INTEGER;
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 23, 1);
+       searchrange.start.include = 1;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, &searchrange,
+           &varbind, 1);
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 22);
+       agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+       varbind.type = TYPE_NULL;
+       varbind.name = OID_STRUCT(MIB_BACKEND_GETNEXT, 23);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_getnext_toofew(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 24, 0),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 24, 1),
+                       .data.int32 = 2
+               }
+       };
+       struct searchrange searchrange[] = {
+               {
+                       .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 24, 0),
+                       .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 25)
+               },
+               {
+                       .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 24, 1),
+                       .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 25)
+               }
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 24), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 24), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, varbind, 2);
+
+       varbind[0].name.subid[varbind[0].name.n_subid - 1]++;
+       varbind[1].name.subid[varbind[1].name.n_subid - 1]++;
+       varbind[0].type = varbind[1].type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, searchrange,
+           varbind, 2);
+       agentx_response(ax_s, buf, NOERROR, 0, varbind, 1);
+       varbind[0].type = varbind[1].type = TYPE_NULL;
+       varbind[0].name = OID_STRUCT(MIB_BACKEND_GETNEXT, 24, 0),
+       varbind[1].name = OID_STRUCT(MIB_BACKEND_GETNEXT, 24, 1),
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 2,
+           varbind, 2);
+}
+
+void
+backend_getnext_toomany(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 25, 0),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 25, 1),
+                       .data.int32 = 2
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 25, 3),
+                       .data.int32 = 3
+               }
+       };
+       struct searchrange searchrange[] = {
+               {
+                       .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 25, 0),
+                       .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 26)
+               },
+               {
+                       .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 25, 1),
+                       .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 26)
+               }
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 25), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 25), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, varbind, 2);
+
+       varbind[0].name.subid[varbind[0].name.n_subid - 1]++;
+       varbind[1].name.subid[varbind[1].name.n_subid - 1]++;
+       varbind[0].type = varbind[1].type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, searchrange,
+           varbind, 2);
+       agentx_response(ax_s, buf, NOERROR, 0, varbind, 3);
+       varbind[0].type = varbind[1].type = TYPE_NULL;
+       varbind[0].name = OID_STRUCT(MIB_BACKEND_GETNEXT, 25, 0),
+       varbind[1].name = OID_STRUCT(MIB_BACKEND_GETNEXT, 25, 1),
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 2,
+           varbind, 2);
+}
+
+void
+backend_getbulk_nonrep_zero_maxrep_one(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind request = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETBULK, 1)
+       }, ax_request[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 1, 0),
+                       .data.int32 = 1
+               }
+       }, ax_response[nitems(ax_request)], response[nitems(ax_request)];
+       int32_t requestid;
+       char buf[1024];
+       size_t n, nvarbind = nitems(ax_request), nout;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETBULK, 1), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETBULK, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getbulk(snmp_s, community, 0, 0, 1, &request, 1);
+
+       memcpy(response, ax_request, sizeof(ax_request));
+       while (nvarbind > 0) {
+               n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+               nout = agentx_getbulk_handle(__func__, buf, n, 0,
+                   sessionid, ax_request, nvarbind, ax_response);
+               agentx_response(ax_s, buf, NOERROR, 0, ax_response, nout);
+               nvarbind -= nout;
+       }
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           response, nitems(response));
+}
+
+void
+backend_getbulk_nonrep_zero_maxrep_two(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind request = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETBULK, 2)
+       }, ax_request[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 2, 1),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 2, 2),
+                       .data.int32 = 2
+               }
+       }, ax_response[nitems(ax_request)], response[nitems(ax_request)];
+       int32_t requestid;
+       char buf[1024];
+       size_t n, nvarbind = nitems(ax_request), nout;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETBULK, 2), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETBULK, 2), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getbulk(snmp_s, community, 0, 0, 2, &request, 1);
+
+       memcpy(response, ax_request, sizeof(ax_request));
+       while (nvarbind > 0) {
+               n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+               nout = agentx_getbulk_handle(__func__, buf, n, 0,
+                   sessionid, ax_request, nvarbind, ax_response);
+               agentx_response(ax_s, buf, NOERROR, 0, ax_response, nout);
+               nvarbind -= nout;
+       }
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           response, nitems(response));
+}
+
+void
+backend_getbulk_nonrep_one_maxrep_one(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind request[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 3, 1)
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 3, 2)
+               }
+       }, ax_request[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 3, 1, 0),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 3, 2, 0),
+                       .data.int32 = 2
+               }
+       }, ax_response[nitems(ax_request)], response[nitems(ax_request)];
+       int32_t requestid;
+       char buf[1024];
+       size_t n, nvarbind = nitems(ax_request), nout;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETBULK, 3), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETBULK, 3), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getbulk(snmp_s, community, 0, 1, 1, request, 2);
+
+       memcpy(response, ax_request, sizeof(ax_request));
+       while (nvarbind > 0) {
+               n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+               nout = agentx_getbulk_handle(__func__, buf, n, 0,
+                   sessionid, ax_request, nvarbind, ax_response);
+               agentx_response(ax_s, buf, NOERROR, 0, ax_response, nout);
+               nvarbind -= nout;
+       }
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           response, nitems(response));
+}
+
+void
+backend_getbulk_nonrep_one_maxrep_two(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind request[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 4, 1)
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 4, 2)
+               }
+       }, ax_request[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 4, 1, 0),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 4, 2, 2),
+                       .data.int32 = 2
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 4, 2, 3),
+                       .data.int32 = 3
+               }
+       }, ax_response[nitems(ax_request)], response[nitems(ax_request)];
+       int32_t requestid;
+       char buf[1024];
+       size_t n, nvarbind = nitems(ax_request), nout;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETBULK, 4), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETBULK, 4), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getbulk(snmp_s, community, 0, 1, 2, request, 2);
+
+       memcpy(response, ax_request, sizeof(ax_request));
+       while (nvarbind > 0) {
+               n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+               nout = agentx_getbulk_handle(__func__, buf, n, 0,
+                   sessionid, ax_request, nvarbind, ax_response);
+               agentx_response(ax_s, buf, NOERROR, 0, ax_response, nout);
+               nvarbind -= nout;
+       }
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           response, nitems(response));
+}
+
+void
+backend_getbulk_nonrep_two_maxrep_two(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind request[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 5, 1)
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 5, 2)
+               },
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 5, 3)
+               }
+       }, ax_request[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 5, 1, 0),
+                       .data.int32 = 1
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 5, 2, 0),
+                       .data.int32 = 2
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 5, 3, 3),
+                       .data.int32 = 3
+               },
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 5, 3, 4),
+                       .data.int32 = 4
+               }
+       }, ax_response[nitems(ax_request)], response[nitems(ax_request)];
+       int32_t requestid;
+       char buf[1024];
+       size_t n, nvarbind = nitems(ax_request), nout;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETBULK, 5), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETBULK, 5), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getbulk(snmp_s, community, 0, 2, 2, request, 3);
+
+       memcpy(response, ax_request, sizeof(ax_request));
+       while (nvarbind > 0) {
+               n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+               nout = agentx_getbulk_handle(__func__, buf, n, 0,
+                   sessionid, ax_request, nvarbind, ax_response);
+               agentx_response(ax_s, buf, NOERROR, 0, ax_response, nout);
+               nvarbind -= nout;
+       }
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           response, nitems(response));
+}
+
+void
+backend_getbulk_nonrep_negative(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind request = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_GETBULK, 6)
+       }, ax_request[] = {
+               {
+                       .type = TYPE_INTEGER,
+                       .name = OID_STRUCT(MIB_BACKEND_GETBULK, 6),
+                       .data.int32 = 1
+               }
+       }, ax_response[nitems(ax_request)], response[nitems(ax_request)];
+       int32_t requestid;
+       char buf[1024];
+       size_t n, nvarbind = nitems(ax_request), nout;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETBULK, 6), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETBULK, 6), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getbulk(snmp_s, community, 0, -1, 1, &request, 1);
+
+       agentx_timeout(ax_s, 1000);
+       snmp_timeout(snmp_s, 1);
+}
+
+void
+backend_error_get_toobig(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 1, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 1), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 1), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, TOOBIG, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, TOOBIG, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_nosuchname(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 2, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 2), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 2), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, NOSUCHNAME, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOSUCHNAME, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_badvalue(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 3, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 3), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 3), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, BADVALUE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_readonly(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 4, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 4), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 4), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, READONLY, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_generr(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 5, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 5), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 5), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, GENERR, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_noaccess(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 6, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 6), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 5), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, NOACCESS, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_wrongtype(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 7, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 7), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 7), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, WRONGTYPE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_wronglength(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 8, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 8), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 8), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, WRONGLENGTH, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_wrongencoding(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 9, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 9), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 9), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, WRONGENCODING, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_wrongvalue(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 10, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 10), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 10), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, WRONGVALUE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_nocreation(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 11, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 11), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 11), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, NOCREATION, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_inconsistentvalue(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 12, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 12), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 12), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, INCONSISTENTVALUE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_resourceunavailable(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 13, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 13), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 13), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, WRONGVALUE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_commitfailed(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 14, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 14), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 14), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, COMMITFAILED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_undofailed(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 15, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 15), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 15), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, UNDOFAILED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_authorizationerror(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 16, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 16), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 16), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, AUTHORIZATIONERROR, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, AUTHORIZATIONERROR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_notwritable(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 17, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 17), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 17), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, NOTWRITABLE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_inconsistentname(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 18, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 18), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 18), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, INCONSISTENTNAME, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_openfailed(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 19, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 19), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 19), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, OPENFAILED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_notopen(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 20, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 20), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 20), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, NOTOPEN, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_indexwrongtype(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 21, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 21), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 21), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, INDEXWRONGTYPE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_indexalreadyallocated(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 22, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 22), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 22), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, INDEXALREADYALLOCATED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_indexnonavailable(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 23, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 23), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 23), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, INDEXNONEAVAILABLE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_indexnotallocated(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 24, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 24), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 24), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, INDEXNOTALLOCATED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_unsupportedcontext(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 25, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 25), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 25), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, UNSUPPORTEDCONTEXT, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_duplicateregistration(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 26, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 26), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 26), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, DUPLICATEREGISTRATION, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_unknownregistration(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 27, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 27), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 27), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, UNKNOWNREGISTRATION, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_parseerror(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 28, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 28), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 28), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, PARSEERROR, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_requestdenied(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 29, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 29), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 29), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, REQUESTDENIED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_processingerror(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 30, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 30), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 30), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, PROCESSINGERROR, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_get_nonstandard(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 31, 0),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 31), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 31), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+
+       agentx_response(ax_s, buf, 0xFFFF, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_toobig(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 32),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 32), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 32), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, TOOBIG, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, TOOBIG, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_nosuchname(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 33),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 33), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 33), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, NOSUCHNAME, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOSUCHNAME, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_badvalue(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 34),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 34), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 34), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, BADVALUE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_readonly(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 35),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 35), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 35), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, READONLY, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_generr(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 36),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 36), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 36), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, GENERR, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_noaccess(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 37),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 37), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 37), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, NOACCESS, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_wrongtype(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 38),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 38), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 38), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, WRONGTYPE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_wronglength(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 39),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 39), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 39), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, WRONGLENGTH, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_wrongencoding(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 40),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 40), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 40), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, WRONGENCODING, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_wrongvalue(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 41),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 41), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 41), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, WRONGVALUE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_nocreation(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 42),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 42), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 42), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, NOCREATION, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_inconsistentvalue(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 43),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 43), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 43), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, INCONSISTENTVALUE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_resourceunavailable(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 44),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 44), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 44), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, RESOURCEUNAVAILABLE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_commitfailed(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 45),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 45), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 45), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, COMMITFAILED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_undofailed(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 46),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 46), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 46), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, UNDOFAILED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_authorizationerror(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 47),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 47), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 47), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, AUTHORIZATIONERROR, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_notwritable(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 48),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 48), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 48), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, NOTWRITABLE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_inconsistentname(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 49),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 49), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 49), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, INCONSISTENTNAME, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_openfailed(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 50),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 50), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 50), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, OPENFAILED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_notopen(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 51),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 51), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 51), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, NOTOPEN, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_indexwrongtype(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 52),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 52), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 52), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, INDEXWRONGTYPE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_indexalreadyallocated(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 53),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 53), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 53), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, INDEXALREADYALLOCATED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_indexnonavailable(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 54),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 54), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 54), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, INDEXNONEAVAILABLE, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_indexnotallocated(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 55),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 55), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 55), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, INDEXNOTALLOCATED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_unsupportedcontext(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 56),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 56), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 56), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, UNSUPPORTEDCONTEXT, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_duplicateregistration(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 57),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 57), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 57), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, DUPLICATEREGISTRATION, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_unknownregistration(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 58),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 58), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 58), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, UNKNOWNREGISTRATION, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_parseerror(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 59),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 59), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 59), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, PARSEERROR, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_requestdenied(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 60),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 60), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 60), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, REQUESTDENIED, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_processingerror(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 61),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 61), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 61), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, PROCESSINGERROR, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
+
+void
+backend_error_getnext_nonstandard(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid;
+       struct varbind varbind = {
+               .type = TYPE_NULL,
+               .name = OID_STRUCT(MIB_BACKEND_ERROR, 62),
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_ERROR, 62), __func__);
+       agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_ERROR, 62), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, &varbind, 1);
+
+       varbind.name.subid[varbind.name.n_subid++] = 0;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid, NULL, &varbind, 1);
+       varbind.name.n_subid--;
+       agentx_response(ax_s, buf, 0xFFFF, 1, &varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1,
+           &varbind, 1);
+}
diff --git a/regress/usr.sbin/snmpd/regress.h b/regress/usr.sbin/snmpd/regress.h
new file mode 100644 (file)
index 0000000..ef49611
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * Generic
+ */
+#define OID_MAX 128
+
+struct oid {
+       uint32_t subid[OID_MAX];
+       size_t n_subid;
+       int include;
+};
+
+struct searchrange {
+       struct oid start;
+       struct oid end;
+};
+
+enum type {
+       TYPE_INTEGER = 2,
+       TYPE_OCTETSTRING = 4,
+       TYPE_NULL = 5,
+       TYPE_OBJECTIDENTIFIER = 6,
+       TYPE_IPADDRESS = 64,
+       TYPE_COUNTER32 = 65,
+       TYPE_GAUGE32 = 66,
+       TYPE_TIMETICKS = 67,
+       TYPE_OPAQUE = 68,
+       TYPE_COUNTER64 = 70,
+       TYPE_NOSUCHOBJECT = 128,
+       TYPE_NOSUCHINSTANCE = 129,
+       TYPE_ENDOFMIBVIEW = 130,
+       /* Don't expect a specific value: mod 1000 */
+       TYPE_INTEGER_UNKNOWN = 1002,
+       TYPE_OCTETSTRING_UNKNOWN = 1004,
+       TYPE_OBJECTIDENTIFIER_UNKNOWN = 1006,
+       TYPE_IPADDRESS_UNKNOWN = 1064
+};
+
+enum error {
+       NOERROR = 0,
+       NOAGENTXERROR = 0,
+       TOOBIG = 1,
+       NOSUCHNAME = 2,
+       BADVALUE = 3,
+       READONLY = 4,
+       GENERR = 5,
+       NOACCESS = 6,
+       WRONGTYPE = 7,
+       WRONGLENGTH = 8,
+       WRONGENCODING = 9,
+       WRONGVALUE = 10,
+       NOCREATION = 11,
+       INCONSISTENTVALUE = 12,
+       RESOURCEUNAVAILABLE = 13,
+       COMMITFAILED = 14,
+       UNDOFAILED = 15,
+       AUTHORIZATIONERROR = 16,
+       NOTWRITABLE = 17,
+       INCONSISTENTNAME = 18,
+       OPENFAILED = 256,
+       NOTOPEN = 257,
+       INDEXWRONGTYPE = 258,
+       INDEXALREADYALLOCATED = 259,
+       INDEXNONEAVAILABLE = 260,
+       INDEXNOTALLOCATED = 261,
+       UNSUPPORTEDCONTEXT = 262,
+       DUPLICATEREGISTRATION = 263,
+       UNKNOWNREGISTRATION = 264,
+       UNKNOWNAGENTCAPS = 265,
+       PARSEERROR = 266,
+       REQUESTDENIED = 267,
+       PROCESSINGERROR = 268
+};
+
+enum close_reason {
+       REASONOTHER = 1,
+       REASONPARSEERROR = 2,
+       REASONPROTOCOLERROR = 3,
+       REASONTIMEOUTS = 4,
+       REASONSHUTDOWN = 5,
+       REASONBYMANAGER = 6
+};
+
+struct varbind {
+       enum type       type;
+       struct oid      name;
+       union data {
+               int32_t          int32;
+               uint32_t         uint32;
+               uint64_t         uint64;
+               struct oid       oid;
+               struct octetstring {
+                       char    *string;
+                       size_t   len;
+               }                octetstring;
+       }               data;
+};
+
+extern int verbose;
+extern char *axsocket;
+extern char *hostname;
+extern char *servname;
+extern char *community;
+
+int oid_cmp(struct oid *, struct oid *);
+char *oid_print(struct oid *, char *, size_t);
+
+#define OID_STRUCT(...) (struct oid){                                  \
+       .subid = { __VA_ARGS__ },                                       \
+       .n_subid = (sizeof((uint32_t []) { __VA_ARGS__ }) / sizeof(uint32_t)) \
+}
+
+#define OID_ARG(...) (uint32_t []) { __VA_ARGS__ },    \
+    (sizeof((uint32_t []) { __VA_ARGS__ }) / sizeof(uint32_t))
+
+/*
+ * AgentX
+ */
+#define MIB_OPENBSD_REGRESS 1, 3, 6, 1, 4, 1, 30155, 42
+/* Subagent names */
+#define MIB_SUBAGENTS MIB_OPENBSD_REGRESS, 1
+#define MIB_SUBAGENT_OPEN MIB_SUBAGENTS, 1
+#define MIB_SUBAGENT_PING MIB_SUBAGENTS, 2
+#define MIB_SUBAGENT_CLOSE MIB_SUBAGENTS, 3
+#define MIB_SUBAGENT_REGISTER MIB_SUBAGENTS, 4
+#define MIB_SUBAGENT_UNREGISTER MIB_SUBAGENTS, 4
+#define MIB_SUBAGENT_BACKEND MIB_SUBAGENTS, 5
+/* Region used for registration testing */
+#define MIB_REGISTER MIB_OPENBSD_REGRESS, 2
+#define MIB_UNREGISTER MIB_OPENBSD_REGRESS, 3
+#define MIB_BACKEND MIB_OPENBSD_REGRESS, 4
+
+#define SYSORTABLE 1, 3, 6, 1, 2, 1, 1, 9
+
+int agentx_connect(const char *);
+uint32_t agentx_open(int, int, uint8_t, uint32_t[], size_t, const char *);
+void agentx_close(int, uint32_t, enum close_reason);
+void agentx_register(int, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t,
+    uint32_t[], size_t, uint32_t);
+void agentx_response(int, void *, enum error, uint16_t, struct varbind *,
+    size_t);
+void agentx_get_handle(const char *, const void *, size_t, uint8_t, uint32_t,
+    struct varbind *, size_t);
+void agentx_getnext_handle(const char *, const void *, size_t, uint8_t,
+    uint32_t, struct searchrange *, struct varbind *, size_t);
+size_t agentx_getbulk_handle(const char *, const void *, size_t, uint8_t, int32_t,
+    struct varbind *, size_t, struct varbind *);
+size_t agentx_read(int, void *, size_t, int);
+void agentx_timeout(int, int);
+
+
+/* Tests */
+void agentx_open_nnbo(void);
+void agentx_open_nbo(void);
+void agentx_open_invalidversion(void);
+void agentx_open_ignore_sessionid(void);
+void agentx_open_invalid_oid(void);
+void agentx_open_descr_too_long(void);
+void agentx_open_descr_invalid(void);
+void agentx_open_context(void);
+void agentx_open_instance_registration(void);
+void agentx_open_new_index(void);
+void agentx_open_any_index(void);
+void agentx_ping_notopen(void);
+void agentx_ping_invalid_sessionid(void);
+void agentx_ping_default(void);
+void agentx_ping_context(void);
+void agentx_ping_invalid_version(void);
+void agentx_ping_instance_registration(void);
+void agentx_ping_new_index(void);
+void agentx_ping_any_index(void);
+void agentx_ping_nbo_nnbo(void);
+void agentx_ping_nnbo_nbo(void);
+void agentx_close_notopen(void);
+void agentx_close_reasonother(void);
+void agentx_close_reasonparseerror(void);
+void agentx_close_reasonprotocolerror(void);
+void agentx_close_reasontimouts(void);
+void agentx_close_reasonshutdown(void);
+void agentx_close_reasonbymanager(void);
+void agentx_close_reasoninvalid(void);
+void agentx_close_single(void);
+void agentx_close_notowned(void);
+void agentx_close_invalid_sessionid(void);
+void agentx_close_context(void);
+void agentx_close_invalid_version(void);
+void agentx_close_instance_registration(void);
+void agentx_close_new_index(void);
+void agentx_close_any_index(void);
+void agentx_close_nnbo_nbo(void);
+void agentx_register_notopen(void);
+void agentx_register_invalid_sessionid(void);
+void agentx_register_default(void);
+void agentx_register_context(void);
+void agentx_register_invalid_version(void);
+void agentx_register_instance_registration(void);
+void agentx_register_new_index(void);
+void agentx_register_any_index(void);
+void agentx_register_duplicate_self(void);
+void agentx_register_duplicate_twocon(void);
+void agentx_register_duplicate_priority(void);
+void agentx_register_range(void);
+void agentx_register_range_invalidupperbound(void);
+void agentx_register_range_single(void);
+void agentx_register_range_overlap_single(void);
+void agentx_register_single_overlap_range(void);
+void agentx_register_range_overlap_range(void);
+void agentx_register_below(void);
+void agentx_register_above(void);
+void agentx_register_restricted(void);
+void agentx_unregister_notopen(void);
+void agentx_unregister_invalid_sessionid(void);
+void agentx_unregister_notregistered(void);
+void agentx_unregister_single(void);
+void agentx_unregister_single_notowned(void);
+void agentx_unregister_range(void);
+void agentx_unregister_range_single(void);
+void agentx_unregister_range_subset(void);
+void agentx_unregister_range_extra(void);
+void agentx_unregister_range_priority(void);
+void agentx_unregister_range_notowned(void);
+
+/*
+ * SNMP
+ */
+socklen_t snmp_resolve(int, const char *, const char *, struct sockaddr *);
+int snmp_connect(int, struct sockaddr *, socklen_t);
+int32_t snmpv2_get(int, const char *, int32_t, struct varbind *, size_t);
+int32_t snmpv2_getnext(int, const char *, int32_t, struct varbind *, size_t);
+int32_t snmpv2_getbulk(int, const char *, int32_t, int32_t, int32_t,
+    struct varbind *, size_t);
+void snmpv2_response_validate(int, int, const char *, int32_t, int32_t, int32_t,
+    struct varbind *, size_t);
+void snmp_timeout(int, int);
+
+void backend_get_integer(void);
+void backend_get_octetstring(void);
+void backend_get_objectidentifier(void);
+void backend_get_ipaddress(void);
+void backend_get_counter32(void);
+void backend_get_gauge32(void);
+void backend_get_timeticks(void);
+void backend_get_opaque(void);
+void backend_get_counter64(void);
+void backend_get_nosuchobject(void);
+void backend_get_nosuchinstance(void);
+void backend_get_endofmibview(void);
+void backend_get_two_single_backend(void);
+void backend_get_two_double_backend(void);
+void backend_get_wrongorder(void);
+void backend_get_toofew(void);
+void backend_get_toomany(void);
+void backend_get_instance(void);
+void backend_get_instance_below(void);
+void backend_get_timeout_default(void);
+void backend_get_timeout_session_lower(void);
+void backend_get_timeout_session_higher(void);
+void backend_get_timeout_region_lower(void);
+void backend_get_timeout_region_higher(void);
+void backend_get_priority_lower(void);
+void backend_get_priority_higher(void);
+void backend_get_priority_below_lower(void);
+void backend_get_priority_below_higher(void);
+void backend_get_close(void);
+void backend_get_close_overlap(void);
+void backend_get_disappear(void);
+void backend_get_disappear_overlap(void);
+void backend_get_disappear_doublesession(void);
+void backend_getnext_selfbound(void);
+void backend_getnext_lowerbound(void);
+void backend_getnext_lowerbound_self(void);
+void backend_getnext_lowerbound_highprio(void);
+void backend_getnext_lowerbound_lowprio(void);
+void backend_getnext_sibling(void);
+void backend_getnext_child_gap(void);
+void backend_getnext_nosuchobject(void);
+void backend_getnext_nosuchinstance(void);
+void backend_getnext_endofmibview(void);
+void backend_getnext_inclusive(void);
+void backend_getnext_jumpnext(void);
+void backend_getnext_jumpnext_endofmibview(void);
+void backend_getnext_jump_up(void);
+void backend_getnext_jump_up(void);
+void backend_getnext_two_single_backend(void);
+void backend_getnext_two_double_backend(void);
+void backend_getnext_instance_below(void);
+void backend_getnext_instance(void);
+void backend_getnext_instance_exact(void);
+void backend_getnext_instance_ignore(void);
+void backend_getnext_instance_ignore(void);
+void backend_getnext_backwards(void);
+void backend_getnext_stale(void);
+void backend_getnext_inclusive_backwards(void);
+void backend_getnext_toofew(void);
+void backend_getnext_toomany(void);
+void backend_getbulk_nonrep_zero_maxrep_one(void);
+void backend_getbulk_nonrep_zero_maxrep_two(void);
+void backend_getbulk_nonrep_one_maxrep_one(void);
+void backend_getbulk_nonrep_one_maxrep_two(void);
+void backend_getbulk_nonrep_two_maxrep_two(void);
+void backend_getbulk_nonrep_negative(void);
+void backend_error_get_toobig(void);
+void backend_error_get_nosuchname(void);
+void backend_error_get_badvalue(void);
+void backend_error_get_readonly(void);
+void backend_error_get_generr(void);
+void backend_error_get_wrongtype(void);
+void backend_error_get_wronglength(void);
+void backend_error_get_wrongencoding(void);
+void backend_error_get_wrongvalue(void);
+void backend_error_get_nocreation(void);
+void backend_error_get_inconsistentvalue(void);
+void backend_error_get_commitfailed(void);
+void backend_error_get_undofailed(void);
+void backend_error_get_authorizationerror(void);
+void backend_error_get_notwritable(void);
+void backend_error_get_inconsistentname(void);
+void backend_error_get_openfailed(void);
+void backend_error_get_notopen(void);
+void backend_error_get_indexwrongtype(void);
+void backend_error_get_indexalreadyallocated(void);
+void backend_error_get_indexnonavailable(void);
+void backend_error_get_indexnotallocated(void);
+void backend_error_get_duplicateregistration(void);
+void backend_error_get_requestdenied(void);
+void backend_error_get_processingerror(void);
+void backend_error_get_nonstandard(void);
+void backend_error_getnext_toobig(void);
+void backend_error_getnext_nosuchname(void);
+void backend_error_getnext_badvalue(void);
+void backend_error_getnext_readonly(void);
+void backend_error_getnext_generr(void);
+void backend_error_getnext_noaccess(void);
+void backend_error_getnext_wrongtype(void);
+void backend_error_getnext_wronglength(void);
+void backend_error_getnext_wrongencoding(void);
+void backend_error_getnext_wrongvalue(void);
+void backend_error_getnext_nocreation(void);
+void backend_error_getnext_inconsistentvalue(void);
+void backend_error_getnext_resourceunavailable(void);
+void backend_error_getnext_commitfailed(void);
+void backend_error_getnext_undofailed(void);
+void backend_error_getnext_notwritable(void);
+void backend_error_getnext_inconsistentname(void);
+void backend_error_getnext_openfailed(void);
+void backend_error_getnext_notopen(void);
+void backend_error_getnext_indexwrongtype(void);
+void backend_error_getnext_indexalreadyallocated(void);
+void backend_error_getnext_indexnonavailable(void);
+void backend_error_getnext_indexnotallocated(void);
+void backend_error_getnext_unsupportedcontext(void);
+void backend_error_getnext_duplicateregistration(void);
+void backend_error_getnext_unknownregistration(void);
+void backend_error_getnext_parseerror(void);
+void backend_error_getnext_requestdenied(void);
+void backend_error_getnext_processingerror(void);
+void backend_error_getnext_nonstandard(void);
diff --git a/regress/usr.sbin/snmpd/snmp.c b/regress/usr.sbin/snmpd/snmp.c
new file mode 100644 (file)
index 0000000..63f0bb6
--- /dev/null
@@ -0,0 +1,855 @@
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <arpa/inet.h>
+
+#include <ber.h>
+#include <err.h>
+#include <inttypes.h>
+#include <netdb.h>
+#include <poll.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <vis.h>
+
+#include "regress.h"
+
+#include <stdio.h>
+
+#define SNMP_HOSTNAME "127.0.0.1"
+#define SNMP_PORT "161"
+
+#define SNMP_R_COMMUNITY "public"
+
+enum snmp_application {
+        APPLICATION_IPADDR = 0,
+        APPLICATION_COUNTER32 = 1,
+        APPLICATION_GAUGE32 = 2,
+        APPLICATION_UNSIGNED32 = 2,
+        APPLICATION_TIMETICKS = 3,
+        APPLICATION_OPAQUE = 4,
+        APPLICATION_NSAPADDR = 5,
+        APPLICATION_COUNTER64 = 6,
+};
+
+enum snmp_exception {
+       EXCEPTION_NOSUCHOBJECT = 0,
+       EXCEPTION_NOSUCHINSTANCE = 1,
+       EXCEPTION_ENDOFMIBVIEW = 2
+};
+
+enum snmp_request {
+       REQUEST_GET = 0,
+       REQUEST_GETNEXT = 1,
+       REQUEST_RESPONSE = 2,
+       REQUEST_SET = 3,
+       REQUEST_TRAP = 4,
+       REQUEST_GETBULK = 5,
+       REQUEST_INFORM = 6,
+       REQUEST_TRAPV2 = 7,
+       REQUEST_REPORT = 8
+};
+
+int32_t snmpv2_send(int, const char *, enum snmp_request, int32_t, int32_t,
+    int32_t, struct varbind *, size_t);
+struct ber_element *snmp_v2_recv(int, int);
+struct ber_element *snmp_pdu(enum snmp_request, int32_t, int32_t, int32_t,
+    struct varbind *, size_t);
+struct ber_element *snmp_varbindlist(struct varbind *, size_t);
+struct ber_oid *snmp_oid2ber_oid(struct oid *, struct ber_oid *);
+struct ber_element *snmp_data2ber_element(enum type, union data *);
+unsigned int smi_application(struct ber_element *);
+char *smi_oid2string(struct ber_oid *, char *, size_t);
+char *smi_print_element(struct ber_element *);
+void smi_debug_elements(struct ber_element *);
+struct ber_element *v2cmps(struct ber_element *, const char *);
+void snmp_pdu_validate(struct ber_element *, enum snmp_request, int32_t,
+    int32_t, int32_t, struct varbind *, size_t);
+
+socklen_t
+snmp_resolve(int type, const char *hostname, const char *servname, struct sockaddr *sa)
+{
+       struct addrinfo hints, *res;
+       socklen_t salen;
+       int error;
+
+       if (hostname == NULL)
+               hostname = SNMP_HOSTNAME;
+       if (servname == NULL)
+               servname = SNMP_PORT;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = AF_UNSPEC;
+       hints.ai_socktype = type;
+
+       if ((error = getaddrinfo(hostname, servname, &hints, &res)) != 0)
+               errx(1, "getaddrinfo(%s, %s): %s", hostname, servname,
+                   gai_strerror(error));
+
+       memcpy(sa, res->ai_addr, res->ai_addrlen);
+       salen = res->ai_addrlen;
+
+       freeaddrinfo(res);
+       return salen;
+}
+
+int
+snmp_connect(int type, struct sockaddr *sa, socklen_t salen)
+{
+       int s;
+
+       if ((s = socket(sa->sa_family, type, 0)) == -1)
+               err(1, "socket");
+       if (connect(s, sa, salen) == -1)
+               err(1, "connect");
+       return s;
+}
+
+int32_t
+snmpv2_get(int s, const char *community, int32_t requestid,
+    struct varbind *varbindlist, size_t nvarbind)
+{
+       return snmpv2_send(s, community, REQUEST_GET, requestid, 0, 0,
+           varbindlist, nvarbind);
+}
+
+int32_t
+snmpv2_getnext(int s, const char *community, int32_t requestid,
+    struct varbind *varbindlist, size_t nvarbind)
+{
+       return snmpv2_send(s, community, REQUEST_GETNEXT, requestid, 0, 0,
+           varbindlist, nvarbind);
+}
+
+int32_t
+snmpv2_getbulk(int s, const char *community, int32_t requestid, int32_t nonrep,
+    int32_t maxrep, struct varbind *varbindlist, size_t nvarbind)
+{
+       return snmpv2_send(s, community, REQUEST_GETBULK, requestid, nonrep,
+           maxrep, varbindlist, nvarbind);
+}
+
+int32_t
+snmpv2_send(int s, const char *community, enum snmp_request request,
+    int32_t requestid, int32_t error, int32_t index,
+    struct varbind *varbindlist, size_t nvarbind)
+{
+       struct ber_element *message;
+       struct ber ber = {};
+       void *buf;
+       ssize_t buflen, writelen;
+
+       if (community == NULL)
+               community = SNMP_R_COMMUNITY;
+       while (requestid == 0) 
+               requestid = arc4random();
+       message = ober_printf_elements(NULL, "{dse}", 1, community,
+           snmp_pdu(request, requestid, error, index, varbindlist, nvarbind));
+       if (message == NULL)
+               err(1, NULL);
+
+       if (ober_write_elements(&ber, message) == -1)
+               err(1, "ober_write_elements");
+
+       buflen = ober_get_writebuf(&ber, &buf);
+       if ((writelen = write(s, buf, buflen)) == -1)
+               err(1, "write");
+       if (writelen != buflen)
+               errx(1, "write: short write");
+
+       if (verbose) {
+               printf("SNMP send(%d):\n", s);
+               smi_debug_elements(message);
+       }
+       ober_free_elements(message);
+       ober_free(&ber);
+
+       return requestid;
+}
+
+void
+snmpv2_response_validate(int s, int timeout, const char *community,
+    int32_t requestid, int32_t error, int32_t index,
+    struct varbind *varbindlist, size_t nvarbind)
+{
+       struct ber_element *message, *pdu;
+
+       message = snmp_v2_recv(s, timeout);
+
+       if (community == NULL)
+               community = SNMP_R_COMMUNITY;
+       snmp_pdu_validate(v2cmps(message, community), REQUEST_RESPONSE,
+           requestid, error, index, varbindlist, nvarbind);
+
+       ober_free_elements(message);
+}
+
+struct ber_element *
+snmp_v2_recv(int s, int timeout)
+{
+       struct pollfd pfd = {
+               .fd = s,
+               .events = POLLIN
+       };
+       char buf[1024];
+       struct ber ber = {};
+       struct ber_element *message;
+       ssize_t n;
+       int ret;
+
+       if ((ret = poll(&pfd, 1, timeout)) == -1)
+               err(1, "poll");
+       if (ret == 0)
+               errx(1, "%s: timeout", __func__);
+       if ((n = read(s, buf, sizeof(buf))) == -1)
+               err(1, "agentx read");
+
+       ober_set_application(&ber, smi_application);
+       ober_set_readbuf(&ber, buf, n);
+
+       message = ober_read_elements(&ber, NULL);
+       if (verbose) {
+               printf("SNMP received(%d):\n", s);
+               smi_debug_elements(message);
+       }
+
+       ober_free(&ber);
+
+       return message;
+}
+
+void
+snmp_timeout(int s, int timeout)
+{
+       int ret;
+       struct pollfd pfd = {
+               .fd = s,
+               .events = POLLIN
+       };
+       
+       if ((ret = poll(&pfd, 1, timeout)) == -1)
+               err(1, "poll");
+       if (ret != 0)
+               errx(1, "%s: unexpected snmp data", __func__);
+}
+
+struct ber_element *
+snmp_pdu(enum snmp_request request, int32_t requestid, int32_t error,
+    int32_t index, struct varbind *varbindlist, size_t nvarbind)
+{
+       struct ber_element *pdu;
+
+       if ((pdu = ober_printf_elements(NULL, "{tddde}", BER_CLASS_CONTEXT,
+           request, requestid, error, index,
+           snmp_varbindlist(varbindlist, nvarbind))) == NULL)
+               err(1, NULL);
+       return pdu;
+}
+
+struct ber_element *
+snmp_varbindlist(struct varbind *varbindlist, size_t nvarbind)
+{
+       struct ber_element *vblist, *prev = NULL;
+       struct ber_oid oid;
+       size_t i;
+
+       if ((vblist = prev = ober_add_sequence(NULL)) == NULL)
+               err(1, NULL);
+       for (i = 0; i < nvarbind; i++) {
+               if ((prev = ober_printf_elements(prev, "{Oe}",
+                   snmp_oid2ber_oid(&varbindlist[i].name, &oid),
+                   snmp_data2ber_element(varbindlist[i].type,
+                   &varbindlist[i].data))) == NULL)
+                       err(1, NULL);
+       }
+
+       return vblist;
+}
+
+struct ber_oid *
+snmp_oid2ber_oid(struct oid *oid, struct ber_oid *boid)
+{
+       size_t i;
+
+       for (i = 0; i < oid->n_subid; i++)
+               boid->bo_id[i] = oid->subid[i];
+       boid->bo_n = oid->n_subid;
+
+       return boid;
+}
+
+struct ber_element *
+snmp_data2ber_element(enum type type, union data *data)
+{
+       struct ber_element *elm;
+       struct ber_oid oid;
+
+       switch (type) {
+       case TYPE_INTEGER:
+               elm = ober_add_integer(NULL, data->int32);
+               break;
+       case TYPE_OCTETSTRING:
+               elm = ober_add_nstring(NULL, data->octetstring.string,
+                   data->octetstring.len);
+               break;
+       case TYPE_NULL:
+               elm = ober_add_null(NULL);
+               break;
+       case TYPE_OBJECTIDENTIFIER:
+               elm = ober_add_oid(NULL, snmp_oid2ber_oid(&data->oid, &oid));
+               break;
+       case TYPE_IPADDRESS:
+               if ((elm = ober_add_nstring(NULL, data->octetstring.string,
+                   data->octetstring.len)) == NULL)
+                       err(1, NULL);
+               ober_set_header(elm, BER_CLASS_APPLICATION, APPLICATION_IPADDR);
+               break;
+       case TYPE_COUNTER32:
+               if ((elm = ober_add_integer(NULL, data->uint32)) == NULL)
+                       err(1, NULL);
+               ober_set_header(elm, BER_CLASS_APPLICATION,
+                   APPLICATION_COUNTER32);
+               break;
+       case TYPE_GAUGE32:
+               if ((elm = ober_add_integer(NULL, data->uint32)) == NULL)
+                       err(1, NULL);
+               ober_set_header(elm, BER_CLASS_APPLICATION,
+                   APPLICATION_GAUGE32);
+               break;
+       case TYPE_TIMETICKS:
+               if ((elm = ober_add_integer(NULL, data->uint32)) == NULL)
+                       err(1, NULL);
+               ober_set_header(elm, BER_CLASS_APPLICATION,
+                   APPLICATION_TIMETICKS);
+               break;
+       case TYPE_OPAQUE:
+               if ((elm = ober_add_nstring(NULL, data->octetstring.string,
+                   data->octetstring.len)) == NULL)
+                       err(1, NULL);
+               ober_set_header(elm, BER_CLASS_APPLICATION, APPLICATION_OPAQUE);
+               break;
+       case TYPE_COUNTER64:
+               if ((elm = ober_add_integer(NULL, data->uint64)) == NULL)
+                       err(1, NULL);
+               ober_set_header(elm, BER_CLASS_APPLICATION,
+                   APPLICATION_COUNTER64);
+               break;
+       case TYPE_NOSUCHOBJECT:
+               if ((elm = ober_add_null(NULL)) == NULL)
+                       err(1, NULL);
+               ober_set_header(elm, BER_CLASS_CONTEXT, EXCEPTION_NOSUCHOBJECT);
+               break;
+       case TYPE_NOSUCHINSTANCE:
+               if ((elm = ober_add_null(NULL)) == NULL)
+                       err(1, NULL);
+               ober_set_header(elm, BER_CLASS_CONTEXT,
+                   EXCEPTION_NOSUCHINSTANCE);
+               break;
+       case TYPE_ENDOFMIBVIEW:
+               if ((elm = ober_add_null(NULL)) == NULL)
+                       err(1, NULL);
+               ober_set_header(elm, BER_CLASS_CONTEXT, EXCEPTION_ENDOFMIBVIEW);
+               break;
+       default:
+               errx(1, "%s: unsupported type: %d", __func__, type);
+       }
+       if (elm == NULL)
+               err(1, NULL);
+       return elm;
+}
+
+unsigned int
+smi_application(struct ber_element *elm)
+{
+       if (elm->be_class != BER_CLASS_APPLICATION)
+               return -1;
+
+       switch (elm->be_type) {
+       case APPLICATION_IPADDR:
+       case APPLICATION_OPAQUE:
+               return BER_TYPE_OCTETSTRING;
+       case APPLICATION_COUNTER32:
+       case APPLICATION_GAUGE32:
+       case APPLICATION_TIMETICKS:
+       case APPLICATION_COUNTER64:
+               return BER_TYPE_INTEGER;
+       default:
+               return -1;
+       }
+}
+
+char *
+smi_oid2string(struct ber_oid *oid, char *buf, size_t len)
+{
+       char digit[11];
+       size_t i;
+
+       buf[0] = '\0';
+       for (i = 0; i < oid->bo_n; i++) {
+               snprintf(digit, sizeof(digit), "%"PRIu32, oid->bo_id[i]);
+               if (i > 0)
+                       strlcat(buf, ".", len);
+               strlcat(buf, digit, len);
+       }
+       return buf;
+}
+
+char *
+smi_print_element(struct ber_element *root)
+{
+       char            *str = NULL, *buf, *p;
+       long long        v;
+       struct ber_oid   o;
+       char             strbuf[BUFSIZ];
+
+       switch (root->be_class) {
+       case BER_CLASS_UNIVERSAL:
+               switch (root->be_type) {
+               case BER_TYPE_INTEGER:
+                       if (ober_get_integer(root, &v) == -1)
+                               goto fail;
+                       if (asprintf(&str, "%lld", v) == -1)
+                               goto fail;
+                       break;
+               case BER_TYPE_OBJECT:
+                       if (ober_get_oid(root, &o) == -1)
+                               goto fail;
+                       if (asprintf(&str, "%s", smi_oid2string(&o, strbuf,
+                           sizeof(strbuf))) == -1)
+                               goto fail;
+                       break;
+               case BER_TYPE_OCTETSTRING:
+                       if (ober_get_string(root, &buf) == -1)
+                               goto fail;
+                       p = reallocarray(NULL, 4, root->be_len + 1);
+                       if (p == NULL)
+                               goto fail;
+                       strvisx(p, buf, root->be_len, VIS_NL);
+                       if (asprintf(&str, "\"%s\"", p) == -1) {
+                               free(p);
+                               goto fail;
+                       }
+                       free(p);
+                       break;
+               case BER_TYPE_NULL:
+                       if (asprintf(&str, "null") == -1)
+                               goto fail;
+                       break;
+               default:
+                       /* Should not happen in a valid SNMP packet */
+                       if (asprintf(&str, "[U/%u]", root->be_type) == -1)
+                               goto fail;
+                       break;
+               }
+               break;
+       case BER_CLASS_APPLICATION:
+               switch (root->be_type) {
+               case APPLICATION_IPADDR:
+                       if (ober_get_string(root, &buf) == -1)
+                               goto fail;
+                       if (asprintf(&str, "%s",
+                           inet_ntoa(*(struct in_addr *)buf)) == -1)
+                                       goto fail;
+                       break;
+               case APPLICATION_COUNTER32:
+                       if (ober_get_integer(root, &v) == -1)
+                               goto fail;
+                       if (asprintf(&str, "%lld(c32)", v) == -1)
+                               goto fail;
+                       break;
+               case APPLICATION_GAUGE32:
+                       if (ober_get_integer(root, &v) == -1)
+                               goto fail;
+                       if (asprintf(&str, "%lld(g32)", v) == -1)
+                               goto fail;
+                       break;
+               case APPLICATION_TIMETICKS:
+                       if (ober_get_integer(root, &v) == -1)
+                               goto fail;
+                       if (asprintf(&str, "%lld.%llds", v/100, v%100) == -1)
+                               goto fail;
+                       break;
+               case APPLICATION_OPAQUE:
+                       if (ober_get_string(root, &buf) == -1)
+                               goto fail;
+                       p = reallocarray(NULL, 4, root->be_len + 1);
+                       if (p == NULL)
+                               goto fail;
+                       strvisx(p, buf, root->be_len, VIS_NL);
+                       if (asprintf(&str, "\"%s\"(opaque)", p) == -1) {
+                               free(p);
+                               goto fail;
+                       }
+                       free(p);
+                       break;
+               case APPLICATION_COUNTER64:
+                       if (ober_get_integer(root, &v) == -1)
+                               goto fail;
+                       if (asprintf(&str, "%lld(c64)", v) == -1)
+                               goto fail;
+                       break;
+               default:
+                       /* Should not happen in a valid SNMP packet */
+                       if (asprintf(&str, "[A/%u]", root->be_type) == -1)
+                               goto fail;
+                       break;
+               }
+               break;
+       case BER_CLASS_CONTEXT:
+               switch (root->be_type) {
+               case EXCEPTION_NOSUCHOBJECT:
+                       str = strdup("noSuchObject");
+                       break;
+               case EXCEPTION_NOSUCHINSTANCE:
+                       str = strdup("noSuchInstance");
+                       break;
+               case EXCEPTION_ENDOFMIBVIEW:
+                       str = strdup("endOfMibView");
+                       break;
+               default:
+                       /* Should not happen in a valid SNMP packet */
+                       if (asprintf(&str, "[C/%u]", root->be_type) == -1)
+                               goto fail;
+                       break;
+               }
+               break;
+       default:
+               /* Should not happen in a valid SNMP packet */
+               if (asprintf(&str, "[%hhu/%u]", root->be_class,
+                   root->be_type) == -1)
+                       goto fail;
+               break;
+       }
+
+       return (str);
+
+ fail:
+       free(str);
+       return (NULL);
+}
+
+void
+smi_debug_elements(struct ber_element *root)
+{
+       static int       indent = 0;
+       char            *value;
+       int              constructed;
+
+       /* calculate lengths */
+       ober_calc_len(root);
+
+       switch (root->be_encoding) {
+       case BER_TYPE_SEQUENCE:
+       case BER_TYPE_SET:
+               constructed = root->be_encoding;
+               break;
+       default:
+               constructed = 0;
+               break;
+       }
+
+       fprintf(stderr, "%*slen %lu ", indent, "", root->be_len);
+       switch (root->be_class) {
+       case BER_CLASS_UNIVERSAL:
+               fprintf(stderr, "class: universal(%u) type: ", root->be_class);
+               switch (root->be_type) {
+               case BER_TYPE_EOC:
+                       fprintf(stderr, "end-of-content");
+                       break;
+               case BER_TYPE_INTEGER:
+                       fprintf(stderr, "integer");
+                       break;
+               case BER_TYPE_BITSTRING:
+                       fprintf(stderr, "bit-string");
+                       break;
+               case BER_TYPE_OCTETSTRING:
+                       fprintf(stderr, "octet-string");
+                       break;
+               case BER_TYPE_NULL:
+                       fprintf(stderr, "null");
+                       break;
+               case BER_TYPE_OBJECT:
+                       fprintf(stderr, "object");
+                       break;
+               case BER_TYPE_ENUMERATED:
+                       fprintf(stderr, "enumerated");
+                       break;
+               case BER_TYPE_SEQUENCE:
+                       fprintf(stderr, "sequence");
+                       break;
+               case BER_TYPE_SET:
+                       fprintf(stderr, "set");
+                       break;
+               }
+               break;
+       case BER_CLASS_APPLICATION:
+               fprintf(stderr, "class: application(%u) type: ",
+                   root->be_class);
+               switch (root->be_type) {
+               case APPLICATION_IPADDR:
+                       fprintf(stderr, "ipaddr");
+                       break;
+               case APPLICATION_COUNTER32:
+                       fprintf(stderr, "counter32");
+                       break;
+               case APPLICATION_GAUGE32:
+                       fprintf(stderr, "gauge32");
+                       break;
+               case APPLICATION_TIMETICKS:
+                       fprintf(stderr, "timeticks");
+                       break;
+               case APPLICATION_OPAQUE:
+                       fprintf(stderr, "opaque");
+                       break;
+               case APPLICATION_COUNTER64:
+                       fprintf(stderr, "counter64");
+                       break;
+               }
+               break;
+       case BER_CLASS_CONTEXT:
+               fprintf(stderr, "class: context(%u) type: ",
+                   root->be_class);
+               switch (root->be_type) {
+               case REQUEST_GET:
+                       fprintf(stderr, "getreq");
+                       break;
+               case REQUEST_GETNEXT:
+                       fprintf(stderr, "getnextreq");
+                       break;
+               case REQUEST_RESPONSE:
+                       fprintf(stderr, "response");
+                       break;
+               case REQUEST_SET:
+                       fprintf(stderr, "setreq");
+                       break;
+               case REQUEST_TRAP:
+                       fprintf(stderr, "trap");
+                       break;
+               case REQUEST_GETBULK:
+                       fprintf(stderr, "getbulkreq");
+                       break;
+               case REQUEST_INFORM:
+                       fprintf(stderr, "informreq");
+                       break;
+               case REQUEST_TRAPV2:
+                       fprintf(stderr, "trapv2");
+                       break;
+               case REQUEST_REPORT:
+                       fprintf(stderr, "report");
+                       break;
+               }
+               break;
+       case BER_CLASS_PRIVATE:
+               fprintf(stderr, "class: private(%u) type: ", root->be_class);
+               break;
+       default:
+               fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class);
+               break;
+       }
+       fprintf(stderr, "(%u) encoding %u ",
+           root->be_type, root->be_encoding);
+
+       if ((value = smi_print_element(root)) == NULL)
+               goto invalid;
+
+       switch (root->be_encoding) {
+       case BER_TYPE_INTEGER:
+       case BER_TYPE_ENUMERATED:
+               fprintf(stderr, "value %s", value);
+               break;
+       case BER_TYPE_BITSTRING:
+               fprintf(stderr, "hexdump %s", value);
+               break;
+       case BER_TYPE_OBJECT:
+               fprintf(stderr, "oid %s", value);
+               break;
+       case BER_TYPE_OCTETSTRING:
+               if (root->be_class == BER_CLASS_APPLICATION &&
+                   root->be_type == APPLICATION_IPADDR) {
+                       fprintf(stderr, "addr %s", value);
+               } else {
+                       fprintf(stderr, "string %s", value);
+               }
+               break;
+       case BER_TYPE_NULL:     /* no payload */
+       case BER_TYPE_EOC:
+       case BER_TYPE_SEQUENCE:
+       case BER_TYPE_SET:
+       default:
+               fprintf(stderr, "%s", value);
+               break;
+       }
+
+ invalid:
+       if (value == NULL)
+               fprintf(stderr, "<INVALID>");
+       else
+               free(value);
+       fprintf(stderr, "\n");
+
+       if (constructed)
+               root->be_encoding = constructed;
+
+       if (constructed && root->be_sub) {
+               indent += 2;
+               smi_debug_elements(root->be_sub);
+               indent -= 2;
+       }
+       if (root->be_next)
+               smi_debug_elements(root->be_next);
+}
+
+struct ber_element *
+v2cmps(struct ber_element *message, const char *community)
+{
+       int version;
+       const char *mcommunity;
+       struct ber_element *pdu;
+
+       if (ober_scanf_elements(message, "{dse}$", &version, &mcommunity, &pdu) == -1)
+               err(1, "%s: ober_scanf_elements", __func__);
+
+       if (strcmp(mcommunity, community) != 0)
+               errx(1, "%s: invalid community (%s/%s)", __func__, mcommunity,
+                   community);
+
+       return pdu;
+}
+
+void
+snmp_pdu_validate(struct ber_element *pdu, enum snmp_request request,
+    int32_t requestid, int32_t error, int32_t index, struct varbind *varbindlist,
+    size_t nvarbind)
+{
+       int32_t mrequestid, merror, mindex;
+       int class;
+       unsigned int type;
+       struct ber_element *mvarbindlist, *varbind;
+       struct ber_oid moid, oid;
+       struct ber_element *value;
+       char oidbuf1[512], oidbuf2[512];
+       size_t i;
+
+       if (ober_scanf_elements(pdu, "t{ddd{e}$}$", &class, &type, &mrequestid,
+           &merror, &mindex, &varbind) == -1)
+               err(1, "%s: ober_scanf_elementsi", __func__);
+
+       if (class != BER_CLASS_CONTEXT || type != request)
+               errx(1, "%s: unexpected pdu type", __func__);
+       if (mrequestid != requestid)
+               errx(1, "%s: unexpected pdu requestid (%d/%d)",
+                   __func__, mrequestid, requestid);
+       if (error != merror)
+               errx(1, "%s: unexpected pdu error (%d/%d)",
+                   __func__, merror, error);
+       if (index != mindex)
+               errx(1, "%s: unepxected pdu index (%d/%d)",
+                   __func__, mindex, index);
+
+       for (i = 0; varbind != NULL; varbind = varbind->be_next, i++) {
+               if (ober_scanf_elements(varbind, "{oeS$}", &moid, &value) == -1)
+                       err(1, "%s: ober_scanf_elements", __func__);
+               if (i >= nvarbind)
+                       continue;
+               snmp_oid2ber_oid(&varbindlist[i].name, &oid);
+               if (ober_oid_cmp(&moid, &oid) != 0)
+                       errx(1, "%s: unexpected oid (%s/%s)", __func__,
+                           smi_oid2string(&moid, oidbuf1, sizeof(oidbuf1)),
+                           smi_oid2string(&oid, oidbuf2, sizeof(oidbuf2)));
+               switch (varbindlist[i].type) {
+               case TYPE_INTEGER:
+                       if (value->be_class != BER_CLASS_UNIVERSAL ||
+                           value->be_type != BER_TYPE_INTEGER ||
+                           value->be_numeric != varbindlist[i].data.int32)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_OCTETSTRING:
+                       if (value->be_class != BER_CLASS_UNIVERSAL ||
+                           value->be_type != BER_TYPE_OCTETSTRING ||
+                           value->be_len !=
+                           varbindlist[i].data.octetstring.len ||
+                           memcmp(varbindlist[i].data.octetstring.string,
+                           value->be_val, value->be_len) != 0)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_NULL:
+                       if (value->be_class != BER_CLASS_UNIVERSAL ||
+                           value->be_type != BER_TYPE_NULL)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_OBJECTIDENTIFIER:
+                       if (value->be_class != BER_CLASS_UNIVERSAL ||
+                           value->be_type != BER_TYPE_OBJECT)
+                               errx(1, "%s: unexpected value", __func__);
+                       if (ober_get_oid(value, &moid) == -1)
+                               errx(1, "%s: unexpected value", __func__);
+                       snmp_oid2ber_oid(&varbindlist[i].data.oid, &oid);
+                       if (ober_oid_cmp(&oid, &moid) != 0)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_IPADDRESS:
+                       if (value->be_class != BER_CLASS_APPLICATION ||
+                           value->be_type != APPLICATION_IPADDR ||
+                           value->be_len !=
+                           varbindlist[i].data.octetstring.len ||
+                           memcmp(varbindlist[i].data.octetstring.string,
+                           value->be_val, value->be_len) != 0)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_COUNTER32:
+                       if (value->be_class != BER_CLASS_APPLICATION ||
+                           value->be_type != APPLICATION_COUNTER32 ||
+                           value->be_numeric != varbindlist[i].data.uint32)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_GAUGE32:
+                       if (value->be_class != BER_CLASS_APPLICATION ||
+                           value->be_type != APPLICATION_GAUGE32 ||
+                           value->be_numeric != varbindlist[i].data.uint32)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_TIMETICKS:
+                       if (value->be_class != BER_CLASS_APPLICATION ||
+                           value->be_type != APPLICATION_TIMETICKS ||
+                           value->be_numeric != varbindlist[i].data.uint32)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_OPAQUE:
+                       if (value->be_class != BER_CLASS_APPLICATION ||
+                           value->be_type != APPLICATION_OPAQUE ||
+                           value->be_len !=
+                           varbindlist[i].data.octetstring.len ||
+                           memcmp(varbindlist[i].data.octetstring.string,
+                           value->be_val, value->be_len) != 0)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_COUNTER64:
+                       if (value->be_class != BER_CLASS_APPLICATION ||
+                           value->be_type != APPLICATION_COUNTER64 ||
+                           value->be_numeric != varbindlist[i].data.uint64)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_NOSUCHOBJECT:
+                       if (value->be_class != BER_CLASS_CONTEXT ||
+                           value->be_type != EXCEPTION_NOSUCHOBJECT)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_NOSUCHINSTANCE:
+                       if (value->be_class != BER_CLASS_CONTEXT ||
+                           value->be_type != EXCEPTION_NOSUCHINSTANCE)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               case TYPE_ENDOFMIBVIEW:
+                       if (value->be_class != BER_CLASS_CONTEXT ||
+                           value->be_type != EXCEPTION_ENDOFMIBVIEW)
+                               errx(1, "%s: unexpected value", __func__);
+                       break;
+               default:
+                       errx(1, "%s: unexpected type", __func__);
+               }
+       }
+       if (i != nvarbind)
+               errx(1, "%s: unexpected amount of varbind (%zu/%zu)", __func__,
+                   i, nvarbind);
+}
diff --git a/regress/usr.sbin/snmpd/snmpd.conf b/regress/usr.sbin/snmpd/snmpd.conf
new file mode 100644 (file)
index 0000000..0bbea07
--- /dev/null
@@ -0,0 +1,35 @@
+## Generic config to test internals
+
+# Assume snmp ports are available
+listen on 127.0.0.1 snmpv1 snmpv2c snmpv3
+listen on tcp 127.0.0.1 snmpv1 snmpv2c snmpv3
+
+agentx path "/tmp/agentx" mode 222
+
+system contact "regress@openbsd.org"
+
+# SNMPv1/SNMPv2c
+read-only community public
+trap community private
+
+# SNMPv3
+seclevel none
+user noauthpriv
+user auth_md5 authkey testpass auth hmac-md5
+user auth_sha1 authkey testpass auth hmac-sha1
+user auth_sha224 authkey testpass auth hmac-sha224
+user auth_sha256 authkey testpass auth hmac-sha256
+user auth_sha384 authkey testpass auth hmac-sha384
+user auth_sha512 authkey testpass auth hmac-sha512
+user authpriv_md5_des authkey testpass auth hmac-md5 enckey testpass enc des
+user authpriv_md5_aes authkey testpass auth hmac-md5 enckey testpass enc aes
+user authpriv_sha1_des authkey testpass auth hmac-sha1 enckey testpass enc des
+user authpriv_sha1_aes authkey testpass auth hmac-sha1 enckey testpass enc aes
+user authpriv_sha224_des authkey testpass auth hmac-sha224 enckey testpass enc des
+user authpriv_sha224_aes authkey testpass auth hmac-sha224 enckey testpass enc aes
+user authpriv_sha256_des authkey testpass auth hmac-sha256 enckey testpass enc des
+user authpriv_sha256_aes authkey testpass auth hmac-sha256 enckey testpass enc aes
+user authpriv_sha384_des authkey testpass auth hmac-sha384 enckey testpass enc des
+user authpriv_sha384_aes authkey testpass auth hmac-sha384 enckey testpass enc aes
+user authpriv_sha512_des authkey testpass auth hmac-sha512 enckey testpass enc des
+user authpriv_sha512_aes authkey testpass auth hmac-sha512 enckey testpass enc aes
diff --git a/regress/usr.sbin/snmpd/snmpd_regress.c b/regress/usr.sbin/snmpd/snmpd_regress.c
new file mode 100644 (file)
index 0000000..a4decb6
--- /dev/null
@@ -0,0 +1,309 @@
+#include <sys/socket.h>
+
+#include <err.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "regress.h"
+
+__dead void usage(void);
+
+const struct {
+       char *target;
+       void (*function)(void);
+} targets[] = {
+       { "agentx_open_nnbo", agentx_open_nnbo },
+       { "agentx_open_nbo", agentx_open_nbo },
+       { "agentx_open_invalidversion", agentx_open_invalidversion },
+       { "agentx_open_ignore_sessionid", agentx_open_ignore_sessionid },
+       { "agentx_open_invalid_oid", agentx_open_invalid_oid },
+       { "agentx_open_descr_too_long", agentx_open_descr_too_long },
+       { "agentx_open_descr_invalid", agentx_open_descr_invalid },
+       { "agentx_open_context", agentx_open_context },
+       { "agentx_open_instance_registration", agentx_open_instance_registration },
+       { "agentx_open_new_index", agentx_open_new_index },
+       { "agentx_open_any_index", agentx_open_any_index },
+       { "agentx_ping_notopen", agentx_ping_notopen },
+       { "agentx_ping_invalid_sessionid", agentx_ping_invalid_sessionid },
+       { "agentx_ping_default", agentx_ping_default },
+       { "agentx_ping_context", agentx_ping_context },
+       { "agentx_ping_invalid_version", agentx_ping_invalid_version },
+       { "agentx_ping_instance_registration", agentx_ping_instance_registration },
+       { "agentx_ping_new_index", agentx_ping_new_index },
+       { "agentx_ping_any_index", agentx_ping_any_index },
+       { "agentx_ping_nbo_nnbo", agentx_ping_nbo_nnbo },
+       { "agentx_ping_nnbo_nbo", agentx_ping_nnbo_nbo },
+       { "agentx_close_notopen", agentx_close_notopen },
+       { "agentx_close_reasonother", agentx_close_reasonother },
+       { "agentx_close_reasonparseerror", agentx_close_reasonparseerror },
+       { "agentx_close_reasonprotocolerror", agentx_close_reasonprotocolerror },
+       { "agentx_close_reasontimouts", agentx_close_reasontimouts },
+       { "agentx_close_reasonshutdown", agentx_close_reasonshutdown },
+       { "agentx_close_reasonbymanager", agentx_close_reasonbymanager },
+       { "agentx_close_reasoninvalid", agentx_close_reasoninvalid },
+       { "agentx_close_single", agentx_close_single },
+       { "agentx_close_notowned", agentx_close_notowned },
+       { "agentx_close_invalid_sessionid", agentx_close_invalid_sessionid },
+       { "agentx_close_context", agentx_close_context },
+       { "agentx_close_invalid_version", agentx_close_invalid_version },
+       { "agentx_close_instance_registration", agentx_close_instance_registration },
+       { "agentx_close_new_index", agentx_close_new_index },
+       { "agentx_close_any_index", agentx_close_any_index },
+       { "agentx_close_nnbo_nbo", agentx_close_nnbo_nbo },
+       { "agentx_register_notopen", agentx_register_notopen },
+       { "agentx_register_invalid_sessionid", agentx_register_invalid_sessionid },
+       { "agentx_register_default", agentx_register_default },
+       { "agentx_register_context", agentx_register_context },
+       { "agentx_register_invalid_version", agentx_register_invalid_version },
+       { "agentx_register_instance_registration", agentx_register_instance_registration },
+       { "agentx_register_new_index", agentx_register_new_index },
+       { "agentx_register_any_index", agentx_register_any_index },
+       { "agentx_register_duplicate_self", agentx_register_duplicate_self },
+       { "agentx_register_duplicate_twocon", agentx_register_duplicate_twocon },
+       { "agentx_register_duplicate_priority", agentx_register_duplicate_priority },
+       { "agentx_register_range", agentx_register_range },
+       { "agentx_register_range_invalidupperbound", agentx_register_range_invalidupperbound },
+       { "agentx_register_range_single", agentx_register_range_single },
+       { "agentx_register_range_overlap_single", agentx_register_range_overlap_single },
+       { "agentx_register_single_overlap_range", agentx_register_single_overlap_range },
+       { "agentx_register_range_overlap_range", agentx_register_range_overlap_range },
+       { "agentx_register_below", agentx_register_below },
+       { "agentx_register_above", agentx_register_above },
+       { "agentx_register_restricted", agentx_register_restricted },
+       { "agentx_unregister_notopen", agentx_unregister_notopen },
+       { "agentx_unregister_invalid_sessionid", agentx_unregister_invalid_sessionid },
+       { "agentx_unregister_notregistered", agentx_unregister_notregistered },
+       { "agentx_unregister_single", agentx_unregister_single },
+       { "agentx_unregister_single_notowned", agentx_unregister_single_notowned },
+       { "agentx_unregister_range", agentx_unregister_range },
+       { "agentx_unregister_range_single", agentx_unregister_range_single },
+       { "agentx_unregister_range_subset", agentx_unregister_range_subset },
+       { "agentx_unregister_range_extra", agentx_unregister_range_extra },
+       { "agentx_unregister_range_priority", agentx_unregister_range_priority },
+       { "agentx_unregister_range_notowned", agentx_unregister_range_notowned },
+       { "backend_get_integer", backend_get_integer },
+       { "backend_get_octetstring", backend_get_octetstring },
+       { "backend_get_objectidentifier", backend_get_objectidentifier },
+       { "backend_get_ipaddress", backend_get_ipaddress },
+       { "backend_get_counter32", backend_get_counter32 },
+       { "backend_get_gauge32", backend_get_gauge32 },
+       { "backend_get_timeticks", backend_get_timeticks },
+       { "backend_get_opaque", backend_get_opaque },
+       { "backend_get_counter64", backend_get_counter64 },
+       { "backend_get_nosuchobject", backend_get_nosuchobject },
+       { "backend_get_nosuchinstance", backend_get_nosuchinstance },
+       { "backend_get_endofmibview", backend_get_endofmibview },
+       { "backend_get_two_single_backend", backend_get_two_single_backend },
+       { "backend_get_two_double_backend", backend_get_two_double_backend },
+       { "backend_get_wrongorder", backend_get_wrongorder },
+       { "backend_get_toofew", backend_get_toofew },
+       { "backend_get_toomany", backend_get_toomany },
+       { "backend_get_instance", backend_get_instance },
+       { "backend_get_instance_below", backend_get_instance_below },
+       { "backend_get_timeout_default", backend_get_timeout_default },
+       { "backend_get_timeout_session_lower", backend_get_timeout_session_lower },
+       { "backend_get_timeout_session_higher", backend_get_timeout_session_higher },
+       { "backend_get_timeout_region_lower", backend_get_timeout_region_lower },
+       { "backend_get_timeout_region_higher", backend_get_timeout_region_higher },
+       { "backend_get_priority_lower", backend_get_priority_lower },
+       { "backend_get_priority_higher", backend_get_priority_higher },
+       { "backend_get_priority_below_lower", backend_get_priority_below_lower },
+       { "backend_get_priority_below_higher", backend_get_priority_below_higher },
+       { "backend_get_close", backend_get_close },
+       { "backend_get_close_overlap", backend_get_close_overlap },
+       { "backend_get_disappear", backend_get_disappear },
+       { "backend_get_disappear_overlap", backend_get_disappear_overlap },
+       { "backend_get_disappear_doublesession", backend_get_disappear_doublesession },
+       { "backend_getnext_selfbound", backend_getnext_selfbound },
+       { "backend_getnext_lowerbound", backend_getnext_lowerbound },
+       { "backend_getnext_lowerbound_self", backend_getnext_lowerbound_self },
+       { "backend_getnext_lowerbound_highprio", backend_getnext_lowerbound_highprio },
+       { "backend_getnext_lowerbound_lowprio", backend_getnext_lowerbound_lowprio },
+       { "backend_getnext_sibling", backend_getnext_sibling },
+       { "backend_getnext_child_gap", backend_getnext_child_gap },
+       { "backend_getnext_nosuchobject", backend_getnext_nosuchobject },
+       { "backend_getnext_nosuchinstance", backend_getnext_nosuchinstance },
+       { "backend_getnext_endofmibview", backend_getnext_endofmibview },
+       { "backend_getnext_inclusive", backend_getnext_inclusive },
+       { "backend_getnext_jumpnext", backend_getnext_jumpnext },
+       { "backend_getnext_jumpnext_endofmibview", backend_getnext_jumpnext_endofmibview },
+       { "backend_getnext_jump_up", backend_getnext_jump_up },
+       { "backend_getnext_two_single_backend", backend_getnext_two_single_backend },
+       { "backend_getnext_two_double_backend", backend_getnext_two_double_backend },
+       { "backend_getnext_instance_below", backend_getnext_instance_below },
+       { "backend_getnext_instance", backend_getnext_instance },
+       { "backend_getnext_instance_exact", backend_getnext_instance_exact },
+       { "backend_getnext_instance_ignore", backend_getnext_instance_ignore },
+       { "backend_getnext_backwards", backend_getnext_backwards },
+       { "backend_getnext_stale", backend_getnext_stale },
+       { "backend_getnext_inclusive_backwards", backend_getnext_inclusive_backwards },
+       { "backend_getnext_toofew", backend_getnext_toofew },
+       { "backend_getnext_toomany", backend_getnext_toomany },
+       { "backend_getbulk_nonrep_zero_maxrep_one", backend_getbulk_nonrep_zero_maxrep_one },
+       { "backend_getbulk_nonrep_zero_maxrep_two", backend_getbulk_nonrep_zero_maxrep_two },
+       { "backend_getbulk_nonrep_one_maxrep_one", backend_getbulk_nonrep_one_maxrep_one },
+       { "backend_getbulk_nonrep_one_maxrep_two", backend_getbulk_nonrep_one_maxrep_two },
+       { "backend_getbulk_nonrep_two_maxrep_two", backend_getbulk_nonrep_two_maxrep_two },
+       { "backend_getbulk_nonrep_negative", backend_getbulk_nonrep_negative },
+       { "backend_error_get_toobig", backend_error_get_toobig },
+       { "backend_error_get_nosuchname", backend_error_get_nosuchname },
+       { "backend_error_get_badvalue", backend_error_get_badvalue },
+       { "backend_error_get_readonly", backend_error_get_readonly },
+       { "backend_error_get_generr", backend_error_get_generr },
+       { "backend_error_get_wrongtype", backend_error_get_wrongtype },
+       { "backend_error_get_wronglength", backend_error_get_wronglength },
+       { "backend_error_get_wrongvalue", backend_error_get_wrongvalue },
+       { "backend_error_get_nocreation", backend_error_get_nocreation },
+       { "backend_error_get_inconsistentvalue", backend_error_get_inconsistentvalue },
+       { "backend_error_get_commitfailed", backend_error_get_commitfailed },
+       { "backend_error_get_undofailed", backend_error_get_undofailed },
+       { "backend_error_get_authorizationerror", backend_error_get_authorizationerror },
+       { "backend_error_get_notwritable", backend_error_get_notwritable },
+       { "backend_error_get_inconsistentname", backend_error_get_inconsistentname },
+       { "backend_error_get_openfailed", backend_error_get_openfailed },
+       { "backend_error_get_notopen", backend_error_get_notopen },
+       { "backend_error_get_indexwrongtype", backend_error_get_indexwrongtype },
+       { "backend_error_get_indexalreadyallocated", backend_error_get_indexalreadyallocated },
+       { "backend_error_get_indexnonavailable", backend_error_get_indexnonavailable },
+       { "backend_error_get_indexnotallocated", backend_error_get_indexnotallocated },
+       { "backend_error_get_duplicateregistration", backend_error_get_duplicateregistration },
+       { "backend_error_get_requestdenied", backend_error_get_requestdenied },
+       { "backend_error_get_processingerror", backend_error_get_processingerror },
+       { "backend_error_get_nonstandard", backend_error_get_nonstandard },
+       { "backend_error_getnext_toobig", backend_error_getnext_toobig },
+       { "backend_error_getnext_nosuchname", backend_error_getnext_nosuchname },
+       { "backend_error_getnext_badvalue", backend_error_getnext_badvalue },
+       { "backend_error_getnext_readonly", backend_error_getnext_readonly },
+       { "backend_error_getnext_generr", backend_error_getnext_generr },
+       { "backend_error_getnext_noaccess", backend_error_getnext_noaccess },
+       { "backend_error_getnext_wrongtype", backend_error_getnext_wrongtype },
+       { "backend_error_getnext_wronglength", backend_error_getnext_wronglength },
+       { "backend_error_getnext_wrongencoding", backend_error_getnext_wrongencoding },
+       { "backend_error_getnext_wrongvalue", backend_error_getnext_wrongvalue },
+       { "backend_error_getnext_nocreation", backend_error_getnext_nocreation },
+       { "backend_error_getnext_inconsistentvalue", backend_error_getnext_inconsistentvalue },
+       { "backend_error_getnext_resourceunavailable", backend_error_getnext_resourceunavailable },
+       { "backend_error_getnext_commitfailed", backend_error_getnext_commitfailed },
+       { "backend_error_getnext_undofailed", backend_error_getnext_undofailed },
+       { "backend_error_getnext_notwritable", backend_error_getnext_notwritable },
+       { "backend_error_getnext_inconsistentname", backend_error_getnext_inconsistentname },
+       { "backend_error_getnext_openfailed", backend_error_getnext_openfailed },
+       { "backend_error_getnext_notopen", backend_error_getnext_notopen },
+       { "backend_error_getnext_indexwrongtype", backend_error_getnext_indexwrongtype },
+       { "backend_error_getnext_indexalreadyallocated", backend_error_getnext_indexalreadyallocated },
+       { "backend_error_getnext_indexnonavailable", backend_error_getnext_indexnonavailable },
+       { "backend_error_getnext_indexnotallocated", backend_error_getnext_indexnotallocated },
+       { "backend_error_getnext_unsupportedcontext", backend_error_getnext_unsupportedcontext },
+       { "backend_error_getnext_duplicateregistration", backend_error_getnext_duplicateregistration },
+       { "backend_error_getnext_unknownregistration", backend_error_getnext_unknownregistration },
+       { "backend_error_getnext_parseerror", backend_error_getnext_parseerror },
+       { "backend_error_getnext_requestdenied", backend_error_getnext_requestdenied },
+       { "backend_error_getnext_processingerror", backend_error_getnext_processingerror },
+       { "backend_error_getnext_nonstandard", backend_error_getnext_nonstandard },
+       { NULL, NULL }
+};
+
+int verbose = 0;
+char *axsocket = NULL;
+
+char *hostname = NULL;
+char *servname = NULL;
+
+char *community = NULL;
+
+int
+main(int argc, char *argv[])
+{
+       size_t i, j;
+       int c;
+
+       while ((c = getopt(argc, argv, "a:h:p:v")) != -1) {
+               switch (c) {
+               case 'a':
+                       axsocket = optarg;
+                       break;
+               case 'c':
+                       community = optarg;
+                       break;
+               case 'h':
+                       hostname = optarg;
+                       break;
+               case 'p':
+                       servname = optarg;
+                       break;
+               case 'v':
+                       verbose = 1;
+                       break;
+               default:
+                       usage();
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 1)
+               usage();
+
+       for (i = 0; i < argc; i++) {
+               for (j = 0; targets[j].target != NULL; j++) {
+                       if (strcmp(argv[i], targets[j].target) == 0) {
+                               targets[j].function();
+                               return 0;
+                       }
+               }
+       }
+
+       errx(1, "Unknown target: %s", argv[1]);
+}
+
+__dead void
+usage(void)
+{
+       fprintf(stderr, "%s: [-v] [-a axsocket] test\n", getprogname());
+       exit(1);
+}
+
+int
+oid_cmp(struct oid *a, struct oid *b) 
+{
+       size_t   i, min;
+
+       min = a->n_subid < b->n_subid ? a->n_subid : b->n_subid;
+       for (i = 0; i < min; i++) {
+               if (a->subid[i] < b->subid[i]) 
+                       return (-1);
+               if (a->subid[i] > b->subid[i])
+                       return (1);
+       }
+       /* a is parent of b */
+       if (a->n_subid < b->n_subid)
+               return (-2);
+       /* a is child of b */
+       if (a->n_subid > b->n_subid)
+               return 2;
+       return (0);
+}
+
+char *
+oid_print(struct oid *oid, char *buf, size_t len)
+{
+       char digit[11];
+       size_t i;
+
+       buf[0] = '\0';
+       for (i = 0; i < oid->n_subid; i++) {
+               snprintf(digit, sizeof(digit), "%"PRIu32, oid->subid[i]);
+               if (i > 0)
+                       strlcat(buf, ".", len);
+               strlcat(buf, digit, len);
+       }
+       if (oid->include) {
+               strlcat(buf, "incl", len);
+               snprintf(digit, sizeof(digit), "(%d)", oid->include);
+               strlcat(buf, digit, len);
+       }
+       return buf;
+}