summaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-tng.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/gnunet-service-tng.c')
-rw-r--r--src/transport/gnunet-service-tng.c495
1 files changed, 360 insertions, 135 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index 2f7129478..d3c3defec 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -24,15 +24,7 @@
24 * 24 *
25 * TODO: 25 * TODO:
26 * Implement next: 26 * Implement next:
27 * - FIXME: handle_client_send(): pick DVH path, and box
28 * message accordingly (if applicable, see FIXMEs)
29 * - proper use/initialization of timestamps in messages exchanged
30 * during DV learning
31 * - persistence of monotonic time from DVInit to prevent
32 * replay attacks using DVInit messages
33 * - dv hop-by-hop signature verification (at least at initiator) 27 * - dv hop-by-hop signature verification (at least at initiator)
34 * - persistence of monotonic time obtained from other peers
35 * in PEERSTORE (by message type) -- done for backchannel, needed elsewhere?
36 * - change transport-core API to provide proper flow control in both 28 * - change transport-core API to provide proper flow control in both
37 * directions, allow multiple messages per peer simultaneously (tag 29 * directions, allow multiple messages per peer simultaneously (tag
38 * confirmations with unique message ID), and replace quota-out with 30 * confirmations with unique message ID), and replace quota-out with
@@ -720,6 +712,20 @@ struct TransportDVLearnMessage
720 struct GNUNET_TIME_RelativeNBO non_network_delay; 712 struct GNUNET_TIME_RelativeNBO non_network_delay;
721 713
722 /** 714 /**
715 * Time at the initiator when generating the signature.
716 *
717 * Note that the receiver MUST IGNORE the absolute time, and only interpret
718 * the value as a mononic time and reject "older" values than the last one
719 * observed. This is necessary as we do not want to require synchronized
720 * clocks and may not have a bidirectional communication channel.
721 *
722 * Even with this, there is no real guarantee against replay achieved here,
723 * unless the latest timestamp is persisted. Persistence should be
724 * provided via PEERSTORE if possible.
725 */
726 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
727
728 /**
723 * Signature of this hop over the path, of purpose 729 * Signature of this hop over the path, of purpose
724 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR 730 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
725 */ 731 */
@@ -923,6 +929,41 @@ enum ClientType
923 929
924 930
925/** 931/**
932 * Which transmission options are allowable for transmission?
933 * Interpreted bit-wise!
934 */
935enum RouteMessageOptions
936{
937 /**
938 * Only confirmed, non-DV direct neighbours.
939 */
940 RMO_NONE = 0,
941
942 /**
943 * We are allowed to use DV routing for this @a hdr
944 */
945 RMO_DV_ALLOWED = 1,
946
947 /**
948 * We are allowed to use unconfirmed queues or DV routes for this message
949 */
950 RMO_UNCONFIRMED_ALLOWED = 2,
951
952 /**
953 * Reliable and unreliable, DV and non-DV are all acceptable.
954 */
955 RMO_ANYTHING_GOES = (RMO_DV_ALLOWED | RMO_UNCONFIRMED_ALLOWED),
956
957 /**
958 * If we have multiple choices, it is OK to send this message
959 * over multiple channels at the same time to improve loss tolerance.
960 * (We do at most 2 transmissions.)
961 */
962 RMO_REDUNDANT = 4
963};
964
965
966/**
926 * When did we launch this DV learning activity? 967 * When did we launch this DV learning activity?
927 */ 968 */
928struct LearnLaunchEntry 969struct LearnLaunchEntry
@@ -1629,6 +1670,18 @@ struct Neighbour
1629 struct GNUNET_SCHEDULER_Task *timeout_task; 1670 struct GNUNET_SCHEDULER_Task *timeout_task;
1630 1671
1631 /** 1672 /**
1673 * Handle for an operation to fetch @e last_dv_learn_monotime information from
1674 * the PEERSTORE, or NULL.
1675 */
1676 struct GNUNET_PEERSTORE_IterateContext *get;
1677
1678 /**
1679 * Handle to a PEERSTORE store operation to store this @e pid's @e
1680 * @e last_dv_learn_monotime. NULL if no PEERSTORE operation is pending.
1681 */
1682 struct GNUNET_PEERSTORE_StoreContext *sc;
1683
1684 /**
1632 * Quota at which CORE is allowed to transmit to this peer 1685 * Quota at which CORE is allowed to transmit to this peer
1633 * (note that the value CORE should actually be told is this 1686 * (note that the value CORE should actually be told is this
1634 * value plus the respective value in `struct DistanceVector`). 1687 * value plus the respective value in `struct DistanceVector`).
@@ -1643,6 +1696,12 @@ struct Neighbour
1643 struct GNUNET_BANDWIDTH_Value32NBO quota_out; 1696 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
1644 1697
1645 /** 1698 /**
1699 * Latest DVLearn monotonic time seen from this peer. Initialized only
1700 * if @e dl_monotime_available is #GNUNET_YES.
1701 */
1702 struct GNUNET_TIME_Absolute last_dv_learn_monotime;
1703
1704 /**
1646 * What is the earliest timeout of any message in @e pending_msg_tail? 1705 * What is the earliest timeout of any message in @e pending_msg_tail?
1647 */ 1706 */
1648 struct GNUNET_TIME_Absolute earliest_timeout; 1707 struct GNUNET_TIME_Absolute earliest_timeout;
@@ -1652,6 +1711,12 @@ struct Neighbour
1652 * CORE? 1711 * CORE?
1653 */ 1712 */
1654 int core_visible; 1713 int core_visible;
1714
1715 /**
1716 * Do we have the lastest value for @e last_dv_learn_monotime from
1717 * PEERSTORE yet, or are we still waiting for a reply of PEERSTORE?
1718 */
1719 int dv_monotime_available;
1655}; 1720};
1656 1721
1657 1722
@@ -2851,7 +2916,20 @@ free_neighbour (struct Neighbour *neighbour)
2851 free_dv_route (dv); 2916 free_dv_route (dv);
2852 } 2917 }
2853 if (NULL != neighbour->reassembly_timeout_task) 2918 if (NULL != neighbour->reassembly_timeout_task)
2919 {
2854 GNUNET_SCHEDULER_cancel (neighbour->reassembly_timeout_task); 2920 GNUNET_SCHEDULER_cancel (neighbour->reassembly_timeout_task);
2921 neighbour->reassembly_timeout_task = NULL;
2922 }
2923 if (NULL != neighbour->get)
2924 {
2925 GNUNET_PEERSTORE_iterate_cancel (neighbour->get);
2926 neighbour->get = NULL;
2927 }
2928 if (NULL != neighbour->sc)
2929 {
2930 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
2931 neighbour->sc = NULL;
2932 }
2855 GNUNET_free (neighbour); 2933 GNUNET_free (neighbour);
2856} 2934}
2857 2935
@@ -3453,6 +3531,130 @@ check_queue_timeouts (void *cls)
3453 3531
3454 3532
3455/** 3533/**
3534 * Create a DV Box message.
3535 *
3536 * @param total_hops how many hops did the message take so far
3537 * @param num_hops length of the @a hops array
3538 * @param origin origin of the message
3539 * @param hops next peer(s) to the destination, including destination
3540 * @param payload payload of the box
3541 * @param payload_size number of bytes in @a payload
3542 * @return boxed message (caller must #GNUNET_free() it).
3543 */
3544static struct TransportDVBoxMessage *
3545create_dv_box (uint16_t total_hops,
3546 const struct GNUNET_PeerIdentity *origin,
3547 const struct GNUNET_PeerIdentity *target,
3548 uint16_t num_hops,
3549 const struct GNUNET_PeerIdentity *hops,
3550 const void *payload,
3551 uint16_t payload_size)
3552{
3553 struct TransportDVBoxMessage *dvb;
3554 struct GNUNET_PeerIdentity *dhops;
3555
3556 GNUNET_assert (UINT16_MAX <
3557 sizeof (struct TransportDVBoxMessage) +
3558 sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) +
3559 payload_size);
3560 dvb = GNUNET_malloc (sizeof (struct TransportDVBoxMessage) +
3561 sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) +
3562 payload_size);
3563 dvb->header.size =
3564 htons (sizeof (struct TransportDVBoxMessage) +
3565 sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) + payload_size);
3566 dvb->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
3567 dvb->total_hops = htons (total_hops);
3568 dvb->num_hops = htons (num_hops + 1);
3569 dvb->origin = *origin;
3570 dhops = (struct GNUNET_PeerIdentity *) &dvb[1];
3571 memcpy (dhops, hops, num_hops * sizeof (struct GNUNET_PeerIdentity));
3572 dhops[num_hops] = *target;
3573 memcpy (&dhops[num_hops + 1], payload, payload_size);
3574 return dvb;
3575}
3576
3577
3578/**
3579 * Pick @a hops_array_length random DV paths satisfying @a options
3580 *
3581 * @param dv data structure to pick paths from
3582 * @param options constraints to satisfy
3583 * @param hops_array[out] set to the result
3584 * @param hops_array_length length of the @a hops_array
3585 * @return number of entries set in @a hops_array
3586 */
3587static unsigned int
3588pick_random_dv_hops (const struct DistanceVector *dv,
3589 enum RouteMessageOptions options,
3590 struct DistanceVectorHop **hops_array,
3591 unsigned int hops_array_length)
3592{
3593 uint64_t choices[hops_array_length];
3594 uint64_t num_dv;
3595 unsigned int dv_count;
3596
3597 /* Pick random vectors, but weighted by distance, giving more weight
3598 to shorter vectors */
3599 num_dv = 0;
3600 dv_count = 0;
3601 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3602 pos = pos->next_dv)
3603 {
3604 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3605 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
3606 .rel_value_us == 0))
3607 continue; /* pos unconfirmed and confirmed required */
3608 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
3609 dv_count++;
3610 }
3611 if (0 == dv_count)
3612 return 0;
3613 if (dv_count <= hops_array_length)
3614 {
3615 dv_count = 0;
3616 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3617 pos = pos->next_dv)
3618 hops_array[dv_count++] = pos;
3619 return dv_count;
3620 }
3621 for (unsigned int i = 0; i < hops_array_length; i++)
3622 {
3623 int ok = GNUNET_NO;
3624 while (GNUNET_NO == ok)
3625 {
3626 choices[i] =
3627 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, num_dv);
3628 ok = GNUNET_YES;
3629 for (unsigned int j = 0; j < i; j++)
3630 if (choices[i] == choices[j])
3631 {
3632 ok = GNUNET_NO;
3633 break;
3634 }
3635 }
3636 }
3637 dv_count = 0;
3638 num_dv = 0;
3639 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3640 pos = pos->next_dv)
3641 {
3642 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
3643
3644 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3645 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
3646 .rel_value_us == 0))
3647 continue; /* pos unconfirmed and confirmed required */
3648 for (unsigned int i = 0; i < hops_array_length; i++)
3649 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
3650 hops_array[dv_count++] = pos;
3651 num_dv += delta;
3652 }
3653 return dv_count;
3654}
3655
3656
3657/**
3456 * Client asked for transmission to a peer. Process the request. 3658 * Client asked for transmission to a peer. Process the request.
3457 * 3659 *
3458 * @param cls the client 3660 * @param cls the client
@@ -3471,6 +3673,7 @@ handle_client_send (void *cls, const struct OutboundMessage *obm)
3471 int was_empty; 3673 int was_empty;
3472 const void *payload; 3674 const void *payload;
3473 size_t payload_size; 3675 size_t payload_size;
3676 struct TransportDVBoxMessage *dvb;
3474 3677
3475 GNUNET_assert (CT_CORE == tc->type); 3678 GNUNET_assert (CT_CORE == tc->type);
3476 obmm = (const struct GNUNET_MessageHeader *) &obm[1]; 3679 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
@@ -3504,18 +3707,26 @@ handle_client_send (void *cls, const struct OutboundMessage *obm)
3504 } 3707 }
3505 if (NULL == target) 3708 if (NULL == target)
3506 { 3709 {
3507 // FIXME: overall, similar logic exists already for DV boxing, 3710 unsigned int res;
3508 // re-use! 3711 struct DistanceVectorHop *dvh;
3509 3712
3510 // FIXME: dvh = pick_dv_hop (dv); 3713 res = pick_random_dv_hops (dv, RMO_NONE, &dvh, 1);
3714 GNUNET_assert (1 == res);
3511 target = dvh->next_hop; 3715 target = dvh->next_hop;
3512 // FIXME: dv box message here! 3716 dvb = create_dv_box (0,
3513 // FIXME: set payload & payload_size to box (and free box below!) 3717 &GST_my_identity,
3718 &obm->peer,
3719 dvh->distance,
3720 dvh->path,
3721 &obm[1],
3722 bytes_msg);
3723 payload = dvb;
3724 payload_size = ntohs (dvb->header.size);
3514 } 3725 }
3515 else 3726 else
3516 { 3727 {
3517 dvh = NULL; 3728 dvh = NULL;
3518 // box = NULL; 3729 dvb = NULL;
3519 payload = &obm[1]; 3730 payload = &obm[1];
3520 payload_size = bytes_msg; 3731 payload_size = bytes_msg;
3521 } 3732 }
@@ -3527,8 +3738,9 @@ handle_client_send (void *cls, const struct OutboundMessage *obm)
3527 pm->bytes_msg = payload_size; 3738 pm->bytes_msg = payload_size;
3528 pm->timeout = 3739 pm->timeout =
3529 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_ntoh (obm->timeout)); 3740 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_ntoh (obm->timeout));
3530 memcpy (&pm[1], &obm[1], payload_size); 3741 memcpy (&pm[1], payload, payload_size);
3531 // FIXME: GNUNET_free_non_null (box); 3742 GNUNET_free_non_null (dvb);
3743 dvb = NULL;
3532 pm->dvh = dvh; 3744 pm->dvh = dvh;
3533 if (NULL != dvh) 3745 if (NULL != dvh)
3534 { 3746 {
@@ -3810,41 +4022,6 @@ queue_send_msg (struct Queue *queue,
3810 4022
3811 4023
3812/** 4024/**
3813 * Which transmission options are allowable for transmission?
3814 * Interpreted bit-wise!
3815 */
3816enum RouteMessageOptions
3817{
3818 /**
3819 * Only confirmed, non-DV direct neighbours.
3820 */
3821 RMO_NONE = 0,
3822
3823 /**
3824 * We are allowed to use DV routing for this @a hdr
3825 */
3826 RMO_DV_ALLOWED = 1,
3827
3828 /**
3829 * We are allowed to use unconfirmed queues or DV routes for this message
3830 */
3831 RMO_UNCONFIRMED_ALLOWED = 2,
3832
3833 /**
3834 * Reliable and unreliable, DV and non-DV are all acceptable.
3835 */
3836 RMO_ANYTHING_GOES = (RMO_DV_ALLOWED | RMO_UNCONFIRMED_ALLOWED),
3837
3838 /**
3839 * If we have multiple choices, it is OK to send this message
3840 * over multiple channels at the same time to improve loss tolerance.
3841 * (We do at most 2 transmissions.)
3842 */
3843 RMO_REDUNDANT = 4
3844};
3845
3846
3847/**
3848 * Pick a queue of @a n under constraints @a options and schedule 4025 * Pick a queue of @a n under constraints @a options and schedule
3849 * transmission of @a hdr. 4026 * transmission of @a hdr.
3850 * 4027 *
@@ -3927,22 +4104,17 @@ forward_via_dvh (const struct DistanceVectorHop *dvh,
3927 const struct GNUNET_MessageHeader *payload, 4104 const struct GNUNET_MessageHeader *payload,
3928 enum RouteMessageOptions options) 4105 enum RouteMessageOptions options)
3929{ 4106{
3930 uint16_t mlen = ntohs (payload->size); 4107 struct TransportDVBoxMessage *dvb;
3931 char boxram[sizeof (struct TransportDVBoxMessage) +
3932 (dvh->distance + 1) * sizeof (struct GNUNET_PeerIdentity) +
3933 mlen] GNUNET_ALIGN;
3934 struct TransportDVBoxMessage *box = (struct TransportDVBoxMessage *) boxram;
3935 struct GNUNET_PeerIdentity *path = (struct GNUNET_PeerIdentity *) &box[1];
3936 4108
3937 box->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX); 4109 dvb = create_dv_box (0,
3938 box->header.size = htons (sizeof (boxram)); 4110 &GST_my_identity,
3939 box->total_hops = htons (0); 4111 &dvh->dv->target,
3940 box->num_hops = htons (dvh->distance + 1); 4112 dvh->distance,
3941 box->origin = GST_my_identity; 4113 dvh->path,
3942 memcpy (path, dvh->path, dvh->distance * sizeof (struct GNUNET_PeerIdentity)); 4114 payload,
3943 path[dvh->distance] = dvh->dv->target; 4115 ntohs (payload->size));
3944 memcpy (&path[dvh->distance + 1], payload, mlen); 4116 route_via_neighbour (dvh->next_hop, &dvb->header, options);
3945 route_via_neighbour (dvh->next_hop, &box->header, options); 4117 GNUNET_free (dvb);
3946} 4118}
3947 4119
3948 4120
@@ -3960,52 +4132,15 @@ route_via_dv (const struct DistanceVector *dv,
3960 const struct GNUNET_MessageHeader *hdr, 4132 const struct GNUNET_MessageHeader *hdr,
3961 enum RouteMessageOptions options) 4133 enum RouteMessageOptions options)
3962{ 4134{
3963 struct DistanceVectorHop *h1; 4135 struct DistanceVectorHop *hops[2];
3964 struct DistanceVectorHop *h2; 4136 unsigned int res;
3965 uint64_t num_dv;
3966 uint64_t choice1;
3967 uint64_t choice2;
3968
3969 /* Pick random vectors, but weighted by distance, giving more weight
3970 to shorter vectors */
3971 num_dv = 0;
3972 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3973 pos = pos->next_dv)
3974 {
3975 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3976 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
3977 .rel_value_us == 0))
3978 continue; /* pos unconfirmed and confirmed required */
3979 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
3980 }
3981 if (0 == num_dv)
3982 {
3983 GNUNET_break (0);
3984 return;
3985 }
3986 choice1 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, num_dv);
3987 choice2 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, num_dv);
3988 num_dv = 0;
3989 h1 = NULL;
3990 h2 = NULL;
3991 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3992 pos = pos->next_dv)
3993 {
3994 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
3995 4137
3996 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) && 4138 res = pick_random_dv_hops (dv,
3997 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until) 4139 options,
3998 .rel_value_us == 0)) 4140 hops,
3999 continue; /* pos unconfirmed and confirmed required */ 4141 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
4000 if ((num_dv <= choice1) && (num_dv + delta > choice1)) 4142 for (unsigned int i = 0; i < res; i++)
4001 h1 = pos; 4143 forward_via_dvh (hops[i], hdr, options & (~RMO_REDUNDANT));
4002 if ((num_dv <= choice2) && (num_dv + delta > choice2))
4003 h2 = pos;
4004 num_dv += delta;
4005 }
4006 forward_via_dvh (h1, hdr, options & (~RMO_REDUNDANT));
4007 if (0 == (options & RMO_REDUNDANT))
4008 forward_via_dvh (h2, hdr, options & (~RMO_REDUNDANT));
4009} 4144}
4010 4145
4011 4146
@@ -5912,6 +6047,7 @@ forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
5912/** 6047/**
5913 * Check signature of type #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR 6048 * Check signature of type #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
5914 * 6049 *
6050 * @param sender_monotonic_time monotonic time of the initiator
5915 * @param init the signer 6051 * @param init the signer
5916 * @param challenge the challenge that was signed 6052 * @param challenge the challenge that was signed
5917 * @param init_sig signature presumably by @a init 6053 * @param init_sig signature presumably by @a init
@@ -5919,6 +6055,7 @@ forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
5919 */ 6055 */
5920static int 6056static int
5921validate_dv_initiator_signature ( 6057validate_dv_initiator_signature (
6058 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
5922 const struct GNUNET_PeerIdentity *init, 6059 const struct GNUNET_PeerIdentity *init,
5923 const struct ChallengeNonceP *challenge, 6060 const struct ChallengeNonceP *challenge,
5924 const struct GNUNET_CRYPTO_EddsaSignature *init_sig) 6061 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
@@ -5926,6 +6063,7 @@ validate_dv_initiator_signature (
5926 struct DvInitPS ip = {.purpose.purpose = htonl ( 6063 struct DvInitPS ip = {.purpose.purpose = htonl (
5927 GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR), 6064 GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR),
5928 .purpose.size = htonl (sizeof (ip)), 6065 .purpose.size = htonl (sizeof (ip)),
6066 .monotonic_time = sender_monotonic_time,
5929 .challenge = *challenge}; 6067 .challenge = *challenge};
5930 6068
5931 if ( 6069 if (
@@ -6132,6 +6270,24 @@ calculate_fork_degree (unsigned int hops_taken,
6132 6270
6133 6271
6134/** 6272/**
6273 * Function called when peerstore is done storing a DV monotonic time.
6274 *
6275 * @param cls a `struct Neighbour`
6276 * @param success #GNUNET_YES if peerstore was successful
6277 */
6278static void
6279neighbour_store_dvmono_cb (void *cls, int success)
6280{
6281 struct Neighbour *n = cls;
6282
6283 n->sc = NULL;
6284 if (GNUNET_YES != success)
6285 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
6286 "Failed to store other peer's monotonic time in peerstore!\n");
6287}
6288
6289
6290/**
6135 * Communicator gave us a DV learn message. Process the request. 6291 * Communicator gave us a DV learn message. Process the request.
6136 * 6292 *
6137 * @param cls a `struct CommunicatorMessageContext` (must call 6293 * @param cls a `struct CommunicatorMessageContext` (must call
@@ -6150,6 +6306,7 @@ handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6150 int do_fwd; 6306 int do_fwd;
6151 int did_initiator; 6307 int did_initiator;
6152 struct GNUNET_TIME_Absolute in_time; 6308 struct GNUNET_TIME_Absolute in_time;
6309 struct Neighbour *n;
6153 6310
6154 nhops = ntohs (dvl->bidirectional); /* 0 = sender is initiator */ 6311 nhops = ntohs (dvl->bidirectional); /* 0 = sender is initiator */
6155 bi_history = ntohs (dvl->bidirectional); 6312 bi_history = ntohs (dvl->bidirectional);
@@ -6184,15 +6341,44 @@ handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6184 /* continue communicator here, everything else can happen asynchronous! */ 6341 /* continue communicator here, everything else can happen asynchronous! */
6185 finish_cmc_handling (cmc); 6342 finish_cmc_handling (cmc);
6186 6343
6187 /* OPTIMIZE-FIXME: Technically, we only need to bother checking 6344 n = lookup_neighbour (&dvl->initiator);
6188 the initiator signature if we send the message back to the initiator... 6345 if (NULL != n)
6189 */
6190 if (GNUNET_OK != validate_dv_initiator_signature (&dvl->initiator,
6191 &dvl->challenge,
6192 &dvl->init_sig))
6193 { 6346 {
6194 GNUNET_break_op (0); 6347 if ((n->dv_monotime_available == GNUNET_YES) &&
6195 return; 6348 (GNUNET_TIME_absolute_ntoh (dvl->monotonic_time).abs_value_us <
6349 n->last_dv_learn_monotime.abs_value_us))
6350 {
6351 GNUNET_STATISTICS_update (GST_stats,
6352 "# DV learn discarded due to time travel",
6353 1,
6354 GNUNET_NO);
6355 return;
6356 }
6357 if (GNUNET_OK != validate_dv_initiator_signature (dvl->monotonic_time,
6358 &dvl->initiator,
6359 &dvl->challenge,
6360 &dvl->init_sig))
6361 {
6362 GNUNET_break_op (0);
6363 return;
6364 }
6365 n->last_dv_learn_monotime = GNUNET_TIME_absolute_ntoh (dvl->monotonic_time);
6366 if (GNUNET_YES == n->dv_monotime_available)
6367 {
6368 if (NULL != n->sc)
6369 GNUNET_PEERSTORE_store_cancel (n->sc);
6370 n->sc =
6371 GNUNET_PEERSTORE_store (peerstore,
6372 "transport",
6373 &dvl->initiator,
6374 GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME,
6375 &dvl->monotonic_time,
6376 sizeof (dvl->monotonic_time),
6377 GNUNET_TIME_UNIT_FOREVER_ABS,
6378 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
6379 &neighbour_store_dvmono_cb,
6380 n);
6381 }
6196 } 6382 }
6197 // FIXME: asynchronously (!) verify hop-by-hop signatures! 6383 // FIXME: asynchronously (!) verify hop-by-hop signatures!
6198 // => if signature verification load too high, implement random drop 6384 // => if signature verification load too high, implement random drop
@@ -6418,25 +6604,16 @@ forward_dv_box (struct Neighbour *next_hop,
6418 uint16_t payload_size) 6604 uint16_t payload_size)
6419{ 6605{
6420 struct TransportDVBoxMessage *dvb; 6606 struct TransportDVBoxMessage *dvb;
6421 struct GNUNET_PeerIdentity *dhops;
6422 6607
6423 GNUNET_assert (UINT16_MAX < sizeof (struct TransportDVBoxMessage) + 6608 dvb = create_dv_box (total_hops,
6424 sizeof (struct GNUNET_PeerIdentity) * num_hops + 6609 origin,
6425 payload_size); 6610 &hops[num_hops - 1] /* == target */,
6426 dvb = GNUNET_malloc (sizeof (struct TransportDVBoxMessage) + 6611 num_hops - 1 /* do not count target twice */,
6427 sizeof (struct GNUNET_PeerIdentity) * num_hops + 6612 hops,
6613 payload,
6428 payload_size); 6614 payload_size);
6429 dvb->header.size =
6430 htons (sizeof (struct TransportDVBoxMessage) +
6431 sizeof (struct GNUNET_PeerIdentity) * num_hops + payload_size);
6432 dvb->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
6433 dvb->total_hops = htons (total_hops);
6434 dvb->num_hops = htons (num_hops);
6435 dvb->origin = *origin;
6436 dhops = (struct GNUNET_PeerIdentity *) &dvb[1];
6437 memcpy (dhops, hops, num_hops * sizeof (struct GNUNET_PeerIdentity));
6438 memcpy (&dhops[num_hops], payload, payload_size);
6439 route_message (&next_hop->pid, &dvb->header, RMO_NONE); 6615 route_message (&next_hop->pid, &dvb->header, RMO_NONE);
6616 GNUNET_free (dvb);
6440} 6617}
6441 6618
6442 6619
@@ -7974,10 +8151,13 @@ start_dv_learn (void *cls)
7974 dvl.num_hops = htons (0); 8151 dvl.num_hops = htons (0);
7975 dvl.bidirectional = htons (0); 8152 dvl.bidirectional = htons (0);
7976 dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO); 8153 dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);
8154 dvl.monotonic_time =
8155 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (GST_cfg));
7977 { 8156 {
7978 struct DvInitPS dvip = {.purpose.purpose = htonl ( 8157 struct DvInitPS dvip = {.purpose.purpose = htonl (
7979 GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR), 8158 GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR),
7980 .purpose.size = htonl (sizeof (dvip)), 8159 .purpose.size = htonl (sizeof (dvip)),
8160 .monotonic_time = dvl.monotonic_time,
7981 .challenge = lle->challenge}; 8161 .challenge = lle->challenge};
7982 8162
7983 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, 8163 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
@@ -8039,6 +8219,44 @@ check_validation_request_pending (void *cls,
8039 8219
8040 8220
8041/** 8221/**
8222 * Function called with the monotonic time of a DV initiator
8223 * by PEERSTORE. Updates the time.
8224 *
8225 * @param cls a `struct Neighbour`
8226 * @param record the information found, NULL for the last call
8227 * @param emsg error message
8228 */
8229static void
8230neighbour_dv_monotime_cb (void *cls,
8231 const struct GNUNET_PEERSTORE_Record *record,
8232 const char *emsg)
8233{
8234 struct Neighbour *n = cls;
8235 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8236 struct GNUNET_TIME_Absolute mt;
8237
8238 (void) emsg;
8239 if (NULL == record)
8240 {
8241 /* we're done with #neighbour_dv_monotime_cb() invocations,
8242 continue normal processing */
8243 n->get = NULL;
8244 n->dv_monotime_available = GNUNET_YES;
8245 return;
8246 }
8247 if (sizeof (*mtbe) != record->value_size)
8248 {
8249 GNUNET_break (0);
8250 return;
8251 }
8252 mtbe = record->value;
8253 n->last_dv_learn_monotime =
8254 GNUNET_TIME_absolute_max (n->last_dv_learn_monotime,
8255 GNUNET_TIME_absolute_ntoh (*mtbe));
8256}
8257
8258
8259/**
8042 * New queue became available. Process the request. 8260 * New queue became available. Process the request.
8043 * 8261 *
8044 * @param cls the client 8262 * @param cls the client
@@ -8074,6 +8292,13 @@ handle_add_queue_message (void *cls,
8074 &neighbour->pid, 8292 &neighbour->pid,
8075 neighbour, 8293 neighbour,
8076 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 8294 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
8295 neighbour->get =
8296 GNUNET_PEERSTORE_iterate (peerstore,
8297 "transport",
8298 &neighbour->pid,
8299 GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME,
8300 &neighbour_dv_monotime_cb,
8301 neighbour);
8077 } 8302 }
8078 addr_len = ntohs (aqm->header.size) - sizeof (*aqm); 8303 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
8079 addr = (const char *) &aqm[1]; 8304 addr = (const char *) &aqm[1];