File: [local] / src / usr.sbin / snmpctl / Attic / snmpctl.c (download)
Revision 1.7, Fri Jan 18 02:09:30 2008 UTC (16 years, 4 months ago) by reyk
Branch: MAIN
CVS Tags: OPENBSD_4_3_BASE, OPENBSD_4_3 Changes since 1.6: +13 -3 lines
add a snmpctl command to send traps to registered receivers using
snmpd's imsg trap interface.
|
/* $OpenBSD: snmpctl.c,v 1.7 2008/01/18 02:09:30 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 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 "snmp.h"
#include "parser.h"
#include "mib.h"
__dead void usage(void);
struct imsgname {
int type;
char *name;
void (*func)(struct imsg *);
};
void show_mib(void);
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;
struct snmpd *env;
struct oid mib_tree[] = MIB_TREE;
__dead void
usage(void)
{
extern char *__progname;
fprintf(stderr, "usage: %s [-n] <command> [arg [...]]\n", __progname);
exit(1);
}
/* dummy function so that snmpctl 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;
int ch;
if ((env = calloc(1, sizeof(struct snmpd *))) == NULL)
err(1, "calloc");
gettimeofday(&env->sc_starttime, NULL);
while ((ch = getopt(argc, argv, "n")) != -1) {
switch (ch) {
case 'n':
env->sc_flags |= SNMPD_F_NONAMES;
break;
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
smi_init();
/* parse options */
if ((res = parse(argc, argv)) == NULL)
exit(1);
switch (res->action) {
case NONE:
usage();
break;
case SHOW_MIB:
show_mib();
break;
default:
goto connect;
}
free(env);
return (0);
connect:
/* 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 (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;
/* process user request */
switch (res->action) {
case MONITOR:
imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0);
break;
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)
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 TRAP:
break;
case NONE:
case SHOW_MIB:
break;
}
imsg_free(&imsg);
}
}
close(ctl_sock);
free(ibuf);
return (0);
}
void
mib_init(void)
{
/*
* MIB declarations (to register the OID names)
*/
smi_mibtree(mib_tree);
}
void
show_mib(void)
{
struct oid *oid;
for (oid = NULL; (oid = smi_foreach(oid, 0)) != NULL;) {
char buf[BUFSIZ];
smi_oidstring(&oid->o_id, buf, sizeof(buf));
printf("%s\n", buf);
}
}
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);
}