xref: /freebsd/contrib/bsnmp/snmpd/main.c (revision 262e143bd46171a6415a5b28af260a5efa2a3db8)
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 
67 uint64_t this_tick;	/* start of processing of current packet (absolute) */
68 uint64_t start_tick;	/* start of processing */
69 
70 struct 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 };
77 struct debug debug = {
78 	0,		/* dump_pdus */
79 	LOG_DEBUG,	/* log_pri */
80 	0,		/* evdebug */
81 };
82 
83 struct 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 };
91 struct snmpd_stats snmpd_stats;
92 
93 /* snmpSerialNo */
94 int32_t snmp_serial_no;
95 
96 /* search path for config files */
97 const char *syspath = PATH_SYSCONFIG;
98 
99 /* list of all loaded modules */
100 struct lmodules lmodules = TAILQ_HEAD_INITIALIZER(lmodules);
101 
102 /* list of loaded modules during start-up in the order they were loaded */
103 static struct lmodules modules_start = TAILQ_HEAD_INITIALIZER(modules_start);
104 
105 /* list of all known communities */
106 struct community_list community_list = TAILQ_HEAD_INITIALIZER(community_list);
107 
108 /* list of all installed object resources */
109 struct objres_list objres_list = TAILQ_HEAD_INITIALIZER(objres_list);
110 
111 /* community value generator */
112 static u_int next_community_index = 1;
113 
114 /* list of all known ranges */
115 struct idrange_list idrange_list = TAILQ_HEAD_INITIALIZER(idrange_list);
116 
117 /* identifier generator */
118 u_int next_idrange = 1;
119 
120 /* list of all current timers */
121 struct timer_list timer_list = LIST_HEAD_INITIALIZER(timer_list);
122 
123 /* list of file descriptors */
124 struct fdesc_list fdesc_list = LIST_HEAD_INITIALIZER(fdesc_list);
125 
126 /* program arguments */
127 static char **progargs;
128 static int nprogargs;
129 
130 /* current community */
131 u_int	community;
132 static struct community *comm;
133 
134 /* file names */
135 static char config_file[MAXPATHLEN + 1];
136 static char pid_file[MAXPATHLEN + 1];
137 
138 #ifndef USE_LIBBEGEMOT
139 /* event context */
140 static evContext evctx;
141 #endif
142 
143 /* signal mask */
144 static sigset_t blocked_sigs;
145 
146 /* signal handling */
147 static int work;
148 #define	WORK_DOINFO	0x0001
149 #define	WORK_RECONFIG	0x0002
150 
151 /* oids */
152 static 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 
158 const struct asn_oid oid_zeroDotZero = { 2, { 0, 0 }};
159 
160 /* request id generator for traps */
161 u_int trap_reqid;
162 
163 /* help text */
164 static const char usgtxt[] = "\
165 Begemot simple SNMP daemon. Copyright (c) 2001-2002 Fraunhofer Institute for\n\
166 Open Communication Systems (FhG Fokus). All rights reserved.\n\
167 usage: snmpd [-dh] [-c file] [-D options] [-I path] [-l prefix]\n\
168              [-m variable=value] [-p file]\n\
169 options:\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
182 static struct request_info req;
183 #endif
184 
185 /* transports */
186 extern const struct transport_def udp_trans;
187 extern const struct transport_def lsock_trans;
188 
189 struct transport_list transport_list = TAILQ_HEAD_INITIALIZER(transport_list);
190 
191 /* forward declarations */
192 static void snmp_printf_func(const char *fmt, ...);
193 static void snmp_error_func(const char *err, ...);
194 static void snmp_debug_func(const char *err, ...);
195 static 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  */
200 void *
201 buf_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  */
219 size_t
220 buf_size(int tx)
221 {
222 	return (tx ? snmpd.txbuf : snmpd.rxbuf);
223 }
224 
225 /*
226  * Prepare a PDU for output
227  */
228 void
229 snmp_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  */
251 enum snmpd_input_err
252 snmp_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  */
357 enum snmpd_input_err
358 snmp_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  */
463 void
464 trans_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  */
481 void
482 trans_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  */
491 struct tport *
492 trans_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  */
501 struct tport *
502 trans_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  */
511 struct tport *
512 trans_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  */
521 struct tport *
522 trans_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  */
536 int
537 trans_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  */
575 int
576 trans_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
591 static void
592 input(int fd, int mask __unused, void *uap)
593 #else
594 static void
595 input(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 
603 void
604 fd_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 
621 int
622 fd_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 
649 void *
650 fd_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 
683 void
684 fd_deselect(void *p)
685 {
686 	struct fdesc *f = p;
687 
688 	LIST_REMOVE(f, link);
689 	fd_suspend(f);
690 	free(f);
691 }
692 
693 static void
694 fd_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  */
710 static void
711 snmp_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 
727 struct credmsg {
728 	struct cmsghdr hdr;
729 	struct cmsgcred cred;
730 };
731 
732 static void
733 check_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  */
760 static int
761 recv_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  */
819 static int
820 recv_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  */
886 int
887 snmpd_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  */
1064 void
1065 snmp_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  */
1100 void
1101 snmpd_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
1115 static void
1116 info_func(void)
1117 #else
1118 static void
1119 info_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
1152 static void
1153 config_func(void)
1154 #else
1155 static void
1156 config_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  */
1174 static void
1175 onusr1(int s __unused)
1176 {
1177 
1178 	work |= WORK_DOINFO;
1179 }
1180 static void
1181 onhup(int s __unused)
1182 {
1183 
1184 	work |= WORK_RECONFIG;
1185 }
1186 
1187 static void
1188 onterm(int s __unused)
1189 {
1190 
1191 	/* allow clean-up */
1192 	exit(0);
1193 }
1194 
1195 static void
1196 init_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 
1227 static void
1228 block_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 }
1238 static void
1239 unblock_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  */
1250 static void
1251 term(void)
1252 {
1253 	(void)unlink(pid_file);
1254 }
1255 
1256 static void
1257 trans_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  */
1268 static void
1269 do_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  */
1290 static int
1291 getsubopt1(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 
1334 int
1335 main(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, "public");
1466 	(void)comm_define(2, "SNMP write", NULL, "public");
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 
1604 uint64_t
1605 get_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
1624 static void
1625 tfunc(int tid __unused, void *uap)
1626 #else
1627 static void
1628 tfunc(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
1643 static void
1644 trfunc(int tid __unused, void *uap)
1645 #else
1646 static void
1647 trfunc(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  */
1659 void *
1660 timer_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  */
1703 void *
1704 timer_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  */
1747 void
1748 timer_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 
1764 static void
1765 timer_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 
1778 static void
1779 snmp_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 
1815 static void
1816 snmp_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 
1833 static void
1834 snmp_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 
1848 static void
1849 asn_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  */
1879 u_int
1880 comm_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 
1936 const char *
1937 comm_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  */
1950 static void
1951 comm_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  */
1972 u_int
1973 reqid_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 
2039 int32_t
2040 reqid_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 
2057 int32_t
2058 reqid_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 
2069 u_int
2070 reqid_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 
2080 int
2081 reqid_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  */
2089 static void
2090 reqid_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  */
2108 static int
2109 compare_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 }
2116 static int
2117 tree_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  */
2143 static void
2144 tree_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  */
2160 struct lmodule *
2161 lm_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  */
2256 void
2257 lm_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  */
2294 void
2295 lm_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  */
2330 u_int
2331 or_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 
2364 void
2365 or_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