aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/transport/gnunet-communicator-tcp.c29
-rw-r--r--src/transport/gnunet-communicator-udp.c1982
2 files changed, 1991 insertions, 20 deletions
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c
index 2980ad532..d0ee326b1 100644
--- a/src/transport/gnunet-communicator-tcp.c
+++ b/src/transport/gnunet-communicator-tcp.c
@@ -24,9 +24,13 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * 25 *
26 * TODO: 26 * TODO:
27 * - support DNS names in BINDTO option 27 * - support DNS names in BINDTO option (#5528)
28 * - support NAT connection reversal method 28 * - support NAT connection reversal method (#5529)
29 * - support other TCP-specific NAT traversal methods 29 * - support other TCP-specific NAT traversal methods (#5531)
30 * - add replay protection support to the protocol by
31 * adding a nonce in the KX and requiring (!) a
32 * nounce ACK to be send within the first X bytes of
33 * data (#5530)
30 */ 34 */
31#include "platform.h" 35#include "platform.h"
32#include "gnunet_util_lib.h" 36#include "gnunet_util_lib.h"
@@ -1263,7 +1267,7 @@ tcp_address_to_sockaddr (const char *bindto,
1263 return in; 1267 return in;
1264 } 1268 }
1265 } 1269 }
1266 /* FIXME (feature!): maybe also try getnameinfo()? */ 1270 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
1267 GNUNET_free (cp); 1271 GNUNET_free (cp);
1268 return NULL; 1272 return NULL;
1269} 1273}
@@ -2348,7 +2352,7 @@ run (void *cls,
2348 (const struct sockaddr **) &in, 2352 (const struct sockaddr **) &in,
2349 &in_len, 2353 &in_len,
2350 &nat_address_cb, 2354 &nat_address_cb,
2351 NULL /* FIXME: support reversal! */, 2355 NULL /* FIXME: support reversal: #5529 */,
2352 NULL /* closure */); 2356 NULL /* closure */);
2353} 2357}
2354 2358
@@ -2387,19 +2391,4 @@ main (int argc,
2387} 2391}
2388 2392
2389 2393
2390#if defined(LINUX) && defined(__GLIBC__)
2391#include <malloc.h>
2392
2393/**
2394 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
2395 */
2396void __attribute__ ((constructor))
2397GNUNET_ARM_memory_init ()
2398{
2399 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
2400 mallopt (M_TOP_PAD, 1 * 1024);
2401 malloc_trim (0);
2402}
2403#endif
2404
2405/* end of gnunet-communicator-tcp.c */ 2394/* end of gnunet-communicator-tcp.c */
diff --git a/src/transport/gnunet-communicator-udp.c b/src/transport/gnunet-communicator-udp.c
new file mode 100644
index 000000000..23fb289bc
--- /dev/null
+++ b/src/transport/gnunet-communicator-udp.c
@@ -0,0 +1,1982 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018, 2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19*/
20
21/**
22 * @file transport/gnunet-communicator-udp.c
23 * @brief Transport plugin using UDP.
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - support DNS names in BINDTO option (#5528)
28 * - support NAT connection reversal method (#5529)
29 * - support other UDP-specific NAT traversal methods
30 */
31#include "platform.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_protocols.h"
34#include "gnunet_signatures.h"
35#include "gnunet_constants.h"
36#include "gnunet_nt_lib.h"
37#include "gnunet_nat_service.h"
38#include "gnunet_statistics_service.h"
39#include "gnunet_transport_communication_service.h"
40
41/**
42 * How many messages do we keep at most in the queue to the
43 * transport service before we start to drop (default,
44 * can be changed via the configuration file).
45 * Should be _below_ the level of the communicator API, as
46 * otherwise we may read messages just to have them dropped
47 * by the communicator API.
48 */
49#define DEFAULT_MAX_QUEUE_LENGTH 8
50
51/**
52 * How often do we rekey based on time (at least)
53 */
54#define REKEY_TIME_INTERVAL GNUNET_TIME_UNIT_DAYS
55
56/**
57 * How long do we wait until we must have received the initial KX?
58 */
59#define PROTO_QUEUE_TIMEOUT GNUNET_TIME_UNIT_MINUTES
60
61/**
62 * How often do we rekey based on number of bytes transmitted?
63 * (additionally randomized).
64 */
65#define REKEY_MAX_BYTES (1024LLU * 1024 * 1024 * 4LLU)
66
67/**
68 * Address prefix used by the communicator.
69 */
70#define COMMUNICATOR_ADDRESS_PREFIX "udp"
71
72/**
73 * Configuration section used by the communicator.
74 */
75#define COMMUNICATOR_CONFIG_SECTION "communicator-udp"
76
77GNUNET_NETWORK_STRUCT_BEGIN
78
79
80/**
81 * Signature we use to verify that the ephemeral key was really chosen by
82 * the specified sender. If possible, the receiver should respond with
83 * a `struct UDPAck` (possibly via backchannel).
84 */
85struct UdpHandshakeSignature
86{
87 /**
88 * Purpose must be #GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE
89 */
90 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
91
92 /**
93 * Identity of the inititor of the UDP connection (UDP client).
94 */
95 struct GNUNET_PeerIdentity sender;
96
97 /**
98 * Presumed identity of the target of the UDP connection (UDP server)
99 */
100 struct GNUNET_PeerIdentity receiver;
101
102 /**
103 * Ephemeral key used by the @e sender.
104 */
105 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
106
107 /**
108 * Monotonic time of @e sender, to possibly help detect replay attacks
109 * (if receiver persists times by sender).
110 */
111 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
112};
113
114
115/**
116 * "Plaintext" header at beginning of KX message. Followed
117 * by encrypted `struct UDPConfirmation`.
118 */
119struct InitialKX
120{
121
122 /**
123 * Ephemeral key for KX.
124 */
125 struct GNUNET_CRYPT_EddsaPublicKey ephemeral;
126
127 /**
128 * HMAC for the following encrypted message, using GCM. HMAC uses
129 * key derived from the handshake with sequence number zero.
130 */
131 uint8_t gcm_tag[128/8];
132
133};
134
135
136/**
137 * Encrypted continuation of UDP initial handshake, followed
138 * by message header with payload.
139 */
140struct UDPConfirmation
141{
142 /**
143 * Sender's identity
144 */
145 struct GNUNET_PeerIdentity sender;
146
147 /**
148 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE
149 */
150 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
151
152 /**
153 * Monotonic time of @e sender, to possibly help detect replay attacks
154 * (if receiver persists times by sender).
155 */
156 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
157
158 /* followed by messages */
159
160 /* padding may follow actual messages */
161};
162
163
164/**
165 * UDP key acknowledgement. May be sent via backchannel. Allows the
166 * sender to use `struct UDPBox` with the acknowledge key henceforth.
167 */
168struct UDPAck
169{
170
171 /**
172 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK.
173 */
174 struct GNUNET_MessageHeader header;
175
176 /**
177 * Sequence acknowledgement limit. Specifies current maximum sequence
178 * number supported by receiver.
179 */
180 uint32_t sequence_max GNUNET_PACKED;
181
182 /**
183 * CMAC of the base key being acknowledged.
184 */
185 struct GNUNET_HashCode cmac;
186
187};
188
189
190/**
191 * UDP message box. Always sent encrypted, only allowed after
192 * the receiver sent a `struct UDPAck` for the base key!
193 */
194struct UDPBox
195{
196
197 /**
198 * Key and IV identification code. KDF applied to an acknowledged
199 * base key and a sequence number. Sequence numbers must be used
200 * monotonically increasing up to the maximum specified in
201 * `struct UDPAck`. Without further `struct UDPAck`s, the sender
202 * must fall back to sending handshakes!
203 */
204 struct GNUNET_ShortHashCode kid;
205
206 /**
207 * 128-bit authentication tag for the following encrypted message,
208 * from GCM. MAC starts at the @e body_start that follows and
209 * extends until the end of the UDP payload. If the @e hmac is
210 * wrong, the receiver should check if the message might be a
211 * `struct UdpHandshakeSignature`.
212 */
213 uint8_t gcm_tag[128/8];
214
215
216};
217
218
219GNUNET_NETWORK_STRUCT_END
220
221/**
222 * Shared secret we generated for a particular sender or receiver.
223 */
224struct SharedSecret;
225
226
227/**
228 * Pre-generated "kid" code (key and IV identification code) to
229 * quickly derive master key for a `struct UDPBox`.
230 */
231struct KeyCacheEntry
232{
233
234 /**
235 * Kept in a DLL.
236 */
237 struct KeyCacheEntry *next;
238
239 /**
240 * Kept in a DLL.
241 */
242 struct KeyCacheEntry *prev;
243
244 /**
245 * Key and IV identification code. KDF applied to an acknowledged
246 * base key and a sequence number. Sequence numbers must be used
247 * monotonically increasing up to the maximum specified in
248 * `struct UDPAck`. Without further `struct UDPAck`s, the sender
249 * must fall back to sending handshakes!
250 */
251 struct GNUNET_ShortHashCode kid;
252
253 /**
254 * Corresponding shared secret.
255 */
256 struct SharedSecret *ss;
257
258 /**
259 * Sequence number used to derive this entry from master key.
260 */
261 uint32_t sequence_number;
262};
263
264
265/**
266 * Information we track per sender address we have recently been
267 * in contact with (decryption from sender).
268 */
269struct SenderAddress;
270
271/**
272 * Information we track per receiving address we have recently been
273 * in contact with (encryption to receiver).
274 */
275struct ReceiverAddress;
276
277/**
278 * Shared secret we generated for a particular sender or receiver.
279 */
280struct SharedSecret
281{
282 /**
283 * Kept in a DLL.
284 */
285 struct SharedSecret *next;
286
287 /**
288 * Kept in a DLL.
289 */
290 struct SharedSecret *prev;
291
292 /**
293 * Kept in a DLL, sorted by sequence number. Only if we are decrypting.
294 */
295 struct KeyCacheEntry *kce_head;
296
297 /**
298 * Kept in a DLL, sorted by sequence number. Only if we are decrypting.
299 */
300 struct KeyCacheEntry *kce_tail;
301
302 /**
303 * Sender we use this shared secret with, or NULL.
304 */
305 struct SenderAddress *sender;
306
307 /**
308 * Receiver we use this shared secret with, or NULL.
309 */
310 struct ReceiverAddress *receiver;
311
312 /**
313 * Master shared secret.
314 */
315 struct GNUNET_HashCode master;
316
317 /**
318 * CMAC is used to identify @e master in ACKs.
319 */
320 struct GNUNET_HashCode cmac;
321
322 /**
323 * Up to which sequence number did we use this @e master already?
324 * (for sending or receiving)
325 */
326 uint32_t sequence_used;
327
328 /**
329 * Up to which sequence number did the other peer allow us to use
330 * this key, or up to which number did we allow the other peer to
331 * use this key?
332 */
333 uint32_t sequence_allowed;
334};
335
336
337/**
338 * Information we track per sender address we have recently been
339 * in contact with (we decrypt messages from the sender).
340 */
341struct SenderAddress
342{
343
344 /**
345 * To whom are we talking to.
346 */
347 struct GNUNET_PeerIdentity target;
348
349 /**
350 * Entry in sender expiration heap.
351 */
352 struct GNUNET_CONTAINER_HeapNode *hn;
353
354 /**
355 * Shared secrets we used with @e target, first used is head.
356 */
357 struct SharedSecret *ss_head;
358
359 /**
360 * Shared secrets we used with @e target, last used is tail.
361 */
362 struct SharedSecret *ss_tail;
363
364 /**
365 * Address of the other peer.
366 */
367 struct sockaddr *address;
368
369 /**
370 * Length of the address.
371 */
372 socklen_t address_len;
373
374 /**
375 * Timeout for this sender.
376 */
377 struct GNUNET_TIME_Absolute timeout;
378
379 /**
380 * Length of the DLL at @a ss_head.
381 */
382 unsigned int num_secrets;
383
384 /**
385 * Which network type does this queue use?
386 */
387 enum GNUNET_NetworkType nt;
388
389};
390
391
392/**
393 * Information we track per receiving address we have recently been
394 * in contact with (encryption to receiver).
395 */
396struct ReceiverAddress
397{
398
399 /**
400 * To whom are we talking to.
401 */
402 struct GNUNET_PeerIdentity target;
403
404 /**
405 * Shared secrets we received from @e target, first used is head.
406 */
407 struct SharedSecret *ss_head;
408
409 /**
410 * Shared secrets we received with @e target, last used is tail.
411 */
412 struct SharedSecret *ss_tail;
413
414 /**
415 * Address of the other peer.
416 */
417 struct sockaddr *address;
418
419 /**
420 * Length of the address.
421 */
422 socklen_t address_len;
423
424 /**
425 * Message queue we are providing for the #ch.
426 */
427 struct GNUNET_MQ_Handle *mq;
428
429 /**
430 * handle for this queue with the #ch.
431 */
432 struct GNUNET_TRANSPORT_QueueHandle *qh;
433
434 /**
435 * Timeout for this receiver address.
436 */
437 struct GNUNET_TIME_Absolute timeout;
438
439 /**
440 * Length of the DLL at @a ss_head.
441 */
442 unsigned int num_secrets;
443
444 /**
445 * Which network type does this queue use?
446 */
447 enum GNUNET_NetworkType nt;
448
449};
450
451
452/**
453 * Cache of pre-generated key IDs.
454 */
455static struct GNUNET_CONTINER_MultiShortMap *key_cache;
456
457/**
458 * ID of read task
459 */
460static struct GNUNET_SCHEDULER_Task *read_task;
461
462/**
463 * ID of timeout task
464 */
465static struct GNUNET_SCHEDULER_Task *timeout_task;
466
467/**
468 * For logging statistics.
469 */
470static struct GNUNET_STATISTICS_Handle *stats;
471
472/**
473 * Our environment.
474 */
475static struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
476
477/**
478 * Receivers (map from peer identity to `struct ReceiverAddress`)
479 */
480static struct GNUNET_CONTAINER_MultiPeerMap *receivers;
481
482/**
483 * Senders (map from peer identity to `struct SenderAddress`)
484 */
485static struct GNUNET_CONTAINER_MultiPeerMap *senders;
486
487/**
488 * Expiration heap for senders (contains `struct SenderAddress`)
489 */
490static struct GNUNET_CONTAINER_Heap *senders_heap;
491
492/**
493 * Expiration heap for receivers (contains `struct ReceiverAddress`)
494 */
495static struct GNUNET_CONTAINER_Heap *receivers_heap;
496
497/**
498 * Our socket.
499 */
500static struct GNUNET_NETWORK_Handle *udp_sock;
501
502/**
503 * Our public key.
504 */
505static struct GNUNET_PeerIdentity my_identity;
506
507/**
508 * Our private key.
509 */
510static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
511
512/**
513 * Our configuration.
514 */
515static const struct GNUNET_CONFIGURATION_Handle *cfg;
516
517/**
518 * Network scanner to determine network types.
519 */
520static struct GNUNET_NT_InterfaceScanner *is;
521
522/**
523 * Connection to NAT service.
524 */
525static struct GNUNET_NAT_Handle *nat;
526
527
528/**
529 * Functions with this signature are called whenever we need
530 * to close a receiving state due to timeout.
531 *
532 * @param receiver entity to close down
533 */
534static void
535receiver_destroy (struct ReceiverAddress *receiver)
536{
537 struct GNUNET_MQ_Handle *mq;
538
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540 "Disconnecting receiver for peer `%s'\n",
541 GNUNET_i2s (&receiver->target));
542 if (NULL != (mq = receiver->mq))
543 {
544 receiver->mq = NULL;
545 GNUNET_MQ_destroy (mq);
546 }
547 GNUNET_assert (GNUNET_YES ==
548 GNUNET_CONTAINER_multipeermap_remove (receivers,
549 &receiver->target,
550 receiver));
551 // FIXME: remove from receiver_heap
552 GNUNET_STATISTICS_set (stats,
553 "# receivers active",
554 GNUNET_CONTAINER_multipeermap_size (receivers),
555 GNUNET_NO);
556 GNUNET_free (receiver->address);
557 GNUNET_free (receiver);
558}
559
560
561/**
562 * Free memory used by key cache entry.
563 *
564 * @param kce the key cache entry
565 */
566static void
567kce_destroy (struct KeyCacheEntry *kce)
568{
569 struct SharedSecret *ss = kce->ss;
570
571 GNUNET_CONTAINER_DLL_remove (ss->kce_head,
572 ss->kce_tail,
573 kce);
574 GNUNET_assert (GNUNET_YES ==
575 GNUNET_CONTAINER_multishortmap_remove (key_cache,
576 &kce->kid,
577 kce));
578 GNUNET_free (kce);
579}
580
581
582/**
583 * Compute @a kid.
584 *
585 * @param msec master secret for HMAC calculation
586 * @param serial number for the @a smac calculation
587 * @param kid[out] where to write the key ID
588 */
589static void
590get_kid (const struct GNUNET_HashCode *msec,
591 uint32_t serial,
592 struct GNUNET_ShortHashCode *kid)
593{
594 uint32_t sid = htonl (serial);
595
596 GNUNET_CRYPTO_hkdf (kid,
597 sizeof (*kid),
598 GCRY_MD_SHA512,
599 GCRY_MD_SHA256,
600 &sid,
601 sizeof (sid),
602 msec,
603 sizeof (*msec),
604 "UDP-KID",
605 strlen ("UDP-KID"),
606 NULL, 0);
607}
608
609
610/**
611 * Setup key cache entry for sequence number @a seq and shared secret @a ss.
612 *
613 * @param ss shared secret
614 * @param seq sequence number for the key cache entry
615 */
616static void
617kce_generate (struct SharedSecret *ss,
618 uint32_t seq)
619{
620 struct KeyCacheEntry *kce;
621
622 GNUNET_assert (0 < seq);
623 kce = GNUNET_new (struct KeyCacheEntry);
624 kce->ss = ss;
625 kce->sequence_number = seq;
626 get_kid (&ss->master,
627 seq,
628 &kce->kid);
629 GNUNET_CONTAINER_DLL_insert (ss->kce_head,
630 ss->kce_tail,
631 kce);
632 (void) GNUNET_CONTAINER_multishortmap_put (key_cache,
633 &kce->kid,
634 kce,
635 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
636 GNUNET_STATISTICS_set (stats,
637 "# KIDs active",
638 GNUNET_CONTAINER_multipeermap_size (key_cache),
639 GNUNET_NO);
640}
641
642
643/**
644 * Destroy @a ss and associated key cache entries.
645 *
646 * @param ss shared secret to destroy
647 */
648static void
649secret_destroy (struct SharedSecret *ss)
650{
651 struct SenderAddress *sender;
652 struct ReceiverAddress *receiver;
653 struct KeyCacheEntry *kce;
654
655 if (NULL != (sender = ss->sender))
656 {
657 GNUNET_CONTAINER_DLL_remove (sender->ss_head,
658 sender->ss_tail,
659 ss);
660 sender->num_secrets--;
661 }
662 if (NULL != (receiver = ss->receiver))
663 {
664 GNUNET_CONTAINER_DLL_remove (receiver->ss_head,
665 receiver->ss_tail,
666 ss);
667 receiver->num_secrets--;
668 }
669 while (NULL != (kce = ss->kce_head))
670 kce_destroy (kce);
671 GNUNET_STATISTICS_update (stats,
672 "# Secrets active",
673 -1,
674 GNUNET_NO);
675 GNUNET_STATISTICS_set (stats,
676 "# KIDs active",
677 GNUNET_CONTAINER_multipeermap_size (key_cache),
678 GNUNET_NO);
679 GNUNET_free (ss);
680}
681
682
683/**
684 * Functions with this signature are called whenever we need
685 * to close a sender's state due to timeout.
686 *
687 * @param sender entity to close down
688 */
689static void
690sender_destroy (struct SenderAddress *sender)
691{
692 GNUNET_assert (GNUNET_YES ==
693 GNUNET_CONTAINER_multipeermap_remove (senders,
694 &sender->target,
695 sender));
696 // FIXME: remove from sender_heap
697 GNUNET_STATISTICS_set (stats,
698 "# senders active",
699 GNUNET_CONTAINER_multipeermap_size (senders),
700 GNUNET_NO);
701 GNUNET_free (sender->address);
702 GNUNET_free (sender);
703}
704
705
706/**
707 * Compute @a smac over @a buf.
708 *
709 * @param msec master secret for HMAC calculation
710 * @param serial number for the @a smac calculation
711 * @param buf buffer to MAC
712 * @param buf_size number of bytes in @a buf
713 * @param smac[out] where to write the HMAC
714 */
715static void
716get_hmac (const struct GNUNET_HashCode *msec,
717 uint32_t serial,
718 const void *buf,
719 size_t buf_size,
720 struct GNUNET_ShortHashCode *smac)
721{
722 uint32_t sid = htonl (serial);
723
724 GNUNET_CRYPTO_hkdf (smac,
725 sizeof (*smac),
726 GCRY_MD_SHA512,
727 GCRY_MD_SHA256,
728 &sid,
729 sizeof (sid),
730 msec,
731 sizeof (*msec),
732 "UDP-HMAC",
733 strlen ("UDP-HMAC"),
734 NULL, 0);
735}
736
737
738/**
739 * Compute @a key and @a iv.
740 *
741 * @param msec master secret for calculation
742 * @param serial number for the @a smac calculation
743 * @param key[out] where to write the decrption key
744 * @param iv[out] where to write the IV
745 */
746static void
747get_iv_key (const struct GNUNET_HashCode *msec,
748 uint32_t serial,
749 char key[256/8],
750 char iv[96/8])
751{
752 uint32_t sid = htonl (serial);
753 char res[sizeof(key) + sizeof (iv)];
754
755 GNUNET_CRYPTO_hkdf (res,
756 sizeof (res),
757 GCRY_MD_SHA512,
758 GCRY_MD_SHA256,
759 &sid,
760 sizeof (sid),
761 msec,
762 sizeof (*msec),
763 "UDP-IV-KEY",
764 strlen ("UDP-IV-KEY"),
765 NULL, 0);
766 memcpy (key,
767 sid,
768 sizeof (key));
769 memcpy (iv,
770 &sid[sizeof(key)],
771 sizeof (iv));
772}
773
774
775/**
776 * Increment sender timeout due to activity.
777 *
778 * @param sender address for which the timeout should be rescheduled
779 */
780static void
781reschedule_sender_timeout (struct SenderAddress *sender)
782{
783 sender->timeout
784 = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
785 // FIXME: update heap!
786}
787
788
789/**
790 * Increment receiver timeout due to activity.
791 *
792 * @param receiver address for which the timeout should be rescheduled
793 */
794static void
795reschedule_receiver_timeout (struct ReceiverAddress *receiver)
796{
797 receiver->timeout
798 = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
799 // FIXME: update heap!
800}
801
802
803/**
804 * Calcualte cmac from master in @a ss.
805 *
806 * @param ss[in,out] data structure to complete
807 */
808static void
809calculate_cmac (struct SharedSecret *ss)
810{
811 GNUNET_CRYPTO_hkdf (&ss->cmac,
812 sizeof (ss->cmac),
813 GCRY_MD_SHA512,
814 GCRY_MD_SHA256,
815 "CMAC",
816 strlen ("CMAC"),
817 &ss->master,
818 sizeof (ss->master),
819 "UDP-CMAC",
820 strlen ("UDP-CMAC"),
821 NULL, 0);
822}
823
824
825/**
826 * We received @a plaintext_len bytes of @a plaintext from a @a sender.
827 * Pass it on to CORE.
828 *
829 * @param queue the queue that received the plaintext
830 * @param plaintext the plaintext that was received
831 * @param plaintext_len number of bytes of plaintext received
832 */
833static void
834pass_plaintext_to_core (struct SenderAddress *sender,
835 const void *plaintext,
836 size_t plaintext_len)
837{
838 const struct GNUNET_MessageHeader *hdr = plaintext;
839
840 while (ntohs (hdr->size) < plaintext_len)
841 {
842 GNUNET_STATISTICS_update (stats,
843 "# bytes given to core",
844 ntohs (hdr->size),
845 GNUNET_NO);
846 (void) GNUNET_TRANSPORT_communicator_receive (ch,
847 &queue->target,
848 hdr,
849 NULL /* no flow control possible */,
850 NULL);
851 /* move on to next message, if any */
852 plaintext_len -= ntohs (hdr->size);
853 if (plaintext_len < sizeof (*hdr))
854 break;
855 hdr = plaintext + ntohs (hdr->size);
856 }
857 GNUNET_STATISTICS_update (stats,
858 "# bytes padding discarded",
859 plaintext_len,
860 GNUNET_NO);
861}
862
863
864/**
865 * Setup @a cipher based on shared secret @a msec and
866 * serial number @a serial.
867 *
868 * @param msec master shared secret
869 * @param serial serial number of cipher to set up
870 * @param cipher[out] cipher to initialize
871 */
872static void
873setup_cipher (const struct GNUNET_HashCode *msec,
874 uint32_t serial,
875 gcry_cipher_hd_t *cipher)
876{
877 char key[256/8];
878 char iv[96/8];
879
880 gcry_cipher_open (cipher,
881 GCRY_CIPHER_AES256 /* low level: go for speed */,
882 GCRY_CIPHER_MODE_GCM,
883 0 /* flags */);
884 get_iv_key (msec,
885 serial,
886 key,
887 iv);
888 gcry_cipher_setkey (*cipher,
889 key,
890 sizeof (key));
891 gcry_cipher_setiv (*cipher,
892 iv,
893 sizeof (iv));
894}
895
896
897/**
898 * Try to decrypt @a buf using shared secret @a ss and key/iv
899 * derived using @a serial.
900 *
901 * @param ss shared secret
902 * @param tag GCM authentication tag
903 * @param serial serial number to use
904 * @param in_buf input buffer to decrypt
905 * @param in_buf_size number of bytes in @a in_buf and available in @a out_buf
906 * @param out_buf where to write the result
907 * @return #GNUNET_OK on success
908 */
909static int
910try_decrypt (const struct SharedSecret *ss,
911 char tag[128/8],
912 uint32_t serial,
913 const char *in_buf,
914 size_t in_buf_size,
915 char *out_buf)
916{
917 gcry_cipher_hd_t cipher;
918
919 setup_cipher (&ss->master,
920 serial,
921 &cipher);
922 GNUNET_assert (0 ==
923 gcry_cipher_decrypt (cipher,
924 in_buf,
925 in_buf_size,
926 out_buf,
927 in_buf_size));
928 if (0 !=
929 gcry_cipher_checktag (cipher,
930 tag,
931 sizeof (tag)))
932 {
933 gcry_cipher_close (cipher);
934 GNUNET_STATISTICS_update (stats,
935 "# AEAD authentication failures",
936 1,
937 GNUNET_NO);
938 return GNUNET_SYSERR;
939 }
940 gcry_cipher_close (cipher);
941 return GNUNET_OK;
942}
943
944
945/**
946 * Setup shared secret for decryption.
947 *
948 * @param ephemeral ephemeral key we received from the other peer
949 * @return new shared secret
950 */
951static struct SharedSecret *
952setup_shared_secret_dec (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral)
953{
954 struct SharedSecret *ss;
955
956 ss = GNUNET_new (struct SharedSecret);
957 GNUNET_CRYPTO_eddsa_ecdh (my_private_key,
958 ephemeral,
959 &ss->master);
960 return ss;
961}
962
963
964/**
965 * Setup shared secret for encryption.
966 *
967 * @param ephemeral ephemeral key we are sending to the other peer
968 * @param receiver[in,out] queue to initialize encryption key for
969 * @return new shared secret
970 */
971static struct SharedSecret *
972setup_shared_secret_enc (const struct GNUNET_CRYPTO_EcdhePrivateKey *ephemeral,
973 struct ReceiverAddress *receiver)
974{
975 struct SharedSecret *ss;
976
977 ss = GNUNET_new (struct SharedSecret);
978 GNUNET_CRYPTO_ecdh_eddsa (ephemeral,
979 &receiver->target.public_key,
980 &ss->master);
981 calculcate_cmac (ss);
982 ss->receiver = receiver;
983 GNUNET_CONTAINER_DLL_insert (receiver->ss_head,
984 receiver->ss_tail,
985 ss);
986 receiver->num_secrets++;
987 GNUNET_STATISTICS_update (stats,
988 "# Secrets active",
989 1,
990 GNUNET_NO);
991 return ss;
992}
993
994
995/**
996 * Test if we have received a valid message in plaintext.
997 * If so, handle it.
998 *
999 * @param sender peer to process inbound plaintext for
1000 * @param buf buffer we received
1001 * @param buf_size number of bytes in @a buf
1002 */
1003static void
1004try_handle_plaintext (struct SenderAddress *sender,
1005 const void *buf,
1006 size_t buf_size)
1007{
1008 const struct GNUNET_MessageHeader *hdr
1009 = (const struct GNUNET_MessageHeader *) queue->pread_buf;
1010 const struct UDPAck *ack
1011 = (const struct UDPAck *) queue->pread_buf;
1012 uint16_t type;
1013
1014 if (sizeof (*hdr) > buf_size)
1015 return; /* not even a header */
1016 if (ntohs (hdr->size) > buf_size)
1017 return 0; /* not even a header */
1018 type = ntohs (hdr->type);
1019 switch (type)
1020 {
1021 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK:
1022 /* lookup master secret by 'cmac', then update sequence_max */
1023 for (struct SharedSecret *ss = sender->ss_head;
1024 NULL != ss;
1025 ss = ss->next)
1026 {
1027 if (0 == memcmp (&ack->cmac,
1028 &ss->cmac,
1029 sizeof (ss->cmac)))
1030 {
1031 ss->sequence_allowed = GNUNET_MAX (ss->sequence_allowed,
1032 ntohl (ack->sequence_max));
1033 /* move ss to head to avoid discarding it anytime soon! */
1034 GNUNET_CONTAINER_DLL_remove (sender->ss_head,
1035 sender->ss_tail,
1036 ss);
1037 GNUNET_CONTAINER_DLL_insert (sender->ss_head,
1038 sender->ss_tail,
1039 ss);
1040 break;
1041 }
1042 }
1043 /* There could be more messages after the ACK, handle those as well */
1044 buf += ntohs (hdr->size);
1045 buf_size -= ntohs (hdr->size);
1046 pass_plaintext_to_core (sender,
1047 buf,
1048 buf_size);
1049 break;
1050 default:
1051 pass_plaintext_to_core (sender,
1052 buf,
1053 buf_size);
1054 }
1055}
1056
1057
1058/**
1059 * We established a shared secret with a sender. We should try to send
1060 * the sender an `struct UDPAck` at the next opportunity to allow the
1061 * sender to use @a ss longer (assuming we did not yet already
1062 * recently).
1063 */
1064static void
1065consider_ss_ack (struct SharedSecret *ss)
1066{
1067 GNUNET_assert (NULL != ss->sender);
1068 for (uint32_t i=1;i<0 /* FIXME: ack-based! */;i++)
1069 kce_generate (ss,
1070 i);
1071 // FIXME: consider generating ACK and more KCEs for ss!
1072}
1073
1074
1075/**
1076 * We received a @a box with matching @a kce. Decrypt and process it.
1077 *
1078 * @param box the data we received
1079 * @param box_len number of bytes in @a box
1080 * @param kce key index to decrypt @a box
1081 */
1082static void
1083decrypt_box (const struct UDPBox *box,
1084 size_t box_len,
1085 struct KeyCacheEntry *kce)
1086{
1087 struct SharedSecret *ss = kce->ss;
1088 gcry_cipher_hd_t cipher;
1089 char out_buf[box_len - sizeof (*box)];
1090
1091 GNUNET_assert (NULL != ss->sender);
1092 if (GNUNET_OK !=
1093 try_decrypt (ss,
1094 box->gcm_tag,
1095 kce->sequence_number,
1096 box_len - sizeof (*box),
1097 out_buf,
1098 sizeof (out_buf)))
1099 {
1100 GNUNET_STATISTICS_update (stats,
1101 "# Decryption failures with valid KCE",
1102 1,
1103 GNUNET_NO);
1104 kce_destroy (kce);
1105 return;
1106 }
1107 kce_destroy (kce);
1108 GNUNET_STATISTICS_update (stats,
1109 "# bytes decrypted with BOX",
1110 sizeof (out_buf),
1111 GNUNET_NO);
1112 try_handle_plaintext (ss->sender,
1113 out_buf,
1114 sizeof (out_buf));
1115 consider_ss_ack (ss);
1116}
1117
1118
1119/**
1120 * Socket read task.
1121 *
1122 * @param cls NULL
1123 */
1124static void
1125sock_read (void *cls)
1126{
1127 struct sockaddr_storage sa;
1128 socklen_t salen = sizeof (sa);
1129 char buf[UINT16_MAX];
1130 ssize_t rcvd;
1131
1132 (void) cls;
1133 read_task
1134 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1135 udp_sock,
1136 &sock_read,
1137 NULL);
1138 rcvd = GNUNET_NETWORK_socket_recvfrom (udp_sock,
1139 buf,
1140 sizeof (buf),
1141 (struct sockaddr *) &sa,
1142 &salen);
1143 if (-1 == rcvd)
1144 {
1145 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG,
1146 "recv");
1147 return;
1148 }
1149 /* first, see if it is a UDPBox */
1150 if (rcvd > sizeof (struct UDPBox))
1151 {
1152 const struct UDPBox *box;
1153 struct KeyCacheEntry *kce;
1154
1155 box = (const struct UDPBox *) buf;
1156 kce = GNUNET_CONTAINER_multihashmap_get (key_cache,
1157 &box->kid);
1158 if (NULL != kce)
1159 {
1160 decrypt_box (box,
1161 (size_t) rcvd,
1162 kce);
1163 return;
1164 }
1165 }
1166 /* next, test if it is a KX */
1167 if (rcvd < sizeof (struct UDPConfirmation) + sizeof (struct InitialKX))
1168 {
1169 GNUNET_STATISTICS_update (stats,
1170 "# messages dropped (no kid, too small for KX)",
1171 1,
1172 GNUNET_NO);
1173 return;
1174 }
1175
1176 {
1177 const struct InitialKX *kx;
1178 struct SharedSecret *ss;
1179 char pbuf[rcvd - sizeof (struct InitialKX)];
1180 const struct UDPConfirmation *uc;
1181 struct SenderAddress *sender;
1182
1183 kx = (const struct InitialKX *) buf;
1184 ss = setup_shared_secret_dec (&kx->ephemral);
1185 if (GNUNET_OK !=
1186 try_decrypt (ss,
1187 0,
1188 kx->gcm_tag,
1189 &buf[sizeof (*kx)],
1190 (const struct GNUNET_CRYPTO_EcdhePublicKey *) buf,
1191 pbuf))
1192 {
1193 GNUNET_free (ss);
1194 GNUNET_STATISTICS_update (stats,
1195 "# messages dropped (no kid, AEAD decryption failed)",
1196 1,
1197 GNUNET_NO);
1198 return;
1199 }
1200 uc = (const struct UDPConfirmation *) pbuf;
1201 if (GNUNET_OK !=
1202 verify_confirmation (&kx->ephemeral,
1203 uc))
1204 {
1205 GNUNET_break_op (0);
1206 GNUNET_free (ss);
1207 GNUNET_STATISTICS_update (stats,
1208 "# messages dropped (sender signature invalid)",
1209 1,
1210 GNUNET_NO);
1211 return;
1212 }
1213 calculcate_cmac (ss);
1214 sender = setup_sender (&uc->sender,
1215 (const struct sockaddr *) &sa,
1216 salen);
1217 ss->sender = sender;
1218 GNUNET_CONTAINER_DLL_insert (sender->ss_head,
1219 sender->ss_tail,
1220 ss);
1221 sender->num_secrets++;
1222 GNUNET_STATISTICS_update (stats,
1223 "# Secrets active",
1224 1,
1225 GNUNET_NO);
1226 GNUNET_STATISTICS_update (stats,
1227 "# bytes decrypted without BOX",
1228 sizeof (pbuf) - sizeof (*uc),
1229 GNUNET_NO);
1230 try_handle_plaintext (sender,
1231 &uc[1],
1232 sizeof (pbuf) - sizeof (*uc));
1233 consider_ss_ack (ss);
1234 if (sender->num_secrets > MAX_SECRETS)
1235 secret_destroy (sender->ss_tail);
1236 }
1237}
1238
1239
1240/**
1241 * Convert UDP bind specification to a `struct sockaddr *`
1242 *
1243 * @param bindto bind specification to convert
1244 * @param[out] sock_len set to the length of the address
1245 * @return converted bindto specification
1246 */
1247static struct sockaddr *
1248udp_address_to_sockaddr (const char *bindto,
1249 socklen_t *sock_len)
1250{
1251 struct sockaddr *in;
1252 unsigned int port;
1253 char dummy[2];
1254 char *colon;
1255 char *cp;
1256
1257 if (1 == SSCANF (bindto,
1258 "%u%1s",
1259 &port,
1260 dummy))
1261 {
1262 /* interpreting value as just a PORT number */
1263 if (port > UINT16_MAX)
1264 {
1265 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1266 "BINDTO specification `%s' invalid: value too large for port\n",
1267 bindto);
1268 return NULL;
1269 }
1270 if (GNUNET_YES ==
1271 GNUNET_CONFIGURATION_get_value_yesno (cfg,
1272 COMMUNICATOR_CONFIG_SECTION,
1273 "DISABLE_V6"))
1274 {
1275 struct sockaddr_in *i4;
1276
1277 i4 = GNUNET_malloc (sizeof (struct sockaddr_in));
1278 i4->sin_family = AF_INET;
1279 i4->sin_port = htons ((uint16_t) port);
1280 *sock_len = sizeof (struct sockaddr_in);
1281 in = (struct sockaddr *) i4;
1282 }
1283 else
1284 {
1285 struct sockaddr_in6 *i6;
1286
1287 i6 = GNUNET_malloc (sizeof (struct sockaddr_in6));
1288 i6->sin6_family = AF_INET6;
1289 i6->sin6_port = htons ((uint16_t) port);
1290 *sock_len = sizeof (struct sockaddr_in6);
1291 in = (struct sockaddr *) i6;
1292 }
1293 return in;
1294 }
1295 cp = GNUNET_strdup (bindto);
1296 colon = strrchr (cp, ':');
1297 if (NULL != colon)
1298 {
1299 /* interpet value after colon as port */
1300 *colon = '\0';
1301 colon++;
1302 if (1 == SSCANF (colon,
1303 "%u%1s",
1304 &port,
1305 dummy))
1306 {
1307 /* interpreting value as just a PORT number */
1308 if (port > UINT16_MAX)
1309 {
1310 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1311 "BINDTO specification `%s' invalid: value too large for port\n",
1312 bindto);
1313 GNUNET_free (cp);
1314 return NULL;
1315 }
1316 }
1317 else
1318 {
1319 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1320 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
1321 bindto);
1322 GNUNET_free (cp);
1323 return NULL;
1324 }
1325 }
1326 else
1327 {
1328 /* interpret missing port as 0, aka pick any free one */
1329 port = 0;
1330 }
1331 {
1332 /* try IPv4 */
1333 struct sockaddr_in v4;
1334
1335 if (1 == inet_pton (AF_INET,
1336 cp,
1337 &v4))
1338 {
1339 v4.sin_port = htons ((uint16_t) port);
1340 in = GNUNET_memdup (&v4,
1341 sizeof (v4));
1342 *sock_len = sizeof (v4);
1343 GNUNET_free (cp);
1344 return in;
1345 }
1346 }
1347 {
1348 /* try IPv6 */
1349 struct sockaddr_in6 v6;
1350 const char *start;
1351
1352 start = cp;
1353 if ( ('[' == *cp) &&
1354 (']' == cp[strlen (cp)-1]) )
1355 {
1356 start++; /* skip over '[' */
1357 cp[strlen (cp) -1] = '\0'; /* eat ']' */
1358 }
1359 if (1 == inet_pton (AF_INET6,
1360 start,
1361 &v6))
1362 {
1363 v6.sin6_port = htons ((uint16_t) port);
1364 in = GNUNET_memdup (&v6,
1365 sizeof (v6));
1366 *sock_len = sizeof (v6);
1367 GNUNET_free (cp);
1368 return in;
1369 }
1370 }
1371 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
1372 GNUNET_free (cp);
1373 return NULL;
1374}
1375
1376
1377#if 0
1378/**
1379 *
1380 *
1381 */
1382static void
1383XXX_write (void *cls)
1384{
1385 ssize_t sent;
1386
1387 sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1388 );
1389 if (-1 == sent)
1390 {
1391 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1392 "send");
1393 return;
1394 }
1395}
1396#endif
1397
1398
1399/**
1400 * Signature of functions implementing the sending functionality of a
1401 * message queue.
1402 *
1403 * @param mq the message queue
1404 * @param msg the message to send
1405 * @param impl_state our `struct ReceiverAddress`
1406 */
1407static void
1408mq_send (struct GNUNET_MQ_Handle *mq,
1409 const struct GNUNET_MessageHeader *msg,
1410 void *impl_state)
1411{
1412 struct ReceiverAddress *receiver = impl_state;
1413 uint16_t msize = ntohs (msg->size);
1414
1415 GNUNET_assert (mq == receiver->mq);
1416 // FIXME: pick encryption method, encrypt and transmit and call MQ-send-contiue!!
1417
1418#if 0
1419 /* compute 'tc' and append in encrypted format to cwrite_buf */
1420 tc.sender = my_identity;
1421 tc.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1422 ths.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE);
1423 ths.purpose.size = htonl (sizeof (ths));
1424 ths.sender = my_identity;
1425 ths.receiver = queue->target;
1426 ths.ephemeral = *epub;
1427 ths.monotonic_time = tc.monotonic_time;
1428 GNUNET_assert (GNUNET_OK ==
1429 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1430 &ths.purpose,
1431 &tc.sender_sig));
1432 GNUNET_assert (0 ==
1433 gcry_cipher_encrypt (queue->out_cipher,
1434 &queue->cwrite_buf[queue->cwrite_off],
1435 sizeof (tc),
1436 &tc,
1437 sizeof (tc)));
1438#endif
1439
1440
1441}
1442
1443
1444/**
1445 * Signature of functions implementing the destruction of a message
1446 * queue. Implementations must not free @a mq, but should take care
1447 * of @a impl_state.
1448 *
1449 * @param mq the message queue to destroy
1450 * @param impl_state our `struct ReceiverAddress`
1451 */
1452static void
1453mq_destroy (struct GNUNET_MQ_Handle *mq,
1454 void *impl_state)
1455{
1456 struct ReceiverAddress *receiver = impl_state;
1457
1458 if (mq == receiver->mq)
1459 {
1460 receiver->mq = NULL;
1461 receiver_destroy (receiver);
1462 }
1463}
1464
1465
1466/**
1467 * Implementation function that cancels the currently sent message.
1468 *
1469 * @param mq message queue
1470 * @param impl_state our `struct RecvierAddress`
1471 */
1472static void
1473mq_cancel (struct GNUNET_MQ_Handle *mq,
1474 void *impl_state)
1475{
1476 /* Cancellation is impossible with UDP; bail */
1477 GNUNET_assert (0);
1478}
1479
1480
1481/**
1482 * Generic error handler, called with the appropriate
1483 * error code and the same closure specified at the creation of
1484 * the message queue.
1485 * Not every message queue implementation supports an error handler.
1486 *
1487 * @param cls our `struct ReceiverAddress`
1488 * @param error error code
1489 */
1490static void
1491mq_error (void *cls,
1492 enum GNUNET_MQ_Error error)
1493{
1494 struct ReceiverAddress *receiver = cls;
1495
1496 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1497 "MQ error in queue to %s: %d\n",
1498 GNUNET_i2s (&receiver->target),
1499 (int) error);
1500 receiver_destroy (receiver);
1501}
1502
1503
1504/**
1505 * Setup a receiver for transmission. Setup the MQ processing and
1506 * inform transport that the queue is ready.
1507 *
1508 * @param
1509 */
1510static struct ReceiverAddress *
1511receiver_setup (const struct GNUNET_PeerIdentity *target,
1512 const struct sockddr *address,
1513 socklen_t address_len)
1514{
1515 struct ReceiverAddress *receiver;
1516
1517 receiver = GNUNET_new (struct ReceiverAddress);
1518 receiver->address = GNUNET_memdup (address,
1519 address_len);
1520 receiver->address_len = address_len;
1521 receiver->target = *target;
1522 receiver->nt = GNUNET_NT_scanner_get_type (is,
1523 address,
1524 address_len);
1525 (void) GNUNET_CONTAINER_multipeermap_put (receivers,
1526 &receiver->target,
1527 receiver,
1528 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1529 // FIXME: add to receiver heap!
1530 GNUNET_STATISTICS_set (stats,
1531 "# receivers active",
1532 GNUNET_CONTAINER_multipeermap_size (receivers),
1533 GNUNET_NO);
1534 receiver->timeout
1535 = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1536 receiver->mq
1537 = GNUNET_MQ_queue_for_callbacks (&mq_send,
1538 &mq_destroy,
1539 &mq_cancel,
1540 receiver,
1541 NULL,
1542 &mq_error,
1543 receiver);
1544 {
1545 char *foreign_addr;
1546
1547 switch (address->sa_family)
1548 {
1549 case AF_INET:
1550 GNUNET_asprintf (&foreign_addr,
1551 "%s-%s",
1552 COMMUNICATOR_ADDRESS_PREFIX,
1553 GNUNET_a2s(queue->address,
1554 queue->address_len));
1555 break;
1556 case AF_INET6:
1557 GNUNET_asprintf (&foreign_addr,
1558 "%s-%s",
1559 COMMUNICATOR_ADDRESS_PREFIX,
1560 GNUNET_a2s(queue->address,
1561 queue->address_len));
1562 break;
1563 default:
1564 GNUNET_assert (0);
1565 }
1566 queue->qh
1567 = GNUNET_TRANSPORT_communicator_mq_add (ch,
1568 &receiver->target,
1569 foreign_addr,
1570 1200 /* FIXME: MTU OK? */,
1571 queue->nt,
1572 GNUNET_TRANSPORT_CS_OUTBOUND,
1573 queue->mq);
1574 GNUNET_free (foreign_addr);
1575 }
1576}
1577
1578
1579/**
1580 * Function called by the transport service to initialize a
1581 * message queue given address information about another peer.
1582 * If and when the communication channel is established, the
1583 * communicator must call #GNUNET_TRANSPORT_communicator_mq_add()
1584 * to notify the service that the channel is now up. It is
1585 * the responsibility of the communicator to manage sane
1586 * retries and timeouts for any @a peer/@a address combination
1587 * provided by the transport service. Timeouts and retries
1588 * do not need to be signalled to the transport service.
1589 *
1590 * @param cls closure
1591 * @param peer identity of the other peer
1592 * @param address where to send the message, human-readable
1593 * communicator-specific format, 0-terminated, UTF-8
1594 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is invalid
1595 */
1596static int
1597mq_init (void *cls,
1598 const struct GNUNET_PeerIdentity *peer,
1599 const char *address)
1600{
1601 struct ReceiverAddress *receiver;
1602 const char *path;
1603 struct sockaddr *in;
1604 socklen_t in_len;
1605
1606 if (0 != strncmp (address,
1607 COMMUNICATOR_ADDRESS_PREFIX "-",
1608 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
1609 {
1610 GNUNET_break_op (0);
1611 return GNUNET_SYSERR;
1612 }
1613 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
1614 in = udp_address_to_sockaddr (path,
1615 &in_len);
1616 receiver = receiver_setup (peer,
1617 in,
1618 in_len);
1619 return GNUNET_OK;
1620}
1621
1622
1623/**
1624 * Iterator over all receivers to clean up.
1625 *
1626 * @param cls NULL
1627 * @param target unused
1628 * @param value the queue to destroy
1629 * @return #GNUNET_OK to continue to iterate
1630 */
1631static int
1632get_receiver_delete_it (void *cls,
1633 const struct GNUNET_PeerIdentity *target,
1634 void *value)
1635{
1636 struct ReceiverAddress *receiver = value;
1637
1638 (void) cls;
1639 (void) target;
1640 receiver_destroy (receiver);
1641 return GNUNET_OK;
1642}
1643
1644
1645/**
1646 * Iterator over all senders to clean up.
1647 *
1648 * @param cls NULL
1649 * @param target unused
1650 * @param value the queue to destroy
1651 * @return #GNUNET_OK to continue to iterate
1652 */
1653static int
1654get_receiver_delete_it (void *cls,
1655 const struct GNUNET_PeerIdentity *target,
1656 void *value)
1657{
1658 struct SenderAddress *sender = value;
1659
1660 (void) cls;
1661 (void) target;
1662 sender_destroy (sender);
1663 return GNUNET_OK;
1664}
1665
1666
1667/**
1668 * Shutdown the UNIX communicator.
1669 *
1670 * @param cls NULL (always)
1671 */
1672static void
1673do_shutdown (void *cls)
1674{
1675 if (NULL != nat)
1676 {
1677 GNUNET_NAT_unregister (nat);
1678 nat = NULL;
1679 }
1680 if (NULL != read_task)
1681 {
1682 GNUNET_SCHEDULER_cancel (read_task);
1683 read_task = NULL;
1684 }
1685 if (NULL != udp_sock)
1686 {
1687 GNUNET_break (GNUNET_OK ==
1688 GNUNET_NETWORK_socket_close (udp_sock));
1689 udp_sock = NULL;
1690 }
1691 GNUNET_CONTAINER_multipeermap_iterate (receivers,
1692 &get_receiver_delete_it,
1693 NULL);
1694 GNUNET_CONTAINER_multipeermap_destroy (receivers);
1695 GNUNET_CONTAINER_multipeermap_iterate (senders,
1696 &get_sender_delete_it,
1697 NULL);
1698 GNUNET_CONTAINER_multipeermap_destroy (senders);
1699 GNUNET_CONTAINER_multishortmap_destroy (key_cache);
1700 GNUNET_CONTAINER_heap_destroy (senders_heap);
1701 GNUNET_CONTAINER_heap_destroy (receivers_heap);
1702 if (NULL != ch)
1703 {
1704 GNUNET_TRANSPORT_communicator_disconnect (ch);
1705 ch = NULL;
1706 }
1707 if (NULL != stats)
1708 {
1709 GNUNET_STATISTICS_destroy (stats,
1710 GNUNET_NO);
1711 stats = NULL;
1712 }
1713 if (NULL != my_private_key)
1714 {
1715 GNUNET_free (my_private_key);
1716 my_private_key = NULL;
1717 }
1718 if (NULL != is)
1719 {
1720 GNUNET_NT_scanner_done (is);
1721 is = NULL;
1722 }
1723}
1724
1725
1726/**
1727 * Function called when the transport service has received an
1728 * acknowledgement for this communicator (!) via a different return
1729 * path.
1730 *
1731 * Not applicable for UDP.
1732 *
1733 * @param cls closure
1734 * @param sender which peer sent the notification
1735 * @param msg payload
1736 */
1737static void
1738enc_notify_cb (void *cls,
1739 const struct GNUNET_PeerIdentity *sender,
1740 const struct GNUNET_MessageHeader *msg)
1741{
1742 (void) cls;
1743 (void) sender;
1744 (void) msg;
1745 GNUNET_break_op (0);
1746}
1747
1748
1749/**
1750 * Signature of the callback passed to #GNUNET_NAT_register() for
1751 * a function to call whenever our set of 'valid' addresses changes.
1752 *
1753 * @param cls closure
1754 * @param app_ctx[in,out] location where the app can store stuff
1755 * on add and retrieve it on remove
1756 * @param add_remove #GNUNET_YES to add a new public IP address,
1757 * #GNUNET_NO to remove a previous (now invalid) one
1758 * @param ac address class the address belongs to
1759 * @param addr either the previous or the new public IP address
1760 * @param addrlen actual length of the @a addr
1761 */
1762static void
1763nat_address_cb (void *cls,
1764 void **app_ctx,
1765 int add_remove,
1766 enum GNUNET_NAT_AddressClass ac,
1767 const struct sockaddr *addr,
1768 socklen_t addrlen)
1769{
1770 char *my_addr;
1771 struct GNUNET_TRANSPORT_AddressIdentifier *ai;
1772
1773 if (GNUNET_YES == add_remove)
1774 {
1775 enum GNUNET_NetworkType nt;
1776
1777 GNUNET_asprintf (&my_addr,
1778 "%s-%s",
1779 COMMUNICATOR_ADDRESS_PREFIX,
1780 GNUNET_a2s (addr,
1781 addrlen));
1782 nt = GNUNET_NT_scanner_get_type (is,
1783 addr,
1784 addrlen);
1785 ai = GNUNET_TRANSPORT_communicator_address_add (ch,
1786 my_addr,
1787 nt,
1788 GNUNET_TIME_UNIT_FOREVER_REL);
1789 GNUNET_free (my_addr);
1790 *app_ctx = ai;
1791 }
1792 else
1793 {
1794 ai = *app_ctx;
1795 GNUNET_TRANSPORT_communicator_address_remove (ai);
1796 *app_ctx = NULL;
1797 }
1798}
1799
1800
1801/**
1802 * Setup communicator and launch network interactions.
1803 *
1804 * @param cls NULL (always)
1805 * @param args remaining command-line arguments
1806 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1807 * @param c configuration
1808 */
1809static void
1810run (void *cls,
1811 char *const *args,
1812 const char *cfgfile,
1813 const struct GNUNET_CONFIGURATION_Handle *c)
1814{
1815 char *bindto;
1816 struct sockaddr *in;
1817 socklen_t in_len;
1818 struct sockaddr_storage in_sto;
1819 socklen_t sto_len;
1820
1821 (void) cls;
1822 cfg = c;
1823 if (GNUNET_OK !=
1824 GNUNET_CONFIGURATION_get_value_filename (cfg,
1825 COMMUNICATOR_CONFIG_SECTION,
1826 "BINDTO",
1827 &bindto))
1828 {
1829 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1830 COMMUNICATOR_CONFIG_SECTION,
1831 "BINDTO");
1832 return;
1833 }
1834 if (GNUNET_OK !=
1835 GNUNET_CONFIGURATION_get_value_number (cfg,
1836 COMMUNICATOR_CONFIG_SECTION,
1837 "MAX_QUEUE_LENGTH",
1838 &max_queue_length))
1839 max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
1840
1841 in = udp_address_to_sockaddr (bindto,
1842 &in_len);
1843 if (NULL == in)
1844 {
1845 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1846 "Failed to setup UDP socket address with path `%s'\n",
1847 bindto);
1848 GNUNET_free (bindto);
1849 return;
1850 }
1851 udp_sock = GNUNET_NETWORK_socket_create (in->sa_family,
1852 SOCK_DGRAM,
1853 IPPROTO_UDP);
1854 if (NULL == udp_sock)
1855 {
1856 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1857 "socket");
1858 GNUNET_free (in);
1859 GNUNET_free (bindto);
1860 return;
1861 }
1862 if (GNUNET_OK !=
1863 GNUNET_NETWORK_socket_bind (udp_sock,
1864 in,
1865 in_len))
1866 {
1867 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
1868 "bind",
1869 bindto);
1870 GNUNET_NETWORK_socket_close (udp_sock);
1871 listen_sock = NULL;
1872 GNUNET_free (in);
1873 GNUNET_free (bindto);
1874 return;
1875 }
1876 /* We might have bound to port 0, allowing the OS to figure it out;
1877 thus, get the real IN-address from the socket */
1878 sto_len = sizeof (in_sto);
1879 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
1880 (struct sockaddr *) &in_sto,
1881 &sto_len))
1882 {
1883 memcpy (&in_sto,
1884 in,
1885 in_len);
1886 sto_len = in_len;
1887 }
1888 GNUNET_free (in);
1889 GNUNET_free (bindto);
1890 in = (struct sockaddr *) &in_sto;
1891 in_len = sto_len;
1892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1893 "Bound to `%s'\n",
1894 GNUNET_a2s ((const struct sockaddr *) &in_sto,
1895 sto_len));
1896 stats = GNUNET_STATISTICS_create ("C-UDP",
1897 cfg);
1898 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1899 NULL);
1900 is = GNUNET_NT_scanner_init ();
1901 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1902 if (NULL == my_private_key)
1903 {
1904 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1905 _("Transport service is lacking key configuration settings. Exiting.\n"));
1906 GNUNET_SCHEDULER_shutdown ();
1907 return;
1908 }
1909 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1910 &my_identity.public_key);
1911 /* start listening */
1912 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1913 udp_sock,
1914 &sock_read,
1915 NULL);
1916 senders = GNUNET_CONTAINER_multipeermap_create (32,
1917 GNUNET_YES);
1918 receivers = GNUNET_CONTAINER_multipeermap_create (32,
1919 GNUNET_YES);
1920 key_cache = GNUNET_CONTAINER_multishortmap_create (1024,
1921 GNUNET_YES);
1922 ch = GNUNET_TRANSPORT_communicator_connect (cfg,
1923 COMMUNICATOR_CONFIG_SECTION,
1924 COMMUNICATOR_ADDRESS_PREFIX,
1925 GNUNET_TRANSPORT_CC_UNRELIABLE,
1926 &mq_init,
1927 NULL,
1928 &enc_notify_cb,
1929 NULL);
1930 if (NULL == ch)
1931 {
1932 GNUNET_break (0);
1933 GNUNET_SCHEDULER_shutdown ();
1934 return;
1935 }
1936 nat = GNUNET_NAT_register (cfg,
1937 COMMUNICATOR_CONFIG_SECTION,
1938 IPPROTO_UDP,
1939 1 /* one address */,
1940 (const struct sockaddr **) &in,
1941 &in_len,
1942 &nat_address_cb,
1943 NULL /* FIXME: support reversal: #5529 */,
1944 NULL /* closure */);
1945}
1946
1947
1948/**
1949 * The main function for the UNIX communicator.
1950 *
1951 * @param argc number of arguments from the command line
1952 * @param argv command line arguments
1953 * @return 0 ok, 1 on error
1954 */
1955int
1956main (int argc,
1957 char *const *argv)
1958{
1959 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1960 GNUNET_GETOPT_OPTION_END
1961 };
1962 int ret;
1963
1964 if (GNUNET_OK !=
1965 GNUNET_STRINGS_get_utf8_args (argc, argv,
1966 &argc, &argv))
1967 return 2;
1968
1969 ret =
1970 (GNUNET_OK ==
1971 GNUNET_PROGRAM_run (argc, argv,
1972 "gnunet-communicator-udp",
1973 _("GNUnet UDP communicator"),
1974 options,
1975 &run,
1976 NULL)) ? 0 : 1;
1977 GNUNET_free ((void*) argv);
1978 return ret;
1979}
1980
1981
1982/* end of gnunet-communicator-udp.c */