920b891342f56bfe954177204fe52e767cd0593d
[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   char hash[sizeof (ps_received.hash)];
745
746   gcry_md_hd_t hd;
747   gcry_error_t err;
748   unsigned char *hash_ptr;
749
750   if (se->shared_secret == NULL)
751   {
752     NOTICE ("network plugin: Received signed network packet but can't verify "
753         "it because no shared secret has been configured. Will accept it.");
754     return (0);
755   }
756
757   if (buffer_len < sizeof (ps_received))
758     return (-ENOMEM);
759
760   hd = NULL;
761   err = gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
762   if (err != 0)
763   {
764     ERROR ("network plugin: Creating HMAC object failed: %s",
765         gcry_strerror (err));
766     return (-1);
767   }
768
769   err = gcry_md_setkey (hd, se->shared_secret,
770       strlen (se->shared_secret));
771   if (err != 0)
772   {
773     ERROR ("network plugin: gcry_md_setkey failed: %s",
774         gcry_strerror (err));
775     gcry_md_close (hd);
776     return (-1);
777   }
778
779   memcpy (&ps_received, buffer, sizeof (ps_received));
780   /* TODO: Check ps_received.head.length! */
781
782   buffer += sizeof (ps_received);
783   buffer_len -= sizeof (ps_received);
784
785   gcry_md_write (hd, buffer, buffer_len);
786   hash_ptr = gcry_md_read (hd, GCRY_MD_SHA256);
787   if (hash_ptr == NULL)
788   {
789     ERROR ("network plugin: gcry_md_read failed.");
790     gcry_md_close (hd);
791     return (-1);
792   }
793   memcpy (hash, hash_ptr, sizeof (hash));
794
795   gcry_md_close (hd);
796   hd = NULL;
797
798   *ret_buffer += sizeof (ps_received);
799   *ret_buffer_len -= sizeof (ps_received);
800
801   if (memcmp (ps_received.hash, hash,
802         sizeof (ps_received.hash)) == 0)
803     return (0);
804   else /* hashes do not match. */
805     return (1);
806 } /* }}} int parse_part_sign_sha256 */
807 /* #endif HAVE_GCRYPT_H */
808
809 #else /* if !HAVE_GCRYPT_H */
810 static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
811     void **ret_buffer, int *ret_buffer_len)
812 {
813   INFO ("network plugin: Received signed packet, but the network "
814       "plugin was not linked with libgcrypt, so I cannot "
815       "verify the signature. The packet will be accepted.");
816   return (0);
817 } /* }}} int parse_part_sign_sha256 */
818 #endif /* !HAVE_GCRYPT_H */
819
820 #if HAVE_GCRYPT_H
821 static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
822                 void **ret_buffer, int *ret_buffer_len)
823 {
824   char  *buffer = *ret_buffer;
825   size_t buffer_len = (size_t) *ret_buffer_len;
826   size_t orig_buffer_len;
827   size_t part_size;
828   size_t buffer_offset = 0;
829   size_t padding_size;
830   part_encryption_aes256_t pea;
831   size_t pea_size;
832   char hash[sizeof (pea.hash)];
833   gcry_error_t err;
834
835   /* Make sure at least the header if available. */
836   if (buffer_len < sizeof (pea))
837   {
838     NOTICE ("network plugin: parse_part_encr_aes256: "
839         "Discarding short packet.");
840     return (-1);
841   }
842
843   if (se->cypher == NULL)
844   {
845     NOTICE ("network plugin: Unable to decrypt packet, because no cypher "
846         "instance is present.");
847     return (-1);
848   }
849
850   /* Size of `pea' without padding. */
851   pea_size = sizeof (pea.head.type) + sizeof (pea.head.length)
852     + sizeof (pea.orig_length) + sizeof (pea.hash);
853
854   /* Copy the header information to `pea' */
855   memcpy (&pea.head, buffer, sizeof (pea.head));
856   buffer_offset += sizeof (pea.head);
857   
858   /* Check the `part size'. */
859   part_size = ntohs (pea.head.length);
860   if (part_size > buffer_len)
861   {
862     NOTICE ("network plugin: parse_part_encr_aes256: "
863         "Discarding large part.");
864     return (-1);
865   }
866
867   /* Decrypt the packet in-place */
868   err = gcry_cipher_decrypt (se->cypher,
869       buffer + sizeof (pea.head), part_size - sizeof (pea.head),
870       /* in = */ NULL, /* in len = */ 0);
871   gcry_cipher_reset (se->cypher);
872   if (err != 0)
873   {
874     ERROR ("network plugin: gcry_cipher_decrypt returned: %s",
875         gcry_strerror (err));
876     return (-1);
877   }
878
879   /* Figure out the length of the payload and the length of the padding. */
880   memcpy (&pea.orig_length, buffer + buffer_offset, sizeof (pea.orig_length));
881   buffer_offset += sizeof (pea.orig_length);
882   orig_buffer_len = ntohs (pea.orig_length);
883   if (orig_buffer_len > (part_size - pea_size))
884   {
885     ERROR ("network plugin: Decryption failed: Invalid original length.");
886     return (-1);
887   }
888
889   /* Calculate the size of the `padding' field. */
890   padding_size = part_size - (orig_buffer_len + pea_size);
891   if (padding_size > sizeof (pea.padding))
892   {
893     ERROR ("network plugin: Part- and original length "
894         "differ more than %zu bytes.", sizeof (pea.padding));
895     return (-1);
896   }
897   buffer_offset += padding_size;
898
899   memcpy (pea.hash, buffer + buffer_offset, sizeof (pea.hash));
900   buffer_offset += sizeof (pea.hash);
901
902   /* Check hash sum */
903   memset (hash, 0, sizeof (hash));
904   gcry_md_hash_buffer (GCRY_MD_SHA1, hash,
905       buffer + buffer_offset, orig_buffer_len);
906   
907   if (memcmp (hash, pea.hash, sizeof (hash)) != 0)
908   {
909     ERROR ("network plugin: Decryption failed: Checksum mismatch.");
910     return (-1);
911   }
912
913   assert ((buffer_offset + orig_buffer_len) <= buffer_len);
914   if ((buffer_offset + orig_buffer_len) < buffer_len)
915   {
916     NOTICE ("network plugin: Trailing, potentially unencrypted data "
917         "(%zu bytes) will be ignored.",
918         buffer_len - (buffer_offset + orig_buffer_len));
919   }
920
921   /* Update return values */
922   *ret_buffer = buffer + buffer_offset;
923   *ret_buffer_len = (int) orig_buffer_len;
924
925   return (0);
926 } /* }}} int parse_part_encr_aes256 */
927 /* #endif HAVE_GCRYPT_H */
928
929 #else /* if !HAVE_GCRYPT_H */
930 static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
931     void **ret_buffer, int *ret_buffer_len)
932 {
933   INFO ("network plugin: Received encrypted packet, but the network "
934       "plugin was not linked with libgcrypt, so I cannot "
935       "decrypt it. The packet will be discarded.");
936   return (-1);
937 } /* }}} int parse_part_encr_aes256 */
938 #endif /* !HAVE_GCRYPT_H */
939
940 static int parse_packet (receive_list_entry_t *rle) /* {{{ */
941 {
942         int status;
943
944         void *buffer;
945         int buffer_len;
946         sockent_t *se;
947
948         value_list_t vl = VALUE_LIST_INIT;
949         notification_t n;
950
951         int packet_was_encrypted = 0;
952         int packet_was_signed = 0;
953 #if HAVE_GCRYPT_H
954         int printed_ignore_warning = 0;
955 #endif /* HAVE_GCRYPT_H */
956
957         buffer = rle->data;
958         buffer_len = rle->data_len;
959
960         /* Look for the correct `sockent_t' */
961         se = listen_sockets;
962         while ((se != NULL) && (se->fd != rle->fd))
963                 se = se->next;
964
965         if (se == NULL)
966         {
967                 ERROR ("network plugin: Got packet from FD %i, but can't "
968                                 "find an appropriate socket entry.",
969                                 rle->fd);
970                 return (-1);
971         }
972
973         memset (&vl, '\0', sizeof (vl));
974         memset (&n, '\0', sizeof (n));
975         status = 0;
976
977         while ((status == 0) && (0 < buffer_len)
978                         && ((unsigned int) buffer_len > sizeof (part_header_t)))
979         {
980                 uint16_t pkg_length;
981                 uint16_t pkg_type;
982
983                 memcpy ((void *) &pkg_type,
984                                 (void *) buffer,
985                                 sizeof (pkg_type));
986                 memcpy ((void *) &pkg_length,
987                                 (void *) (buffer + sizeof (pkg_type)),
988                                 sizeof (pkg_length));
989
990                 pkg_length = ntohs (pkg_length);
991                 pkg_type = ntohs (pkg_type);
992
993                 if (pkg_length > buffer_len)
994                         break;
995                 /* Ensure that this loop terminates eventually */
996                 if (pkg_length < (2 * sizeof (uint16_t)))
997                         break;
998
999                 if (pkg_type == TYPE_ENCR_AES256)
1000                 {
1001                         status = parse_part_encr_aes256 (se, &buffer, &buffer_len);
1002                         if (status != 0)
1003                         {
1004                                 ERROR ("network plugin: Decrypting AES256 "
1005                                                 "part failed "
1006                                                 "with status %i.", status);
1007                                 break;
1008                         }
1009                         else
1010                         {
1011                                 packet_was_encrypted = 1;
1012                         }
1013                 }
1014 #if HAVE_GCRYPT_H
1015                 else if ((se->security_level == SECURITY_LEVEL_ENCRYPT)
1016                                 && (packet_was_encrypted == 0))
1017                 {
1018                         if (printed_ignore_warning == 0)
1019                         {
1020                                 INFO ("network plugin: Unencrypted packet or "
1021                                                 "part has been ignored.");
1022                                 printed_ignore_warning = 1;
1023                         }
1024                         buffer = ((char *) buffer) + pkg_length;
1025                         continue;
1026                 }
1027 #endif /* HAVE_GCRYPT_H */
1028                 else if (pkg_type == TYPE_SIGN_SHA256)
1029                 {
1030                         status = parse_part_sign_sha256 (se, &buffer, &buffer_len);
1031                         if (status < 0)
1032                         {
1033                                 ERROR ("network plugin: Verifying SHA-256 "
1034                                                 "signature failed "
1035                                                 "with status %i.", status);
1036                                 break;
1037                         }
1038                         else if (status > 0)
1039                         {
1040                                 ERROR ("network plugin: Ignoring packet with "
1041                                                 "invalid SHA-256 signature.");
1042                                 break;
1043                         }
1044                         else
1045                         {
1046                                 packet_was_signed = 1;
1047                         }
1048                 }
1049 #if HAVE_GCRYPT_H
1050                 else if ((se->security_level == SECURITY_LEVEL_SIGN)
1051                                 && (packet_was_encrypted == 0)
1052                                 && (packet_was_signed == 0))
1053                 {
1054                         if (printed_ignore_warning == 0)
1055                         {
1056                                 INFO ("network plugin: Unsigned packet or "
1057                                                 "part has been ignored.");
1058                                 printed_ignore_warning = 1;
1059                         }
1060                         buffer = ((char *) buffer) + pkg_length;
1061                         continue;
1062                 }
1063 #endif /* HAVE_GCRYPT_H */
1064                 else if (pkg_type == TYPE_VALUES)
1065                 {
1066                         status = parse_part_values (&buffer, &buffer_len,
1067                                         &vl.values, &vl.values_len);
1068
1069                         if (status != 0)
1070                                 break;
1071
1072                         if ((vl.time > 0)
1073                                         && (strlen (vl.host) > 0)
1074                                         && (strlen (vl.plugin) > 0)
1075                                         && (strlen (vl.type) > 0)
1076                                         && (cache_check (&vl) == 0))
1077                         {
1078                                 plugin_dispatch_values (&vl);
1079                         }
1080                         else
1081                         {
1082                                 DEBUG ("network plugin: parse_packet:"
1083                                                 " NOT dispatching values");
1084                         }
1085
1086                         sfree (vl.values);
1087                 }
1088                 else if (pkg_type == TYPE_TIME)
1089                 {
1090                         uint64_t tmp = 0;
1091                         status = parse_part_number (&buffer, &buffer_len,
1092                                         &tmp);
1093                         if (status == 0)
1094                         {
1095                                 vl.time = (time_t) tmp;
1096                                 n.time = (time_t) tmp;
1097                         }
1098                 }
1099                 else if (pkg_type == TYPE_INTERVAL)
1100                 {
1101                         uint64_t tmp = 0;
1102                         status = parse_part_number (&buffer, &buffer_len,
1103                                         &tmp);
1104                         if (status == 0)
1105                                 vl.interval = (int) tmp;
1106                 }
1107                 else if (pkg_type == TYPE_HOST)
1108                 {
1109                         status = parse_part_string (&buffer, &buffer_len,
1110                                         vl.host, sizeof (vl.host));
1111                         if (status == 0)
1112                                 sstrncpy (n.host, vl.host, sizeof (n.host));
1113                 }
1114                 else if (pkg_type == TYPE_PLUGIN)
1115                 {
1116                         status = parse_part_string (&buffer, &buffer_len,
1117                                         vl.plugin, sizeof (vl.plugin));
1118                         if (status == 0)
1119                                 sstrncpy (n.plugin, vl.plugin,
1120                                                 sizeof (n.plugin));
1121                 }
1122                 else if (pkg_type == TYPE_PLUGIN_INSTANCE)
1123                 {
1124                         status = parse_part_string (&buffer, &buffer_len,
1125                                         vl.plugin_instance,
1126                                         sizeof (vl.plugin_instance));
1127                         if (status == 0)
1128                                 sstrncpy (n.plugin_instance,
1129                                                 vl.plugin_instance,
1130                                                 sizeof (n.plugin_instance));
1131                 }
1132                 else if (pkg_type == TYPE_TYPE)
1133                 {
1134                         status = parse_part_string (&buffer, &buffer_len,
1135                                         vl.type, sizeof (vl.type));
1136                         if (status == 0)
1137                                 sstrncpy (n.type, vl.type, sizeof (n.type));
1138                 }
1139                 else if (pkg_type == TYPE_TYPE_INSTANCE)
1140                 {
1141                         status = parse_part_string (&buffer, &buffer_len,
1142                                         vl.type_instance,
1143                                         sizeof (vl.type_instance));
1144                         if (status == 0)
1145                                 sstrncpy (n.type_instance, vl.type_instance,
1146                                                 sizeof (n.type_instance));
1147                 }
1148                 else if (pkg_type == TYPE_MESSAGE)
1149                 {
1150                         status = parse_part_string (&buffer, &buffer_len,
1151                                         n.message, sizeof (n.message));
1152
1153                         if (status != 0)
1154                         {
1155                                 /* do nothing */
1156                         }
1157                         else if ((n.severity != NOTIF_FAILURE)
1158                                         && (n.severity != NOTIF_WARNING)
1159                                         && (n.severity != NOTIF_OKAY))
1160                         {
1161                                 INFO ("network plugin: "
1162                                                 "Ignoring notification with "
1163                                                 "unknown severity %i.",
1164                                                 n.severity);
1165                         }
1166                         else if (n.time <= 0)
1167                         {
1168                                 INFO ("network plugin: "
1169                                                 "Ignoring notification with "
1170                                                 "time == 0.");
1171                         }
1172                         else if (strlen (n.message) <= 0)
1173                         {
1174                                 INFO ("network plugin: "
1175                                                 "Ignoring notification with "
1176                                                 "an empty message.");
1177                         }
1178                         else
1179                         {
1180                                 plugin_dispatch_notification (&n);
1181                         }
1182                 }
1183                 else if (pkg_type == TYPE_SEVERITY)
1184                 {
1185                         uint64_t tmp = 0;
1186                         status = parse_part_number (&buffer, &buffer_len,
1187                                         &tmp);
1188                         if (status == 0)
1189                                 n.severity = (int) tmp;
1190                 }
1191                 else
1192                 {
1193                         DEBUG ("network plugin: parse_packet: Unknown part"
1194                                         " type: 0x%04hx", pkg_type);
1195                         buffer = ((char *) buffer) + pkg_length;
1196                 }
1197         } /* while (buffer_len > sizeof (part_header_t)) */
1198
1199         return (status);
1200 } /* }}} int parse_packet */
1201
1202 static void free_sockent (sockent_t *se) /* {{{ */
1203 {
1204         sockent_t *next;
1205         while (se != NULL)
1206         {
1207                 next = se->next;
1208
1209 #if HAVE_GCRYPT_H
1210                 if (se->cypher != NULL)
1211                 {
1212                         gcry_cipher_close (se->cypher);
1213                         se->cypher = NULL;
1214                 }
1215                 free (se->shared_secret);
1216 #endif /* HAVE_GCRYPT_H */
1217
1218                 free (se->addr);
1219                 free (se);
1220
1221                 se = next;
1222         }
1223 } /* }}} void free_sockent */
1224
1225 /*
1226  * int network_set_ttl
1227  *
1228  * Set the `IP_MULTICAST_TTL', `IP_TTL', `IPV6_MULTICAST_HOPS' or
1229  * `IPV6_UNICAST_HOPS', depending on which option is applicable.
1230  *
1231  * The `struct addrinfo' is used to destinguish between unicast and multicast
1232  * sockets.
1233  */
1234 static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
1235 {
1236         DEBUG ("network plugin: network_set_ttl: network_config_ttl = %i;",
1237                         network_config_ttl);
1238
1239         if ((network_config_ttl < 1) || (network_config_ttl > 255))
1240                 return (-1);
1241
1242         if (ai->ai_family == AF_INET)
1243         {
1244                 struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
1245                 int optname;
1246
1247                 if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
1248                         optname = IP_MULTICAST_TTL;
1249                 else
1250                         optname = IP_TTL;
1251
1252                 if (setsockopt (se->fd, IPPROTO_IP, optname,
1253                                         &network_config_ttl,
1254                                         sizeof (network_config_ttl)) == -1)
1255                 {
1256                         char errbuf[1024];
1257                         ERROR ("setsockopt: %s",
1258                                         sstrerror (errno, errbuf, sizeof (errbuf)));
1259                         return (-1);
1260                 }
1261         }
1262         else if (ai->ai_family == AF_INET6)
1263         {
1264                 /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
1265                 struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
1266                 int optname;
1267
1268                 if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
1269                         optname = IPV6_MULTICAST_HOPS;
1270                 else
1271                         optname = IPV6_UNICAST_HOPS;
1272
1273                 if (setsockopt (se->fd, IPPROTO_IPV6, optname,
1274                                         &network_config_ttl,
1275                                         sizeof (network_config_ttl)) == -1)
1276                 {
1277                         char errbuf[1024];
1278                         ERROR ("setsockopt: %s",
1279                                         sstrerror (errno, errbuf,
1280                                                 sizeof (errbuf)));
1281                         return (-1);
1282                 }
1283         }
1284
1285         return (0);
1286 } /* int network_set_ttl */
1287
1288 #if HAVE_GCRYPT_H
1289 static int network_set_encryption (sockent_t *se, /* {{{ */
1290                 const char *shared_secret)
1291 {
1292   char hash[32];
1293   gcry_error_t err;
1294
1295   se->shared_secret = sstrdup (shared_secret);
1296
1297   /*
1298    * We use CBC *without* an initialization vector: The cipher is reset after
1299    * each packet and we would have to re-set the IV each time. The first
1300    * encrypted block will contain the SHA-224 checksum anyway, so this should
1301    * be quite unpredictable. Also, there's a 2 byte field in the header that's
1302    * being filled with random numbers. So we only use CBC so the blocks
1303    * *within* one packet are chained.
1304    */
1305   err = gcry_cipher_open (&se->cypher,
1306       GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, /* flags = */ 0);
1307   if (err != 0)
1308   {
1309     ERROR ("network plugin: gcry_cipher_open returned: %s",
1310         gcry_strerror (err));
1311     return (-1);
1312   }
1313
1314   assert (se->shared_secret != NULL);
1315   gcry_md_hash_buffer (GCRY_MD_SHA256, hash,
1316       se->shared_secret, strlen (se->shared_secret));
1317
1318   err = gcry_cipher_setkey (se->cypher, hash, sizeof (hash));
1319   if (err != 0)
1320   {
1321     DEBUG ("network plugin: gcry_cipher_setkey returned: %s",
1322         gcry_strerror (err));
1323     gcry_cipher_close (se->cypher);
1324     se->cypher = NULL;
1325     return (-1);
1326   }
1327
1328   return (0);
1329 } /* }}} int network_set_encryption */
1330 #endif /* HAVE_GCRYPT_H */
1331
1332 static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
1333 {
1334         int loop = 0;
1335         int yes  = 1;
1336
1337         /* allow multiple sockets to use the same PORT number */
1338         if (setsockopt(se->fd, SOL_SOCKET, SO_REUSEADDR,
1339                                 &yes, sizeof(yes)) == -1) {
1340                 char errbuf[1024];
1341                 ERROR ("setsockopt: %s", 
1342                                 sstrerror (errno, errbuf, sizeof (errbuf)));
1343                 return (-1);
1344         }
1345
1346         DEBUG ("fd = %i; calling `bind'", se->fd);
1347
1348         if (bind (se->fd, ai->ai_addr, ai->ai_addrlen) == -1)
1349         {
1350                 char errbuf[1024];
1351                 ERROR ("bind: %s",
1352                                 sstrerror (errno, errbuf, sizeof (errbuf)));
1353                 return (-1);
1354         }
1355
1356         if (ai->ai_family == AF_INET)
1357         {
1358                 struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
1359                 if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
1360                 {
1361                         struct ip_mreq mreq;
1362
1363                         DEBUG ("fd = %i; IPv4 multicast address found", se->fd);
1364
1365                         mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
1366                         mreq.imr_interface.s_addr = htonl (INADDR_ANY);
1367
1368                         if (setsockopt (se->fd, IPPROTO_IP, IP_MULTICAST_LOOP,
1369                                                 &loop, sizeof (loop)) == -1)
1370                         {
1371                                 char errbuf[1024];
1372                                 ERROR ("setsockopt: %s",
1373                                                 sstrerror (errno, errbuf,
1374                                                         sizeof (errbuf)));
1375                                 return (-1);
1376                         }
1377
1378                         if (setsockopt (se->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1379                                                 &mreq, sizeof (mreq)) == -1)
1380                         {
1381                                 char errbuf[1024];
1382                                 ERROR ("setsockopt: %s",
1383                                                 sstrerror (errno, errbuf,
1384                                                         sizeof (errbuf)));
1385                                 return (-1);
1386                         }
1387                 }
1388         }
1389         else if (ai->ai_family == AF_INET6)
1390         {
1391                 /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
1392                 struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
1393                 if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
1394                 {
1395                         struct ipv6_mreq mreq;
1396
1397                         DEBUG ("fd = %i; IPv6 multicast address found", se->fd);
1398
1399                         memcpy (&mreq.ipv6mr_multiaddr,
1400                                         &addr->sin6_addr,
1401                                         sizeof (addr->sin6_addr));
1402
1403                         /* http://developer.apple.com/documentation/Darwin/Reference/ManPages/man4/ip6.4.html
1404                          * ipv6mr_interface may be set to zeroes to
1405                          * choose the default multicast interface or to
1406                          * the index of a particular multicast-capable
1407                          * interface if the host is multihomed.
1408                          * Membership is associ-associated with a
1409                          * single interface; programs running on
1410                          * multihomed hosts may need to join the same
1411                          * group on more than one interface.*/
1412                         mreq.ipv6mr_interface = 0;
1413
1414                         if (setsockopt (se->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
1415                                                 &loop, sizeof (loop)) == -1)
1416                         {
1417                                 char errbuf[1024];
1418                                 ERROR ("setsockopt: %s",
1419                                                 sstrerror (errno, errbuf,
1420                                                         sizeof (errbuf)));
1421                                 return (-1);
1422                         }
1423
1424                         if (setsockopt (se->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
1425                                                 &mreq, sizeof (mreq)) == -1)
1426                         {
1427                                 char errbuf[1024];
1428                                 ERROR ("setsockopt: %s",
1429                                                 sstrerror (errno, errbuf,
1430                                                         sizeof (errbuf)));
1431                                 return (-1);
1432                         }
1433                 }
1434         }
1435
1436         return (0);
1437 } /* int network_bind_socket */
1438
1439 #define CREATE_SOCKET_FLAGS_LISTEN    0x0001
1440 static sockent_t *network_create_socket (const char *node, /* {{{ */
1441                 const char *service,
1442                 const char *shared_secret,
1443                 int security_level,
1444                 int flags)
1445 {
1446         struct addrinfo  ai_hints;
1447         struct addrinfo *ai_list, *ai_ptr;
1448         int              ai_return;
1449
1450         sockent_t *se_head = NULL;
1451         sockent_t *se_tail = NULL;
1452
1453         DEBUG ("node = %s, service = %s", node, service);
1454
1455         memset (&ai_hints, '\0', sizeof (ai_hints));
1456         ai_hints.ai_flags    = 0;
1457 #ifdef AI_PASSIVE
1458         ai_hints.ai_flags |= AI_PASSIVE;
1459 #endif
1460 #ifdef AI_ADDRCONFIG
1461         ai_hints.ai_flags |= AI_ADDRCONFIG;
1462 #endif
1463         ai_hints.ai_family   = AF_UNSPEC;
1464         ai_hints.ai_socktype = SOCK_DGRAM;
1465         ai_hints.ai_protocol = IPPROTO_UDP;
1466
1467         ai_return = getaddrinfo (node, service, &ai_hints, &ai_list);
1468         if (ai_return != 0)
1469         {
1470                 char errbuf[1024];
1471                 ERROR ("getaddrinfo (%s, %s): %s",
1472                                 (node == NULL) ? "(null)" : node,
1473                                 (service == NULL) ? "(null)" : service,
1474                                 (ai_return == EAI_SYSTEM)
1475                                 ? sstrerror (errno, errbuf, sizeof (errbuf))
1476                                 : gai_strerror (ai_return));
1477                 return (NULL);
1478         }
1479
1480         for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
1481         {
1482                 sockent_t *se;
1483                 int status;
1484
1485                 if ((se = (sockent_t *) malloc (sizeof (sockent_t))) == NULL)
1486                 {
1487                         char errbuf[1024];
1488                         ERROR ("malloc: %s",
1489                                         sstrerror (errno, errbuf,
1490                                                 sizeof (errbuf)));
1491                         continue;
1492                 }
1493
1494                 if ((se->addr = (struct sockaddr_storage *) malloc (sizeof (struct sockaddr_storage))) == NULL)
1495                 {
1496                         char errbuf[1024];
1497                         ERROR ("malloc: %s",
1498                                         sstrerror (errno, errbuf,
1499                                                 sizeof (errbuf)));
1500                         free (se);
1501                         continue;
1502                 }
1503
1504                 assert (sizeof (struct sockaddr_storage) >= ai_ptr->ai_addrlen);
1505                 memset (se->addr, '\0', sizeof (struct sockaddr_storage));
1506                 memcpy (se->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
1507                 se->addrlen = ai_ptr->ai_addrlen;
1508
1509                 se->fd   = socket (ai_ptr->ai_family,
1510                                 ai_ptr->ai_socktype,
1511                                 ai_ptr->ai_protocol);
1512                 se->next = NULL;
1513
1514                 if (se->fd == -1)
1515                 {
1516                         char errbuf[1024];
1517                         ERROR ("socket: %s",
1518                                         sstrerror (errno, errbuf,
1519                                                 sizeof (errbuf)));
1520                         free (se->addr);
1521                         free (se);
1522                         continue;
1523                 }
1524
1525                 if ((flags & CREATE_SOCKET_FLAGS_LISTEN) != 0)
1526                 {
1527                         status = network_bind_socket (se, ai_ptr);
1528                         if (status != 0)
1529                         {
1530                                 close (se->fd);
1531                                 free (se->addr);
1532                                 free (se);
1533                                 continue;
1534                         }
1535                 }
1536                 else /* sending socket */
1537                 {
1538                         network_set_ttl (se, ai_ptr);
1539                 }
1540
1541 #if HAVE_GCRYPT_H
1542                 se->security_level = security_level;
1543                 se->shared_secret = NULL;
1544                 se->cypher = NULL;
1545                 if (shared_secret != NULL)
1546                 {
1547                         status = network_set_encryption (se, shared_secret);
1548                         if ((status != 0) && (security_level <= SECURITY_LEVEL_SIGN))
1549                         {
1550                                 WARNING ("network plugin: Starting cryptograp"
1551                                                 "hic subsystem failed. Since "
1552                                                 "security level `Sign' or "
1553                                                 "`None' is configured I will "
1554                                                 "continue.");
1555                         }
1556                         else if (status != 0)
1557                         {
1558                                 ERROR ("network plugin: Starting cryptograp"
1559                                                 "hic subsystem failed. "
1560                                                 "Because the security level "
1561                                                 "is set to `Encrypt' I will "
1562                                                 "not continue!");
1563                                 close (se->fd);
1564                                 free (se->addr);
1565                                 free (se);
1566                                 continue;
1567                         }
1568                 } /* if (shared_secret != NULL) */
1569 #else
1570                 /* Make compiler happy */
1571                 security_level = 0;
1572                 shared_secret = NULL;
1573 #endif /* HAVE_GCRYPT_H */
1574
1575                 if (se_tail == NULL)
1576                 {
1577                         se_head = se;
1578                         se_tail = se;
1579                 }
1580                 else
1581                 {
1582                         se_tail->next = se;
1583                         se_tail = se;
1584                 }
1585
1586                 /* We don't open more than one write-socket per node/service pair.. */
1587                 if ((flags & CREATE_SOCKET_FLAGS_LISTEN) == 0)
1588                         break;
1589         }
1590
1591         freeaddrinfo (ai_list);
1592
1593         return (se_head);
1594 } /* }}} sockent_t *network_create_socket */
1595
1596 static sockent_t *network_create_default_socket (int flags) /* {{{ */
1597 {
1598         sockent_t *se_ptr  = NULL;
1599         sockent_t *se_head = NULL;
1600         sockent_t *se_tail = NULL;
1601
1602         se_ptr = network_create_socket (NET_DEFAULT_V6_ADDR, NET_DEFAULT_PORT,
1603                         /* shared secret = */ NULL, SECURITY_LEVEL_NONE,
1604                         flags);
1605
1606         /* Don't send to the same machine in IPv6 and IPv4 if both are available. */
1607         if (((flags & CREATE_SOCKET_FLAGS_LISTEN) == 0) && (se_ptr != NULL))
1608                 return (se_ptr);
1609
1610         if (se_ptr != NULL)
1611         {
1612                 se_head = se_ptr;
1613                 se_tail = se_ptr;
1614                 while (se_tail->next != NULL)
1615                         se_tail = se_tail->next;
1616         }
1617
1618         se_ptr = network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT,
1619                         /* shared secret = */ NULL, SECURITY_LEVEL_NONE,
1620                         flags);
1621
1622         if (se_tail == NULL)
1623                 return (se_ptr);
1624
1625         se_tail->next = se_ptr;
1626         return (se_head);
1627 } /* }}} sockent_t *network_create_default_socket */
1628
1629 static int network_add_listen_socket (const char *node, /* {{{ */
1630     const char *service, const char *shared_secret, int security_level)
1631 {
1632         sockent_t *se;
1633         sockent_t *se_ptr;
1634         int se_num = 0;
1635
1636         int flags;
1637
1638         flags = CREATE_SOCKET_FLAGS_LISTEN;
1639
1640         if (service == NULL)
1641                 service = NET_DEFAULT_PORT;
1642
1643         if (node == NULL)
1644                 se = network_create_default_socket (flags);
1645         else
1646                 se = network_create_socket (node, service,
1647                     shared_secret, security_level, flags);
1648
1649         if (se == NULL)
1650                 return (-1);
1651
1652         for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
1653                 se_num++;
1654
1655         listen_sockets_pollfd = realloc (listen_sockets_pollfd,
1656                         (listen_sockets_num + se_num)
1657                         * sizeof (struct pollfd));
1658
1659         for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
1660         {
1661                 listen_sockets_pollfd[listen_sockets_num].fd = se_ptr->fd;
1662                 listen_sockets_pollfd[listen_sockets_num].events = POLLIN | POLLPRI;
1663                 listen_sockets_pollfd[listen_sockets_num].revents = 0;
1664                 listen_sockets_num++;
1665         } /* for (se) */
1666
1667         se_ptr = listen_sockets;
1668         while ((se_ptr != NULL) && (se_ptr->next != NULL))
1669                 se_ptr = se_ptr->next;
1670
1671         if (se_ptr == NULL)
1672                 listen_sockets = se;
1673         else
1674                 se_ptr->next = se;
1675
1676         return (0);
1677 } /* }}} int network_add_listen_socket */
1678
1679 static int network_add_sending_socket (const char *node, /* {{{ */
1680     const char *service, const char *shared_secret, int security_level)
1681 {
1682         sockent_t *se;
1683         sockent_t *se_ptr;
1684
1685         if (service == NULL)
1686                 service = NET_DEFAULT_PORT;
1687
1688         if (node == NULL)
1689                 se = network_create_default_socket (/* flags = */ 0);
1690         else
1691                 se = network_create_socket (node, service,
1692                                 shared_secret, security_level,
1693                                 /* flags = */ 0);
1694
1695         if (se == NULL)
1696                 return (-1);
1697
1698         if (sending_sockets == NULL)
1699         {
1700                 sending_sockets = se;
1701                 return (0);
1702         }
1703
1704         for (se_ptr = sending_sockets; se_ptr->next != NULL; se_ptr = se_ptr->next)
1705                 /* seek end */;
1706
1707         se_ptr->next = se;
1708         return (0);
1709 } /* }}} int network_add_sending_socket */
1710
1711 static void *dispatch_thread (void __attribute__((unused)) *arg)
1712 {
1713   while (42)
1714   {
1715     receive_list_entry_t *ent;
1716
1717     /* Lock and wait for more data to come in */
1718     pthread_mutex_lock (&receive_list_lock);
1719     while ((listen_loop == 0)
1720         && (receive_list_head == NULL))
1721       pthread_cond_wait (&receive_list_cond, &receive_list_lock);
1722
1723     /* Remove the head entry and unlock */
1724     ent = receive_list_head;
1725     if (ent != NULL)
1726       receive_list_head = ent->next;
1727     pthread_mutex_unlock (&receive_list_lock);
1728
1729     /* Check whether we are supposed to exit. We do NOT check `listen_loop'
1730      * because we dispatch all missing packets before shutting down. */
1731     if (ent == NULL)
1732       break;
1733
1734     parse_packet (ent);
1735
1736     sfree (ent);
1737   } /* while (42) */
1738
1739   return (NULL);
1740 } /* void *dispatch_thread */
1741
1742 static int network_receive (void)
1743 {
1744         char buffer[BUFF_SIZE];
1745         int  buffer_len;
1746
1747         int i;
1748         int status;
1749
1750         receive_list_entry_t *private_list_head;
1751         receive_list_entry_t *private_list_tail;
1752
1753         if (listen_sockets_num == 0)
1754                 network_add_listen_socket (/* node = */ NULL,
1755                                 /* service = */ NULL,
1756                                 /* shared secret = */ NULL,
1757                                 /* encryption = */ 0);
1758
1759         if (listen_sockets_num == 0)
1760         {
1761                 ERROR ("network: Failed to open a listening socket.");
1762                 return (-1);
1763         }
1764
1765         private_list_head = NULL;
1766         private_list_tail = NULL;
1767
1768         while (listen_loop == 0)
1769         {
1770                 status = poll (listen_sockets_pollfd, listen_sockets_num, -1);
1771
1772                 if (status <= 0)
1773                 {
1774                         char errbuf[1024];
1775                         if (errno == EINTR)
1776                                 continue;
1777                         ERROR ("poll failed: %s",
1778                                         sstrerror (errno, errbuf, sizeof (errbuf)));
1779                         return (-1);
1780                 }
1781
1782                 for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
1783                 {
1784                         receive_list_entry_t *ent;
1785
1786                         if ((listen_sockets_pollfd[i].revents
1787                                                 & (POLLIN | POLLPRI)) == 0)
1788                                 continue;
1789                         status--;
1790
1791                         buffer_len = recv (listen_sockets_pollfd[i].fd,
1792                                         buffer, sizeof (buffer),
1793                                         0 /* no flags */);
1794                         if (buffer_len < 0)
1795                         {
1796                                 char errbuf[1024];
1797                                 ERROR ("recv failed: %s",
1798                                                 sstrerror (errno, errbuf,
1799                                                         sizeof (errbuf)));
1800                                 return (-1);
1801                         }
1802
1803                         /* TODO: Possible performance enhancement: Do not free
1804                          * these entries in the dispatch thread but put them in
1805                          * another list, so we don't have to allocate more and
1806                          * more of these structures. */
1807                         ent = malloc (sizeof (receive_list_entry_t));
1808                         if (ent == NULL)
1809                         {
1810                                 ERROR ("network plugin: malloc failed.");
1811                                 return (-1);
1812                         }
1813                         memset (ent, 0, sizeof (receive_list_entry_t));
1814                         ent->fd = listen_sockets_pollfd[i].fd;
1815                         ent->next = NULL;
1816
1817                         /* Hopefully this be optimized out by the compiler. It
1818                          * might help prevent stupid bugs in the future though.
1819                          */
1820                         assert (sizeof (ent->data) == sizeof (buffer));
1821
1822                         memcpy (ent->data, buffer, buffer_len);
1823                         ent->data_len = buffer_len;
1824
1825                         if (private_list_head == NULL)
1826                                 private_list_head = ent;
1827                         else
1828                                 private_list_tail->next = ent;
1829                         private_list_tail = ent;
1830
1831                         /* Do not block here. Blocking here has led to
1832                          * insufficient performance in the past. */
1833                         if (pthread_mutex_trylock (&receive_list_lock) == 0)
1834                         {
1835                                 if (receive_list_head == NULL)
1836                                         receive_list_head = private_list_head;
1837                                 else
1838                                         receive_list_tail->next = private_list_head;
1839                                 receive_list_tail = private_list_tail;
1840
1841                                 private_list_head = NULL;
1842                                 private_list_tail = NULL;
1843
1844                                 pthread_cond_signal (&receive_list_cond);
1845                                 pthread_mutex_unlock (&receive_list_lock);
1846                         }
1847                 } /* for (listen_sockets_pollfd) */
1848         } /* while (listen_loop == 0) */
1849
1850         /* Make sure everything is dispatched before exiting. */
1851         if (private_list_head != NULL)
1852         {
1853                 pthread_mutex_lock (&receive_list_lock);
1854
1855                 if (receive_list_head == NULL)
1856                         receive_list_head = private_list_head;
1857                 else
1858                         receive_list_tail->next = private_list_head;
1859                 receive_list_tail = private_list_tail;
1860
1861                 private_list_head = NULL;
1862                 private_list_tail = NULL;
1863
1864                 pthread_cond_signal (&receive_list_cond);
1865                 pthread_mutex_unlock (&receive_list_lock);
1866         }
1867
1868         return (0);
1869 } /* int network_receive */
1870
1871 static void *receive_thread (void __attribute__((unused)) *arg)
1872 {
1873         return (network_receive () ? (void *) 1 : (void *) 0);
1874 } /* void *receive_thread */
1875
1876 static void network_init_buffer (void)
1877 {
1878         memset (send_buffer, 0, sizeof (send_buffer));
1879         send_buffer_ptr = send_buffer;
1880         send_buffer_fill = 0;
1881
1882         memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
1883 } /* int network_init_buffer */
1884
1885 static void networt_send_buffer_plain (const sockent_t *se, /* {{{ */
1886                 const char *buffer, size_t buffer_size)
1887 {
1888         int status;
1889
1890         while (42)
1891         {
1892                 status = sendto (se->fd, buffer, buffer_size, 0 /* no flags */,
1893                                 (struct sockaddr *) se->addr, se->addrlen);
1894                 if (status < 0)
1895                 {
1896                         char errbuf[1024];
1897                         if (errno == EINTR)
1898                                 continue;
1899                         ERROR ("network plugin: sendto failed: %s",
1900                                         sstrerror (errno, errbuf,
1901                                                 sizeof (errbuf)));
1902                         break;
1903                 }
1904
1905                 break;
1906         } /* while (42) */
1907 } /* }}} void networt_send_buffer_plain */
1908
1909 #if HAVE_GCRYPT_H
1910 static void networt_send_buffer_signed (const sockent_t *se, /* {{{ */
1911                 const char *in_buffer, size_t in_buffer_size)
1912 {
1913         part_signature_sha256_t ps;
1914         char buffer[sizeof (ps) + in_buffer_size];
1915
1916         gcry_md_hd_t hd;
1917         gcry_error_t err;
1918         unsigned char *hash;
1919
1920         hd = NULL;
1921         err = gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
1922         if (err != 0)
1923         {
1924                 ERROR ("network plugin: Creating HMAC object failed: %s",
1925                                 gcry_strerror (err));
1926                 return;
1927         }
1928
1929         err = gcry_md_setkey (hd, se->shared_secret,
1930                         strlen (se->shared_secret));
1931         if (err != 0)
1932         {
1933                 ERROR ("network plugin: gcry_md_setkey failed: %s",
1934                                 gcry_strerror (err));
1935                 gcry_md_close (hd);
1936                 return;
1937         }
1938
1939         /* Initialize the `ps' structure. */
1940         memset (&ps, 0, sizeof (ps));
1941         ps.head.type = htons (TYPE_SIGN_SHA256);
1942         ps.head.length = htons ((uint16_t) sizeof (ps));
1943
1944         /* Calculate the hash value. */
1945         gcry_md_write (hd, in_buffer, in_buffer_size);
1946         hash = gcry_md_read (hd, GCRY_MD_SHA256);
1947         if (hash == NULL)
1948         {
1949                 ERROR ("network plugin: gcry_md_read failed.");
1950                 gcry_md_close (hd);
1951                 return;
1952         }
1953
1954         /* Add the signature and fill the rest of the buffer. */
1955         memcpy (ps.hash, hash, sizeof (ps.hash));
1956         memcpy (buffer, &ps, sizeof (ps));
1957         memcpy (buffer + sizeof (ps), in_buffer, in_buffer_size);
1958
1959         gcry_md_close (hd);
1960         hd = NULL;
1961
1962         networt_send_buffer_plain (se, buffer, sizeof (buffer));
1963 } /* }}} void networt_send_buffer_signed */
1964
1965 static void networt_send_buffer_encrypted (const sockent_t *se, /* {{{ */
1966                 const char *in_buffer, size_t in_buffer_size)
1967 {
1968   part_encryption_aes256_t pea;
1969   char buffer[sizeof (pea) + in_buffer_size];
1970   size_t buffer_size;
1971   size_t buffer_offset;
1972   size_t padding_size;
1973   gcry_error_t err;
1974
1975   /* Round to the next multiple of 16, because AES has a block size of 128 bit.
1976    * the first four bytes of `pea' are not encrypted and must be subtracted. */
1977   buffer_size = sizeof (pea.orig_length) + sizeof (pea.hash) + in_buffer_size;
1978   padding_size = buffer_size;
1979   buffer_size = (buffer_size + 15) / 16;
1980   buffer_size = buffer_size * 16;
1981   padding_size = buffer_size - padding_size;
1982   assert (padding_size <= sizeof (pea.padding));
1983   buffer_size += sizeof (pea.head);
1984
1985   DEBUG ("network plugin: networt_send_buffer_encrypted: "
1986       "buffer_size = %zu;", buffer_size);
1987
1988   /* Initialize the header fields */
1989   memset (&pea, 0, sizeof (pea));
1990   pea.head.type = htons (TYPE_ENCR_AES256);
1991   pea.head.length = htons ((uint16_t) buffer_size);
1992   pea.orig_length = htons ((uint16_t) in_buffer_size);
1993
1994   /* Fill the extra field with random values. Some entropy in the encrypted
1995    * data is usually not a bad thing, I hope. */
1996   if (padding_size > 0)
1997     gcry_randomize (&pea.padding, padding_size, GCRY_STRONG_RANDOM);
1998
1999   /* Create hash of the payload */
2000   gcry_md_hash_buffer (GCRY_MD_SHA1, pea.hash, in_buffer, in_buffer_size);
2001
2002   /* Initialize the buffer */
2003   buffer_offset = 0;
2004   memset (buffer, 0, sizeof (buffer));
2005
2006   memcpy (buffer + buffer_offset, &pea.head, sizeof (pea.head));
2007   buffer_offset += sizeof (pea.head);
2008
2009   memcpy (buffer + buffer_offset, &pea.orig_length, sizeof (pea.orig_length));
2010   buffer_offset += sizeof (pea.orig_length);
2011
2012   if (padding_size > 0)
2013   {
2014     memcpy (buffer + buffer_offset, &pea.padding, padding_size);
2015     buffer_offset += padding_size;
2016   }
2017
2018   memcpy (buffer + buffer_offset, &pea.hash, sizeof (pea.hash));
2019   buffer_offset += sizeof (pea.hash);
2020
2021   memcpy (buffer + buffer_offset, in_buffer, in_buffer_size);
2022   buffer_offset += in_buffer_size;
2023
2024   assert (buffer_offset == buffer_size);
2025
2026   /* Encrypt the buffer in-place */
2027   err = gcry_cipher_encrypt (se->cypher,
2028       buffer + sizeof (pea.head), buffer_size - sizeof (pea.head),
2029       /* in = */ NULL, /* in len = */ 0);
2030   gcry_cipher_reset (se->cypher);
2031   if (err != 0)
2032   {
2033     ERROR ("network plugin: gcry_cipher_encrypt returned: %s",
2034         gcry_strerror (err));
2035     return;
2036   }
2037
2038   /* Send it out without further modifications */
2039   networt_send_buffer_plain (se, buffer, buffer_size);
2040 } /* }}} void networt_send_buffer_encrypted */
2041 #endif /* HAVE_GCRYPT_H */
2042
2043 static void network_send_buffer (char *buffer, size_t buffer_len) /* {{{ */
2044 {
2045   sockent_t *se;
2046
2047   DEBUG ("network plugin: network_send_buffer: buffer_len = %zu", buffer_len);
2048
2049   for (se = sending_sockets; se != NULL; se = se->next)
2050   {
2051 #if HAVE_GCRYPT_H
2052     if (se->security_level == SECURITY_LEVEL_ENCRYPT)
2053       networt_send_buffer_encrypted (se, buffer, buffer_len);
2054     else if (se->security_level == SECURITY_LEVEL_SIGN)
2055       networt_send_buffer_signed (se, buffer, buffer_len);
2056     else /* if (se->security_level == SECURITY_LEVEL_NONE) */
2057 #endif /* HAVE_GCRYPT_H */
2058       networt_send_buffer_plain (se, buffer, buffer_len);
2059   } /* for (sending_sockets) */
2060 } /* }}} void network_send_buffer */
2061
2062 static int add_to_buffer (char *buffer, int buffer_size, /* {{{ */
2063                 value_list_t *vl_def,
2064                 const data_set_t *ds, const value_list_t *vl)
2065 {
2066         char *buffer_orig = buffer;
2067
2068         if (strcmp (vl_def->host, vl->host) != 0)
2069         {
2070                 if (write_part_string (&buffer, &buffer_size, TYPE_HOST,
2071                                         vl->host, strlen (vl->host)) != 0)
2072                         return (-1);
2073                 sstrncpy (vl_def->host, vl->host, sizeof (vl_def->host));
2074         }
2075
2076         if (vl_def->time != vl->time)
2077         {
2078                 if (write_part_number (&buffer, &buffer_size, TYPE_TIME,
2079                                         (uint64_t) vl->time))
2080                         return (-1);
2081                 vl_def->time = vl->time;
2082         }
2083
2084         if (vl_def->interval != vl->interval)
2085         {
2086                 if (write_part_number (&buffer, &buffer_size, TYPE_INTERVAL,
2087                                         (uint64_t) vl->interval))
2088                         return (-1);
2089                 vl_def->interval = vl->interval;
2090         }
2091
2092         if (strcmp (vl_def->plugin, vl->plugin) != 0)
2093         {
2094                 if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN,
2095                                         vl->plugin, strlen (vl->plugin)) != 0)
2096                         return (-1);
2097                 sstrncpy (vl_def->plugin, vl->plugin, sizeof (vl_def->plugin));
2098         }
2099
2100         if (strcmp (vl_def->plugin_instance, vl->plugin_instance) != 0)
2101         {
2102                 if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
2103                                         vl->plugin_instance,
2104                                         strlen (vl->plugin_instance)) != 0)
2105                         return (-1);
2106                 sstrncpy (vl_def->plugin_instance, vl->plugin_instance, sizeof (vl_def->plugin_instance));
2107         }
2108
2109         if (strcmp (vl_def->type, vl->type) != 0)
2110         {
2111                 if (write_part_string (&buffer, &buffer_size, TYPE_TYPE,
2112                                         vl->type, strlen (vl->type)) != 0)
2113                         return (-1);
2114                 sstrncpy (vl_def->type, ds->type, sizeof (vl_def->type));
2115         }
2116
2117         if (strcmp (vl_def->type_instance, vl->type_instance) != 0)
2118         {
2119                 if (write_part_string (&buffer, &buffer_size, TYPE_TYPE_INSTANCE,
2120                                         vl->type_instance,
2121                                         strlen (vl->type_instance)) != 0)
2122                         return (-1);
2123                 sstrncpy (vl_def->type_instance, vl->type_instance, sizeof (vl_def->type_instance));
2124         }
2125         
2126         if (write_part_values (&buffer, &buffer_size, ds, vl) != 0)
2127                 return (-1);
2128
2129         return (buffer - buffer_orig);
2130 } /* }}} int add_to_buffer */
2131
2132 static void flush_buffer (void)
2133 {
2134         DEBUG ("network plugin: flush_buffer: send_buffer_fill = %i",
2135                         send_buffer_fill);
2136
2137         network_send_buffer (send_buffer, (size_t) send_buffer_fill);
2138         network_init_buffer ();
2139 }
2140
2141 static int network_write (const data_set_t *ds, const value_list_t *vl,
2142                 user_data_t __attribute__((unused)) *user_data)
2143 {
2144         int status;
2145
2146         /* If the value is already in the cache, we have received it via the
2147          * network. We write it again if forwarding is activated. It's then in
2148          * the cache and should we receive it again we will ignore it. */
2149         status = cache_check (vl);
2150         if ((network_config_forward == 0)
2151                         && (status != 0))
2152                 return (0);
2153
2154         pthread_mutex_lock (&send_buffer_lock);
2155
2156         status = add_to_buffer (send_buffer_ptr,
2157                         sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
2158                         &send_buffer_vl,
2159                         ds, vl);
2160         if (status >= 0)
2161         {
2162                 /* status == bytes added to the buffer */
2163                 send_buffer_fill += status;
2164                 send_buffer_ptr  += status;
2165         }
2166         else
2167         {
2168                 flush_buffer ();
2169
2170                 status = add_to_buffer (send_buffer_ptr,
2171                                 sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
2172                                 &send_buffer_vl,
2173                                 ds, vl);
2174
2175                 if (status >= 0)
2176                 {
2177                         send_buffer_fill += status;
2178                         send_buffer_ptr  += status;
2179                 }
2180         }
2181
2182         if (status < 0)
2183         {
2184                 ERROR ("network plugin: Unable to append to the "
2185                                 "buffer for some weird reason");
2186         }
2187         else if ((sizeof (send_buffer) - send_buffer_fill) < 15)
2188         {
2189                 flush_buffer ();
2190         }
2191
2192         pthread_mutex_unlock (&send_buffer_lock);
2193
2194         return ((status < 0) ? -1 : 0);
2195 } /* int network_write */
2196
2197 static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */
2198     int *retval)
2199 {
2200   if ((ci->values_num != 1)
2201       || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN)
2202         && (ci->values[0].type != OCONFIG_TYPE_STRING)))
2203   {
2204     ERROR ("network plugin: The `%s' config option needs "
2205         "exactly one boolean argument.", ci->key);
2206     return (-1);
2207   }
2208
2209   if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
2210   {
2211     if (ci->values[0].value.boolean)
2212       *retval = 1;
2213     else
2214       *retval = 0;
2215   }
2216   else
2217   {
2218     char *str = ci->values[0].value.string;
2219
2220     if ((strcasecmp ("true", str) == 0)
2221         || (strcasecmp ("yes", str) == 0)
2222         || (strcasecmp ("on", str) == 0))
2223       *retval = 1;
2224     else if ((strcasecmp ("false", str) == 0)
2225         || (strcasecmp ("no", str) == 0)
2226         || (strcasecmp ("off", str) == 0))
2227       *retval = 0;
2228     else
2229     {
2230       ERROR ("network plugin: Cannot parse string value `%s' of the `%s' "
2231           "option as boolean value.",
2232           str, ci->key);
2233       return (-1);
2234     }
2235   }
2236
2237   return (0);
2238 } /* }}} int network_config_set_boolean */
2239
2240 static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
2241 {
2242   int tmp;
2243   if ((ci->values_num != 1)
2244       || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
2245   {
2246     WARNING ("network plugin: The `TimeToLive' config option needs exactly "
2247         "one numeric argument.");
2248     return (-1);
2249   }
2250
2251   tmp = (int) ci->values[0].value.number;
2252   if ((tmp > 0) && (tmp <= 255))
2253     network_config_ttl = tmp;
2254
2255   return (0);
2256 } /* }}} int network_config_set_ttl */
2257
2258 #if HAVE_GCRYPT_H
2259 static int network_config_set_security_level (oconfig_item_t *ci, /* {{{ */
2260     int *retval)
2261 {
2262   char *str;
2263   if ((ci->values_num != 1)
2264       || (ci->values[0].type != OCONFIG_TYPE_STRING))
2265   {
2266     WARNING ("network plugin: The `SecurityLevel' config option needs exactly "
2267         "one string argument.");
2268     return (-1);
2269   }
2270
2271   str = ci->values[0].value.string;
2272   if (strcasecmp ("Encrypt", str) == 0)
2273     *retval = SECURITY_LEVEL_ENCRYPT;
2274   else if (strcasecmp ("Sign", str) == 0)
2275     *retval = SECURITY_LEVEL_SIGN;
2276   else if (strcasecmp ("None", str) == 0)
2277     *retval = SECURITY_LEVEL_NONE;
2278   else
2279   {
2280     WARNING ("network plugin: Unknown security level: %s.", str);
2281     return (-1);
2282   }
2283
2284   return (0);
2285 } /* }}} int network_config_set_security_level */
2286 #endif /* HAVE_GCRYPT_H */
2287
2288 static int network_config_listen_server (const oconfig_item_t *ci) /* {{{ */
2289 {
2290   char *node;
2291   char *service;
2292   char *shared_secret = NULL;
2293   int security_level = SECURITY_LEVEL_NONE;
2294   int i;
2295
2296   if ((ci->values_num < 1) || (ci->values_num > 2)
2297       || (ci->values[0].type != OCONFIG_TYPE_STRING)
2298       || ((ci->values_num > 1) && (ci->values[1].type != OCONFIG_TYPE_STRING)))
2299   {
2300     ERROR ("network plugin: The `%s' config option needs "
2301         "one or two string arguments.", ci->key);
2302     return (-1);
2303   }
2304
2305   node = ci->values[0].value.string;
2306   if (ci->values_num >= 2)
2307     service = ci->values[1].value.string;
2308   else
2309     service = NULL;
2310
2311   for (i = 0; i < ci->children_num; i++)
2312   {
2313     oconfig_item_t *child = ci->children + i;
2314
2315 #if HAVE_GCRYPT_H
2316     if (strcasecmp ("Secret", child->key) == 0)
2317     {
2318       if ((child->values_num == 1)
2319           && (child->values[0].type == OCONFIG_TYPE_STRING))
2320         shared_secret = child->values[0].value.string;
2321       else
2322         ERROR ("network plugin: The `Secret' option needs exactly one string "
2323             "argument.");
2324     }
2325     else if (strcasecmp ("SecurityLevel", child->key) == 0)
2326       network_config_set_security_level (child, &security_level);
2327     else
2328 #endif /* HAVE_GCRYPT_H */
2329     {
2330       WARNING ("network plugin: Option `%s' is not allowed here.",
2331           child->key);
2332     }
2333   }
2334
2335   if ((security_level > SECURITY_LEVEL_NONE) && (shared_secret == NULL))
2336   {
2337     ERROR ("network plugin: A security level higher than `none' was "
2338         "requested, but no shared key was given. Cowardly refusing to open "
2339         "this socket!");
2340     return (-1);
2341   }
2342
2343   if (strcasecmp ("Listen", ci->key) == 0)
2344     network_add_listen_socket (node, service, shared_secret, security_level);
2345   else
2346     network_add_sending_socket (node, service, shared_secret, security_level);
2347
2348   return (0);
2349 } /* }}} int network_config_listen_server */
2350
2351 static int network_config_set_cache_flush (const oconfig_item_t *ci) /* {{{ */
2352 {
2353   int tmp;
2354   if ((ci->values_num != 1)
2355       || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
2356   {
2357     WARNING ("network plugin: The `CacheFlush' config option needs exactly "
2358         "one numeric argument.");
2359     return (-1);
2360   }
2361
2362   tmp = (int) ci->values[0].value.number;
2363   if (tmp > 0)
2364     network_config_ttl = tmp;
2365
2366   return (0);
2367 } /* }}} int network_config_set_cache_flush */
2368
2369 static int network_config (oconfig_item_t *ci) /* {{{ */
2370 {
2371   int i;
2372
2373   for (i = 0; i < ci->children_num; i++)
2374   {
2375     oconfig_item_t *child = ci->children + i;
2376
2377     if ((strcasecmp ("Listen", child->key) == 0)
2378         || (strcasecmp ("Server", child->key) == 0))
2379       network_config_listen_server (child);
2380     else if (strcasecmp ("TimeToLive", child->key) == 0)
2381       network_config_set_ttl (child);
2382     else if (strcasecmp ("Forward", child->key) == 0)
2383       network_config_set_boolean (child, &network_config_forward);
2384     else if (strcasecmp ("CacheFlush", child->key) == 0)
2385       network_config_set_cache_flush (child);
2386     else
2387     {
2388       WARNING ("network plugin: Option `%s' is not allowed here.",
2389           child->key);
2390     }
2391   }
2392
2393   return (0);
2394 } /* }}} int network_config */
2395
2396 static int network_notification (const notification_t *n,
2397                 user_data_t __attribute__((unused)) *user_data)
2398 {
2399   char  buffer[BUFF_SIZE];
2400   char *buffer_ptr = buffer;
2401   int   buffer_free = sizeof (buffer);
2402   int   status;
2403
2404   memset (buffer, '\0', sizeof (buffer));
2405
2406
2407   status = write_part_number (&buffer_ptr, &buffer_free, TYPE_TIME,
2408       (uint64_t) n->time);
2409   if (status != 0)
2410     return (-1);
2411
2412   status = write_part_number (&buffer_ptr, &buffer_free, TYPE_SEVERITY,
2413       (uint64_t) n->severity);
2414   if (status != 0)
2415     return (-1);
2416
2417   if (strlen (n->host) > 0)
2418   {
2419     status = write_part_string (&buffer_ptr, &buffer_free, TYPE_HOST,
2420         n->host, strlen (n->host));
2421     if (status != 0)
2422       return (-1);
2423   }
2424
2425   if (strlen (n->plugin) > 0)
2426   {
2427     status = write_part_string (&buffer_ptr, &buffer_free, TYPE_PLUGIN,
2428         n->plugin, strlen (n->plugin));
2429     if (status != 0)
2430       return (-1);
2431   }
2432
2433   if (strlen (n->plugin_instance) > 0)
2434   {
2435     status = write_part_string (&buffer_ptr, &buffer_free,
2436         TYPE_PLUGIN_INSTANCE,
2437         n->plugin_instance, strlen (n->plugin_instance));
2438     if (status != 0)
2439       return (-1);
2440   }
2441
2442   if (strlen (n->type) > 0)
2443   {
2444     status = write_part_string (&buffer_ptr, &buffer_free, TYPE_TYPE,
2445         n->type, strlen (n->type));
2446     if (status != 0)
2447       return (-1);
2448   }
2449
2450   if (strlen (n->type_instance) > 0)
2451   {
2452     status = write_part_string (&buffer_ptr, &buffer_free, TYPE_TYPE_INSTANCE,
2453         n->type_instance, strlen (n->type_instance));
2454     if (status != 0)
2455       return (-1);
2456   }
2457
2458   status = write_part_string (&buffer_ptr, &buffer_free, TYPE_MESSAGE,
2459       n->message, strlen (n->message));
2460   if (status != 0)
2461     return (-1);
2462
2463   network_send_buffer (buffer, sizeof (buffer) - buffer_free);
2464
2465   return (0);
2466 } /* int network_notification */
2467
2468 static int network_shutdown (void)
2469 {
2470         listen_loop++;
2471
2472         /* Kill the listening thread */
2473         if (receive_thread_running != 0)
2474         {
2475                 INFO ("network plugin: Stopping receive thread.");
2476                 pthread_kill (receive_thread_id, SIGTERM);
2477                 pthread_join (receive_thread_id, NULL /* no return value */);
2478                 memset (&receive_thread_id, 0, sizeof (receive_thread_id));
2479                 receive_thread_running = 0;
2480         }
2481
2482         /* Shutdown the dispatching thread */
2483         if (dispatch_thread_running != 0)
2484         {
2485                 INFO ("network plugin: Stopping dispatch thread.");
2486                 pthread_mutex_lock (&receive_list_lock);
2487                 pthread_cond_broadcast (&receive_list_cond);
2488                 pthread_mutex_unlock (&receive_list_lock);
2489                 pthread_join (dispatch_thread_id, /* ret = */ NULL);
2490                 dispatch_thread_running = 0;
2491         }
2492
2493         free_sockent (listen_sockets);
2494
2495         if (send_buffer_fill > 0)
2496                 flush_buffer ();
2497
2498         if (cache_tree != NULL)
2499         {
2500                 void *key;
2501                 void *value;
2502
2503                 while (c_avl_pick (cache_tree, &key, &value) == 0)
2504                 {
2505                         sfree (key);
2506                         sfree (value);
2507                 }
2508                 c_avl_destroy (cache_tree);
2509                 cache_tree = NULL;
2510         }
2511
2512         /* TODO: Close `sending_sockets' */
2513
2514         plugin_unregister_config ("network");
2515         plugin_unregister_init ("network");
2516         plugin_unregister_write ("network");
2517         plugin_unregister_shutdown ("network");
2518
2519         /* Let the init function do it's move again ;) */
2520         cache_flush_last = 0;
2521
2522         return (0);
2523 } /* int network_shutdown */
2524
2525 static int network_init (void)
2526 {
2527         /* Check if we were already initialized. If so, just return - there's
2528          * nothing more to do (for now, that is). */
2529         if (cache_flush_last != 0)
2530                 return (0);
2531
2532         plugin_register_shutdown ("network", network_shutdown);
2533
2534         network_init_buffer ();
2535
2536         cache_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
2537         cache_flush_last = time (NULL);
2538
2539         /* setup socket(s) and so on */
2540         if (sending_sockets != NULL)
2541         {
2542                 plugin_register_write ("network", network_write,
2543                                 /* user_data = */ NULL);
2544                 plugin_register_notification ("network", network_notification,
2545                                 /* user_data = */ NULL);
2546         }
2547
2548         /* If no threads need to be started, return here. */
2549         if ((listen_sockets_num == 0)
2550                         || ((dispatch_thread_running != 0)
2551                                 && (receive_thread_running != 0)))
2552                 return (0);
2553
2554         if (dispatch_thread_running == 0)
2555         {
2556                 int status;
2557                 status = pthread_create (&dispatch_thread_id,
2558                                 NULL /* no attributes */,
2559                                 dispatch_thread,
2560                                 NULL /* no argument */);
2561                 if (status != 0)
2562                 {
2563                         char errbuf[1024];
2564                         ERROR ("network: pthread_create failed: %s",
2565                                         sstrerror (errno, errbuf,
2566                                                 sizeof (errbuf)));
2567                 }
2568                 else
2569                 {
2570                         dispatch_thread_running = 1;
2571                 }
2572         }
2573
2574         if (receive_thread_running == 0)
2575         {
2576                 int status;
2577                 status = pthread_create (&receive_thread_id,
2578                                 NULL /* no attributes */,
2579                                 receive_thread,
2580                                 NULL /* no argument */);
2581                 if (status != 0)
2582                 {
2583                         char errbuf[1024];
2584                         ERROR ("network: pthread_create failed: %s",
2585                                         sstrerror (errno, errbuf,
2586                                                 sizeof (errbuf)));
2587                 }
2588                 else
2589                 {
2590                         receive_thread_running = 1;
2591                 }
2592         }
2593
2594         return (0);
2595 } /* int network_init */
2596
2597 /* 
2598  * The flush option of the network plugin cannot flush individual identifiers.
2599  * All the values are added to a buffer and sent when the buffer is full, the
2600  * requested value may or may not be in there, it's not worth finding out. We
2601  * just send the buffer if `flush'  is called - if the requested value was in
2602  * there, good. If not, well, then there is nothing to flush.. -octo
2603  */
2604 static int network_flush (int timeout,
2605                 const char __attribute__((unused)) *identifier,
2606                 user_data_t __attribute__((unused)) *user_data)
2607 {
2608         pthread_mutex_lock (&send_buffer_lock);
2609
2610         if (((time (NULL) - cache_flush_last) >= timeout)
2611                         && (send_buffer_fill > 0))
2612         {
2613                 flush_buffer ();
2614         }
2615
2616         pthread_mutex_unlock (&send_buffer_lock);
2617
2618         return (0);
2619 } /* int network_flush */
2620
2621 void module_register (void)
2622 {
2623         plugin_register_complex_config ("network", network_config);
2624         plugin_register_init   ("network", network_init);
2625         plugin_register_flush   ("network", network_flush,
2626                         /* user_data = */ NULL);
2627 } /* void module_register */
2628
2629 /* vim: set fdm=marker : */