summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/snmpd/snmpd.h10
-rw-r--r--usr.sbin/snmpd/snmpe.c20
2 files changed, 28 insertions, 2 deletions
diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h
index c490ed2fd46..40f08748d4b 100644
--- a/usr.sbin/snmpd/snmpd.h
+++ b/usr.sbin/snmpd/snmpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmpd.h,v 1.93 2021/01/28 20:45:14 martijn Exp $ */
+/* $OpenBSD: snmpd.h,v 1.94 2021/02/05 10:30:45 martijn Exp $ */
/*
* Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org>
@@ -399,6 +399,8 @@ struct snmp_message {
u_int8_t sm_data[READ_BUF_SIZE];
size_t sm_datalen;
+ uint32_t sm_transactionid;
+
u_int sm_version;
/* V1, V2c */
@@ -436,7 +438,11 @@ struct snmp_message {
struct ber_element *sm_varbind;
struct ber_element *sm_varbindresp;
+
+ RB_ENTRY(snmp_message) sm_entry;
};
+RB_HEAD(snmp_messages, snmp_message);
+extern struct snmp_messages snmp_messages;
/* Defined in SNMPv2-MIB.txt (RFC 3418) */
struct snmp_stats {
@@ -642,6 +648,8 @@ struct kif_arp *karp_getaddr(struct sockaddr *, u_short, int);
void snmpe(struct privsep *, struct privsep_proc *);
void snmpe_shutdown(void);
void snmpe_dispatchmsg(struct snmp_message *);
+int snmp_messagecmp(struct snmp_message *, struct snmp_message *);
+RB_PROTOTYPE(snmp_messages, snmp_message, sm_entry, snmp_messagecmp)
/* trap.c */
void trap_init(void);
diff --git a/usr.sbin/snmpd/snmpe.c b/usr.sbin/snmpd/snmpe.c
index 4aea2d5c2b1..9d063206854 100644
--- a/usr.sbin/snmpd/snmpe.c
+++ b/usr.sbin/snmpd/snmpe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmpe.c,v 1.68 2021/01/22 06:33:27 martijn Exp $ */
+/* $OpenBSD: snmpe.c,v 1.69 2021/02/05 10:30:45 martijn Exp $ */
/*
* Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org>
@@ -58,6 +58,8 @@ void snmp_msgfree(struct snmp_message *);
struct imsgev *iev_parent;
static const struct timeval snmpe_tcp_timeout = { 10, 0 }; /* 10s */
+struct snmp_messages snmp_messages = RB_INITIALIZER(&snmp_messages);
+
static struct privsep_proc procs[] = {
{ "parent", PROC_PARENT }
};
@@ -210,6 +212,11 @@ snmpe_parse(struct snmp_message *msg)
msg->sm_errstr = "invalid message";
+ do {
+ msg->sm_transactionid = arc4random();
+ } while (msg->sm_transactionid == 0 ||
+ RB_INSERT(snmp_messages, &snmp_messages, msg) != NULL);
+
if (ober_scanf_elements(root, "{ie", &ver, &a) != 0)
goto parsefail;
@@ -834,6 +841,8 @@ snmpe_response(struct snmp_message *msg)
void
snmp_msgfree(struct snmp_message *msg)
{
+ if (msg->sm_transactionid != 0)
+ RB_REMOVE(snmp_messages, &snmp_messages, msg);
event_del(&msg->sm_sockev);
ober_free(&msg->sm_ber);
if (msg->sm_req != NULL)
@@ -896,3 +905,12 @@ snmpe_encode(struct snmp_message *msg)
#endif
return 0;
}
+
+int
+snmp_messagecmp(struct snmp_message *m1, struct snmp_message *m2)
+{
+ return (m1->sm_transactionid < m2->sm_transactionid ? -1 :
+ m1->sm_transactionid > m2->sm_transactionid);
+}
+
+RB_GENERATE(snmp_messages, snmp_message, sm_entry, snmp_messagecmp)