summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/snmpctl/parser.c215
-rw-r--r--usr.sbin/snmpctl/parser.h10
-rw-r--r--usr.sbin/snmpctl/snmpctl.851
-rw-r--r--usr.sbin/snmpctl/snmpctl.c16
-rw-r--r--usr.sbin/snmpd/imsg.c40
-rw-r--r--usr.sbin/snmpd/snmpd.h4
-rw-r--r--usr.sbin/snmpd/trap.c2
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>