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