summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2008-01-16 09:36:31 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2008-01-16 09:36:31 +0000
commit031fa3c3eee7859e08bdb17182579db193dfa644 (patch)
treeda5632fb4421d1fca08ab173b8f2e1f5abaad0a5
parenta25938ad144a024f282fec3159fc8af9f5d79263 (diff)
start working on an interface to send traps via snmpd.sock. userland
applications will be able to send imsgs defining the trap to snmpd and the daemon will do the ASN.1/BER encoding before sending traps to the registered receivers. there are two advantages of this approach that a) the applications do not need to handle any ASN.1/BER encoding and b) snmpd will provide a central interface to define trap receivers. discussed with thib and others
-rw-r--r--usr.sbin/snmpd/control.c12
-rw-r--r--usr.sbin/snmpd/snmp.h52
-rw-r--r--usr.sbin/snmpd/snmpd.h3
-rw-r--r--usr.sbin/snmpd/snmpe.c154
4 files changed, 217 insertions, 4 deletions
diff --git a/usr.sbin/snmpd/control.c b/usr.sbin/snmpd/control.c
index 24023e798c5..a048f652fa5 100644
--- a/usr.sbin/snmpd/control.c
+++ b/usr.sbin/snmpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.1 2007/12/05 09:22:44 reyk Exp $ */
+/* $OpenBSD: control.c,v 1.2 2008/01/16 09:36:30 reyk Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -230,6 +230,16 @@ control_dispatch_imsg(int fd, short event, void *arg)
}
c->flags |= CTL_CONN_NOTIFY;
break;
+ case IMSG_SNMP_TRAP:
+ if (snmpe_trap(&c->ibuf, imsg.hdr.pid) == -1) {
+ log_debug("control_dispatch_imsg: "
+ "received invalid trap (pid %d)",
+ imsg.hdr.pid);
+ imsg_free(&imsg);
+ control_close(fd);
+ return;
+ }
+ break;
default:
log_debug("control_dispatch_imsg: "
"error handling imsg %d", imsg.hdr.type);
diff --git a/usr.sbin/snmpd/snmp.h b/usr.sbin/snmpd/snmp.h
index 0ba2d24d287..7d67cb44252 100644
--- a/usr.sbin/snmpd/snmp.h
+++ b/usr.sbin/snmpd/snmp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmp.h,v 1.2 2008/01/11 12:12:14 reyk Exp $ */
+/* $OpenBSD: snmp.h,v 1.3 2008/01/16 09:36:30 reyk Exp $ */
/*
* Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
@@ -19,6 +19,54 @@
#ifndef SNMP_HEADER
#define SNMP_HEADER
+/*
+ * SNMP IMSG interface
+ */
+
+#define SNMP_MAX_OID_LEN 128 /* max size of the OID _string_ */
+#define SNMP_SOCKET "/var/run/snmpd.sock"
+
+enum snmp_type {
+ SNMP_IPADDR = 0,
+ SNMP_COUNTER32 = 1,
+ SNMP_GAUGE32 = 2,
+ SNMP_UNSIGNED32 = 2,
+ SNMP_TIMETICKS = 3,
+ SNMP_OPAQUE = 4,
+ SNMP_NSAPADDR = 5,
+ SNMP_COUNTER64 = 6,
+ SNMP_UINTEGER32 = 7,
+
+ SNMP_INTEGER32 = 100,
+ SNMP_BITSTRING = 101,
+ SNMP_OCTETSTRING = 102,
+ SNMP_NULL = 103,
+ SNMP_OBJECT = 104
+};
+
+enum snmp_imsg_ctl {
+ IMSG_SNMP_TRAP = 1000, /* something that works everywhere */
+ IMSG_SNMP_ELEMENT,
+ IMSG_SNMP_END
+};
+
+struct snmp_imsg_hdr {
+ u_int16_t imsg_type;
+ u_int16_t imsg_len;
+ u_int32_t imsg_peerid;
+ pid_t imsg_pid;
+};
+
+struct snmp_imsg {
+ char snmp_oid[SNMP_MAX_OID_LEN];
+ u_int8_t snmp_type;
+ u_int16_t snmp_len;
+};
+
+/*
+ * SNMP BER types
+ */
+
enum snmp_version {
SNMP_V1 = 0,
SNMP_V2 = 1,
@@ -46,7 +94,9 @@ enum snmp_application {
SNMP_T_UNSIGNED32 = 2,
SNMP_T_TIMETICKS = 3,
SNMP_T_OPAQUE = 4,
+ SNMP_T_NSAPADDR = 5,
SNMP_T_COUNTER64 = 6,
+ SNMP_T_UINTEGER32 = 7
};
enum snmp_generic_trap {
diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h
index fc6418536b1..7499ea4231e 100644
--- a/usr.sbin/snmpd/snmpd.h
+++ b/usr.sbin/snmpd/snmpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmpd.h,v 1.10 2008/01/03 15:03:47 reyk Exp $ */
+/* $OpenBSD: snmpd.h,v 1.11 2008/01/16 09:36:30 reyk Exp $ */
/*
* Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
@@ -387,6 +387,7 @@ struct kif_addr *kr_getnextaddr(struct in_addr *);
/* snmpe.c */
pid_t snmpe(struct snmpd *, int [2]);
+int snmpe_trap(struct imsgbuf *, pid_t);
/* mps.c */
struct ber_element *
diff --git a/usr.sbin/snmpd/snmpe.c b/usr.sbin/snmpd/snmpe.c
index 4db07333c10..44960a0abf7 100644
--- a/usr.sbin/snmpd/snmpe.c
+++ b/usr.sbin/snmpd/snmpe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmpe.c,v 1.10 2008/01/12 13:57:43 reyk Exp $ */
+/* $OpenBSD: snmpe.c,v 1.11 2008/01/16 09:36:30 reyk Exp $ */
/*
* Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
@@ -804,3 +804,155 @@ snmpe_recvmsg(int fd, short sig, void *arg)
if (resp != NULL)
ber_free_elements(resp);
}
+
+int
+snmpe_trap(struct imsgbuf *ibuf, pid_t pid)
+{
+ struct imsg imsg;
+ int ret = -1, n, x = 0;
+ int done = 0;
+ struct snmp_imsg *sm;
+ u_int32_t d;
+ u_int64_t l;
+ u_int8_t *c;
+ char o[SNMP_MAX_OID_LEN];
+ struct ber_element *ber, *trap = NULL, *oid = NULL, *a;
+ size_t len;
+
+ ber = trap = ber_add_sequence(NULL);
+
+ while (!done) {
+ while (!done) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ goto done;
+ if (n == 0)
+ break;
+ switch (imsg.hdr.type) {
+ case IMSG_SNMP_ELEMENT:
+ if (imsg.hdr.len < (IMSG_HEADER_SIZE +
+ sizeof(struct snmp_imsg)))
+ goto imsgdone;
+
+ sm = (struct snmp_imsg *)imsg.data;
+
+ if (oid == NULL) {
+ /* First element must be the trap OID */
+ if (sm->snmp_type != SNMP_NULL)
+ goto imsgdone;
+ ber = oid = ber_printf_elements(ber,
+ "{o0}", sm->snmp_oid);
+ break;
+ }
+
+ ber = a = ber_add_sequence(ber);
+ a = ber_add_oidstring(a, sm->snmp_oid);
+
+ switch (sm->snmp_type) {
+ case SNMP_OBJECT:
+ if (sm->snmp_len != sizeof(o))
+ goto imsgdone;
+ bcopy(sm + 1, &o, sm->snmp_len);
+ a = ber_add_oidstring(a, o);
+ break;
+ case SNMP_BITSTRING:
+ case SNMP_OCTETSTRING:
+ if ((sm->snmp_len < 1) ||
+ (sm->snmp_len >= SNMPD_MAXSTRLEN))
+ goto imsgdone;
+ if ((c =
+ calloc(1, sm->snmp_len)) == NULL)
+ goto imsgdone;
+ bcopy(sm + 1, c, sm->snmp_len);
+ if (sm->snmp_type == SNMP_BITSTRING)
+ a = ber_add_bitstring(a, c,
+ sm->snmp_len);
+ else
+ a = ber_add_nstring(a, c,
+ sm->snmp_len);
+ a->be_free = 1;
+ break;
+ case SNMP_NULL:
+ a = ber_add_null(a);
+ break;
+ case SNMP_INTEGER32:
+ case SNMP_IPADDR:
+ case SNMP_COUNTER32:
+ case SNMP_GAUGE32:
+ case SNMP_TIMETICKS:
+ case SNMP_OPAQUE:
+ case SNMP_UINTEGER32:
+ if (sm->snmp_len != sizeof(d))
+ goto imsgdone;
+ bcopy(sm + 1, &d, sm->snmp_len);
+ a = ber_add_integer(a, d);
+ break;
+ case SNMP_COUNTER64:
+ if (sm->snmp_len != sizeof(l))
+ goto imsgdone;
+ bcopy(sm + 1, &l, sm->snmp_len);
+ a = ber_add_integer(a, d);
+ break;
+ default:
+ log_debug("snmpe_trap: illegal type %d",
+ sm->snmp_type);
+ imsg_free(&imsg);
+ goto imsgdone;
+ }
+ switch (sm->snmp_type) {
+ case SNMP_INTEGER32:
+ case SNMP_BITSTRING:
+ case SNMP_OCTETSTRING:
+ case SNMP_NULL:
+ case SNMP_OBJECT:
+ /* universal types */
+ break;
+ case SNMP_IPADDR:
+ case SNMP_COUNTER32:
+ case SNMP_GAUGE32:
+ case SNMP_TIMETICKS:
+ case SNMP_OPAQUE:
+ case SNMP_NSAPADDR:
+ case SNMP_COUNTER64:
+ case SNMP_UINTEGER32:
+ /* application-specific types */
+ ber_set_header(a, BER_CLASS_APPLICATION,
+ sm->snmp_type);
+ break;
+ }
+ x++;
+ break;
+ case IMSG_SNMP_END:
+ done = 1;
+ break;
+ default:
+ log_debug("snmpe_trap: illegal imsg %d",
+ imsg.hdr.type);
+ goto imsgdone;
+ }
+ imsg_free(&imsg);
+ }
+ if (done)
+ break;
+ if ((n = imsg_read(ibuf)) == -1)
+ goto done;
+ if (n == 0)
+ goto done;
+ }
+
+ len = ber_calc_len(trap);
+ log_debug("snmpe_trap: %d bytes from pid %d", len, pid);
+
+ /* XXX send trap to registered receivers */
+
+#ifdef DEBUG
+ snmpe_debug_elements(trap);
+#endif
+
+ ret = 0;
+ imsgdone:
+ if (ret != 0)
+ imsg_free(&imsg);
+ done:
+ ber_free_elements(trap);
+ return (ret);
+}