diff options
-rw-r--r-- | usr.sbin/snmpctl/parser.c | 215 | ||||
-rw-r--r-- | usr.sbin/snmpctl/parser.h | 10 | ||||
-rw-r--r-- | usr.sbin/snmpctl/snmpctl.8 | 51 | ||||
-rw-r--r-- | usr.sbin/snmpctl/snmpctl.c | 16 | ||||
-rw-r--r-- | usr.sbin/snmpd/imsg.c | 40 | ||||
-rw-r--r-- | usr.sbin/snmpd/snmpd.h | 4 | ||||
-rw-r--r-- | usr.sbin/snmpd/trap.c | 2 |
7 files changed, 312 insertions, 26 deletions
diff --git a/usr.sbin/snmpctl/parser.c b/usr.sbin/snmpctl/parser.c index 60175a81079..f03983bb701 100644 --- a/usr.sbin/snmpctl/parser.c +++ b/usr.sbin/snmpctl/parser.c @@ -1,6 +1,7 @@ -/* $OpenBSD: parser.c,v 1.3 2007/12/28 17:22:32 reyk Exp $ */ +/* $OpenBSD: parser.c,v 1.4 2008/01/18 02:09:30 reyk Exp $ */ /* + * Copyright (c) 2008 Reyk Floeter <reyk@vantronix.net> * Copyright (c) 2004 Esben Norby <norby@openbsd.org> * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> * @@ -21,6 +22,7 @@ #include <sys/socket.h> #include <sys/queue.h> #include <sys/tree.h> +#include <sys/uio.h> #include <netinet/in.h> #include <net/if.h> @@ -31,16 +33,25 @@ #include <limits.h> #include <stdio.h> #include <stdlib.h> +#include <stdint.h> #include <string.h> #include <event.h> #include "snmpd.h" +#include "snmp.h" #include "parser.h" enum token_type { NOTOKEN, ENDTOKEN, - KEYWORD + KEYWORD, + TRAPOID, + ELEMENTOBJECT, + VALTYPE, + INT32VAL, + UINT32VAL, + INT64VAL, + STRINGVAL }; struct token { @@ -52,19 +63,93 @@ struct token { static const struct token t_main[]; static const struct token t_show[]; +static const struct token t_trap[]; +static const struct token t_trapoid[]; +static const struct token t_element[]; +static const struct token t_oid[]; +static const struct token t_type[]; +static const struct token t_int32[]; +static const struct token t_uint32[]; +static const struct token t_int64[]; +static const struct token t_string[]; static const struct token t_main[] = { {KEYWORD, "monitor", MONITOR, NULL}, {KEYWORD, "show", NONE, t_show}, + {KEYWORD, "trap", NONE, t_trap}, {ENDTOKEN, "", NONE, NULL} }; static const struct token t_show[] = { - {KEYWORD, "mib" , SHOW_MIB, NULL}, + {KEYWORD, "mib", SHOW_MIB, NULL}, {ENDTOKEN, "", NONE, NULL} }; -static struct parse_result res; +static const struct token t_trap[] = { + {KEYWORD, "send", TRAP, t_trapoid}, + {ENDTOKEN, "", NONE, NULL} +}; + +static const struct token t_trapoid[] = { + {TRAPOID, "", NONE, t_element}, + {ENDTOKEN, "", NONE, NULL} +}; + +static const struct token t_element[] = { + {NOTOKEN, "", NONE, NULL}, + {KEYWORD, "oid", NONE, t_oid}, + {ENDTOKEN, "", NONE, NULL} +}; + +static const struct token t_oid[] = { + {ELEMENTOBJECT, "", NONE, t_type}, + {ENDTOKEN, "", NONE, NULL} +}; + +static const struct token t_type[] = { + {VALTYPE, "ip", SNMP_IPADDR, t_int32 }, + {VALTYPE, "counter", SNMP_COUNTER32, t_int32 }, + {VALTYPE, "gauge", SNMP_GAUGE32, t_int32 }, + {VALTYPE, "unsigned", SNMP_GAUGE32, t_uint32 }, + {VALTYPE, "ticks", SNMP_TIMETICKS, t_int32 }, + {VALTYPE, "opaque", SNMP_OPAQUE, t_int32 }, + {VALTYPE, "nsap", SNMP_NSAPADDR, t_int32 }, + {VALTYPE, "counter64", SNMP_COUNTER64, t_int64 }, + {VALTYPE, "uint", SNMP_UINTEGER32, t_uint32 }, + {VALTYPE, "int", SNMP_INTEGER32, t_int32 }, + {VALTYPE, "bitstring", SNMP_BITSTRING, t_string }, + {VALTYPE, "string", SNMP_OCTETSTRING, t_string }, + {VALTYPE, "null", SNMP_NULL, t_element }, + {VALTYPE, "oid", SNMP_OBJECT, t_string }, + {ENDTOKEN, "", NONE, NULL} +}; + +static const struct token t_int32[] = { + {INT32VAL, "", NONE, t_element}, + {ENDTOKEN, "", NONE, NULL} +}; + +static const struct token t_uint32[] = { + {UINT32VAL, "", NONE, t_element}, + {ENDTOKEN, "", NONE, NULL} +}; + +static const struct token t_int64[] = { + {INT64VAL, "", NONE, t_element}, + {ENDTOKEN, "", NONE, NULL} +}; + +static const struct token t_string[] = { + {STRINGVAL, "", NONE, t_element}, + {ENDTOKEN, "", NONE, NULL} +}; + +static struct parse_result res; +static struct imsgbuf *ibuf; +static struct snmp_imsg sm; + +const struct token *match_token(char *, const struct token []); +void show_valid_args(const struct token []); struct parse_result * parse(int argc, char *argv[]) @@ -99,12 +184,18 @@ parse(int argc, char *argv[]) } const struct token * -match_token(const char *word, const struct token table[]) +match_token(char *word, const struct token table[]) { - u_int i, match; + u_int i, match = 0; const struct token *t = NULL; + const char *errs = NULL; + u_int32_t u; + int32_t d; + int64_t l; + struct iovec iov[2]; + int iovcnt = 0; - match = 0; + bzero(&iov, sizeof(iov)); for (i = 0; table[i].type != ENDTOKEN; i++) { switch (table[i].type) { @@ -123,12 +214,101 @@ match_token(const char *word, const struct token table[]) res.action = t->value; } break; + case VALTYPE: + if (word != NULL && strncmp(word, table[i].keyword, + strlen(word)) == 0) { + match++; + t = &table[i]; + sm.snmp_type = t->value; + if (t->value == SNMP_NULL) + iovcnt = 1; + } + break; + case TRAPOID: + if (word == NULL || strlen(word) == 0) + break; + if (ibuf == NULL && + (ibuf = malloc(sizeof(struct imsgbuf))) == NULL) + err(1, "malloc"); + res.ibuf = ibuf; + imsg_init(ibuf, -1, NULL); + + /* Create a new trap */ + imsg_compose(ibuf, IMSG_SNMP_TRAP, + 0, 0, -1, NULL, 0); + + /* First element must be the trap OID. */ + bzero(&sm, sizeof(sm)); + sm.snmp_type = SNMP_NULL; + if (strlcpy(sm.snmp_oid, word, + sizeof(sm.snmp_oid)) >= sizeof(sm.snmp_oid)) + errx(1, "trap oid too long"); + if (imsg_compose(ibuf, IMSG_SNMP_ELEMENT, 0, 0, -1, + &sm, sizeof(sm)) == -1) + errx(1, "imsg"); + + match++; + t = &table[i]; + break; + case ELEMENTOBJECT: + if (word == NULL || strlen(word) == 0) + break; + bzero(&sm, sizeof(sm)); + if (strlcpy(sm.snmp_oid, word, + sizeof(sm.snmp_oid)) >= sizeof(sm.snmp_oid)) + errx(1, "oid too long"); + match++; + t = &table[i]; + break; + case INT32VAL: + if (word == NULL || strlen(word) == 0) + break; + d = strtonum(word, INT_MIN, INT_MAX, &errs); + iov[1].iov_len = sizeof(d); + iov[1].iov_base = &d; + iovcnt = 2; + break; + case UINT32VAL: + if (word == NULL || strlen(word) == 0) + break; + u = strtonum(word, 0, UINT_MAX, &errs); + iov[1].iov_len = sizeof(u); + iov[1].iov_base = &u; + iovcnt = 2; + break; + case INT64VAL: + if (word == NULL || strlen(word) == 0) + break; + l = strtonum(word, INT64_MIN, INT64_MAX, &errs); + iov[1].iov_len = sizeof(l); + iov[1].iov_base = &l; + iovcnt = 2; + break; + case STRINGVAL: + if (word == NULL || strlen(word) == 0) + break; + iov[1].iov_len = strlen(word) + 1; + iov[1].iov_base = word; + iovcnt = 2; + break; case ENDTOKEN: break; } + if (iovcnt) + break; } - if (match != 1) { + if (iovcnt) { + /* Write trap varbind element */ + sm.snmp_len = iov[1].iov_len; + iov[0].iov_len = sizeof(sm); + iov[0].iov_base = &sm; + if (imsg_composev(ibuf, IMSG_SNMP_ELEMENT, 0, 0, -1, + iov, iovcnt) == -1) + err(1, "imsg"); + + t = &table[i]; + } else if (match != 1) { if (word == NULL) fprintf(stderr, "missing argument:\n"); else if (match > 1) @@ -154,6 +334,25 @@ show_valid_args(const struct token table[]) case KEYWORD: fprintf(stderr, " %s\n", table[i].keyword); break; + case VALTYPE: + fprintf(stderr, " %s <value>\n", table[i].keyword); + break; + case TRAPOID: + case ELEMENTOBJECT: + fprintf(stderr, " <oid-string>\n"); + break; + case INT32VAL: + fprintf(stderr, " <int32>\n"); + break; + case UINT32VAL: + fprintf(stderr, " <uint32>\n"); + break; + case INT64VAL: + fprintf(stderr, " <int64>\n"); + break; + case STRINGVAL: + fprintf(stderr, " <string>\n"); + break; case ENDTOKEN: break; } diff --git a/usr.sbin/snmpctl/parser.h b/usr.sbin/snmpctl/parser.h index 5fe1833d67d..2eb0154a72d 100644 --- a/usr.sbin/snmpctl/parser.h +++ b/usr.sbin/snmpctl/parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.h,v 1.3 2008/01/16 09:51:15 reyk Exp $ */ +/* $OpenBSD: parser.h,v 1.4 2008/01/18 02:09:30 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter <reyk@vantronix.net> @@ -19,13 +19,13 @@ enum actions { NONE, MONITOR, - SHOW_MIB + SHOW_MIB, + TRAP }; struct parse_result { - enum actions action; + enum actions action; + struct imsgbuf *ibuf; }; struct parse_result *parse(int, char *[]); -const struct token *match_token(const char *, const struct token []); -void show_valid_args(const struct token []); diff --git a/usr.sbin/snmpctl/snmpctl.8 b/usr.sbin/snmpctl/snmpctl.8 index c6dc25c4208..ecb22f7cf5a 100644 --- a/usr.sbin/snmpctl/snmpctl.8 +++ b/usr.sbin/snmpctl/snmpctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: snmpctl.8,v 1.4 2008/01/16 09:51:15 reyk Exp $ +.\" $OpenBSD: snmpctl.8,v 1.5 2008/01/18 02:09:30 reyk Exp $ .\" .\" Copyright (c) 2007, 2008 Reyk Floeter <reyk@vantronix.net> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 16 2008 $ +.Dd $Mdocdate: January 18 2008 $ .Dt SNMPCTL 8 .Os .Sh NAME @@ -46,6 +46,53 @@ Monitor internal messages of the subsystems and engines. .It Cm show mib Dump the tree of compiled-in MIB objects. +.It Xo +.Cm trap send Ar oid-string +.Op Cm oid Ar oid-string Ar type value ... Oc +.Xc +Send a SNMP trap via +.Xr snmpd 8 +to the registered trap receivers. +The command takes one +.Ar oid-string +argument as the trap OID and optional varbind arguments with the specified +.Ar oid-string , +.Ar type , +and +.Ar value . +The following types are supported: +.Pp +.Bl -tag -width bitstringXXXXXXXX -compact +.It Cm ip Ar value +An IPv4 address. +.It Cm counter Ar value +A 32 bit counter. +.It Cm gauge Ar value +A 32 bit gauge. +.It Cm unsigned Ar value +A 32 bit unsigned integer. +.It Cm ticks Ar value +A 32 bit timeticks integer value. +.It Cm opaque Ar value +A 32 bit opaque. +.It Cm nsap Ar value +A 32 bit NSAP address. +.It Cm counter64 Ar value +A 64 bit counter. +.It Cm uint Ar value +A 32 bit unsigned integer. +.It Cm int Ar value +A 32 bit integer. +.It Cm bitstring Ar string +A bit string. +.It Cm string Ar string +An octet string. +.It Cm null +This type takes no argument. +.It Cm oid Ar oid-string +An string describing a Object ID, for example +.Ar 1.3.6.1.4.1.30155 . +.El .El .Sh FILES .Bl -tag -width "/var/run/snmpd.sockXX" -compact diff --git a/usr.sbin/snmpctl/snmpctl.c b/usr.sbin/snmpctl/snmpctl.c index 58e0b1ef6c4..c52725f6112 100644 --- a/usr.sbin/snmpctl/snmpctl.c +++ b/usr.sbin/snmpctl/snmpctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpctl.c,v 1.6 2008/01/16 09:51:15 reyk Exp $ */ +/* $OpenBSD: snmpctl.c,v 1.7 2008/01/18 02:09:30 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter <reyk@vantronix.net> @@ -40,6 +40,7 @@ #include <event.h> #include "snmpd.h" +#include "snmp.h" #include "parser.h" #include "mib.h" @@ -151,8 +152,11 @@ main(int argc, char *argv[]) err(1, "connect: %s", SNMPD_SOCKET); } - if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) - err(1, "malloc"); + if (res->ibuf != NULL) + ibuf = res->ibuf; + else + if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) + err(1, "malloc"); imsg_init(ibuf, ctl_sock, NULL); done = 0; @@ -164,6 +168,10 @@ main(int argc, char *argv[]) case NONE: case SHOW_MIB: break; + case TRAP: + imsg_compose(ibuf, IMSG_SNMP_END, 0, 0, -1, NULL, 0); + done = 1; + break; } while (ibuf->w.queued) @@ -185,6 +193,8 @@ main(int argc, char *argv[]) case MONITOR: done = monitor(&imsg); break; + case TRAP: + break; case NONE: case SHOW_MIB: break; diff --git a/usr.sbin/snmpd/imsg.c b/usr.sbin/snmpd/imsg.c index 83bb7262568..708154602df 100644 --- a/usr.sbin/snmpd/imsg.c +++ b/usr.sbin/snmpd/imsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.c,v 1.1 2007/12/05 09:22:44 reyk Exp $ */ +/* $OpenBSD: imsg.c,v 1.2 2008/01/18 02:09:30 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -36,13 +36,15 @@ void imsg_init(struct imsgbuf *ibuf, int fd, void (*handler)(int, short, void *)) { - msgbuf_init(&ibuf->w); - bzero(&ibuf->r, sizeof(ibuf->r)); + if (!ibuf->pid) { + msgbuf_init(&ibuf->w); + bzero(&ibuf->r, sizeof(ibuf->r)); + ibuf->pid = getpid(); + ibuf->handler = handler; + TAILQ_INIT(&ibuf->fds); + } ibuf->fd = fd; ibuf->w.fd = fd; - ibuf->pid = getpid(); - ibuf->handler = handler; - TAILQ_INIT(&ibuf->fds); } ssize_t @@ -150,6 +152,32 @@ imsg_compose(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, return (n); } +int +imsg_composev(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, + pid_t pid, int fd, const struct iovec *iov, int iovcnt) +{ + struct buf *wbuf; + int n; + int i, datalen = 0; + + for (i = 0; i < iovcnt; i++) + datalen += iov[i].iov_len; + + if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) + return (-1); + + for (i = 0; i < iovcnt; i++) + if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1) + return (-1); + + wbuf->fd = fd; + + if ((n = imsg_close(ibuf, wbuf)) < 0) + return (-1); + + return (n); +} + /* ARGSUSED */ struct buf * imsg_create(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h index a8aee636262..89128558637 100644 --- a/usr.sbin/snmpd/snmpd.h +++ b/usr.sbin/snmpd/snmpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.h,v 1.16 2008/01/17 17:35:06 reyk Exp $ */ +/* $OpenBSD: snmpd.h,v 1.17 2008/01/18 02:09:30 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter <reyk@vantronix.net> @@ -371,6 +371,8 @@ ssize_t imsg_read(struct imsgbuf *); ssize_t imsg_get(struct imsgbuf *, struct imsg *); int imsg_compose(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t, int, void *, u_int16_t); +int imsg_composev(struct imsgbuf *, enum imsg_type , u_int32_t, + pid_t, int, const struct iovec *, int); struct buf *imsg_create(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t, u_int16_t); int imsg_add(struct buf *, void *, u_int16_t); diff --git a/usr.sbin/snmpd/trap.c b/usr.sbin/snmpd/trap.c index e7a7a83f7f0..4c61dbf4e19 100644 --- a/usr.sbin/snmpd/trap.c +++ b/usr.sbin/snmpd/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.7 2008/01/17 23:36:26 reyk Exp $ */ +/* $OpenBSD: trap.c,v 1.8 2008/01/18 02:09:30 reyk Exp $ */ /* * Copyright (c) 2008 Reyk Floeter <reyk@vantronix.net> |