/contrib/bsnmp/snmpd/main.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 3277 lines · 2434 code · 513 blank · 330 comment · 654 complexity · 0688c8abe78f8fe7c0eac9a3c53b4665 MD5 · raw file

Large files are truncated click here to view the full file

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