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