diff options
-rw-r--r-- | src/transport/gnunet-communicator-tcp.c | 29 | ||||
-rw-r--r-- | src/transport/gnunet-communicator-udp.c | 1982 |
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 | */ | ||
2396 | void __attribute__ ((constructor)) | ||
2397 | GNUNET_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 | |||
77 | GNUNET_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 | */ | ||
85 | struct 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 | */ | ||
119 | struct 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 | */ | ||
140 | struct 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 | */ | ||
168 | struct 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 | */ | ||
194 | struct 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 | |||
219 | GNUNET_NETWORK_STRUCT_END | ||
220 | |||
221 | /** | ||
222 | * Shared secret we generated for a particular sender or receiver. | ||
223 | */ | ||
224 | struct 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 | */ | ||
231 | struct 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 | */ | ||
269 | struct SenderAddress; | ||
270 | |||
271 | /** | ||
272 | * Information we track per receiving address we have recently been | ||
273 | * in contact with (encryption to receiver). | ||
274 | */ | ||
275 | struct ReceiverAddress; | ||
276 | |||
277 | /** | ||
278 | * Shared secret we generated for a particular sender or receiver. | ||
279 | */ | ||
280 | struct 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 | */ | ||
341 | struct 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 | */ | ||
396 | struct 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 | */ | ||
455 | static struct GNUNET_CONTINER_MultiShortMap *key_cache; | ||
456 | |||
457 | /** | ||
458 | * ID of read task | ||
459 | */ | ||
460 | static struct GNUNET_SCHEDULER_Task *read_task; | ||
461 | |||
462 | /** | ||
463 | * ID of timeout task | ||
464 | */ | ||
465 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
466 | |||
467 | /** | ||
468 | * For logging statistics. | ||
469 | */ | ||
470 | static struct GNUNET_STATISTICS_Handle *stats; | ||
471 | |||
472 | /** | ||
473 | * Our environment. | ||
474 | */ | ||
475 | static struct GNUNET_TRANSPORT_CommunicatorHandle *ch; | ||
476 | |||
477 | /** | ||
478 | * Receivers (map from peer identity to `struct ReceiverAddress`) | ||
479 | */ | ||
480 | static struct GNUNET_CONTAINER_MultiPeerMap *receivers; | ||
481 | |||
482 | /** | ||
483 | * Senders (map from peer identity to `struct SenderAddress`) | ||
484 | */ | ||
485 | static struct GNUNET_CONTAINER_MultiPeerMap *senders; | ||
486 | |||
487 | /** | ||
488 | * Expiration heap for senders (contains `struct SenderAddress`) | ||
489 | */ | ||
490 | static struct GNUNET_CONTAINER_Heap *senders_heap; | ||
491 | |||
492 | /** | ||
493 | * Expiration heap for receivers (contains `struct ReceiverAddress`) | ||
494 | */ | ||
495 | static struct GNUNET_CONTAINER_Heap *receivers_heap; | ||
496 | |||
497 | /** | ||
498 | * Our socket. | ||
499 | */ | ||
500 | static struct GNUNET_NETWORK_Handle *udp_sock; | ||
501 | |||
502 | /** | ||
503 | * Our public key. | ||
504 | */ | ||
505 | static struct GNUNET_PeerIdentity my_identity; | ||
506 | |||
507 | /** | ||
508 | * Our private key. | ||
509 | */ | ||
510 | static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | ||
511 | |||
512 | /** | ||
513 | * Our configuration. | ||
514 | */ | ||
515 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
516 | |||
517 | /** | ||
518 | * Network scanner to determine network types. | ||
519 | */ | ||
520 | static struct GNUNET_NT_InterfaceScanner *is; | ||
521 | |||
522 | /** | ||
523 | * Connection to NAT service. | ||
524 | */ | ||
525 | static 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 | */ | ||
534 | static void | ||
535 | receiver_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 | */ | ||
566 | static void | ||
567 | kce_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 | */ | ||
589 | static void | ||
590 | get_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 | */ | ||
616 | static void | ||
617 | kce_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 | */ | ||
648 | static void | ||
649 | secret_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 | */ | ||
689 | static void | ||
690 | sender_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 | */ | ||
715 | static void | ||
716 | get_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 | */ | ||
746 | static void | ||
747 | get_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 | */ | ||
780 | static void | ||
781 | reschedule_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 | */ | ||
794 | static void | ||
795 | reschedule_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 | */ | ||
808 | static void | ||
809 | calculate_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 | */ | ||
833 | static void | ||
834 | pass_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 | */ | ||
872 | static void | ||
873 | setup_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 | */ | ||
909 | static int | ||
910 | try_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 | */ | ||
951 | static struct SharedSecret * | ||
952 | setup_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 | */ | ||
971 | static struct SharedSecret * | ||
972 | setup_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 | */ | ||
1003 | static void | ||
1004 | try_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 | */ | ||
1064 | static void | ||
1065 | consider_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 | */ | ||
1082 | static void | ||
1083 | decrypt_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 | */ | ||
1124 | static void | ||
1125 | sock_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 | */ | ||
1247 | static struct sockaddr * | ||
1248 | udp_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 | */ | ||
1382 | static void | ||
1383 | XXX_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 | */ | ||
1407 | static void | ||
1408 | mq_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 | */ | ||
1452 | static void | ||
1453 | mq_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 | */ | ||
1472 | static void | ||
1473 | mq_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 | */ | ||
1490 | static void | ||
1491 | mq_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 | */ | ||
1510 | static struct ReceiverAddress * | ||
1511 | receiver_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 | */ | ||
1596 | static int | ||
1597 | mq_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 | */ | ||
1631 | static int | ||
1632 | get_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 | */ | ||
1653 | static int | ||
1654 | get_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 | */ | ||
1672 | static void | ||
1673 | do_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 | */ | ||
1737 | static void | ||
1738 | enc_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 | */ | ||
1762 | static void | ||
1763 | nat_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 | */ | ||
1809 | static void | ||
1810 | run (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 | */ | ||
1955 | int | ||
1956 | main (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 */ | ||