main.c revision 154180
1/*
2 * Copyright (c) 2001-2003
3 *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 *	All rights reserved.
5 *
6 * Author: Harti Brandt <harti@freebsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Begemot: bsnmp/snmpd/main.c,v 1.97 2005/10/04 14:32:45 brandt_h Exp $
30 *
31 * SNMPd main stuff.
32 */
33#include <sys/param.h>
34#include <sys/un.h>
35#include <sys/ucred.h>
36#include <sys/uio.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <stddef.h>
40#include <string.h>
41#include <stdarg.h>
42#include <ctype.h>
43#include <errno.h>
44#include <syslog.h>
45#include <unistd.h>
46#include <signal.h>
47#include <dlfcn.h>
48#include <inttypes.h>
49
50#ifdef USE_TCPWRAPPERS
51#include <arpa/inet.h>
52#include <tcpd.h>
53#endif
54
55#include "snmpmod.h"
56#include "snmpd.h"
57#include "tree.h"
58#include "oid.h"
59
60#if !defined(INT32_MAX)
61#define	INT32_MAX	(0x7fffffff)
62#endif
63
64#define	PATH_PID	"/var/run/%s.pid"
65#define PATH_CONFIG	"/etc/%s.config"
66
67uint64_t this_tick;	/* start of processing of current packet (absolute) */
68uint64_t start_tick;	/* start of processing */
69
70struct systemg systemg = {
71	NULL,
72	{ 8, { 1, 3, 6, 1, 4, 1, 1115, 7352 }},
73	NULL, NULL, NULL,
74	64 + 8 + 4,
75	0
76};
77struct debug debug = {
78	0,		/* dump_pdus */
79	LOG_DEBUG,	/* log_pri */
80	0,		/* evdebug */
81};
82
83struct snmpd snmpd = {
84	2048,		/* txbuf */
85	2048,		/* rxbuf */
86	0,		/* comm_dis */
87	0,		/* auth_traps */
88	{0, 0, 0, 0},	/* trap1addr */
89	VERS_ENABLE_ALL,/* version_enable */
90};
91struct snmpd_stats snmpd_stats;
92
93/* snmpSerialNo */
94int32_t snmp_serial_no;
95
96/* search path for config files */
97const char *syspath = PATH_SYSCONFIG;
98
99/* list of all loaded modules */
100struct lmodules lmodules = TAILQ_HEAD_INITIALIZER(lmodules);
101
102/* list of loaded modules during start-up in the order they were loaded */
103static struct lmodules modules_start = TAILQ_HEAD_INITIALIZER(modules_start);
104
105/* list of all known communities */
106struct community_list community_list = TAILQ_HEAD_INITIALIZER(community_list);
107
108/* list of all installed object resources */
109struct objres_list objres_list = TAILQ_HEAD_INITIALIZER(objres_list);
110
111/* community value generator */
112static u_int next_community_index = 1;
113
114/* list of all known ranges */
115struct idrange_list idrange_list = TAILQ_HEAD_INITIALIZER(idrange_list);
116
117/* identifier generator */
118u_int next_idrange = 1;
119
120/* list of all current timers */
121struct timer_list timer_list = LIST_HEAD_INITIALIZER(timer_list);
122
123/* list of file descriptors */
124struct fdesc_list fdesc_list = LIST_HEAD_INITIALIZER(fdesc_list);
125
126/* program arguments */
127static char **progargs;
128static int nprogargs;
129
130/* current community */
131u_int	community;
132static struct community *comm;
133
134/* file names */
135static char config_file[MAXPATHLEN + 1];
136static char pid_file[MAXPATHLEN + 1];
137
138#ifndef USE_LIBBEGEMOT
139/* event context */
140static evContext evctx;
141#endif
142
143/* signal mask */
144static sigset_t blocked_sigs;
145
146/* signal handling */
147static int work;
148#define	WORK_DOINFO	0x0001
149#define	WORK_RECONFIG	0x0002
150
151/* oids */
152static const struct asn_oid
153	oid_snmpMIB = OIDX_snmpMIB,
154	oid_begemotSnmpd = OIDX_begemotSnmpd,
155	oid_coldStart = OIDX_coldStart,
156	oid_authenticationFailure = OIDX_authenticationFailure;
157
158const struct asn_oid oid_zeroDotZero = { 2, { 0, 0 }};
159
160/* request id generator for traps */
161u_int trap_reqid;
162
163/* help text */
164static const char usgtxt[] = "\
165Begemot simple SNMP daemon. Copyright (c) 2001-2002 Fraunhofer Institute for\n\
166Open Communication Systems (FhG Fokus). All rights reserved.\n\
167usage: snmpd [-dh] [-c file] [-D options] [-I path] [-l prefix]\n\
168             [-m variable=value] [-p file]\n\
169options:\n\
170  -d		don't daemonize\n\
171  -h		print this info\n\
172  -c file	specify configuration file\n\
173  -D options	debugging options\n\
174  -I path	system include path\n\
175  -l prefix	default basename for pid and config file\n\
176  -m var=val	define variable\n\
177  -p file	specify pid file\n\
178";
179
180/* hosts_access(3) request */
181#ifdef USE_TCPWRAPPERS
182static struct request_info req;
183#endif
184
185/* transports */
186extern const struct transport_def udp_trans;
187extern const struct transport_def lsock_trans;
188
189struct transport_list transport_list = TAILQ_HEAD_INITIALIZER(transport_list);
190
191/* forward declarations */
192static void snmp_printf_func(const char *fmt, ...);
193static void snmp_error_func(const char *err, ...);
194static void snmp_debug_func(const char *err, ...);
195static void asn_error_func(const struct asn_buf *b, const char *err, ...);
196
197/*
198 * Allocate rx/tx buffer. We allocate one byte more for rx.
199 */
200void *
201buf_alloc(int tx)
202{
203	void *buf;
204
205	if ((buf = malloc(tx ? snmpd.txbuf : snmpd.rxbuf)) == NULL) {
206		syslog(LOG_CRIT, "cannot allocate buffer");
207		if (tx)
208			snmpd_stats.noTxbuf++;
209		else
210			snmpd_stats.noRxbuf++;
211		return (NULL);
212	}
213	return (buf);
214}
215
216/*
217 * Return the buffer size.
218 */
219size_t
220buf_size(int tx)
221{
222	return (tx ? snmpd.txbuf : snmpd.rxbuf);
223}
224
225/*
226 * Prepare a PDU for output
227 */
228void
229snmp_output(struct snmp_pdu *pdu, u_char *sndbuf, size_t *sndlen,
230    const char *dest)
231{
232	struct asn_buf resp_b;
233
234	resp_b.asn_ptr = sndbuf;
235	resp_b.asn_len = snmpd.txbuf;
236
237	if (snmp_pdu_encode(pdu, &resp_b) != 0) {
238		syslog(LOG_ERR, "cannot encode message");
239		abort();
240	}
241	if (debug.dump_pdus) {
242		snmp_printf("%s <- ", dest);
243		snmp_pdu_dump(pdu);
244	}
245	*sndlen = (size_t)(resp_b.asn_ptr - sndbuf);
246}
247
248/*
249 * SNMP input. Start: decode the PDU, find the community.
250 */
251enum snmpd_input_err
252snmp_input_start(const u_char *buf, size_t len, const char *source,
253    struct snmp_pdu *pdu, int32_t *ip, size_t *pdulen)
254{
255	struct asn_buf b;
256	enum snmp_code code;
257	enum snmpd_input_err ret;
258	int sret;
259
260	b.asn_cptr = buf;
261	b.asn_len = len;
262
263	/* look whether we have enough bytes for the entire PDU. */
264	switch (sret = snmp_pdu_snoop(&b)) {
265
266	  case 0:
267		return (SNMPD_INPUT_TRUNC);
268
269	  case -1:
270		snmpd_stats.inASNParseErrs++;
271		return (SNMPD_INPUT_FAILED);
272	}
273	b.asn_len = *pdulen = (size_t)sret;
274
275	code = snmp_pdu_decode(&b, pdu, ip);
276
277	snmpd_stats.inPkts++;
278
279	ret = SNMPD_INPUT_OK;
280	switch (code) {
281
282	  case SNMP_CODE_FAILED:
283		snmpd_stats.inASNParseErrs++;
284		return (SNMPD_INPUT_FAILED);
285
286	  case SNMP_CODE_BADVERS:
287	  bad_vers:
288		snmpd_stats.inBadVersions++;
289		return (SNMPD_INPUT_FAILED);
290
291	  case SNMP_CODE_BADLEN:
292		if (pdu->type == SNMP_OP_SET)
293			ret = SNMPD_INPUT_VALBADLEN;
294		break;
295
296	  case SNMP_CODE_OORANGE:
297		if (pdu->type == SNMP_OP_SET)
298			ret = SNMPD_INPUT_VALRANGE;
299		break;
300
301	  case SNMP_CODE_BADENC:
302		if (pdu->type == SNMP_OP_SET)
303			ret = SNMPD_INPUT_VALBADENC;
304		break;
305
306	  case SNMP_CODE_OK:
307		switch (pdu->version) {
308
309		  case SNMP_V1:
310			if (!(snmpd.version_enable & VERS_ENABLE_V1))
311				goto bad_vers;
312			break;
313
314		  case SNMP_V2c:
315			if (!(snmpd.version_enable & VERS_ENABLE_V2C))
316				goto bad_vers;
317			break;
318
319		  case SNMP_Verr:
320			goto bad_vers;
321		}
322		break;
323	}
324
325	if (debug.dump_pdus) {
326		snmp_printf("%s -> ", source);
327		snmp_pdu_dump(pdu);
328	}
329
330	/*
331	 * Look, whether we know the community
332	 */
333	TAILQ_FOREACH(comm, &community_list, link)
334		if (comm->string != NULL &&
335		    strcmp(comm->string, pdu->community) == 0)
336			break;
337
338	if (comm == NULL) {
339		snmpd_stats.inBadCommunityNames++;
340		snmp_pdu_free(pdu);
341		if (snmpd.auth_traps)
342			snmp_send_trap(&oid_authenticationFailure,
343			    (struct snmp_value *)NULL);
344		ret = SNMPD_INPUT_BAD_COMM;
345	} else
346		community = comm->value;
347
348	/* update uptime */
349	this_tick = get_ticks();
350
351	return (ret);
352}
353
354/*
355 * Will return only _OK or _FAILED
356 */
357enum snmpd_input_err
358snmp_input_finish(struct snmp_pdu *pdu, const u_char *rcvbuf, size_t rcvlen,
359    u_char *sndbuf, size_t *sndlen, const char *source,
360    enum snmpd_input_err ierr, int32_t ivar, void *data)
361{
362	struct snmp_pdu resp;
363	struct asn_buf resp_b, pdu_b;
364	enum snmp_ret ret;
365
366	resp_b.asn_ptr = sndbuf;
367	resp_b.asn_len = snmpd.txbuf;
368
369	pdu_b.asn_cptr = rcvbuf;
370	pdu_b.asn_len = rcvlen;
371
372	if (ierr != SNMPD_INPUT_OK) {
373		/* error decoding the input of a SET */
374		if (pdu->version == SNMP_V1)
375			pdu->error_status = SNMP_ERR_BADVALUE;
376		else if (ierr == SNMPD_INPUT_VALBADLEN)
377			pdu->error_status = SNMP_ERR_WRONG_LENGTH;
378		else if (ierr == SNMPD_INPUT_VALRANGE)
379			pdu->error_status = SNMP_ERR_WRONG_VALUE;
380		else
381			pdu->error_status = SNMP_ERR_WRONG_ENCODING;
382
383		pdu->error_index = ivar;
384
385		if (snmp_make_errresp(pdu, &pdu_b, &resp_b) == SNMP_RET_IGN) {
386			syslog(LOG_WARNING, "could not encode error response");
387			snmpd_stats.silentDrops++;
388			return (SNMPD_INPUT_FAILED);
389		}
390
391		if (debug.dump_pdus) {
392			snmp_printf("%s <- ", source);
393			snmp_pdu_dump(pdu);
394		}
395		*sndlen = (size_t)(resp_b.asn_ptr - sndbuf);
396		return (SNMPD_INPUT_OK);
397	}
398
399	switch (pdu->type) {
400
401	  case SNMP_PDU_GET:
402		ret = snmp_get(pdu, &resp_b, &resp, data);
403		break;
404
405	  case SNMP_PDU_GETNEXT:
406		ret = snmp_getnext(pdu, &resp_b, &resp, data);
407		break;
408
409	  case SNMP_PDU_SET:
410		ret = snmp_set(pdu, &resp_b, &resp, data);
411		break;
412
413	  case SNMP_PDU_GETBULK:
414		ret = snmp_getbulk(pdu, &resp_b, &resp, data);
415		break;
416
417	  default:
418		ret = SNMP_RET_IGN;
419		break;
420	}
421
422	switch (ret) {
423
424	  case SNMP_RET_OK:
425		/* normal return - send a response */
426		if (debug.dump_pdus) {
427			snmp_printf("%s <- ", source);
428			snmp_pdu_dump(&resp);
429		}
430		*sndlen = (size_t)(resp_b.asn_ptr - sndbuf);
431		snmp_pdu_free(&resp);
432		return (SNMPD_INPUT_OK);
433
434	  case SNMP_RET_IGN:
435		/* error - send nothing */
436		snmpd_stats.silentDrops++;
437		return (SNMPD_INPUT_FAILED);
438
439	  case SNMP_RET_ERR:
440		/* error - send error response. The snmp routine has
441		 * changed the error fields in the original message. */
442		resp_b.asn_ptr = sndbuf;
443		resp_b.asn_len = snmpd.txbuf;
444		if (snmp_make_errresp(pdu, &pdu_b, &resp_b) == SNMP_RET_IGN) {
445			syslog(LOG_WARNING, "could not encode error response");
446			snmpd_stats.silentDrops++;
447			return (SNMPD_INPUT_FAILED);
448		} else {
449			if (debug.dump_pdus) {
450				snmp_printf("%s <- ", source);
451				snmp_pdu_dump(pdu);
452			}
453			*sndlen = (size_t)(resp_b.asn_ptr - sndbuf);
454			return (SNMPD_INPUT_OK);
455		}
456	}
457	abort();
458}
459
460/*
461 * Insert a port into the right place in the transport's table of ports
462 */
463void
464trans_insert_port(struct transport *t, struct tport *port)
465{
466	struct tport *p;
467
468	TAILQ_FOREACH(p, &t->table, link) {
469		if (asn_compare_oid(&p->index, &port->index) > 0) {
470			TAILQ_INSERT_BEFORE(p, port, link);
471			return;
472		}
473	}
474	port->transport = t;
475	TAILQ_INSERT_TAIL(&t->table, port, link);
476}
477
478/*
479 * Remove a port from a transport's list
480 */
481void
482trans_remove_port(struct tport *port)
483{
484
485	TAILQ_REMOVE(&port->transport->table, port, link);
486}
487
488/*
489 * Find a port on a transport's list
490 */
491struct tport *
492trans_find_port(struct transport *t, const struct asn_oid *idx, u_int sub)
493{
494
495	return (FIND_OBJECT_OID(&t->table, idx, sub));
496}
497
498/*
499 * Find next port on a transport's list
500 */
501struct tport *
502trans_next_port(struct transport *t, const struct asn_oid *idx, u_int sub)
503{
504
505	return (NEXT_OBJECT_OID(&t->table, idx, sub));
506}
507
508/*
509 * Return first port
510 */
511struct tport *
512trans_first_port(struct transport *t)
513{
514
515	return (TAILQ_FIRST(&t->table));
516}
517
518/*
519 * Iterate through all ports until a function returns a 0.
520 */
521struct tport *
522trans_iter_port(struct transport *t, int (*func)(struct tport *, intptr_t),
523    intptr_t arg)
524{
525	struct tport *p;
526
527	TAILQ_FOREACH(p, &t->table, link)
528		if (func(p, arg) == 0)
529			return (p);
530	return (NULL);
531}
532
533/*
534 * Register a transport
535 */
536int
537trans_register(const struct transport_def *def, struct transport **pp)
538{
539	u_int i;
540	char or_descr[256];
541
542	if ((*pp = malloc(sizeof(**pp))) == NULL)
543		return (SNMP_ERR_GENERR);
544
545	/* construct index */
546	(*pp)->index.len = strlen(def->name) + 1;
547	(*pp)->index.subs[0] = strlen(def->name);
548	for (i = 0; i < (*pp)->index.subs[0]; i++)
549		(*pp)->index.subs[i + 1] = def->name[i];
550
551	(*pp)->vtab = def;
552
553	if (FIND_OBJECT_OID(&transport_list, &(*pp)->index, 0) != NULL) {
554		free(*pp);
555		return (SNMP_ERR_INCONS_VALUE);
556	}
557
558	/* register module */
559	snprintf(or_descr, sizeof(or_descr), "%s transport mapping", def->name);
560	if (((*pp)->or_index = or_register(&def->id, or_descr, NULL)) == 0) {
561		free(*pp);
562		return (SNMP_ERR_GENERR);
563	}
564
565	INSERT_OBJECT_OID((*pp), &transport_list);
566
567	TAILQ_INIT(&(*pp)->table);
568
569	return (SNMP_ERR_NOERROR);
570}
571
572/*
573 * Unregister transport
574 */
575int
576trans_unregister(struct transport *t)
577{
578	if (!TAILQ_EMPTY(&t->table))
579		return (SNMP_ERR_INCONS_VALUE);
580
581	or_unregister(t->or_index);
582	TAILQ_REMOVE(&transport_list, t, link);
583
584	return (SNMP_ERR_NOERROR);
585}
586
587/*
588 * File descriptor support
589 */
590#ifdef USE_LIBBEGEMOT
591static void
592input(int fd, int mask __unused, void *uap)
593#else
594static void
595input(evContext ctx __unused, void *uap, int fd, int mask __unused)
596#endif
597{
598	struct fdesc *f = uap;
599
600	(*f->func)(fd, f->udata);
601}
602
603void
604fd_suspend(void *p)
605{
606	struct fdesc *f = p;
607
608#ifdef USE_LIBBEGEMOT
609	if (f->id >= 0) {
610		poll_unregister(f->id);
611		f->id = -1;
612	}
613#else
614	if (evTestID(f->id)) {
615		(void)evDeselectFD(evctx, f->id);
616		evInitID(&f->id);
617	}
618#endif
619}
620
621int
622fd_resume(void *p)
623{
624	struct fdesc *f = p;
625	int err;
626
627#ifdef USE_LIBBEGEMOT
628	if (f->id >= 0)
629		return (0);
630	if ((f->id = poll_register(f->fd, input, f, POLL_IN)) < 0) {
631		err = errno;
632		syslog(LOG_ERR, "select fd %d: %m", f->fd);
633		errno = err;
634		return (-1);
635	}
636#else
637	if (evTestID(f->id))
638		return (0);
639	if (evSelectFD(evctx, f->fd, EV_READ, input, f, &f->id)) {
640		err = errno;
641		syslog(LOG_ERR, "select fd %d: %m", f->fd);
642		errno = err;
643		return (-1);
644	}
645#endif
646	return (0);
647}
648
649void *
650fd_select(int fd, void (*func)(int, void *), void *udata, struct lmodule *mod)
651{
652	struct fdesc *f;
653	int err;
654
655	if ((f = malloc(sizeof(struct fdesc))) == NULL) {
656		err = errno;
657		syslog(LOG_ERR, "fd_select: %m");
658		errno = err;
659		return (NULL);
660	}
661	f->fd = fd;
662	f->func = func;
663	f->udata = udata;
664	f->owner = mod;
665#ifdef USE_LIBBEGEMOT
666	f->id = -1;
667#else
668	evInitID(&f->id);
669#endif
670
671	if (fd_resume(f)) {
672		err = errno;
673		free(f);
674		errno = err;
675		return (NULL);
676	}
677
678	LIST_INSERT_HEAD(&fdesc_list, f, link);
679
680	return (f);
681}
682
683void
684fd_deselect(void *p)
685{
686	struct fdesc *f = p;
687
688	LIST_REMOVE(f, link);
689	fd_suspend(f);
690	free(f);
691}
692
693static void
694fd_flush(struct lmodule *mod)
695{
696	struct fdesc *t, *t1;
697
698	t = LIST_FIRST(&fdesc_list);
699	while (t != NULL) {
700		t1 = LIST_NEXT(t, link);
701		if (t->owner == mod)
702			fd_deselect(t);
703		t = t1;
704	}
705}
706
707/*
708 * Consume a message from the input buffer
709 */
710static void
711snmp_input_consume(struct port_input *pi)
712{
713	if (!pi->stream) {
714		/* always consume everything */
715		pi->length = 0;
716		return;
717	}
718	if (pi->consumed >= pi->length) {
719		/* all bytes consumed */
720		pi->length = 0;
721		return;
722	}
723	memmove(pi->buf, pi->buf + pi->consumed, pi->length - pi->consumed);
724	pi->length -= pi->consumed;
725}
726
727struct credmsg {
728	struct cmsghdr hdr;
729	struct cmsgcred cred;
730};
731
732static void
733check_priv(struct port_input *pi, struct msghdr *msg)
734{
735	struct credmsg *cmsg;
736	struct xucred ucred;
737	socklen_t ucredlen;
738
739	pi->priv = 0;
740
741	if (msg->msg_controllen == sizeof(*cmsg)) {
742		/* process explicitly sends credentials */
743
744		cmsg = (struct credmsg *)msg->msg_control;
745		pi->priv = (cmsg->cred.cmcred_euid == 0);
746		return;
747	}
748
749	/* ok, obtain the accept time credentials */
750	ucredlen = sizeof(ucred);
751
752	if (getsockopt(pi->fd, 0, LOCAL_PEERCRED, &ucred, &ucredlen) == 0 &&
753	    ucredlen >= sizeof(ucred) && ucred.cr_version == XUCRED_VERSION)
754		pi->priv = (ucred.cr_uid == 0);
755}
756
757/*
758 * Input from a stream socket.
759 */
760static int
761recv_stream(struct port_input *pi)
762{
763	struct msghdr msg;
764	struct iovec iov[1];
765	ssize_t len;
766	struct credmsg cmsg;
767
768	if (pi->buf == NULL) {
769		/* no buffer yet - allocate one */
770		if ((pi->buf = buf_alloc(0)) == NULL) {
771			/* ups - could not get buffer. Return an error
772			 * the caller must close the transport. */
773			return (-1);
774		}
775		pi->buflen = buf_size(0);
776		pi->consumed = 0;
777		pi->length = 0;
778	}
779
780	/* try to get a message */
781	msg.msg_name = pi->peer;
782	msg.msg_namelen = pi->peerlen;
783	msg.msg_iov = iov;
784	msg.msg_iovlen = 1;
785	if (pi->cred) {
786		msg.msg_control = &cmsg;
787		msg.msg_controllen = sizeof(cmsg);
788
789		cmsg.hdr.cmsg_len = sizeof(cmsg);
790		cmsg.hdr.cmsg_level = SOL_SOCKET;
791		cmsg.hdr.cmsg_type = SCM_CREDS;
792	} else {
793		msg.msg_control = NULL;
794		msg.msg_controllen = 0;
795	}
796	msg.msg_flags = 0;
797
798	iov[0].iov_base = pi->buf + pi->length;
799	iov[0].iov_len = pi->buflen - pi->length;
800
801	len = recvmsg(pi->fd, &msg, 0);
802
803	if (len == -1 || len == 0)
804		/* receive error */
805		return (-1);
806
807	pi->length += len;
808
809	if (pi->cred)
810		check_priv(pi, &msg);
811
812	return (0);
813}
814
815/*
816 * Input from a datagram socket.
817 * Each receive should return one datagram.
818 */
819static int
820recv_dgram(struct port_input *pi)
821{
822	u_char embuf[1000];
823	struct msghdr msg;
824	struct iovec iov[1];
825	ssize_t len;
826	struct credmsg cmsg;
827
828	if (pi->buf == NULL) {
829		/* no buffer yet - allocate one */
830		if ((pi->buf = buf_alloc(0)) == NULL) {
831			/* ups - could not get buffer. Read away input
832			 * and drop it */
833			(void)recvfrom(pi->fd, embuf, sizeof(embuf),
834			    0, NULL, NULL);
835			/* return error */
836			return (-1);
837		}
838		pi->buflen = buf_size(0);
839	}
840
841	/* try to get a message */
842	msg.msg_name = pi->peer;
843	msg.msg_namelen = pi->peerlen;
844	msg.msg_iov = iov;
845	msg.msg_iovlen = 1;
846	if (pi->cred) {
847		msg.msg_control = &cmsg;
848		msg.msg_controllen = sizeof(cmsg);
849
850		cmsg.hdr.cmsg_len = sizeof(cmsg);
851		cmsg.hdr.cmsg_level = SOL_SOCKET;
852		cmsg.hdr.cmsg_type = SCM_CREDS;
853	} else {
854		msg.msg_control = NULL;
855		msg.msg_controllen = 0;
856	}
857	msg.msg_flags = 0;
858
859	iov[0].iov_base = pi->buf;
860	iov[0].iov_len = pi->buflen;
861
862	len = recvmsg(pi->fd, &msg, 0);
863
864	if (len == -1 || len == 0)
865		/* receive error */
866		return (-1);
867
868	if (msg.msg_flags & MSG_TRUNC) {
869		/* truncated - drop */
870		snmpd_stats.silentDrops++;
871		snmpd_stats.inTooLong++;
872		return (-1);
873	}
874
875	pi->length = (size_t)len;
876
877	if (pi->cred)
878		check_priv(pi, &msg);
879
880	return (0);
881}
882
883/*
884 * Input from a socket
885 */
886int
887snmpd_input(struct port_input *pi, struct tport *tport)
888{
889	u_char *sndbuf;
890	size_t sndlen;
891	struct snmp_pdu pdu;
892	enum snmpd_input_err ierr, ferr;
893	enum snmpd_proxy_err perr;
894	int32_t vi;
895	int ret;
896	ssize_t slen;
897#ifdef USE_TCPWRAPPERS
898	char client[16];
899#endif
900
901	/* get input depending on the transport */
902	if (pi->stream) {
903		ret = recv_stream(pi);
904	} else {
905		ret = recv_dgram(pi);
906	}
907
908	if (ret == -1)
909		return (-1);
910
911#ifdef USE_TCPWRAPPERS
912	/*
913	 * In case of AF_INET{6} peer, do hosts_access(5) check.
914	 */
915	if (inet_ntop(pi->peer->sa_family,
916	    &((const struct sockaddr_in *)(const void *)pi->peer)->sin_addr,
917	    client, sizeof(client)) != NULL) {
918		request_set(&req, RQ_CLIENT_ADDR, client, 0);
919		if (hosts_access(&req) == 0) {
920			syslog(LOG_ERR, "refused connection from %.500s",
921			    eval_client(&req));
922			return (-1);
923		}
924	} else
925		syslog(LOG_ERR, "inet_ntop(): %m");
926#endif
927
928	/*
929	 * Handle input
930	 */
931	ierr = snmp_input_start(pi->buf, pi->length, "SNMP", &pdu, &vi,
932	    &pi->consumed);
933	if (ierr == SNMPD_INPUT_TRUNC) {
934		/* need more bytes. This is ok only for streaming transports.
935		 * but only if we have not reached bufsiz yet. */
936		if (pi->stream) {
937			if (pi->length == buf_size(0)) {
938				snmpd_stats.silentDrops++;
939				return (-1);
940			}
941			return (0);
942		}
943		snmpd_stats.silentDrops++;
944		return (-1);
945	}
946
947	/* can't check for bad SET pdus here, because a proxy may have to
948	 * check the access first. We don't want to return an error response
949	 * to a proxy PDU with a wrong community */
950	if (ierr == SNMPD_INPUT_FAILED) {
951		/* for streaming transports this is fatal */
952		if (pi->stream)
953			return (-1);
954		snmp_input_consume(pi);
955		return (0);
956	}
957	if (ierr == SNMPD_INPUT_BAD_COMM) {
958		snmp_input_consume(pi);
959		return (0);
960	}
961
962	/*
963	 * If that is a module community and the module has a proxy function,
964	 * the hand it over to the module.
965	 */
966	if (comm->owner != NULL && comm->owner->config->proxy != NULL) {
967		perr = (*comm->owner->config->proxy)(&pdu, tport->transport,
968		    &tport->index, pi->peer, pi->peerlen, ierr, vi,
969		    !pi->cred || pi->priv);
970
971		switch (perr) {
972
973		  case SNMPD_PROXY_OK:
974			snmp_input_consume(pi);
975			return (0);
976
977		  case SNMPD_PROXY_REJ:
978			break;
979
980		  case SNMPD_PROXY_DROP:
981			snmp_input_consume(pi);
982			snmp_pdu_free(&pdu);
983			snmpd_stats.proxyDrops++;
984			return (0);
985
986		  case SNMPD_PROXY_BADCOMM:
987			snmp_input_consume(pi);
988			snmp_pdu_free(&pdu);
989			snmpd_stats.inBadCommunityNames++;
990			if (snmpd.auth_traps)
991				snmp_send_trap(&oid_authenticationFailure,
992				    (struct snmp_value *)NULL);
993			return (0);
994
995		  case SNMPD_PROXY_BADCOMMUSE:
996			snmp_input_consume(pi);
997			snmp_pdu_free(&pdu);
998			snmpd_stats.inBadCommunityUses++;
999			if (snmpd.auth_traps)
1000				snmp_send_trap(&oid_authenticationFailure,
1001				    (struct snmp_value *)NULL);
1002			return (0);
1003		}
1004	}
1005
1006	/*
1007	 * Check type
1008	 */
1009	if (pdu.type == SNMP_PDU_RESPONSE ||
1010	    pdu.type == SNMP_PDU_TRAP ||
1011	    pdu.type == SNMP_PDU_TRAP2) {
1012		snmpd_stats.silentDrops++;
1013		snmpd_stats.inBadPduTypes++;
1014		snmp_pdu_free(&pdu);
1015		snmp_input_consume(pi);
1016		return (0);
1017	}
1018
1019	/*
1020	 * Check community
1021	 */
1022	if ((pi->cred && !pi->priv && pdu.type == SNMP_PDU_SET) ||
1023	    (community != COMM_WRITE &&
1024            (pdu.type == SNMP_PDU_SET || community != COMM_READ))) {
1025		snmpd_stats.inBadCommunityUses++;
1026		snmp_pdu_free(&pdu);
1027		snmp_input_consume(pi);
1028		if (snmpd.auth_traps)
1029			snmp_send_trap(&oid_authenticationFailure,
1030			    (struct snmp_value *)NULL);
1031		return (0);
1032	}
1033
1034	/*
1035	 * Execute it.
1036	 */
1037	if ((sndbuf = buf_alloc(1)) == NULL) {
1038		snmpd_stats.silentDrops++;
1039		snmp_pdu_free(&pdu);
1040		snmp_input_consume(pi);
1041		return (0);
1042	}
1043	ferr = snmp_input_finish(&pdu, pi->buf, pi->length,
1044	    sndbuf, &sndlen, "SNMP", ierr, vi, NULL);
1045
1046	if (ferr == SNMPD_INPUT_OK) {
1047		slen = sendto(pi->fd, sndbuf, sndlen, 0, pi->peer, pi->peerlen);
1048		if (slen == -1)
1049			syslog(LOG_ERR, "sendto: %m");
1050		else if ((size_t)slen != sndlen)
1051			syslog(LOG_ERR, "sendto: short write %zu/%zu",
1052			    sndlen, (size_t)slen);
1053	}
1054	snmp_pdu_free(&pdu);
1055	free(sndbuf);
1056	snmp_input_consume(pi);
1057
1058	return (0);
1059}
1060
1061/*
1062 * Send a PDU to a given port
1063 */
1064void
1065snmp_send_port(void *targ, const struct asn_oid *port, struct snmp_pdu *pdu,
1066    const struct sockaddr *addr, socklen_t addrlen)
1067{
1068	struct transport *trans = targ;
1069	struct tport *tp;
1070	u_char *sndbuf;
1071	size_t sndlen;
1072	ssize_t len;
1073
1074	TAILQ_FOREACH(tp, &trans->table, link)
1075		if (asn_compare_oid(port, &tp->index) == 0)
1076			break;
1077	if (tp == 0)
1078		return;
1079
1080	if ((sndbuf = buf_alloc(1)) == NULL)
1081		return;
1082
1083	snmp_output(pdu, sndbuf, &sndlen, "SNMP PROXY");
1084
1085	len = trans->vtab->send(tp, sndbuf, sndlen, addr, addrlen);
1086
1087	if (len == -1)
1088		syslog(LOG_ERR, "sendto: %m");
1089	else if ((size_t)len != sndlen)
1090		syslog(LOG_ERR, "sendto: short write %zu/%zu",
1091		    sndlen, (size_t)len);
1092
1093	free(sndbuf);
1094}
1095
1096
1097/*
1098 * Close an input source
1099 */
1100void
1101snmpd_input_close(struct port_input *pi)
1102{
1103	if (pi->id != NULL)
1104		fd_deselect(pi->id);
1105	if (pi->fd >= 0)
1106		(void)close(pi->fd);
1107	if (pi->buf != NULL)
1108		free(pi->buf);
1109}
1110
1111/*
1112 * Dump internal state.
1113 */
1114#ifdef USE_LIBBEGEMOT
1115static void
1116info_func(void)
1117#else
1118static void
1119info_func(evContext ctx __unused, void *uap __unused, const void *tag __unused)
1120#endif
1121{
1122	struct lmodule *m;
1123	u_int i;
1124	char buf[10000];
1125
1126	syslog(LOG_DEBUG, "Dump of SNMPd %lu\n", (u_long)getpid());
1127	for (i = 0; i < tree_size; i++) {
1128		switch (tree[i].type) {
1129
1130		  case SNMP_NODE_LEAF:
1131			sprintf(buf, "LEAF: %s %s", tree[i].name,
1132			    asn_oid2str(&tree[i].oid));
1133			break;
1134
1135		  case SNMP_NODE_COLUMN:
1136			sprintf(buf, "COL: %s %s", tree[i].name,
1137			    asn_oid2str(&tree[i].oid));
1138			break;
1139		}
1140		syslog(LOG_DEBUG, "%s", buf);
1141	}
1142
1143	TAILQ_FOREACH(m, &lmodules, link)
1144		if (m->config->dump)
1145			(*m->config->dump)();
1146}
1147
1148/*
1149 * Re-read configuration
1150 */
1151#ifdef USE_LIBBEGEMOT
1152static void
1153config_func(void)
1154#else
1155static void
1156config_func(evContext ctx __unused, void *uap __unused,
1157    const void *tag __unused)
1158#endif
1159{
1160	struct lmodule *m;
1161
1162	if (read_config(config_file, NULL)) {
1163		syslog(LOG_ERR, "error reading config file '%s'", config_file);
1164		return;
1165	}
1166	TAILQ_FOREACH(m, &lmodules, link)
1167		if (m->config->config)
1168			(*m->config->config)();
1169}
1170
1171/*
1172 * On USR1 dump actual configuration.
1173 */
1174static void
1175onusr1(int s __unused)
1176{
1177
1178	work |= WORK_DOINFO;
1179}
1180static void
1181onhup(int s __unused)
1182{
1183
1184	work |= WORK_RECONFIG;
1185}
1186
1187static void
1188onterm(int s __unused)
1189{
1190
1191	/* allow clean-up */
1192	exit(0);
1193}
1194
1195static void
1196init_sigs(void)
1197{
1198	struct sigaction sa;
1199
1200	sa.sa_handler = onusr1;
1201	sa.sa_flags = SA_RESTART;
1202	sigemptyset(&sa.sa_mask);
1203	if (sigaction(SIGUSR1, &sa, NULL)) {
1204		syslog(LOG_ERR, "sigaction: %m");
1205		exit(1);
1206	}
1207
1208	sa.sa_handler = onhup;
1209	if (sigaction(SIGHUP, &sa, NULL)) {
1210		syslog(LOG_ERR, "sigaction: %m");
1211		exit(1);
1212	}
1213
1214	sa.sa_handler = onterm;
1215	sa.sa_flags = 0;
1216	sigemptyset(&sa.sa_mask);
1217	if (sigaction(SIGTERM, &sa, NULL)) {
1218		syslog(LOG_ERR, "sigaction: %m");
1219		exit(1);
1220	}
1221	if (sigaction(SIGINT, &sa, NULL)) {
1222		syslog(LOG_ERR, "sigaction: %m");
1223		exit(1);
1224	}
1225}
1226
1227static void
1228block_sigs(void)
1229{
1230	sigset_t set;
1231
1232	sigfillset(&set);
1233	if (sigprocmask(SIG_BLOCK, &set, &blocked_sigs) == -1) {
1234		syslog(LOG_ERR, "SIG_BLOCK: %m");
1235		exit(1);
1236	}
1237}
1238static void
1239unblock_sigs(void)
1240{
1241	if (sigprocmask(SIG_SETMASK, &blocked_sigs, NULL) == -1) {
1242		syslog(LOG_ERR, "SIG_SETMASK: %m");
1243		exit(1);
1244	}
1245}
1246
1247/*
1248 * Shut down
1249 */
1250static void
1251term(void)
1252{
1253	(void)unlink(pid_file);
1254}
1255
1256static void
1257trans_stop(void)
1258{
1259	struct transport *t;
1260
1261	TAILQ_FOREACH(t, &transport_list, link)
1262		(void)t->vtab->stop(1);
1263}
1264
1265/*
1266 * Define a macro from the command line
1267 */
1268static void
1269do_macro(char *arg)
1270{
1271	char *eq;
1272	int err;
1273
1274	if ((eq = strchr(arg, '=')) == NULL)
1275		err = define_macro(arg, "");
1276	else {
1277		*eq++ = '\0';
1278		err = define_macro(arg, eq);
1279	}
1280	if (err == -1) {
1281		syslog(LOG_ERR, "cannot save macro: %m");
1282		exit(1);
1283	}
1284}
1285
1286/*
1287 * Re-implement getsubopt from scratch, because the second argument is broken
1288 * and will not compile with WARNS=5.
1289 */
1290static int
1291getsubopt1(char **arg, const char *const *options, char **valp, char **optp)
1292{
1293	static const char *const delim = ",\t ";
1294	u_int i;
1295	char *ptr;
1296
1297	*optp = NULL;
1298
1299	/* skip leading junk */
1300	for (ptr = *arg; *ptr != '\0'; ptr++)
1301		if (strchr(delim, *ptr) == NULL)
1302			break;
1303	if (*ptr == '\0') {
1304		*arg = ptr;
1305		return (-1);
1306	}
1307	*optp = ptr;
1308
1309	/* find the end of the option */
1310	while (*++ptr != '\0')
1311		if (strchr(delim, *ptr) != NULL || *ptr == '=')
1312			break;
1313
1314	if (*ptr != '\0') {
1315		if (*ptr == '=') {
1316			*ptr++ = '\0';
1317			*valp = ptr;
1318			while (*ptr != '\0' && strchr(delim, *ptr) == NULL)
1319				ptr++;
1320			if (*ptr != '\0')
1321				*ptr++ = '\0';
1322		} else
1323			*ptr++ = '\0';
1324	}
1325
1326	*arg = ptr;
1327
1328	for (i = 0; *options != NULL; options++, i++)
1329		if (strcmp(*optp, *options) == 0)
1330			return (i);
1331	return (-1);
1332}
1333
1334int
1335main(int argc, char *argv[])
1336{
1337	int opt;
1338	FILE *fp;
1339	int background = 1;
1340	struct tport *p;
1341	const char *prefix = "snmpd";
1342	struct lmodule *m;
1343	char *value, *option;
1344	struct transport *t;
1345
1346#define DBG_DUMP	0
1347#define DBG_EVENTS	1
1348#define DBG_TRACE	2
1349	static const char *const debug_opts[] = {
1350		"dump",
1351		"events",
1352		"trace",
1353		NULL
1354	};
1355
1356	snmp_printf = snmp_printf_func;
1357	snmp_error = snmp_error_func;
1358	snmp_debug = snmp_debug_func;
1359	asn_error = asn_error_func;
1360
1361	while ((opt = getopt(argc, argv, "c:dD:hI:l:m:p:")) != EOF)
1362		switch (opt) {
1363
1364		  case 'c':
1365			strlcpy(config_file, optarg, sizeof(config_file));
1366			break;
1367
1368		  case 'd':
1369			background = 0;
1370			break;
1371
1372		  case 'D':
1373			while (*optarg) {
1374				switch (getsubopt1(&optarg, debug_opts,
1375				    &value, &option)) {
1376
1377				  case DBG_DUMP:
1378					debug.dump_pdus = 1;
1379					break;
1380
1381				  case DBG_EVENTS:
1382					debug.evdebug++;
1383					break;
1384
1385				  case DBG_TRACE:
1386					if (value == NULL)
1387						syslog(LOG_ERR,
1388						    "no value for 'trace'");
1389					snmp_trace = strtoul(value, NULL, 0);
1390					break;
1391
1392				  case -1:
1393					if (suboptarg)
1394						syslog(LOG_ERR,
1395						    "unknown debug flag '%s'",
1396						    option);
1397					else
1398						syslog(LOG_ERR,
1399						    "missing debug flag");
1400					break;
1401				}
1402			}
1403			break;
1404
1405		  case 'h':
1406			fprintf(stderr, "%s", usgtxt);
1407			exit(0);
1408
1409		  case 'I':
1410			syspath = optarg;
1411			break;
1412
1413		  case 'l':
1414			prefix = optarg;
1415			break;
1416
1417		  case 'm':
1418			do_macro(optarg);
1419			break;
1420
1421		  case 'p':
1422			strlcpy(pid_file, optarg, sizeof(pid_file));
1423			break;
1424		}
1425
1426	openlog(prefix, LOG_PID | (background ? 0 : LOG_PERROR), LOG_USER);
1427	setlogmask(LOG_UPTO(debug.logpri - 1));
1428
1429	if (background && daemon(0, 0) < 0) {
1430		syslog(LOG_ERR, "daemon: %m");
1431		exit(1);
1432	}
1433
1434	argc -= optind;
1435	argv += optind;
1436
1437	progargs = argv;
1438	nprogargs = argc;
1439
1440	srandomdev();
1441
1442	snmp_serial_no = random();
1443
1444#ifdef USE_TCPWRAPPERS
1445	/*
1446	 * Initialize hosts_access(3) handler.
1447	 */
1448	request_init(&req, RQ_DAEMON, "snmpd", 0);
1449	sock_methods(&req);
1450#endif
1451
1452	/*
1453	 * Initialize the tree.
1454	 */
1455	if ((tree = malloc(sizeof(struct snmp_node) * CTREE_SIZE)) == NULL) {
1456		syslog(LOG_ERR, "%m");
1457		exit(1);
1458	}
1459	memcpy(tree, ctree, sizeof(struct snmp_node) * CTREE_SIZE);
1460	tree_size = CTREE_SIZE;
1461
1462	/*
1463	 * Get standard communities
1464	 */
1465	(void)comm_define(1, "SNMP read", NULL, NULL);
1466	(void)comm_define(2, "SNMP write", NULL, NULL);
1467	community = COMM_INITIALIZE;
1468
1469	trap_reqid = reqid_allocate(512, NULL);
1470
1471	if (config_file[0] == '\0')
1472		snprintf(config_file, sizeof(config_file), PATH_CONFIG, prefix);
1473
1474	init_actvals();
1475
1476	this_tick = get_ticks();
1477	start_tick = this_tick;
1478
1479	/* start transports */
1480	if (atexit(trans_stop) == -1) {
1481		syslog(LOG_ERR, "atexit failed: %m");
1482		exit(1);
1483	}
1484	if (udp_trans.start() != SNMP_ERR_NOERROR)
1485		syslog(LOG_WARNING, "cannot start UDP transport");
1486	if (lsock_trans.start() != SNMP_ERR_NOERROR)
1487		syslog(LOG_WARNING, "cannot start LSOCK transport");
1488
1489#ifdef USE_LIBBEGEMOT
1490	if (debug.evdebug > 0)
1491		rpoll_trace = 1;
1492#else
1493	if (evCreate(&evctx)) {
1494		syslog(LOG_ERR, "evCreate: %m");
1495		exit(1);
1496	}
1497	if (debug.evdebug > 0)
1498		evSetDebug(evctx, 10, stderr);
1499#endif
1500
1501	if (read_config(config_file, NULL)) {
1502		syslog(LOG_ERR, "error in config file");
1503		exit(1);
1504	}
1505
1506	TAILQ_FOREACH(t, &transport_list, link)
1507		TAILQ_FOREACH(p, &t->table, link)
1508			t->vtab->init_port(p);
1509
1510	init_sigs();
1511
1512	if (pid_file[0] == '\0')
1513		snprintf(pid_file, sizeof(pid_file), PATH_PID, prefix);
1514
1515	if ((fp = fopen(pid_file, "w")) != NULL) {
1516		fprintf(fp, "%u", getpid());
1517		fclose(fp);
1518		if (atexit(term) == -1) {
1519			syslog(LOG_ERR, "atexit failed: %m");
1520			(void)remove(pid_file);
1521			exit(0);
1522		}
1523	}
1524
1525	if (or_register(&oid_snmpMIB, "The MIB module for SNMPv2 entities.",
1526	    NULL) == 0) {
1527		syslog(LOG_ERR, "cannot register SNMPv2 MIB");
1528		exit(1);
1529	}
1530	if (or_register(&oid_begemotSnmpd, "The MIB module for the Begemot SNMPd.",
1531	    NULL) == 0) {
1532		syslog(LOG_ERR, "cannot register begemotSnmpd MIB");
1533		exit(1);
1534	}
1535
1536	snmp_send_trap(&oid_coldStart, (struct snmp_value *)NULL);
1537
1538	while ((m = TAILQ_FIRST(&modules_start)) != NULL) {
1539		m->flags &= ~LM_ONSTARTLIST;
1540		TAILQ_REMOVE(&modules_start, m, start);
1541		lm_start(m);
1542	}
1543
1544	for (;;) {
1545#ifndef USE_LIBBEGEMOT
1546		evEvent event;
1547#endif
1548		struct lmodule *mod;
1549
1550		TAILQ_FOREACH(mod, &lmodules, link)
1551			if (mod->config->idle != NULL)
1552				(*mod->config->idle)();
1553
1554#ifndef USE_LIBBEGEMOT
1555		if (evGetNext(evctx, &event, EV_WAIT) == 0) {
1556			if (evDispatch(evctx, event))
1557				syslog(LOG_ERR, "evDispatch: %m");
1558		} else if (errno != EINTR) {
1559			syslog(LOG_ERR, "evGetNext: %m");
1560			exit(1);
1561		}
1562#else
1563		poll_dispatch(1);
1564#endif
1565
1566		if (work != 0) {
1567			block_sigs();
1568			if (work & WORK_DOINFO) {
1569#ifdef USE_LIBBEGEMOT
1570				info_func();
1571#else
1572				if (evWaitFor(evctx, &work, info_func,
1573				    NULL, NULL) == -1) {
1574					syslog(LOG_ERR, "evWaitFor: %m");
1575					exit(1);
1576				}
1577#endif
1578			}
1579			if (work & WORK_RECONFIG) {
1580#ifdef USE_LIBBEGEMOT
1581				config_func();
1582#else
1583				if (evWaitFor(evctx, &work, config_func,
1584				    NULL, NULL) == -1) {
1585					syslog(LOG_ERR, "evWaitFor: %m");
1586					exit(1);
1587				}
1588#endif
1589			}
1590			work = 0;
1591			unblock_sigs();
1592#ifndef USE_LIBBEGEMOT
1593			if (evDo(evctx, &work) == -1) {
1594				syslog(LOG_ERR, "evDo: %m");
1595				exit(1);
1596			}
1597#endif
1598		}
1599	}
1600
1601	return (0);
1602}
1603
1604uint64_t
1605get_ticks()
1606{
1607	struct timeval tv;
1608	uint64_t ret;
1609
1610	if (gettimeofday(&tv, NULL))
1611		abort();
1612	ret = tv.tv_sec * 100ULL + tv.tv_usec / 10000ULL;
1613	return (ret);
1614}
1615
1616/*
1617 * Timer support
1618 */
1619
1620/*
1621 * Trampoline for the non-repeatable timers.
1622 */
1623#ifdef USE_LIBBEGEMOT
1624static void
1625tfunc(int tid __unused, void *uap)
1626#else
1627static void
1628tfunc(evContext ctx __unused, void *uap, struct timespec due __unused,
1629	struct timespec inter __unused)
1630#endif
1631{
1632	struct timer *tp = uap;
1633
1634	LIST_REMOVE(tp, link);
1635	tp->func(tp->udata);
1636	free(tp);
1637}
1638
1639/*
1640 * Trampoline for the repeatable timers.
1641 */
1642#ifdef USE_LIBBEGEMOT
1643static void
1644trfunc(int tid __unused, void *uap)
1645#else
1646static void
1647trfunc(evContext ctx __unused, void *uap, struct timespec due __unused,
1648	struct timespec inter __unused)
1649#endif
1650{
1651	struct timer *tp = uap;
1652
1653	tp->func(tp->udata);
1654}
1655
1656/*
1657 * Start a one-shot timer
1658 */
1659void *
1660timer_start(u_int ticks, void (*func)(void *), void *udata, struct lmodule *mod)
1661{
1662	struct timer *tp;
1663#ifndef USE_LIBBEGEMOT
1664	struct timespec due;
1665#endif
1666
1667	if ((tp = malloc(sizeof(struct timer))) == NULL) {
1668		syslog(LOG_CRIT, "out of memory for timer");
1669		exit(1);
1670	}
1671
1672#ifndef USE_LIBBEGEMOT
1673	due = evAddTime(evNowTime(),
1674	    evConsTime(ticks / 100, (ticks % 100) * 10000));
1675#endif
1676
1677	tp->udata = udata;
1678	tp->owner = mod;
1679	tp->func = func;
1680
1681	LIST_INSERT_HEAD(&timer_list, tp, link);
1682
1683#ifdef USE_LIBBEGEMOT
1684	if ((tp->id = poll_start_timer(ticks * 10, 0, tfunc, tp)) < 0) {
1685		syslog(LOG_ERR, "cannot set timer: %m");
1686		exit(1);
1687	}
1688#else
1689	if (evSetTimer(evctx, tfunc, tp, due, evConsTime(0, 0), &tp->id)
1690	    == -1) {
1691		syslog(LOG_ERR, "cannot set timer: %m");
1692		exit(1);
1693	}
1694#endif
1695	return (tp);
1696}
1697
1698/*
1699 * Start a repeatable timer. When used with USE_LIBBEGEMOT the first argument
1700 * is currently ignored and the initial number of ticks is set to the
1701 * repeat number of ticks.
1702 */
1703void *
1704timer_start_repeat(u_int ticks __unused, u_int repeat_ticks,
1705    void (*func)(void *), void *udata, struct lmodule *mod)
1706{
1707	struct timer *tp;
1708#ifndef USE_LIBBEGEMOT
1709	struct timespec due;
1710	struct timespec inter;
1711#endif
1712
1713	if ((tp = malloc(sizeof(struct timer))) == NULL) {
1714		syslog(LOG_CRIT, "out of memory for timer");
1715		exit(1);
1716	}
1717
1718#ifndef USE_LIBBEGEMOT
1719	due = evAddTime(evNowTime(),
1720	    evConsTime(ticks / 100, (ticks % 100) * 10000));
1721	inter = evConsTime(repeat_ticks / 100, (repeat_ticks % 100) * 10000);
1722#endif
1723
1724	tp->udata = udata;
1725	tp->owner = mod;
1726	tp->func = func;
1727
1728	LIST_INSERT_HEAD(&timer_list, tp, link);
1729
1730#ifdef USE_LIBBEGEMOT
1731	if ((tp->id = poll_start_timer(repeat_ticks * 10, 1, trfunc, tp)) < 0) {
1732		syslog(LOG_ERR, "cannot set timer: %m");
1733		exit(1);
1734	}
1735#else
1736	if (evSetTimer(evctx, trfunc, tp, due, inter, &tp->id) == -1) {
1737		syslog(LOG_ERR, "cannot set timer: %m");
1738		exit(1);
1739	}
1740#endif
1741	return (tp);
1742}
1743
1744/*
1745 * Stop a timer.
1746 */
1747void
1748timer_stop(void *p)
1749{
1750	struct timer *tp = p;
1751
1752	LIST_REMOVE(tp, link);
1753#ifdef USE_LIBBEGEMOT
1754	poll_stop_timer(tp->id);
1755#else
1756	if (evClearTimer(evctx, tp->id) == -1) {
1757		syslog(LOG_ERR, "cannot stop timer: %m");
1758		exit(1);
1759	}
1760#endif
1761	free(p);
1762}
1763
1764static void
1765timer_flush(struct lmodule *mod)
1766{
1767	struct timer *t, *t1;
1768
1769	t = LIST_FIRST(&timer_list);
1770	while (t != NULL) {
1771		t1 = LIST_NEXT(t, link);
1772		if (t->owner == mod)
1773			timer_stop(t);
1774		t = t1;
1775	}
1776}
1777
1778static void
1779snmp_printf_func(const char *fmt, ...)
1780{
1781	va_list ap;
1782	static char *pend = NULL;
1783	char *ret, *new;
1784
1785	va_start(ap, fmt);
1786	vasprintf(&ret, fmt, ap);
1787	va_end(ap);
1788
1789	if (ret == NULL)
1790		return;
1791	if (pend != NULL) {
1792		if ((new = realloc(pend, strlen(pend) + strlen(ret) + 1))
1793		    == NULL) {
1794			free(ret);
1795			return;
1796		}
1797		pend = new;
1798		strcat(pend, ret);
1799		free(ret);
1800	} else
1801		pend = ret;
1802
1803	while ((ret = strchr(pend, '\n')) != NULL) {
1804		*ret = '\0';
1805		syslog(LOG_DEBUG, "%s", pend);
1806		if (strlen(ret + 1) == 0) {
1807			free(pend);
1808			pend = NULL;
1809			break;
1810		}
1811		strcpy(pend, ret + 1);
1812	}
1813}
1814
1815static void
1816snmp_error_func(const char *err, ...)
1817{
1818	char errbuf[1000];
1819	va_list ap;
1820
1821	if (!(snmp_trace & LOG_SNMP_ERRORS))
1822		return;
1823
1824	va_start(ap, err);
1825	snprintf(errbuf, sizeof(errbuf), "SNMP: ");
1826	vsnprintf(errbuf + strlen(errbuf),
1827	    sizeof(errbuf) - strlen(errbuf), err, ap);
1828	va_end(ap);
1829
1830	syslog(LOG_ERR, "%s", errbuf);
1831}
1832
1833static void
1834snmp_debug_func(const char *err, ...)
1835{
1836	char errbuf[1000];
1837	va_list ap;
1838
1839	va_start(ap, err);
1840	snprintf(errbuf, sizeof(errbuf), "SNMP: ");
1841	vsnprintf(errbuf+strlen(errbuf), sizeof(errbuf)-strlen(errbuf),
1842	    err, ap);
1843	va_end(ap);
1844
1845	syslog(LOG_DEBUG, "%s", errbuf);
1846}
1847
1848static void
1849asn_error_func(const struct asn_buf *b, const char *err, ...)
1850{
1851	char errbuf[1000];
1852	va_list ap;
1853	u_int i;
1854
1855	if (!(snmp_trace & LOG_ASN1_ERRORS))
1856		return;
1857
1858	va_start(ap, err);
1859	snprintf(errbuf, sizeof(errbuf), "ASN.1: ");
1860	vsnprintf(errbuf + strlen(errbuf),
1861	    sizeof(errbuf) - strlen(errbuf), err, ap);
1862	va_end(ap);
1863
1864	if (b != NULL) {
1865		snprintf(errbuf + strlen(errbuf),
1866		    sizeof(errbuf) - strlen(errbuf), " at");
1867		for (i = 0; b->asn_len > i; i++)
1868			snprintf(errbuf + strlen(errbuf),
1869			    sizeof(errbuf) - strlen(errbuf),
1870			    " %02x", b->asn_cptr[i]);
1871	}
1872
1873	syslog(LOG_ERR, "%s", errbuf);
1874}
1875
1876/*
1877 * Create a new community
1878 */
1879u_int
1880comm_define(u_int priv, const char *descr, struct lmodule *owner,
1881    const char *str)
1882{
1883	struct community *c, *p;
1884	u_int ncomm;
1885
1886	/* generate an identifier */
1887	do {
1888		if ((ncomm = next_community_index++) == UINT_MAX)
1889			next_community_index = 1;
1890		TAILQ_FOREACH(c, &community_list, link)
1891			if (c->value == ncomm)
1892				break;
1893	} while (c != NULL);
1894
1895	if ((c = malloc(sizeof(struct community))) == NULL) {
1896		syslog(LOG_ERR, "comm_define: %m");
1897		return (0);
1898	}
1899	c->owner = owner;
1900	c->value = ncomm;
1901	c->descr = descr;
1902	c->string = NULL;
1903	c->private = priv;
1904
1905	if (str != NULL) {
1906		if((c->string = malloc(strlen(str)+1)) == NULL) {
1907			free(c);
1908			return (0);
1909		}
1910		strcpy(c->string, str);
1911	}
1912
1913	/* make index */
1914	if (c->owner == NULL) {
1915		c->index.len = 1;
1916		c->index.subs[0] = 0;
1917	} else {
1918		c->index = c->owner->index;
1919	}
1920	c->index.subs[c->index.len++] = c->private;
1921
1922	/*
1923	 * Insert ordered
1924	 */
1925	TAILQ_FOREACH(p, &community_list, link) {
1926		if (asn_compare_oid(&p->index, &c->index) > 0) {
1927			TAILQ_INSERT_BEFORE(p, c, link);
1928			break;
1929		}
1930	}
1931	if (p == NULL)
1932		TAILQ_INSERT_TAIL(&community_list, c, link);
1933	return (c->value);
1934}
1935
1936const char *
1937comm_string(u_int ncomm)
1938{
1939	struct community *p;
1940
1941	TAILQ_FOREACH(p, &community_list, link)
1942		if (p->value == ncomm)
1943			return (p->string);
1944	return (NULL);
1945}
1946
1947/*
1948 * Delete all communities allocated by a module
1949 */
1950static void
1951comm_flush(struct lmodule *mod)
1952{
1953	struct community *p, *p1;
1954
1955	p = TAILQ_FIRST(&community_list);
1956	while (p != NULL) {
1957		p1 = TAILQ_NEXT(p, link);
1958		if (p->owner == mod) {
1959			free(p->string);
1960			TAILQ_REMOVE(&community_list, p, link);
1961			free(p);
1962		}
1963		p = p1;
1964	}
1965}
1966
1967/*
1968 * Request ID handling.
1969 *
1970 * Allocate a new range of request ids. Use a first fit algorithm.
1971 */
1972u_int
1973reqid_allocate(int size, struct lmodule *mod)
1974{
1975	u_int type;
1976	struct idrange *r, *r1;
1977
1978	if (size <= 0 || size > INT32_MAX) {
1979		syslog(LOG_CRIT, "%s: size out of range: %d", __func__, size);
1980		return (0);
1981	}
1982	/* allocate a type id */
1983	do {
1984		if ((type = next_idrange++) == UINT_MAX)
1985			next_idrange = 1;
1986		TAILQ_FOREACH(r, &idrange_list, link)
1987			if (r->type == type)
1988				break;
1989	} while(r != NULL);
1990
1991	/* find a range */
1992	if (TAILQ_EMPTY(&idrange_list))
1993		r = NULL;
1994	else {
1995		r = TAILQ_FIRST(&idrange_list);
1996		if (r->base < size) {
1997			while((r1 = TAILQ_NEXT(r, link)) != NULL) {
1998				if (r1->base - (r->base + r->size) >= size)
1999					break;
2000				r = r1;
2001			}
2002			r = r1;
2003		}
2004		if (r == NULL) {
2005			r1 = TAILQ_LAST(&idrange_list, idrange_list);
2006			if (INT32_MAX - size + 1 < r1->base + r1->size) {
2007				syslog(LOG_ERR, "out of id ranges (%u)", size);
2008				return (0);
2009			}
2010		}
2011	}
2012
2013	/* allocate structure */
2014	if ((r1 = malloc(sizeof(struct idrange))) == NULL) {
2015		syslog(LOG_ERR, "%s: %m", __FUNCTION__);
2016		return (0);
2017	}
2018
2019	r1->type = type;
2020	r1->size = size;
2021	r1->owner = mod;
2022	if (TAILQ_EMPTY(&idrange_list) || r == TAILQ_FIRST(&idrange_list)) {
2023		r1->base = 0;
2024		TAILQ_INSERT_HEAD(&idrange_list, r1, link);
2025	} else if (r == NULL) {
2026		r = TAILQ_LAST(&idrange_list, idrange_list);
2027		r1->base = r->base + r->size;
2028		TAILQ_INSERT_TAIL(&idrange_list, r1, link);
2029	} else {
2030		r = TAILQ_PREV(r, idrange_list, link);
2031		r1->base = r->base + r->size;
2032		TAILQ_INSERT_AFTER(&idrange_list, r, r1, link);
2033	}
2034	r1->next = r1->base;
2035
2036	return (type);
2037}
2038
2039int32_t
2040reqid_next(u_int type)
2041{
2042	struct idrange *r;
2043	int32_t id;
2044
2045	TAILQ_FOREACH(r, &idrange_list, link)
2046		if (r->type == type)
2047			break;
2048	if (r == NULL) {
2049		syslog(LOG_CRIT, "wrong idrange type");
2050		abort();
2051	}
2052	if ((id = r->next++) == r->base + (r->size - 1))
2053		r->next = r->base;
2054	return (id);
2055}
2056
2057int32_t
2058reqid_base(u_int type)
2059{
2060	struct idrange *r;
2061
2062	TAILQ_FOREACH(r, &idrange_list, link)
2063		if (r->type == type)
2064			return (r->base);
2065	syslog(LOG_CRIT, "wrong idrange type");
2066	abort();
2067}
2068
2069u_int
2070reqid_type(int32_t reqid)
2071{
2072	struct idrange *r;
2073
2074	TAILQ_FOREACH(r, &idrange_list, link)
2075		if (reqid >= r->base && reqid <= r->base + (r->size - 1))
2076			return (r->type);
2077	return (0);
2078}
2079
2080int
2081reqid_istype(int32_t reqid, u_int type)
2082{
2083	return (reqid_type(reqid) == type);
2084}
2085
2086/*
2087 * Delete all communities allocated by a module
2088 */
2089static void
2090reqid_flush(struct lmodule *mod)
2091{
2092	struct idrange *p, *p1;
2093
2094	p = TAILQ_FIRST(&idrange_list);
2095	while (p != NULL) {
2096		p1 = TAILQ_NEXT(p, link);
2097		if (p->owner == mod) {
2098			TAILQ_REMOVE(&idrange_list, p, link);
2099			free(p);
2100		}
2101		p = p1;
2102	}
2103}
2104
2105/*
2106 * Merge the given tree for the given module into the main tree.
2107 */
2108static int
2109compare_node(const void *v1, const void *v2)
2110{
2111	const struct snmp_node *n1 = v1;
2112	const struct snmp_node *n2 = v2;
2113
2114	return (asn_compare_oid(&n1->oid, &n2->oid));
2115}
2116static int
2117tree_merge(const struct snmp_node *ntree, u_int nsize, struct lmodule *mod)
2118{
2119	struct snmp_node *xtree;
2120	u_int i;
2121
2122	xtree = realloc(tree, sizeof(*tree) * (tree_size + nsize));
2123	if (xtree == NULL) {
2124		syslog(LOG_ERR, "tree_merge: %m");
2125		return (-1);
2126	}
2127	tree = xtree;
2128	memcpy(&tree[tree_size], ntree, sizeof(*tree) * nsize);
2129
2130	for (i = 0; i < nsize; i++)
2131		tree[tree_size + i].tree_data = mod;
2132
2133	tree_size += nsize;
2134
2135	qsort(tree, tree_size, sizeof(tree[0]), compare_node);
2136
2137	return (0);
2138}
2139
2140/*
2141 * Remove all nodes belonging to the loadable module
2142 */
2143static void
2144tree_unmerge(struct lmodule *mod)
2145{
2146	u_int s, d;
2147
2148	for(s = d = 0; s < tree_size; s++)
2149		if (tree[s].tree_data != mod) {
2150			if (s != d)
2151				tree[d] = tree[s];
2152			d++;
2153		}
2154	tree_size = d;
2155}
2156
2157/*
2158 * Loadable modules
2159 */
2160struct lmodule *
2161lm_load(const char *path, const char *section)
2162{
2163	struct lmodule *m;
2164	int err;
2165	int i;
2166	char *av[MAX_MOD_ARGS + 1];
2167	int ac;
2168	u_int u;
2169
2170	if ((m = malloc(sizeof(*m))) == NULL) {
2171		syslog(LOG_ERR, "lm_load: %m");
2172		return (NULL);
2173	}
2174	m->handle = NULL;
2175	m->flags = 0;
2176	strcpy(m->section, section);
2177
2178	if ((m->path = malloc(strlen(path) + 1)) == NULL) {
2179		syslog(LOG_ERR, "lm_load: %m");
2180		goto err;
2181	}
2182	strcpy(m->path, path);
2183
2184	/*
2185	 * Make index
2186	 */
2187	m->index.subs[0] = strlen(section);
2188	m->index.len = m->index.subs[0] + 1;
2189	for (u = 0; u < m->index.subs[0]; u++)
2190		m->index.subs[u + 1] = section[u];
2191
2192	/*
2193	 * Load the object file and locate the config structure
2194	 */
2195	if ((m->handle = dlopen(m->path, RTLD_NOW|RTLD_GLOBAL)) == NULL) {
2196		syslog(LOG_ERR, "lm_load: open %s", dlerror());
2197		goto err;
2198	}
2199
2200	if ((m->config = dlsym(m->handle, "config")) == NULL) {
2201		syslog(LOG_ERR, "lm_load: no 'config' symbol %s", dlerror());
2202		goto err;
2203	}
2204
2205	/*
2206	 * Insert it into the right place
2207	 */
2208	INSERT_OBJECT_OID(m, &lmodules);
2209
2210	/* preserve order */
2211	if (community == COMM_INITIALIZE) {
2212		m->flags |= LM_ONSTARTLIST;
2213		TAILQ_INSERT_TAIL(&modules_start, m, start);
2214	}
2215
2216	/*
2217	 * make the argument vector.
2218	 */
2219	ac = 0;
2220	for (i = 0; i < nprogargs; i++) {
2221		if (strlen(progargs[i]) >= strlen(section) + 1 &&
2222		    strncmp(progargs[i], section, strlen(section)) == 0 &&
2223		    progargs[i][strlen(section)] == ':') {
2224			if (ac == MAX_MOD_ARGS) {
2225				syslog(LOG_WARNING, "too many arguments for "
2226				    "module '%s", section);
2227				break;
2228			}
2229			av[ac++] = &progargs[i][strlen(section)+1];
2230		}
2231	}
2232	av[ac] = NULL;
2233
2234	/*
2235	 * Run the initialization function
2236	 */
2237	if ((err = (*m->config->init)(m, ac, av)) != 0) {
2238		syslog(LOG_ERR, "lm_load: init failed: %d", err);
2239		TAILQ_REMOVE(&lmodules, m, link);
2240		goto err;
2241	}
2242
2243	return (m);
2244
2245  err:
2246	if (m->handle)
2247		dlclose(m->handle);
2248	free(m->path);
2249	free(m);
2250	return (NULL);
2251}
2252
2253/*
2254 * Start a module
2255 */
2256void
2257lm_start(struct lmodule *mod)
2258{
2259	const struct lmodule *m;
2260
2261	/*
2262	 * Merge tree. If this fails, unload the module.
2263	 */
2264	if (tree_merge(mod->config->tree, mod->config->tree_size, mod)) {
2265		lm_unload(mod);
2266		return;
2267	}
2268
2269	/*
2270	 * Read configuration
2271	 */
2272	if (read_config(config_file, mod)) {
2273		syslog(LOG_ERR, "error in config file");
2274		lm_unload(mod);
2275		return;
2276	}
2277	if (mod->config->start)
2278		(*mod->config->start)();
2279
2280	mod->flags |= LM_STARTED;
2281
2282	/*
2283	 * Inform other modules
2284	 */
2285	TAILQ_FOREACH(m, &lmodules, link)
2286		if (m->config->loading)
2287			(*m->config->loading)(mod, 1);
2288}
2289
2290
2291/*
2292 * Unload a module.
2293 */
2294void
2295lm_unload(struct lmodule *m)
2296{
2297	int err;
2298	const struct lmodule *mod;
2299
2300	TAILQ_REMOVE(&lmodules, m, link);
2301	if (m->flags & LM_ONSTARTLIST)
2302		TAILQ_REMOVE(&modules_start, m, start);
2303	tree_unmerge(m);
2304
2305	if ((m->flags & LM_STARTED) && m->config->fini &&
2306	    (err = (*m->config->fini)()) != 0)
2307		syslog(LOG_WARNING, "lm_unload(%s): fini %d", m->section, err);
2308
2309	comm_flush(m);
2310	reqid_flush(m);
2311	timer_flush(m);
2312	fd_flush(m);
2313
2314	dlclose(m->handle);
2315	free(m->path);
2316
2317	/*
2318	 * Inform other modules
2319	 */
2320	TAILQ_FOREACH(mod, &lmodules, link)
2321		if (mod->config->loading)
2322			(*mod->config->loading)(m, 0);
2323
2324	free(m);
2325}
2326
2327/*
2328 * Register an object resource and return the index (or 0 on failures)
2329 */
2330u_int
2331or_register(const struct asn_oid *or, const char *descr, struct lmodule *mod)
2332{
2333	struct objres *objres, *or1;
2334	u_int idx;
2335
2336	/* find a free index */
2337	idx = 1;
2338	for (objres = TAILQ_FIRST(&objres_list);
2339	     objres != NULL;
2340	     objres = TAILQ_NEXT(objres, link)) {
2341		if ((or1 = TAILQ_NEXT(objres, link)) == NULL ||
2342		    or1->index > objres->index + 1) {
2343			idx = objres->index + 1;
2344			break;
2345		}
2346	}
2347
2348	if ((objres = malloc(sizeof(*objres))) == NULL)
2349		return (0);
2350
2351	objres->index = idx;
2352	objres->oid = *or;
2353	strlcpy(objres->descr, descr, sizeof(objres->descr));
2354	objres->uptime = (uint32_t)(get_ticks() - start_tick);
2355	objres->module = mod;
2356
2357	INSERT_OBJECT_INT(objres, &objres_list);
2358
2359	systemg.or_last_change = objres->uptime;
2360
2361	return (idx);
2362}
2363
2364void
2365or_unregister(u_int idx)
2366{
2367	struct objres *objres;
2368
2369	TAILQ_FOREACH(objres, &objres_list, link)
2370		if (objres->index == idx) {
2371			TAILQ_REMOVE(&objres_list, objres, link);
2372			free(objres);
2373			return;
2374		}
2375}
2376