network plugin: Use SHA-1 instead of SHA-224 to check integrity.
[collectd.git] / src / network.c
1 /**
2  * collectd - src/network.c
3  * Copyright (C) 2005-2009  Florian octo Forster
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  * Authors:
19  *   Florian octo Forster <octo at verplant.org>
20  **/
21
22 #include "collectd.h"
23 #include "plugin.h"
24 #include "common.h"
25 #include "configfile.h"
26 #include "utils_avltree.h"
27
28 #include "network.h"
29
30 #if HAVE_PTHREAD_H
31 # include <pthread.h>
32 #endif
33 #if HAVE_SYS_SOCKET_H
34 # include <sys/socket.h>
35 #endif
36 #if HAVE_NETDB_H
37 # include <netdb.h>
38 #endif
39 #if HAVE_NETINET_IN_H
40 # include <netinet/in.h>
41 #endif
42 #if HAVE_ARPA_INET_H
43 # include <arpa/inet.h>
44 #endif
45 #if HAVE_POLL_H
46 # include <poll.h>
47 #endif
48
49 #if HAVE_GCRYPT_H
50 # include <gcrypt.h>
51 #endif
52
53 /* 1500 - 40 - 8  =  Ethernet packet - IPv6 header - UDP header */
54 /* #define BUFF_SIZE 1452 */
55
56 #ifndef IPV6_ADD_MEMBERSHIP
57 # ifdef IPV6_JOIN_GROUP
58 #  define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
59 # else
60 #  error "Neither IP_ADD_MEMBERSHIP nor IPV6_JOIN_GROUP is defined"
61 # endif
62 #endif /* !IP_ADD_MEMBERSHIP */
63
64 /* Buffer size to allocate. */
65 #define BUFF_SIZE 1024
66
67 /*
68  * Maximum size required for encryption / signing:
69  * Type/length:       4
70  * Hash/orig length: 22
71  * Padding (up to):  15
72  * --------------------
73  *                   41
74  */
75 #define BUFF_SIG_SIZE 41
76
77 /*
78  * Private data types
79  */
80 typedef struct sockent
81 {
82         int                      fd;
83         struct sockaddr_storage *addr;
84         socklen_t                addrlen;
85
86 #define SECURITY_LEVEL_NONE     0
87 #if HAVE_GCRYPT_H
88 # define SECURITY_LEVEL_SIGN    1
89 # define SECURITY_LEVEL_ENCRYPT 2
90         int security_level;
91         char *shared_secret;
92         gcry_cipher_hd_t cypher;
93 #endif /* HAVE_GCRYPT_H */
94
95         struct sockent          *next;
96 } sockent_t;
97
98 /*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
99  *  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
100  * +-------+-----------------------+-------------------------------+
101  * ! Ver.  !                       ! Length                        !
102  * +-------+-----------------------+-------------------------------+
103  */
104 struct part_header_s
105 {
106         uint16_t type;
107         uint16_t length;
108 };
109 typedef struct part_header_s part_header_t;
110
111 /*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
112  *  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
113  * +-------------------------------+-------------------------------+
114  * ! Type                          ! Length                        !
115  * +-------------------------------+-------------------------------+
116  * : (Length - 4) Bytes                                            :
117  * +---------------------------------------------------------------+
118  */
119 struct part_string_s
120 {
121         part_header_t *head;
122         char *value;
123 };
124 typedef struct part_string_s part_string_t;
125
126 /*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
127  *  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
128  * +-------------------------------+-------------------------------+
129  * ! Type                          ! Length                        !
130  * +-------------------------------+-------------------------------+
131  * : (Length - 4 == 2 || 4 || 8) Bytes                             :
132  * +---------------------------------------------------------------+
133  */
134 struct part_number_s
135 {
136         part_header_t *head;
137         uint64_t *value;
138 };
139 typedef struct part_number_s part_number_t;
140
141 /*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
142  *  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
143  * +-------------------------------+-------------------------------+
144  * ! Type                          ! Length                        !
145  * +-------------------------------+---------------+---------------+
146  * ! Num of values                 ! Type0         ! Type1         !
147  * +-------------------------------+---------------+---------------+
148  * ! Value0                                                        !
149  * !                                                               !
150  * +---------------------------------------------------------------+
151  * ! Value1                                                        !
152  * !                                                               !
153  * +---------------------------------------------------------------+
154  */
155 struct part_values_s
156 {
157         part_header_t *head;
158         uint16_t *num_values;
159         uint8_t  *values_types;
160         value_t  *values;
161 };
162 typedef struct part_values_s part_values_t;
163
164 /*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
165  *  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
166  * +-------------------------------+-------------------------------+
167  * ! Type                          ! Length                        !
168  * +-------------------------------+-------------------------------+
169  * ! Hash (Bits   0 -  31)                                         !
170  * : :                                                             :
171  * ! Hash (Bits 224 - 255)                                         !
172  * +---------------------------------------------------------------+
173  */
174 struct part_signature_sha256_s
175 {
176   part_header_t head;
177   char hash[32];
178 };
179 typedef struct part_signature_sha256_s part_signature_sha256_t;
180
181 /*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
182  *  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
183  * +-------------------------------+-------------------------------+
184  * ! Type                          ! Length                        !
185  * +-------------------------------+-------------------------------+
186  * ! Original length               ! Padding (0 - 15 bytes)        !
187  * +-------------------------------+-------------------------------+
188  * ! Hash (Bits   0 -  31)                                         !
189  * : :                                                             :
190  * ! Hash (Bits 128 - 159)                                         !
191  * +---------------------------------------------------------------+
192  */
193 struct part_encryption_aes256_s
194 {
195   part_header_t head;
196   uint16_t orig_length;
197   char padding[15];
198   char hash[20];
199 };
200 typedef struct part_encryption_aes256_s part_encryption_aes256_t;
201
202 struct receive_list_entry_s
203 {
204   char data[BUFF_SIZE];
205   int  data_len;
206   int  fd;
207   struct receive_list_entry_s *next;
208 };
209 typedef struct receive_list_entry_s receive_list_entry_t;
210
211 /*
212  * Private variables
213  */
214 static int network_config_ttl = 0;
215 static int network_config_forward = 0;
216
217 static sockent_t *sending_sockets = NULL;
218
219 static receive_list_entry_t *receive_list_head = NULL;
220 static receive_list_entry_t *receive_list_tail = NULL;
221 static pthread_mutex_t       receive_list_lock = PTHREAD_MUTEX_INITIALIZER;
222 static pthread_cond_t        receive_list_cond = PTHREAD_COND_INITIALIZER;
223
224 static sockent_t     *listen_sockets = NULL;
225 static struct pollfd *listen_sockets_pollfd = NULL;
226 static int            listen_sockets_num = 0;
227
228 /* The receive and dispatch threads will run as long as `listen_loop' is set to
229  * zero. */
230 static int       listen_loop = 0;
231 static int       receive_thread_running = 0;
232 static pthread_t receive_thread_id;
233 static int       dispatch_thread_running = 0;
234 static pthread_t dispatch_thread_id;
235
236 /* Buffer in which to-be-sent network packets are constructed. */
237 static char             send_buffer[BUFF_SIZE];
238 static char            *send_buffer_ptr;
239 static int              send_buffer_fill;
240 static value_list_t     send_buffer_vl = VALUE_LIST_STATIC;
241 static pthread_mutex_t  send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
242
243 /* In this cache we store all the values we received, so we can send out only
244  * those values which were *not* received via the network plugin, too. This is
245  * used for the `Forward false' option. */
246 static c_avl_tree_t    *cache_tree = NULL;
247 static pthread_mutex_t  cache_lock = PTHREAD_MUTEX_INITIALIZER;
248 static time_t           cache_flush_last = 0;
249 static int              cache_flush_interval = 1800;
250
251 /*
252  * Private functions
253  */
254 static int cache_flush (void)
255 {
256         char **keys = NULL;
257         int    keys_num = 0;
258
259         char **tmp;
260         int    i;
261
262         char   *key;
263         time_t *value;
264         c_avl_iterator_t *iter;
265
266         time_t curtime = time (NULL);
267
268         iter = c_avl_get_iterator (cache_tree);
269         while (c_avl_iterator_next (iter, (void *) &key, (void *) &value) == 0)
270         {
271                 if ((curtime - *value) <= cache_flush_interval)
272                         continue;
273                 tmp = (char **) realloc (keys,
274                                 (keys_num + 1) * sizeof (char *));
275                 if (tmp == NULL)
276                 {
277                         sfree (keys);
278                         c_avl_iterator_destroy (iter);
279                         ERROR ("network plugin: cache_flush: realloc"
280                                         " failed.");
281                         return (-1);
282                 }
283                 keys = tmp;
284                 keys[keys_num] = key;
285                 keys_num++;
286         } /* while (c_avl_iterator_next) */
287         c_avl_iterator_destroy (iter);
288
289         for (i = 0; i < keys_num; i++)
290         {
291                 if (c_avl_remove (cache_tree, keys[i], (void *) &key,
292                                         (void *) &value) != 0)
293                 {
294                         WARNING ("network plugin: cache_flush: c_avl_remove"
295                                         " (%s) failed.", keys[i]);
296                         continue;
297                 }
298
299                 sfree (key);
300                 sfree (value);
301         }
302
303         sfree (keys);
304
305         DEBUG ("network plugin: cache_flush: Removed %i %s",
306                         keys_num, (keys_num == 1) ? "entry" : "entries");
307         cache_flush_last = curtime;
308         return (0);
309 } /* int cache_flush */
310
311 static int cache_check (const value_list_t *vl)
312 {
313         char key[1024];
314         time_t *value = NULL;
315         int retval = -1;
316
317         if (cache_tree == NULL)
318                 return (-1);
319
320         if (format_name (key, sizeof (key), vl->host, vl->plugin,
321                                 vl->plugin_instance, vl->type, vl->type_instance))
322                 return (-1);
323
324         pthread_mutex_lock (&cache_lock);
325
326         if (c_avl_get (cache_tree, key, (void *) &value) == 0)
327         {
328                 if (*value < vl->time)
329                 {
330                         *value = vl->time;
331                         retval = 0;
332                 }
333                 else
334                 {
335                         DEBUG ("network plugin: cache_check: *value = %i >= vl->time = %i",
336                                         (int) *value, (int) vl->time);
337                         retval = 1;
338                 }
339         }
340         else
341         {
342                 char *key_copy = strdup (key);
343                 value = malloc (sizeof (time_t));
344                 if ((key_copy != NULL) && (value != NULL))
345                 {
346                         *value = vl->time;
347                         c_avl_insert (cache_tree, key_copy, value);
348                         retval = 0;
349                 }
350                 else
351                 {
352                         sfree (key_copy);
353                         sfree (value);
354                 }
355         }
356
357         if ((time (NULL) - cache_flush_last) > cache_flush_interval)
358                 cache_flush ();
359
360         pthread_mutex_unlock (&cache_lock);
361
362         return (retval);
363 } /* int cache_check */
364
365 static int write_part_values (char **ret_buffer, int *ret_buffer_len,
366                 const data_set_t *ds, const value_list_t *vl)
367 {
368         char *packet_ptr;
369         int packet_len;
370         int num_values;
371
372         part_header_t pkg_ph;
373         uint16_t      pkg_num_values;
374         uint8_t      *pkg_values_types;
375         value_t      *pkg_values;
376
377         int offset;
378         int i;
379
380         num_values = vl->values_len;
381         packet_len = sizeof (part_header_t) + sizeof (uint16_t)
382                 + (num_values * sizeof (uint8_t))
383                 + (num_values * sizeof (value_t));
384
385         if (*ret_buffer_len < packet_len)
386                 return (-1);
387
388         pkg_values_types = (uint8_t *) malloc (num_values * sizeof (uint8_t));
389         if (pkg_values_types == NULL)
390         {
391                 ERROR ("network plugin: write_part_values: malloc failed.");
392                 return (-1);
393         }
394
395         pkg_values = (value_t *) malloc (num_values * sizeof (value_t));
396         if (pkg_values == NULL)
397         {
398                 free (pkg_values_types);
399                 ERROR ("network plugin: write_part_values: malloc failed.");
400                 return (-1);
401         }
402
403         pkg_ph.type = htons (TYPE_VALUES);
404         pkg_ph.length = htons (packet_len);
405
406         pkg_num_values = htons ((uint16_t) vl->values_len);
407
408         for (i = 0; i < num_values; i++)
409         {
410                 if (ds->ds[i].type == DS_TYPE_COUNTER)
411                 {
412                         pkg_values_types[i] = DS_TYPE_COUNTER;
413                         pkg_values[i].counter = htonll (vl->values[i].counter);
414                 }
415                 else
416                 {
417                         pkg_values_types[i] = DS_TYPE_GAUGE;
418                         pkg_values[i].gauge = htond (vl->values[i].gauge);
419                 }
420         }
421
422         /*
423          * Use `memcpy' to write everything to the buffer, because the pointer
424          * may be unaligned and some architectures, such as SPARC, can't handle
425          * that.
426          */
427         packet_ptr = *ret_buffer;
428         offset = 0;
429         memcpy (packet_ptr + offset, &pkg_ph, sizeof (pkg_ph));
430         offset += sizeof (pkg_ph);
431         memcpy (packet_ptr + offset, &pkg_num_values, sizeof (pkg_num_values));
432         offset += sizeof (pkg_num_values);
433         memcpy (packet_ptr + offset, pkg_values_types, num_values * sizeof (uint8_t));
434         offset += num_values * sizeof (uint8_t);
435         memcpy (packet_ptr + offset, pkg_values, num_values * sizeof (value_t));
436         offset += num_values * sizeof (value_t);
437
438         assert (offset == packet_len);
439
440         *ret_buffer = packet_ptr + packet_len;
441         *ret_buffer_len -= packet_len;
442
443         free (pkg_values_types);
444         free (pkg_values);
445
446         return (0);
447 } /* int write_part_values */
448
449 static int write_part_number (char **ret_buffer, int *ret_buffer_len,
450                 int type, uint64_t value)
451 {
452         char *packet_ptr;
453         int packet_len;
454
455         part_header_t pkg_head;
456         uint64_t pkg_value;
457         
458         int offset;
459
460         packet_len = sizeof (pkg_head) + sizeof (pkg_value);
461
462         if (*ret_buffer_len < packet_len)
463                 return (-1);
464
465         pkg_head.type = htons (type);
466         pkg_head.length = htons (packet_len);
467         pkg_value = htonll (value);
468
469         packet_ptr = *ret_buffer;
470         offset = 0;
471         memcpy (packet_ptr + offset, &pkg_head, sizeof (pkg_head));
472         offset += sizeof (pkg_head);
473         memcpy (packet_ptr + offset, &pkg_value, sizeof (pkg_value));
474         offset += sizeof (pkg_value);
475
476         assert (offset == packet_len);
477
478         *ret_buffer = packet_ptr + packet_len;
479         *ret_buffer_len -= packet_len;
480
481         return (0);
482 } /* int write_part_number */
483
484 static int write_part_string (char **ret_buffer, int *ret_buffer_len,
485                 int type, const char *str, int str_len)
486 {
487         char *buffer;
488         int buffer_len;
489
490         uint16_t pkg_type;
491         uint16_t pkg_length;
492
493         int offset;
494
495         buffer_len = 2 * sizeof (uint16_t) + str_len + 1;
496         if (*ret_buffer_len < buffer_len)
497                 return (-1);
498
499         pkg_type = htons (type);
500         pkg_length = htons (buffer_len);
501
502         buffer = *ret_buffer;
503         offset = 0;
504         memcpy (buffer + offset, (void *) &pkg_type, sizeof (pkg_type));
505         offset += sizeof (pkg_type);
506         memcpy (buffer + offset, (void *) &pkg_length, sizeof (pkg_length));
507         offset += sizeof (pkg_length);
508         memcpy (buffer + offset, str, str_len);
509         offset += str_len;
510         memset (buffer + offset, '\0', 1);
511         offset += 1;
512
513         assert (offset == buffer_len);
514
515         *ret_buffer = buffer + buffer_len;
516         *ret_buffer_len -= buffer_len;
517
518         return (0);
519 } /* int write_part_string */
520
521 static int parse_part_values (void **ret_buffer, int *ret_buffer_len,
522                 value_t **ret_values, int *ret_num_values)
523 {
524         char *buffer = *ret_buffer;
525         int   buffer_len = *ret_buffer_len;
526
527         uint16_t tmp16;
528         size_t exp_size;
529         int   i;
530
531         uint16_t pkg_length;
532         uint16_t pkg_type;
533         uint16_t pkg_numval;
534
535         uint8_t *pkg_types;
536         value_t *pkg_values;
537
538         if (buffer_len < (15))
539         {
540                 DEBUG ("network plugin: packet is too short: buffer_len = %i",
541                                 buffer_len);
542                 return (-1);
543         }
544
545         memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
546         buffer += sizeof (tmp16);
547         pkg_type = ntohs (tmp16);
548
549         memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
550         buffer += sizeof (tmp16);
551         pkg_length = ntohs (tmp16);
552
553         memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
554         buffer += sizeof (tmp16);
555         pkg_numval = ntohs (tmp16);
556
557         assert (pkg_type == TYPE_VALUES);
558
559         exp_size = 3 * sizeof (uint16_t)
560                 + pkg_numval * (sizeof (uint8_t) + sizeof (value_t));
561         if ((buffer_len < 0) || ((size_t) buffer_len < exp_size))
562         {
563                 WARNING ("network plugin: parse_part_values: "
564                                 "Packet too short: "
565                                 "Chunk of size %u expected, "
566                                 "but buffer has only %i bytes left.",
567                                 (unsigned int) exp_size, buffer_len);
568                 return (-1);
569         }
570
571         if (pkg_length != exp_size)
572         {
573                 WARNING ("network plugin: parse_part_values: "
574                                 "Length and number of values "
575                                 "in the packet don't match.");
576                 return (-1);
577         }
578
579         pkg_types = (uint8_t *) malloc (pkg_numval * sizeof (uint8_t));
580         pkg_values = (value_t *) malloc (pkg_numval * sizeof (value_t));
581         if ((pkg_types == NULL) || (pkg_values == NULL))
582         {
583                 sfree (pkg_types);
584                 sfree (pkg_values);
585                 ERROR ("network plugin: parse_part_values: malloc failed.");
586                 return (-1);
587         }
588
589         memcpy ((void *) pkg_types, (void *) buffer, pkg_numval * sizeof (uint8_t));
590         buffer += pkg_numval * sizeof (uint8_t);
591         memcpy ((void *) pkg_values, (void *) buffer, pkg_numval * sizeof (value_t));
592         buffer += pkg_numval * sizeof (value_t);
593
594         for (i = 0; i < pkg_numval; i++)
595         {
596                 if (pkg_types[i] == DS_TYPE_COUNTER)
597                         pkg_values[i].counter = ntohll (pkg_values[i].counter);
598                 else if (pkg_types[i] == DS_TYPE_GAUGE)
599                         pkg_values[i].gauge = ntohd (pkg_values[i].gauge);
600         }
601
602         *ret_buffer     = buffer;
603         *ret_buffer_len = buffer_len - pkg_length;
604         *ret_num_values = pkg_numval;
605         *ret_values     = pkg_values;
606
607         sfree (pkg_types);
608
609         return (0);
610 } /* int parse_part_values */
611
612 static int parse_part_number (void **ret_buffer, int *ret_buffer_len,
613                 uint64_t *value)
614 {
615         char *buffer = *ret_buffer;
616         int buffer_len = *ret_buffer_len;
617
618         uint16_t tmp16;
619         uint64_t tmp64;
620         size_t exp_size = 2 * sizeof (uint16_t) + sizeof (uint64_t);
621
622         uint16_t pkg_length;
623         uint16_t pkg_type;
624
625         if ((buffer_len < 0) || ((size_t) buffer_len < exp_size))
626         {
627                 WARNING ("network plugin: parse_part_number: "
628                                 "Packet too short: "
629                                 "Chunk of size %u expected, "
630                                 "but buffer has only %i bytes left.",
631                                 (unsigned int) exp_size, buffer_len);
632                 return (-1);
633         }
634
635         memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
636         buffer += sizeof (tmp16);
637         pkg_type = ntohs (tmp16);
638
639         memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
640         buffer += sizeof (tmp16);
641         pkg_length = ntohs (tmp16);
642
643         memcpy ((void *) &tmp64, buffer, sizeof (tmp64));
644         buffer += sizeof (tmp64);
645         *value = ntohll (tmp64);
646
647         *ret_buffer = buffer;
648         *ret_buffer_len = buffer_len - pkg_length;
649
650         return (0);
651 } /* int parse_part_number */
652
653 static int parse_part_string (void **ret_buffer, int *ret_buffer_len,
654                 char *output, int output_len)
655 {
656         char *buffer = *ret_buffer;
657         int   buffer_len = *ret_buffer_len;
658
659         uint16_t tmp16;
660         size_t header_size = 2 * sizeof (uint16_t);
661
662         uint16_t pkg_length;
663         uint16_t pkg_type;
664
665         if ((buffer_len < 0) || ((size_t) buffer_len < header_size))
666         {
667                 WARNING ("network plugin: parse_part_string: "
668                                 "Packet too short: "
669                                 "Chunk of at least size %u expected, "
670                                 "but buffer has only %i bytes left.",
671                                 (unsigned int) header_size, buffer_len);
672                 return (-1);
673         }
674
675         memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
676         buffer += sizeof (tmp16);
677         pkg_type = ntohs (tmp16);
678
679         memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
680         buffer += sizeof (tmp16);
681         pkg_length = ntohs (tmp16);
682
683         /* Check that packet fits in the input buffer */
684         if (pkg_length > buffer_len)
685         {
686                 WARNING ("network plugin: parse_part_string: "
687                                 "Packet too big: "
688                                 "Chunk of size %hu received, "
689                                 "but buffer has only %i bytes left.",
690                                 pkg_length, buffer_len);
691                 return (-1);
692         }
693
694         /* Check that pkg_length is in the valid range */
695         if (pkg_length <= header_size)
696         {
697                 WARNING ("network plugin: parse_part_string: "
698                                 "Packet too short: "
699                                 "Header claims this packet is only %hu "
700                                 "bytes long.", pkg_length);
701                 return (-1);
702         }
703
704         /* Check that the package data fits into the output buffer.
705          * The previous if-statement ensures that:
706          * `pkg_length > header_size' */
707         if ((output_len < 0)
708                         || ((size_t) output_len < ((size_t) pkg_length - header_size)))
709         {
710                 WARNING ("network plugin: parse_part_string: "
711                                 "Output buffer too small.");
712                 return (-1);
713         }
714
715         /* All sanity checks successfull, let's copy the data over */
716         output_len = pkg_length - header_size;
717         memcpy ((void *) output, (void *) buffer, output_len);
718         buffer += output_len;
719
720         /* For some very weird reason '\0' doesn't do the trick on SPARC in
721          * this statement. */
722         if (output[output_len - 1] != 0)
723         {
724                 WARNING ("network plugin: parse_part_string: "
725                                 "Received string does not end "
726                                 "with a NULL-byte.");
727                 return (-1);
728         }
729
730         *ret_buffer = buffer;
731         *ret_buffer_len = buffer_len - pkg_length;
732
733         return (0);
734 } /* int parse_part_string */
735
736 #if HAVE_GCRYPT_H
737 static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
738     void **ret_buffer, int *ret_buffer_len)
739 {
740   char *buffer = *ret_buffer;
741   size_t buffer_len = (size_t) *ret_buffer_len;
742
743   part_signature_sha256_t ps_received;
744   part_signature_sha256_t ps_expected;
745
746   if (se->shared_secret == NULL)
747   {
748     NOTICE ("network plugin: Received signed network packet but can't verify "
749         "it because no shared secret has been configured. Will accept it.");
750     return (0);
751   }
752
753   if (buffer_len < sizeof (ps_received))
754     return (-ENOMEM);
755
756   memcpy (&ps_received, buffer, sizeof (ps_received));
757
758   memset (&ps_expected, 0, sizeof (ps_expected));
759   ps_expected.head.type = htons (TYPE_SIGN_SHA256);
760   ps_expected.head.length = htons (sizeof (ps_expected));
761   sstrncpy (ps_expected.hash, se->shared_secret, sizeof (ps_expected.hash));
762   memcpy (buffer, &ps_expected, sizeof (ps_expected));
763
764   gcry_md_hash_buffer (GCRY_MD_SHA256, ps_expected.hash, buffer, buffer_len);
765
766   *ret_buffer += sizeof (ps_received);
767
768   if (memcmp (ps_received.hash, ps_expected.hash,
769         sizeof (ps_received.hash)) == 0)
770     return (0);
771   else /* hashes do not match. */
772     return (1);
773 } /* }}} int parse_part_sign_sha256 */
774 /* #endif HAVE_GCRYPT_H */
775
776 #else /* if !HAVE_GCRYPT_H */
777 static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
778     void **ret_buffer, int *ret_buffer_len)
779 {
780   INFO ("network plugin: Received signed packet, but the network "
781       "plugin was not linked with libgcrypt, so I cannot "
782       "verify the signature. The packet will be accepted.");
783   return (0);
784 } /* }}} int parse_part_sign_sha256 */
785 #endif /* !HAVE_GCRYPT_H */
786
787 #if HAVE_GCRYPT_H
788 static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
789                 void **ret_buffer, int *ret_buffer_len)
790 {
791   char  *buffer = *ret_buffer;
792   size_t buffer_len = (size_t) *ret_buffer_len;
793   size_t orig_buffer_len;
794   size_t part_size;
795   size_t buffer_offset = 0;
796   size_t padding_size;
797   part_encryption_aes256_t pea;
798   size_t pea_size;
799   char hash[sizeof (pea.hash)];
800   gcry_error_t err;
801
802   /* Make sure at least the header if available. */
803   if (buffer_len < sizeof (pea))
804   {
805     NOTICE ("network plugin: parse_part_encr_aes256: "
806         "Discarding short packet.");
807     return (-1);
808   }
809
810   if (se->cypher == NULL)
811   {
812     NOTICE ("network plugin: Unable to decrypt packet, because no cypher "
813         "instance is present.");
814     return (-1);
815   }
816
817   /* Size of `pea' without padding. */
818   pea_size = sizeof (pea.head.type) + sizeof (pea.head.length)
819     + sizeof (pea.orig_length) + sizeof (pea.hash);
820
821   /* Copy the header information to `pea' */
822   memcpy (&pea.head, buffer, sizeof (pea.head));
823   buffer_offset += sizeof (pea.head);
824   
825   /* Check the `part size'. */
826   part_size = ntohs (pea.head.length);
827   if (part_size > buffer_len)
828   {
829     NOTICE ("network plugin: parse_part_encr_aes256: "
830         "Discarding large part.");
831     return (-1);
832   }
833
834   /* Decrypt the packet in-place */
835   err = gcry_cipher_decrypt (se->cypher,
836       buffer + sizeof (pea.head), part_size - sizeof (pea.head),
837       /* in = */ NULL, /* in len = */ 0);
838   gcry_cipher_reset (se->cypher);
839   if (err != 0)
840   {
841     ERROR ("network plugin: gcry_cipher_decrypt returned: %s",
842         gcry_strerror (err));
843     return (-1);
844   }
845
846   /* Figure out the length of the payload and the length of the padding. */
847   memcpy (&pea.orig_length, buffer + buffer_offset, sizeof (pea.orig_length));
848   buffer_offset += sizeof (pea.orig_length);
849   orig_buffer_len = ntohs (pea.orig_length);
850   if (orig_buffer_len > (part_size - pea_size))
851   {
852     ERROR ("network plugin: Decryption failed: Invalid original length.");
853     return (-1);
854   }
855
856   /* Calculate the size of the `padding' field. */
857   padding_size = part_size - (orig_buffer_len + pea_size);
858   if (padding_size > sizeof (pea.padding))
859   {
860     ERROR ("network plugin: Part- and original length "
861         "differ more than %zu bytes.", sizeof (pea.padding));
862     return (-1);
863   }
864   buffer_offset += padding_size;
865
866   memcpy (pea.hash, buffer + buffer_offset, sizeof (pea.hash));
867   buffer_offset += sizeof (pea.hash);
868
869   /* Check hash sum */
870   memset (hash, 0, sizeof (hash));
871   gcry_md_hash_buffer (GCRY_MD_SHA1, hash,
872       buffer + buffer_offset, orig_buffer_len);
873   
874   if (memcmp (hash, pea.hash, sizeof (hash)) != 0)
875   {
876     ERROR ("network plugin: Decryption failed: Checksum mismatch.");
877     return (-1);
878   }
879
880   assert ((buffer_offset + orig_buffer_len) <= buffer_len);
881   if ((buffer_offset + orig_buffer_len) < buffer_len)
882   {
883     NOTICE ("network plugin: Trailing, potentially unencrypted data "
884         "(%zu bytes) will be ignored.",
885         buffer_len - (buffer_offset + orig_buffer_len));
886   }
887
888   /* Update return values */
889   *ret_buffer = buffer + buffer_offset;
890   *ret_buffer_len = (int) orig_buffer_len;
891
892   return (0);
893 } /* }}} int parse_part_encr_aes256 */
894 /* #endif HAVE_GCRYPT_H */
895
896 #else /* if !HAVE_GCRYPT_H */
897 static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
898     void **ret_buffer, int *ret_buffer_len)
899 {
900   INFO ("network plugin: Received encrypted packet, but the network "
901       "plugin was not linked with libgcrypt, so I cannot "
902       "decrypt it. The packet will be discarded.");
903   return (-1);
904 } /* }}} int parse_part_encr_aes256 */
905 #endif /* !HAVE_GCRYPT_H */
906
907 static int parse_packet (receive_list_entry_t *rle) /* {{{ */
908 {
909         int status;
910
911         void *buffer;
912         int buffer_len;
913         sockent_t *se;
914
915         value_list_t vl = VALUE_LIST_INIT;
916         notification_t n;
917
918         int packet_was_encrypted = 0;
919         int packet_was_signed = 0;
920 #if HAVE_GCRYPT_H
921         int printed_ignore_warning = 0;
922 #endif /* HAVE_GCRYPT_H */
923
924         buffer = rle->data;
925         buffer_len = rle->data_len;
926
927         /* Look for the correct `sockent_t' */
928         se = listen_sockets;
929         while ((se != NULL) && (se->fd != rle->fd))
930                 se = se->next;
931
932         if (se == NULL)
933         {
934                 ERROR ("network plugin: Got packet from FD %i, but can't "
935                                 "find an appropriate socket entry.",
936                                 rle->fd);
937                 return (-1);
938         }
939
940         memset (&vl, '\0', sizeof (vl));
941         memset (&n, '\0', sizeof (n));
942         status = 0;
943
944         while ((status == 0) && (0 < buffer_len)
945                         && ((unsigned int) buffer_len > sizeof (part_header_t)))
946         {
947                 uint16_t pkg_length;
948                 uint16_t pkg_type;
949
950                 memcpy ((void *) &pkg_type,
951                                 (void *) buffer,
952                                 sizeof (pkg_type));
953                 memcpy ((void *) &pkg_length,
954                                 (void *) (buffer + sizeof (pkg_type)),
955                                 sizeof (pkg_length));
956
957                 pkg_length = ntohs (pkg_length);
958                 pkg_type = ntohs (pkg_type);
959
960                 if (pkg_length > buffer_len)
961                         break;
962                 /* Ensure that this loop terminates eventually */
963                 if (pkg_length < (2 * sizeof (uint16_t)))
964                         break;
965
966                 if (pkg_type == TYPE_ENCR_AES256)
967                 {
968                         status = parse_part_encr_aes256 (se, &buffer, &buffer_len);
969                         if (status != 0)
970                         {
971                                 ERROR ("network plugin: Decrypting AES256 "
972                                                 "part failed "
973                                                 "with status %i.", status);
974                                 break;
975                         }
976                         else
977                         {
978                                 packet_was_encrypted = 1;
979                         }
980                 }
981 #if HAVE_GCRYPT_H
982                 else if ((se->security_level == SECURITY_LEVEL_ENCRYPT)
983                                 && (packet_was_encrypted == 0))
984                 {
985                         if (printed_ignore_warning == 0)
986                         {
987                                 INFO ("network plugin: Unencrypted packet or "
988                                                 "part has been ignored.");
989                                 printed_ignore_warning = 1;
990                         }
991                         buffer = ((char *) buffer) + pkg_length;
992                         continue;
993                 }
994 #endif /* HAVE_GCRYPT_H */
995                 else if (pkg_type == TYPE_SIGN_SHA256)
996                 {
997                         status = parse_part_sign_sha256 (se, &buffer, &buffer_len);
998                         if (status < 0)
999                         {
1000                                 ERROR ("network plugin: Verifying SHA-256 "
1001                                                 "signature failed "
1002                                                 "with status %i.", status);
1003                                 break;
1004                         }
1005                         else if (status > 0)
1006                         {
1007                                 ERROR ("network plugin: Ignoring packet with "
1008                                                 "invalid SHA-256 signature.");
1009                                 break;
1010                         }
1011                         else
1012                         {
1013                                 packet_was_signed = 1;
1014                         }
1015                 }
1016 #if HAVE_GCRYPT_H
1017                 else if ((se->security_level == SECURITY_LEVEL_SIGN)
1018                                 && (packet_was_encrypted == 0)
1019                                 && (packet_was_signed == 0))
1020                 {
1021                         if (printed_ignore_warning == 0)
1022                         {
1023                                 INFO ("network plugin: Unsigned packet or "
1024                                                 "part has been ignored.");
1025                                 printed_ignore_warning = 1;
1026                         }
1027                         buffer = ((char *) buffer) + pkg_length;
1028                         continue;
1029                 }
1030 #endif /* HAVE_GCRYPT_H */
1031                 else if (pkg_type == TYPE_VALUES)
1032                 {
1033                         status = parse_part_values (&buffer, &buffer_len,
1034                                         &vl.values, &vl.values_len);
1035
1036                         if (status != 0)
1037                                 break;
1038
1039                         if ((vl.time > 0)
1040                                         && (strlen (vl.host) > 0)
1041                                         && (strlen (vl.plugin) > 0)
1042                                         && (strlen (vl.type) > 0)
1043                                         && (cache_check (&vl) == 0))
1044                         {
1045                                 plugin_dispatch_values (&vl);
1046                         }
1047                         else
1048                         {
1049                                 DEBUG ("network plugin: parse_packet:"
1050                                                 " NOT dispatching values");
1051                         }
1052
1053                         sfree (vl.values);
1054                 }
1055                 else if (pkg_type == TYPE_TIME)
1056                 {
1057                         uint64_t tmp = 0;
1058                         status = parse_part_number (&buffer, &buffer_len,
1059                                         &tmp);
1060                         if (status == 0)
1061                         {
1062                                 vl.time = (time_t) tmp;
1063                                 n.time = (time_t) tmp;
1064                         }
1065                 }
1066                 else if (pkg_type == TYPE_INTERVAL)
1067                 {
1068                         uint64_t tmp = 0;
1069                         status = parse_part_number (&buffer, &buffer_len,
1070                                         &tmp);
1071                         if (status == 0)
1072                                 vl.interval = (int) tmp;
1073                 }
1074                 else if (pkg_type == TYPE_HOST)
1075                 {
1076                         status = parse_part_string (&buffer, &buffer_len,
1077                                         vl.host, sizeof (vl.host));
1078                         if (status == 0)
1079                                 sstrncpy (n.host, vl.host, sizeof (n.host));
1080                 }
1081                 else if (pkg_type == TYPE_PLUGIN)
1082                 {
1083                         status = parse_part_string (&buffer, &buffer_len,
1084                                         vl.plugin, sizeof (vl.plugin));
1085                         if (status == 0)
1086                                 sstrncpy (n.plugin, vl.plugin,
1087                                                 sizeof (n.plugin));
1088                 }
1089                 else if (pkg_type == TYPE_PLUGIN_INSTANCE)
1090                 {
1091                         status = parse_part_string (&buffer, &buffer_len,
1092                                         vl.plugin_instance,
1093                                         sizeof (vl.plugin_instance));
1094                         if (status == 0)
1095                                 sstrncpy (n.plugin_instance,
1096                                                 vl.plugin_instance,
1097                                                 sizeof (n.plugin_instance));
1098                 }
1099                 else if (pkg_type == TYPE_TYPE)
1100                 {
1101                         status = parse_part_string (&buffer, &buffer_len,
1102                                         vl.type, sizeof (vl.type));
1103                         if (status == 0)
1104                                 sstrncpy (n.type, vl.type, sizeof (n.type));
1105                 }
1106                 else if (pkg_type == TYPE_TYPE_INSTANCE)
1107                 {
1108                         status = parse_part_string (&buffer, &buffer_len,
1109                                         vl.type_instance,
1110                                         sizeof (vl.type_instance));
1111                         if (status == 0)
1112                                 sstrncpy (n.type_instance, vl.type_instance,
1113                                                 sizeof (n.type_instance));
1114                 }
1115                 else if (pkg_type == TYPE_MESSAGE)
1116                 {
1117                         status = parse_part_string (&buffer, &buffer_len,
1118                                         n.message, sizeof (n.message));
1119
1120                         if (status != 0)
1121                         {
1122                                 /* do nothing */
1123                         }
1124                         else if ((n.severity != NOTIF_FAILURE)
1125                                         && (n.severity != NOTIF_WARNING)
1126                                         && (n.severity != NOTIF_OKAY))
1127                         {
1128                                 INFO ("network plugin: "
1129                                                 "Ignoring notification with "
1130                                                 "unknown severity %i.",
1131                                                 n.severity);
1132                         }
1133                         else if (n.time <= 0)
1134                         {
1135                                 INFO ("network plugin: "
1136                                                 "Ignoring notification with "
1137                                                 "time == 0.");
1138                         }
1139                         else if (strlen (n.message) <= 0)
1140                         {
1141                                 INFO ("network plugin: "
1142                                                 "Ignoring notification with "
1143                                                 "an empty message.");
1144                         }
1145                         else
1146                         {
1147                                 plugin_dispatch_notification (&n);
1148                         }
1149                 }
1150                 else if (pkg_type == TYPE_SEVERITY)
1151                 {
1152                         uint64_t tmp = 0;
1153                         status = parse_part_number (&buffer, &buffer_len,
1154                                         &tmp);
1155                         if (status == 0)
1156                                 n.severity = (int) tmp;
1157                 }
1158                 else
1159                 {
1160                         DEBUG ("network plugin: parse_packet: Unknown part"
1161                                         " type: 0x%04hx", pkg_type);
1162                         buffer = ((char *) buffer) + pkg_length;
1163                 }
1164         } /* while (buffer_len > sizeof (part_header_t)) */
1165
1166         return (status);
1167 } /* }}} int parse_packet */
1168
1169 static void free_sockent (sockent_t *se) /* {{{ */
1170 {
1171         sockent_t *next;
1172         while (se != NULL)
1173         {
1174                 next = se->next;
1175
1176 #if HAVE_GCRYPT_H
1177                 if (se->cypher != NULL)
1178                 {
1179                         gcry_cipher_close (se->cypher);
1180                         se->cypher = NULL;
1181                 }
1182                 free (se->shared_secret);
1183 #endif /* HAVE_GCRYPT_H */
1184
1185                 free (se->addr);
1186                 free (se);
1187
1188                 se = next;
1189         }
1190 } /* }}} void free_sockent */
1191
1192 /*
1193  * int network_set_ttl
1194  *
1195  * Set the `IP_MULTICAST_TTL', `IP_TTL', `IPV6_MULTICAST_HOPS' or
1196  * `IPV6_UNICAST_HOPS', depending on which option is applicable.
1197  *
1198  * The `struct addrinfo' is used to destinguish between unicast and multicast
1199  * sockets.
1200  */
1201 static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
1202 {
1203         DEBUG ("network plugin: network_set_ttl: network_config_ttl = %i;",
1204                         network_config_ttl);
1205
1206         if ((network_config_ttl < 1) || (network_config_ttl > 255))
1207                 return (-1);
1208
1209         if (ai->ai_family == AF_INET)
1210         {
1211                 struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
1212                 int optname;
1213
1214                 if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
1215                         optname = IP_MULTICAST_TTL;
1216                 else
1217                         optname = IP_TTL;
1218
1219                 if (setsockopt (se->fd, IPPROTO_IP, optname,
1220                                         &network_config_ttl,
1221                                         sizeof (network_config_ttl)) == -1)
1222                 {
1223                         char errbuf[1024];
1224                         ERROR ("setsockopt: %s",
1225                                         sstrerror (errno, errbuf, sizeof (errbuf)));
1226                         return (-1);
1227                 }
1228         }
1229         else if (ai->ai_family == AF_INET6)
1230         {
1231                 /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
1232                 struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
1233                 int optname;
1234
1235                 if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
1236                         optname = IPV6_MULTICAST_HOPS;
1237                 else
1238                         optname = IPV6_UNICAST_HOPS;
1239
1240                 if (setsockopt (se->fd, IPPROTO_IPV6, optname,
1241                                         &network_config_ttl,
1242                                         sizeof (network_config_ttl)) == -1)
1243                 {
1244                         char errbuf[1024];
1245                         ERROR ("setsockopt: %s",
1246                                         sstrerror (errno, errbuf,
1247                                                 sizeof (errbuf)));
1248                         return (-1);
1249                 }
1250         }
1251
1252         return (0);
1253 } /* int network_set_ttl */
1254
1255 #if HAVE_GCRYPT_H
1256 static int network_set_encryption (sockent_t *se, /* {{{ */
1257                 const char *shared_secret)
1258 {
1259   char hash[32];
1260   gcry_error_t err;
1261
1262   se->shared_secret = sstrdup (shared_secret);
1263
1264   /*
1265    * We use CBC *without* an initialization vector: The cipher is reset after
1266    * each packet and we would have to re-set the IV each time. The first
1267    * encrypted block will contain the SHA-224 checksum anyway, so this should
1268    * be quite unpredictable. Also, there's a 2 byte field in the header that's
1269    * being filled with random numbers. So we only use CBC so the blocks
1270    * *within* one packet are chained.
1271    */
1272   err = gcry_cipher_open (&se->cypher,
1273       GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, /* flags = */ 0);
1274   if (err != 0)
1275   {
1276     ERROR ("network plugin: gcry_cipher_open returned: %s",
1277         gcry_strerror (err));
1278     return (-1);
1279   }
1280
1281   assert (se->shared_secret != NULL);
1282   gcry_md_hash_buffer (GCRY_MD_SHA256, hash,
1283       se->shared_secret, strlen (se->shared_secret));
1284
1285   err = gcry_cipher_setkey (se->cypher, hash, sizeof (hash));
1286   if (err != 0)
1287   {
1288     DEBUG ("network plugin: gcry_cipher_setkey returned: %s",
1289         gcry_strerror (err));
1290     gcry_cipher_close (se->cypher);
1291     se->cypher = NULL;
1292     return (-1);
1293   }
1294
1295   return (0);
1296 } /* }}} int network_set_encryption */
1297 #endif /* HAVE_GCRYPT_H */
1298
1299 static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
1300 {
1301         int loop = 0;
1302         int yes  = 1;
1303
1304         /* allow multiple sockets to use the same PORT number */
1305         if (setsockopt(se->fd, SOL_SOCKET, SO_REUSEADDR,
1306                                 &yes, sizeof(yes)) == -1) {
1307                 char errbuf[1024];
1308                 ERROR ("setsockopt: %s", 
1309                                 sstrerror (errno, errbuf, sizeof (errbuf)));
1310                 return (-1);
1311         }
1312
1313         DEBUG ("fd = %i; calling `bind'", se->fd);
1314
1315         if (bind (se->fd, ai->ai_addr, ai->ai_addrlen) == -1)
1316         {
1317                 char errbuf[1024];
1318                 ERROR ("bind: %s",
1319                                 sstrerror (errno, errbuf, sizeof (errbuf)));
1320                 return (-1);
1321         }
1322
1323         if (ai->ai_family == AF_INET)
1324         {
1325                 struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
1326                 if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
1327                 {
1328                         struct ip_mreq mreq;
1329
1330                         DEBUG ("fd = %i; IPv4 multicast address found", se->fd);
1331
1332                         mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
1333                         mreq.imr_interface.s_addr = htonl (INADDR_ANY);
1334
1335                         if (setsockopt (se->fd, IPPROTO_IP, IP_MULTICAST_LOOP,
1336                                                 &loop, sizeof (loop)) == -1)
1337                         {
1338                                 char errbuf[1024];
1339                                 ERROR ("setsockopt: %s",
1340                                                 sstrerror (errno, errbuf,
1341                                                         sizeof (errbuf)));
1342                                 return (-1);
1343                         }
1344
1345                         if (setsockopt (se->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1346                                                 &mreq, sizeof (mreq)) == -1)
1347                         {
1348                                 char errbuf[1024];
1349                                 ERROR ("setsockopt: %s",
1350                                                 sstrerror (errno, errbuf,
1351                                                         sizeof (errbuf)));
1352                                 return (-1);
1353                         }
1354                 }
1355         }
1356         else if (ai->ai_family == AF_INET6)
1357         {
1358                 /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
1359                 struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
1360                 if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
1361                 {
1362                         struct ipv6_mreq mreq;
1363
1364                         DEBUG ("fd = %i; IPv6 multicast address found", se->fd);
1365
1366                         memcpy (&mreq.ipv6mr_multiaddr,
1367                                         &addr->sin6_addr,
1368                                         sizeof (addr->sin6_addr));
1369
1370                         /* http://developer.apple.com/documentation/Darwin/Reference/ManPages/man4/ip6.4.html
1371                          * ipv6mr_interface may be set to zeroes to
1372                          * choose the default multicast interface or to
1373                          * the index of a particular multicast-capable
1374                          * interface if the host is multihomed.
1375                          * Membership is associ-associated with a
1376                          * single interface; programs running on
1377                          * multihomed hosts may need to join the same
1378                          * group on more than one interface.*/
1379                         mreq.ipv6mr_interface = 0;
1380
1381                         if (setsockopt (se->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
1382                                                 &loop, sizeof (loop)) == -1)
1383                         {
1384                                 char errbuf[1024];
1385                                 ERROR ("setsockopt: %s",
1386                                                 sstrerror (errno, errbuf,
1387                                                         sizeof (errbuf)));
1388                                 return (-1);
1389                         }
1390
1391                         if (setsockopt (se->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
1392                                                 &mreq, sizeof (mreq)) == -1)
1393                         {
1394                                 char errbuf[1024];
1395                                 ERROR ("setsockopt: %s",
1396                                                 sstrerror (errno, errbuf,
1397                                                         sizeof (errbuf)));
1398                                 return (-1);
1399                         }
1400                 }
1401         }
1402
1403         return (0);
1404 } /* int network_bind_socket */
1405
1406 #define CREATE_SOCKET_FLAGS_LISTEN    0x0001
1407 static sockent_t *network_create_socket (const char *node, /* {{{ */
1408                 const char *service,
1409                 const char *shared_secret,
1410                 int security_level,
1411                 int flags)
1412 {
1413         struct addrinfo  ai_hints;
1414         struct addrinfo *ai_list, *ai_ptr;
1415         int              ai_return;
1416
1417         sockent_t *se_head = NULL;
1418         sockent_t *se_tail = NULL;
1419
1420         DEBUG ("node = %s, service = %s", node, service);
1421
1422         memset (&ai_hints, '\0', sizeof (ai_hints));
1423         ai_hints.ai_flags    = 0;
1424 #ifdef AI_PASSIVE
1425         ai_hints.ai_flags |= AI_PASSIVE;
1426 #endif
1427 #ifdef AI_ADDRCONFIG
1428         ai_hints.ai_flags |= AI_ADDRCONFIG;
1429 #endif
1430         ai_hints.ai_family   = AF_UNSPEC;
1431         ai_hints.ai_socktype = SOCK_DGRAM;
1432         ai_hints.ai_protocol = IPPROTO_UDP;
1433
1434         ai_return = getaddrinfo (node, service, &ai_hints, &ai_list);
1435         if (ai_return != 0)
1436         {
1437                 char errbuf[1024];
1438                 ERROR ("getaddrinfo (%s, %s): %s",
1439                                 (node == NULL) ? "(null)" : node,
1440                                 (service == NULL) ? "(null)" : service,
1441                                 (ai_return == EAI_SYSTEM)
1442                                 ? sstrerror (errno, errbuf, sizeof (errbuf))
1443                                 : gai_strerror (ai_return));
1444                 return (NULL);
1445         }
1446
1447         for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
1448         {
1449                 sockent_t *se;
1450                 int status;
1451
1452                 if ((se = (sockent_t *) malloc (sizeof (sockent_t))) == NULL)
1453                 {
1454                         char errbuf[1024];
1455                         ERROR ("malloc: %s",
1456                                         sstrerror (errno, errbuf,
1457                                                 sizeof (errbuf)));
1458                         continue;
1459                 }
1460
1461                 if ((se->addr = (struct sockaddr_storage *) malloc (sizeof (struct sockaddr_storage))) == NULL)
1462                 {
1463                         char errbuf[1024];
1464                         ERROR ("malloc: %s",
1465                                         sstrerror (errno, errbuf,
1466                                                 sizeof (errbuf)));
1467                         free (se);
1468                         continue;
1469                 }
1470
1471                 assert (sizeof (struct sockaddr_storage) >= ai_ptr->ai_addrlen);
1472                 memset (se->addr, '\0', sizeof (struct sockaddr_storage));
1473                 memcpy (se->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
1474                 se->addrlen = ai_ptr->ai_addrlen;
1475
1476                 se->fd   = socket (ai_ptr->ai_family,
1477                                 ai_ptr->ai_socktype,
1478                                 ai_ptr->ai_protocol);
1479                 se->next = NULL;
1480
1481                 if (se->fd == -1)
1482                 {
1483                         char errbuf[1024];
1484                         ERROR ("socket: %s",
1485                                         sstrerror (errno, errbuf,
1486                                                 sizeof (errbuf)));
1487                         free (se->addr);
1488                         free (se);
1489                         continue;
1490                 }
1491
1492                 if ((flags & CREATE_SOCKET_FLAGS_LISTEN) != 0)
1493                 {
1494                         status = network_bind_socket (se, ai_ptr);
1495                         if (status != 0)
1496                         {
1497                                 close (se->fd);
1498                                 free (se->addr);
1499                                 free (se);
1500                                 continue;
1501                         }
1502                 }
1503                 else /* sending socket */
1504                 {
1505                         network_set_ttl (se, ai_ptr);
1506                 }
1507
1508 #if HAVE_GCRYPT_H
1509                 se->security_level = security_level;
1510                 se->shared_secret = NULL;
1511                 se->cypher = NULL;
1512                 if (shared_secret != NULL)
1513                 {
1514                         status = network_set_encryption (se, shared_secret);
1515                         if ((status != 0) && (security_level <= SECURITY_LEVEL_SIGN))
1516                         {
1517                                 WARNING ("network plugin: Starting cryptograp"
1518                                                 "hic subsystem failed. Since "
1519                                                 "security level `Sign' or "
1520                                                 "`None' is configured I will "
1521                                                 "continue.");
1522                         }
1523                         else if (status != 0)
1524                         {
1525                                 ERROR ("network plugin: Starting cryptograp"
1526                                                 "hic subsystem failed. "
1527                                                 "Because the security level "
1528                                                 "is set to `Encrypt' I will "
1529                                                 "not continue!");
1530                                 close (se->fd);
1531                                 free (se->addr);
1532                                 free (se);
1533                                 continue;
1534                         }
1535                 } /* if (shared_secret != NULL) */
1536 #else
1537                 /* Make compiler happy */
1538                 security_level = 0;
1539                 shared_secret = NULL;
1540 #endif /* HAVE_GCRYPT_H */
1541
1542                 if (se_tail == NULL)
1543                 {
1544                         se_head = se;
1545                         se_tail = se;
1546                 }
1547                 else
1548                 {
1549                         se_tail->next = se;
1550                         se_tail = se;
1551                 }
1552
1553                 /* We don't open more than one write-socket per node/service pair.. */
1554                 if ((flags & CREATE_SOCKET_FLAGS_LISTEN) == 0)
1555                         break;
1556         }
1557
1558         freeaddrinfo (ai_list);
1559
1560         return (se_head);
1561 } /* }}} sockent_t *network_create_socket */
1562
1563 static sockent_t *network_create_default_socket (int flags) /* {{{ */
1564 {
1565         sockent_t *se_ptr  = NULL;
1566         sockent_t *se_head = NULL;
1567         sockent_t *se_tail = NULL;
1568
1569         se_ptr = network_create_socket (NET_DEFAULT_V6_ADDR, NET_DEFAULT_PORT,
1570                         /* shared secret = */ NULL, SECURITY_LEVEL_NONE,
1571                         flags);
1572
1573         /* Don't send to the same machine in IPv6 and IPv4 if both are available. */
1574         if (((flags & CREATE_SOCKET_FLAGS_LISTEN) == 0) && (se_ptr != NULL))
1575                 return (se_ptr);
1576
1577         if (se_ptr != NULL)
1578         {
1579                 se_head = se_ptr;
1580                 se_tail = se_ptr;
1581                 while (se_tail->next != NULL)
1582                         se_tail = se_tail->next;
1583         }
1584
1585         se_ptr = network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT,
1586                         /* shared secret = */ NULL, SECURITY_LEVEL_NONE,
1587                         flags);
1588
1589         if (se_tail == NULL)
1590                 return (se_ptr);
1591
1592         se_tail->next = se_ptr;
1593         return (se_head);
1594 } /* }}} sockent_t *network_create_default_socket */
1595
1596 static int network_add_listen_socket (const char *node, /* {{{ */
1597     const char *service, const char *shared_secret, int security_level)
1598 {
1599         sockent_t *se;
1600         sockent_t *se_ptr;
1601         int se_num = 0;
1602
1603         int flags;
1604
1605         flags = CREATE_SOCKET_FLAGS_LISTEN;
1606
1607         if (service == NULL)
1608                 service = NET_DEFAULT_PORT;
1609
1610         if (node == NULL)
1611                 se = network_create_default_socket (flags);
1612         else
1613                 se = network_create_socket (node, service,
1614                     shared_secret, security_level, flags);
1615
1616         if (se == NULL)
1617                 return (-1);
1618
1619         for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
1620                 se_num++;
1621
1622         listen_sockets_pollfd = realloc (listen_sockets_pollfd,
1623                         (listen_sockets_num + se_num)
1624                         * sizeof (struct pollfd));
1625
1626         for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
1627         {
1628                 listen_sockets_pollfd[listen_sockets_num].fd = se_ptr->fd;
1629                 listen_sockets_pollfd[listen_sockets_num].events = POLLIN | POLLPRI;
1630                 listen_sockets_pollfd[listen_sockets_num].revents = 0;
1631                 listen_sockets_num++;
1632         } /* for (se) */
1633
1634         se_ptr = listen_sockets;
1635         while ((se_ptr != NULL) && (se_ptr->next != NULL))
1636                 se_ptr = se_ptr->next;
1637
1638         if (se_ptr == NULL)
1639                 listen_sockets = se;
1640         else
1641                 se_ptr->next = se;
1642
1643         return (0);
1644 } /* }}} int network_add_listen_socket */
1645
1646 static int network_add_sending_socket (const char *node, /* {{{ */
1647     const char *service, const char *shared_secret, int security_level)
1648 {
1649         sockent_t *se;
1650         sockent_t *se_ptr;
1651
1652         if (service == NULL)
1653                 service = NET_DEFAULT_PORT;
1654
1655         if (node == NULL)
1656                 se = network_create_default_socket (/* flags = */ 0);
1657         else
1658                 se = network_create_socket (node, service,
1659                                 shared_secret, security_level,
1660                                 /* flags = */ 0);
1661
1662         if (se == NULL)
1663                 return (-1);
1664
1665         if (sending_sockets == NULL)
1666         {
1667                 sending_sockets = se;
1668                 return (0);
1669         }
1670
1671         for (se_ptr = sending_sockets; se_ptr->next != NULL; se_ptr = se_ptr->next)
1672                 /* seek end */;
1673
1674         se_ptr->next = se;
1675         return (0);
1676 } /* }}} int network_add_sending_socket */
1677
1678 static void *dispatch_thread (void __attribute__((unused)) *arg)
1679 {
1680   while (42)
1681   {
1682     receive_list_entry_t *ent;
1683
1684     /* Lock and wait for more data to come in */
1685     pthread_mutex_lock (&receive_list_lock);
1686     while ((listen_loop == 0)
1687         && (receive_list_head == NULL))
1688       pthread_cond_wait (&receive_list_cond, &receive_list_lock);
1689
1690     /* Remove the head entry and unlock */
1691     ent = receive_list_head;
1692     if (ent != NULL)
1693       receive_list_head = ent->next;
1694     pthread_mutex_unlock (&receive_list_lock);
1695
1696     /* Check whether we are supposed to exit. We do NOT check `listen_loop'
1697      * because we dispatch all missing packets before shutting down. */
1698     if (ent == NULL)
1699       break;
1700
1701     parse_packet (ent);
1702
1703     sfree (ent);
1704   } /* while (42) */
1705
1706   return (NULL);
1707 } /* void *dispatch_thread */
1708
1709 static int network_receive (void)
1710 {
1711         char buffer[BUFF_SIZE];
1712         int  buffer_len;
1713
1714         int i;
1715         int status;
1716
1717         receive_list_entry_t *private_list_head;
1718         receive_list_entry_t *private_list_tail;
1719
1720         if (listen_sockets_num == 0)
1721                 network_add_listen_socket (/* node = */ NULL,
1722                                 /* service = */ NULL,
1723                                 /* shared secret = */ NULL,
1724                                 /* encryption = */ 0);
1725
1726         if (listen_sockets_num == 0)
1727         {
1728                 ERROR ("network: Failed to open a listening socket.");
1729                 return (-1);
1730         }
1731
1732         private_list_head = NULL;
1733         private_list_tail = NULL;
1734
1735         while (listen_loop == 0)
1736         {
1737                 status = poll (listen_sockets_pollfd, listen_sockets_num, -1);
1738
1739                 if (status <= 0)
1740                 {
1741                         char errbuf[1024];
1742                         if (errno == EINTR)
1743                                 continue;
1744                         ERROR ("poll failed: %s",
1745                                         sstrerror (errno, errbuf, sizeof (errbuf)));
1746                         return (-1);
1747                 }
1748
1749                 for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
1750                 {
1751                         receive_list_entry_t *ent;
1752
1753                         if ((listen_sockets_pollfd[i].revents
1754                                                 & (POLLIN | POLLPRI)) == 0)
1755                                 continue;
1756                         status--;
1757
1758                         buffer_len = recv (listen_sockets_pollfd[i].fd,
1759                                         buffer, sizeof (buffer),
1760                                         0 /* no flags */);
1761                         if (buffer_len < 0)
1762                         {
1763                                 char errbuf[1024];
1764                                 ERROR ("recv failed: %s",
1765                                                 sstrerror (errno, errbuf,
1766                                                         sizeof (errbuf)));
1767                                 return (-1);
1768                         }
1769
1770                         /* TODO: Possible performance enhancement: Do not free
1771                          * these entries in the dispatch thread but put them in
1772                          * another list, so we don't have to allocate more and
1773                          * more of these structures. */
1774                         ent = malloc (sizeof (receive_list_entry_t));
1775                         if (ent == NULL)
1776                         {
1777                                 ERROR ("network plugin: malloc failed.");
1778                                 return (-1);
1779                         }
1780                         memset (ent, 0, sizeof (receive_list_entry_t));
1781                         ent->fd = listen_sockets_pollfd[i].fd;
1782                         ent->next = NULL;
1783
1784                         /* Hopefully this be optimized out by the compiler. It
1785                          * might help prevent stupid bugs in the future though.
1786                          */
1787                         assert (sizeof (ent->data) == sizeof (buffer));
1788
1789                         memcpy (ent->data, buffer, buffer_len);
1790                         ent->data_len = buffer_len;
1791
1792                         if (private_list_head == NULL)
1793                                 private_list_head = ent;
1794                         else
1795                                 private_list_tail->next = ent;
1796                         private_list_tail = ent;
1797
1798                         /* Do not block here. Blocking here has led to
1799                          * insufficient performance in the past. */
1800                         if (pthread_mutex_trylock (&receive_list_lock) == 0)
1801                         {
1802                                 if (receive_list_head == NULL)
1803                                         receive_list_head = private_list_head;
1804                                 else
1805                                         receive_list_tail->next = private_list_head;
1806                                 receive_list_tail = private_list_tail;
1807
1808                                 private_list_head = NULL;
1809                                 private_list_tail = NULL;
1810
1811                                 pthread_cond_signal (&receive_list_cond);
1812                                 pthread_mutex_unlock (&receive_list_lock);
1813                         }
1814                 } /* for (listen_sockets_pollfd) */
1815         } /* while (listen_loop == 0) */
1816
1817         /* Make sure everything is dispatched before exiting. */
1818         if (private_list_head != NULL)
1819         {
1820                 pthread_mutex_lock (&receive_list_lock);
1821
1822                 if (receive_list_head == NULL)
1823                         receive_list_head = private_list_head;
1824                 else
1825                         receive_list_tail->next = private_list_head;
1826                 receive_list_tail = private_list_tail;
1827
1828                 private_list_head = NULL;
1829                 private_list_tail = NULL;
1830
1831                 pthread_cond_signal (&receive_list_cond);
1832                 pthread_mutex_unlock (&receive_list_lock);
1833         }
1834
1835         return (0);
1836 } /* int network_receive */
1837
1838 static void *receive_thread (void __attribute__((unused)) *arg)
1839 {
1840         return (network_receive () ? (void *) 1 : (void *) 0);
1841 } /* void *receive_thread */
1842
1843 static void network_init_buffer (void)
1844 {
1845         memset (send_buffer, 0, sizeof (send_buffer));
1846         send_buffer_ptr = send_buffer;
1847         send_buffer_fill = 0;
1848
1849         memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
1850 } /* int network_init_buffer */
1851
1852 static void networt_send_buffer_plain (const sockent_t *se, /* {{{ */
1853                 const char *buffer, size_t buffer_size)
1854 {
1855         int status;
1856
1857         while (42)
1858         {
1859                 status = sendto (se->fd, buffer, buffer_size, 0 /* no flags */,
1860                                 (struct sockaddr *) se->addr, se->addrlen);
1861                 if (status < 0)
1862                 {
1863                         char errbuf[1024];
1864                         if (errno == EINTR)
1865                                 continue;
1866                         ERROR ("network plugin: sendto failed: %s",
1867                                         sstrerror (errno, errbuf,
1868                                                 sizeof (errbuf)));
1869                         break;
1870                 }
1871
1872                 break;
1873         } /* while (42) */
1874 } /* }}} void networt_send_buffer_plain */
1875
1876 #if HAVE_GCRYPT_H
1877 static void networt_send_buffer_signed (const sockent_t *se, /* {{{ */
1878                 const char *in_buffer, size_t in_buffer_size)
1879 {
1880         part_signature_sha256_t ps;
1881         char buffer[sizeof (ps) + in_buffer_size];
1882         char hash[sizeof (ps.hash)];
1883
1884         /* Initialize the `ps' structure. */
1885         memset (&ps, 0, sizeof (ps));
1886         ps.head.type = htons (TYPE_SIGN_SHA256);
1887         ps.head.length = htons ((uint16_t) sizeof (ps));
1888         sstrncpy (ps.hash, se->shared_secret, sizeof (ps.hash));
1889
1890         /* Prepend the signature. */
1891         memcpy (buffer, &ps, sizeof (ps));
1892         memcpy (buffer + sizeof (ps), in_buffer, in_buffer_size);
1893
1894         /* Calculate the hash value. */
1895         gcry_md_hash_buffer (GCRY_MD_SHA256, hash, buffer, sizeof (buffer));
1896
1897         /* Copy the hash value into the buffer. */
1898         memcpy (ps.hash, hash, sizeof (ps.hash));
1899         memcpy (buffer, &ps, sizeof (ps));
1900
1901         networt_send_buffer_plain (se, buffer, sizeof (buffer));
1902 } /* }}} void networt_send_buffer_signed */
1903
1904 static void networt_send_buffer_encrypted (const sockent_t *se, /* {{{ */
1905                 const char *in_buffer, size_t in_buffer_size)
1906 {
1907   part_encryption_aes256_t pea;
1908   char buffer[sizeof (pea) + in_buffer_size];
1909   size_t buffer_size;
1910   size_t buffer_offset;
1911   size_t padding_size;
1912   gcry_error_t err;
1913
1914   /* Round to the next multiple of 16, because AES has a block size of 128 bit.
1915    * the first four bytes of `pea' are not encrypted and must be subtracted. */
1916   buffer_size = sizeof (pea.orig_length) + sizeof (pea.hash) + in_buffer_size;
1917   padding_size = buffer_size;
1918   buffer_size = (buffer_size + 15) / 16;
1919   buffer_size = buffer_size * 16;
1920   padding_size = buffer_size - padding_size;
1921   assert (padding_size <= sizeof (pea.padding));
1922   buffer_size += sizeof (pea.head);
1923
1924   DEBUG ("network plugin: networt_send_buffer_encrypted: "
1925       "buffer_size = %zu;", buffer_size);
1926
1927   /* Initialize the header fields */
1928   memset (&pea, 0, sizeof (pea));
1929   pea.head.type = htons (TYPE_ENCR_AES256);
1930   pea.head.length = htons ((uint16_t) buffer_size);
1931   pea.orig_length = htons ((uint16_t) in_buffer_size);
1932
1933   /* Fill the extra field with random values. Some entropy in the encrypted
1934    * data is usually not a bad thing, I hope. */
1935   if (padding_size > 0)
1936     gcry_randomize (&pea.padding, padding_size, GCRY_STRONG_RANDOM);
1937
1938   /* Create hash of the payload */
1939   gcry_md_hash_buffer (GCRY_MD_SHA1, pea.hash, in_buffer, in_buffer_size);
1940
1941   /* Initialize the buffer */
1942   buffer_offset = 0;
1943   memset (buffer, 0, sizeof (buffer));
1944
1945   memcpy (buffer + buffer_offset, &pea.head, sizeof (pea.head));
1946   buffer_offset += sizeof (pea.head);
1947
1948   memcpy (buffer + buffer_offset, &pea.orig_length, sizeof (pea.orig_length));
1949   buffer_offset += sizeof (pea.orig_length);
1950
1951   if (padding_size > 0)
1952   {
1953     memcpy (buffer + buffer_offset, &pea.padding, padding_size);
1954     buffer_offset += padding_size;
1955   }
1956
1957   memcpy (buffer + buffer_offset, &pea.hash, sizeof (pea.hash));
1958   buffer_offset += sizeof (pea.hash);
1959
1960   memcpy (buffer + buffer_offset, in_buffer, in_buffer_size);
1961   buffer_offset += in_buffer_size;
1962
1963   assert (buffer_offset == buffer_size);
1964
1965   /* Encrypt the buffer in-place */
1966   err = gcry_cipher_encrypt (se->cypher,
1967       buffer + sizeof (pea.head), buffer_size - sizeof (pea.head),
1968       /* in = */ NULL, /* in len = */ 0);
1969   gcry_cipher_reset (se->cypher);
1970   if (err != 0)
1971   {
1972     ERROR ("network plugin: gcry_cipher_encrypt returned: %s",
1973         gcry_strerror (err));
1974     return;
1975   }
1976
1977   /* Send it out without further modifications */
1978   networt_send_buffer_plain (se, buffer, buffer_size);
1979 } /* }}} void networt_send_buffer_encrypted */
1980 #endif /* HAVE_GCRYPT_H */
1981
1982 static void network_send_buffer (char *buffer, size_t buffer_len) /* {{{ */
1983 {
1984   sockent_t *se;
1985
1986   DEBUG ("network plugin: network_send_buffer: buffer_len = %zu", buffer_len);
1987
1988   for (se = sending_sockets; se != NULL; se = se->next)
1989   {
1990 #if HAVE_GCRYPT_H
1991     if (se->security_level == SECURITY_LEVEL_ENCRYPT)
1992       networt_send_buffer_encrypted (se, buffer, buffer_len);
1993     else if (se->security_level == SECURITY_LEVEL_SIGN)
1994       networt_send_buffer_signed (se, buffer, buffer_len);
1995     else /* if (se->security_level == SECURITY_LEVEL_NONE) */
1996 #endif /* HAVE_GCRYPT_H */
1997       networt_send_buffer_plain (se, buffer, buffer_len);
1998   } /* for (sending_sockets) */
1999 } /* }}} void network_send_buffer */
2000
2001 static int add_to_buffer (char *buffer, int buffer_size, /* {{{ */
2002                 value_list_t *vl_def,
2003                 const data_set_t *ds, const value_list_t *vl)
2004 {
2005         char *buffer_orig = buffer;
2006
2007         if (strcmp (vl_def->host, vl->host) != 0)
2008         {
2009                 if (write_part_string (&buffer, &buffer_size, TYPE_HOST,
2010                                         vl->host, strlen (vl->host)) != 0)
2011                         return (-1);
2012                 sstrncpy (vl_def->host, vl->host, sizeof (vl_def->host));
2013         }
2014
2015         if (vl_def->time != vl->time)
2016         {
2017                 if (write_part_number (&buffer, &buffer_size, TYPE_TIME,
2018                                         (uint64_t) vl->time))
2019                         return (-1);
2020                 vl_def->time = vl->time;
2021         }
2022
2023         if (vl_def->interval != vl->interval)
2024         {
2025                 if (write_part_number (&buffer, &buffer_size, TYPE_INTERVAL,
2026                                         (uint64_t) vl->interval))
2027                         return (-1);
2028                 vl_def->interval = vl->interval;
2029         }
2030
2031         if (strcmp (vl_def->plugin, vl->plugin) != 0)
2032         {
2033                 if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN,
2034                                         vl->plugin, strlen (vl->plugin)) != 0)
2035                         return (-1);
2036                 sstrncpy (vl_def->plugin, vl->plugin, sizeof (vl_def->plugin));
2037         }
2038
2039         if (strcmp (vl_def->plugin_instance, vl->plugin_instance) != 0)
2040         {
2041                 if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
2042                                         vl->plugin_instance,
2043                                         strlen (vl->plugin_instance)) != 0)
2044                         return (-1);
2045                 sstrncpy (vl_def->plugin_instance, vl->plugin_instance, sizeof (vl_def->plugin_instance));
2046         }
2047
2048         if (strcmp (vl_def->type, vl->type) != 0)
2049         {
2050                 if (write_part_string (&buffer, &buffer_size, TYPE_TYPE,
2051                                         vl->type, strlen (vl->type)) != 0)
2052                         return (-1);
2053                 sstrncpy (vl_def->type, ds->type, sizeof (vl_def->type));
2054         }
2055
2056         if (strcmp (vl_def->type_instance, vl->type_instance) != 0)
2057         {
2058                 if (write_part_string (&buffer, &buffer_size, TYPE_TYPE_INSTANCE,
2059                                         vl->type_instance,
2060                                         strlen (vl->type_instance)) != 0)
2061                         return (-1);
2062                 sstrncpy (vl_def->type_instance, vl->type_instance, sizeof (vl_def->type_instance));
2063         }
2064         
2065         if (write_part_values (&buffer, &buffer_size, ds, vl) != 0)
2066                 return (-1);
2067
2068         return (buffer - buffer_orig);
2069 } /* }}} int add_to_buffer */
2070
2071 static void flush_buffer (void)
2072 {
2073         DEBUG ("network plugin: flush_buffer: send_buffer_fill = %i",
2074                         send_buffer_fill);
2075
2076         network_send_buffer (send_buffer, (size_t) send_buffer_fill);
2077         network_init_buffer ();
2078 }
2079
2080 static int network_write (const data_set_t *ds, const value_list_t *vl,
2081                 user_data_t __attribute__((unused)) *user_data)
2082 {
2083         int status;
2084
2085         /* If the value is already in the cache, we have received it via the
2086          * network. We write it again if forwarding is activated. It's then in
2087          * the cache and should we receive it again we will ignore it. */
2088         status = cache_check (vl);
2089         if ((network_config_forward == 0)
2090                         && (status != 0))
2091                 return (0);
2092
2093         pthread_mutex_lock (&send_buffer_lock);
2094
2095         status = add_to_buffer (send_buffer_ptr,
2096                         sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
2097                         &send_buffer_vl,
2098                         ds, vl);
2099         if (status >= 0)
2100         {
2101                 /* status == bytes added to the buffer */
2102                 send_buffer_fill += status;
2103                 send_buffer_ptr  += status;
2104         }
2105         else
2106         {
2107                 flush_buffer ();
2108
2109                 status = add_to_buffer (send_buffer_ptr,
2110                                 sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
2111                                 &send_buffer_vl,
2112                                 ds, vl);
2113
2114                 if (status >= 0)
2115                 {
2116                         send_buffer_fill += status;
2117                         send_buffer_ptr  += status;
2118                 }
2119         }
2120
2121         if (status < 0)
2122         {
2123                 ERROR ("network plugin: Unable to append to the "
2124                                 "buffer for some weird reason");
2125         }
2126         else if ((sizeof (send_buffer) - send_buffer_fill) < 15)
2127         {
2128                 flush_buffer ();
2129         }
2130
2131         pthread_mutex_unlock (&send_buffer_lock);
2132
2133         return ((status < 0) ? -1 : 0);
2134 } /* int network_write */
2135
2136 static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */
2137     int *retval)
2138 {
2139   if ((ci->values_num != 1)
2140       || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN)
2141         && (ci->values[0].type != OCONFIG_TYPE_STRING)))
2142   {
2143     ERROR ("network plugin: The `%s' config option needs "
2144         "exactly one boolean argument.", ci->key);
2145     return (-1);
2146   }
2147
2148   if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
2149   {
2150     if (ci->values[0].value.boolean)
2151       *retval = 1;
2152     else
2153       *retval = 0;
2154   }
2155   else
2156   {
2157     char *str = ci->values[0].value.string;
2158
2159     if ((strcasecmp ("true", str) == 0)
2160         || (strcasecmp ("yes", str) == 0)
2161         || (strcasecmp ("on", str) == 0))
2162       *retval = 1;
2163     else if ((strcasecmp ("false", str) == 0)
2164         || (strcasecmp ("no", str) == 0)
2165         || (strcasecmp ("off", str) == 0))
2166       *retval = 0;
2167     else
2168     {
2169       ERROR ("network plugin: Cannot parse string value `%s' of the `%s' "
2170           "option as boolean value.",
2171           str, ci->key);
2172       return (-1);
2173     }
2174   }
2175
2176   return (0);
2177 } /* }}} int network_config_set_boolean */
2178
2179 static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
2180 {
2181   int tmp;
2182   if ((ci->values_num != 1)
2183       || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
2184   {
2185     WARNING ("network plugin: The `TimeToLive' config option needs exactly "
2186         "one numeric argument.");
2187     return (-1);
2188   }
2189
2190   tmp = (int) ci->values[0].value.number;
2191   if ((tmp > 0) && (tmp <= 255))
2192     network_config_ttl = tmp;
2193
2194   return (0);
2195 } /* }}} int network_config_set_ttl */
2196
2197 #if HAVE_GCRYPT_H
2198 static int network_config_set_security_level (oconfig_item_t *ci, /* {{{ */
2199     int *retval)
2200 {
2201   char *str;
2202   if ((ci->values_num != 1)
2203       || (ci->values[0].type != OCONFIG_TYPE_STRING))
2204   {
2205     WARNING ("network plugin: The `SecurityLevel' config option needs exactly "
2206         "one string argument.");
2207     return (-1);
2208   }
2209
2210   str = ci->values[0].value.string;
2211   if (strcasecmp ("Encrypt", str) == 0)
2212     *retval = SECURITY_LEVEL_ENCRYPT;
2213   else if (strcasecmp ("Sign", str) == 0)
2214     *retval = SECURITY_LEVEL_SIGN;
2215   else if (strcasecmp ("None", str) == 0)
2216     *retval = SECURITY_LEVEL_NONE;
2217   else
2218   {
2219     WARNING ("network plugin: Unknown security level: %s.", str);
2220     return (-1);
2221   }
2222
2223   return (0);
2224 } /* }}} int network_config_set_security_level */
2225 #endif /* HAVE_GCRYPT_H */
2226
2227 static int network_config_listen_server (const oconfig_item_t *ci) /* {{{ */
2228 {
2229   char *node;
2230   char *service;
2231   char *shared_secret = NULL;
2232   int security_level = SECURITY_LEVEL_NONE;
2233   int i;
2234
2235   if ((ci->values_num < 1) || (ci->values_num > 2)
2236       || (ci->values[0].type != OCONFIG_TYPE_STRING)
2237       || ((ci->values_num > 1) && (ci->values[1].type != OCONFIG_TYPE_STRING)))
2238   {
2239     ERROR ("network plugin: The `%s' config option needs "
2240         "one or two string arguments.", ci->key);
2241     return (-1);
2242   }
2243
2244   node = ci->values[0].value.string;
2245   if (ci->values_num >= 2)
2246     service = ci->values[1].value.string;
2247   else
2248     service = NULL;
2249
2250   for (i = 0; i < ci->children_num; i++)
2251   {
2252     oconfig_item_t *child = ci->children + i;
2253
2254 #if HAVE_GCRYPT_H
2255     if (strcasecmp ("Secret", child->key) == 0)
2256     {
2257       if ((child->values_num == 1)
2258           && (child->values[0].type == OCONFIG_TYPE_STRING))
2259         shared_secret = child->values[0].value.string;
2260       else
2261         ERROR ("network plugin: The `Secret' option needs exactly one string "
2262             "argument.");
2263     }
2264     else if (strcasecmp ("SecurityLevel", child->key) == 0)
2265       network_config_set_security_level (child, &security_level);
2266     else
2267 #endif /* HAVE_GCRYPT_H */
2268     {
2269       WARNING ("network plugin: Option `%s' is not allowed here.",
2270           child->key);
2271     }
2272   }
2273
2274   if ((security_level > SECURITY_LEVEL_NONE) && (shared_secret == NULL))
2275   {
2276     ERROR ("network plugin: A security level higher than `none' was "
2277         "requested, but no shared key was given. Cowardly refusing to open "
2278         "this socket!");
2279     return (-1);
2280   }
2281
2282   if (strcasecmp ("Listen", ci->key) == 0)
2283     network_add_listen_socket (node, service, shared_secret, security_level);
2284   else
2285     network_add_sending_socket (node, service, shared_secret, security_level);
2286
2287   return (0);
2288 } /* }}} int network_config_listen_server */
2289
2290 static int network_config_set_cache_flush (const oconfig_item_t *ci) /* {{{ */
2291 {
2292   int tmp;
2293   if ((ci->values_num != 1)
2294       || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
2295   {
2296     WARNING ("network plugin: The `CacheFlush' config option needs exactly "
2297         "one numeric argument.");
2298     return (-1);
2299   }
2300
2301   tmp = (int) ci->values[0].value.number;
2302   if (tmp > 0)
2303     network_config_ttl = tmp;
2304
2305   return (0);
2306 } /* }}} int network_config_set_cache_flush */
2307
2308 static int network_config (oconfig_item_t *ci) /* {{{ */
2309 {
2310   int i;
2311
2312   for (i = 0; i < ci->children_num; i++)
2313   {
2314     oconfig_item_t *child = ci->children + i;
2315
2316     if ((strcasecmp ("Listen", child->key) == 0)
2317         || (strcasecmp ("Server", child->key) == 0))
2318       network_config_listen_server (child);
2319     else if (strcasecmp ("TimeToLive", child->key) == 0)
2320       network_config_set_ttl (child);
2321     else if (strcasecmp ("Forward", child->key) == 0)
2322       network_config_set_boolean (child, &network_config_forward);
2323     else if (strcasecmp ("CacheFlush", child->key) == 0)
2324       network_config_set_cache_flush (child);
2325     else
2326     {
2327       WARNING ("network plugin: Option `%s' is not allowed here.",
2328           child->key);
2329     }
2330   }
2331
2332   return (0);
2333 } /* }}} int network_config */
2334
2335 static int network_notification (const notification_t *n,
2336                 user_data_t __attribute__((unused)) *user_data)
2337 {
2338   char  buffer[BUFF_SIZE];
2339   char *buffer_ptr = buffer;
2340   int   buffer_free = sizeof (buffer);
2341   int   status;
2342
2343   memset (buffer, '\0', sizeof (buffer));
2344
2345
2346   status = write_part_number (&buffer_ptr, &buffer_free, TYPE_TIME,
2347       (uint64_t) n->time);
2348   if (status != 0)
2349     return (-1);
2350
2351   status = write_part_number (&buffer_ptr, &buffer_free, TYPE_SEVERITY,
2352       (uint64_t) n->severity);
2353   if (status != 0)
2354     return (-1);
2355
2356   if (strlen (n->host) > 0)
2357   {
2358     status = write_part_string (&buffer_ptr, &buffer_free, TYPE_HOST,
2359         n->host, strlen (n->host));
2360     if (status != 0)
2361       return (-1);
2362   }
2363
2364   if (strlen (n->plugin) > 0)
2365   {
2366     status = write_part_string (&buffer_ptr, &buffer_free, TYPE_PLUGIN,
2367         n->plugin, strlen (n->plugin));
2368     if (status != 0)
2369       return (-1);
2370   }
2371
2372   if (strlen (n->plugin_instance) > 0)
2373   {
2374     status = write_part_string (&buffer_ptr, &buffer_free,
2375         TYPE_PLUGIN_INSTANCE,
2376         n->plugin_instance, strlen (n->plugin_instance));
2377     if (status != 0)
2378       return (-1);
2379   }
2380
2381   if (strlen (n->type) > 0)
2382   {
2383     status = write_part_string (&buffer_ptr, &buffer_free, TYPE_TYPE,
2384         n->type, strlen (n->type));
2385     if (status != 0)
2386       return (-1);
2387   }
2388
2389   if (strlen (n->type_instance) > 0)
2390   {
2391     status = write_part_string (&buffer_ptr, &buffer_free, TYPE_TYPE_INSTANCE,
2392         n->type_instance, strlen (n->type_instance));
2393     if (status != 0)
2394       return (-1);
2395   }
2396
2397   status = write_part_string (&buffer_ptr, &buffer_free, TYPE_MESSAGE,
2398       n->message, strlen (n->message));
2399   if (status != 0)
2400     return (-1);
2401
2402   network_send_buffer (buffer, sizeof (buffer) - buffer_free);
2403
2404   return (0);
2405 } /* int network_notification */
2406
2407 static int network_shutdown (void)
2408 {
2409         listen_loop++;
2410
2411         /* Kill the listening thread */
2412         if (receive_thread_running != 0)
2413         {
2414                 INFO ("network plugin: Stopping receive thread.");
2415                 pthread_kill (receive_thread_id, SIGTERM);
2416                 pthread_join (receive_thread_id, NULL /* no return value */);
2417                 memset (&receive_thread_id, 0, sizeof (receive_thread_id));
2418                 receive_thread_running = 0;
2419         }
2420
2421         /* Shutdown the dispatching thread */
2422         if (dispatch_thread_running != 0)
2423         {
2424                 INFO ("network plugin: Stopping dispatch thread.");
2425                 pthread_mutex_lock (&receive_list_lock);
2426                 pthread_cond_broadcast (&receive_list_cond);
2427                 pthread_mutex_unlock (&receive_list_lock);
2428                 pthread_join (dispatch_thread_id, /* ret = */ NULL);
2429                 dispatch_thread_running = 0;
2430         }
2431
2432         free_sockent (listen_sockets);
2433
2434         if (send_buffer_fill > 0)
2435                 flush_buffer ();
2436
2437         if (cache_tree != NULL)
2438         {
2439                 void *key;
2440                 void *value;
2441
2442                 while (c_avl_pick (cache_tree, &key, &value) == 0)
2443                 {
2444                         sfree (key);
2445                         sfree (value);
2446                 }
2447                 c_avl_destroy (cache_tree);
2448                 cache_tree = NULL;
2449         }
2450
2451         /* TODO: Close `sending_sockets' */
2452
2453         plugin_unregister_config ("network");
2454         plugin_unregister_init ("network");
2455         plugin_unregister_write ("network");
2456         plugin_unregister_shutdown ("network");
2457
2458         /* Let the init function do it's move again ;) */
2459         cache_flush_last = 0;
2460
2461         return (0);
2462 } /* int network_shutdown */
2463
2464 static int network_init (void)
2465 {
2466         /* Check if we were already initialized. If so, just return - there's
2467          * nothing more to do (for now, that is). */
2468         if (cache_flush_last != 0)
2469                 return (0);
2470
2471         plugin_register_shutdown ("network", network_shutdown);
2472
2473         network_init_buffer ();
2474
2475         cache_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
2476         cache_flush_last = time (NULL);
2477
2478         /* setup socket(s) and so on */
2479         if (sending_sockets != NULL)
2480         {
2481                 plugin_register_write ("network", network_write,
2482                                 /* user_data = */ NULL);
2483                 plugin_register_notification ("network", network_notification,
2484                                 /* user_data = */ NULL);
2485         }
2486
2487         /* If no threads need to be started, return here. */
2488         if ((listen_sockets_num == 0)
2489                         || ((dispatch_thread_running != 0)
2490                                 && (receive_thread_running != 0)))
2491                 return (0);
2492
2493         if (dispatch_thread_running == 0)
2494         {
2495                 int status;
2496                 status = pthread_create (&dispatch_thread_id,
2497                                 NULL /* no attributes */,
2498                                 dispatch_thread,
2499                                 NULL /* no argument */);
2500                 if (status != 0)
2501                 {
2502                         char errbuf[1024];
2503                         ERROR ("network: pthread_create failed: %s",
2504                                         sstrerror (errno, errbuf,
2505                                                 sizeof (errbuf)));
2506                 }
2507                 else
2508                 {
2509                         dispatch_thread_running = 1;
2510                 }
2511         }
2512
2513         if (receive_thread_running == 0)
2514         {
2515                 int status;
2516                 status = pthread_create (&receive_thread_id,
2517                                 NULL /* no attributes */,
2518                                 receive_thread,
2519                                 NULL /* no argument */);
2520                 if (status != 0)
2521                 {
2522                         char errbuf[1024];
2523                         ERROR ("network: pthread_create failed: %s",
2524                                         sstrerror (errno, errbuf,
2525                                                 sizeof (errbuf)));
2526                 }
2527                 else
2528                 {
2529                         receive_thread_running = 1;
2530                 }
2531         }
2532
2533         return (0);
2534 } /* int network_init */
2535
2536 /* 
2537  * The flush option of the network plugin cannot flush individual identifiers.
2538  * All the values are added to a buffer and sent when the buffer is full, the
2539  * requested value may or may not be in there, it's not worth finding out. We
2540  * just send the buffer if `flush'  is called - if the requested value was in
2541  * there, good. If not, well, then there is nothing to flush.. -octo
2542  */
2543 static int network_flush (int timeout,
2544                 const char __attribute__((unused)) *identifier,
2545                 user_data_t __attribute__((unused)) *user_data)
2546 {
2547         pthread_mutex_lock (&send_buffer_lock);
2548
2549         if (((time (NULL) - cache_flush_last) >= timeout)
2550                         && (send_buffer_fill > 0))
2551         {
2552                 flush_buffer ();
2553         }
2554
2555         pthread_mutex_unlock (&send_buffer_lock);
2556
2557         return (0);
2558 } /* int network_flush */
2559
2560 void module_register (void)
2561 {
2562         plugin_register_complex_config ("network", network_config);
2563         plugin_register_init   ("network", network_init);
2564         plugin_register_flush   ("network", network_flush,
2565                         /* user_data = */ NULL);
2566 } /* void module_register */
2567
2568 /* vim: set fdm=marker : */