summaryrefslogtreecommitdiff
path: root/usr.sbin/snmpctl
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2007-12-05 09:22:45 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2007-12-05 09:22:45 +0000
commit174402352855c05a4a262f9afbbd6de1dd3ed82c (patch)
tree66e421d1b6a3d063f3d25c178aef3a600d370fc1 /usr.sbin/snmpctl
parent67c2cb68245a11d91e5fe144633f5f970f775656 (diff)
Start working on snmpd(8) and snmpctl(8), a lightweight SNMP implementation
for OpenBSD. SNMP is a necessary evil. This is work in progress, don't expect too much from it yet. ok deraadt@
Diffstat (limited to 'usr.sbin/snmpctl')
-rw-r--r--usr.sbin/snmpctl/Makefile16
-rw-r--r--usr.sbin/snmpctl/parser.c155
-rw-r--r--usr.sbin/snmpctl/parser.h30
-rw-r--r--usr.sbin/snmpctl/snmpctl.856
-rw-r--r--usr.sbin/snmpctl/snmpctl.c191
5 files changed, 448 insertions, 0 deletions
diff --git a/usr.sbin/snmpctl/Makefile b/usr.sbin/snmpctl/Makefile
new file mode 100644
index 00000000000..dedb04dd6e7
--- /dev/null
+++ b/usr.sbin/snmpctl/Makefile
@@ -0,0 +1,16 @@
+# $Id: Makefile,v 1.1 2007/12/05 09:22:44 reyk Exp $
+
+.PATH: ${.CURDIR}/../snmpd
+
+PROG= snmpctl
+SRCS= buffer.c imsg.c log.c snmpctl.c parser.c
+
+MAN= snmpctl.8
+
+CFLAGS+= -Wall -I${.CURDIR} -I${.CURDIR}/../snmpd
+CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS+= -Wmissing-declarations
+CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
+CFLAGS+= -Wsign-compare -Wbounded
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/snmpctl/parser.c b/usr.sbin/snmpctl/parser.c
new file mode 100644
index 00000000000..1f9c0140c6e
--- /dev/null
+++ b/usr.sbin/snmpctl/parser.c
@@ -0,0 +1,155 @@
+/* $Id: parser.c,v 1.1 2007/12/05 09:22:44 reyk Exp $ */
+
+/*
+ * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <event.h>
+
+#include "snmpd.h"
+#include "parser.h"
+
+enum token_type {
+ NOTOKEN,
+ ENDTOKEN,
+ KEYWORD
+};
+
+struct token {
+ enum token_type type;
+ const char *keyword;
+ int value;
+ const struct token *next;
+};
+
+static const struct token t_main[];
+static const struct token t_show[];
+
+static const struct token t_main[] = {
+ {KEYWORD, "monitor", MONITOR, NULL},
+ {ENDTOKEN, "", NONE, NULL}
+};
+
+static struct parse_result res;
+
+struct parse_result *
+parse(int argc, char *argv[])
+{
+ const struct token *table = t_main;
+ const struct token *match;
+
+ bzero(&res, sizeof(res));
+
+ while (argc >= 0) {
+ if ((match = match_token(argv[0], table)) == NULL) {
+ fprintf(stderr, "valid commands/args:\n");
+ show_valid_args(table);
+ return (NULL);
+ }
+
+ argc--;
+ argv++;
+
+ if (match->type == NOTOKEN || match->next == NULL)
+ break;
+
+ table = match->next;
+ }
+
+ if (argc > 0) {
+ fprintf(stderr, "superfluous argument: %s\n", argv[0]);
+ return (NULL);
+ }
+
+ return (&res);
+}
+
+const struct token *
+match_token(const char *word, const struct token table[])
+{
+ u_int i, match;
+ const struct token *t = NULL;
+
+ match = 0;
+
+ for (i = 0; table[i].type != ENDTOKEN; i++) {
+ switch (table[i].type) {
+ case NOTOKEN:
+ if (word == NULL || strlen(word) == 0) {
+ match++;
+ t = &table[i];
+ }
+ break;
+ case KEYWORD:
+ if (word != NULL && strncmp(word, table[i].keyword,
+ strlen(word)) == 0) {
+ match++;
+ t = &table[i];
+ if (t->value)
+ res.action = t->value;
+ }
+ break;
+ case ENDTOKEN:
+ break;
+ }
+ }
+
+ if (match != 1) {
+ if (word == NULL)
+ fprintf(stderr, "missing argument:\n");
+ else if (match > 1)
+ fprintf(stderr, "ambiguous argument: %s\n", word);
+ else if (match < 1)
+ fprintf(stderr, "unknown argument: %s\n", word);
+ return (NULL);
+ }
+
+ return (t);
+}
+
+void
+show_valid_args(const struct token table[])
+{
+ int i;
+
+ for (i = 0; table[i].type != ENDTOKEN; i++) {
+ switch (table[i].type) {
+ case NOTOKEN:
+ fprintf(stderr, " <cr>\n");
+ break;
+ case KEYWORD:
+ fprintf(stderr, " %s\n", table[i].keyword);
+ break;
+ case ENDTOKEN:
+ break;
+ }
+ }
+}
diff --git a/usr.sbin/snmpctl/parser.h b/usr.sbin/snmpctl/parser.h
new file mode 100644
index 00000000000..41202685b9d
--- /dev/null
+++ b/usr.sbin/snmpctl/parser.h
@@ -0,0 +1,30 @@
+/* $OpenBSD: parser.h,v 1.1 2007/12/05 09:22:44 reyk Exp $ */
+
+/*
+ * Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+enum actions {
+ NONE,
+ MONITOR
+};
+
+struct parse_result {
+ enum actions action;
+};
+
+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
new file mode 100644
index 00000000000..c83747ffe1c
--- /dev/null
+++ b/usr.sbin/snmpctl/snmpctl.8
@@ -0,0 +1,56 @@
+.\" $OpenBSD: snmpctl.8,v 1.1 2007/12/05 09:22:44 reyk Exp $
+.\"
+.\" Copyright (c) 2006 Reyk Floeter <reyk@vantronix.net>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: December 5 2007 $
+.Dt SNMPCTL 8
+.Os
+.Sh NAME
+.Nm snmpctl
+.Nd control the SNMP daemon
+.Sh SYNOPSIS
+.Nm
+.Ar command
+.Op Ar arguments ...
+.Sh DESCRIPTION
+The
+.Nm
+program controls the
+.Xr snmpd 8
+daemon.
+.Pp
+The following commands are available:
+.Bl -tag -width Ds
+.It Cm something
+Do something
+.El
+.Sh FILES
+.Bl -tag -width "/var/run/snmpd.sockXX" -compact
+.It /var/run/snmpd.sock
+Unix-domain socket used for communication with
+.Xr snmpd 8 .
+.El
+.Sh SEE ALSO
+.Xr snmpd 8
+.Sh HISTORY
+The
+.Nm
+program first appeared in
+.Ox 4.3 .
+.Sh AUTHORS
+The
+.Nm
+program was written by
+.An Reyk Floeter Aq reyk@vantronix.net .
diff --git a/usr.sbin/snmpctl/snmpctl.c b/usr.sbin/snmpctl/snmpctl.c
new file mode 100644
index 00000000000..c625645223f
--- /dev/null
+++ b/usr.sbin/snmpctl/snmpctl.c
@@ -0,0 +1,191 @@
+/* $Id: snmpctl.c,v 1.1 2007/12/05 09:22:44 reyk Exp $ */
+
+/*
+ * Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
+ * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
+ * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
+ * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/un.h>
+#include <sys/tree.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <event.h>
+
+#include "snmpd.h"
+#include "parser.h"
+
+__dead void usage(void);
+
+struct imsgname {
+ int type;
+ char *name;
+ void (*func)(struct imsg *);
+};
+
+struct imsgname *monitor_lookup(u_int8_t);
+void monitor_host_status(struct imsg *);
+void monitor_id(struct imsg *);
+int monitor(struct imsg *);
+
+struct imsgname imsgs[] = {
+ { 0, NULL, NULL }
+};
+struct imsgname imsgunknown = {
+ -1, "<unknown>", NULL
+};
+
+struct imsgbuf *ibuf;
+
+__dead void
+usage(void)
+{
+ extern char *__progname;
+
+ fprintf(stderr, "usage: %s <command> [arg [...]]\n", __progname);
+ exit(1);
+}
+
+/* dummy function so that hoststatectl does not need libevent */
+void
+imsg_event_add(struct imsgbuf *i)
+{
+ /* nothing */
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct sockaddr_un sun;
+ struct parse_result *res;
+ struct imsg imsg;
+ int ctl_sock;
+ int done = 0;
+ int n;
+
+ /* parse options */
+ if ((res = parse(argc - 1, argv + 1)) == NULL)
+ exit(1);
+
+ /* connect to snmpd control socket */
+ if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ err(1, "socket");
+
+ bzero(&sun, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strlcpy(sun.sun_path, SNMPD_SOCKET, sizeof(sun.sun_path));
+ reconnect:
+ if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
+ /* Keep retrying if running in monitor mode */
+ if (res->action == MONITOR &&
+ (errno == ENOENT || errno == ECONNREFUSED)) {
+ usleep(100);
+ goto reconnect;
+ }
+ err(1, "connect: %s", SNMPD_SOCKET);
+ }
+
+ if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
+ err(1, NULL);
+ imsg_init(ibuf, ctl_sock, NULL);
+ done = 0;
+
+ /* process user request */
+ switch (res->action) {
+ case NONE:
+ usage();
+ /* not reached */
+ case MONITOR:
+ imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0);
+ break;
+ }
+
+ while (ibuf->w.queued)
+ if (msgbuf_write(&ibuf->w) < 0)
+ err(1, "write error");
+
+ while (!done) {
+ if ((n = imsg_read(ibuf)) == -1)
+ errx(1, "imsg_read error");
+ if (n == 0)
+ errx(1, "pipe closed");
+
+ while (!done) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ errx(1, "imsg_get error");
+ if (n == 0)
+ break;
+ switch (res->action) {
+ case MONITOR:
+ done = monitor(&imsg);
+ break;
+ case NONE:
+ break;
+ }
+ imsg_free(&imsg);
+ }
+ }
+ close(ctl_sock);
+ free(ibuf);
+
+ return (0);
+}
+
+struct imsgname *
+monitor_lookup(u_int8_t type)
+{
+ int i;
+
+ for (i = 0; imsgs[i].name != NULL; i++)
+ if (imsgs[i].type == type)
+ return (&imsgs[i]);
+ return (&imsgunknown);
+}
+
+int
+monitor(struct imsg *imsg)
+{
+ time_t now;
+ int done = 0;
+ struct imsgname *imn;
+
+ now = time(NULL);
+
+ imn = monitor_lookup(imsg->hdr.type);
+ printf("%s: imsg type %u len %u peerid %u pid %d\n", imn->name,
+ imsg->hdr.type, imsg->hdr.len, imsg->hdr.peerid, imsg->hdr.pid);
+ printf("\ttimestamp: %u, %s", now, ctime(&now));
+ if (imn->type == -1)
+ done = 1;
+ if (imn->func != NULL)
+ (*imn->func)(imsg);
+
+ return (done);
+}