aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-05-11 19:30:57 +0200
committerChristian Grothoff <christian@grothoff.org>2019-05-11 19:30:57 +0200
commitbc32b1f4b64ab0897efc1fe3125c5748e17cb561 (patch)
treea48ffce44427b7bfa47c0c3bef3f37110ba4d817 /src
parentda604c171418b64fcd37a46c4526ba97b6ee47dc (diff)
downloadgnunet-bc32b1f4b64ab0897efc1fe3125c5748e17cb561.tar.gz
gnunet-bc32b1f4b64ab0897efc1fe3125c5748e17cb561.zip
move encryption logic into DVBox
Diffstat (limited to 'src')
-rw-r--r--src/transport/gnunet-service-tng.c2068
1 files changed, 889 insertions, 1179 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index 08a8ec893..f07e1c88d 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -24,8 +24,14 @@
24 * 24 *
25 * TODO: 25 * TODO:
26 * Implement next: 26 * Implement next:
27 * - properly encrypt *all* DV traffic, not only backchannel; 27 * - realize "pull" based logic (#handle_client_send()) for
28 * rename BackchannelEncapsulation logic to DVEncapsulation! 28 * `struct PendingMessage` which waits for a queue on any
29 * applicable route to be 'ready', in contrast
30 * to the 'push' based routing we use for control messages.
31 * Basically, when a queue goes idle, it should "search"
32 * via its neighbour for either virtual links or DVH's that
33 * have it as first hop and then find messages in those
34 * virtual links!
29 * - realize transport-to-transport flow control (needed in case 35 * - realize transport-to-transport flow control (needed in case
30 * communicators do not offer flow control). Note that we may not 36 * communicators do not offer flow control). Note that we may not
31 * want to simply delay the ACKs as that may cause unnecessary 37 * want to simply delay the ACKs as that may cause unnecessary
@@ -327,37 +333,10 @@ struct TransportBackchannelEncapsulationMessage
327 */ 333 */
328 struct GNUNET_MessageHeader header; 334 struct GNUNET_MessageHeader header;
329 335
330 /** 336 /* Followed by *another* message header which is the message to
331 * Reserved, always zero. 337 the communicator */
332 */
333 uint32_t reserved GNUNET_PACKED;
334
335 /**
336 * Target's peer identity (as backchannels may be transmitted
337 * indirectly, or even be broadcast).
338 */
339 struct GNUNET_PeerIdentity target;
340
341 /**
342 * Ephemeral key setup by the sender for @e target, used
343 * to encrypt the payload.
344 */
345 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
346
347 /**
348 * We use an IV here as the @e ephemeral_key is re-used for
349 * #EPHEMERAL_VALIDITY time to avoid re-signing it all the time.
350 */
351 struct GNUNET_ShortHashCode iv;
352
353 /**
354 * HMAC over the ciphertext of the encrypted, variable-size
355 * body that follows. Verified via DH of @e target and
356 * @e ephemeral_key
357 */
358 struct GNUNET_HashCode hmac;
359 338
360 /* Followed by encrypted, variable-size payload */ 339 /* Followed by a 0-terminated name of the communicator */
361}; 340};
362 341
363 342
@@ -405,7 +384,7 @@ struct EphemeralConfirmationPS
405 * Plaintext of the variable-size payload that is encrypted 384 * Plaintext of the variable-size payload that is encrypted
406 * within a `struct TransportBackchannelEncapsulationMessage` 385 * within a `struct TransportBackchannelEncapsulationMessage`
407 */ 386 */
408struct TransportBackchannelRequestPayloadP 387struct TransportDVBoxPayloadP
409{ 388{
410 389
411 /** 390 /**
@@ -432,10 +411,7 @@ struct TransportBackchannelRequestPayloadP
432 struct GNUNET_TIME_AbsoluteNBO monotonic_time; 411 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
433 412
434 /* Followed by a `struct GNUNET_MessageHeader` with a message 413 /* Followed by a `struct GNUNET_MessageHeader` with a message
435 for a communicator */ 414 for the target peer */
436
437 /* Followed by a 0-termianted string specifying the name of
438 the communicator which is to receive the message */
439}; 415};
440 416
441 417
@@ -746,6 +722,13 @@ struct TransportDVLearnMessage
746 * shortcut. 722 * shortcut.
747 * 723 *
748 * If a peer finds itself still on the list, it must drop the message. 724 * If a peer finds itself still on the list, it must drop the message.
725 *
726 * The payload of the box can only be decrypted and verified by the
727 * ultimate receiver. Intermediaries do not learn the sender's
728 * identity and the path the message has taken. However, the first
729 * hop does learn the sender as @e total_hops would be zero and thus
730 * the predecessor must be the origin (so this is not really useful
731 * for anonymization).
749 */ 732 */
750struct TransportDVBoxMessage 733struct TransportDVBoxMessage
751{ 734{
@@ -757,27 +740,48 @@ struct TransportDVBoxMessage
757 /** 740 /**
758 * Number of total hops this messages travelled. In NBO. 741 * Number of total hops this messages travelled. In NBO.
759 * @e origin sets this to zero, to be incremented at 742 * @e origin sets this to zero, to be incremented at
760 * each hop. 743 * each hop. Peers should limit the @e total_hops value
744 * they accept from other peers.
761 */ 745 */
762 uint16_t total_hops GNUNET_PACKED; 746 uint16_t total_hops GNUNET_PACKED;
763 747
764 /** 748 /**
765 * Number of hops this messages includes. In NBO. 749 * Number of hops this messages includes. In NBO. Reduced by one
750 * or more at each hop. Peers should limit the @e num_hops value
751 * they accept from other peers.
766 */ 752 */
767 uint16_t num_hops GNUNET_PACKED; 753 uint16_t num_hops GNUNET_PACKED;
768 754
769 /** 755 /**
770 * Identity of the peer that originated the message. 756 * Ephemeral key setup by the sender for target, used to encrypt the
757 * payload. Intermediaries must not change this value.
758 */
759 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
760
761 /**
762 * We use an IV here as the @e ephemeral_key is re-used for
763 * #EPHEMERAL_VALIDITY time to avoid re-signing it all the time.
764 * Intermediaries must not change this value.
765 */
766 struct GNUNET_ShortHashCode iv;
767
768 /**
769 * HMAC over the ciphertext of the encrypted, variable-size body
770 * that follows. Verified via DH of target and @e ephemeral_key.
771 * Intermediaries must not change this value.
771 */ 772 */
772 struct GNUNET_PeerIdentity origin; 773 struct GNUNET_HashCode hmac;
773 774
774 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values; 775 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
775 excluding the @e origin and the current peer, the last must be 776 excluding the @e origin and the current peer, the last must be
776 the ultimate target; if @e num_hops is zero, the receiver of this 777 the ultimate target; if @e num_hops is zero, the receiver of this
777 message is the ultimate target. */ 778 message is the ultimate target. */
778 779
779 /* Followed by the actual message, which itself may be 780 /* Followed by encrypted, variable-size payload, which
780 another box, but not a DV_LEARN or DV_BOX message! */ 781 must begin with a `struct TransportDVBoxPayloadP` */
782
783 /* Followed by the actual message, which itself must not be a
784 a DV_LEARN or DV_BOX message! */
781}; 785};
782 786
783 787
@@ -978,56 +982,6 @@ struct LearnLaunchEntry
978 982
979 983
980/** 984/**
981 * Entry in our cache of ephemeral keys we currently use. This way, we only
982 * sign an ephemeral once per @e target, and then can re-use it over multiple
983 * #GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION messages (as
984 * signing is expensive and in some cases we may use backchannel messages a
985 * lot).
986 */
987struct EphemeralCacheEntry
988{
989
990 /**
991 * Target's peer identity (we don't re-use ephemerals
992 * to limit linkability of messages).
993 */
994 struct GNUNET_PeerIdentity target;
995
996 /**
997 * Signature affirming @e ephemeral_key of type
998 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
999 */
1000 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
1001
1002 /**
1003 * How long is @e sender_sig valid
1004 */
1005 struct GNUNET_TIME_Absolute ephemeral_validity;
1006
1007 /**
1008 * What time was @e sender_sig created
1009 */
1010 struct GNUNET_TIME_Absolute monotime;
1011
1012 /**
1013 * Our ephemeral key.
1014 */
1015 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
1016
1017 /**
1018 * Our private ephemeral key.
1019 */
1020 struct GNUNET_CRYPTO_EcdhePrivateKey private_key;
1021
1022 /**
1023 * Node in the ephemeral cache for this entry.
1024 * Used for expiration.
1025 */
1026 struct GNUNET_CONTAINER_HeapNode *hn;
1027};
1028
1029
1030/**
1031 * Information we keep per #GOODPUT_AGING_SLOTS about historic 985 * Information we keep per #GOODPUT_AGING_SLOTS about historic
1032 * (or current) transmission performance. 986 * (or current) transmission performance.
1033 */ 987 */
@@ -1168,6 +1122,16 @@ struct VirtualLink
1168 struct CommunicatorMessageContext *cmc_tail; 1122 struct CommunicatorMessageContext *cmc_tail;
1169 1123
1170 /** 1124 /**
1125 * Head of list of messages pending for this VL.
1126 */
1127 struct PendingMessage *pending_msg_head;
1128
1129 /**
1130 * Tail of list of messages pending for this VL.
1131 */
1132 struct PendingMessage *pending_msg_tail;
1133
1134 /**
1171 * Task scheduled to possibly notfiy core that this peer is no 1135 * Task scheduled to possibly notfiy core that this peer is no
1172 * longer counting as confirmed. Runs the #core_visibility_check(), 1136 * longer counting as confirmed. Runs the #core_visibility_check(),
1173 * which checks that some DV-path or a queue exists that is still 1137 * which checks that some DV-path or a queue exists that is still
@@ -1186,6 +1150,12 @@ struct VirtualLink
1186 struct DistanceVector *dv; 1150 struct DistanceVector *dv;
1187 1151
1188 /** 1152 /**
1153 * Used to generate unique UUIDs for messages that are being
1154 * fragmented.
1155 */
1156 uint64_t message_uuid_ctr;
1157
1158 /**
1189 * How many more messages can we send to core before we exhaust 1159 * How many more messages can we send to core before we exhaust
1190 * the receive window of CORE for this peer? If this hits zero, 1160 * the receive window of CORE for this peer? If this hits zero,
1191 * we must tell communicators to stop providing us more messages 1161 * we must tell communicators to stop providing us more messages
@@ -1319,16 +1289,6 @@ struct DistanceVectorHop
1319 struct DistanceVectorHop *prev_neighbour; 1289 struct DistanceVectorHop *prev_neighbour;
1320 1290
1321 /** 1291 /**
1322 * Head of MDLL of messages routed via this path.
1323 */
1324 struct PendingMessage *pending_msg_head;
1325
1326 /**
1327 * Tail of MDLL of messages routed via this path.
1328 */
1329 struct PendingMessage *pending_msg_tail;
1330
1331 /**
1332 * Head of DLL of PAs that used our @a path. 1292 * Head of DLL of PAs that used our @a path.
1333 */ 1293 */
1334 struct PendingAcknowledgement *pa_head; 1294 struct PendingAcknowledgement *pa_head;
@@ -1416,6 +1376,32 @@ struct DistanceVector
1416 * CORE? If so, this is the virtual link, otherwise NULL. 1376 * CORE? If so, this is the virtual link, otherwise NULL.
1417 */ 1377 */
1418 struct VirtualLink *link; 1378 struct VirtualLink *link;
1379
1380 /**
1381 * Signature affirming @e ephemeral_key of type
1382 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
1383 */
1384 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
1385
1386 /**
1387 * How long is @e sender_sig valid
1388 */
1389 struct GNUNET_TIME_Absolute ephemeral_validity;
1390
1391 /**
1392 * What time was @e sender_sig created
1393 */
1394 struct GNUNET_TIME_Absolute monotime;
1395
1396 /**
1397 * Our ephemeral key.
1398 */
1399 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
1400
1401 /**
1402 * Our private ephemeral key.
1403 */
1404 struct GNUNET_CRYPTO_EcdhePrivateKey private_key;
1419}; 1405};
1420 1406
1421 1407
@@ -1673,16 +1659,6 @@ struct Neighbour
1673 struct GNUNET_SCHEDULER_Task *reassembly_timeout_task; 1659 struct GNUNET_SCHEDULER_Task *reassembly_timeout_task;
1674 1660
1675 /** 1661 /**
1676 * Head of list of messages pending for this neighbour.
1677 */
1678 struct PendingMessage *pending_msg_head;
1679
1680 /**
1681 * Tail of list of messages pending for this neighbour.
1682 */
1683 struct PendingMessage *pending_msg_tail;
1684
1685 /**
1686 * Head of MDLL of DV hops that have this neighbour as next hop. Must be 1662 * Head of MDLL of DV hops that have this neighbour as next hop. Must be
1687 * purged if this neighbour goes down. 1663 * purged if this neighbour goes down.
1688 */ 1664 */
@@ -1729,12 +1705,6 @@ struct Neighbour
1729 struct GNUNET_TIME_Absolute last_dv_learn_monotime; 1705 struct GNUNET_TIME_Absolute last_dv_learn_monotime;
1730 1706
1731 /** 1707 /**
1732 * Used to generate unique UUIDs for messages that are being
1733 * fragmented.
1734 */
1735 uint64_t message_uuid_ctr;
1736
1737 /**
1738 * Do we have the lastest value for @e last_dv_learn_monotime from 1708 * Do we have the lastest value for @e last_dv_learn_monotime from
1739 * PEERSTORE yet, or are we still waiting for a reply of PEERSTORE? 1709 * PEERSTORE yet, or are we still waiting for a reply of PEERSTORE?
1740 */ 1710 */
@@ -1840,14 +1810,14 @@ enum PendingMessageType
1840struct PendingMessage 1810struct PendingMessage
1841{ 1811{
1842 /** 1812 /**
1843 * Kept in a MDLL of messages for this @a target. 1813 * Kept in a MDLL of messages for this @a vl.
1844 */ 1814 */
1845 struct PendingMessage *next_neighbour; 1815 struct PendingMessage *next_vl;
1846 1816
1847 /** 1817 /**
1848 * Kept in a MDLL of messages for this @a target. 1818 * Kept in a MDLL of messages for this @a vl.
1849 */ 1819 */
1850 struct PendingMessage *prev_neighbour; 1820 struct PendingMessage *prev_vl;
1851 1821
1852 /** 1822 /**
1853 * Kept in a MDLL of messages from this @a client (if @e pmt is #PMT_CORE) 1823 * Kept in a MDLL of messages from this @a client (if @e pmt is #PMT_CORE)
@@ -1872,18 +1842,6 @@ struct PendingMessage
1872 struct PendingMessage *prev_frag; 1842 struct PendingMessage *prev_frag;
1873 1843
1874 /** 1844 /**
1875 * Kept in a MDLL of messages using this @a dvh (if @e dvh is
1876 * non-NULL).
1877 */
1878 struct PendingMessage *next_dvh;
1879
1880 /**
1881 * Kept in a MDLL of messages using this @a dvh (if @e dvh is
1882 * non-NULL).
1883 */
1884 struct PendingMessage *prev_dvh;
1885
1886 /**
1887 * Head of DLL of PAs for this pending message. 1845 * Head of DLL of PAs for this pending message.
1888 */ 1846 */
1889 struct PendingAcknowledgement *pa_head; 1847 struct PendingAcknowledgement *pa_head;
@@ -1900,16 +1858,9 @@ struct PendingMessage
1900 struct PendingMessage *bpm; 1858 struct PendingMessage *bpm;
1901 1859
1902 /** 1860 /**
1903 * Target of the request (for transmission, may not be ultimate 1861 * Target of the request (always the ultimate destination!).
1904 * destination!).
1905 */ 1862 */
1906 struct Neighbour *target; 1863 struct VirtualLink *vl;
1907
1908 /**
1909 * Distance vector path selected for this message, or
1910 * NULL if transmitted directly.
1911 */
1912 struct DistanceVectorHop *dvh;
1913 1864
1914 /** 1865 /**
1915 * Set to non-NULL value if this message is currently being given to a 1866 * Set to non-NULL value if this message is currently being given to a
@@ -2508,26 +2459,6 @@ static struct GNUNET_CONTAINER_Heap *validation_heap;
2508static struct GNUNET_PEERSTORE_Handle *peerstore; 2459static struct GNUNET_PEERSTORE_Handle *peerstore;
2509 2460
2510/** 2461/**
2511 * Heap sorting `struct EphemeralCacheEntry` by their
2512 * key/signature validity.
2513 */
2514static struct GNUNET_CONTAINER_Heap *ephemeral_heap;
2515
2516/**
2517 * Hash map for looking up `struct EphemeralCacheEntry`s
2518 * by peer identity. (We may have ephemerals in our
2519 * cache for which we do not have a neighbour entry,
2520 * and similar many neighbours may not need ephemerals,
2521 * so we use a second map.)
2522 */
2523static struct GNUNET_CONTAINER_MultiPeerMap *ephemeral_map;
2524
2525/**
2526 * Task to free expired ephemerals.
2527 */
2528static struct GNUNET_SCHEDULER_Task *ephemeral_task;
2529
2530/**
2531 * Task run to initiate DV learning. 2462 * Task run to initiate DV learning.
2532 */ 2463 */
2533static struct GNUNET_SCHEDULER_Task *dvlearn_task; 2464static struct GNUNET_SCHEDULER_Task *dvlearn_task;
@@ -2629,16 +2560,76 @@ free_pending_acknowledgement (struct PendingAcknowledgement *pa)
2629 2560
2630 2561
2631/** 2562/**
2632 * Free cached ephemeral key. 2563 * Free fragment tree below @e root, excluding @e root itself.
2564 * FIXME: this does NOT seem to have the intended semantics
2565 * based on how this is called. Seems we generally DO expect
2566 * @a root to be free'ed itself as well!
2633 * 2567 *
2634 * @param ece cached signature to free 2568 * @param root root of the tree to free
2635 */ 2569 */
2636static void 2570static void
2637free_ephemeral (struct EphemeralCacheEntry *ece) 2571free_fragment_tree (struct PendingMessage *root)
2638{ 2572{
2639 GNUNET_CONTAINER_multipeermap_remove (ephemeral_map, &ece->target, ece); 2573 struct PendingMessage *frag;
2640 GNUNET_CONTAINER_heap_remove_node (ece->hn); 2574
2641 GNUNET_free (ece); 2575 while (NULL != (frag = root->head_frag))
2576 {
2577 struct PendingAcknowledgement *pa;
2578
2579 free_fragment_tree (frag);
2580 while (NULL != (pa = frag->pa_head))
2581 {
2582 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
2583 pa->pm = NULL;
2584 }
2585 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
2586 GNUNET_free (frag);
2587 }
2588}
2589
2590
2591/**
2592 * Release memory associated with @a pm and remove @a pm from associated
2593 * data structures. @a pm must be a top-level pending message and not
2594 * a fragment in the tree. The entire tree is freed (if applicable).
2595 *
2596 * @param pm the pending message to free
2597 */
2598static void
2599free_pending_message (struct PendingMessage *pm)
2600{
2601 struct TransportClient *tc = pm->client;
2602 struct VirtualLink *vl = pm->vl;
2603 struct PendingAcknowledgement *pa;
2604
2605 if (NULL != tc)
2606 {
2607 GNUNET_CONTAINER_MDLL_remove (client,
2608 tc->details.core.pending_msg_head,
2609 tc->details.core.pending_msg_tail,
2610 pm);
2611 }
2612 if (NULL != vl)
2613 {
2614 GNUNET_CONTAINER_MDLL_remove (vl,
2615 vl->pending_msg_head,
2616 vl->pending_msg_tail,
2617 pm);
2618 }
2619 while (NULL != (pa = pm->pa_head))
2620 {
2621 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
2622 pa->pm = NULL;
2623 }
2624
2625 free_fragment_tree (pm);
2626 if (NULL != pm->qe)
2627 {
2628 GNUNET_assert (pm == pm->qe->pm);
2629 pm->qe->pm = NULL;
2630 }
2631 GNUNET_free_non_null (pm->bpm);
2632 GNUNET_free (pm);
2642} 2633}
2643 2634
2644 2635
@@ -2650,6 +2641,10 @@ free_ephemeral (struct EphemeralCacheEntry *ece)
2650static void 2641static void
2651free_virtual_link (struct VirtualLink *vl) 2642free_virtual_link (struct VirtualLink *vl)
2652{ 2643{
2644 struct PendingMessage *pm;
2645
2646 while (NULL != (pm = vl->pending_msg_head))
2647 free_pending_message (pm);
2653 GNUNET_CONTAINER_multipeermap_remove (links, &vl->target, vl); 2648 GNUNET_CONTAINER_multipeermap_remove (links, &vl->target, vl);
2654 if (NULL != vl->visibility_task) 2649 if (NULL != vl->visibility_task)
2655 { 2650 {
@@ -2744,16 +2739,7 @@ free_distance_vector_hop (struct DistanceVectorHop *dvh)
2744 struct Neighbour *n = dvh->next_hop; 2739 struct Neighbour *n = dvh->next_hop;
2745 struct DistanceVector *dv = dvh->dv; 2740 struct DistanceVector *dv = dvh->dv;
2746 struct PendingAcknowledgement *pa; 2741 struct PendingAcknowledgement *pa;
2747 struct PendingMessage *pm;
2748 2742
2749 while (NULL != (pm = dvh->pending_msg_head))
2750 {
2751 GNUNET_CONTAINER_MDLL_remove (dvh,
2752 dvh->pending_msg_head,
2753 dvh->pending_msg_tail,
2754 pm);
2755 pm->dvh = NULL;
2756 }
2757 while (NULL != (pa = dvh->pa_head)) 2743 while (NULL != (pa = dvh->pa_head))
2758 { 2744 {
2759 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa); 2745 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
@@ -3098,11 +3084,6 @@ transmit_on_queue (void *cls);
3098static void 3084static void
3099schedule_transmit_on_queue (struct Queue *queue, int inside_job) 3085schedule_transmit_on_queue (struct Queue *queue, int inside_job)
3100{ 3086{
3101 struct Neighbour *n = queue->neighbour;
3102 struct PendingMessage *pm = n->pending_msg_head;
3103 struct GNUNET_TIME_Relative out_delay;
3104
3105 GNUNET_assert (NULL != pm);
3106 if (queue->tc->details.communicator.total_queue_length >= 3087 if (queue->tc->details.communicator.total_queue_length >=
3107 COMMUNICATOR_TOTAL_QUEUE_LIMIT) 3088 COMMUNICATOR_TOTAL_QUEUE_LIMIT)
3108 { 3089 {
@@ -3121,8 +3102,10 @@ schedule_transmit_on_queue (struct Queue *queue, int inside_job)
3121 GNUNET_NO); 3102 GNUNET_NO);
3122 return; 3103 return;
3123 } 3104 }
3105#if FIXME - NEXT
3106 struct Neighbour *n = queue->neighbour;
3107 struct GNUNET_TIME_Relative out_delay;
3124 3108
3125 out_delay = GNUNET_TIME_absolute_get_remaining (pm->next_attempt);
3126 if ((GNUNET_YES == inside_job) && (0 == out_delay.rel_value_us)) 3109 if ((GNUNET_YES == inside_job) && (0 == out_delay.rel_value_us))
3127 { 3110 {
3128 GNUNET_log ( 3111 GNUNET_log (
@@ -3148,6 +3131,7 @@ schedule_transmit_on_queue (struct Queue *queue, int inside_job)
3148 pm->logging_uuid, 3131 pm->logging_uuid,
3149 queue->address, 3132 queue->address,
3150 GNUNET_STRINGS_relative_time_to_string (out_delay, GNUNET_YES)); 3133 GNUNET_STRINGS_relative_time_to_string (out_delay, GNUNET_YES));
3134#endif
3151} 3135}
3152 3136
3153 3137
@@ -3488,85 +3472,6 @@ check_client_send (void *cls, const struct OutboundMessage *obm)
3488 3472
3489 3473
3490/** 3474/**
3491 * Free fragment tree below @e root, excluding @e root itself.
3492 * FIXME: this does NOT seem to have the intended semantics
3493 * based on how this is called. Seems we generally DO expect
3494 * @a root to be free'ed itself as well!
3495 *
3496 * @param root root of the tree to free
3497 */
3498static void
3499free_fragment_tree (struct PendingMessage *root)
3500{
3501 struct PendingMessage *frag;
3502
3503 while (NULL != (frag = root->head_frag))
3504 {
3505 struct PendingAcknowledgement *pa;
3506
3507 free_fragment_tree (frag);
3508 while (NULL != (pa = frag->pa_head))
3509 {
3510 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
3511 pa->pm = NULL;
3512 }
3513 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3514 GNUNET_free (frag);
3515 }
3516}
3517
3518
3519/**
3520 * Release memory associated with @a pm and remove @a pm from associated
3521 * data structures. @a pm must be a top-level pending message and not
3522 * a fragment in the tree. The entire tree is freed (if applicable).
3523 *
3524 * @param pm the pending message to free
3525 */
3526static void
3527free_pending_message (struct PendingMessage *pm)
3528{
3529 struct TransportClient *tc = pm->client;
3530 struct Neighbour *target = pm->target;
3531 struct DistanceVectorHop *dvh = pm->dvh;
3532 struct PendingAcknowledgement *pa;
3533
3534 if (NULL != tc)
3535 {
3536 GNUNET_CONTAINER_MDLL_remove (client,
3537 tc->details.core.pending_msg_head,
3538 tc->details.core.pending_msg_tail,
3539 pm);
3540 }
3541 if (NULL != dvh)
3542 {
3543 GNUNET_CONTAINER_MDLL_remove (dvh,
3544 dvh->pending_msg_head,
3545 dvh->pending_msg_tail,
3546 pm);
3547 }
3548 GNUNET_CONTAINER_MDLL_remove (neighbour,
3549 target->pending_msg_head,
3550 target->pending_msg_tail,
3551 pm);
3552 while (NULL != (pa = pm->pa_head))
3553 {
3554 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3555 pa->pm = NULL;
3556 }
3557
3558 free_fragment_tree (pm);
3559 if (NULL != pm->qe)
3560 {
3561 GNUNET_assert (pm == pm->qe->pm);
3562 pm->qe->pm = NULL;
3563 }
3564 GNUNET_free_non_null (pm->bpm);
3565 GNUNET_free (pm);
3566}
3567
3568
3569/**
3570 * Send a response to the @a pm that we have processed a "send" 3475 * Send a response to the @a pm that we have processed a "send"
3571 * request. Sends a confirmation to the "core" client responsible for 3476 * request. Sends a confirmation to the "core" client responsible for
3572 * the original request and free's @a pm. 3477 * the original request and free's @a pm.
@@ -3577,18 +3482,18 @@ static void
3577client_send_response (struct PendingMessage *pm) 3482client_send_response (struct PendingMessage *pm)
3578{ 3483{
3579 struct TransportClient *tc = pm->client; 3484 struct TransportClient *tc = pm->client;
3580 struct Neighbour *target = pm->target; 3485 struct VirtualLink *vl = pm->vl;
3581 struct GNUNET_MQ_Envelope *env; 3486 struct GNUNET_MQ_Envelope *env;
3582 struct SendOkMessage *som; 3487 struct SendOkMessage *som;
3583 3488
3584 if (NULL != tc) 3489 if (NULL != tc)
3585 { 3490 {
3586 env = GNUNET_MQ_msg (som, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); 3491 env = GNUNET_MQ_msg (som, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
3587 som->peer = target->pid; 3492 som->peer = vl->target;
3588 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3589 "Confirming transmission of <%llu> to %s\n", 3494 "Confirming transmission of <%llu> to %s\n",
3590 pm->logging_uuid, 3495 pm->logging_uuid,
3591 GNUNET_i2s (&pm->target->pid)); 3496 GNUNET_i2s (&vl->target));
3592 GNUNET_MQ_send (tc->mq, env); 3497 GNUNET_MQ_send (tc->mq, env);
3593 } 3498 }
3594 free_pending_message (pm); 3499 free_pending_message (pm);
@@ -3596,72 +3501,6 @@ client_send_response (struct PendingMessage *pm)
3596 3501
3597 3502
3598/** 3503/**
3599 * Create a DV Box message.
3600 *
3601 * @param total_hops how many hops did the message take so far
3602 * @param num_hops length of the @a hops array
3603 * @param origin origin of the message
3604 * @param hops next peer(s) to the destination, including destination
3605 * @param payload encrypted (!) payload of the box
3606 * @param payload_size number of bytes in @a payload
3607 * @return boxed message (caller must #GNUNET_free() it).
3608 */
3609static struct TransportDVBoxMessage *
3610create_dv_box (uint16_t total_hops,
3611 const struct GNUNET_PeerIdentity *origin,
3612 const struct GNUNET_PeerIdentity *target,
3613 uint16_t num_hops,
3614 const struct GNUNET_PeerIdentity *hops,
3615 const void *payload,
3616 uint16_t payload_size)
3617{
3618 struct TransportDVBoxMessage *dvb;
3619 struct GNUNET_PeerIdentity *dhops;
3620
3621 GNUNET_assert (UINT16_MAX <
3622 sizeof (struct TransportDVBoxMessage) +
3623 sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) +
3624 payload_size);
3625 dvb = GNUNET_malloc (sizeof (struct TransportDVBoxMessage) +
3626 sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) +
3627 payload_size);
3628 dvb->header.size =
3629 htons (sizeof (struct TransportDVBoxMessage) +
3630 sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) + payload_size);
3631 dvb->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
3632 dvb->total_hops = htons (total_hops);
3633 dvb->num_hops = htons (num_hops + 1);
3634 dvb->origin = *origin;
3635 dhops = (struct GNUNET_PeerIdentity *) &dvb[1];
3636 memcpy (dhops, hops, num_hops * sizeof (struct GNUNET_PeerIdentity));
3637 dhops[num_hops] = *target;
3638 memcpy (&dhops[num_hops + 1], payload, payload_size);
3639
3640 if (GNUNET_EXTRA_LOGGING > 0)
3641 {
3642 char *path;
3643
3644 path = GNUNET_strdup (GNUNET_i2s (&dvb->origin));
3645 for (unsigned int i = 0; i <= num_hops; i++)
3646 {
3647 char *tmp;
3648
3649 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[i]));
3650 GNUNET_free (path);
3651 path = tmp;
3652 }
3653 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3654 "Creating DVBox for %u bytes of payload via %s\n",
3655 (unsigned int) payload_size,
3656 path);
3657 GNUNET_free (path);
3658 }
3659
3660 return dvb;
3661}
3662
3663
3664/**
3665 * Pick @a hops_array_length random DV paths satisfying @a options 3504 * Pick @a hops_array_length random DV paths satisfying @a options
3666 * 3505 *
3667 * @param dv data structure to pick paths from 3506 * @param dv data structure to pick paths from
@@ -3752,16 +3591,10 @@ handle_client_send (void *cls, const struct OutboundMessage *obm)
3752 struct TransportClient *tc = cls; 3591 struct TransportClient *tc = cls;
3753 struct PendingMessage *pm; 3592 struct PendingMessage *pm;
3754 const struct GNUNET_MessageHeader *obmm; 3593 const struct GNUNET_MessageHeader *obmm;
3755 struct Neighbour *target;
3756 struct DistanceVector *dv;
3757 struct DistanceVectorHop *dvh;
3758 uint32_t bytes_msg; 3594 uint32_t bytes_msg;
3759 int was_empty;
3760 const void *payload;
3761 size_t payload_size;
3762 struct TransportDVBoxMessage *dvb;
3763 struct VirtualLink *vl; 3595 struct VirtualLink *vl;
3764 enum GNUNET_MQ_PriorityPreferences pp; 3596 enum GNUNET_MQ_PriorityPreferences pp;
3597 int was_empty;
3765 3598
3766 GNUNET_assert (CT_CORE == tc->type); 3599 GNUNET_assert (CT_CORE == tc->type);
3767 obmm = (const struct GNUNET_MessageHeader *) &obm[1]; 3600 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
@@ -3781,73 +3614,34 @@ handle_client_send (void *cls, const struct OutboundMessage *obm)
3781 GNUNET_NO); 3614 GNUNET_NO);
3782 return; 3615 return;
3783 } 3616 }
3784 target = lookup_neighbour (&obm->peer);
3785 if (NULL == target)
3786 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &obm->peer);
3787 else
3788 dv = NULL;
3789 GNUNET_assert ((NULL != target) || (NULL != dv));
3790 if (NULL == target)
3791 {
3792 unsigned int res;
3793 struct DistanceVectorHop *dvh;
3794
3795 res = pick_random_dv_hops (dv, RMO_NONE, &dvh, 1);
3796 GNUNET_assert (1 == res);
3797 target = dvh->next_hop;
3798 /* FIXME: encrypt bytes_msg at &obm[1] to &obm->peer first! */
3799 dvb = create_dv_box (0,
3800 &GST_my_identity,
3801 &obm->peer,
3802 dvh->distance,
3803 dvh->path,
3804 &obm[1],
3805 bytes_msg);
3806 payload = dvb;
3807 payload_size = ntohs (dvb->header.size);
3808 }
3809 else
3810 {
3811 dvh = NULL;
3812 dvb = NULL;
3813 payload = &obm[1];
3814 payload_size = bytes_msg;
3815 }
3816 3617
3817 was_empty = (NULL == target->pending_msg_head); 3618 pm = GNUNET_malloc (sizeof (struct PendingMessage) + bytes_msg);
3818 pm = GNUNET_malloc (sizeof (struct PendingMessage) + payload_size);
3819 pm->logging_uuid = logging_uuid_gen++; 3619 pm->logging_uuid = logging_uuid_gen++;
3820 pm->prefs = pp; 3620 pm->prefs = pp;
3821 pm->client = tc; 3621 pm->client = tc;
3822 pm->target = target; 3622 pm->vl = vl;
3823 pm->bytes_msg = payload_size; 3623 pm->bytes_msg = bytes_msg;
3824 memcpy (&pm[1], payload, payload_size); 3624 memcpy (&pm[1], obmm, bytes_msg);
3825 GNUNET_free_non_null (dvb);
3826 dvb = NULL;
3827 pm->dvh = dvh;
3828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3829 "Sending %u bytes as <%llu> to %s using %s\n", 3626 "Sending %u bytes as <%llu> to %s\n",
3830 bytes_msg, 3627 bytes_msg,
3831 pm->logging_uuid, 3628 pm->logging_uuid,
3832 GNUNET_i2s (&obm->peer), 3629 GNUNET_i2s (&obm->peer));
3833 (NULL == target) ? "distance vector path" : "direct queue");
3834 if (NULL != dvh)
3835 {
3836 GNUNET_CONTAINER_MDLL_insert (dvh,
3837 dvh->pending_msg_head,
3838 dvh->pending_msg_tail,
3839 pm);
3840 }
3841 GNUNET_CONTAINER_MDLL_insert (neighbour,
3842 target->pending_msg_head,
3843 target->pending_msg_tail,
3844 pm);
3845 GNUNET_CONTAINER_MDLL_insert (client, 3630 GNUNET_CONTAINER_MDLL_insert (client,
3846 tc->details.core.pending_msg_head, 3631 tc->details.core.pending_msg_head,
3847 tc->details.core.pending_msg_tail, 3632 tc->details.core.pending_msg_tail,
3848 pm); 3633 pm);
3634 was_empty = (NULL == vl->pending_msg_head);
3635 GNUNET_CONTAINER_MDLL_insert (vl,
3636 vl->pending_msg_head,
3637 vl->pending_msg_tail,
3638 pm);
3849 if (! was_empty) 3639 if (! was_empty)
3850 return; /* all queues must already be busy */ 3640 return; /* all queues must already be busy */
3641#if 0
3642 // FIXME: check if any DVH or neighbour queue of 'vl'
3643 // is ready for transmission now. If so, encapsulate
3644 // 'pm' accordingly and send!
3851 for (struct Queue *queue = target->queue_head; NULL != queue; 3645 for (struct Queue *queue = target->queue_head; NULL != queue;
3852 queue = queue->next_neighbour) 3646 queue = queue->next_neighbour)
3853 { 3647 {
@@ -3862,6 +3656,7 @@ handle_client_send (void *cls, const struct OutboundMessage *obm)
3862 GNUNET_SCHEDULER_add_now (&transmit_on_queue, queue); 3656 GNUNET_SCHEDULER_add_now (&transmit_on_queue, queue);
3863 } 3657 }
3864 } 3658 }
3659#endif
3865} 3660}
3866 3661
3867 3662
@@ -4015,13 +3810,6 @@ check_communicator_backchannel (
4015 3810
4016 (void) cls; 3811 (void) cls;
4017 msize = ntohs (cb->header.size) - sizeof (*cb); 3812 msize = ntohs (cb->header.size) - sizeof (*cb);
4018 if (((size_t) (UINT16_MAX - msize)) >
4019 sizeof (struct TransportBackchannelEncapsulationMessage) +
4020 sizeof (struct TransportBackchannelRequestPayloadP))
4021 {
4022 GNUNET_break (0);
4023 return GNUNET_SYSERR;
4024 }
4025 inbox = (const struct GNUNET_MessageHeader *) &cb[1]; 3813 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4026 isize = ntohs (inbox->size); 3814 isize = ntohs (inbox->size);
4027 if (isize >= msize) 3815 if (isize >= msize)
@@ -4032,7 +3820,7 @@ check_communicator_backchannel (
4032 is = (const char *) inbox; 3820 is = (const char *) inbox;
4033 is += isize; 3821 is += isize;
4034 msize -= isize; 3822 msize -= isize;
4035 GNUNET_assert (msize > 0); 3823 GNUNET_assert (0 < msize);
4036 if ('\0' != is[msize - 1]) 3824 if ('\0' != is[msize - 1])
4037 { 3825 {
4038 GNUNET_break (0); 3826 GNUNET_break (0);
@@ -4043,97 +3831,32 @@ check_communicator_backchannel (
4043 3831
4044 3832
4045/** 3833/**
4046 * Remove memory used by expired ephemeral keys. 3834 * Ensure ephemeral keys in our @a dv are current. If no current one exists,
3835 * set it up.
4047 * 3836 *
4048 * @param cls NULL 3837 * @param dv[in,out] virtual link to update ephemeral for
4049 */ 3838 */
4050static void 3839static void
4051expire_ephemerals (void *cls) 3840update_ephemeral (struct DistanceVector *dv)
4052{ 3841{
4053 struct EphemeralCacheEntry *ece;
4054
4055 (void) cls;
4056 ephemeral_task = NULL;
4057 while (NULL != (ece = GNUNET_CONTAINER_heap_peek (ephemeral_heap)))
4058 {
4059 if (0 == GNUNET_TIME_absolute_get_remaining (ece->ephemeral_validity)
4060 .rel_value_us)
4061 {
4062 free_ephemeral (ece);
4063 continue;
4064 }
4065 ephemeral_task = GNUNET_SCHEDULER_add_at (ece->ephemeral_validity,
4066 &expire_ephemerals,
4067 NULL);
4068 return;
4069 }
4070}
4071
4072
4073/**
4074 * Lookup ephemeral key in our #ephemeral_map. If no valid one exists,
4075 * generate one, cache it and return it.
4076 *
4077 * @param pid peer to look up ephemeral for
4078 * @param private_key[out] set to the private key
4079 * @param ephemeral_key[out] set to the key
4080 * @param ephemeral_sender_sig[out] set to the signature
4081 * @param monotime[out] set to the monotime used for the signature
4082 */
4083static void
4084lookup_ephemeral (const struct GNUNET_PeerIdentity *pid,
4085 struct GNUNET_CRYPTO_EcdhePrivateKey *private_key,
4086 struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key,
4087 struct GNUNET_CRYPTO_EddsaSignature *ephemeral_sender_sig,
4088 struct GNUNET_TIME_Absolute *monotime)
4089{
4090 struct EphemeralCacheEntry *ece;
4091 struct EphemeralConfirmationPS ec; 3842 struct EphemeralConfirmationPS ec;
4092 3843
4093 ece = GNUNET_CONTAINER_multipeermap_get (ephemeral_map, pid); 3844 if (0 !=
4094 if ((NULL != ece) && 3845 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
4095 (0 == GNUNET_TIME_absolute_get_remaining (ece->ephemeral_validity) 3846 return;
4096 .rel_value_us)) 3847 dv->monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
4097 { 3848 dv->ephemeral_validity =
4098 free_ephemeral (ece); 3849 GNUNET_TIME_absolute_add (dv->monotime, EPHEMERAL_VALIDITY);
4099 ece = NULL; 3850 GNUNET_assert (GNUNET_OK ==
4100 } 3851 GNUNET_CRYPTO_ecdhe_key_create2 (&dv->private_key));
4101 if (NULL == ece) 3852 GNUNET_CRYPTO_ecdhe_key_get_public (&dv->private_key, &dv->ephemeral_key);
4102 { 3853 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
4103 ece = GNUNET_new (struct EphemeralCacheEntry); 3854 ec.purpose.size = htonl (sizeof (ec));
4104 ece->target = *pid; 3855 ec.target = dv->target;
4105 ece->monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg); 3856 ec.ephemeral_key = dv->ephemeral_key;
4106 ece->ephemeral_validity = 3857 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
4107 GNUNET_TIME_absolute_add (ece->monotime, EPHEMERAL_VALIDITY); 3858 &ec.purpose,
4108 GNUNET_assert (GNUNET_OK == 3859 &dv->sender_sig));
4109 GNUNET_CRYPTO_ecdhe_key_create2 (&ece->private_key));
4110 GNUNET_CRYPTO_ecdhe_key_get_public (&ece->private_key, &ece->ephemeral_key);
4111 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
4112 ec.purpose.size = htonl (sizeof (ec));
4113 ec.target = *pid;
4114 ec.ephemeral_key = ece->ephemeral_key;
4115 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
4116 &ec.purpose,
4117 &ece->sender_sig));
4118 ece->hn =
4119 GNUNET_CONTAINER_heap_insert (ephemeral_heap,
4120 ece,
4121 ece->ephemeral_validity.abs_value_us);
4122 GNUNET_assert (GNUNET_OK ==
4123 GNUNET_CONTAINER_multipeermap_put (
4124 ephemeral_map,
4125 &ece->target,
4126 ece,
4127 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
4128 if (NULL == ephemeral_task)
4129 ephemeral_task = GNUNET_SCHEDULER_add_at (ece->ephemeral_validity,
4130 &expire_ephemerals,
4131 NULL);
4132 }
4133 *private_key = ece->private_key;
4134 *ephemeral_key = ece->ephemeral_key;
4135 *ephemeral_sender_sig = ece->sender_sig;
4136 *monotime = ece->monotime;
4137} 3860}
4138 3861
4139 3862
@@ -4239,6 +3962,7 @@ route_via_neighbour (const struct Neighbour *n,
4239 GNUNET_NO); 3962 GNUNET_NO);
4240 return; 3963 return;
4241 } 3964 }
3965
4242 sel1 = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidates); 3966 sel1 = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidates);
4243 if (0 == (options & RMO_REDUNDANT)) 3967 if (0 == (options & RMO_REDUNDANT))
4244 sel2 = candidates; /* picks none! */ 3968 sel2 = candidates; /* picks none! */
@@ -4268,155 +3992,9 @@ route_via_neighbour (const struct Neighbour *n,
4268 3992
4269 3993
4270/** 3994/**
4271 * Given a distance vector path @a dvh route @a payload to
4272 * the ultimate destination respecting @a options.
4273 * Sets up the boxed message and queues it at the next hop.
4274 *
4275 * @param dvh choice of the path for the message
4276 * @param payload encrypted body to transmit
4277 * @param payload_len number of bytes in @a payload
4278 * @param options options to use for control
4279 */
4280static void
4281forward_via_dvh (const struct DistanceVectorHop *dvh,
4282 const void *payload,
4283 size_t payload_len,
4284 enum RouteMessageOptions options)
4285{
4286 struct TransportDVBoxMessage *dvb;
4287
4288 dvb = create_dv_box (0,
4289 &GST_my_identity,
4290 &dvh->dv->target,
4291 dvh->distance,
4292 dvh->path,
4293 payload,
4294 payload_len);
4295 route_via_neighbour (dvh->next_hop, &dvb->header, options);
4296 GNUNET_free (dvb);
4297}
4298
4299
4300/**
4301 * Pick a path of @a dv under constraints @a options and schedule
4302 * transmission of @a hdr.
4303 *
4304 * @param n neighbour to send to
4305 * @param hdr message to send as payload
4306 * @param options whether path must be confirmed or not
4307 * and whether we may pick multiple (2) paths
4308 */
4309static void
4310route_via_dv (const struct DistanceVector *dv,
4311 const struct GNUNET_MessageHeader *hdr,
4312 enum RouteMessageOptions options)
4313{
4314 struct DistanceVectorHop *hops[2];
4315 unsigned int res;
4316
4317 res = pick_random_dv_hops (dv,
4318 options,
4319 hops,
4320 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
4321 if (0 == res)
4322 {
4323 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4324 "Failed to route message, could not determine DV path\n");
4325 return;
4326 }
4327 // FIXME: we should encrypt `hdr` here first!
4328 for (unsigned int i = 0; i < res; i++)
4329 {
4330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4331 "Routing message of type %u to %s using DV (#%u/%u)\n",
4332 ntohs (hdr->type),
4333 GNUNET_i2s (&dv->target),
4334 i + 1,
4335 res + 1);
4336 forward_via_dvh (hops[i],
4337 hdr,
4338 ntohs (
4339 hdr->size), /* FIXME: can't do this once encrypted... */
4340 options & (~RMO_REDUNDANT));
4341 }
4342}
4343
4344
4345/**
4346 * We need to transmit @a hdr to @a target. If necessary, this may
4347 * involve DV routing.
4348 *
4349 * @param target peer to receive @a hdr
4350 * @param hdr header of the message to route and #GNUNET_free()
4351 * @param options which transmission channels are allowed
4352 */
4353static void
4354route_message (const struct GNUNET_PeerIdentity *target,
4355 struct GNUNET_MessageHeader *hdr,
4356 enum RouteMessageOptions options)
4357{
4358 struct VirtualLink *vl;
4359 struct Neighbour *n;
4360 struct DistanceVector *dv;
4361
4362 vl = GNUNET_CONTAINER_multipeermap_get (links, target);
4363 n = vl->n;
4364 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
4365 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
4366 {
4367 /* if confirmed is required, and we do not have anything
4368 confirmed, drop respective options */
4369 if (NULL == n)
4370 n = lookup_neighbour (target);
4371 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
4372 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, target);
4373 }
4374 if ((NULL == n) && (NULL == dv))
4375 {
4376 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4377 "Cannot route message of type %u to %s: no route\n",
4378 ntohs (hdr->type),
4379 GNUNET_i2s (target));
4380 GNUNET_STATISTICS_update (GST_stats,
4381 "# Messages dropped in routing: no acceptable method",
4382 1,
4383 GNUNET_NO);
4384 GNUNET_free (hdr);
4385 return;
4386 }
4387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4388 "Routing message of type %u to %s with options %X\n",
4389 ntohs (hdr->type),
4390 GNUNET_i2s (target),
4391 (unsigned int) options);
4392 /* If both dv and n are possible and we must choose:
4393 flip a coin for the choice between the two; for now 50/50 */
4394 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
4395 {
4396 if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2))
4397 n = NULL;
4398 else
4399 dv = NULL;
4400 }
4401 if ((NULL != n) && (NULL != dv))
4402 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
4403 enough for redunancy, so clear the flag. */
4404 if (NULL != n)
4405 {
4406 route_via_neighbour (n, hdr, options);
4407 }
4408 if (NULL != dv)
4409 {
4410 route_via_dv (dv, hdr, options);
4411 }
4412 GNUNET_free (hdr);
4413}
4414
4415
4416/**
4417 * Structure of the key material used to encrypt backchannel messages. 3995 * Structure of the key material used to encrypt backchannel messages.
4418 */ 3996 */
4419struct BackchannelKeyState 3997struct DVKeyState
4420{ 3998{
4421 /** 3999 /**
4422 * State of our block cipher. 4000 * State of our block cipher.
@@ -4457,9 +4035,9 @@ struct BackchannelKeyState
4457 * @param key[out] symmetric cipher and HMAC state to generate 4035 * @param key[out] symmetric cipher and HMAC state to generate
4458 */ 4036 */
4459static void 4037static void
4460bc_setup_key_state_from_km (const struct GNUNET_HashCode *km, 4038dv_setup_key_state_from_km (const struct GNUNET_HashCode *km,
4461 const struct GNUNET_ShortHashCode *iv, 4039 const struct GNUNET_ShortHashCode *iv,
4462 struct BackchannelKeyState *key) 4040 struct DVKeyState *key)
4463{ 4041{
4464 /* must match #dh_key_derive_eph_pub */ 4042 /* must match #dh_key_derive_eph_pub */
4465 GNUNET_assert (GNUNET_YES == 4043 GNUNET_assert (GNUNET_YES ==
@@ -4502,14 +4080,14 @@ dh_key_derive_eph_pid (
4502 const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ephemeral, 4080 const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ephemeral,
4503 const struct GNUNET_PeerIdentity *target, 4081 const struct GNUNET_PeerIdentity *target,
4504 const struct GNUNET_ShortHashCode *iv, 4082 const struct GNUNET_ShortHashCode *iv,
4505 struct BackchannelKeyState *key) 4083 struct DVKeyState *key)
4506{ 4084{
4507 struct GNUNET_HashCode km; 4085 struct GNUNET_HashCode km;
4508 4086
4509 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_ecdh_eddsa (priv_ephemeral, 4087 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_ecdh_eddsa (priv_ephemeral,
4510 &target->public_key, 4088 &target->public_key,
4511 &km)); 4089 &km));
4512 bc_setup_key_state_from_km (&km, iv, key); 4090 dv_setup_key_state_from_km (&km, iv, key);
4513} 4091}
4514 4092
4515 4093
@@ -4525,14 +4103,14 @@ dh_key_derive_eph_pid (
4525static void 4103static void
4526dh_key_derive_eph_pub (const struct GNUNET_CRYPTO_EcdhePublicKey *pub_ephemeral, 4104dh_key_derive_eph_pub (const struct GNUNET_CRYPTO_EcdhePublicKey *pub_ephemeral,
4527 const struct GNUNET_ShortHashCode *iv, 4105 const struct GNUNET_ShortHashCode *iv,
4528 struct BackchannelKeyState *key) 4106 struct DVKeyState *key)
4529{ 4107{
4530 struct GNUNET_HashCode km; 4108 struct GNUNET_HashCode km;
4531 4109
4532 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_eddsa_ecdh (GST_my_private_key, 4110 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_eddsa_ecdh (GST_my_private_key,
4533 pub_ephemeral, 4111 pub_ephemeral,
4534 &km)); 4112 &km));
4535 bc_setup_key_state_from_km (&km, iv, key); 4113 dv_setup_key_state_from_km (&km, iv, key);
4536} 4114}
4537 4115
4538 4116
@@ -4546,7 +4124,7 @@ dh_key_derive_eph_pub (const struct GNUNET_CRYPTO_EcdhePublicKey *pub_ephemeral,
4546 * @param data_size number of bytes in @a data 4124 * @param data_size number of bytes in @a data
4547 */ 4125 */
4548static void 4126static void
4549bc_hmac (const struct BackchannelKeyState *key, 4127dv_hmac (const struct DVKeyState *key,
4550 struct GNUNET_HashCode *hmac, 4128 struct GNUNET_HashCode *hmac,
4551 const void *data, 4129 const void *data,
4552 size_t data_size) 4130 size_t data_size)
@@ -4565,10 +4143,7 @@ bc_hmac (const struct BackchannelKeyState *key,
4565 * @param in_size number of bytes of input in @a in and available at @a dst 4143 * @param in_size number of bytes of input in @a in and available at @a dst
4566 */ 4144 */
4567static void 4145static void
4568bc_encrypt (struct BackchannelKeyState *key, 4146dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
4569 const void *in,
4570 void *dst,
4571 size_t in_size)
4572{ 4147{
4573 GNUNET_assert (0 == 4148 GNUNET_assert (0 ==
4574 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size)); 4149 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
@@ -4585,7 +4160,7 @@ bc_encrypt (struct BackchannelKeyState *key,
4585 * @param out_size number of bytes of input in @a ciph and available in @a out 4160 * @param out_size number of bytes of input in @a ciph and available in @a out
4586 */ 4161 */
4587static void 4162static void
4588bc_decrypt (struct BackchannelKeyState *key, 4163dv_decrypt (struct DVKeyState *key,
4589 void *out, 4164 void *out,
4590 const void *ciph, 4165 const void *ciph,
4591 size_t out_size) 4166 size_t out_size)
@@ -4601,7 +4176,7 @@ bc_decrypt (struct BackchannelKeyState *key,
4601 * @param key key material to clean up (memory must not be free'd!) 4176 * @param key key material to clean up (memory must not be free'd!)
4602 */ 4177 */
4603static void 4178static void
4604bc_key_clean (struct BackchannelKeyState *key) 4179dv_key_clean (struct DVKeyState *key)
4605{ 4180{
4606 gcry_cipher_close (key->cipher); 4181 gcry_cipher_close (key->cipher);
4607 GNUNET_CRYPTO_zero_keys (&key->material, sizeof (key->material)); 4182 GNUNET_CRYPTO_zero_keys (&key->material, sizeof (key->material));
@@ -4609,7 +4184,234 @@ bc_key_clean (struct BackchannelKeyState *key)
4609 4184
4610 4185
4611/** 4186/**
4187 * Function to call to further operate on the now DV encapsulated
4188 * message @a hdr, forwarding it via @a next_hop under respect of
4189 * @a options.
4190 *
4191 * @param cls closure
4192 * @param next_hop next hop of the DV path
4193 * @param hdr encapsulated message, technically a `struct TransportDFBoxMessage`
4194 * @param options options of the original message
4195 */
4196typedef void (*DVMessageHandler) (void *cls,
4197 struct Neighbour *next_hop,
4198 const struct GNUNET_MessageHeader *hdr,
4199 enum RouteMessageOptions options);
4200
4201/**
4202 * Pick a path of @a dv under constraints @a options and schedule
4203 * transmission of @a hdr.
4204 *
4205 * @param target neighbour to ultimately send to
4206 * @param num_dvhs length of the @a dvhs array
4207 * @param dvhs array of hops to send the message to
4208 * @param hdr message to send as payload
4209 * @param use function to call with the encapsulated message
4210 * @param use_cls closure for @a use
4211 * @param options whether path must be confirmed or not, to be passed to @a use
4212 */
4213static void
4214encapsulate_for_dv (struct DistanceVector *dv,
4215 unsigned int num_dvhs,
4216 struct DistanceVectorHop **dvhs,
4217 const struct GNUNET_MessageHeader *hdr,
4218 DVMessageHandler use,
4219 void *use_cls,
4220 enum RouteMessageOptions options)
4221{
4222 struct TransportDVBoxMessage box_hdr;
4223 struct TransportDVBoxPayloadP payload_hdr;
4224 uint16_t enc_body_size = ntohs (hdr->size);
4225 char enc[sizeof (struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
4226 struct TransportDVBoxPayloadP *enc_payload_hdr =
4227 (struct TransportDVBoxPayloadP *) enc;
4228 struct DVKeyState key;
4229
4230 /* Encrypt payload */
4231 box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
4232 box_hdr.total_hops = htons (0);
4233 update_ephemeral (dv);
4234 box_hdr.ephemeral_key = dv->ephemeral_key;
4235 payload_hdr.sender_sig = dv->sender_sig;
4236 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
4237 &box_hdr.iv,
4238 sizeof (box_hdr.iv));
4239 dh_key_derive_eph_pid (&dv->private_key, &dv->target, &box_hdr.iv, &key);
4240 payload_hdr.sender = GST_my_identity;
4241 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4242 dv_encrypt (&key, &payload_hdr, enc_payload_hdr, sizeof (payload_hdr));
4243 dv_encrypt (&key,
4244 hdr,
4245 &enc[sizeof (struct TransportDVBoxPayloadP)],
4246 enc_body_size);
4247 dv_hmac (&key, &box_hdr.hmac, enc, sizeof (enc));
4248 dv_key_clean (&key);
4249
4250 /* For each selected path, take the pre-computed header and body
4251 and add the path in the middle of the message; then send it. */
4252 for (unsigned int i = 0; i < num_dvhs; i++)
4253 {
4254 struct DistanceVectorHop *dvh = dvhs[i];
4255 unsigned int num_hops = dvh->distance + 1;
4256 char buf[sizeof (struct TransportDVBoxMessage) +
4257 sizeof (struct GNUNET_PeerIdentity) * num_hops +
4258 sizeof (struct TransportDVBoxPayloadP) +
4259 enc_body_size] GNUNET_ALIGN;
4260 struct GNUNET_PeerIdentity *dhops;
4261
4262 box_hdr.header.size = htons (sizeof (buf));
4263 box_hdr.num_hops = htons (num_hops);
4264 memcpy (buf, &box_hdr, sizeof (box_hdr));
4265 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof (box_hdr)];
4266 memcpy (dhops,
4267 dvh->path,
4268 dvh->distance * sizeof (struct GNUNET_PeerIdentity));
4269 dhops[dvh->distance] = dv->target;
4270 if (GNUNET_EXTRA_LOGGING > 0)
4271 {
4272 char *path;
4273
4274 path = GNUNET_strdup (GNUNET_i2s (&GST_my_identity));
4275 for (unsigned int i = 0; i <= num_hops; i++)
4276 {
4277 char *tmp;
4278
4279 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[i]));
4280 GNUNET_free (path);
4281 path = tmp;
4282 }
4283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4284 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
4285 ntohs (hdr->type),
4286 GNUNET_i2s (&dv->target),
4287 i + 1,
4288 num_dvhs + 1,
4289 path);
4290 GNUNET_free (path);
4291 }
4292
4293 memcpy (&dhops[num_hops], enc, sizeof (enc));
4294 use (use_cls,
4295 dvh->next_hop,
4296 (const struct GNUNET_MessageHeader *) buf,
4297 options);
4298 }
4299}
4300
4301
4302/**
4303 * Wrapper around #route_via_neighbour() that matches the
4304 * #DVMessageHandler structure.
4305 *
4306 * @param cls unused
4307 * @param next_hop where to send next
4308 * @param hdr header of the message to send
4309 * @param options message options for queue selection
4310 */
4311static void
4312send_dv_to_neighbour (void *cls,
4313 struct Neighbour *next_hop,
4314 const struct GNUNET_MessageHeader *hdr,
4315 enum RouteMessageOptions options)
4316{
4317 (void) cls;
4318 route_via_neighbour (next_hop, hdr, options);
4319}
4320
4321
4322/**
4323 * We need to transmit @a hdr to @a target. If necessary, this may
4324 * involve DV routing.
4325 *
4326 * @param target peer to receive @a hdr
4327 * @param hdr header of the message to route and #GNUNET_free()
4328 * @param options which transmission channels are allowed
4329 */
4330static void
4331route_message (const struct GNUNET_PeerIdentity *target,
4332 const struct GNUNET_MessageHeader *hdr,
4333 enum RouteMessageOptions options)
4334{
4335 struct VirtualLink *vl;
4336 struct Neighbour *n;
4337 struct DistanceVector *dv;
4338
4339 vl = GNUNET_CONTAINER_multipeermap_get (links, target);
4340 n = vl->n;
4341 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
4342 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
4343 {
4344 /* if confirmed is required, and we do not have anything
4345 confirmed, drop respective options */
4346 if (NULL == n)
4347 n = lookup_neighbour (target);
4348 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
4349 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, target);
4350 }
4351 if ((NULL == n) && (NULL == dv))
4352 {
4353 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4354 "Cannot route message of type %u to %s: no route\n",
4355 ntohs (hdr->type),
4356 GNUNET_i2s (target));
4357 GNUNET_STATISTICS_update (GST_stats,
4358 "# Messages dropped in routing: no acceptable method",
4359 1,
4360 GNUNET_NO);
4361 return;
4362 }
4363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4364 "Routing message of type %u to %s with options %X\n",
4365 ntohs (hdr->type),
4366 GNUNET_i2s (target),
4367 (unsigned int) options);
4368 /* If both dv and n are possible and we must choose:
4369 flip a coin for the choice between the two; for now 50/50 */
4370 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
4371 {
4372 if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2))
4373 n = NULL;
4374 else
4375 dv = NULL;
4376 }
4377 if ((NULL != n) && (NULL != dv))
4378 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
4379 enough for redunancy, so clear the flag. */
4380 if (NULL != n)
4381 {
4382 route_via_neighbour (n, hdr, options);
4383 }
4384 if (NULL != dv)
4385 {
4386 struct DistanceVectorHop *hops[2];
4387 unsigned int res;
4388
4389 res = pick_random_dv_hops (dv,
4390 options,
4391 hops,
4392 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
4393 if (0 == res)
4394 {
4395 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4396 "Failed to route message, could not determine DV path\n");
4397 return;
4398 }
4399 encapsulate_for_dv (dv,
4400 res,
4401 hops,
4402 hdr,
4403 &send_dv_to_neighbour,
4404 NULL,
4405 options & (~RMO_REDUNDANT));
4406 }
4407}
4408
4409
4410/**
4612 * Communicator requests backchannel transmission. Process the request. 4411 * Communicator requests backchannel transmission. Process the request.
4412 * Just repacks it into our `struct TransportBackchannelEncapsulationMessage *`
4413 * (which for now has exactly the same format, only a different message type)
4414 * and passes it on for routing.
4613 * 4415 *
4614 * @param cls the client 4416 * @param cls the client
4615 * @param cb the send message that was sent 4417 * @param cb the send message that was sent
@@ -4620,62 +4422,33 @@ handle_communicator_backchannel (
4620 const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb) 4422 const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4621{ 4423{
4622 struct TransportClient *tc = cls; 4424 struct TransportClient *tc = cls;
4623 struct GNUNET_CRYPTO_EcdhePrivateKey private_key; 4425 const struct GNUNET_MessageHeader *inbox =
4624 struct GNUNET_TIME_Absolute monotime; 4426 (const struct GNUNET_MessageHeader *) &cb[1];
4625 struct TransportBackchannelEncapsulationMessage *enc; 4427 uint16_t isize = ntohs (inbox->size);
4626 struct TransportBackchannelRequestPayloadP ppay; 4428 const char *is = ((const char *) &cb[1]) + isize;
4627 struct BackchannelKeyState key; 4429 char
4628 char *mpos; 4430 mbuf[isize +
4629 uint16_t msize; 4431 sizeof (struct TransportBackchannelEncapsulationMessage)] GNUNET_ALIGN;
4630 4432 struct TransportBackchannelEncapsulationMessage *be =
4631 { 4433 (struct TransportBackchannelEncapsulationMessage *) mbuf;
4632 const struct GNUNET_MessageHeader *inbox; 4434
4633 const char *is; 4435 /* 0-termination of 'is' was checked already in
4634 4436 #check_communicator_backchannel() */
4635 inbox = (const struct GNUNET_MessageHeader *) &cb[1]; 4437 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4636 /* 0-termination of 'is' was checked already in 4438 "Preparing backchannel transmission to %s:%s of type %u\n",
4637 #check_communicator_backchannel() */ 4439 GNUNET_i2s (&cb->pid),
4638 is = (const char *) &cb[1]; 4440 is,
4639 is += ntohs (inbox->size); 4441 ntohs (inbox->size));
4640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4641 "Preparing backchannel transmission to %s:%s of type %u\n",
4642 GNUNET_i2s (&cb->pid),
4643 is,
4644 ntohs (inbox->size));
4645 }
4646 /* encapsulate and encrypt message */ 4442 /* encapsulate and encrypt message */
4647 4443 be->header.type =
4648 /* FIXME: this should be done with the DV logic for all
4649 DV messages, NOT here only for backchannel! */
4650 msize = ntohs (cb->header.size) - sizeof (*cb) +
4651 sizeof (struct TransportBackchannelRequestPayloadP);
4652 enc = GNUNET_malloc (sizeof (*enc) + msize);
4653 enc->header.type =
4654 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION); 4444 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION);
4655 enc->header.size = htons (sizeof (*enc) + msize); 4445 be->header.size = htons (sizeof (mbuf));
4656 enc->target = cb->pid; 4446 memcpy (&be[1], inbox, isize);
4657 lookup_ephemeral (&cb->pid, 4447 memcpy (&mbuf[sizeof (struct TransportBackchannelEncapsulationMessage) +
4658 &private_key, 4448 isize],
4659 &enc->ephemeral_key, 4449 is,
4660 &ppay.sender_sig, 4450 strlen (is) + 1);
4661 &monotime); 4451 route_message (&cb->pid, &be->header, RMO_DV_ALLOWED);
4662 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
4663 &enc->iv,
4664 sizeof (enc->iv));
4665 dh_key_derive_eph_pid (&private_key, &cb->pid, &enc->iv, &key);
4666 ppay.monotonic_time = GNUNET_TIME_absolute_hton (monotime);
4667 mpos = (char *) &enc[1];
4668 bc_encrypt (&key, &ppay, mpos, sizeof (ppay));
4669 bc_encrypt (&key,
4670 &cb[1],
4671 &mpos[sizeof (ppay)],
4672 ntohs (cb->header.size) - sizeof (*cb));
4673 bc_hmac (&key,
4674 &enc->hmac,
4675 mpos,
4676 sizeof (ppay) + ntohs (cb->header.size) - sizeof (*cb));
4677 bc_key_clean (&key);
4678 route_message (&cb->pid, &enc->header, RMO_DV_ALLOWED);
4679 GNUNET_SERVICE_client_continue (tc->client); 4452 GNUNET_SERVICE_client_continue (tc->client);
4680} 4453}
4681 4454
@@ -5012,7 +4785,11 @@ static void
5012transmit_cummulative_ack_cb (void *cls) 4785transmit_cummulative_ack_cb (void *cls)
5013{ 4786{
5014 struct AcknowledgementCummulator *ac = cls; 4787 struct AcknowledgementCummulator *ac = cls;
5015 struct TransportReliabilityAckMessage *ack; 4788 char buf[sizeof (struct TransportReliabilityAckMessage) +
4789 ac->ack_counter *
4790 sizeof (struct TransportCummulativeAckPayloadP)] GNUNET_ALIGN;
4791 struct TransportReliabilityAckMessage *ack =
4792 (struct TransportReliabilityAckMessage *) buf;
5016 struct TransportCummulativeAckPayloadP *ap; 4793 struct TransportCummulativeAckPayloadP *ap;
5017 4794
5018 ac->task = NULL; 4795 ac->task = NULL;
@@ -5021,9 +4798,6 @@ transmit_cummulative_ack_cb (void *cls)
5021 ac->ack_counter, 4798 ac->ack_counter,
5022 GNUNET_i2s (&ac->target)); 4799 GNUNET_i2s (&ac->target));
5023 GNUNET_assert (0 < ac->ack_counter); 4800 GNUNET_assert (0 < ac->ack_counter);
5024 ack = GNUNET_malloc (sizeof (*ack) +
5025 ac->ack_counter *
5026 sizeof (struct TransportCummulativeAckPayloadP));
5027 ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK); 4801 ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK);
5028 ack->header.size = 4802 ack->header.size =
5029 htons (sizeof (*ack) + 4803 htons (sizeof (*ack) +
@@ -5576,12 +5350,22 @@ check_backchannel_encapsulation (
5576 void *cls, 5350 void *cls,
5577 const struct TransportBackchannelEncapsulationMessage *be) 5351 const struct TransportBackchannelEncapsulationMessage *be)
5578{ 5352{
5579 uint16_t size = ntohs (be->header.size); 5353 uint16_t size = ntohs (be->header.size) - sizeof (*be);
5354 const struct GNUNET_MessageHeader *inbox =
5355 (const struct GNUNET_MessageHeader *) &be[1];
5356 const char *is;
5357 uint16_t isize;
5580 5358
5581 (void) cls; 5359 (void) cls;
5582 if ((size - sizeof (*be)) < 5360 if (ntohs (inbox->size) >= size)
5583 (sizeof (struct TransportBackchannelRequestPayloadP) + 5361 {
5584 sizeof (struct GNUNET_MessageHeader))) 5362 GNUNET_break_op (0);
5363 return GNUNET_SYSERR;
5364 }
5365 isize = ntohs (inbox->size);
5366 is = ((const char *) inbox) + isize;
5367 size -= isize;
5368 if ('\0' != is[size - 1])
5585 { 5369 {
5586 GNUNET_break_op (0); 5370 GNUNET_break_op (0);
5587 return GNUNET_SYSERR; 5371 return GNUNET_SYSERR;
@@ -5591,40 +5375,27 @@ check_backchannel_encapsulation (
5591 5375
5592 5376
5593/** 5377/**
5594 * We received the plaintext @a msg from backtalker @a b. Forward 5378 * Communicator gave us a backchannel encapsulation. Process the request.
5595 * it to the respective communicator. 5379 * (We are the destination of the backchannel here.)
5596 * 5380 *
5597 * @param b a backtalker 5381 * @param cls a `struct CommunicatorMessageContext` (must call
5598 * @param msg a message, consisting of a `struct GNUNET_MessageHeader` 5382 * #finish_cmc_handling() when done)
5599 * followed by the target name of the communicator 5383 * @param be the message that was received
5600 * @param msg_size number of bytes in @a msg
5601 */ 5384 */
5602static void 5385static void
5603forward_backchannel_payload (struct Backtalker *b, 5386handle_backchannel_encapsulation (
5604 const void *msg, 5387 void *cls,
5605 size_t msg_size) 5388 const struct TransportBackchannelEncapsulationMessage *be)
5606{ 5389{
5390 struct CommunicatorMessageContext *cmc = cls;
5607 struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi; 5391 struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi;
5608 struct GNUNET_MQ_Envelope *env; 5392 struct GNUNET_MQ_Envelope *env;
5609 struct TransportClient *tc; 5393 struct TransportClient *tc;
5610 const struct GNUNET_MessageHeader *mh; 5394 const struct GNUNET_MessageHeader *inbox =
5611 const char *target_communicator; 5395 (const struct GNUNET_MessageHeader *) &be[1];
5612 uint16_t mhs; 5396 uint16_t isize = ntohs (inbox->size);
5397 const char *target_communicator = ((const char *) inbox) + isize;
5613 5398
5614 /* Determine target_communicator and check @a msg is well-formed */
5615 mh = msg;
5616 mhs = ntohs (mh->size);
5617 if (mhs <= msg_size)
5618 {
5619 GNUNET_break_op (0);
5620 return;
5621 }
5622 target_communicator = &((const char *) msg)[ntohs (mh->size)];
5623 if ('\0' != target_communicator[msg_size - mhs - 1])
5624 {
5625 GNUNET_break_op (0);
5626 return;
5627 }
5628 /* Find client providing this communicator */ 5399 /* Find client providing this communicator */
5629 for (tc = clients_head; NULL != tc; tc = tc->next) 5400 for (tc = clients_head; NULL != tc; tc = tc->next)
5630 if ((CT_COMMUNICATOR == tc->type) && 5401 if ((CT_COMMUNICATOR == tc->type) &&
@@ -5646,344 +5417,20 @@ forward_backchannel_payload (struct Backtalker *b,
5646 /* Finally, deliver backchannel message to communicator */ 5417 /* Finally, deliver backchannel message to communicator */
5647 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 5418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5648 "Delivering backchannel message from %s of type %u to %s\n", 5419 "Delivering backchannel message from %s of type %u to %s\n",
5649 GNUNET_i2s (&b->pid), 5420 GNUNET_i2s (&cmc->im.sender),
5650 ntohs (mh->type), 5421 ntohs (inbox->type),
5651 target_communicator); 5422 target_communicator);
5652 env = GNUNET_MQ_msg_extra ( 5423 env = GNUNET_MQ_msg_extra (
5653 cbi, 5424 cbi,
5654 msg_size, 5425 isize,
5655 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING); 5426 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING);
5656 cbi->pid = b->pid; 5427 cbi->pid = cmc->im.sender;
5657 memcpy (&cbi[1], msg, msg_size); 5428 memcpy (&cbi[1], inbox, isize);
5658 GNUNET_MQ_send (tc->mq, env); 5429 GNUNET_MQ_send (tc->mq, env);
5659} 5430}
5660 5431
5661 5432
5662/** 5433/**
5663 * Free data structures associated with @a b.
5664 *
5665 * @param b data structure to release
5666 */
5667static void
5668free_backtalker (struct Backtalker *b)
5669{
5670 if (NULL != b->get)
5671 {
5672 GNUNET_PEERSTORE_iterate_cancel (b->get);
5673 b->get = NULL;
5674 GNUNET_assert (NULL != b->cmc);
5675 finish_cmc_handling (b->cmc);
5676 b->cmc = NULL;
5677 }
5678 if (NULL != b->task)
5679 {
5680 GNUNET_SCHEDULER_cancel (b->task);
5681 b->task = NULL;
5682 }
5683 if (NULL != b->sc)
5684 {
5685 GNUNET_PEERSTORE_store_cancel (b->sc);
5686 b->sc = NULL;
5687 }
5688 GNUNET_assert (
5689 GNUNET_YES ==
5690 GNUNET_CONTAINER_multipeermap_remove (backtalkers, &b->pid, b));
5691 GNUNET_free (b);
5692}
5693
5694
5695/**
5696 * Callback to free backtalker records.
5697 *
5698 * @param cls NULL
5699 * @param pid unused
5700 * @param value a `struct Backtalker`
5701 * @return #GNUNET_OK (always)
5702 */
5703static int
5704free_backtalker_cb (void *cls,
5705 const struct GNUNET_PeerIdentity *pid,
5706 void *value)
5707{
5708 struct Backtalker *b = value;
5709
5710 (void) cls;
5711 (void) pid;
5712 free_backtalker (b);
5713 return GNUNET_OK;
5714}
5715
5716
5717/**
5718 * Function called when it is time to clean up a backtalker.
5719 *
5720 * @param cls a `struct Backtalker`
5721 */
5722static void
5723backtalker_timeout_cb (void *cls)
5724{
5725 struct Backtalker *b = cls;
5726
5727 b->task = NULL;
5728 if (0 != GNUNET_TIME_absolute_get_remaining (b->timeout).rel_value_us)
5729 {
5730 b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
5731 return;
5732 }
5733 GNUNET_assert (NULL == b->sc);
5734 free_backtalker (b);
5735}
5736
5737
5738/**
5739 * Function called with the monotonic time of a backtalker
5740 * by PEERSTORE. Updates the time and continues processing.
5741 *
5742 * @param cls a `struct Backtalker`
5743 * @param record the information found, NULL for the last call
5744 * @param emsg error message
5745 */
5746static void
5747backtalker_monotime_cb (void *cls,
5748 const struct GNUNET_PEERSTORE_Record *record,
5749 const char *emsg)
5750{
5751 struct Backtalker *b = cls;
5752 struct GNUNET_TIME_AbsoluteNBO *mtbe;
5753 struct GNUNET_TIME_Absolute mt;
5754
5755 (void) emsg;
5756 if (NULL == record)
5757 {
5758 /* we're done with #backtalker_monotime_cb() invocations,
5759 continue normal processing */
5760 b->get = NULL;
5761 GNUNET_assert (NULL != b->cmc);
5762 finish_cmc_handling (b->cmc);
5763 b->cmc = NULL;
5764 if (0 != b->body_size)
5765 forward_backchannel_payload (b, &b[1], b->body_size);
5766 return;
5767 }
5768 if (sizeof (*mtbe) != record->value_size)
5769 {
5770 GNUNET_break (0);
5771 return;
5772 }
5773 mtbe = record->value;
5774 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
5775 if (mt.abs_value_us > b->monotonic_time.abs_value_us)
5776 {
5777 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5778 "Backtalker message from %s dropped, monotime in the past\n",
5779 GNUNET_i2s (&b->pid));
5780 GNUNET_STATISTICS_update (
5781 GST_stats,
5782 "# Backchannel messages dropped: monotonic time not increasing",
5783 1,
5784 GNUNET_NO);
5785 b->monotonic_time = mt;
5786 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
5787 */
5788 b->body_size = 0;
5789 return;
5790 }
5791}
5792
5793
5794/**
5795 * Function called by PEERSTORE when the store operation of
5796 * a backtalker's monotonic time is complete.
5797 *
5798 * @param cls the `struct Backtalker`
5799 * @param success #GNUNET_OK on success
5800 */
5801static void
5802backtalker_monotime_store_cb (void *cls, int success)
5803{
5804 struct Backtalker *b = cls;
5805
5806 if (GNUNET_OK != success)
5807 {
5808 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5809 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
5810 }
5811 b->sc = NULL;
5812 b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
5813}
5814
5815
5816/**
5817 * The backtalker @a b monotonic time changed. Update PEERSTORE.
5818 *
5819 * @param b a backtalker with updated monotonic time
5820 */
5821static void
5822update_backtalker_monotime (struct Backtalker *b)
5823{
5824 struct GNUNET_TIME_AbsoluteNBO mtbe;
5825
5826 if (NULL != b->sc)
5827 {
5828 GNUNET_PEERSTORE_store_cancel (b->sc);
5829 b->sc = NULL;
5830 }
5831 else
5832 {
5833 GNUNET_SCHEDULER_cancel (b->task);
5834 b->task = NULL;
5835 }
5836 mtbe = GNUNET_TIME_absolute_hton (b->monotonic_time);
5837 b->sc =
5838 GNUNET_PEERSTORE_store (peerstore,
5839 "transport",
5840 &b->pid,
5841 GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME,
5842 &mtbe,
5843 sizeof (mtbe),
5844 GNUNET_TIME_UNIT_FOREVER_ABS,
5845 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
5846 &backtalker_monotime_store_cb,
5847 b);
5848}
5849
5850
5851/**
5852 * Communicator gave us a backchannel encapsulation. Process the request.
5853 * (We are not the origin of the backchannel here, the communicator simply
5854 * received a backchannel message and we are expected to forward it.)
5855 *
5856 * @param cls a `struct CommunicatorMessageContext` (must call
5857 * #finish_cmc_handling() when done)
5858 * @param be the message that was received
5859 */
5860static void
5861handle_backchannel_encapsulation (
5862 void *cls,
5863 const struct TransportBackchannelEncapsulationMessage *be)
5864{
5865 struct CommunicatorMessageContext *cmc = cls;
5866 struct BackchannelKeyState key;
5867 struct GNUNET_HashCode hmac;
5868 const char *hdr;
5869 size_t hdr_len;
5870
5871 if (0 != GNUNET_memcmp (&be->target, &GST_my_identity))
5872 {
5873 /* not for me, try to route to target */
5874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5875 "Forwarding backtalk to %s\n",
5876 GNUNET_i2s (&be->target));
5877 route_message (&be->target,
5878 GNUNET_copy_message (&be->header),
5879 RMO_DV_ALLOWED);
5880 finish_cmc_handling (cmc);
5881 return;
5882 }
5883 /* FIXME: this should be done when decrypting _any_ DV
5884 message, not only for backchannels! */
5885 dh_key_derive_eph_pub (&be->ephemeral_key, &be->iv, &key);
5886 hdr = (const char *) &be[1];
5887 hdr_len = ntohs (be->header.size) - sizeof (*be);
5888 bc_hmac (&key, &hmac, hdr, hdr_len);
5889 if (0 != GNUNET_memcmp (&hmac, &be->hmac))
5890 {
5891 /* HMAC missmatch, disard! */
5892 GNUNET_break_op (0);
5893 finish_cmc_handling (cmc);
5894 return;
5895 }
5896 /* begin actual decryption */
5897 {
5898 struct Backtalker *b;
5899 struct GNUNET_TIME_Absolute monotime;
5900 struct TransportBackchannelRequestPayloadP ppay;
5901 char body[hdr_len - sizeof (ppay)];
5902
5903 GNUNET_assert (hdr_len >=
5904 sizeof (ppay) + sizeof (struct GNUNET_MessageHeader));
5905 bc_decrypt (&key, &ppay, hdr, sizeof (ppay));
5906 bc_decrypt (&key, &body, &hdr[sizeof (ppay)], hdr_len - sizeof (ppay));
5907 bc_key_clean (&key);
5908 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
5909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5910 "Decrypted backtalk from %s\n",
5911 GNUNET_i2s (&ppay.sender));
5912 b = GNUNET_CONTAINER_multipeermap_get (backtalkers, &ppay.sender);
5913 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
5914 {
5915 GNUNET_STATISTICS_update (
5916 GST_stats,
5917 "# Backchannel messages dropped: monotonic time not increasing",
5918 1,
5919 GNUNET_NO);
5920 finish_cmc_handling (cmc);
5921 return;
5922 }
5923 if ((NULL == b) ||
5924 (0 != GNUNET_memcmp (&b->last_ephemeral, &be->ephemeral_key)))
5925 {
5926 /* Check signature */
5927 struct EphemeralConfirmationPS ec;
5928
5929 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
5930 ec.purpose.size = htonl (sizeof (ec));
5931 ec.target = GST_my_identity;
5932 ec.ephemeral_key = be->ephemeral_key;
5933 if (
5934 GNUNET_OK !=
5935 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL,
5936 &ec.purpose,
5937 &ppay.sender_sig,
5938 &ppay.sender.public_key))
5939 {
5940 /* Signature invalid, disard! */
5941 GNUNET_break_op (0);
5942 finish_cmc_handling (cmc);
5943 return;
5944 }
5945 }
5946 if (NULL != b)
5947 {
5948 /* update key cache and mono time */
5949 b->last_ephemeral = be->ephemeral_key;
5950 b->monotonic_time = monotime;
5951 update_backtalker_monotime (b);
5952 forward_backchannel_payload (b, body, sizeof (body));
5953 b->timeout =
5954 GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT);
5955 finish_cmc_handling (cmc);
5956 return;
5957 }
5958 /* setup data structure to cache signature AND check
5959 monotonic time with PEERSTORE before forwarding backchannel payload */
5960 b = GNUNET_malloc (sizeof (struct Backtalker) + sizeof (body));
5961 b->pid = ppay.sender;
5962 b->body_size = sizeof (body);
5963 memcpy (&b[1], body, sizeof (body));
5964 GNUNET_assert (GNUNET_YES ==
5965 GNUNET_CONTAINER_multipeermap_put (
5966 backtalkers,
5967 &b->pid,
5968 b,
5969 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
5970 b->monotonic_time = monotime; /* NOTE: to be checked still! */
5971 b->cmc = cmc;
5972 b->timeout =
5973 GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT);
5974 b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
5975 b->get =
5976 GNUNET_PEERSTORE_iterate (peerstore,
5977 "transport",
5978 &b->pid,
5979 GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME,
5980 &backtalker_monotime_cb,
5981 b);
5982 }
5983}
5984
5985
5986/**
5987 * Task called when we should check if any of the DV paths 5434 * Task called when we should check if any of the DV paths
5988 * we have learned to a target are due for garbage collection. 5435 * we have learned to a target are due for garbage collection.
5989 * 5436 *
@@ -6043,6 +5490,8 @@ activate_core_visible_dv_path (struct DistanceVectorHop *hop)
6043 "Creating new virtual link to %s using DV!\n", 5490 "Creating new virtual link to %s using DV!\n",
6044 GNUNET_i2s (&dv->target)); 5491 GNUNET_i2s (&dv->target));
6045 vl = GNUNET_new (struct VirtualLink); 5492 vl = GNUNET_new (struct VirtualLink);
5493 vl->message_uuid_ctr =
5494 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
6046 vl->target = dv->target; 5495 vl->target = dv->target;
6047 vl->dv = dv; 5496 vl->dv = dv;
6048 vl->core_recv_window = RECV_WINDOW_SIZE; 5497 vl->core_recv_window = RECV_WINDOW_SIZE;
@@ -6300,7 +5749,9 @@ forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
6300 struct GNUNET_TIME_Absolute in_time) 5749 struct GNUNET_TIME_Absolute in_time)
6301{ 5750{
6302 struct DVPathEntryP *dhops; 5751 struct DVPathEntryP *dhops;
6303 struct TransportDVLearnMessage *fwd; 5752 char buf[sizeof (struct TransportDVLearnMessage) +
5753 (nhops + 1) * sizeof (struct DVPathEntryP)] GNUNET_ALIGN;
5754 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
6304 struct GNUNET_TIME_Relative nnd; 5755 struct GNUNET_TIME_Relative nnd;
6305 5756
6306 /* compute message for forwarding */ 5757 /* compute message for forwarding */
@@ -6309,8 +5760,6 @@ forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
6309 GNUNET_i2s (&msg->initiator), 5760 GNUNET_i2s (&msg->initiator),
6310 GNUNET_i2s2 (next_hop)); 5761 GNUNET_i2s2 (next_hop));
6311 GNUNET_assert (nhops < MAX_DV_HOPS_ALLOWED); 5762 GNUNET_assert (nhops < MAX_DV_HOPS_ALLOWED);
6312 fwd = GNUNET_malloc (sizeof (struct TransportDVLearnMessage) +
6313 (nhops + 1) * sizeof (struct DVPathEntryP));
6314 fwd->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN); 5763 fwd->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
6315 fwd->header.size = htons (sizeof (struct TransportDVLearnMessage) + 5764 fwd->header.size = htons (sizeof (struct TransportDVLearnMessage) +
6316 (nhops + 1) * sizeof (struct DVPathEntryP)); 5765 (nhops + 1) * sizeof (struct DVPathEntryP));
@@ -6914,10 +6363,6 @@ check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
6914 uint16_t num_hops = ntohs (dvb->num_hops); 6363 uint16_t num_hops = ntohs (dvb->num_hops);
6915 const struct GNUNET_PeerIdentity *hops = 6364 const struct GNUNET_PeerIdentity *hops =
6916 (const struct GNUNET_PeerIdentity *) &dvb[1]; 6365 (const struct GNUNET_PeerIdentity *) &dvb[1];
6917 const struct GNUNET_MessageHeader *inbox =
6918 (const struct GNUNET_MessageHeader *) &hops[num_hops];
6919 uint16_t isize;
6920 uint16_t itype;
6921 6366
6922 (void) cls; 6367 (void) cls;
6923 if (size < sizeof (*dvb) + num_hops * sizeof (struct GNUNET_PeerIdentity) + 6368 if (size < sizeof (*dvb) + num_hops * sizeof (struct GNUNET_PeerIdentity) +
@@ -6926,25 +6371,13 @@ check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
6926 GNUNET_break_op (0); 6371 GNUNET_break_op (0);
6927 return GNUNET_SYSERR; 6372 return GNUNET_SYSERR;
6928 } 6373 }
6929 isize = ntohs (inbox->size); 6374 /* This peer must not be on the path */
6930 if (size != 6375 for (unsigned int i = 0; i < num_hops; i++)
6931 sizeof (*dvb) + num_hops * sizeof (struct GNUNET_PeerIdentity) + isize) 6376 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
6932 { 6377 {
6933 GNUNET_break_op (0); 6378 GNUNET_break_op (0);
6934 return GNUNET_SYSERR; 6379 return GNUNET_SYSERR;
6935 } 6380 }
6936 itype = ntohs (inbox->type);
6937 if ((GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX == itype) ||
6938 (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN == itype))
6939 {
6940 GNUNET_break_op (0);
6941 return GNUNET_SYSERR;
6942 }
6943 if (0 == GNUNET_memcmp (&dvb->origin, &GST_my_identity))
6944 {
6945 GNUNET_break_op (0);
6946 return GNUNET_SYSERR;
6947 }
6948 return GNUNET_YES; 6381 return GNUNET_YES;
6949} 6382}
6950 6383
@@ -6963,31 +6396,215 @@ check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
6963 */ 6396 */
6964static void 6397static void
6965forward_dv_box (struct Neighbour *next_hop, 6398forward_dv_box (struct Neighbour *next_hop,
6399 const struct TransportDVBoxMessage *hdr,
6966 uint16_t total_hops, 6400 uint16_t total_hops,
6967 uint16_t num_hops, 6401 uint16_t num_hops,
6968 const struct GNUNET_PeerIdentity *origin,
6969 const struct GNUNET_PeerIdentity *hops, 6402 const struct GNUNET_PeerIdentity *hops,
6970 const void *payload, 6403 const void *enc_payload,
6971 uint16_t payload_size) 6404 uint16_t enc_payload_size)
6972{ 6405{
6973 struct TransportDVBoxMessage *dvb; 6406 char buf[sizeof (struct TransportDVBoxMessage) +
6407 num_hops * sizeof (struct GNUNET_PeerIdentity) + enc_payload_size];
6408 struct GNUNET_PeerIdentity *dhops =
6409 (struct GNUNET_PeerIdentity *) &buf[sizeof (struct TransportDVBoxMessage)];
6974 6410
6975 dvb = create_dv_box (total_hops, 6411 memcpy (buf, hdr, sizeof (*hdr));
6976 origin, 6412 memcpy (dhops, hops, num_hops * sizeof (struct GNUNET_PeerIdentity));
6977 &hops[num_hops - 1] /* == target */, 6413 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
6978 num_hops - 1 /* do not count target twice */, 6414 route_message (&next_hop->pid,
6979 hops, 6415 (const struct GNUNET_MessageHeader *) buf,
6980 payload, 6416 RMO_NONE);
6981 payload_size); 6417}
6982 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 6418
6983 "Routing DV Box of %u bytes from %s at %u/%u hops via %s\n", 6419
6984 payload_size, 6420/**
6985 GNUNET_i2s (origin), 6421 * Free data structures associated with @a b.
6986 (unsigned int) num_hops, 6422 *
6987 (unsigned int) total_hops, 6423 * @param b data structure to release
6988 GNUNET_i2s2 (&next_hop->pid)); 6424 */
6989 route_message (&next_hop->pid, &dvb->header, RMO_NONE); 6425static void
6990 GNUNET_free (dvb); 6426free_backtalker (struct Backtalker *b)
6427{
6428 if (NULL != b->get)
6429 {
6430 GNUNET_PEERSTORE_iterate_cancel (b->get);
6431 b->get = NULL;
6432 GNUNET_assert (NULL != b->cmc);
6433 finish_cmc_handling (b->cmc);
6434 b->cmc = NULL;
6435 }
6436 if (NULL != b->task)
6437 {
6438 GNUNET_SCHEDULER_cancel (b->task);
6439 b->task = NULL;
6440 }
6441 if (NULL != b->sc)
6442 {
6443 GNUNET_PEERSTORE_store_cancel (b->sc);
6444 b->sc = NULL;
6445 }
6446 GNUNET_assert (
6447 GNUNET_YES ==
6448 GNUNET_CONTAINER_multipeermap_remove (backtalkers, &b->pid, b));
6449 GNUNET_free (b);
6450}
6451
6452
6453/**
6454 * Callback to free backtalker records.
6455 *
6456 * @param cls NULL
6457 * @param pid unused
6458 * @param value a `struct Backtalker`
6459 * @return #GNUNET_OK (always)
6460 */
6461static int
6462free_backtalker_cb (void *cls,
6463 const struct GNUNET_PeerIdentity *pid,
6464 void *value)
6465{
6466 struct Backtalker *b = value;
6467
6468 (void) cls;
6469 (void) pid;
6470 free_backtalker (b);
6471 return GNUNET_OK;
6472}
6473
6474
6475/**
6476 * Function called when it is time to clean up a backtalker.
6477 *
6478 * @param cls a `struct Backtalker`
6479 */
6480static void
6481backtalker_timeout_cb (void *cls)
6482{
6483 struct Backtalker *b = cls;
6484
6485 b->task = NULL;
6486 if (0 != GNUNET_TIME_absolute_get_remaining (b->timeout).rel_value_us)
6487 {
6488 b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
6489 return;
6490 }
6491 GNUNET_assert (NULL == b->sc);
6492 free_backtalker (b);
6493}
6494
6495
6496/**
6497 * Function called with the monotonic time of a backtalker
6498 * by PEERSTORE. Updates the time and continues processing.
6499 *
6500 * @param cls a `struct Backtalker`
6501 * @param record the information found, NULL for the last call
6502 * @param emsg error message
6503 */
6504static void
6505backtalker_monotime_cb (void *cls,
6506 const struct GNUNET_PEERSTORE_Record *record,
6507 const char *emsg)
6508{
6509 struct Backtalker *b = cls;
6510 struct GNUNET_TIME_AbsoluteNBO *mtbe;
6511 struct GNUNET_TIME_Absolute mt;
6512
6513 (void) emsg;
6514 if (NULL == record)
6515 {
6516 /* we're done with #backtalker_monotime_cb() invocations,
6517 continue normal processing */
6518 b->get = NULL;
6519 GNUNET_assert (NULL != b->cmc);
6520 if (0 != b->body_size)
6521 demultiplex_with_cmc (b->cmc,
6522 (const struct GNUNET_MessageHeader *) &b[1]);
6523 else
6524 finish_cmc_handling (b->cmc);
6525 b->cmc = NULL;
6526 return;
6527 }
6528 if (sizeof (*mtbe) != record->value_size)
6529 {
6530 GNUNET_break (0);
6531 return;
6532 }
6533 mtbe = record->value;
6534 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
6535 if (mt.abs_value_us > b->monotonic_time.abs_value_us)
6536 {
6537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6538 "Backtalker message from %s dropped, monotime in the past\n",
6539 GNUNET_i2s (&b->pid));
6540 GNUNET_STATISTICS_update (
6541 GST_stats,
6542 "# Backchannel messages dropped: monotonic time not increasing",
6543 1,
6544 GNUNET_NO);
6545 b->monotonic_time = mt;
6546 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
6547 */
6548 b->body_size = 0;
6549 return;
6550 }
6551}
6552
6553
6554/**
6555 * Function called by PEERSTORE when the store operation of
6556 * a backtalker's monotonic time is complete.
6557 *
6558 * @param cls the `struct Backtalker`
6559 * @param success #GNUNET_OK on success
6560 */
6561static void
6562backtalker_monotime_store_cb (void *cls, int success)
6563{
6564 struct Backtalker *b = cls;
6565
6566 if (GNUNET_OK != success)
6567 {
6568 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
6569 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
6570 }
6571 b->sc = NULL;
6572 b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
6573}
6574
6575
6576/**
6577 * The backtalker @a b monotonic time changed. Update PEERSTORE.
6578 *
6579 * @param b a backtalker with updated monotonic time
6580 */
6581static void
6582update_backtalker_monotime (struct Backtalker *b)
6583{
6584 struct GNUNET_TIME_AbsoluteNBO mtbe;
6585
6586 if (NULL != b->sc)
6587 {
6588 GNUNET_PEERSTORE_store_cancel (b->sc);
6589 b->sc = NULL;
6590 }
6591 else
6592 {
6593 GNUNET_SCHEDULER_cancel (b->task);
6594 b->task = NULL;
6595 }
6596 mtbe = GNUNET_TIME_absolute_hton (b->monotonic_time);
6597 b->sc =
6598 GNUNET_PEERSTORE_store (peerstore,
6599 "transport",
6600 &b->pid,
6601 GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME,
6602 &mtbe,
6603 sizeof (mtbe),
6604 GNUNET_TIME_UNIT_FOREVER_ABS,
6605 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
6606 &backtalker_monotime_store_cb,
6607 b);
6991} 6608}
6992 6609
6993 6610
@@ -7006,8 +6623,13 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
7006 uint16_t num_hops = ntohs (dvb->num_hops); 6623 uint16_t num_hops = ntohs (dvb->num_hops);
7007 const struct GNUNET_PeerIdentity *hops = 6624 const struct GNUNET_PeerIdentity *hops =
7008 (const struct GNUNET_PeerIdentity *) &dvb[1]; 6625 (const struct GNUNET_PeerIdentity *) &dvb[1];
7009 const struct GNUNET_MessageHeader *inbox = 6626 const char *enc_payload = (const char *) &hops[num_hops];
7010 (const struct GNUNET_MessageHeader *) &hops[num_hops]; 6627 uint16_t enc_payload_size =
6628 size - (num_hops * sizeof (struct GNUNET_PeerIdentity));
6629 struct DVKeyState key;
6630 struct GNUNET_HashCode hmac;
6631 const char *hdr;
6632 size_t hdr_len;
7011 6633
7012 if (GNUNET_EXTRA_LOGGING > 0) 6634 if (GNUNET_EXTRA_LOGGING > 0)
7013 { 6635 {
@@ -7050,12 +6672,12 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
7050 i, 6672 i,
7051 num_hops); 6673 num_hops);
7052 forward_dv_box (n, 6674 forward_dv_box (n,
6675 dvb,
7053 ntohs (dvb->total_hops) + 1, 6676 ntohs (dvb->total_hops) + 1,
7054 num_hops - i - 1, /* number of hops left */ 6677 num_hops - i - 1, /* number of hops left */
7055 &dvb->origin,
7056 &hops[i + 1], /* remaining hops */ 6678 &hops[i + 1], /* remaining hops */
7057 (const void *) &dvb[1], 6679 enc_payload,
7058 size); 6680 enc_payload_size);
7059 GNUNET_STATISTICS_update (GST_stats, 6681 GNUNET_STATISTICS_update (GST_stats,
7060 "# DV hops skipped routing boxes", 6682 "# DV hops skipped routing boxes",
7061 i, 6683 i,
@@ -7076,18 +6698,140 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
7076 return; 6698 return;
7077 } 6699 }
7078 /* We are the target. Unbox and handle message. */ 6700 /* We are the target. Unbox and handle message. */
7079 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7080 "DVBox received for me from %s\n",
7081 GNUNET_i2s (&dvb->origin));
7082 GNUNET_STATISTICS_update (GST_stats, 6701 GNUNET_STATISTICS_update (GST_stats,
7083 "# DV boxes opened (ultimate target)", 6702 "# DV boxes opened (ultimate target)",
7084 1, 6703 1,
7085 GNUNET_NO); 6704 GNUNET_NO);
7086 cmc->im.sender = dvb->origin;
7087 cmc->total_hops = ntohs (dvb->total_hops); 6705 cmc->total_hops = ntohs (dvb->total_hops);
7088 // FIXME: should *decrypt* inbox here; needs BackchannelEncapsulation! 6706
7089 // FIXME: need to prevent box-in-a-box, so check inbox type! 6707 dh_key_derive_eph_pub (&dvb->ephemeral_key, &dvb->iv, &key);
7090 demultiplex_with_cmc (cmc, inbox); 6708 hdr = (const char *) &dvb[1];
6709 hdr_len = ntohs (dvb->header.size) - sizeof (*dvb);
6710 dv_hmac (&key, &hmac, hdr, hdr_len);
6711 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
6712 {
6713 /* HMAC missmatch, disard! */
6714 GNUNET_break_op (0);
6715 finish_cmc_handling (cmc);
6716 return;
6717 }
6718 /* begin actual decryption */
6719 {
6720 struct Backtalker *b;
6721 struct GNUNET_TIME_Absolute monotime;
6722 struct TransportDVBoxPayloadP ppay;
6723 char body[hdr_len - sizeof (ppay)] GNUNET_ALIGN;
6724 const struct GNUNET_MessageHeader *mh =
6725 (const struct GNUNET_MessageHeader *) body;
6726
6727 GNUNET_assert (hdr_len >=
6728 sizeof (ppay) + sizeof (struct GNUNET_MessageHeader));
6729 dv_decrypt (&key, &ppay, hdr, sizeof (ppay));
6730 dv_decrypt (&key, &body, &hdr[sizeof (ppay)], hdr_len - sizeof (ppay));
6731 dv_key_clean (&key);
6732 if (ntohs (mh->size) != sizeof (body))
6733 {
6734 GNUNET_break_op (0);
6735 finish_cmc_handling (cmc);
6736 return;
6737 }
6738 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
6739 switch (ntohs (mh->type))
6740 {
6741 case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX:
6742 GNUNET_break_op (0);
6743 finish_cmc_handling (cmc);
6744 return;
6745 case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN:
6746 GNUNET_break_op (0);
6747 finish_cmc_handling (cmc);
6748 return;
6749 default:
6750 /* permitted, continue */
6751 break;
6752 }
6753 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
6754 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6755 "Decrypted backtalk from %s\n",
6756 GNUNET_i2s (&ppay.sender));
6757 b = GNUNET_CONTAINER_multipeermap_get (backtalkers, &ppay.sender);
6758 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
6759 {
6760 GNUNET_STATISTICS_update (
6761 GST_stats,
6762 "# Backchannel messages dropped: monotonic time not increasing",
6763 1,
6764 GNUNET_NO);
6765 finish_cmc_handling (cmc);
6766 return;
6767 }
6768 if ((NULL == b) ||
6769 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
6770 {
6771 /* Check signature */
6772 struct EphemeralConfirmationPS ec;
6773
6774 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
6775 ec.purpose.size = htonl (sizeof (ec));
6776 ec.target = GST_my_identity;
6777 ec.ephemeral_key = dvb->ephemeral_key;
6778 if (
6779 GNUNET_OK !=
6780 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL,
6781 &ec.purpose,
6782 &ppay.sender_sig,
6783 &ppay.sender.public_key))
6784 {
6785 /* Signature invalid, disard! */
6786 GNUNET_break_op (0);
6787 finish_cmc_handling (cmc);
6788 return;
6789 }
6790 }
6791 /* Update sender, we now know the real origin! */
6792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6793 "DVBox received for me from %s via %s\n",
6794 GNUNET_i2s2 (&ppay.sender),
6795 GNUNET_i2s (&cmc->im.sender));
6796 cmc->im.sender = ppay.sender;
6797
6798 if (NULL != b)
6799 {
6800 /* update key cache and mono time */
6801 b->last_ephemeral = dvb->ephemeral_key;
6802 b->monotonic_time = monotime;
6803 update_backtalker_monotime (b);
6804 b->timeout =
6805 GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT);
6806
6807 demultiplex_with_cmc (cmc, mh);
6808 return;
6809 }
6810 /* setup data structure to cache signature AND check
6811 monotonic time with PEERSTORE before forwarding backchannel payload */
6812 b = GNUNET_malloc (sizeof (struct Backtalker) + sizeof (body));
6813 b->pid = ppay.sender;
6814 b->body_size = sizeof (body);
6815 memcpy (&b[1], body, sizeof (body));
6816 GNUNET_assert (GNUNET_YES ==
6817 GNUNET_CONTAINER_multipeermap_put (
6818 backtalkers,
6819 &b->pid,
6820 b,
6821 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
6822 b->monotonic_time = monotime; /* NOTE: to be checked still! */
6823 b->cmc = cmc;
6824 b->timeout =
6825 GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT);
6826 b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
6827 b->get =
6828 GNUNET_PEERSTORE_iterate (peerstore,
6829 "transport",
6830 &b->pid,
6831 GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME,
6832 &backtalker_monotime_cb,
6833 b);
6834 } /* end actual decryption */
7091} 6835}
7092 6836
7093 6837
@@ -7579,7 +7323,7 @@ set_pending_message_uuid (struct PendingMessage *pm)
7579{ 7323{
7580 if (pm->msg_uuid_set) 7324 if (pm->msg_uuid_set)
7581 return; 7325 return;
7582 pm->msg_uuid.uuid = pm->target->message_uuid_ctr++; 7326 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
7583 pm->msg_uuid_set = GNUNET_YES; 7327 pm->msg_uuid_set = GNUNET_YES;
7584} 7328}
7585 7329
@@ -7655,7 +7399,7 @@ fragment_message (struct Queue *queue,
7655 "Fragmenting message %llu <%llu> to %s for MTU %u\n", 7399 "Fragmenting message %llu <%llu> to %s for MTU %u\n",
7656 (unsigned long long) pm->msg_uuid.uuid, 7400 (unsigned long long) pm->msg_uuid.uuid,
7657 pm->logging_uuid, 7401 pm->logging_uuid,
7658 GNUNET_i2s (&pm->target->pid), 7402 GNUNET_i2s (&pm->vl->target),
7659 (unsigned int) mtu); 7403 (unsigned int) mtu);
7660 pa = prepare_pending_acknowledgement (queue, dvh, pm); 7404 pa = prepare_pending_acknowledgement (queue, dvh, pm);
7661 7405
@@ -7702,7 +7446,7 @@ fragment_message (struct Queue *queue,
7702 GNUNET_malloc (sizeof (struct PendingMessage) + 7446 GNUNET_malloc (sizeof (struct PendingMessage) +
7703 sizeof (struct TransportFragmentBoxMessage) + fragsize); 7447 sizeof (struct TransportFragmentBoxMessage) + fragsize);
7704 frag->logging_uuid = logging_uuid_gen++; 7448 frag->logging_uuid = logging_uuid_gen++;
7705 frag->target = pm->target; 7449 frag->vl = pm->vl;
7706 frag->frag_parent = ff; 7450 frag->frag_parent = ff;
7707 frag->timeout = pm->timeout; 7451 frag->timeout = pm->timeout;
7708 frag->bytes_msg = sizeof (struct TransportFragmentBoxMessage) + fragsize; 7452 frag->bytes_msg = sizeof (struct TransportFragmentBoxMessage) + fragsize;
@@ -7773,14 +7517,14 @@ reliability_box_message (struct Queue *queue,
7773 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 7517 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7774 "Preparing reliability box for message <%llu> to %s on queue %s\n", 7518 "Preparing reliability box for message <%llu> to %s on queue %s\n",
7775 pm->logging_uuid, 7519 pm->logging_uuid,
7776 GNUNET_i2s (&pm->target->pid), 7520 GNUNET_i2s (&pm->vl->target),
7777 queue->address); 7521 queue->address);
7778 pa = prepare_pending_acknowledgement (queue, dvh, pm); 7522 pa = prepare_pending_acknowledgement (queue, dvh, pm);
7779 7523
7780 bpm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (rbox) + 7524 bpm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (rbox) +
7781 pm->bytes_msg); 7525 pm->bytes_msg);
7782 bpm->logging_uuid = logging_uuid_gen++; 7526 bpm->logging_uuid = logging_uuid_gen++;
7783 bpm->target = pm->target; 7527 bpm->vl = pm->vl;
7784 bpm->frag_parent = pm; 7528 bpm->frag_parent = pm;
7785 GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm); 7529 GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
7786 bpm->timeout = pm->timeout; 7530 bpm->timeout = pm->timeout;
@@ -7812,7 +7556,7 @@ static void
7812update_pm_next_attempt (struct PendingMessage *pm, 7556update_pm_next_attempt (struct PendingMessage *pm,
7813 struct GNUNET_TIME_Absolute next_attempt) 7557 struct GNUNET_TIME_Absolute next_attempt)
7814{ 7558{
7815 struct Neighbour *neighbour = pm->target; 7559 struct VirtualLink *vl = pm->vl;
7816 7560
7817 pm->next_attempt = next_attempt; 7561 pm->next_attempt = next_attempt;
7818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 7562 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -7825,17 +7569,17 @@ update_pm_next_attempt (struct PendingMessage *pm,
7825 struct PendingMessage *pos; 7569 struct PendingMessage *pos;
7826 7570
7827 /* re-insert sort in neighbour list */ 7571 /* re-insert sort in neighbour list */
7828 GNUNET_CONTAINER_MDLL_remove (neighbour, 7572 GNUNET_CONTAINER_MDLL_remove (vl,
7829 neighbour->pending_msg_head, 7573 vl->pending_msg_head,
7830 neighbour->pending_msg_tail, 7574 vl->pending_msg_tail,
7831 pm); 7575 pm);
7832 pos = neighbour->pending_msg_tail; 7576 pos = vl->pending_msg_tail;
7833 while ((NULL != pos) && 7577 while ((NULL != pos) &&
7834 (next_attempt.abs_value_us > pos->next_attempt.abs_value_us)) 7578 (next_attempt.abs_value_us > pos->next_attempt.abs_value_us))
7835 pos = pos->prev_neighbour; 7579 pos = pos->prev_vl;
7836 GNUNET_CONTAINER_MDLL_insert_after (neighbour, 7580 GNUNET_CONTAINER_MDLL_insert_after (vl,
7837 neighbour->pending_msg_head, 7581 vl->pending_msg_head,
7838 neighbour->pending_msg_tail, 7582 vl->pending_msg_tail,
7839 pos, 7583 pos,
7840 pm); 7584 pm);
7841 } 7585 }
@@ -7871,12 +7615,14 @@ static void
7871transmit_on_queue (void *cls) 7615transmit_on_queue (void *cls)
7872{ 7616{
7873 struct Queue *queue = cls; 7617 struct Queue *queue = cls;
7618
7619 queue->transmit_task = NULL;
7620#if FIXME - NEXT
7874 struct Neighbour *n = queue->neighbour; 7621 struct Neighbour *n = queue->neighbour;
7875 struct PendingMessage *pm; 7622 struct PendingMessage *pm;
7876 struct PendingMessage *s; 7623 struct PendingMessage *s;
7877 uint32_t overhead; 7624 uint32_t overhead;
7878 7625
7879 queue->transmit_task = NULL;
7880 if (NULL == (pm = n->pending_msg_head)) 7626 if (NULL == (pm = n->pending_msg_head))
7881 { 7627 {
7882 /* no message pending, nothing to do here! */ 7628 /* no message pending, nothing to do here! */
@@ -8010,6 +7756,7 @@ transmit_on_queue (void *cls)
8010 7756
8011 /* finally, re-schedule queue transmission task itself */ 7757 /* finally, re-schedule queue transmission task itself */
8012 schedule_transmit_on_queue (queue, GNUNET_NO); 7758 schedule_transmit_on_queue (queue, GNUNET_NO);
7759#endif
8013} 7760}
8014 7761
8015 7762
@@ -8138,19 +7885,21 @@ handle_send_message_ack (void *cls,
8138 7885
8139 if (NULL != (pm = qe->pm)) 7886 if (NULL != (pm = qe->pm))
8140 { 7887 {
8141 struct Neighbour *n; 7888 struct VirtualLink *vl;
8142 7889
8143 GNUNET_assert (qe == pm->qe); 7890 GNUNET_assert (qe == pm->qe);
8144 pm->qe = NULL; 7891 pm->qe = NULL;
8145 /* If waiting for this communicator may have blocked transmission 7892 /* If waiting for this communicator may have blocked transmission
8146 of pm on other queues for this neighbour, force schedule 7893 of pm on other queues for this neighbour, force schedule
8147 transmit on queue for queues of the neighbour */ 7894 transmit on queue for queues of the neighbour */
8148 n = pm->target; 7895 vl = pm->vl;
8149 if (n->pending_msg_head == pm) 7896 if (vl->pending_msg_head == pm)
8150 { 7897 {
7898#if FIXME - NEXT
8151 for (struct Queue *queue = n->queue_head; NULL != queue; 7899 for (struct Queue *queue = n->queue_head; NULL != queue;
8152 queue = queue->next_neighbour) 7900 queue = queue->next_neighbour)
8153 schedule_transmit_on_queue (queue, GNUNET_NO); 7901 schedule_transmit_on_queue (queue, GNUNET_NO);
7902#endif
8154 } 7903 }
8155 if (GNUNET_OK != ntohl (sma->status)) 7904 if (GNUNET_OK != ntohl (sma->status))
8156 { 7905 {
@@ -8651,8 +8400,6 @@ handle_add_queue_message (void *cls,
8651 if (NULL == neighbour) 8400 if (NULL == neighbour)
8652 { 8401 {
8653 neighbour = GNUNET_new (struct Neighbour); 8402 neighbour = GNUNET_new (struct Neighbour);
8654 neighbour->message_uuid_ctr =
8655 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
8656 neighbour->pid = aqm->receiver; 8403 neighbour->pid = aqm->receiver;
8657 GNUNET_assert (GNUNET_OK == 8404 GNUNET_assert (GNUNET_OK ==
8658 GNUNET_CONTAINER_multipeermap_put ( 8405 GNUNET_CONTAINER_multipeermap_put (
@@ -9081,28 +8828,6 @@ free_dv_routes_cb (void *cls,
9081 8828
9082 8829
9083/** 8830/**
9084 * Free ephemeral entry.
9085 *
9086 * @param cls NULL
9087 * @param pid unused
9088 * @param value a `struct EphemeralCacheEntry`
9089 * @return #GNUNET_OK (always)
9090 */
9091static int
9092free_ephemeral_cb (void *cls,
9093 const struct GNUNET_PeerIdentity *pid,
9094 void *value)
9095{
9096 struct EphemeralCacheEntry *ece = value;
9097
9098 (void) cls;
9099 (void) pid;
9100 free_ephemeral (ece);
9101 return GNUNET_OK;
9102}
9103
9104
9105/**
9106 * Free validation state. 8831 * Free validation state.
9107 * 8832 *
9108 * @param cls NULL 8833 * @param cls NULL
@@ -9180,11 +8905,6 @@ do_shutdown (void *cls)
9180 struct LearnLaunchEntry *lle; 8905 struct LearnLaunchEntry *lle;
9181 (void) cls; 8906 (void) cls;
9182 8907
9183 if (NULL != ephemeral_task)
9184 {
9185 GNUNET_SCHEDULER_cancel (ephemeral_task);
9186 ephemeral_task = NULL;
9187 }
9188 GNUNET_CONTAINER_multipeermap_iterate (neighbours, &free_neighbour_cb, NULL); 8908 GNUNET_CONTAINER_multipeermap_iterate (neighbours, &free_neighbour_cb, NULL);
9189 if (NULL != peerstore) 8909 if (NULL != peerstore)
9190 { 8910 {
@@ -9239,13 +8959,6 @@ do_shutdown (void *cls)
9239 GNUNET_CONTAINER_multipeermap_iterate (dv_routes, &free_dv_routes_cb, NULL); 8959 GNUNET_CONTAINER_multipeermap_iterate (dv_routes, &free_dv_routes_cb, NULL);
9240 GNUNET_CONTAINER_multipeermap_destroy (dv_routes); 8960 GNUNET_CONTAINER_multipeermap_destroy (dv_routes);
9241 dv_routes = NULL; 8961 dv_routes = NULL;
9242 GNUNET_CONTAINER_multipeermap_iterate (ephemeral_map,
9243 &free_ephemeral_cb,
9244 NULL);
9245 GNUNET_CONTAINER_multipeermap_destroy (ephemeral_map);
9246 ephemeral_map = NULL;
9247 GNUNET_CONTAINER_heap_destroy (ephemeral_heap);
9248 ephemeral_heap = NULL;
9249} 8962}
9250 8963
9251 8964
@@ -9272,9 +8985,6 @@ run (void *cls,
9272 neighbours = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); 8985 neighbours = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
9273 links = GNUNET_CONTAINER_multipeermap_create (512, GNUNET_YES); 8986 links = GNUNET_CONTAINER_multipeermap_create (512, GNUNET_YES);
9274 dv_routes = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); 8987 dv_routes = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
9275 ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES);
9276 ephemeral_heap =
9277 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
9278 dvlearn_map = GNUNET_CONTAINER_multishortmap_create (2 * MAX_DV_LEARN_PENDING, 8988 dvlearn_map = GNUNET_CONTAINER_multishortmap_create (2 * MAX_DV_LEARN_PENDING,
9279 GNUNET_YES); 8989 GNUNET_YES);
9280 validation_map = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); 8990 validation_map = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);