summaryrefslogtreecommitdiff
path: root/regress
diff options
context:
space:
mode:
authorMartijn van Duren <martijn@cvs.openbsd.org>2023-11-20 10:34:22 +0000
committerMartijn van Duren <martijn@cvs.openbsd.org>2023-11-20 10:34:22 +0000
commite689bf794c4c1407f574721c69c26e47a07211ce (patch)
treef55c742b6eb7c5e4568f3266815fc5dd24d2acd9 /regress
parentf38f180651b835135458eb9beee8a09b9e3cb926 (diff)
Add a couple of tests for handling of tcp connections.
Diffstat (limited to 'regress')
-rw-r--r--regress/usr.sbin/snmpd/Makefile12
-rw-r--r--regress/usr.sbin/snmpd/regress.h21
-rw-r--r--regress/usr.sbin/snmpd/snmp.c39
-rw-r--r--regress/usr.sbin/snmpd/snmpd_regress.c5
-rw-r--r--regress/usr.sbin/snmpd/transport.c150
5 files changed, 205 insertions, 22 deletions
diff --git a/regress/usr.sbin/snmpd/Makefile b/regress/usr.sbin/snmpd/Makefile
index 9f3403736b8..63b0fc01711 100644
--- a/regress/usr.sbin/snmpd/Makefile
+++ b/regress/usr.sbin/snmpd/Makefile
@@ -1,8 +1,9 @@
-# $OpenBSD: Makefile,v 1.11 2023/11/16 13:26:45 martijn Exp $
+# $OpenBSD: Makefile,v 1.12 2023/11/20 10:34:21 martijn Exp $
# Regress tests for snmpd
PROG = snmpd_regress
SRCS = snmpd_regress.c agentx.c backend.c snmp.c
+SRCS+= transport.c
LDADD= -lutil
DPADD= ${LIBUTIL}
@@ -249,7 +250,14 @@ SNMP_TARGETS+= snmp_v3_usm_noauthpriv
REGRESS_TARGETS+= ${SNMP_TARGETS}
snmp: ${SNMP_TARGETS}
-.PHONY: agentx backend
+TRANSPORT_TARGETS+= transport_tcp_get
+TRANSPORT_TARGETS+= transport_tcp_disconnect
+TRANSPORT_TARGETS+= transport_tcp_double_get_disconnect
+
+REGRESS_TARGETS+= ${TRANSPORT_TARGETS}
+transport: ${TRANSPORT_TARGETS}
+
+.PHONY: agentx backend snmp transport
${REGRESS_TARGETS}: snmpd_regress
# Always start snmpd if it's not running
diff --git a/regress/usr.sbin/snmpd/regress.h b/regress/usr.sbin/snmpd/regress.h
index cd05eb51bf2..b63a58723d3 100644
--- a/regress/usr.sbin/snmpd/regress.h
+++ b/regress/usr.sbin/snmpd/regress.h
@@ -98,6 +98,19 @@ struct varbind {
} data;
};
+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
+};
+
+
extern int verbose;
extern char *axsocket;
extern char *hostname;
@@ -128,11 +141,13 @@ char *oid_print(struct oid *, char *, size_t);
#define MIB_SUBAGENT_UNREGISTER MIB_SUBAGENTS, 4
#define MIB_SUBAGENT_BACKEND MIB_SUBAGENTS, 5
#define MIB_SUBAGENT_SNMP MIB_SUBAGENTS, 6
+#define MIB_SUBAGENT_TRANSPORT MIB_SUBAGENTS, 7
/* 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 MIB_SNMP MIB_OPENBSD_REGRESS, 5
+#define MIB_TRANSPORT MIB_OPENBSD_REGRESS, 6
#define SYSORTABLE 1, 3, 6, 1, 2, 1, 1, 9
@@ -234,9 +249,12 @@ 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);
+struct ber_element *snmpv2_build(const char *, enum snmp_request, 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 smi_debug_elements(struct ber_element *);
void backend_get_integer(void);
void backend_get_octetstring(void);
@@ -370,3 +388,6 @@ void backend_error_getnext_nonstandard(void);
void backend_error_getbulk_firstrepetition(void);
void backend_error_getbulk_secondrepetition(void);
void snmp_v3_usm_noauthpriv(void);
+void transport_tcp_get(void);
+void transport_tcp_disconnect(void);
+void transport_tcp_double_get_disconnect(void);
diff --git a/regress/usr.sbin/snmpd/snmp.c b/regress/usr.sbin/snmpd/snmp.c
index 333909531f8..d2e105edff0 100644
--- a/regress/usr.sbin/snmpd/snmp.c
+++ b/regress/usr.sbin/snmpd/snmp.c
@@ -54,18 +54,6 @@ enum snmp_exception {
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
-};
-
enum security_model {
SM_USM = 3,
SM_TSM = 4
@@ -127,7 +115,6 @@ 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);
@@ -243,6 +230,23 @@ snmpv2_getbulk(int s, const char *community, int32_t requestid, int32_t nonrep,
maxrep, varbindlist, nvarbind);
}
+struct ber_element *
+snmpv2_build(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;
+
+ if (community == NULL)
+ community = SNMP_R_COMMUNITY;
+ message = ober_printf_elements(NULL, "{dse}", 1, community,
+ snmp_pdu(request, requestid, error, index, varbindlist, nvarbind));
+ if (message == NULL)
+ err(1, NULL);
+
+ return message;
+}
+
int32_t
snmpv2_send(int s, const char *community, enum snmp_request request,
int32_t requestid, int32_t error, int32_t index,
@@ -253,14 +257,11 @@ snmpv2_send(int s, const char *community, enum snmp_request request,
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);
+
+ message = snmpv2_build(community, request, requestid, error, index,
+ varbindlist,nvarbind);
if (ober_write_elements(&ber, message) == -1)
err(1, "ober_write_elements");
diff --git a/regress/usr.sbin/snmpd/snmpd_regress.c b/regress/usr.sbin/snmpd/snmpd_regress.c
index 36714ce3708..044f843e491 100644
--- a/regress/usr.sbin/snmpd/snmpd_regress.c
+++ b/regress/usr.sbin/snmpd/snmpd_regress.c
@@ -213,7 +213,10 @@ const struct {
{ "backend_error_getnext_nonstandard", backend_error_getnext_nonstandard },
{ "backend_error_getbulk_firstrepetition", backend_error_getbulk_firstrepetition },
{ "backend_error_getbulk_secondrepetition", backend_error_getbulk_secondrepetition },
- { "snmp_v3_usm_noauthpriv", snmp_v3_usm_noauthpriv},
+ { "snmp_v3_usm_noauthpriv", snmp_v3_usm_noauthpriv },
+ { "transport_tcp_get", transport_tcp_get },
+ { "transport_tcp_disconnect", transport_tcp_disconnect },
+ { "transport_tcp_double_get_disconnect", transport_tcp_double_get_disconnect },
{ NULL, NULL }
};
diff --git a/regress/usr.sbin/snmpd/transport.c b/regress/usr.sbin/snmpd/transport.c
new file mode 100644
index 00000000000..cfda5ba4fd3
--- /dev/null
+++ b/regress/usr.sbin/snmpd/transport.c
@@ -0,0 +1,150 @@
+#include <sys/socket.h>
+
+#include <ber.h>
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "regress.h"
+
+#define MIB_SUBAGENT_TRANSPORT_TCP MIB_SUBAGENT_TRANSPORT, 1
+#define MIB_TRANSPORT_TCP MIB_TRANSPORT, 1
+
+void
+transport_tcp_get(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_TRANSPORT_TCP, 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_TRANSPORT_TCP, 1), __func__);
+ agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+ OID_ARG(MIB_TRANSPORT_TCP, 1), 0);
+
+ salen = snmp_resolve(SOCK_STREAM, hostname, servname, sa);
+ snmp_s = snmp_connect(SOCK_STREAM, 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
+transport_tcp_disconnect(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_TRANSPORT_TCP, 2, 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_TRANSPORT_TCP, 2), __func__);
+ agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+ OID_ARG(MIB_TRANSPORT_TCP, 2), 0);
+
+ salen = snmp_resolve(SOCK_STREAM, hostname, servname, sa);
+ snmp_s = snmp_connect(SOCK_STREAM, sa, salen);
+ requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1);
+
+ close(snmp_s);
+
+ 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);
+}
+
+void
+transport_tcp_double_get_disconnect(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_TRANSPORT_TCP, 2, 0),
+ .data.int32 = 1
+ };
+ struct ber_element *message;
+ struct ber ber = {};
+ char buf[1024];
+ ssize_t buflen, writelen;
+ void *ptr;
+ size_t n;
+
+ ax_s = agentx_connect(axsocket);
+ sessionid = agentx_open(ax_s, 0, 0,
+ OID_ARG(MIB_SUBAGENT_TRANSPORT_TCP, 2), __func__);
+ agentx_register(ax_s, sessionid, 0, 0, 127, 0,
+ OID_ARG(MIB_TRANSPORT_TCP, 2), 0);
+
+ salen = snmp_resolve(SOCK_STREAM, hostname, servname, sa);
+ snmp_s = snmp_connect(SOCK_STREAM, sa, salen);
+
+ message = snmpv2_build(community, REQUEST_GET, 0, 0, 0, &varbind, 1);
+
+ if (ober_write_elements(&ber, message) == -1)
+ err(1, "ober_write_elements");
+
+ buflen = ober_get_writebuf(&ber, &ptr);
+ /* send two copies in a single window */
+ memcpy(buf, ptr, buflen);
+ memcpy(buf + buflen, ptr, buflen);
+
+ if ((writelen = write(snmp_s, buf, buflen * 2)) == -1)
+ err(1, "write");
+ if (writelen != buflen * 2)
+ errx(1, "write: short write");
+
+ if (verbose) {
+ printf("SNMP send(%d):\n", snmp_s);
+ smi_debug_elements(message);
+ }
+ ober_free_elements(message);
+ ober_free(&ber);
+
+ close(snmp_s);
+
+ 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);
+
+ n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+ agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1);
+ agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1);
+}