diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2008-01-16 19:36:07 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2008-01-16 19:36:07 +0000 |
commit | 30a6a57434dccbe1344c874f0241339612913209 (patch) | |
tree | 0be5644d3f6a32ee5a930aba2b1f7981d1bccbb0 /usr.sbin/snmpd/trap.c | |
parent | 2c9cd77dfb76942480fde4b9025e1691b097919a (diff) |
implementation of the SNMP trap sender interface
Diffstat (limited to 'usr.sbin/snmpd/trap.c')
-rw-r--r-- | usr.sbin/snmpd/trap.c | 99 |
1 files changed, 80 insertions, 19 deletions
diff --git a/usr.sbin/snmpd/trap.c b/usr.sbin/snmpd/trap.c index 4ea84b9d282..513ad313c1f 100644 --- a/usr.sbin/snmpd/trap.c +++ b/usr.sbin/snmpd/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.2 2008/01/16 09:45:17 reyk Exp $ */ +/* $OpenBSD: trap.c,v 1.3 2008/01/16 19:36:06 reyk Exp $ */ /* * Copyright (c) 2008 Reyk Floeter <reyk@vantronix.net> @@ -38,22 +38,32 @@ #include <pwd.h> #include "snmpd.h" +#include "mib.h" + +extern struct snmpd *env; int -trap_request(struct imsgbuf *ibuf, pid_t pid) +trap_imsg(struct imsgbuf *ibuf, pid_t pid) { - struct imsg imsg; - int ret = -1, n, x = 0; - int done = 0; + 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_int32_t d; + u_int64_t l; u_int8_t *c; - char o[SNMP_MAX_OID_LEN]; + char ostr[SNMP_MAX_OID_LEN]; struct ber_element *ber, *trap = NULL, *oid = NULL, *a; size_t len; + struct ber_oid o; + struct ber_oid uptime = OID(MIB_sysUpTime); + struct ber_oid trapoid = OID(MIB_snmpTrapOID); - ber = trap = ber_add_sequence(NULL); + bzero(&o, sizeof(o)); + smi_oidlen(&uptime); + ber = trap = ber_printf_elements(NULL, "{{Oit}", + &uptime, smi_getticks(), + BER_CLASS_APPLICATION, SNMP_T_TIMETICKS); while (!done) { while (!done) { @@ -73,8 +83,10 @@ trap_request(struct imsgbuf *ibuf, pid_t pid) /* First element must be the trap OID */ if (sm->snmp_type != SNMP_NULL) goto imsgdone; + ber_string2oid(sm->snmp_oid, &o); + smi_oidlen(&trapoid); ber = oid = ber_printf_elements(ber, - "{o0}", sm->snmp_oid); + "{OO}", &trapoid, &o); break; } @@ -83,10 +95,10 @@ trap_request(struct imsgbuf *ibuf, pid_t pid) switch (sm->snmp_type) { case SNMP_OBJECT: - if (sm->snmp_len != sizeof(o)) + if (sm->snmp_len != sizeof(ostr)) goto imsgdone; - bcopy(sm + 1, &o, sm->snmp_len); - a = ber_add_oidstring(a, o); + bcopy(sm + 1, &ostr, sm->snmp_len); + a = ber_add_oidstring(a, ostr); break; case SNMP_BITSTRING: case SNMP_OCTETSTRING: @@ -167,13 +179,10 @@ trap_request(struct imsgbuf *ibuf, pid_t pid) } len = ber_calc_len(trap); - log_debug("snmpe_trap: %d bytes from pid %d", len, pid); - -#ifdef DEBUG - snmpe_debug_elements(trap); -#endif + smi_oidstring(&o, ostr, sizeof(ostr)); + log_debug("trap_imsg: %s, len %d, pid %d", ostr, len, pid); - /* XXX send trap to registered receivers */ + trap_send(trap, &o); ret = 0; imsgdone: @@ -183,3 +192,55 @@ trap_request(struct imsgbuf *ibuf, pid_t pid) ber_free_elements(trap); return (ret); } + +int +trap_send(struct ber_element *trap, struct ber_oid *oid) +{ + int ok = 0, s; + struct address *tr; + struct ber_element *root, *b; + struct ber ber; + char *c; + ssize_t len; + u_int8_t *ptr; + + if (TAILQ_EMPTY(&env->sc_trapreceivers)) + return (0); + + bzero(&ber, sizeof(ber)); + ber.fd = -1; + + TAILQ_FOREACH(tr, &env->sc_trapreceivers, entry) { + if (tr->sa_oid != NULL && tr->sa_oid->bo_n) + /* XXX only send if the OID is specified */; + + if ((s = snmpd_socket_af(&tr->ss, htons(tr->port))) == -1) + return (-1); + + c = tr->sa_community != NULL ? + tr->sa_community : env->sc_trcommunity; + + /* SNMP header */ + root = ber_add_sequence(NULL); + b = ber_printf_elements(root, "ds{tiii", + SNMP_V2, c, BER_CLASS_CONTEXT, SNMP_C_TRAPV2, + arc4random(), 0, 0); + ber_link_elements(b, trap); + +#ifdef DEBUG + snmpe_debug_elements(root); +#endif + + len = ber_write_elements(&ber, root); + if (ber_get_writebuf(&ber, (void *)&ptr) > 0 && + sendto(s, ptr, len, 0, (struct sockaddr *)&tr->ss, + tr->ss.ss_len) != -1) + env->sc_stats.snmp_outpkts++; + + close(s); + ber_unlink_elements(b); + ber_free_elements(root); + } + + return (ok); +} |