722f1d674dd6ecd078a19753fbd067cc3393ff18
[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, size_t *ret_buffer_len,
577                 value_t **ret_values, int *ret_num_values)
578 {
579         char *buffer = *ret_buffer;
580         size_t 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                 NOTICE ("network plugin: packet is too short: "
596                                 "buffer_len = %zu", 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) || (buffer_len < exp_size))
617         {
618                 WARNING ("network plugin: parse_part_values: "
619                                 "Packet too short: "
620                                 "Chunk of size %zu expected, "
621                                 "but buffer has only %zu bytes left.",
622                                 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, size_t *ret_buffer_len,
668                 uint64_t *value)
669 {
670         char *buffer = *ret_buffer;
671         size_t 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 %zu expected, "
685                                 "but buffer has only %zu bytes left.",
686                                 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, size_t *ret_buffer_len,
709                 char *output, int output_len)
710 {
711         char *buffer = *ret_buffer;
712         size_t 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) || (buffer_len < header_size))
721         {
722                 WARNING ("network plugin: parse_part_string: "
723                                 "Packet too short: "
724                                 "Chunk of at least size %zu expected, "
725                                 "but buffer has only %zu bytes left.",
726                                 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 %"PRIu16" received, "
744                                 "but buffer has only %zu 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 /* Forward declaration: parse_part_sign_sha256 and parse_part_encr_aes256 call
792  * parse_packet and vice versa. */
793 #define PP_SIGNED    0x01
794 #define PP_ENCRYPTED 0x02
795 static int parse_packet (sockent_t *se,
796                 void *buffer, size_t buffer_size, int flags);
797
798 #if HAVE_GCRYPT_H
799 static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
800     void **ret_buffer, size_t *ret_buffer_len)
801 {
802   char *buffer = *ret_buffer;
803   size_t buffer_len = *ret_buffer_len;
804
805   part_signature_sha256_t ps_received;
806   char hash[sizeof (ps_received.hash)];
807
808   gcry_md_hd_t hd;
809   gcry_error_t err;
810   unsigned char *hash_ptr;
811
812   if (se->shared_secret == NULL)
813   {
814     NOTICE ("network plugin: Received signed network packet but can't verify "
815         "it because no shared secret has been configured. Will accept it.");
816     return (0);
817   }
818
819   if (buffer_len < sizeof (ps_received))
820     return (-ENOMEM);
821
822   hd = NULL;
823   err = gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
824   if (err != 0)
825   {
826     ERROR ("network plugin: Creating HMAC-SHA-256 object failed: %s",
827         gcry_strerror (err));
828     return (-1);
829   }
830
831   err = gcry_md_setkey (hd, se->shared_secret,
832       strlen (se->shared_secret));
833   if (err != 0)
834   {
835     ERROR ("network plugin: gcry_md_setkey failed: %s",
836         gcry_strerror (err));
837     gcry_md_close (hd);
838     return (-1);
839   }
840
841   memcpy (&ps_received, buffer, sizeof (ps_received));
842   /* TODO: Check ps_received.head.length! */
843
844   buffer += sizeof (ps_received);
845   buffer_len -= sizeof (ps_received);
846
847   gcry_md_write (hd, buffer, buffer_len);
848   hash_ptr = gcry_md_read (hd, GCRY_MD_SHA256);
849   if (hash_ptr == NULL)
850   {
851     ERROR ("network plugin: gcry_md_read failed.");
852     gcry_md_close (hd);
853     return (-1);
854   }
855   memcpy (hash, hash_ptr, sizeof (hash));
856
857   gcry_md_close (hd);
858   hd = NULL;
859
860   *ret_buffer += sizeof (ps_received);
861   *ret_buffer_len -= sizeof (ps_received);
862
863   if (memcmp (ps_received.hash, hash,
864         sizeof (ps_received.hash)) == 0)
865     return (0);
866   else /* hashes do not match. */
867     return (1);
868 } /* }}} int parse_part_sign_sha256 */
869 /* #endif HAVE_GCRYPT_H */
870
871 #else /* if !HAVE_GCRYPT_H */
872 static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
873     void **ret_buffer, size_t *ret_buffer_len)
874 {
875   INFO ("network plugin: Received signed packet, but the network "
876       "plugin was not linked with libgcrypt, so I cannot "
877       "verify the signature. The packet will be accepted.");
878   return (0);
879 } /* }}} int parse_part_sign_sha256 */
880 #endif /* !HAVE_GCRYPT_H */
881
882 #if HAVE_GCRYPT_H
883 static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
884                 void **ret_buffer, size_t *ret_buffer_len,
885                 int flags)
886 {
887   char  *buffer = *ret_buffer;
888   size_t buffer_len = *ret_buffer_len;
889   size_t orig_buffer_len;
890   size_t part_size;
891   size_t buffer_offset;
892   size_t padding_size;
893   part_encryption_aes256_t pea;
894   unsigned char hash[sizeof (pea.hash)];
895
896   gcry_cipher_hd_t cypher;
897   gcry_error_t err;
898
899   /* Make sure at least the header if available. */
900   if (buffer_len < sizeof (pea))
901   {
902     NOTICE ("network plugin: parse_part_encr_aes256: "
903         "Discarding short packet.");
904     return (-1);
905   }
906
907   buffer_offset = 0;
908
909 #define BUFFER_READ(p,s) do { \
910   memcpy ((p), buffer + buffer_offset, (s)); \
911   buffer_offset += (s); \
912 } while (0)
913
914   /* Copy the unencrypted information into `pea'. */
915   BUFFER_READ (&pea.head.type, sizeof (pea.head.type));
916   BUFFER_READ (&pea.head.length, sizeof (pea.head.length));
917   BUFFER_READ (pea.iv, sizeof (pea.iv));
918
919   /* Check the `part size'. */
920   part_size = ntohs (pea.head.length);
921   if (part_size > buffer_len)
922   {
923     NOTICE ("network plugin: parse_part_encr_aes256: "
924         "Discarding large part.");
925     return (-1);
926   }
927
928   cypher = network_get_aes256_cypher (se, pea.iv, sizeof (pea.iv));
929   if (cypher == NULL)
930     return (-1);
931
932   /* Decrypt the packet in-place */
933   err = gcry_cipher_decrypt (cypher,
934       buffer    + PART_ENCRYPTION_AES256_UNENCR_SIZE,
935       part_size - PART_ENCRYPTION_AES256_UNENCR_SIZE,
936       /* in = */ NULL, /* in len = */ 0);
937   if (err != 0)
938   {
939     ERROR ("network plugin: gcry_cipher_decrypt returned: %s",
940         gcry_strerror (err));
941     return (-1);
942   }
943
944   /* Figure out the length of the payload and the length of the padding. */
945   BUFFER_READ (&pea.orig_length, sizeof (pea.orig_length));
946
947   orig_buffer_len = ntohs (pea.orig_length);
948   if (orig_buffer_len > (part_size - PART_ENCRYPTION_AES256_SIZE))
949   {
950     ERROR ("network plugin: Decryption failed: Invalid original length.");
951     return (-1);
952   }
953
954   /* Calculate the size of the `padding' field. */
955   padding_size = part_size - (orig_buffer_len + PART_ENCRYPTION_AES256_SIZE);
956   if (padding_size > sizeof (pea.padding))
957   {
958     ERROR ("network plugin: Part- and original length "
959         "differ more than %zu bytes.", sizeof (pea.padding));
960     return (-1);
961   }
962
963   BUFFER_READ (pea.hash, sizeof (pea.hash));
964
965   /* Read the padding. */
966   BUFFER_READ (pea.padding, padding_size);
967
968   /* Check hash sum */
969   memset (hash, 0, sizeof (hash));
970   gcry_md_hash_buffer (GCRY_MD_SHA1, hash,
971       buffer + buffer_offset, orig_buffer_len);
972   
973   if (memcmp (hash, pea.hash, sizeof (hash)) != 0)
974   {
975     ERROR ("network plugin: Decryption failed: Checksum mismatch.");
976     return (-1);
977   }
978
979   assert ((PART_ENCRYPTION_AES256_SIZE + padding_size + orig_buffer_len)
980                   == part_size);
981
982   parse_packet (se, buffer + PART_ENCRYPTION_AES256_SIZE + padding_size,
983                   orig_buffer_len, flags | PP_ENCRYPTED);
984
985   /* Update return values */
986   *ret_buffer =     buffer     + part_size;
987   *ret_buffer_len = buffer_len - part_size;
988
989   return (0);
990 #undef BUFFER_READ
991 } /* }}} int parse_part_encr_aes256 */
992 /* #endif HAVE_GCRYPT_H */
993
994 #else /* if !HAVE_GCRYPT_H */
995 static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
996     void **ret_buffer, size_t *ret_buffer_len)
997 {
998   INFO ("network plugin: Received encrypted packet, but the network "
999       "plugin was not linked with libgcrypt, so I cannot "
1000       "decrypt it. The packet will be discarded.");
1001   return (-1);
1002 } /* }}} int parse_part_encr_aes256 */
1003 #endif /* !HAVE_GCRYPT_H */
1004
1005 static int parse_packet (sockent_t *se, /* {{{ */
1006                 void *buffer, size_t buffer_size, int flags)
1007 {
1008         int status;
1009
1010         value_list_t vl = VALUE_LIST_INIT;
1011         notification_t n;
1012
1013         int packet_was_signed = (flags & PP_SIGNED);
1014         int packet_was_encrypted = (flags & PP_ENCRYPTED);
1015 #if HAVE_GCRYPT_H
1016         int printed_ignore_warning = 0;
1017 #endif /* HAVE_GCRYPT_H */
1018
1019
1020         memset (&vl, '\0', sizeof (vl));
1021         memset (&n, '\0', sizeof (n));
1022         status = 0;
1023
1024         while ((status == 0) && (0 < buffer_size)
1025                         && ((unsigned int) buffer_size > sizeof (part_header_t)))
1026         {
1027                 uint16_t pkg_length;
1028                 uint16_t pkg_type;
1029
1030                 memcpy ((void *) &pkg_type,
1031                                 (void *) buffer,
1032                                 sizeof (pkg_type));
1033                 memcpy ((void *) &pkg_length,
1034                                 (void *) (buffer + sizeof (pkg_type)),
1035                                 sizeof (pkg_length));
1036
1037                 pkg_length = ntohs (pkg_length);
1038                 pkg_type = ntohs (pkg_type);
1039
1040                 if (pkg_length > buffer_size)
1041                         break;
1042                 /* Ensure that this loop terminates eventually */
1043                 if (pkg_length < (2 * sizeof (uint16_t)))
1044                         break;
1045
1046                 if (pkg_type == TYPE_ENCR_AES256)
1047                 {
1048                         status = parse_part_encr_aes256 (se,
1049                                         &buffer, &buffer_size,
1050                                         flags);
1051                         if (status != 0)
1052                         {
1053                                 ERROR ("network plugin: Decrypting AES256 "
1054                                                 "part failed "
1055                                                 "with status %i.", status);
1056                                 break;
1057                         }
1058                 }
1059 #if HAVE_GCRYPT_H
1060                 else if ((se->security_level == SECURITY_LEVEL_ENCRYPT)
1061                                 && (packet_was_encrypted == 0))
1062                 {
1063                         if (printed_ignore_warning == 0)
1064                         {
1065                                 INFO ("network plugin: Unencrypted packet or "
1066                                                 "part has been ignored.");
1067                                 printed_ignore_warning = 1;
1068                         }
1069                         buffer = ((char *) buffer) + pkg_length;
1070                         continue;
1071                 }
1072 #endif /* HAVE_GCRYPT_H */
1073                 else if (pkg_type == TYPE_SIGN_SHA256)
1074                 {
1075                         status = parse_part_sign_sha256 (se, &buffer, &buffer_size);
1076                         if (status < 0)
1077                         {
1078                                 ERROR ("network plugin: Verifying HMAC-SHA-256 "
1079                                                 "signature failed "
1080                                                 "with status %i.", status);
1081                                 break;
1082                         }
1083                         else if (status > 0)
1084                         {
1085                                 ERROR ("network plugin: Ignoring packet with "
1086                                                 "invalid HMAC-SHA-256 signature.");
1087                                 break;
1088                         }
1089                         else
1090                         {
1091                                 packet_was_signed = 1;
1092                         }
1093                 }
1094 #if HAVE_GCRYPT_H
1095                 else if ((se->security_level == SECURITY_LEVEL_SIGN)
1096                                 && (packet_was_encrypted == 0)
1097                                 && (packet_was_signed == 0))
1098                 {
1099                         if (printed_ignore_warning == 0)
1100                         {
1101                                 INFO ("network plugin: Unsigned packet or "
1102                                                 "part has been ignored.");
1103                                 printed_ignore_warning = 1;
1104                         }
1105                         buffer = ((char *) buffer) + pkg_length;
1106                         continue;
1107                 }
1108 #endif /* HAVE_GCRYPT_H */
1109                 else if (pkg_type == TYPE_VALUES)
1110                 {
1111                         status = parse_part_values (&buffer, &buffer_size,
1112                                         &vl.values, &vl.values_len);
1113
1114                         if (status != 0)
1115                                 break;
1116
1117                         if ((vl.time > 0)
1118                                         && (strlen (vl.host) > 0)
1119                                         && (strlen (vl.plugin) > 0)
1120                                         && (strlen (vl.type) > 0)
1121                                         && (cache_check (&vl) == 0))
1122                         {
1123                                 plugin_dispatch_values (&vl);
1124                         }
1125                         else
1126                         {
1127                                 DEBUG ("network plugin: parse_packet:"
1128                                                 " NOT dispatching values");
1129                         }
1130
1131                         sfree (vl.values);
1132                 }
1133                 else if (pkg_type == TYPE_TIME)
1134                 {
1135                         uint64_t tmp = 0;
1136                         status = parse_part_number (&buffer, &buffer_size,
1137                                         &tmp);
1138                         if (status == 0)
1139                         {
1140                                 vl.time = (time_t) tmp;
1141                                 n.time = (time_t) tmp;
1142                         }
1143                 }
1144                 else if (pkg_type == TYPE_INTERVAL)
1145                 {
1146                         uint64_t tmp = 0;
1147                         status = parse_part_number (&buffer, &buffer_size,
1148                                         &tmp);
1149                         if (status == 0)
1150                                 vl.interval = (int) tmp;
1151                 }
1152                 else if (pkg_type == TYPE_HOST)
1153                 {
1154                         status = parse_part_string (&buffer, &buffer_size,
1155                                         vl.host, sizeof (vl.host));
1156                         if (status == 0)
1157                                 sstrncpy (n.host, vl.host, sizeof (n.host));
1158                 }
1159                 else if (pkg_type == TYPE_PLUGIN)
1160                 {
1161                         status = parse_part_string (&buffer, &buffer_size,
1162                                         vl.plugin, sizeof (vl.plugin));
1163                         if (status == 0)
1164                                 sstrncpy (n.plugin, vl.plugin,
1165                                                 sizeof (n.plugin));
1166                 }
1167                 else if (pkg_type == TYPE_PLUGIN_INSTANCE)
1168                 {
1169                         status = parse_part_string (&buffer, &buffer_size,
1170                                         vl.plugin_instance,
1171                                         sizeof (vl.plugin_instance));
1172                         if (status == 0)
1173                                 sstrncpy (n.plugin_instance,
1174                                                 vl.plugin_instance,
1175                                                 sizeof (n.plugin_instance));
1176                 }
1177                 else if (pkg_type == TYPE_TYPE)
1178                 {
1179                         status = parse_part_string (&buffer, &buffer_size,
1180                                         vl.type, sizeof (vl.type));
1181                         if (status == 0)
1182                                 sstrncpy (n.type, vl.type, sizeof (n.type));
1183                 }
1184                 else if (pkg_type == TYPE_TYPE_INSTANCE)
1185                 {
1186                         status = parse_part_string (&buffer, &buffer_size,
1187                                         vl.type_instance,
1188                                         sizeof (vl.type_instance));
1189                         if (status == 0)
1190                                 sstrncpy (n.type_instance, vl.type_instance,
1191                                                 sizeof (n.type_instance));
1192                 }
1193                 else if (pkg_type == TYPE_MESSAGE)
1194                 {
1195                         status = parse_part_string (&buffer, &buffer_size,
1196                                         n.message, sizeof (n.message));
1197
1198                         if (status != 0)
1199                         {
1200                                 /* do nothing */
1201                         }
1202                         else if ((n.severity != NOTIF_FAILURE)
1203                                         && (n.severity != NOTIF_WARNING)
1204                                         && (n.severity != NOTIF_OKAY))
1205                         {
1206                                 INFO ("network plugin: "
1207                                                 "Ignoring notification with "
1208                                                 "unknown severity %i.",
1209                                                 n.severity);
1210                         }
1211                         else if (n.time <= 0)
1212                         {
1213                                 INFO ("network plugin: "
1214                                                 "Ignoring notification with "
1215                                                 "time == 0.");
1216                         }
1217                         else if (strlen (n.message) <= 0)
1218                         {
1219                                 INFO ("network plugin: "
1220                                                 "Ignoring notification with "
1221                                                 "an empty message.");
1222                         }
1223                         else
1224                         {
1225                                 plugin_dispatch_notification (&n);
1226                         }
1227                 }
1228                 else if (pkg_type == TYPE_SEVERITY)
1229                 {
1230                         uint64_t tmp = 0;
1231                         status = parse_part_number (&buffer, &buffer_size,
1232                                         &tmp);
1233                         if (status == 0)
1234                                 n.severity = (int) tmp;
1235                 }
1236                 else
1237                 {
1238                         DEBUG ("network plugin: parse_packet: Unknown part"
1239                                         " type: 0x%04hx", pkg_type);
1240                         buffer = ((char *) buffer) + pkg_length;
1241                 }
1242         } /* while (buffer_size > sizeof (part_header_t)) */
1243
1244         return (status);
1245 } /* }}} int parse_packet */
1246
1247 static void free_sockent (sockent_t *se) /* {{{ */
1248 {
1249         sockent_t *next;
1250         while (se != NULL)
1251         {
1252                 next = se->next;
1253
1254 #if HAVE_GCRYPT_H
1255                 if (se->cypher != NULL)
1256                 {
1257                         gcry_cipher_close (se->cypher);
1258                         se->cypher = NULL;
1259                 }
1260                 free (se->shared_secret);
1261 #endif /* HAVE_GCRYPT_H */
1262
1263                 free (se->addr);
1264                 free (se);
1265
1266                 se = next;
1267         }
1268 } /* }}} void free_sockent */
1269
1270 /*
1271  * int network_set_ttl
1272  *
1273  * Set the `IP_MULTICAST_TTL', `IP_TTL', `IPV6_MULTICAST_HOPS' or
1274  * `IPV6_UNICAST_HOPS', depending on which option is applicable.
1275  *
1276  * The `struct addrinfo' is used to destinguish between unicast and multicast
1277  * sockets.
1278  */
1279 static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
1280 {
1281         DEBUG ("network plugin: network_set_ttl: network_config_ttl = %i;",
1282                         network_config_ttl);
1283
1284         if ((network_config_ttl < 1) || (network_config_ttl > 255))
1285                 return (-1);
1286
1287         if (ai->ai_family == AF_INET)
1288         {
1289                 struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
1290                 int optname;
1291
1292                 if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
1293                         optname = IP_MULTICAST_TTL;
1294                 else
1295                         optname = IP_TTL;
1296
1297                 if (setsockopt (se->fd, IPPROTO_IP, optname,
1298                                         &network_config_ttl,
1299                                         sizeof (network_config_ttl)) == -1)
1300                 {
1301                         char errbuf[1024];
1302                         ERROR ("setsockopt: %s",
1303                                         sstrerror (errno, errbuf, sizeof (errbuf)));
1304                         return (-1);
1305                 }
1306         }
1307         else if (ai->ai_family == AF_INET6)
1308         {
1309                 /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
1310                 struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
1311                 int optname;
1312
1313                 if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
1314                         optname = IPV6_MULTICAST_HOPS;
1315                 else
1316                         optname = IPV6_UNICAST_HOPS;
1317
1318                 if (setsockopt (se->fd, IPPROTO_IPV6, optname,
1319                                         &network_config_ttl,
1320                                         sizeof (network_config_ttl)) == -1)
1321                 {
1322                         char errbuf[1024];
1323                         ERROR ("setsockopt: %s",
1324                                         sstrerror (errno, errbuf,
1325                                                 sizeof (errbuf)));
1326                         return (-1);
1327                 }
1328         }
1329
1330         return (0);
1331 } /* int network_set_ttl */
1332
1333 static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
1334 {
1335         int loop = 0;
1336         int yes  = 1;
1337
1338         /* allow multiple sockets to use the same PORT number */
1339         if (setsockopt(se->fd, SOL_SOCKET, SO_REUSEADDR,
1340                                 &yes, sizeof(yes)) == -1) {
1341                 char errbuf[1024];
1342                 ERROR ("setsockopt: %s", 
1343                                 sstrerror (errno, errbuf, sizeof (errbuf)));
1344                 return (-1);
1345         }
1346
1347         DEBUG ("fd = %i; calling `bind'", se->fd);
1348
1349         if (bind (se->fd, ai->ai_addr, ai->ai_addrlen) == -1)
1350         {
1351                 char errbuf[1024];
1352                 ERROR ("bind: %s",
1353                                 sstrerror (errno, errbuf, sizeof (errbuf)));
1354                 return (-1);
1355         }
1356
1357         if (ai->ai_family == AF_INET)
1358         {
1359                 struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
1360                 if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
1361                 {
1362                         struct ip_mreq mreq;
1363
1364                         DEBUG ("fd = %i; IPv4 multicast address found", se->fd);
1365
1366                         mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
1367                         mreq.imr_interface.s_addr = htonl (INADDR_ANY);
1368
1369                         if (setsockopt (se->fd, IPPROTO_IP, IP_MULTICAST_LOOP,
1370                                                 &loop, sizeof (loop)) == -1)
1371                         {
1372                                 char errbuf[1024];
1373                                 ERROR ("setsockopt: %s",
1374                                                 sstrerror (errno, errbuf,
1375                                                         sizeof (errbuf)));
1376                                 return (-1);
1377                         }
1378
1379                         if (setsockopt (se->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1380                                                 &mreq, sizeof (mreq)) == -1)
1381                         {
1382                                 char errbuf[1024];
1383                                 ERROR ("setsockopt: %s",
1384                                                 sstrerror (errno, errbuf,
1385                                                         sizeof (errbuf)));
1386                                 return (-1);
1387                         }
1388                 }
1389         }
1390         else if (ai->ai_family == AF_INET6)
1391         {
1392                 /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
1393                 struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
1394                 if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
1395                 {
1396                         struct ipv6_mreq mreq;
1397
1398                         DEBUG ("fd = %i; IPv6 multicast address found", se->fd);
1399
1400                         memcpy (&mreq.ipv6mr_multiaddr,
1401                                         &addr->sin6_addr,
1402                                         sizeof (addr->sin6_addr));
1403
1404                         /* http://developer.apple.com/documentation/Darwin/Reference/ManPages/man4/ip6.4.html
1405                          * ipv6mr_interface may be set to zeroes to
1406                          * choose the default multicast interface or to
1407                          * the index of a particular multicast-capable
1408                          * interface if the host is multihomed.
1409                          * Membership is associ-associated with a
1410                          * single interface; programs running on
1411                          * multihomed hosts may need to join the same
1412                          * group on more than one interface.*/
1413                         mreq.ipv6mr_interface = 0;
1414
1415                         if (setsockopt (se->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
1416                                                 &loop, sizeof (loop)) == -1)
1417                         {
1418                                 char errbuf[1024];
1419                                 ERROR ("setsockopt: %s",
1420                                                 sstrerror (errno, errbuf,
1421                                                         sizeof (errbuf)));
1422                                 return (-1);
1423                         }
1424
1425                         if (setsockopt (se->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
1426                                                 &mreq, sizeof (mreq)) == -1)
1427                         {
1428                                 char errbuf[1024];
1429                                 ERROR ("setsockopt: %s",
1430                                                 sstrerror (errno, errbuf,
1431                                                         sizeof (errbuf)));
1432                                 return (-1);
1433                         }
1434                 }
1435         }
1436
1437         return (0);
1438 } /* int network_bind_socket */
1439
1440 #define CREATE_SOCKET_FLAGS_LISTEN    0x0001
1441 static sockent_t *network_create_socket (const char *node, /* {{{ */
1442                 const char *service,
1443                 const char *shared_secret,
1444                 int security_level,
1445                 int flags)
1446 {
1447         struct addrinfo  ai_hints;
1448         struct addrinfo *ai_list, *ai_ptr;
1449         int              ai_return;
1450
1451         sockent_t *se_head = NULL;
1452         sockent_t *se_tail = NULL;
1453
1454         DEBUG ("node = %s, service = %s", node, service);
1455
1456         memset (&ai_hints, '\0', sizeof (ai_hints));
1457         ai_hints.ai_flags    = 0;
1458 #ifdef AI_PASSIVE
1459         ai_hints.ai_flags |= AI_PASSIVE;
1460 #endif
1461 #ifdef AI_ADDRCONFIG
1462         ai_hints.ai_flags |= AI_ADDRCONFIG;
1463 #endif
1464         ai_hints.ai_family   = AF_UNSPEC;
1465         ai_hints.ai_socktype = SOCK_DGRAM;
1466         ai_hints.ai_protocol = IPPROTO_UDP;
1467
1468         ai_return = getaddrinfo (node, service, &ai_hints, &ai_list);
1469         if (ai_return != 0)
1470         {
1471                 char errbuf[1024];
1472                 ERROR ("getaddrinfo (%s, %s): %s",
1473                                 (node == NULL) ? "(null)" : node,
1474                                 (service == NULL) ? "(null)" : service,
1475                                 (ai_return == EAI_SYSTEM)
1476                                 ? sstrerror (errno, errbuf, sizeof (errbuf))
1477                                 : gai_strerror (ai_return));
1478                 return (NULL);
1479         }
1480
1481         for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
1482         {
1483                 sockent_t *se;
1484                 int status;
1485
1486                 if ((se = (sockent_t *) malloc (sizeof (sockent_t))) == NULL)
1487                 {
1488                         char errbuf[1024];
1489                         ERROR ("malloc: %s",
1490                                         sstrerror (errno, errbuf,
1491                                                 sizeof (errbuf)));
1492                         continue;
1493                 }
1494
1495                 if ((se->addr = (struct sockaddr_storage *) malloc (sizeof (struct sockaddr_storage))) == NULL)
1496                 {
1497                         char errbuf[1024];
1498                         ERROR ("malloc: %s",
1499                                         sstrerror (errno, errbuf,
1500                                                 sizeof (errbuf)));
1501                         free (se);
1502                         continue;
1503                 }
1504
1505                 assert (sizeof (struct sockaddr_storage) >= ai_ptr->ai_addrlen);
1506                 memset (se->addr, '\0', sizeof (struct sockaddr_storage));
1507                 memcpy (se->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
1508                 se->addrlen = ai_ptr->ai_addrlen;
1509
1510                 se->fd   = socket (ai_ptr->ai_family,
1511                                 ai_ptr->ai_socktype,
1512                                 ai_ptr->ai_protocol);
1513                 se->next = NULL;
1514
1515                 if (se->fd == -1)
1516                 {
1517                         char errbuf[1024];
1518                         ERROR ("socket: %s",
1519                                         sstrerror (errno, errbuf,
1520                                                 sizeof (errbuf)));
1521                         free (se->addr);
1522                         free (se);
1523                         continue;
1524                 }
1525
1526                 if ((flags & CREATE_SOCKET_FLAGS_LISTEN) != 0)
1527                 {
1528                         status = network_bind_socket (se, ai_ptr);
1529                         if (status != 0)
1530                         {
1531                                 close (se->fd);
1532                                 free (se->addr);
1533                                 free (se);
1534                                 continue;
1535                         }
1536                 }
1537                 else /* sending socket */
1538                 {
1539                         network_set_ttl (se, ai_ptr);
1540                 }
1541
1542 #if HAVE_GCRYPT_H
1543                 se->security_level = security_level;
1544                 se->shared_secret = NULL;
1545                 se->cypher = NULL;
1546                 if (shared_secret != NULL)
1547                 {
1548                         se->shared_secret = sstrdup (shared_secret);
1549                         assert (se->shared_secret != NULL);
1550
1551                         memset (se->shared_secret_hash, 0,
1552                                         sizeof (se->shared_secret_hash));
1553                         gcry_md_hash_buffer (GCRY_MD_SHA256,
1554                                         se->shared_secret_hash,
1555                                         se->shared_secret,
1556                                         strlen (se->shared_secret));
1557                 }
1558 #else
1559                 /* Make compiler happy */
1560                 security_level = 0;
1561                 shared_secret = NULL;
1562 #endif /* HAVE_GCRYPT_H */
1563
1564                 if (se_tail == NULL)
1565                 {
1566                         se_head = se;
1567                         se_tail = se;
1568                 }
1569                 else
1570                 {
1571                         se_tail->next = se;
1572                         se_tail = se;
1573                 }
1574
1575                 /* We don't open more than one write-socket per node/service pair.. */
1576                 if ((flags & CREATE_SOCKET_FLAGS_LISTEN) == 0)
1577                         break;
1578         }
1579
1580         freeaddrinfo (ai_list);
1581
1582         return (se_head);
1583 } /* }}} sockent_t *network_create_socket */
1584
1585 static sockent_t *network_create_default_socket (int flags) /* {{{ */
1586 {
1587         sockent_t *se_ptr  = NULL;
1588         sockent_t *se_head = NULL;
1589         sockent_t *se_tail = NULL;
1590
1591         se_ptr = network_create_socket (NET_DEFAULT_V6_ADDR, NET_DEFAULT_PORT,
1592                         /* shared secret = */ NULL, SECURITY_LEVEL_NONE,
1593                         flags);
1594
1595         /* Don't send to the same machine in IPv6 and IPv4 if both are available. */
1596         if (((flags & CREATE_SOCKET_FLAGS_LISTEN) == 0) && (se_ptr != NULL))
1597                 return (se_ptr);
1598
1599         if (se_ptr != NULL)
1600         {
1601                 se_head = se_ptr;
1602                 se_tail = se_ptr;
1603                 while (se_tail->next != NULL)
1604                         se_tail = se_tail->next;
1605         }
1606
1607         se_ptr = network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT,
1608                         /* shared secret = */ NULL, SECURITY_LEVEL_NONE,
1609                         flags);
1610
1611         if (se_tail == NULL)
1612                 return (se_ptr);
1613
1614         se_tail->next = se_ptr;
1615         return (se_head);
1616 } /* }}} sockent_t *network_create_default_socket */
1617
1618 static int network_add_listen_socket (const char *node, /* {{{ */
1619     const char *service, const char *shared_secret, int security_level)
1620 {
1621         sockent_t *se;
1622         sockent_t *se_ptr;
1623         int se_num = 0;
1624
1625         int flags;
1626
1627         flags = CREATE_SOCKET_FLAGS_LISTEN;
1628
1629         if (service == NULL)
1630                 service = NET_DEFAULT_PORT;
1631
1632         if (node == NULL)
1633                 se = network_create_default_socket (flags);
1634         else
1635                 se = network_create_socket (node, service,
1636                     shared_secret, security_level, flags);
1637
1638         if (se == NULL)
1639                 return (-1);
1640
1641         for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
1642                 se_num++;
1643
1644         listen_sockets_pollfd = realloc (listen_sockets_pollfd,
1645                         (listen_sockets_num + se_num)
1646                         * sizeof (struct pollfd));
1647
1648         for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
1649         {
1650                 listen_sockets_pollfd[listen_sockets_num].fd = se_ptr->fd;
1651                 listen_sockets_pollfd[listen_sockets_num].events = POLLIN | POLLPRI;
1652                 listen_sockets_pollfd[listen_sockets_num].revents = 0;
1653                 listen_sockets_num++;
1654         } /* for (se) */
1655
1656         se_ptr = listen_sockets;
1657         while ((se_ptr != NULL) && (se_ptr->next != NULL))
1658                 se_ptr = se_ptr->next;
1659
1660         if (se_ptr == NULL)
1661                 listen_sockets = se;
1662         else
1663                 se_ptr->next = se;
1664
1665         return (0);
1666 } /* }}} int network_add_listen_socket */
1667
1668 static int network_add_sending_socket (const char *node, /* {{{ */
1669     const char *service, const char *shared_secret, int security_level)
1670 {
1671         sockent_t *se;
1672         sockent_t *se_ptr;
1673
1674         if (service == NULL)
1675                 service = NET_DEFAULT_PORT;
1676
1677         if (node == NULL)
1678                 se = network_create_default_socket (/* flags = */ 0);
1679         else
1680                 se = network_create_socket (node, service,
1681                                 shared_secret, security_level,
1682                                 /* flags = */ 0);
1683
1684         if (se == NULL)
1685                 return (-1);
1686
1687         if (sending_sockets == NULL)
1688         {
1689                 sending_sockets = se;
1690                 return (0);
1691         }
1692
1693         for (se_ptr = sending_sockets; se_ptr->next != NULL; se_ptr = se_ptr->next)
1694                 /* seek end */;
1695
1696         se_ptr->next = se;
1697         return (0);
1698 } /* }}} int network_add_sending_socket */
1699
1700 static void *dispatch_thread (void __attribute__((unused)) *arg) /* {{{ */
1701 {
1702   while (42)
1703   {
1704     receive_list_entry_t *ent;
1705     sockent_t *se;
1706
1707     /* Lock and wait for more data to come in */
1708     pthread_mutex_lock (&receive_list_lock);
1709     while ((listen_loop == 0)
1710         && (receive_list_head == NULL))
1711       pthread_cond_wait (&receive_list_cond, &receive_list_lock);
1712
1713     /* Remove the head entry and unlock */
1714     ent = receive_list_head;
1715     if (ent != NULL)
1716       receive_list_head = ent->next;
1717     pthread_mutex_unlock (&receive_list_lock);
1718
1719     /* Check whether we are supposed to exit. We do NOT check `listen_loop'
1720      * because we dispatch all missing packets before shutting down. */
1721     if (ent == NULL)
1722       break;
1723
1724     /* Look for the correct `sockent_t' */
1725     se = listen_sockets;
1726     while ((se != NULL) && (se->fd != ent->fd))
1727             se = se->next;
1728
1729     if (se == NULL)
1730     {
1731             ERROR ("network plugin: Got packet from FD %i, but can't "
1732                             "find an appropriate socket entry.",
1733                             ent->fd);
1734             sfree (ent);
1735             continue;
1736     }
1737
1738     parse_packet (se, ent->data, ent->data_len, /* flags = */ 0);
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 : */