diff options
Diffstat (limited to 'daemon')
| -rw-r--r-- | daemon/Makefile.am | 14 | ||||
| -rw-r--r-- | daemon/rrdbotd.c | 3 | ||||
| -rw-r--r-- | daemon/snmpclient.c | 967 | ||||
| -rw-r--r-- | daemon/snmpclient.h | 187 | 
4 files changed, 7 insertions, 1164 deletions
| diff --git a/daemon/Makefile.am b/daemon/Makefile.am index fa8144a..c83aabe 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -1,11 +1,11 @@ -SUBDIRS = bsnmp  sbin_PROGRAMS = rrdbotd -rrdbotd_SOURCES = rrdbotd.c rrdbotd.h config.c \ +rrdbotd_SOURCES = rrdbotd.c rrdbotd.h config.c usuals.h \                  snmp-help.c snmp-engine.c rrd-update.c \ -                common/server-mainloop.c common/server-mainloop.h \ -                common/sock-any.h common/sock-any.c \ -                usuals.h common/stringx.h common/stringx.c common/hash.h common/hash.c -rrdbotd_CFLAGS = -I${top_srcdir}/src/common/ -I${top_srcdir} -Ibsnmp -rrdbotd_LDADD = $(top_builddir)/src/bsnmp/libbsnmp-custom.a +                ../common/server-mainloop.c ../common/server-mainloop.h \ +                ../common/sock-any.h ../common/sock-any.c \ +                ../common/stringx.h ../common/stringx.c \ +                ../common/hash.h ../common/hash.c +rrdbotd_CFLAGS = -I${top_srcdir}/common/ -I${top_srcdir}/bsnmp/ -I${top_srcdir} +rrdbotd_LDADD = $(top_builddir)/bsnmp/libbsnmp-custom.a diff --git a/daemon/rrdbotd.c b/daemon/rrdbotd.c index 95ab092..f9952bb 100644 --- a/daemon/rrdbotd.c +++ b/daemon/rrdbotd.c @@ -49,9 +49,6 @@  #include "stringx.h"  #include "rrdbotd.h" -/* TODO: Temporary */ -#include "snmpclient.h" -  /* -----------------------------------------------------------------------------   * GLOBALS   */ diff --git a/daemon/snmpclient.c b/daemon/snmpclient.c deleted file mode 100644 index 5d316ad..0000000 --- a/daemon/snmpclient.c +++ /dev/null @@ -1,967 +0,0 @@ -/* - * Copyright (c) 2004-2005 - *	Hartmut Brandt. - *	All rights reserved. - * Copyright (c) 2001-2003 - *	Fraunhofer Institute for Open Communication Systems (FhG Fokus). - *	All rights reserved. - * - * Author: Harti Brandt <harti@freebsd.org> - *         Kendy Kutzner - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Begemot: bsnmp/lib/snmpclient.c,v 1.31 2005/05/23 11:10:13 brandt_h Exp $ - * - * Support functions for SNMP clients. - */ -#include <sys/types.h> -#include <sys/time.h> -#include <sys/queue.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <netdb.h> -#include <stdint.h> -#include <limits.h> -#ifdef HAVE_ERR_H -#include <err.h> -#endif - -#include "asn1.h" -#include "snmp.h" -#include "snmpclient.h" -#include "snmppriv.h" - -/* ---------------------------------------------------------------------------- */ - -#define LIST_EMPTY(head)        ((head)->lh_first == NULL) -#define LIST_FIRST(head)        ((head)->lh_first) -#define LIST_NEXT(elm, field)   ((elm)->field.le_next) -#define LIST_FOREACH(var, head, field)                                  \ -        for ((var) = LIST_FIRST((head));                                \ -            (var);                                                      \ -            (var) = LIST_NEXT((var), field)) - - -/* ---------------------------------------------------------------------------- */ - -/* global context */ -struct snmp_client snmp_client; - -/* List of all outstanding requests */ -struct sent_pdu { -	int		reqid; -	struct snmp_pdu	*pdu; -	struct timeval	time; -	u_int		retrycount; -	snmp_send_cb_f	callback; -	void		*arg; -	void		*timeout_id; -	LIST_ENTRY(sent_pdu) entries; -}; -LIST_HEAD(sent_pdu_list, sent_pdu); - -static struct sent_pdu_list sent_pdus; - -/* - * Set the error string - */ -static void -seterr(struct snmp_client *sc, const char *fmt, ...) -{ -	va_list ap; - -	va_start(ap, fmt); -	vsnprintf(sc->error, sizeof(sc->error), fmt, ap); -	va_end(ap); -} - -/* - * Initialize a client structure - */ -void -snmp_client_init(struct snmp_client *c) -{ -	memset(c, 0, sizeof(*c)); - -	c->version = SNMP_V2c; -	c->trans = SNMP_TRANS_UDP; -	c->chost = NULL; -	c->cport = NULL; - -	strcpy(c->read_community, "public"); -	strcpy(c->write_community, "private"); - -	c->timeout.tv_sec = 3; -	c->timeout.tv_usec = 0; -	c->retries = 3; -	c->dump_pdus = 0; -	c->txbuflen = c->rxbuflen = 10000; - -	c->fd = -1; - -	c->max_reqid = INT32_MAX; -	c->min_reqid = 0; -	c->next_reqid = 0; -} - - -/* - * Open UDP client socket - */ -static int -open_client_udp(const char *host, const char *port) -{ -	int error; -	char *ptr; -	struct addrinfo hints, *res0, *res; - -	/* copy host- and portname */ -	if (snmp_client.chost == NULL) { -		if ((snmp_client.chost = malloc(1 + sizeof(DEFAULT_HOST))) -		    == NULL) { -			seterr(&snmp_client, "%s", strerror(errno)); -			return (-1); -		} -		strcpy(snmp_client.chost, DEFAULT_HOST); -	} -	if (host != NULL) { -		if ((ptr = malloc(1 + strlen(host))) == NULL) { -			seterr(&snmp_client, "%s", strerror(errno)); -			return (-1); -		} -		free(snmp_client.chost); -		snmp_client.chost = ptr; -		strcpy(snmp_client.chost, host); -	} -	if (snmp_client.cport == NULL) { -		if ((snmp_client.cport = malloc(1 + sizeof(DEFAULT_PORT))) -		    == NULL) { -			seterr(&snmp_client, "%s", strerror(errno)); -			return (-1); -		} -		strcpy(snmp_client.cport, DEFAULT_PORT); -	} -	if (port != NULL) { -		if ((ptr = malloc(1 + strlen(port))) == NULL) { -			seterr(&snmp_client, "%s", strerror(errno)); -			return (-1); -		} -		free(snmp_client.cport); -		snmp_client.cport = ptr; -		strcpy(snmp_client.cport, port); -	} - -	/* open connection */ -	memset(&hints, 0, sizeof(hints)); -	hints.ai_flags = AI_CANONNAME; -	hints.ai_family = AF_INET; -	hints.ai_socktype = SOCK_DGRAM; -	hints.ai_protocol = 0; -	error = getaddrinfo(snmp_client.chost, snmp_client.cport, &hints, &res0); -	if (error != 0) { -		seterr(&snmp_client, "%s: %s", snmp_client.chost, -		    gai_strerror(error)); -		return (-1); -	} -	res = res0; -	for (;;) { -		if ((snmp_client.fd = socket(res->ai_family, res->ai_socktype, -		    res->ai_protocol)) == -1) { -			if ((res = res->ai_next) == NULL) { -				seterr(&snmp_client, "%s", strerror(errno)); -				freeaddrinfo(res0); -				return (-1); -			} -		} else if (connect(snmp_client.fd, res->ai_addr, -		    res->ai_addrlen) == -1) { -			if ((res = res->ai_next) == NULL) { -				seterr(&snmp_client, "%s", strerror(errno)); -				freeaddrinfo(res0); -				return (-1); -			} -		} else -			break; -	} -	freeaddrinfo(res0); -	return (0); -} - -/* - * SNMP_OPEN - */ -int -snmp_open(const char *host, const char *port, const char *readcomm, -    const char *writecomm) -{ -	struct timeval tout; - -	/* still open ? */ -	if (snmp_client.fd != -1) { -		errno = EBUSY; -		seterr(&snmp_client, "%s", strerror(errno)); -		return (-1); -	} - -	/* copy community strings */ -	if (readcomm != NULL) { -		strncpy(snmp_client.read_community, readcomm, -		    sizeof(snmp_client.read_community)); -        snmp_client.read_community[sizeof(snmp_client.read_community) - 1] = 0; -    } -	if (writecomm != NULL) { -		strncpy(snmp_client.write_community, writecomm, -		    sizeof(snmp_client.write_community)); -        snmp_client.write_community[sizeof(snmp_client.write_community) - 1] = 0; -    } - -	switch (snmp_client.trans) { - -	  case SNMP_TRANS_UDP: -		if (open_client_udp(host, port)) -			return (-1); -		break; - -	  default: -		seterr(&snmp_client, "bad transport mapping"); -		return (-1); -	} -	tout.tv_sec = 0; -	tout.tv_usec = 0; -	if (setsockopt(snmp_client.fd, SOL_SOCKET, SO_SNDTIMEO, -	    &tout, sizeof(struct timeval)) == -1) { -		seterr(&snmp_client, "%s", strerror(errno)); -		(void)close(snmp_client.fd); -		snmp_client.fd = -1; -		if (snmp_client.local_path[0] != '\0') -			(void)remove(snmp_client.local_path); -		return (-1); -	} - -	/* initialize list */ -	LIST_INIT(&sent_pdus); - -	return (0); -} - - -/* - * SNMP_CLOSE - * - * closes connection to snmp server - * - function cannot fail - * - clears connection - * - clears list of sent pdus - * - * input: - *  void - * return: - *  void - */ -void -snmp_close(void) -{ -	struct sent_pdu *p1; - -	if (snmp_client.fd != -1) { -		(void)close(snmp_client.fd); -		snmp_client.fd = -1; -		if (snmp_client.local_path[0] != '\0') -			(void)remove(snmp_client.local_path); -	} -	while(!LIST_EMPTY(&sent_pdus)){ -		p1 = LIST_FIRST(&sent_pdus); -		if (p1->timeout_id != NULL) -			snmp_client.timeout_stop(p1->timeout_id); -		LIST_REMOVE(p1, entries); -		free(p1); -	} -	free(snmp_client.chost); -	free(snmp_client.cport); -} - -/* - * initialize a snmp_pdu structure - */ -void -snmp_pdu_create(struct snmp_pdu *pdu, u_int op) -{ -	memset(pdu,0,sizeof(struct snmp_pdu)); -	if (op == SNMP_PDU_SET) -		strncpy(pdu->community, snmp_client.write_community, -		    sizeof(pdu->community)); -    else -		strncpy(pdu->community, snmp_client.read_community, -		    sizeof(pdu->community)); -    pdu->community[sizeof(pdu->community) - 1] = 0; - - -	pdu->type = op; -	pdu->version = snmp_client.version; -	pdu->error_status = 0; -	pdu->error_index = 0; -	pdu->nbindings = 0; -} - -/* add pairs of (struct asn_oid, enum snmp_syntax) to an existing pdu */ -/* added 10/04/02 by kek: check for MAX_BINDINGS */ -int -snmp_add_binding(struct snmp_v1_pdu *pdu, ...) -{ -	va_list ap; -	const struct asn_oid *oid; -	u_int ret; - -	va_start(ap, pdu); - -	ret = pdu->nbindings; -	while ((oid = va_arg(ap, const struct asn_oid *)) != NULL) { -		if (pdu->nbindings >= SNMP_MAX_BINDINGS){ -			va_end(ap); -			return (-1); -		} -		pdu->bindings[pdu->nbindings].var = *oid; -		pdu->bindings[pdu->nbindings].syntax = -		    va_arg(ap, enum snmp_syntax); -		pdu->nbindings++; -	} -	va_end(ap); -	return (ret); -} - - -static int32_t -snmp_next_reqid(struct snmp_client * c) -{ -	int32_t i; - -	i = c->next_reqid; -	if (c->next_reqid >= c->max_reqid) -		c->next_reqid = c->min_reqid; -	else -		c->next_reqid++; -	return (i); -} - -/* - * Send request and return request id. - */ -static int32_t -snmp_send_packet(struct snmp_pdu * pdu) -{ -        u_char *buf; -        struct asn_buf b; -        ssize_t ret; - -	if ((buf = malloc(snmp_client.txbuflen)) == NULL) { -		seterr(&snmp_client, "%s", strerror(errno)); -		return (-1); -	} - -        pdu->request_id = snmp_next_reqid(&snmp_client); - -        b.asn_ptr = buf; -        b.asn_len = snmp_client.txbuflen; -        if (snmp_pdu_encode(pdu, &b)) { -		seterr(&snmp_client, "%s", strerror(errno)); -		free(buf); -		return (-1); -	} - -        if (snmp_client.dump_pdus) -                snmp_pdu_dump(pdu); - -        if ((ret = send(snmp_client.fd, buf, b.asn_ptr - buf, 0)) == -1) { -		seterr(&snmp_client, "%s", strerror(errno)); -		free(buf); -                return (-1); -	} -	free(buf); - -	return pdu->request_id; -} - -/* - * to be called when a snmp request timed out - */ -static void -snmp_timeout(void * listentry_ptr) -{ -	struct sent_pdu *listentry = listentry_ptr; - -#if 0 -	warnx("snmp request %i timed out, attempt (%i/%i)", -	    listentry->reqid, listentry->retrycount, snmp_client.retries); -#endif - -	listentry->retrycount++; -	if (listentry->retrycount > snmp_client.retries) { -		/* there is no answer at all */ -		LIST_REMOVE(listentry, entries); -		listentry->callback(listentry->pdu, NULL, listentry->arg); -		free(listentry); -	} else { -		/* try again */ -		/* new request with new request ID */ -		listentry->reqid = snmp_send_packet(listentry->pdu); -		listentry->timeout_id = -		    snmp_client.timeout_start(&snmp_client.timeout, -		    snmp_timeout, listentry); -	} -} - -int32_t -snmp_pdu_send(struct snmp_pdu *pdu, snmp_send_cb_f func, void *arg) -{ -	struct sent_pdu *listentry; -	int32_t id; - -	if ((listentry = malloc(sizeof(struct sent_pdu))) == NULL) { -		seterr(&snmp_client, "%s", strerror(errno)); -		return (-1); -	} - -	/* here we really send */ -	if ((id = snmp_send_packet(pdu)) == -1) { -		free(listentry); -		return (-1); -	} - -	/* add entry to list of sent PDUs */ -	listentry->pdu = pdu; -	if (gettimeofday(&listentry->time, NULL) == -1) -		warn("gettimeofday() failed"); - -	listentry->reqid = pdu->request_id; -	listentry->callback = func; -	listentry->arg = arg; -	listentry->retrycount=1; -	listentry->timeout_id = -	    snmp_client.timeout_start(&snmp_client.timeout, snmp_timeout, -	    listentry); - -	LIST_INSERT_HEAD(&sent_pdus, listentry, entries); - -	return (id); -} - -/* - * Receive an SNMP packet. - * - * tv controls how we wait for a packet: if tv is a NULL pointer, - * the receive blocks forever, if tv points to a structure with all - * members 0 the socket is polled, in all other cases tv specifies the - * maximum time to wait for a packet. - * - * Return: - *	-1 on errors - *	0 on timeout - *	+1 if packet received - */ -static int -snmp_receive_packet(struct snmp_pdu *pdu, struct timeval *tv) -{ -	int dopoll, setpoll; -	int flags; -	int saved_errno; -	u_char *buf; -	int ret; -	struct asn_buf abuf; -	int32_t ip; -#ifdef bsdi -	int optlen; -#else -	socklen_t optlen; -#endif - -	if ((buf = malloc(snmp_client.rxbuflen)) == NULL) { -		seterr(&snmp_client, "%s", strerror(errno)); -		return (-1); -	} -	dopoll = setpoll = 0; -	flags = 0; -	if (tv != NULL) { -		/* poll or timeout */ -		if (tv->tv_sec != 0 || tv->tv_usec != 0) { -			/* wait with timeout */ -			if (setsockopt(snmp_client.fd, SOL_SOCKET, SO_RCVTIMEO, -			    tv, sizeof(*tv)) == -1) { -				seterr(&snmp_client, "setsockopt: %s", -				    strerror(errno)); -				free(buf); -				return (-1); -			} -			optlen = sizeof(*tv); -			if (getsockopt(snmp_client.fd, SOL_SOCKET, SO_RCVTIMEO, -			    tv, &optlen) == -1) { -				seterr(&snmp_client, "getsockopt: %s", -				    strerror(errno)); -				free(buf); -				return (-1); -			} -			/* at this point tv_sec and tv_usec may appear -			 * as 0. This happens for timeouts lesser than -			 * the clock granularity. The kernel rounds these to -			 * 0 and this would result in a blocking receive. -			 * Instead of an else we check tv_sec and tv_usec -			 * again below and if this rounding happens, -			 * switch to a polling receive. */ -		} -		if (tv->tv_sec == 0 && tv->tv_usec == 0) { -			/* poll */ -			dopoll = 1; -			if ((flags = fcntl(snmp_client.fd, F_GETFL, 0)) == -1) { -				seterr(&snmp_client, "fcntl: %s", -				    strerror(errno)); -				free(buf); -				return (-1); -			} -			if (!(flags & O_NONBLOCK)) { -				setpoll = 1; -				flags |= O_NONBLOCK; -				if (fcntl(snmp_client.fd, F_SETFL, flags) == -1) { -					seterr(&snmp_client, "fcntl: %s", -					    strerror(errno)); -					free(buf); -					return (-1); -				} -			} -		} -	} -	ret = recv(snmp_client.fd, buf, snmp_client.rxbuflen, 0); -	saved_errno = errno; -	if (tv != NULL) { -		if (dopoll) { -			if (setpoll) { -				flags &= ~O_NONBLOCK; -				(void)fcntl(snmp_client.fd, F_SETFL, flags); -			} -		} else { -			tv->tv_sec = 0; -			tv->tv_usec = 0; -			(void)setsockopt(snmp_client.fd, SOL_SOCKET, SO_RCVTIMEO, -			    tv, sizeof(*tv)); -		} -	} -	if (ret == -1) { -		free(buf); -		if (errno == EAGAIN || errno == EWOULDBLOCK) -			return (0); -		seterr(&snmp_client, "recv: %s", strerror(saved_errno)); -		return (-1); -	} -	if (ret == 0) { -		/* this happens when we have a streaming socket and the -		 * remote side has closed it */ -		free(buf); -		seterr(&snmp_client, "recv: socket closed by peer"); -		errno = EPIPE; -		return (-1); -	} - -	abuf.asn_ptr = buf; -	abuf.asn_len = ret; - -	if (SNMP_CODE_OK != (ret = snmp_pdu_decode(&abuf, pdu, &ip))) { -		seterr(&snmp_client, "snmp_decode_pdu: failed %d", ret); -		free(buf); -		return (-1); -	} -	free(buf); -	if (snmp_client.dump_pdus) -		snmp_pdu_dump(pdu); - -	return (+1); -} - -static int -snmp_deliver_packet(struct snmp_pdu * resp) -{ -	struct sent_pdu *listentry; - -	if (resp->type != SNMP_PDU_RESPONSE) { -		warn("ignoring snmp pdu %u", resp->type); -		return (-1); -	} - -	LIST_FOREACH(listentry, &sent_pdus, entries) -		if (listentry->reqid == resp->request_id) -			break; -	if (listentry == NULL) -		return (-1); - -	LIST_REMOVE(listentry, entries); -	listentry->callback(listentry->pdu, resp, listentry->arg); - -	snmp_client.timeout_stop(listentry->timeout_id); - -	free(listentry); -	return (0); -} - -int -snmp_receive(int blocking) -{ -	int ret; - -	struct timeval tv; -	struct snmp_pdu * resp; - -	memset(&tv, 0, sizeof(tv)); - -	resp = malloc(sizeof(struct snmp_pdu)); -	if (resp == NULL) { -		seterr(&snmp_client, "no memory for returning PDU"); -		return (-1) ; -	} - -	if ((ret = snmp_receive_packet(resp, blocking ? NULL : &tv)) <= 0) { -		free(resp); -		return (ret); -	} -	ret = snmp_deliver_packet(resp); -	snmp_pdu_free(resp); -	free(resp); -	return (ret); -} - - -/* - * Check a GETNEXT response. Here we have three possible outcomes: -1 an - * unexpected error happened. +1 response is ok and is within the table 0 - * response is ok, but is behind the table or error is NOSUCHNAME. The req - * should point to a template PDU which contains the base OIDs and the - * syntaxes. This is really only useful to sweep non-sparse tables. - */ -static int -ok_getnext(const struct snmp_pdu * req, const struct snmp_pdu * resp) -{ -	u_int i; - -	if (resp->version != req->version) { -		warnx("SNMP GETNEXT: response has wrong version"); -		return (-1); -	} - -	if (resp->error_status == SNMP_ERR_NOSUCHNAME) -		return (0); - -	if (resp->error_status != SNMP_ERR_NOERROR) { -		warnx("SNMP GETNEXT: error %d", resp->error_status); -		return (-1); -	} -	if (resp->nbindings != req->nbindings) { -		warnx("SNMP GETNEXT: bad number of bindings in response"); -		return (-1); -	} -	for (i = 0; i < req->nbindings; i++) { -		if (!asn_is_suboid(&req->bindings[i].var, -		    &resp->bindings[i].var)) { -			if (i != 0) -				warnx("SNMP GETNEXT: inconsistent table " -				      "response"); -			return (0); -		} -		if (resp->version != SNMP_V1 && -		    resp->bindings[i].syntax == SNMP_SYNTAX_ENDOFMIBVIEW) -			return (0); - -		if (resp->bindings[i].syntax != req->bindings[i].syntax) { -			warnx("SNMP GETNEXT: bad syntax in response"); -			return (0); -		} -	} -	return (1); -} - -/* - * Check a GET response. Here we have three possible outcomes: -1 an - * unexpected error happened. +1 response is ok. 0 NOSUCHNAME The req should - * point to a template PDU which contains the OIDs and the syntaxes. This - * is only useful for SNMPv1 or single object GETS. - */ -static int -ok_get(const struct snmp_pdu * req, const struct snmp_pdu * resp) -{ -	u_int i; - -	if (resp->version != req->version) { -		warnx("SNMP GET: response has wrong version"); -		return (-1); -	} - -	if (resp->error_status == SNMP_ERR_NOSUCHNAME) -		return (0); - -	if (resp->error_status != SNMP_ERR_NOERROR) { -		warnx("SNMP GET: error %d", resp->error_status); -		return (-1); -	} - -	if (resp->nbindings != req->nbindings) { -		warnx("SNMP GET: bad number of bindings in response"); -		return (-1); -	} -	for (i = 0; i < req->nbindings; i++) { -		if (asn_compare_oid(&req->bindings[i].var, -		    &resp->bindings[i].var) != 0) { -			warnx("SNMP GET: bad OID in response"); -			return (-1); -		} -		if (snmp_client.version != SNMP_V1 && -		    (resp->bindings[i].syntax == SNMP_SYNTAX_NOSUCHOBJECT || -		    resp->bindings[i].syntax == SNMP_SYNTAX_NOSUCHINSTANCE)) -			return (0); -		if (resp->bindings[i].syntax != req->bindings[i].syntax) { -			warnx("SNMP GET: bad syntax in response"); -			return (-1); -		} -	} -	return (1); -} - -/* - * Check the reponse to a SET PDU. We check: - the error status must be 0 - - * the number of bindings must be equal in response and request - the - * syntaxes must be the same in response and request - the OIDs must be the - * same in response and request - */ -static int -ok_set(const struct snmp_pdu * req, const struct snmp_pdu * resp) -{ -	u_int i; - -	if (resp->version != req->version) { -		warnx("SNMP SET: response has wrong version"); -		return (-1); -	} - -	if (resp->error_status == SNMP_ERR_NOSUCHNAME) { -		warnx("SNMP SET: error %d", resp->error_status); -		return (0); -	} -	if (resp->error_status != SNMP_ERR_NOERROR) { -		warnx("SNMP SET: error %d", resp->error_status); -		return (-1); -	} - -	if (resp->nbindings != req->nbindings) { -		warnx("SNMP SET: bad number of bindings in response"); -		return (-1); -	} -	for (i = 0; i < req->nbindings; i++) { -		if (asn_compare_oid(&req->bindings[i].var, -		    &resp->bindings[i].var) != 0) { -			warnx("SNMP SET: wrong OID in response to SET"); -			return (-1); -		} -		if (resp->bindings[i].syntax != req->bindings[i].syntax) { -			warnx("SNMP SET: bad syntax in response"); -			return (-1); -		} -	} -	return (1); -} - -/* - * Simple checks for response PDUs against request PDUs. Return values: 1=ok, - * 0=nosuchname or similar, -1=failure, -2=no response at all - */ -int -snmp_pdu_check(const struct snmp_pdu *req, -    const struct snmp_pdu *resp) -{ -	if (resp == NULL) -		return (-2); - -	switch (req->type) { - -	  case SNMP_PDU_GET: -		return (ok_get(req, resp)); - -	  case SNMP_PDU_SET: -		return (ok_set(req, resp)); - -	  case SNMP_PDU_GETNEXT: -		return (ok_getnext(req, resp)); - -	} -	errx(1, "%s: bad pdu type %i", __func__, req->type); -} - -int -snmp_dialog(struct snmp_v1_pdu *req, struct snmp_v1_pdu *resp) -{ -        u_int i; -        int32_t reqid; -	int ret; -        struct timeval tv = snmp_client.timeout; -	struct timeval end; -	struct snmp_pdu pdu; - -	/* -	 * Make a copy of the request and replace the syntaxes by NULL -	 * if this is a GET,GETNEXT or GETBULK. -	 */ -	pdu = *req; -	if (pdu.type == SNMP_PDU_GET || pdu.type == SNMP_PDU_GETNEXT || -	    pdu.type == SNMP_PDU_GETBULK) { -		for (i = 0; i < pdu.nbindings; i++) -			pdu.bindings[i].syntax = SNMP_SYNTAX_NULL; -	} - -        for (i = 0; i <= snmp_client.retries; i++) { -		(void)gettimeofday(&end, NULL); -		timeradd(&end, &snmp_client.timeout, &end); -                if ((reqid = snmp_send_packet(&pdu)) == -1) -			return (-1); -		for (;;) { -			(void)gettimeofday(&tv, NULL); -			if (timercmp(&end, &tv, <=)) -				break; -			timersub(&end, &tv, &tv); -			if ((ret = snmp_receive_packet(resp, &tv)) == 0) -				/* timeout */ -				break; - -			if (ret > 0) { -				if (reqid == resp->request_id) -					return (0); -				/* not for us */ -				(void)snmp_deliver_packet(resp); -			} -			if (ret < 0 && errno == EPIPE) -				/* stream closed */ -				return (-1); -		} -        } -	errno = ETIMEDOUT; -	seterr(&snmp_client, "retry count exceeded"); -        return (-1); -} - -/* - * parse a server specification - * - * [trans::][community@][server][:port] - */ -int -snmp_parse_server(struct snmp_client *sc, const char *str) -{ -	const char *p, *s = str; - -	/* look for a double colon */ -	for (p = s; *p != '\0'; p++) { -		if (*p == '\\' && p[1] != '\0') { -			p++; -			continue; -		} -		if (*p == ':' && p[1] == ':') -			break; -	} -	if (*p != '\0') { -		if (p > s) { -			if (p - s == 3 && strncmp(s, "udp", 3) == 0) -				sc->trans = SNMP_TRANS_UDP; -			else if (p - s == 6 && strncmp(s, "stream", 6) == 0) -				sc->trans = SNMP_TRANS_LOC_STREAM; -			else if (p - s == 5 && strncmp(s, "dgram", 5) == 0) -				sc->trans = SNMP_TRANS_LOC_DGRAM; -			else { -				seterr(sc, "unknown SNMP transport '%.*s'", -				    (int)(p - s), s); -				return (-1); -			} -		} -		s = p + 2; -	} - -	/* look for a @ */ -	for (p = s; *p != '\0'; p++) { -		if (*p == '\\' && p[1] != '\0') { -			p++; -			continue; -		} -		if (*p == '@') -			break; -	} - -	if (*p != '\0') { -		if (p - s > SNMP_COMMUNITY_MAXLEN) { -			seterr(sc, "community string too long"); -			return (-1); -		} -		strncpy(sc->read_community, s, p - s); -		sc->read_community[p - s] = '\0'; -		strncpy(sc->write_community, s, p - s); -		sc->write_community[p - s] = '\0'; -		s = p + 1; -	} - -	/* look for a colon */ -	for (p = s; *p != '\0'; p++) { -		if (*p == '\\' && p[1] != '\0') { -			p++; -			continue; -		} -		if (*p == ':') -			break; -	} - -	if (*p == ':') { -		if (p > s) { -			/* host:port */ -			free(sc->chost); -			if ((sc->chost = malloc(p - s + 1)) == NULL) { -				seterr(sc, "%s", strerror(errno)); -				return (-1); -			} -			strncpy(sc->chost, s, p - s); -			sc->chost[p - s] = '\0'; -		} -		/* port */ -		free(sc->cport); -		if ((sc->cport = malloc(strlen(p + 1) + 1)) == NULL) { -			seterr(sc, "%s", strerror(errno)); -			return (-1); -		} -		strcpy(sc->cport, p + 1); - -	} else if (p > s) { -		/* host */ -		free(sc->chost); -		if ((sc->chost = malloc(strlen(s) + 1)) == NULL) { -			seterr(sc, "%s", strerror(errno)); -			return (-1); -		} -		strcpy(sc->chost, s); -	} -	return (0); -} diff --git a/daemon/snmpclient.h b/daemon/snmpclient.h deleted file mode 100644 index f47493f..0000000 --- a/daemon/snmpclient.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2001-2003 - *	Fraunhofer Institute for Open Communication Systems (FhG Fokus). - *	All rights reserved. - * - * Author: Harti Brandt <harti@freebsd.org> - *	   Kendy Kutzner - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Begemot: bsnmp/lib/snmpclient.h,v 1.19 2005/05/23 11:10:14 brandt_h Exp $ - */ -#ifndef _BSNMP_SNMPCLIENT_H -#define _BSNMP_SNMPCLIENT_H - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <netinet/in.h> -#include <stddef.h> - - -#define SNMP_STRERROR_LEN 200 - -#define SNMP_LOCAL_PATH	"/tmp/snmpXXXXXXXXXXXXXX" - -/* - * transport methods - */ -#define	SNMP_TRANS_UDP		0 -#define	SNMP_TRANS_LOC_DGRAM	1 -#define	SNMP_TRANS_LOC_STREAM	2 - -/* type of callback function for responses - * this callback function is responsible for free() any memory associated with - * any of the PDUs. Therefor it may call snmp_pdu_free() */ -typedef void (*snmp_send_cb_f)(struct snmp_pdu *, struct snmp_pdu *, void *); - -/* type of callback function for timeouts */ -typedef void (*snmp_timeout_cb_f)(void * ); - -/* timeout start function */ -typedef void *(*snmp_timeout_start_f)(struct timeval *timeout, -    snmp_timeout_cb_f callback, void *); - -/* timeout stop function */ -typedef void (*snmp_timeout_stop_f)(void *timeout_id); - -/* - * Client context. - */ -struct snmp_client { -	enum snmp_version version; -	int		trans;	/* which transport to use */ - -	/* these two are read-only for the application */ -	char		*cport;	/* port number as string */ -	char		*chost;	/* host name or IP address as string */ - -	char		read_community[SNMP_COMMUNITY_MAXLEN + 1]; -	char		write_community[SNMP_COMMUNITY_MAXLEN + 1]; - -	struct timeval	timeout; -	u_int		retries; - -	int		dump_pdus; - -	size_t		txbuflen; -	size_t		rxbuflen; - -	int		fd; - -	int32_t		next_reqid; -	int32_t		max_reqid; -	int32_t		min_reqid; - -	char		error[SNMP_STRERROR_LEN]; - -	snmp_timeout_start_f timeout_start; -	snmp_timeout_stop_f timeout_stop; - -	char		local_path[sizeof(SNMP_LOCAL_PATH)]; -}; - -/* the global context */ -extern struct snmp_client snmp_client; - -/* initizialies a snmp_client structure */ -void snmp_client_init(struct snmp_client *); - -/* initialize fields */ -int snmp_client_set_host(struct snmp_client *, const char *); -int snmp_client_set_port(struct snmp_client *, const char *); - -/* open connection to snmp server (hostname or portname can be NULL) */ -int snmp_open(const char *_hostname, const char *_portname, -    const char *_read_community, const char *_write_community); - -/* close connection */ -void snmp_close(void); - -/* initialize a snmp_pdu structure */ -void snmp_pdu_create(struct snmp_pdu *, u_int _op); - -/* add pairs of (struct asn_oid *, enum snmp_syntax) to an existing pdu */ -int snmp_add_binding(struct snmp_pdu *, ...); - -/* check wheater the answer is valid or not */ -int snmp_pdu_check(const struct snmp_pdu *_req, const struct snmp_pdu *_resp); - -int32_t snmp_pdu_send(struct snmp_pdu *_pdu, snmp_send_cb_f _func, void *_arg); - -/*  append an index to an oid */ -int snmp_oid_append(struct asn_oid *_oid, const char *_fmt, ...); - -/* receive a packet */ -int snmp_receive(int _blocking); - -/* - * This structure is used to describe an SNMP table that is to be fetched. - * The C-structure that is produced by the fetch function must start with - * a TAILQ_ENTRY and an u_int64_t. - */ -struct snmp_table { -	/* base OID of the table */ -	struct asn_oid		table; -	/* type OID of the LastChange variable for the table if any */ -	struct asn_oid		last_change; -	/* maximum number of iterations if table has changed */ -	u_int			max_iter; -	/* size of the C-structure */ -	size_t			entry_size; -	/* number of index fields */ -	u_int			index_size; -	/* bit mask of required fields */ -	uint64_t		req_mask; - -	/* indexes and columns to fetch. Ended by a NULL syntax entry */ -	struct snmp_table_entry { -	    /* the column sub-oid, ignored for index fields */ -	    asn_subid_t		subid; -	    /* the syntax of the column or index */ -	    enum snmp_syntax	syntax; -	    /* offset of the field into the C-structure. For octet strings -	     * this points to an u_char * followed by a size_t */ -	    off_t		offset; -#if defined(__GNUC__) && __GNUC__ < 3 -	}			entries[0]; -#else -	}			entries[]; -#endif -}; - -/* callback type for table fetch */ -typedef void (*snmp_table_cb_f)(void *_list, void *_arg, int _res); - -/* fetch a table. The argument points to a TAILQ_HEAD */ -int snmp_table_fetch(const struct snmp_table *descr, void *); -int snmp_table_fetch_async(const struct snmp_table *, void *, -    snmp_table_cb_f, void *); - -/* send a request and wait for the response */ -int snmp_dialog(struct snmp_pdu *_req, struct snmp_pdu *_resp); - -/* parse a server specification */ -int snmp_parse_server(struct snmp_client *, const char *); - -#endif /* _BSNMP_SNMPCLIENT_H */ | 
