PageRenderTime 80ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/src/network.c

https://github.com/DavidS/collectd
C | 3507 lines | 2716 code | 529 blank | 262 comment | 654 complexity | 607c71a19769115269c945ec0b832e79 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /**
  2. * collectd - src/network.c
  3. * Copyright (C) 2005-2013 Florian octo Forster
  4. * Copyright (C) 2009 Aman Gupta
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation; only version 2.1 of the License is
  9. * applicable.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. * Authors:
  21. * Florian octo Forster <octo at collectd.org>
  22. * Aman Gupta <aman at tmm1.net>
  23. **/
  24. #define _BSD_SOURCE /* For struct ip_mreq */
  25. #include "collectd.h"
  26. #include "plugin.h"
  27. #include "common.h"
  28. #include "configfile.h"
  29. #include "utils_fbhash.h"
  30. #include "utils_avltree.h"
  31. #include "utils_cache.h"
  32. #include "utils_complain.h"
  33. #include "network.h"
  34. #if HAVE_PTHREAD_H
  35. # include <pthread.h>
  36. #endif
  37. #if HAVE_SYS_SOCKET_H
  38. # include <sys/socket.h>
  39. #endif
  40. #if HAVE_NETDB_H
  41. # include <netdb.h>
  42. #endif
  43. #if HAVE_NETINET_IN_H
  44. # include <netinet/in.h>
  45. #endif
  46. #if HAVE_ARPA_INET_H
  47. # include <arpa/inet.h>
  48. #endif
  49. #if HAVE_POLL_H
  50. # include <poll.h>
  51. #endif
  52. #if HAVE_NET_IF_H
  53. # include <net/if.h>
  54. #endif
  55. #if HAVE_LIBGCRYPT
  56. # include <pthread.h>
  57. # if defined __APPLE__
  58. /* default xcode compiler throws warnings even when deprecated functionality
  59. * is not used. -Werror breaks the build because of erroneous warnings.
  60. * http://stackoverflow.com/questions/10556299/compiler-warnings-with-libgcrypt-v1-5-0/12830209#12830209
  61. */
  62. # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  63. # endif
  64. /* FreeBSD's copy of libgcrypt extends the existing GCRYPT_NO_DEPRECATED
  65. * to properly hide all deprecated functionality.
  66. * http://svnweb.freebsd.org/ports/head/security/libgcrypt/files/patch-src__gcrypt.h.in
  67. */
  68. # define GCRYPT_NO_DEPRECATED
  69. # include <gcrypt.h>
  70. # if defined __APPLE__
  71. /* Re enable deprecation warnings */
  72. # pragma GCC diagnostic warning "-Wdeprecated-declarations"
  73. # endif
  74. GCRY_THREAD_OPTION_PTHREAD_IMPL;
  75. #endif
  76. #ifndef IPV6_ADD_MEMBERSHIP
  77. # ifdef IPV6_JOIN_GROUP
  78. # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
  79. # else
  80. # error "Neither IP_ADD_MEMBERSHIP nor IPV6_JOIN_GROUP is defined"
  81. # endif
  82. #endif /* !IP_ADD_MEMBERSHIP */
  83. /*
  84. * Maximum size required for encryption / signing:
  85. *
  86. * 42 bytes for the encryption header
  87. * + 64 bytes for the username
  88. * -----------
  89. * = 106 bytes
  90. */
  91. #define BUFF_SIG_SIZE 106
  92. /*
  93. * Private data types
  94. */
  95. #define SECURITY_LEVEL_NONE 0
  96. #if HAVE_LIBGCRYPT
  97. # define SECURITY_LEVEL_SIGN 1
  98. # define SECURITY_LEVEL_ENCRYPT 2
  99. #endif
  100. struct sockent_client
  101. {
  102. int fd;
  103. struct sockaddr_storage *addr;
  104. socklen_t addrlen;
  105. #if HAVE_LIBGCRYPT
  106. int security_level;
  107. char *username;
  108. char *password;
  109. gcry_cipher_hd_t cypher;
  110. unsigned char password_hash[32];
  111. #endif
  112. };
  113. struct sockent_server
  114. {
  115. int *fd;
  116. size_t fd_num;
  117. #if HAVE_LIBGCRYPT
  118. int security_level;
  119. char *auth_file;
  120. fbhash_t *userdb;
  121. gcry_cipher_hd_t cypher;
  122. #endif
  123. };
  124. typedef struct sockent
  125. {
  126. #define SOCKENT_TYPE_CLIENT 1
  127. #define SOCKENT_TYPE_SERVER 2
  128. int type;
  129. char *node;
  130. char *service;
  131. int interface;
  132. union
  133. {
  134. struct sockent_client client;
  135. struct sockent_server server;
  136. } data;
  137. struct sockent *next;
  138. } sockent_t;
  139. /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
  140. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  141. * +-------+-----------------------+-------------------------------+
  142. * ! Ver. ! ! Length !
  143. * +-------+-----------------------+-------------------------------+
  144. */
  145. struct part_header_s
  146. {
  147. uint16_t type;
  148. uint16_t length;
  149. };
  150. typedef struct part_header_s part_header_t;
  151. /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
  152. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  153. * +-------------------------------+-------------------------------+
  154. * ! Type ! Length !
  155. * +-------------------------------+-------------------------------+
  156. * : (Length - 4) Bytes :
  157. * +---------------------------------------------------------------+
  158. */
  159. struct part_string_s
  160. {
  161. part_header_t *head;
  162. char *value;
  163. };
  164. typedef struct part_string_s part_string_t;
  165. /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
  166. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  167. * +-------------------------------+-------------------------------+
  168. * ! Type ! Length !
  169. * +-------------------------------+-------------------------------+
  170. * : (Length - 4 == 2 || 4 || 8) Bytes :
  171. * +---------------------------------------------------------------+
  172. */
  173. struct part_number_s
  174. {
  175. part_header_t *head;
  176. uint64_t *value;
  177. };
  178. typedef struct part_number_s part_number_t;
  179. /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
  180. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  181. * +-------------------------------+-------------------------------+
  182. * ! Type ! Length !
  183. * +-------------------------------+---------------+---------------+
  184. * ! Num of values ! Type0 ! Type1 !
  185. * +-------------------------------+---------------+---------------+
  186. * ! Value0 !
  187. * ! !
  188. * +---------------------------------------------------------------+
  189. * ! Value1 !
  190. * ! !
  191. * +---------------------------------------------------------------+
  192. */
  193. struct part_values_s
  194. {
  195. part_header_t *head;
  196. uint16_t *num_values;
  197. uint8_t *values_types;
  198. value_t *values;
  199. };
  200. typedef struct part_values_s part_values_t;
  201. /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
  202. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  203. * +-------------------------------+-------------------------------+
  204. * ! Type ! Length !
  205. * +-------------------------------+-------------------------------+
  206. * ! Hash (Bits 0 - 31) !
  207. * : : :
  208. * ! Hash (Bits 224 - 255) !
  209. * +---------------------------------------------------------------+
  210. */
  211. /* Minimum size */
  212. #define PART_SIGNATURE_SHA256_SIZE 36
  213. struct part_signature_sha256_s
  214. {
  215. part_header_t head;
  216. unsigned char hash[32];
  217. char *username;
  218. };
  219. typedef struct part_signature_sha256_s part_signature_sha256_t;
  220. /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
  221. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  222. * +-------------------------------+-------------------------------+
  223. * ! Type ! Length !
  224. * +-------------------------------+-------------------------------+
  225. * ! Original length ! Padding (0 - 15 bytes) !
  226. * +-------------------------------+-------------------------------+
  227. * ! Hash (Bits 0 - 31) !
  228. * : : :
  229. * ! Hash (Bits 128 - 159) !
  230. * +---------------------------------------------------------------+
  231. */
  232. /* Minimum size */
  233. #define PART_ENCRYPTION_AES256_SIZE 42
  234. struct part_encryption_aes256_s
  235. {
  236. part_header_t head;
  237. uint16_t username_length;
  238. char *username;
  239. unsigned char iv[16];
  240. /* <encrypted> */
  241. unsigned char hash[20];
  242. /* <payload /> */
  243. /* </encrypted> */
  244. };
  245. typedef struct part_encryption_aes256_s part_encryption_aes256_t;
  246. struct receive_list_entry_s
  247. {
  248. char *data;
  249. int data_len;
  250. int fd;
  251. struct receive_list_entry_s *next;
  252. };
  253. typedef struct receive_list_entry_s receive_list_entry_t;
  254. /*
  255. * Private variables
  256. */
  257. static int network_config_ttl = 0;
  258. /* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */
  259. static size_t network_config_packet_size = 1452;
  260. static int network_config_forward = 0;
  261. static int network_config_stats = 0;
  262. static sockent_t *sending_sockets = NULL;
  263. static receive_list_entry_t *receive_list_head = NULL;
  264. static receive_list_entry_t *receive_list_tail = NULL;
  265. static pthread_mutex_t receive_list_lock = PTHREAD_MUTEX_INITIALIZER;
  266. static pthread_cond_t receive_list_cond = PTHREAD_COND_INITIALIZER;
  267. static uint64_t receive_list_length = 0;
  268. static sockent_t *listen_sockets = NULL;
  269. static struct pollfd *listen_sockets_pollfd = NULL;
  270. static size_t listen_sockets_num = 0;
  271. /* The receive and dispatch threads will run as long as `listen_loop' is set to
  272. * zero. */
  273. static int listen_loop = 0;
  274. static int receive_thread_running = 0;
  275. static pthread_t receive_thread_id;
  276. static int dispatch_thread_running = 0;
  277. static pthread_t dispatch_thread_id;
  278. /* Buffer in which to-be-sent network packets are constructed. */
  279. static char *send_buffer;
  280. static char *send_buffer_ptr;
  281. static int send_buffer_fill;
  282. static value_list_t send_buffer_vl = VALUE_LIST_STATIC;
  283. static pthread_mutex_t send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
  284. /* XXX: These counters are incremented from one place only. The spot in which
  285. * the values are incremented is either only reachable by one thread (the
  286. * dispatch thread, for example) or locked by some lock (send_buffer_lock for
  287. * example). Only if neither is true, the stats_lock is acquired. The counters
  288. * are always read without holding a lock in the hope that writing 8 bytes to
  289. * memory is an atomic operation. */
  290. static derive_t stats_octets_rx = 0;
  291. static derive_t stats_octets_tx = 0;
  292. static derive_t stats_packets_rx = 0;
  293. static derive_t stats_packets_tx = 0;
  294. static derive_t stats_values_dispatched = 0;
  295. static derive_t stats_values_not_dispatched = 0;
  296. static derive_t stats_values_sent = 0;
  297. static derive_t stats_values_not_sent = 0;
  298. static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
  299. /*
  300. * Private functions
  301. */
  302. static _Bool check_receive_okay (const value_list_t *vl) /* {{{ */
  303. {
  304. uint64_t time_sent = 0;
  305. int status;
  306. status = uc_meta_data_get_unsigned_int (vl,
  307. "network:time_sent", &time_sent);
  308. /* This is a value we already sent. Don't allow it to be received again in
  309. * order to avoid looping. */
  310. if ((status == 0) && (time_sent >= ((uint64_t) vl->time)))
  311. return (0);
  312. return (1);
  313. } /* }}} _Bool check_receive_okay */
  314. static _Bool check_send_okay (const value_list_t *vl) /* {{{ */
  315. {
  316. _Bool received = 0;
  317. int status;
  318. if (network_config_forward != 0)
  319. return (1);
  320. if (vl->meta == NULL)
  321. return (1);
  322. status = meta_data_get_boolean (vl->meta, "network:received", &received);
  323. if (status == -ENOENT)
  324. return (1);
  325. else if (status != 0)
  326. {
  327. ERROR ("network plugin: check_send_okay: meta_data_get_boolean failed "
  328. "with status %i.", status);
  329. return (1);
  330. }
  331. /* By default, only *send* value lists that were not *received* by the
  332. * network plugin. */
  333. return (!received);
  334. } /* }}} _Bool check_send_okay */
  335. static _Bool check_notify_received (const notification_t *n) /* {{{ */
  336. {
  337. notification_meta_t *ptr;
  338. for (ptr = n->meta; ptr != NULL; ptr = ptr->next)
  339. if ((strcmp ("network:received", ptr->name) == 0)
  340. && (ptr->type == NM_TYPE_BOOLEAN))
  341. return ((_Bool) ptr->nm_value.nm_boolean);
  342. return (0);
  343. } /* }}} _Bool check_notify_received */
  344. static _Bool check_send_notify_okay (const notification_t *n) /* {{{ */
  345. {
  346. static c_complain_t complain_forwarding = C_COMPLAIN_INIT_STATIC;
  347. _Bool received = 0;
  348. if (n->meta == NULL)
  349. return (1);
  350. received = check_notify_received (n);
  351. if (network_config_forward && received)
  352. {
  353. c_complain_once (LOG_ERR, &complain_forwarding,
  354. "network plugin: A notification has been received via the network "
  355. "forwarding if enabled. Forwarding of notifications is currently "
  356. "not supported, because there is not loop-deteciton available. "
  357. "Please contact the collectd mailing list if you need this "
  358. "feature.");
  359. }
  360. /* By default, only *send* value lists that were not *received* by the
  361. * network plugin. */
  362. return (!received);
  363. } /* }}} _Bool check_send_notify_okay */
  364. static int network_dispatch_values (value_list_t *vl, /* {{{ */
  365. const char *username)
  366. {
  367. int status;
  368. if ((vl->time <= 0)
  369. || (strlen (vl->host) <= 0)
  370. || (strlen (vl->plugin) <= 0)
  371. || (strlen (vl->type) <= 0))
  372. return (-EINVAL);
  373. if (!check_receive_okay (vl))
  374. {
  375. #if COLLECT_DEBUG
  376. char name[6*DATA_MAX_NAME_LEN];
  377. FORMAT_VL (name, sizeof (name), vl);
  378. name[sizeof (name) - 1] = 0;
  379. DEBUG ("network plugin: network_dispatch_values: "
  380. "NOT dispatching %s.", name);
  381. #endif
  382. stats_values_not_dispatched++;
  383. return (0);
  384. }
  385. assert (vl->meta == NULL);
  386. vl->meta = meta_data_create ();
  387. if (vl->meta == NULL)
  388. {
  389. ERROR ("network plugin: meta_data_create failed.");
  390. return (-ENOMEM);
  391. }
  392. status = meta_data_add_boolean (vl->meta, "network:received", 1);
  393. if (status != 0)
  394. {
  395. ERROR ("network plugin: meta_data_add_boolean failed.");
  396. meta_data_destroy (vl->meta);
  397. vl->meta = NULL;
  398. return (status);
  399. }
  400. if (username != NULL)
  401. {
  402. status = meta_data_add_string (vl->meta, "network:username", username);
  403. if (status != 0)
  404. {
  405. ERROR ("network plugin: meta_data_add_string failed.");
  406. meta_data_destroy (vl->meta);
  407. vl->meta = NULL;
  408. return (status);
  409. }
  410. }
  411. plugin_dispatch_values (vl);
  412. stats_values_dispatched++;
  413. meta_data_destroy (vl->meta);
  414. vl->meta = NULL;
  415. return (0);
  416. } /* }}} int network_dispatch_values */
  417. static int network_dispatch_notification (notification_t *n) /* {{{ */
  418. {
  419. int status;
  420. assert (n->meta == NULL);
  421. status = plugin_notification_meta_add_boolean (n, "network:received", 1);
  422. if (status != 0)
  423. {
  424. ERROR ("network plugin: plugin_notification_meta_add_boolean failed.");
  425. plugin_notification_meta_free (n->meta);
  426. n->meta = NULL;
  427. return (status);
  428. }
  429. status = plugin_dispatch_notification (n);
  430. plugin_notification_meta_free (n->meta);
  431. n->meta = NULL;
  432. return (status);
  433. } /* }}} int network_dispatch_notification */
  434. #if HAVE_LIBGCRYPT
  435. static void network_init_gcrypt (void) /* {{{ */
  436. {
  437. /* http://lists.gnupg.org/pipermail/gcrypt-devel/2003-August/000458.html
  438. * Because you can't know in a library whether another library has
  439. * already initialized the library */
  440. if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P))
  441. return;
  442. gcry_check_version (NULL); /* before calling any other functions */
  443. gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
  444. gcry_control (GCRYCTL_INIT_SECMEM, 32768);
  445. gcry_control (GCRYCTL_INITIALIZATION_FINISHED);
  446. } /* }}} void network_init_gcrypt */
  447. static gcry_cipher_hd_t network_get_aes256_cypher (sockent_t *se, /* {{{ */
  448. const void *iv, size_t iv_size, const char *username)
  449. {
  450. gcry_error_t err;
  451. gcry_cipher_hd_t *cyper_ptr;
  452. unsigned char password_hash[32];
  453. if (se->type == SOCKENT_TYPE_CLIENT)
  454. {
  455. cyper_ptr = &se->data.client.cypher;
  456. memcpy (password_hash, se->data.client.password_hash,
  457. sizeof (password_hash));
  458. }
  459. else
  460. {
  461. char *secret;
  462. cyper_ptr = &se->data.server.cypher;
  463. if (username == NULL)
  464. return (NULL);
  465. secret = fbh_get (se->data.server.userdb, username);
  466. if (secret == NULL)
  467. return (NULL);
  468. gcry_md_hash_buffer (GCRY_MD_SHA256,
  469. password_hash,
  470. secret, strlen (secret));
  471. sfree (secret);
  472. }
  473. if (*cyper_ptr == NULL)
  474. {
  475. err = gcry_cipher_open (cyper_ptr,
  476. GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB, /* flags = */ 0);
  477. if (err != 0)
  478. {
  479. ERROR ("network plugin: gcry_cipher_open returned: %s",
  480. gcry_strerror (err));
  481. *cyper_ptr = NULL;
  482. return (NULL);
  483. }
  484. }
  485. else
  486. {
  487. gcry_cipher_reset (*cyper_ptr);
  488. }
  489. assert (*cyper_ptr != NULL);
  490. err = gcry_cipher_setkey (*cyper_ptr,
  491. password_hash, sizeof (password_hash));
  492. if (err != 0)
  493. {
  494. ERROR ("network plugin: gcry_cipher_setkey returned: %s",
  495. gcry_strerror (err));
  496. gcry_cipher_close (*cyper_ptr);
  497. *cyper_ptr = NULL;
  498. return (NULL);
  499. }
  500. err = gcry_cipher_setiv (*cyper_ptr, iv, iv_size);
  501. if (err != 0)
  502. {
  503. ERROR ("network plugin: gcry_cipher_setkey returned: %s",
  504. gcry_strerror (err));
  505. gcry_cipher_close (*cyper_ptr);
  506. *cyper_ptr = NULL;
  507. return (NULL);
  508. }
  509. return (*cyper_ptr);
  510. } /* }}} int network_get_aes256_cypher */
  511. #endif /* HAVE_LIBGCRYPT */
  512. static int write_part_values (char **ret_buffer, int *ret_buffer_len,
  513. const data_set_t *ds, const value_list_t *vl)
  514. {
  515. char *packet_ptr;
  516. int packet_len;
  517. int num_values;
  518. part_header_t pkg_ph;
  519. uint16_t pkg_num_values;
  520. uint8_t *pkg_values_types;
  521. value_t *pkg_values;
  522. int offset;
  523. int i;
  524. num_values = vl->values_len;
  525. packet_len = sizeof (part_header_t) + sizeof (uint16_t)
  526. + (num_values * sizeof (uint8_t))
  527. + (num_values * sizeof (value_t));
  528. if (*ret_buffer_len < packet_len)
  529. return (-1);
  530. pkg_values_types = (uint8_t *) malloc (num_values * sizeof (uint8_t));
  531. if (pkg_values_types == NULL)
  532. {
  533. ERROR ("network plugin: write_part_values: malloc failed.");
  534. return (-1);
  535. }
  536. pkg_values = (value_t *) malloc (num_values * sizeof (value_t));
  537. if (pkg_values == NULL)
  538. {
  539. free (pkg_values_types);
  540. ERROR ("network plugin: write_part_values: malloc failed.");
  541. return (-1);
  542. }
  543. pkg_ph.type = htons (TYPE_VALUES);
  544. pkg_ph.length = htons (packet_len);
  545. pkg_num_values = htons ((uint16_t) vl->values_len);
  546. for (i = 0; i < num_values; i++)
  547. {
  548. pkg_values_types[i] = (uint8_t) ds->ds[i].type;
  549. switch (ds->ds[i].type)
  550. {
  551. case DS_TYPE_COUNTER:
  552. pkg_values[i].counter = htonll (vl->values[i].counter);
  553. break;
  554. case DS_TYPE_GAUGE:
  555. pkg_values[i].gauge = htond (vl->values[i].gauge);
  556. break;
  557. case DS_TYPE_DERIVE:
  558. pkg_values[i].derive = htonll (vl->values[i].derive);
  559. break;
  560. case DS_TYPE_ABSOLUTE:
  561. pkg_values[i].absolute = htonll (vl->values[i].absolute);
  562. break;
  563. default:
  564. free (pkg_values_types);
  565. free (pkg_values);
  566. ERROR ("network plugin: write_part_values: "
  567. "Unknown data source type: %i",
  568. ds->ds[i].type);
  569. return (-1);
  570. } /* switch (ds->ds[i].type) */
  571. } /* for (num_values) */
  572. /*
  573. * Use `memcpy' to write everything to the buffer, because the pointer
  574. * may be unaligned and some architectures, such as SPARC, can't handle
  575. * that.
  576. */
  577. packet_ptr = *ret_buffer;
  578. offset = 0;
  579. memcpy (packet_ptr + offset, &pkg_ph, sizeof (pkg_ph));
  580. offset += sizeof (pkg_ph);
  581. memcpy (packet_ptr + offset, &pkg_num_values, sizeof (pkg_num_values));
  582. offset += sizeof (pkg_num_values);
  583. memcpy (packet_ptr + offset, pkg_values_types, num_values * sizeof (uint8_t));
  584. offset += num_values * sizeof (uint8_t);
  585. memcpy (packet_ptr + offset, pkg_values, num_values * sizeof (value_t));
  586. offset += num_values * sizeof (value_t);
  587. assert (offset == packet_len);
  588. *ret_buffer = packet_ptr + packet_len;
  589. *ret_buffer_len -= packet_len;
  590. free (pkg_values_types);
  591. free (pkg_values);
  592. return (0);
  593. } /* int write_part_values */
  594. static int write_part_number (char **ret_buffer, int *ret_buffer_len,
  595. int type, uint64_t value)
  596. {
  597. char *packet_ptr;
  598. int packet_len;
  599. part_header_t pkg_head;
  600. uint64_t pkg_value;
  601. int offset;
  602. packet_len = sizeof (pkg_head) + sizeof (pkg_value);
  603. if (*ret_buffer_len < packet_len)
  604. return (-1);
  605. pkg_head.type = htons (type);
  606. pkg_head.length = htons (packet_len);
  607. pkg_value = htonll (value);
  608. packet_ptr = *ret_buffer;
  609. offset = 0;
  610. memcpy (packet_ptr + offset, &pkg_head, sizeof (pkg_head));
  611. offset += sizeof (pkg_head);
  612. memcpy (packet_ptr + offset, &pkg_value, sizeof (pkg_value));
  613. offset += sizeof (pkg_value);
  614. assert (offset == packet_len);
  615. *ret_buffer = packet_ptr + packet_len;
  616. *ret_buffer_len -= packet_len;
  617. return (0);
  618. } /* int write_part_number */
  619. static int write_part_string (char **ret_buffer, int *ret_buffer_len,
  620. int type, const char *str, int str_len)
  621. {
  622. char *buffer;
  623. int buffer_len;
  624. uint16_t pkg_type;
  625. uint16_t pkg_length;
  626. int offset;
  627. buffer_len = 2 * sizeof (uint16_t) + str_len + 1;
  628. if (*ret_buffer_len < buffer_len)
  629. return (-1);
  630. pkg_type = htons (type);
  631. pkg_length = htons (buffer_len);
  632. buffer = *ret_buffer;
  633. offset = 0;
  634. memcpy (buffer + offset, (void *) &pkg_type, sizeof (pkg_type));
  635. offset += sizeof (pkg_type);
  636. memcpy (buffer + offset, (void *) &pkg_length, sizeof (pkg_length));
  637. offset += sizeof (pkg_length);
  638. memcpy (buffer + offset, str, str_len);
  639. offset += str_len;
  640. memset (buffer + offset, '\0', 1);
  641. offset += 1;
  642. assert (offset == buffer_len);
  643. *ret_buffer = buffer + buffer_len;
  644. *ret_buffer_len -= buffer_len;
  645. return (0);
  646. } /* int write_part_string */
  647. static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
  648. value_t **ret_values, int *ret_num_values)
  649. {
  650. char *buffer = *ret_buffer;
  651. size_t buffer_len = *ret_buffer_len;
  652. uint16_t tmp16;
  653. size_t exp_size;
  654. int i;
  655. uint16_t pkg_length;
  656. uint16_t pkg_type;
  657. uint16_t pkg_numval;
  658. uint8_t *pkg_types;
  659. value_t *pkg_values;
  660. if (buffer_len < 15)
  661. {
  662. NOTICE ("network plugin: packet is too short: "
  663. "buffer_len = %zu", buffer_len);
  664. return (-1);
  665. }
  666. memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
  667. buffer += sizeof (tmp16);
  668. pkg_type = ntohs (tmp16);
  669. memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
  670. buffer += sizeof (tmp16);
  671. pkg_length = ntohs (tmp16);
  672. memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
  673. buffer += sizeof (tmp16);
  674. pkg_numval = ntohs (tmp16);
  675. assert (pkg_type == TYPE_VALUES);
  676. exp_size = 3 * sizeof (uint16_t)
  677. + pkg_numval * (sizeof (uint8_t) + sizeof (value_t));
  678. if (buffer_len < exp_size)
  679. {
  680. WARNING ("network plugin: parse_part_values: "
  681. "Packet too short: "
  682. "Chunk of size %zu expected, "
  683. "but buffer has only %zu bytes left.",
  684. exp_size, buffer_len);
  685. return (-1);
  686. }
  687. if (pkg_length != exp_size)
  688. {
  689. WARNING ("network plugin: parse_part_values: "
  690. "Length and number of values "
  691. "in the packet don't match.");
  692. return (-1);
  693. }
  694. pkg_types = (uint8_t *) malloc (pkg_numval * sizeof (uint8_t));
  695. pkg_values = (value_t *) malloc (pkg_numval * sizeof (value_t));
  696. if ((pkg_types == NULL) || (pkg_values == NULL))
  697. {
  698. sfree (pkg_types);
  699. sfree (pkg_values);
  700. ERROR ("network plugin: parse_part_values: malloc failed.");
  701. return (-1);
  702. }
  703. memcpy ((void *) pkg_types, (void *) buffer, pkg_numval * sizeof (uint8_t));
  704. buffer += pkg_numval * sizeof (uint8_t);
  705. memcpy ((void *) pkg_values, (void *) buffer, pkg_numval * sizeof (value_t));
  706. buffer += pkg_numval * sizeof (value_t);
  707. for (i = 0; i < pkg_numval; i++)
  708. {
  709. switch (pkg_types[i])
  710. {
  711. case DS_TYPE_COUNTER:
  712. pkg_values[i].counter = (counter_t) ntohll (pkg_values[i].counter);
  713. break;
  714. case DS_TYPE_GAUGE:
  715. pkg_values[i].gauge = (gauge_t) ntohd (pkg_values[i].gauge);
  716. break;
  717. case DS_TYPE_DERIVE:
  718. pkg_values[i].derive = (derive_t) ntohll (pkg_values[i].derive);
  719. break;
  720. case DS_TYPE_ABSOLUTE:
  721. pkg_values[i].absolute = (absolute_t) ntohll (pkg_values[i].absolute);
  722. break;
  723. default:
  724. NOTICE ("network plugin: parse_part_values: "
  725. "Don't know how to handle data source type %"PRIu8,
  726. pkg_types[i]);
  727. sfree (pkg_types);
  728. sfree (pkg_values);
  729. return (-1);
  730. } /* switch (pkg_types[i]) */
  731. }
  732. *ret_buffer = buffer;
  733. *ret_buffer_len = buffer_len - pkg_length;
  734. *ret_num_values = pkg_numval;
  735. *ret_values = pkg_values;
  736. sfree (pkg_types);
  737. return (0);
  738. } /* int parse_part_values */
  739. static int parse_part_number (void **ret_buffer, size_t *ret_buffer_len,
  740. uint64_t *value)
  741. {
  742. char *buffer = *ret_buffer;
  743. size_t buffer_len = *ret_buffer_len;
  744. uint16_t tmp16;
  745. uint64_t tmp64;
  746. size_t exp_size = 2 * sizeof (uint16_t) + sizeof (uint64_t);
  747. uint16_t pkg_length;
  748. if (buffer_len < exp_size)
  749. {
  750. WARNING ("network plugin: parse_part_number: "
  751. "Packet too short: "
  752. "Chunk of size %zu expected, "
  753. "but buffer has only %zu bytes left.",
  754. exp_size, buffer_len);
  755. return (-1);
  756. }
  757. memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
  758. buffer += sizeof (tmp16);
  759. /* pkg_type = ntohs (tmp16); */
  760. memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
  761. buffer += sizeof (tmp16);
  762. pkg_length = ntohs (tmp16);
  763. memcpy ((void *) &tmp64, buffer, sizeof (tmp64));
  764. buffer += sizeof (tmp64);
  765. *value = ntohll (tmp64);
  766. *ret_buffer = buffer;
  767. *ret_buffer_len = buffer_len - pkg_length;
  768. return (0);
  769. } /* int parse_part_number */
  770. static int parse_part_string (void **ret_buffer, size_t *ret_buffer_len,
  771. char *output, int output_len)
  772. {
  773. char *buffer = *ret_buffer;
  774. size_t buffer_len = *ret_buffer_len;
  775. uint16_t tmp16;
  776. size_t header_size = 2 * sizeof (uint16_t);
  777. uint16_t pkg_length;
  778. if (buffer_len < header_size)
  779. {
  780. WARNING ("network plugin: parse_part_string: "
  781. "Packet too short: "
  782. "Chunk of at least size %zu expected, "
  783. "but buffer has only %zu bytes left.",
  784. header_size, buffer_len);
  785. return (-1);
  786. }
  787. memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
  788. buffer += sizeof (tmp16);
  789. /* pkg_type = ntohs (tmp16); */
  790. memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
  791. buffer += sizeof (tmp16);
  792. pkg_length = ntohs (tmp16);
  793. /* Check that packet fits in the input buffer */
  794. if (pkg_length > buffer_len)
  795. {
  796. WARNING ("network plugin: parse_part_string: "
  797. "Packet too big: "
  798. "Chunk of size %"PRIu16" received, "
  799. "but buffer has only %zu bytes left.",
  800. pkg_length, buffer_len);
  801. return (-1);
  802. }
  803. /* Check that pkg_length is in the valid range */
  804. if (pkg_length <= header_size)
  805. {
  806. WARNING ("network plugin: parse_part_string: "
  807. "Packet too short: "
  808. "Header claims this packet is only %hu "
  809. "bytes long.", pkg_length);
  810. return (-1);
  811. }
  812. /* Check that the package data fits into the output buffer.
  813. * The previous if-statement ensures that:
  814. * `pkg_length > header_size' */
  815. if ((output_len < 0)
  816. || ((size_t) output_len < ((size_t) pkg_length - header_size)))
  817. {
  818. WARNING ("network plugin: parse_part_string: "
  819. "Output buffer too small.");
  820. return (-1);
  821. }
  822. /* All sanity checks successfull, let's copy the data over */
  823. output_len = pkg_length - header_size;
  824. memcpy ((void *) output, (void *) buffer, output_len);
  825. buffer += output_len;
  826. /* For some very weird reason '\0' doesn't do the trick on SPARC in
  827. * this statement. */
  828. if (output[output_len - 1] != 0)
  829. {
  830. WARNING ("network plugin: parse_part_string: "
  831. "Received string does not end "
  832. "with a NULL-byte.");
  833. return (-1);
  834. }
  835. *ret_buffer = buffer;
  836. *ret_buffer_len = buffer_len - pkg_length;
  837. return (0);
  838. } /* int parse_part_string */
  839. /* Forward declaration: parse_part_sign_sha256 and parse_part_encr_aes256 call
  840. * parse_packet and vice versa. */
  841. #define PP_SIGNED 0x01
  842. #define PP_ENCRYPTED 0x02
  843. static int parse_packet (sockent_t *se,
  844. void *buffer, size_t buffer_size, int flags,
  845. const char *username);
  846. #define BUFFER_READ(p,s) do { \
  847. memcpy ((p), buffer + buffer_offset, (s)); \
  848. buffer_offset += (s); \
  849. } while (0)
  850. #if HAVE_LIBGCRYPT
  851. static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
  852. void **ret_buffer, size_t *ret_buffer_len, int flags)
  853. {
  854. static c_complain_t complain_no_users = C_COMPLAIN_INIT_STATIC;
  855. char *buffer;
  856. size_t buffer_len;
  857. size_t buffer_offset;
  858. size_t username_len;
  859. char *secret;
  860. part_signature_sha256_t pss;
  861. uint16_t pss_head_length;
  862. char hash[sizeof (pss.hash)];
  863. gcry_md_hd_t hd;
  864. gcry_error_t err;
  865. unsigned char *hash_ptr;
  866. buffer = *ret_buffer;
  867. buffer_len = *ret_buffer_len;
  868. buffer_offset = 0;
  869. if (se->data.server.userdb == NULL)
  870. {
  871. c_complain (LOG_NOTICE, &complain_no_users,
  872. "network plugin: Received signed network packet but can't verify it "
  873. "because no user DB has been configured. Will accept it.");
  874. return (0);
  875. }
  876. /* Check if the buffer has enough data for this structure. */
  877. if (buffer_len <= PART_SIGNATURE_SHA256_SIZE)
  878. return (-ENOMEM);
  879. /* Read type and length header */
  880. BUFFER_READ (&pss.head.type, sizeof (pss.head.type));
  881. BUFFER_READ (&pss.head.length, sizeof (pss.head.length));
  882. pss_head_length = ntohs (pss.head.length);
  883. /* Check if the `pss_head_length' is within bounds. */
  884. if ((pss_head_length <= PART_SIGNATURE_SHA256_SIZE)
  885. || (pss_head_length > buffer_len))
  886. {
  887. ERROR ("network plugin: HMAC-SHA-256 with invalid length received.");
  888. return (-1);
  889. }
  890. /* Copy the hash. */
  891. BUFFER_READ (pss.hash, sizeof (pss.hash));
  892. /* Calculate username length (without null byte) and allocate memory */
  893. username_len = pss_head_length - PART_SIGNATURE_SHA256_SIZE;
  894. pss.username = malloc (username_len + 1);
  895. if (pss.username == NULL)
  896. return (-ENOMEM);
  897. /* Read the username */
  898. BUFFER_READ (pss.username, username_len);
  899. pss.username[username_len] = 0;
  900. assert (buffer_offset == pss_head_length);
  901. /* Query the password */
  902. secret = fbh_get (se->data.server.userdb, pss.username);
  903. if (secret == NULL)
  904. {
  905. ERROR ("network plugin: Unknown user: %s", pss.username);
  906. sfree (pss.username);
  907. return (-ENOENT);
  908. }
  909. /* Create a hash device and check the HMAC */
  910. hd = NULL;
  911. err = gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
  912. if (err != 0)
  913. {
  914. ERROR ("network plugin: Creating HMAC-SHA-256 object failed: %s",
  915. gcry_strerror (err));
  916. sfree (secret);
  917. sfree (pss.username);
  918. return (-1);
  919. }
  920. err = gcry_md_setkey (hd, secret, strlen (secret));
  921. if (err != 0)
  922. {
  923. ERROR ("network plugin: gcry_md_setkey failed: %s", gcry_strerror (err));
  924. gcry_md_close (hd);
  925. sfree (secret);
  926. sfree (pss.username);
  927. return (-1);
  928. }
  929. gcry_md_write (hd,
  930. buffer + PART_SIGNATURE_SHA256_SIZE,
  931. buffer_len - PART_SIGNATURE_SHA256_SIZE);
  932. hash_ptr = gcry_md_read (hd, GCRY_MD_SHA256);
  933. if (hash_ptr == NULL)
  934. {
  935. ERROR ("network plugin: gcry_md_read failed.");
  936. gcry_md_close (hd);
  937. sfree (secret);
  938. sfree (pss.username);
  939. return (-1);
  940. }
  941. memcpy (hash, hash_ptr, sizeof (hash));
  942. /* Clean up */
  943. gcry_md_close (hd);
  944. hd = NULL;
  945. if (memcmp (pss.hash, hash, sizeof (pss.hash)) != 0)
  946. {
  947. WARNING ("network plugin: Verifying HMAC-SHA-256 signature failed: "
  948. "Hash mismatch.");
  949. }
  950. else
  951. {
  952. parse_packet (se, buffer + buffer_offset, buffer_len - buffer_offset,
  953. flags | PP_SIGNED, pss.username);
  954. }
  955. sfree (secret);
  956. sfree (pss.username);
  957. *ret_buffer = buffer + buffer_len;
  958. *ret_buffer_len = 0;
  959. return (0);
  960. } /* }}} int parse_part_sign_sha256 */
  961. /* #endif HAVE_LIBGCRYPT */
  962. #else /* if !HAVE_LIBGCRYPT */
  963. static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
  964. void **ret_buffer, size_t *ret_buffer_size, int flags)
  965. {
  966. static int warning_has_been_printed = 0;
  967. char *buffer;
  968. size_t buffer_size;
  969. size_t buffer_offset;
  970. uint16_t part_len;
  971. part_signature_sha256_t pss;
  972. buffer = *ret_buffer;
  973. buffer_size = *ret_buffer_size;
  974. buffer_offset = 0;
  975. if (buffer_size <= PART_SIGNATURE_SHA256_SIZE)
  976. return (-ENOMEM);
  977. BUFFER_READ (&pss.head.type, sizeof (pss.head.type));
  978. BUFFER_READ (&pss.head.length, sizeof (pss.head.length));
  979. part_len = ntohs (pss.head.length);
  980. if ((part_len <= PART_SIGNATURE_SHA256_SIZE)
  981. || (part_len > buffer_size))
  982. return (-EINVAL);
  983. if (warning_has_been_printed == 0)
  984. {
  985. WARNING ("network plugin: Received signed packet, but the network "
  986. "plugin was not linked with libgcrypt, so I cannot "
  987. "verify the signature. The packet will be accepted.");
  988. warning_has_been_printed = 1;
  989. }
  990. parse_packet (se, buffer + part_len, buffer_size - part_len, flags,
  991. /* username = */ NULL);
  992. *ret_buffer = buffer + buffer_size;
  993. *ret_buffer_size = 0;
  994. return (0);
  995. } /* }}} int parse_part_sign_sha256 */
  996. #endif /* !HAVE_LIBGCRYPT */
  997. #if HAVE_LIBGCRYPT
  998. static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
  999. void **ret_buffer, size_t *ret_buffer_len,
  1000. int flags)
  1001. {
  1002. char *buffer = *ret_buffer;
  1003. size_t buffer_len = *ret_buffer_len;
  1004. size_t payload_len;
  1005. size_t part_size;
  1006. size_t buffer_offset;
  1007. uint16_t username_len;
  1008. part_encryption_aes256_t pea;
  1009. unsigned char hash[sizeof (pea.hash)];
  1010. gcry_cipher_hd_t cypher;
  1011. gcry_error_t err;
  1012. /* Make sure at least the header if available. */
  1013. if (buffer_len <= PART_ENCRYPTION_AES256_SIZE)
  1014. {
  1015. NOTICE ("network plugin: parse_part_encr_aes256: "
  1016. "Discarding short packet.");
  1017. return (-1);
  1018. }
  1019. buffer_offset = 0;
  1020. /* Copy the unencrypted information into `pea'. */
  1021. BUFFER_READ (&pea.head.type, sizeof (pea.head.type));
  1022. BUFFER_READ (&pea.head.length, sizeof (pea.head.length));
  1023. /* Check the `part size'. */
  1024. part_size = ntohs (pea.head.length);
  1025. if ((part_size <= PART_ENCRYPTION_AES256_SIZE)
  1026. || (part_size > buffer_len))
  1027. {
  1028. NOTICE ("network plugin: parse_part_encr_aes256: "
  1029. "Discarding part with invalid size.");
  1030. return (-1);
  1031. }
  1032. /* Read the username */
  1033. BUFFER_READ (&username_len, sizeof (username_len));
  1034. username_len = ntohs (username_len);
  1035. if ((username_len <= 0)
  1036. || (username_len > (part_size - (PART_ENCRYPTION_AES256_SIZE + 1))))
  1037. {
  1038. NOTICE ("network plugin: parse_part_encr_aes256: "
  1039. "Discarding part with invalid username length.");
  1040. return (-1);
  1041. }
  1042. assert (username_len > 0);
  1043. pea.username = malloc (username_len + 1);
  1044. if (pea.username == NULL)
  1045. return (-ENOMEM);
  1046. BUFFER_READ (pea.username, username_len);
  1047. pea.username[username_len] = 0;
  1048. /* Last but not least, the initialization vector */
  1049. BUFFER_READ (pea.iv, sizeof (pea.iv));
  1050. /* Make sure we are at the right position */
  1051. assert (buffer_offset == (username_len +
  1052. PART_ENCRYPTION_AES256_SIZE - sizeof (pea.hash)));
  1053. cypher = network_get_aes256_cypher (se, pea.iv, sizeof (pea.iv),
  1054. pea.username);
  1055. if (cypher == NULL)
  1056. {
  1057. sfree (pea.username);
  1058. return (-1);
  1059. }
  1060. payload_len = part_size - (PART_ENCRYPTION_AES256_SIZE + username_len);
  1061. assert (payload_len > 0);
  1062. /* Decrypt the packet in-place */
  1063. err = gcry_cipher_decrypt (cypher,
  1064. buffer + buffer_offset,
  1065. part_size - buffer_offset,
  1066. /* in = */ NULL, /* in len = */ 0);
  1067. if (err != 0)
  1068. {
  1069. sfree (pea.username);
  1070. ERROR ("network plugin: gcry_cipher_decrypt returned: %s",
  1071. gcry_strerror (err));
  1072. return (-1);
  1073. }
  1074. /* Read the hash */
  1075. BUFFER_READ (pea.hash, sizeof (pea.hash));
  1076. /* Make sure we're at the right position - again */
  1077. assert (buffer_offset == (username_len + PART_ENCRYPTION_AES256_SIZE));
  1078. assert (buffer_offset == (part_size - payload_len));
  1079. /* Check hash sum */
  1080. memset (hash, 0, sizeof (hash));
  1081. gcry_md_hash_buffer (GCRY_MD_SHA1, hash,
  1082. buffer + buffer_offset, payload_len);
  1083. if (memcmp (hash, pea.hash, sizeof (hash)) != 0)
  1084. {
  1085. sfree (pea.username);
  1086. ERROR ("network plugin: Decryption failed: Checksum mismatch.");
  1087. return (-1);
  1088. }
  1089. parse_packet (se, buffer + buffer_offset, payload_len,
  1090. flags | PP_ENCRYPTED, pea.username);
  1091. /* XXX: Free pea.username?!? */
  1092. /* Update return values */
  1093. *ret_buffer = buffer + part_size;
  1094. *ret_buffer_len = buffer_len - part_size;
  1095. sfree (pea.username);
  1096. return (0);
  1097. } /* }}} int parse_part_encr_aes256 */
  1098. /* #endif HAVE_LIBGCRYPT */
  1099. #else /* if !HAVE_LIBGCRYPT */
  1100. static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
  1101. void **ret_buffer, size_t *ret_buffer_size, int flags)
  1102. {
  1103. static int warning_has_been_printed = 0;
  1104. char *buffer;
  1105. size_t buffer_size;
  1106. size_t buffer_offset;
  1107. part_header_t ph;
  1108. size_t ph_length;
  1109. buffer = *ret_buffer;
  1110. buffer_size = *ret_buffer_size;
  1111. buffer_offset = 0;
  1112. /* parse_packet assures this minimum size. */
  1113. assert (buffer_size >= (sizeof (ph.type) + sizeof (ph.length)));
  1114. BUFFER_READ (&ph.type, sizeof (ph.type));
  1115. BUFFER_READ (&ph.length, sizeof (ph.length));
  1116. ph_length = ntohs (ph.length);
  1117. if ((ph_length <= PART_ENCRYPTION_AES256_SIZE)
  1118. || (ph_length > buffer_size))
  1119. {
  1120. ERROR ("network plugin: AES-256 encrypted part "
  1121. "with invalid length received.");
  1122. return (-1);
  1123. }
  1124. if (warning_has_been_printed == 0)
  1125. {
  1126. WARNING ("network plugin: Received encrypted packet, but the network "
  1127. "plugin was not linked with libgcrypt, so I cannot "
  1128. "decrypt it. The part will be discarded.");
  1129. warning_has_been_printed = 1;
  1130. }
  1131. *ret_buffer += ph_length;
  1132. *ret_buffer_size -= ph_length;
  1133. return (0);
  1134. } /* }}} int parse_part_encr_aes256 */
  1135. #endif /* !HAVE_LIBGCRYPT */
  1136. #undef BUFFER_READ
  1137. static int parse_packet (sockent_t *se, /* {{{ */
  1138. void *buffer, size_t buffer_size, int flags,
  1139. const char *username)
  1140. {
  1141. int status;
  1142. value_list_t vl = VALUE_LIST_INIT;
  1143. notification_t n;
  1144. #if HAVE_LIBGCRYPT
  1145. int packet_was_signed = (flags & PP_SIGNED);
  1146. int packet_was_encrypted = (flags & PP_ENCRYPTED);
  1147. int printed_ignore_warning = 0;
  1148. #endif /* HAVE_LIBGCRYPT */
  1149. memset (&vl, '\0', sizeof (vl));
  1150. memset (&n, '\0', sizeof (n));
  1151. status = 0;
  1152. while ((status == 0) && (0 < buffer_size)
  1153. && ((unsigned int) buffer_size > sizeof (part_header_t)))
  1154. {
  1155. uint16_t pkg_length;
  1156. uint16_t pkg_type;
  1157. memcpy ((void *) &pkg_type,
  1158. (void *) buffer,
  1159. sizeof (pkg_type));
  1160. memcpy ((void *) &pkg_length,
  1161. (void *) (buffer + sizeof (pkg_type)),
  1162. sizeof (pkg_length));
  1163. pkg_length = ntohs (pkg_length);
  1164. pkg_type = ntohs (pkg_type);
  1165. if (pkg_length > buffer_size)
  1166. break;
  1167. /* Ensure that this loop terminates eventually */
  1168. if (pkg_length < (2 * sizeof (uint16_t)))
  1169. break;
  1170. if (pkg_type == TYPE_ENCR_AES256)
  1171. {
  1172. status = parse_part_encr_aes256 (se,
  1173. &buffer, &buffer_size, flags);
  1174. if (status != 0)
  1175. {
  1176. ERROR ("network plugin: Decrypting AES256 "
  1177. "part failed "
  1178. "with status %i.", status);
  1179. break;
  1180. }
  1181. }
  1182. #if HAVE_LIBGCRYPT
  1183. else if ((se->data.server.security_level == SECURITY_LEVEL_ENCRYPT)
  1184. && (packet_was_encrypted == 0))
  1185. {
  1186. if (printed_ignore_warning == 0)
  1187. {
  1188. INFO ("network plugin: Unencrypted packet or "
  1189. "part has been ignored.");
  1190. printed_ignore_warning = 1;
  1191. }
  1192. buffer = ((char *) buffer) + pkg_length;
  1193. continue;
  1194. }
  1195. #endif /* HAVE_LIBGCRYPT */
  1196. else if (pkg_type == TYPE_SIGN_SHA256)
  1197. {
  1198. status = parse_part_sign_sha256 (se,
  1199. &buffer, &buffer_size, flags);
  1200. if (status != 0)
  1201. {
  1202. ERROR ("network plugin: Verifying HMAC-SHA-256 "
  1203. "signature failed "
  1204. "with status %i.", status);
  1205. break;
  1206. }
  1207. }
  1208. #if HAVE_LIBGCRYPT
  1209. else if ((se->data.server.security_level == SECURITY_LEVEL_SIGN)
  1210. && (packet_was_encrypted == 0)
  1211. && (packet_was_signed == 0))
  1212. {
  1213. if (printed_ignore_warning == 0)
  1214. {
  1215. INFO ("network plugin: Unsigned packet or "
  1216. "part has been ignored.");
  1217. printed_ignore_warning = 1;
  1218. }
  1219. buffer = ((char *) buffer) + pkg_length;
  1220. continue;
  1221. }
  1222. #endif /* HAVE_LIBGCRYPT */
  1223. else if (pkg_type == TYPE_VALUES)
  1224. {
  1225. status = parse_part_values (&buffer, &buffer_size,
  1226. &vl.values, &vl.values_len);
  1227. if (status != 0)
  1228. break;
  1229. network_dispatch_values (&vl, username);
  1230. sfree (vl.values);
  1231. }
  1232. else if (pkg_type == TYPE_TIME)
  1233. {
  1234. uint64_t tmp = 0;
  1235. status = parse_part_number (&buffer, &buffer_size,
  1236. &tmp);
  1237. if (status == 0)
  1238. {
  1239. vl.time = TIME_T_TO_CDTIME_T (tmp);
  1240. n.time = TIME_T_TO_CDTIME_T (tmp);
  1241. }
  1242. }
  1243. else if (pkg_type == TYPE_TIME_HR)
  1244. {
  1245. uint64_t tmp = 0;
  1246. status = parse_part_number (&buffer, &buffer_size,
  1247. &tmp);
  1248. if (status == 0)
  1249. {
  1250. vl.time = (cdtime_t) tmp;
  1251. n.time = (cdtime_t) tmp;
  1252. }
  1253. }
  1254. else if (pkg_type == TYPE_INTERVAL)
  1255. {
  1256. uint64_t tmp = 0;
  1257. status = parse_part_number (&buffer, &buffer_size,
  1258. &tmp);
  1259. if (status == 0)
  1260. vl.interval = TIME_T_TO_CDTIME_T (tmp);
  1261. }
  1262. else if (pkg_type == TYPE_INTERVAL_HR)
  1263. {
  1264. uint64_t tmp = 0;
  1265. status = parse_part_number (&buffer, &buffer_size,
  1266. &tmp);
  1267. if (status == 0)
  1268. vl.interval = (cdtime_t) tmp;
  1269. }
  1270. else if (pkg_type == TYPE_HOST)
  1271. {
  1272. status = parse_part_string (&buffer, &buffer_size,
  1273. vl.host, sizeof (vl.host));
  1274. if (status == 0)
  1275. sstrncpy (n.host, vl.host, sizeof (n.host));
  1276. }
  1277. else if (pkg_type == TYPE_PLUGIN)
  1278. {
  1279. status = parse_part_string (&buffer, &buffer_size,
  1280. vl.plugin, sizeof (vl.plugin));
  1281. if (status == 0)
  1282. sstrncpy (n.plugin, vl.plugin,
  1283. sizeof (n.plugin));
  1284. }
  1285. else if (pkg_type == TYPE_PLUGIN_INSTANCE)
  1286. {
  1287. status = parse_part_string (&buffer, &buffer_size,
  1288. vl.plugin_instance,
  1289. sizeof (vl.plugin_instance));
  1290. if (status == 0)
  1291. sstrncpy (n.plugin_instance,
  1292. vl.plugin_instance,
  1293. sizeof (n.plugin_instance));
  1294. }
  1295. else if (pkg_type == TYPE_TYPE)
  1296. {
  1297. status = parse_part_string (&buffer, &buffer_size,
  1298. vl.type, sizeof (vl.type));
  1299. if (status == 0)
  1300. sstrncpy (n.type, vl.type, sizeof (n.type));
  1301. }
  1302. else if (pkg_type == TYPE_TYPE_INSTANCE)
  1303. {
  1304. status = parse_part_string (&buffer, &buffer_size,
  1305. vl.type_instance,
  1306. sizeof (vl.type_instance));
  1307. if (status == 0)
  1308. sstrncpy (n.type_instance, vl.type_instance,
  1309. sizeof (n.type_instance));
  1310. }
  1311. else if (pkg_type == TYPE_MESSAGE)
  1312. {
  1313. status = parse_part_string (&buffer, &buffer_size,
  1314. n.message, sizeof (n.message));
  1315. if (status != 0)
  1316. {
  1317. /* do nothing */
  1318. }
  1319. else if ((n.severity != NOTIF_FAILURE)
  1320. && (n.severity != NOTIF_WARNING)
  1321. && (n.severity != NOTIF_OKAY))
  1322. {
  1323. INFO ("network plugin: "
  1324. "Ignoring notification with "
  1325. "unknown severity %i.",
  1326. n.severity);
  1327. }
  1328. else if (n.time <= 0)
  1329. {
  1330. INFO ("network plugin: "
  1331. "Ignoring notification with "
  1332. "time == 0.");
  1333. }
  1334. else if (strlen (n.message) <= 0)
  1335. {
  1336. INFO ("network plugin: "
  1337. "Ignoring notification with "
  1338. "an empty message.");
  1339. }
  1340. else
  1341. {
  1342. network_dispatch_notification (&n);
  1343. }
  1344. }
  1345. else if (pkg_type == TYPE_SEVERITY)
  1346. {
  1347. uint64_t tmp = 0;
  1348. status = parse_part_number (&buffer, &buffer_size,
  1349. &tmp);
  1350. if (status == 0)
  1351. n.severity = (int) tmp;
  1352. }
  1353. else
  1354. {
  1355. DEBUG ("network plugin: parse_packet: Unknown part"
  1356. " type: 0x%04hx", pkg_type);
  1357. buffer = ((char *) buffer) + pkg_length;
  1358. }
  1359. } /* while (buffer_size > sizeof (part_header_t)) */
  1360. if (status == 0 && buffer_size > 0)
  1361. WARNING ("network plugin: parse_packet: Received truncated "
  1362. "packet, try increasing `MaxPacketSize'");
  1363. return (status);
  1364. } /* }}} int parse_packet */
  1365. static void free_sockent_client (struct sockent_client *sec) /* {{{ */
  1366. {
  1367. if (sec->fd >= 0)
  1368. {
  1369. close (sec->fd);
  1370. sec->fd = -1;
  1371. }
  1372. sfree (sec->addr);
  1373. #if HAVE_LIBGCRYPT
  1374. sfree (sec->username);
  1375. sfree (sec->password);
  1376. if (sec->cypher != NULL)
  1377. gcry_cipher_close (sec->cypher);
  1378. #endif
  1379. } /* }}} void free_sockent_client */
  1380. static void free_sockent_server (struct sockent_server *ses) /* {{{ */
  1381. {
  1382. size_t i;
  1383. for (i = 0; i < ses->fd_num; i++)
  1384. {
  1385. if (ses->fd[i] >= 0)
  1386. {
  1387. close (ses->fd[i]);
  1388. ses->fd[i] = -1;
  1389. }
  1390. }
  1391. sfree (ses->fd);
  1392. #if HAVE_LIBGCRYPT
  1393. sfree (ses->auth_file);
  1394. fbh_destroy (ses->userdb);
  1395. if (ses->cypher != NULL)
  1396. gcry_cipher_close (ses->cypher);
  1397. #endif
  1398. } /* }}} void free_sockent_server */
  1399. static void sockent_destroy (sockent_t *se) /* {{{ */
  1400. {
  1401. sockent_t *next;
  1402. DEBUG ("network plugin: sockent_destroy (se = %p);", (void *) se);
  1403. while (se != NULL)
  1404. {
  1405. next = se->next;
  1406. sfree (se->node);
  1407. sfree (se->service);
  1408. if (se->type == SOCKENT_TYPE_CLIENT)
  1409. free_sockent_client (&se->data.client);
  1410. else
  1411. free_sockent_server (&se->data.server);
  1412. sfree (se);
  1413. se = next;
  1414. }
  1415. } /* }}} void sockent_destroy */
  1416. /*
  1417. * int network_set_ttl
  1418. *
  1419. * Set the `IP_MULTICAST_TTL', `IP_TTL', `IPV6_MULTICAST_HOPS' or
  1420. * `IPV6_UNICAST_HOPS', depending on which option is applicable.
  1421. *
  1422. * The `struct addrinfo' is used to destinguish between unicast and multicast
  1423. * sockets.
  1424. */
  1425. static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
  1426. {
  1427. DEBUG ("network plugin: network_set_ttl: network_config_ttl = %i;",
  1428. network_config_ttl);
  1429. assert (se->type == SOCKENT_TYPE_CLIENT);
  1430. if ((network_config_ttl < 1) || (network_config_ttl > 255))
  1431. return (-1);
  1432. if (ai->ai_family == AF_INET)
  1433. {
  1434. struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
  1435. int optname;
  1436. if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
  1437. optname = IP_MULTICAST_TTL;
  1438. else
  1439. optname = IP_TTL;
  1440. if (setsockopt (se->data.client.fd, IPPROTO_IP, optname,
  1441. &network_config_ttl,
  1442. sizeof (network_config_ttl)) != 0)
  1443. {
  1444. char errbuf[1024];
  1445. ERROR ("network plugin: setsockopt (ipv4-ttl): %s",
  1446. sstrerror (errno, errbuf, sizeof (errbuf)));
  1447. return (-1);
  1448. }
  1449. }
  1450. else if (ai->ai_family == AF_INET6)
  1451. {
  1452. /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
  1453. struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
  1454. int optname;
  1455. if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
  1456. optname = IPV6_MULTICAST_HOPS;
  1457. else
  1458. optname = IPV6_UNICAST_HOPS;
  1459. if (setsockopt (se->data.client.fd, IPPROTO_IPV6, optname,
  1460. &network_config_ttl,
  1461. sizeof (network_config_ttl)) != 0)
  1462. {
  1463. char errbuf[1024];
  1464. ERROR ("network plugin: setsockopt(ipv6-ttl): %s",
  1465. sstrerror (errno, errbuf,
  1466. sizeof (errbuf)));
  1467. return (-1);
  1468. }
  1469. }
  1470. return (0);
  1471. } /* int network_set_ttl */
  1472. static int network_set_interface (const sockent_t *se, const struct addrinfo *ai) /* {{{ */
  1473. {
  1474. DEBUG ("network plugin: network_set_interface: interface index = %i;",
  1475. se->interface);
  1476. assert (se->type == SOCKENT_TYPE_CLIENT);
  1477. if (ai->ai_family == AF_INET)
  1478. {
  1479. struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
  1480. if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
  1481. {
  1482. #if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
  1483. /* If possible, use the "ip_mreqn" structure which has
  1484. * an "interface index" member. Using the interface
  1485. * index is preferred here, because of its similarity
  1486. * to the way IPv6 handles this. Unfortunately, it
  1487. * appears not to be portable. */
  1488. struct ip_mreqn mreq;
  1489. memset (&mreq, 0, sizeof (mreq));
  1490. mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
  1491. mreq.imr_address.s_addr = ntohl (INADDR_ANY);
  1492. mreq.imr_ifindex = se->interface;
  1493. #else
  1494. struct ip_mreq mreq;
  1495. memset (&mreq, 0, sizeof (mreq));
  1496. mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
  1497. mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
  1498. #endif
  1499. if (setsockopt (se->data.client.fd, IPPROTO_IP, IP_MULTICAST_IF,
  1500. &mreq, sizeof (mreq)) != 0)
  1501. {
  1502. char errbuf[1024];
  1503. ERROR ("network plugin: setsockopt (ipv4-multicast-if): %s",
  1504. sstrerror (errno, errbuf, sizeof (errbuf)));
  1505. return (-1);
  1506. }
  1507. return (0);
  1508. }
  1509. }
  1510. else if (ai->ai_family == AF_INET6)
  1511. {
  1512. struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
  1513. if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
  1514. {
  1515. if (setsockopt (se->data.client.fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
  1516. &se->interface,
  1517. sizeof (se->interface)) != 0)
  1518. {
  1519. char errbuf[1024];
  1520. ERROR ("network plugin: setsockopt (ipv6-multicast-if): %s",
  1521. sstrerror (errno, errbuf,
  1522. sizeof (errbuf)));
  1523. return (-1);
  1524. }
  1525. return (0);
  1526. }
  1527. }
  1528. /* else: Not a multicast interface. */
  1529. if (se->interface != 0)
  1530. {
  1531. #if defined(HAVE_IF_INDEXTONAME) && HAVE_IF_INDEXTONAME && defined(SO_BINDTODEVICE)
  1532. char interface_name[IFNAMSIZ];
  1533. if (if_indextoname (se->interface, interface_name) == NULL)
  1534. return (-1);
  1535. DEBUG ("network plugin: Binding socket to interface %s", interface_name);
  1536. if (setsockopt (se->data.client.fd, SOL_SOCKET, SO_BINDTODEVICE,
  1537. interface_name,
  1538. sizeof(interface_name)) == -1 )
  1539. {
  1540. char errbuf[1024];
  1541. ERROR ("network plugin: setsockopt (bind-if): %s",
  1542. sstrerror (errno, errbuf, sizeof (errbuf)));
  1543. return (-1);
  1544. }
  1545. /* #endif HAVE_IF_INDEXTONAME && SO_BINDTODEVICE */
  1546. #else
  1547. WARNING ("network plugin: Cannot set the interface on a unicast "
  1548. "socket because "
  1549. # if !defined(SO_BINDTODEVICE)
  1550. "the \"SO_BINDTODEVICE\" socket option "
  1551. # else
  1552. "the \"if_indextoname\" function "
  1553. # endif
  1554. "is not available on your system.");
  1555. #endif
  1556. }
  1557. return (0);
  1558. } /* }}} network_set_interface */
  1559. static int network_bind_socket (int fd, const struct addrinfo *ai, const int interface_idx)
  1560. {
  1561. #if KERNEL_SOLARIS
  1562. char loop = 0;
  1563. #else
  1564. int loop = 0;
  1565. #endif
  1566. int yes = 1;
  1567. /* allow multiple sockets to use the same PORT number */
  1568. if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
  1569. &yes, sizeof(yes)) == -1) {
  1570. char errbuf[1024];
  1571. ERROR ("network plugin: setsockopt (reuseaddr): %s",
  1572. sstrerror (errno, errbuf, sizeof (errbuf)));
  1573. return (-1);
  1574. }
  1575. DEBUG ("fd = %i; calling `bind'", fd);
  1576. if (bind (fd, ai->ai_addr, ai->ai_addrlen) == -1)
  1577. {
  1578. char errbuf[1024];
  1579. ERROR ("bind: %s",
  1580. sstrerror (errno, errbuf, sizeof (errbuf)));
  1581. return (-1);
  1582. }
  1583. if (ai->ai_family == AF_INET)
  1584. {
  1585. struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
  1586. if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
  1587. {
  1588. #if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
  1589. struct ip_mreqn mreq;
  1590. #else
  1591. struct ip_mreq mreq;
  1592. #endif
  1593. DEBUG ("fd = %i; IPv4 multicast address found"

Large files files are truncated, but you can click here to view the full file