GNUnet  0.11.x
gnunet-service-transport_validation.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2010-2015 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
33 #include "gnunet_hello_lib.h"
34 #include "gnunet_ats_service.h"
36 #include "gnunet_signatures.h"
37 
46 {
53 
60 
67 
74 
81 };
82 
83 
91 #define PONG_SIGNATURE_LIFETIME GNUNET_TIME_relative_multiply ( \
92  GNUNET_TIME_UNIT_HOURS, 1)
93 
99 #define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply ( \
100  GNUNET_TIME_UNIT_HOURS, 12)
101 
108 #define UNVALIDATED_PING_KEEPALIVE GNUNET_TIME_relative_multiply ( \
109  GNUNET_TIME_UNIT_MINUTES, 5)
110 
116 #define VALIDATED_PING_FREQUENCY GNUNET_TIME_relative_multiply ( \
117  GNUNET_TIME_UNIT_MINUTES, 15)
118 
122 #define CONNECTED_PING_FREQUENCY GNUNET_TIME_relative_multiply ( \
123  GNUNET_TIME_UNIT_MINUTES, 2)
124 
128 #define ACCEPTABLE_PING_DELAY GNUNET_TIME_relative_multiply ( \
129  GNUNET_TIME_UNIT_SECONDS, 1)
130 
134 #define VALIDATION_MAP_SIZE 256
135 
139 #define PING_PRIORITY 2
140 
144 #define PONG_PRIORITY 4
145 
146 
148 
156 {
161 
166 
171 };
172 
173 
185 {
190 
196 
201 
207 
212 
217  uint32_t addrlen GNUNET_PACKED;
218 };
220 
225 {
230 
235 
239  struct GNUNET_CRYPTO_EddsaSignature pong_sig_cache;
240 
245 
250 
254  struct GNUNET_TIME_Absolute send_time;
255 
259  struct GNUNET_TIME_Absolute next_validation;
260 
265  struct GNUNET_TIME_Absolute valid_until;
266 
271  struct GNUNET_TIME_Absolute pong_sig_valid_until;
272 
279  struct GNUNET_TIME_Absolute revalidation_block;
280 
285  struct GNUNET_TIME_Relative latency;
286 
291 
295  uint32_t challenge;
296 
301  int copied;
302 
306  int in_use;
307 
312 
317 
321  enum GNUNET_NetworkType network;
322 };
323 
324 
331 
336 
341 
347 static unsigned int validations_running;
348 
353 
358 
359 
364 {
369 
374 };
375 
376 
382 static void
384 {
386  gettext_noop ("# Addresses in validation map"),
387  GNUNET_CONTAINER_multipeermap_size (validation_map),
388  GNUNET_NO);
389 }
390 
391 
401 static int
403  const struct GNUNET_PeerIdentity *key,
404  void *value)
405 {
406  struct ValidationEntryMatchContext *vemc = cls;
407  struct ValidationEntry *ve = value;
408 
409  if (0 == GNUNET_HELLO_address_cmp (ve->address,
410  vemc->address))
411  {
412  vemc->ve = ve;
413  return GNUNET_NO;
414  }
415  return GNUNET_YES;
416 }
417 
418 
426 static void
429 {
430  ve->state = state;
431 }
432 
433 
442 static int
444  const struct GNUNET_PeerIdentity *key,
445  void *value)
446 {
447  struct ValidationEntry *ve = value;
448 
451 
452  /* Notify about deleted entry */
455 
456  if (NULL != ve->bc)
457  {
459  ve->bc = NULL;
460  }
462  GNUNET_CONTAINER_multipeermap_remove (validation_map,
463  &ve->address->peer,
464  ve));
466  if (GNUNET_YES == ve->known_to_ats)
467  {
471  ve->known_to_ats = GNUNET_NO;
472  }
474  if (NULL != ve->timeout_task)
475  {
477  ve->timeout_task = NULL;
478  }
479  if (NULL != ve->revalidation_task)
480  {
482  ve->revalidation_task = NULL;
483  }
484  if ((GNUNET_YES == ve->expecting_pong) &&
485  (validations_running > 0))
486  {
489  gettext_noop ("# validations running"),
491  GNUNET_NO);
492  }
493  GNUNET_free (ve);
494  return GNUNET_OK;
495 }
496 
497 
504 static void
506 {
507  struct ValidationEntry *ve = cls;
508  struct GNUNET_TIME_Absolute max;
509  struct GNUNET_TIME_Relative left;
510 
511  ve->timeout_task = NULL;
512  /* For valid addresses, we want to wait until the expire;
513  for addresses under PING validation, we want to wait
514  until we give up on the PING */
516  ve->revalidation_block);
518  if (left.rel_value_us > 0)
519  {
520  /* We should wait a bit longer. This happens when
521  address lifetimes are extended due to successful
522  validations. */
523  ve->timeout_task =
526  ve);
527  return;
528  }
530  gettext_noop (
531  "# address records discarded (timeout)"),
532  1,
533  GNUNET_NO);
535  &ve->address->peer,
536  ve);
537 }
538 
539 
552 static void
554  const struct GNUNET_PeerIdentity *pid,
555  const struct GNUNET_HELLO_Address *address_null,
556  struct GNUNET_ATS_Session *session_null,
557  int result)
558 {
559  struct ValidationEntry *ve = cls;
560  struct TransportPingMessage ping;
562  struct GNUNET_TIME_Absolute next;
563  const struct GNUNET_MessageHeader *hello;
564  ssize_t ret;
565  size_t tsize;
566  size_t slen;
567  uint16_t hsize;
568  struct GNUNET_ATS_Session *session;
569 
570  ve->bc = NULL;
571  if (GNUNET_OK != result)
572  {
574  "Blacklist denies sending PING to `%s' `%s' `%s'\n",
575  GNUNET_i2s (pid),
576  GST_plugins_a2s (ve->address),
577  ve->address->transport_name);
579  gettext_noop (
580  "# address records discarded (blacklist)"),
581  1,
582  GNUNET_NO);
584  pid,
585  ve);
586  return;
587  }
588  hello = GST_hello_get ();
589  GNUNET_assert (NULL != hello);
590  slen = strlen (ve->address->transport_name) + 1;
591  hsize = ntohs (hello->size);
592  tsize = sizeof(struct TransportPingMessage)
593  + ve->address->address_length + slen + hsize;
594 
595  ping.header.size =
596  htons (sizeof(struct TransportPingMessage)
597  + ve->address->address_length + slen);
599  ping.challenge = htonl (ve->challenge);
600  ping.target = *pid;
601 
602  if (tsize >= GNUNET_MAX_MESSAGE_SIZE)
603  {
604  GNUNET_break (0);
605  hsize = 0;
606  tsize =
607  sizeof(struct TransportPingMessage) + ve->address->address_length
608  + slen + hsize;
609  }
610  {
611  char message_buf[tsize] GNUNET_ALIGN;
612 
613  GNUNET_memcpy (message_buf,
614  hello,
615  hsize);
616  GNUNET_memcpy (&message_buf[hsize],
617  &ping,
618  sizeof(struct TransportPingMessage));
619  GNUNET_memcpy (&message_buf[sizeof(struct TransportPingMessage) + hsize],
620  ve->address->transport_name,
621  slen);
622  GNUNET_memcpy (&message_buf[sizeof(struct TransportPingMessage) + slen
623  + hsize],
624  ve->address->address,
625  ve->address->address_length);
626  papi = GST_plugins_find (ve->address->transport_name);
627  GNUNET_assert (NULL != papi);
628  session = papi->get_session (papi->cls,
629  ve->address);
630  if (NULL == session)
631  {
632  /* Could not get a valid session */
634  "Failed to get session to send PING to `%s' at `%s'\n",
635  GNUNET_i2s (pid),
636  GST_plugins_a2s (ve->address));
637  return;
638  }
639 
640  ret = papi->send (papi->cls, session,
641  message_buf, tsize,
644  NULL, NULL);
645  if (-1 == ret)
646  {
648  "Failed to send PING to `%s' at `%s'\n",
649  GNUNET_i2s (pid),
650  GST_plugins_a2s (ve->address));
651  return;
652  }
654  "Transmitted plain PING to `%s' `%s' `%s'\n",
655  GNUNET_i2s (pid),
656  GST_plugins_a2s (ve->address),
657  ve->address->transport_name);
658  ve->network = papi->get_network (papi->cls,
659  session);
660  GNUNET_break (GNUNET_NT_UNSPECIFIED != ve->network);
661  GST_neighbours_notify_data_sent (ve->address,
662  session,
663  tsize);
667  ve->send_time = GNUNET_TIME_absolute_get ();
669  gettext_noop (
670  "# PINGs for address validation sent"),
671  1,
672  GNUNET_NO);
673  ve->expecting_pong = GNUNET_YES;
676  "Validation started, %u validation processes running\n",
679  gettext_noop ("# validations running"),
681  GNUNET_NO);
682  /* Notify about PING sent */
685  }
686 }
687 
688 
694 static void
696 {
697  struct ValidationEntry *ve = cls;
698  struct GNUNET_TIME_Relative canonical_delay;
699  struct GNUNET_TIME_Relative delay;
700  struct GNUNET_TIME_Relative blocked_for;
701  struct GST_BlacklistCheck *bc;
702  uint32_t rdelay;
703 
704  ve->revalidation_task = NULL;
706  /* Considering current connectivity situation, what is the maximum
707  block period permitted? */
708  if (GNUNET_YES == ve->in_use)
709  canonical_delay = CONNECTED_PING_FREQUENCY;
711  0)
712  canonical_delay = VALIDATED_PING_FREQUENCY;
713  else
714  canonical_delay = UNVALIDATED_PING_KEEPALIVE;
715  /* Use delay that is MIN of original delay and possibly adjusted
716  new maximum delay (which may be lower); the real delay
717  is originally randomized between "canonical_delay" and "2 * canonical_delay",
718  so continue to permit that window for the operation. */
719  delay = GNUNET_TIME_relative_min (delay,
721  canonical_delay,
722  2));
724  if (delay.rel_value_us > 0)
725  {
726  /* should wait a bit longer */
728  "Waiting for %s longer before (re)validating address `%s'\n",
730  GNUNET_YES),
731  GST_plugins_a2s (ve->address));
732  ve->revalidation_task =
734  &revalidate_address, ve);
736  return;
737  }
738  /* check if globally we have too many active validations at a
739  too high rate, if so, delay ours */
742  (blocked_for.rel_value_us > 0))
743  {
744  /* Validations are blocked, have to wait for blocked_for time */
746  "Validations blocked for another %s, delaying validating address `%s'\n",
748  GNUNET_YES),
749  GST_plugins_a2s (ve->address));
751  gettext_noop (
752  "# validations delayed by global throttle"),
753  1,
754  GNUNET_NO);
755  ve->revalidation_task =
756  GNUNET_SCHEDULER_add_delayed (blocked_for,
758  ve);
760  return;
761  }
762 
763  /* We are good to go; remember to not go again for `canonical_delay` time;
764  add up to `canonical_delay` to randomize start time */
766  /* schedule next PINGing with some extra random delay to avoid synchronous re-validations */
767  rdelay =
769  canonical_delay.rel_value_us);
770 
771  delay = GNUNET_TIME_relative_add (canonical_delay,
774  rdelay));
775 
777  "Validating now, next scheduled for %s, now validating address `%s'\n",
779  GNUNET_YES),
780  GST_plugins_a2s (ve->address));
781  ve->revalidation_task =
784  ve);
786 
787  /* start PINGing by checking blacklist */
789  gettext_noop ("# address revalidations started"), 1,
790  GNUNET_NO);
791  if (NULL != ve->bc)
792  {
794  ve->bc = NULL;
795  }
797  ve->address->transport_name,
799  ve,
800  NULL,
801  NULL);
802  if (NULL != bc)
803  {
804  /* If transmit_ping_if_allowed was already called it may have freed ve,
805  * so only set ve->bc if it has not been called.
806  */
807  ve->bc = bc;
808  }
809 }
810 
811 
821 static struct ValidationEntry *
823 {
824  struct ValidationEntryMatchContext vemc;
825  struct ValidationEntry *ve;
826 
827  vemc.ve = NULL;
828  vemc.address = address;
830  &address->peer,
831  &validation_entry_match, &vemc);
832  if (NULL != (ve = vemc.ve))
833  return ve;
835  GST_ats_is_known_no_session (address));
836  ve = GNUNET_new (struct ValidationEntry);
837  ve->in_use = GNUNET_SYSERR; /* not defined */
838  ve->address = GNUNET_HELLO_address_copy (address);
840  memset (&ve->pong_sig_cache,
841  '\0',
842  sizeof(struct GNUNET_CRYPTO_EddsaSignature));
844  ve->challenge =
846  ve->timeout_task =
849  ve);
850  GNUNET_CONTAINER_multipeermap_put (validation_map,
851  &address->peer,
852  ve,
857  return ve;
858 }
859 
860 
872 static int
873 add_valid_address (void *cls,
874  const struct GNUNET_HELLO_Address *address,
876 {
877  const struct GNUNET_HELLO_Message *hello = cls;
878  struct ValidationEntry *ve;
879  struct GNUNET_PeerIdentity pid;
880  struct GNUNET_ATS_Properties prop;
882 
883  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
884  return GNUNET_OK; /* expired */
885  if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
886  {
887  GNUNET_break (0);
888  return GNUNET_OK; /* invalid HELLO !? */
889  }
890  if (NULL == (papi = GST_plugins_find (address->transport_name)))
891  {
892  /* might have been valid in the past, but we don't have that
893  plugin loaded right now */
894  return GNUNET_OK;
895  }
896  if (NULL ==
897  papi->address_to_string (papi->cls,
898  address->address,
899  address->address_length))
900  {
901  /* Why do we try to add an ill-formed address? */
902  GNUNET_break (0);
904  "Address with %u bytes for plugin %s and peer %s is malformed\n",
905  (unsigned int) address->address_length,
906  address->transport_name,
907  GNUNET_i2s (&pid));
908  return GNUNET_OK;
909  }
910 
911  ve = find_validation_entry (address);
912  ve->network = papi->get_network_for_address (papi->cls,
913  address);
916  expiration);
917  if (NULL == ve->revalidation_task)
918  {
920  "Starting revalidations for valid address `%s'\n",
921  GST_plugins_a2s (ve->address));
924  }
927  memset (&prop, 0, sizeof(prop));
928  prop.scope = ve->network;
929  prop.delay = GNUNET_TIME_relative_divide (ve->latency, 2);
930  if (GNUNET_YES != ve->known_to_ats)
931  {
932  ve->known_to_ats = GNUNET_YES;
933  GST_ats_add_address (address, &prop);
936  }
937  return GNUNET_OK;
938 }
939 
940 
950 static void
952  const struct GNUNET_PeerIdentity *peer,
953  const struct GNUNET_HELLO_Message *hello,
954  const char *err_msg)
955 {
956  GNUNET_assert (NULL != peer);
957  if (NULL == hello)
958  return;
959  if (0 == memcmp (&GST_my_identity,
960  peer,
961  sizeof(struct GNUNET_PeerIdentity)))
962  {
963  /* Peerinfo returned own identity, skip validation */
964  return;
965  }
967  "Handling HELLO for peer `%s'\n",
968  GNUNET_i2s (peer));
969  GNUNET_assert (NULL ==
972  (void *) hello));
973 }
974 
975 
981 void
982 GST_validation_start (unsigned int max_fds)
996  (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2);
997  validations_fast_start_threshold = (max_fds / 2);
1000  gettext_noop ("# validations running"),
1002  GNUNET_NO);
1004  "Validation uses a fast start threshold of %u connections and a delay of %s\n",
1007  GNUNET_YES));
1009  GNUNET_NO);
1011  &process_peerinfo_hello, NULL);
1012 }
1013 
1014 
1018 void
1020 {
1021  GNUNET_CONTAINER_multipeermap_iterate (validation_map,
1023  NULL);
1024  GNUNET_CONTAINER_multipeermap_destroy (validation_map);
1025  validation_map = NULL;
1027 }
1028 
1029 
1041 static void
1043  struct GNUNET_TIME_Absolute valid_until,
1044  struct GNUNET_TIME_Absolute validation_block,
1045  const struct GNUNET_HELLO_Address *address)
1046 {
1047  struct TransportPongMessage *pong = cls;
1048  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1049  struct GNUNET_ATS_Session *session;
1050 
1051  papi = GST_plugins_find (address->transport_name);
1052  if (NULL == papi)
1053  {
1055  "Plugin %s not supported, cannot send PONG\n",
1056  address->transport_name);
1057  return;
1058  }
1059  GNUNET_assert (NULL != papi->send);
1060  GNUNET_assert (NULL != papi->get_session);
1061  session = papi->get_session (papi->cls, address);
1062  if (NULL == session)
1063  {
1064  GNUNET_break (0);
1065  return;
1066  }
1067  GST_ats_new_session (address, session);
1068  papi->send (papi->cls, session,
1069  (const char *) pong,
1070  ntohs (pong->header.size),
1071  PONG_PRIORITY,
1073  NULL, NULL);
1075  session,
1076  pong->header.size);
1077 }
1078 
1079 
1089 int
1091  const struct GNUNET_MessageHeader *hdr,
1092  const struct GNUNET_HELLO_Address *sender_address,
1093  struct GNUNET_ATS_Session *session)
1094 {
1095  const struct TransportPingMessage *ping;
1096  struct TransportPongMessage *pong;
1097  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1098  struct GNUNET_CRYPTO_EddsaSignature *sig_cache;
1099  struct GNUNET_TIME_Absolute *sig_cache_exp;
1100  const char *addr;
1101  const char *addrend;
1102  char *plugin_name;
1103  char *pos;
1104  size_t len_address;
1105  size_t len_plugin;
1106  ssize_t ret;
1107  struct GNUNET_HELLO_Address address;
1108 
1109  if (0 ==
1110  memcmp (&GST_my_identity,
1111  sender,
1112  sizeof(struct GNUNET_PeerIdentity)))
1113  return GNUNET_OK; /* our own, ignore! */
1114  if (ntohs (hdr->size) < sizeof(struct TransportPingMessage))
1115  {
1116  GNUNET_break_op (0);
1117  return GNUNET_SYSERR;
1118  }
1119  ping = (const struct TransportPingMessage *) hdr;
1120  if (0 !=
1121  memcmp (&ping->target,
1122  &GST_my_identity,
1123  sizeof(struct GNUNET_PeerIdentity)))
1124  {
1126  gettext_noop
1127  ("# PING message for different peer received"),
1128  1,
1129  GNUNET_NO);
1130  return GNUNET_SYSERR;
1131  }
1133  gettext_noop ("# PING messages received"), 1,
1134  GNUNET_NO);
1135  addr = (const char *) &ping[1];
1136  len_address = ntohs (hdr->size) - sizeof(struct TransportPingMessage);
1137  /* peer wants to confirm that this is one of our addresses, this is what is
1138  * used for address validation */
1139 
1140  sig_cache = NULL;
1141  sig_cache_exp = NULL;
1142  papi = NULL;
1143  if (len_address > 0)
1144  {
1145  addrend = memchr (addr, '\0', len_address);
1146  if (NULL == addrend)
1147  {
1148  GNUNET_break_op (0);
1149  return GNUNET_SYSERR;
1150  }
1151  addrend++;
1152  len_plugin = strlen (addr) + 1;
1153  len_address -= len_plugin;
1155  address.address = addrend;
1156  address.address_length = len_address;
1157  address.transport_name = addr;
1158  address.peer = GST_my_identity;
1159 
1160  if (NULL == address.transport_name)
1161  {
1162  GNUNET_break (0);
1163  }
1164 
1165  if (0 != strstr (address.transport_name, "_client"))
1166  {
1167  plugin_name = GNUNET_strdup (address.transport_name);
1168  pos = strstr (plugin_name, "_client");
1169  GNUNET_assert (NULL != pos);
1170  GNUNET_snprintf (pos, strlen ("_server") + 1, "%s", "_server");
1171  }
1172  else
1173  plugin_name = GNUNET_strdup (address.transport_name);
1174 
1175  if (NULL == (papi = GST_plugins_find (plugin_name)))
1176  {
1177  /* we don't have the plugin for this address */
1179  _ (
1180  "Plugin `%s' not available, cannot confirm having this address\n"),
1181  plugin_name);
1182  GNUNET_free (plugin_name);
1183  return GNUNET_SYSERR;
1184  }
1185  GNUNET_free (plugin_name);
1186  if (GNUNET_OK !=
1187  papi->check_address (papi->cls,
1188  addrend,
1189  len_address))
1190  {
1192  gettext_noop
1193  ("# failed address checks during validation"),
1194  1,
1195  GNUNET_NO);
1197  _ (
1198  "Address `%s' is not one of my addresses, not confirming PING\n"),
1199  GST_plugins_a2s (&address));
1200  return GNUNET_SYSERR;
1201  }
1202  else
1203  {
1205  gettext_noop
1206  (
1207  "# successful address checks during validation"),
1208  1,
1209  GNUNET_NO);
1211  "Address `%s' is one of my addresses, confirming PING\n",
1212  GST_plugins_a2s (&address));
1213  }
1214 
1215  if (GNUNET_YES !=
1216  GST_hello_test_address (&address,
1217  &sig_cache,
1218  &sig_cache_exp))
1219  {
1221  _ (
1222  "Not confirming PING from peer `%s' with address `%s' since I cannot confirm having this address.\n"),
1223  GNUNET_i2s (sender),
1224  GST_plugins_a2s (&address));
1225  return GNUNET_SYSERR;
1226  }
1227  }
1228  else
1229  {
1230  addrend = NULL; /* make gcc happy */
1231  len_plugin = 0;
1232  static struct GNUNET_CRYPTO_EddsaSignature no_address_signature;
1233  static struct GNUNET_TIME_Absolute no_address_signature_expiration;
1234 
1235  sig_cache = &no_address_signature;
1236  sig_cache_exp = &no_address_signature_expiration;
1237  }
1238 
1240  "I am `%s', sending PONG to peer `%s'\n",
1242  GNUNET_i2s (sender));
1243 
1244  /* message with structure:
1245  * [TransportPongMessage][Transport name][Address] */
1246 
1247  pong = GNUNET_malloc (sizeof(struct TransportPongMessage) + len_address
1248  + len_plugin);
1249  pong->header.size =
1250  htons (sizeof(struct TransportPongMessage) + len_address + len_plugin);
1252  pong->purpose.size =
1253  htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
1254  + sizeof(uint32_t) + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1255  + len_address + len_plugin);
1257  GNUNET_memcpy (&pong->challenge, &ping->challenge, sizeof(ping->challenge));
1258  pong->addrlen = htonl (len_address + len_plugin);
1259  GNUNET_memcpy (&pong[1], addr, len_plugin); /* Copy transport plugin */
1260  if (len_address > 0)
1261  {
1262  GNUNET_assert (NULL != addrend);
1263  GNUNET_memcpy (&((char *) &pong[1])[len_plugin], addrend, len_address);
1264  }
1265  if (GNUNET_TIME_absolute_get_remaining (*sig_cache_exp).rel_value_us <
1266  PONG_SIGNATURE_LIFETIME.rel_value_us / 4)
1267  {
1268  /* create / update cached sig */
1270  "Creating PONG signature to indicate ownership.\n");
1272  pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
1273  if (GNUNET_OK !=
1275  sig_cache))
1276  {
1278  _ ("Failed to create PONG signature for peer `%s'\n"),
1279  GNUNET_i2s (sender));
1280  }
1281  }
1282  else
1283  {
1284  pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
1285  }
1286  pong->signature = *sig_cache;
1287 
1288  GNUNET_assert (NULL != sender_address);
1289 
1290  /* first see if the session we got this PING from can be used to transmit
1291  * a response reliably */
1292  if (NULL == papi)
1293  {
1294  ret = -1;
1295  }
1296  else
1297  {
1298  GNUNET_assert (NULL != papi->send);
1299  GNUNET_assert (NULL != papi->get_session);
1300  if (NULL == session)
1301  {
1302  session = papi->get_session (papi->cls, sender_address);
1303  }
1304  if (NULL == session)
1305  {
1306  GNUNET_break (0);
1307  ret = -1;
1308  }
1309  else
1310  {
1311  ret = papi->send (papi->cls, session,
1312  (const char *) pong,
1313  ntohs (pong->header.size),
1315  NULL, NULL);
1316  if (-1 != ret)
1317  GST_neighbours_notify_data_sent (sender_address,
1318  session,
1319  pong->header.size);
1320  }
1321  }
1322  if (-1 != ret)
1323  {
1325  "Transmitted PONG to `%s' via reliable mechanism\n",
1326  GNUNET_i2s (sender));
1327  /* done! */
1329  gettext_noop
1330  ("# PONGs unicast via reliable transport"), 1,
1331  GNUNET_NO);
1332  GNUNET_free (pong);
1333  return GNUNET_OK;
1334  }
1335 
1336  /* no reliable method found, try transmission via all known addresses */
1338  gettext_noop
1339  ("# PONGs multicast to all available addresses"),
1340  1,
1341  GNUNET_NO);
1343  &multicast_pong, pong);
1344  GNUNET_free (pong);
1345  return GNUNET_OK;
1346 }
1347 
1348 
1354 void
1356 {
1357  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1358  struct ValidationEntry *ve;
1359 
1360  papi = GST_plugins_find (address->transport_name);
1361  if (NULL == papi)
1362  {
1363  /* This plugin is currently unvailable ... ignore */
1365  "No plugin available for %s\n",
1366  address->transport_name);
1367  return;
1368  }
1369  ve = find_validation_entry (address);
1370  if (NULL == ve->revalidation_task)
1371  {
1373  "Validation process started for fresh address `%s' of %s\n",
1374  GST_plugins_a2s (ve->address),
1375  GNUNET_i2s (&ve->address->peer));
1377  }
1378  else
1379  {
1381  "Validation already running for address `%s' of %s\n",
1382  GST_plugins_a2s (ve->address),
1383  GNUNET_i2s (&ve->address->peer));
1384  }
1385 }
1386 
1387 
1397 static int
1399  const struct GNUNET_HELLO_Address *address,
1401 {
1402  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
1403  {
1405  "Skipping expired address from HELLO\n");
1406  return GNUNET_OK; /* expired */
1407  }
1409  return GNUNET_OK;
1410 }
1411 
1412 
1422 static ssize_t
1424  size_t max,
1425  void *buf)
1426 {
1427  struct ValidationEntry *ve = cls;
1428 
1429  if (GNUNET_YES == ve->copied)
1430  return GNUNET_SYSERR; /* Done */
1431  ve->copied = GNUNET_YES;
1432  return GNUNET_HELLO_add_address (ve->address,
1433  ve->valid_until,
1434  buf,
1435  max);
1436 }
1437 
1438 
1447 int
1449  const struct GNUNET_MessageHeader *hdr)
1450 {
1451  const struct TransportPongMessage *pong;
1452  struct ValidationEntry *ve;
1453  const char *tname;
1454  const char *addr;
1455  size_t addrlen;
1456  size_t slen;
1457  size_t size;
1458  struct GNUNET_HELLO_Message *hello;
1459  struct GNUNET_HELLO_Address address;
1460  int sig_res;
1461  int do_verify;
1462 
1463  if (0 ==
1464  memcmp (&GST_my_identity,
1465  sender,
1466  sizeof(struct GNUNET_PeerIdentity)))
1467  return GNUNET_OK; /* our own, ignore! */
1468 
1469  if (ntohs (hdr->size) < sizeof(struct TransportPongMessage))
1470  {
1471  GNUNET_break_op (0);
1472  return GNUNET_SYSERR;
1473  }
1475  gettext_noop ("# PONG messages received"), 1,
1476  GNUNET_NO);
1477 
1478  /* message with structure:
1479  * [TransportPongMessage][Transport name][Address] */
1480 
1481  pong = (const struct TransportPongMessage *) hdr;
1482  tname = (const char *) &pong[1];
1483  size = ntohs (hdr->size) - sizeof(struct TransportPongMessage);
1484  addr = memchr (tname, '\0', size);
1485  if (NULL == addr)
1486  {
1487  GNUNET_break_op (0);
1488  return GNUNET_SYSERR;
1489  }
1490  addr++;
1491  slen = strlen (tname) + 1;
1492  addrlen = size - slen;
1493 
1494  if (NULL == GST_plugins_find (tname))
1495  {
1496  /* we got the PONG, but the transport plugin specified in it
1497  is not supported by this peer, so this cannot be a good
1498  PONG for us. */
1499  GNUNET_break_op (0);
1500  return GNUNET_OK;
1501  }
1502 
1503  address.peer = *sender;
1504  address.address = addr;
1505  address.address_length = addrlen;
1506  address.transport_name = tname;
1508  ve = find_validation_entry (&address);
1509  if ((NULL == ve) || (GNUNET_NO == ve->expecting_pong))
1510  {
1512  gettext_noop
1513  (
1514  "# PONGs dropped, no matching pending validation"),
1515  1, GNUNET_NO);
1516  return GNUNET_OK;
1517  }
1518  /* now check that PONG is well-formed */
1519  if (0 != memcmp (&ve->address->peer,
1520  sender,
1521  sizeof(struct GNUNET_PeerIdentity)))
1522  {
1523  GNUNET_break_op (0);
1524  return GNUNET_SYSERR;
1525  }
1526  if (0 ==
1529  {
1531  gettext_noop
1532  ("# PONGs dropped, signature expired"), 1,
1533  GNUNET_NO);
1534  return GNUNET_SYSERR;
1535  }
1536 
1537  sig_res = GNUNET_SYSERR;
1538  do_verify = GNUNET_YES;
1541  {
1542  /* We have a cached and valid signature for this peer,
1543  * try to compare instead of verify */
1544  if (0 == memcmp (&ve->pong_sig_cache,
1545  &pong->signature,
1546  sizeof(struct GNUNET_CRYPTO_EddsaSignature)))
1547  {
1548  /* signatures are identical, we can skip verification */
1549  sig_res = GNUNET_OK;
1550  do_verify = GNUNET_NO;
1551  }
1552  else
1553  {
1554  sig_res = GNUNET_SYSERR;
1555  /* signatures do not match, we have to verify */
1556  }
1557  }
1558 
1559  if (GNUNET_YES == do_verify)
1560  {
1561  /* Do expensive verification */
1562  sig_res = GNUNET_CRYPTO_eddsa_verify (
1564  &pong->purpose,
1565  &pong->signature,
1566  &ve->address->peer.public_key);
1567  if (sig_res == GNUNET_SYSERR)
1568  {
1569  GNUNET_break_op (0);
1571  "Failed to verify: invalid signature on address `%s':%s from peer `%s'\n",
1572  tname,
1573  GST_plugins_a2s (ve->address),
1574  GNUNET_i2s (sender));
1575  }
1576  }
1577  if (sig_res == GNUNET_SYSERR)
1578  {
1579  GNUNET_break_op (0);
1580  return GNUNET_SYSERR;
1581  }
1582 
1584  "Validation process successful for peer `%s' with plugin `%s' address `%s'\n",
1585  GNUNET_i2s (sender),
1586  tname,
1587  GST_plugins_a2s (ve->address));
1589  gettext_noop ("# validations succeeded"),
1590  1,
1591  GNUNET_NO);
1592  /* validity achieved, remember it! */
1593  ve->expecting_pong = GNUNET_NO;
1595  ve->pong_sig_cache = pong->signature;
1598  {
1599  if (GNUNET_YES == ve->known_to_ats)
1600  {
1605  }
1606  else
1607  {
1608  struct GNUNET_ATS_Properties prop;
1609 
1610  memset (&prop, 0, sizeof(prop));
1612  prop.scope = ve->network;
1613  prop.delay = GNUNET_TIME_relative_divide (ve->latency, 2);
1616  ve->known_to_ats = GNUNET_YES;
1617  GST_ats_add_address (ve->address, &prop);
1620  }
1621  }
1622  if (validations_running > 0)
1623  {
1626  gettext_noop ("# validations running"),
1628  GNUNET_NO);
1630  "Validation finished, %u validation processes running\n",
1632  }
1633  else
1634  {
1635  GNUNET_break (0);
1636  }
1637 
1638  /* Notify about new validity */
1641 
1642  /* build HELLO to store in PEERINFO */
1644  gettext_noop ("# HELLOs given to peerinfo"),
1645  1,
1646  GNUNET_NO);
1647  ve->copied = GNUNET_NO;
1648  hello = GNUNET_HELLO_create (&ve->address->peer.public_key,
1650  ve,
1651  GNUNET_NO);
1652  GNUNET_break (NULL !=
1654  hello,
1655  NULL,
1656  NULL));
1657  GNUNET_free (hello);
1658  return GNUNET_OK;
1659 }
1660 
1661 
1669 int
1671 {
1672  const struct GNUNET_HELLO_Message *hm =
1673  (const struct GNUNET_HELLO_Message *) hello;
1674  struct GNUNET_PeerIdentity pid;
1675  int friend;
1676 
1677  friend = GNUNET_HELLO_is_friend_only (hm);
1678  if (((GNUNET_YES != friend) &&
1679  (GNUNET_NO != friend)) ||
1680  (GNUNET_OK != GNUNET_HELLO_get_id (hm, &pid)))
1681  {
1682  /* malformed HELLO */
1683  GNUNET_break_op (0);
1684  return GNUNET_SYSERR;
1685  }
1686  if (0 ==
1687  memcmp (&GST_my_identity,
1688  &pid,
1689  sizeof(struct GNUNET_PeerIdentity)))
1690  {
1691  /* got our own HELLO, how boring */
1693  "Validation received our own HELLO (%s), ignoring\n",
1694  GNUNET_i2s (&pid));
1695  return GNUNET_OK;
1696  }
1698  "Validation received HELLO message for peer `%s' with size %u, checking for new addresses\n",
1699  GNUNET_i2s (&pid),
1700  ntohs (hello->size));
1701  GNUNET_assert (NULL ==
1703  GNUNET_NO,
1705  NULL));
1706  return GNUNET_OK;
1707 }
1708 
1709 
1713 struct IteratorContext
1714 {
1719 
1723  void *cb_cls;
1724 };
1725 
1726 
1735 static int
1737  const struct GNUNET_PeerIdentity *key,
1738  void *value)
1739 {
1740  struct IteratorContext *ic = cls;
1741  struct ValidationEntry *ve = value;
1742 
1743  ic->cb (ic->cb_cls,
1744  ve->valid_until,
1745  ve->revalidation_block,
1746  ve->address);
1747  return GNUNET_OK;
1748 }
1749 
1750 
1759 void
1762  void *cb_cls)
1763 {
1764  struct IteratorContext ic;
1765 
1766  ic.cb = cb;
1767  ic.cb_cls = cb_cls;
1769  target,
1770  &iterate_addresses, &ic);
1771 }
1772 
1773 
1783 void
1785  int in_use)
1786 {
1787  struct ValidationEntry *ve;
1788 
1789  if (GNUNET_HELLO_address_check_option (address,
1791  return; /* ignore inbound for validation */
1792  if (NULL == GST_plugins_find (address->transport_name))
1793  {
1794  /* How can we use an address for which we don't have the plugin? */
1795  GNUNET_break (0);
1796  return;
1797  }
1798  ve = find_validation_entry (address);
1799  if (NULL == ve)
1800  {
1801  GNUNET_break (0);
1802  return;
1803  }
1804  if (in_use == ve->in_use)
1805  return;
1806  ve->in_use = in_use;
1807  if (GNUNET_YES == in_use)
1808  {
1809  /* from now on, higher frequeny, so reschedule now */
1810  if (NULL != ve->revalidation_task)
1813  ve);
1814  }
1815 }
1816 
1817 
1818 /* end of file gnunet-service-transport_validation.c */
#define CONNECTED_PING_FREQUENCY
How often do we PING an address that we are currently using?
static struct GNUNET_PeerIdentity GST_my_identity
Our public key.
size_t address_length
Number of bytes in address.
GST_ValidationAddressCallback cb
Function to call on each address.
int GNUNET_HELLO_get_id(const struct GNUNET_HELLO_Message *hello, struct GNUNET_PeerIdentity *peer)
Get the peer identity from a HELLO message.
Definition: hello.c:671
struct GNUNET_TIME_Absolute revalidation_block
How long until we can try to validate this address again? FOREVER if the address is for an unsupporte...
enum GNUNET_HELLO_AddressInfo local_info
Extended information about address.
A HELLO message is used to exchange information about transports with other peers.
static void ping(void *cls)
Send a ping to destination.
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:673
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only)...
void(* GST_ValidationAddressCallback)(void *cls, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute validation_block, const struct GNUNET_HELLO_Address *address)
Function called for each address (or address status change) that the validation module is aware of (f...
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
uint64_t rel_value_us
The actual value.
Context we use when performing a blacklist check.
struct GNUNET_TIME_Absolute valid_until
Until when is this address valid? ZERO if it is not currently considered valid.
void GST_validation_start(unsigned int max_fds)
Start the validation subsystem.
int expecting_pong
Are we expecting a PONG message for this validation entry?
const void * address
Binary representation of the address (plugin-specific).
#define GNUNET_MESSAGE_TYPE_TRANSPORT_PING
Transport PING message.
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
struct GNUNET_HELLO_Message * GNUNET_HELLO_create(const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, GNUNET_HELLO_GenerateAddressListCallback addrgen, void *addrgen_cls, int friend_only)
Construct a HELLO message given the public key, expiration time and an iterator that spews the transp...
Definition: hello.c:204
Context for the info handler.
static int validation_entry_match(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterate over validation entries until a matching one is found.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
struct GST_BlacklistCheck * GST_blacklist_test_allowed(const struct GNUNET_PeerIdentity *peer, const char *transport_name, GST_BlacklistTestContinuation cont, void *cont_cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
Test if a peer/transport combination is blacklisted.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PONG.
int copied
When passing the address in add_valid_peer_address(), did we copy the address to the HELLO yet...
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
int GST_validation_handle_ping(const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *hdr, const struct GNUNET_HELLO_Address *sender_address, struct GNUNET_ATS_Session *session)
We&#39;ve received a PING.
static void timeout_hello_validation(void *cls)
Address validation cleanup task.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int in_use
Are we currently using this address for a connection?
void GST_validation_get_addresses(const struct GNUNET_PeerIdentity *target, GST_ValidationAddressCallback cb, void *cb_cls)
Call the given function for each address for the given target.
static struct GNUNET_TIME_Absolute validation_next
When is next validation allowed.
struct GNUNET_CRYPTO_EddsaSignature signature
Signature.
Information about an address under validation.
void GST_ats_add_address(const struct GNUNET_HELLO_Address *address, const struct GNUNET_ATS_Properties *prop)
Notify ATS about the new address including the network this address is located in.
void GNUNET_PEERINFO_notify_cancel(struct GNUNET_PEERINFO_NotifyContext *nc)
Stop notifying about changes.
const struct GNUNET_HELLO_Address * address
Address we&#39;re interested in.
int known_to_ats
Is this address known to ATS as valid right now?
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
int GNUNET_CRYPTO_eddsa_sign(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition: crypto_ecc.c:987
static ssize_t add_valid_peer_address(void *cls, size_t max, void *buf)
Add the validated peer address to the HELLO.
#define UNVALIDATED_PING_KEEPALIVE
How often do we allow PINGing an address that we have not yet validated? This also determines how lon...
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
interfacing between transport and ATS service
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_NO
Definition: gnunet_common.h:78
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
int GST_validation_handle_hello(const struct GNUNET_MessageHeader *hello)
We&#39;ve received a HELLO, check which addresses are new and trigger validation.
static int iterate_addresses(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Call the callback in the closure for each validation entry.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GST_validation_stop()
Stop the validation subsystem.
#define PONG_PRIORITY
Priority to use for PONGs.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
uint32_t challenge
Challenge number we used.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
uint32_t addrlen
Size of address appended to this message (part of what is being signed, hence not redundant)...
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
static void publish_ve_stat_update()
Provide an update on the validation_map map size to statistics.
static struct ValidationEntry * find_validation_entry(const struct GNUNET_HELLO_Address *address)
Find a ValidationEntry entry for the given neighbour that matches the given address and transport...
Time for absolute time used by GNUnet, in microseconds and in network byte order. ...
static void validation_entry_changed(struct ValidationEntry *ve, enum GNUNET_TRANSPORT_ValidationState state)
A validation entry changed.
int GST_hello_test_address(const struct GNUNET_HELLO_Address *address, struct GNUNET_CRYPTO_EddsaSignature **sig, struct GNUNET_TIME_Absolute **sig_expiration)
Test if a particular address is one of ours.
ATS performance characteristics for an address.
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:35
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
static void multicast_pong(void *cls, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute validation_block, const struct GNUNET_HELLO_Address *address)
Send the given PONG to the given address.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct GNUNET_PEERINFO_NotifyContext * GNUNET_PEERINFO_notify(const struct GNUNET_CONFIGURATION_Handle *cfg, int include_friend_only, GNUNET_PEERINFO_Processor callback, void *callback_cls)
Call a method whenever our known information about peers changes.
struct GNUNET_TIME_Relative latency
Last observed latency for this address (round-trip), delay between last PING sent and PONG received; ...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_SCHEDULER_Task * revalidation_task
ID of task that will trigger address revalidation.
static int cleanup_validation_entry(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterate over validation entries and free them.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
int GNUNET_HELLO_address_check_option(const struct GNUNET_HELLO_Address *address, enum GNUNET_HELLO_AddressInfo option)
Check if an address has a local option set.
Definition: address.c:39
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:130
Closure for the neighbours_iterate() function.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1253
Message used to ask a peer to validate receipt (to check an address from a HELLO).
int GST_validation_handle_pong(const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *hdr)
We&#39;ve received a PONG.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
static struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
enum State state
current state of profiling
void * cls
Closure for all of the callbacks.
int GNUNET_CRYPTO_eddsa_verify(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EddsaSignature *sig, const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Verify EdDSA signature.
Definition: crypto_ecc.c:1114
#define ACCEPTABLE_PING_DELAY
How much delay is acceptable for sending the PING or PONG?
static char * value
Value of the record to add/remove.
static unsigned int validations_running
Number of validations running; any PING that was not yet matched by a PONG and for which we have not ...
#define VALIDATION_MAP_SIZE
Size of the validation map hashmap.
struct GNUNET_HELLO_Message * GNUNET_HELLO_iterate_addresses(const struct GNUNET_HELLO_Message *msg, int return_modified, GNUNET_HELLO_AddressIterator it, void *it_cls)
Iterate over all of the addresses in the HELLO.
Definition: hello.c:254
Session handle for connections.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
This is an inbound address and cannot be used to initiate an outbound connection to another peer...
Message used to validate a HELLO.
static void process_peerinfo_hello(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg)
Function called for any HELLO known to PEERINFO.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1280
neighbour manipulation API, allows manipulation of performance metrics (delay and towards ATS) ...
Context for the validation entry match function.
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
void GST_validation_set_address_use(const struct GNUNET_HELLO_Address *address, int in_use)
Update if we are using an address for a connection actively right now.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:687
void GST_neighbours_notify_data_sent(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, size_t size)
Track information about data we transmitted using the given address and session (used to notify ATS a...
static int add_valid_address(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
Iterator which adds the given address to the set of validated addresses.
struct GNUNET_PeerIdentity sender
To whom are we talking to (set to our identity if we are still waiting for the welcome message) ...
Randomness for IVs etc.
static char buf[2048]
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition: time.c:317
const char * transport_name
Name of the transport plugin enabling the communication using this address.
struct GNUNET_TIME_Relative delay
Delay.
static int result
Global testing status.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:442
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
void GST_ats_expire_address(const struct GNUNET_HELLO_Address *address)
Notify ATS that the address has expired and thus cannot be used any longer.
struct GNUNET_SCHEDULER_Task * timeout_task
ID of task that will clean up this entry if nothing happens.
const char * GST_plugins_a2s(const struct GNUNET_HELLO_Address *address)
Convert a given address to a human-readable format.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
Internal representation of the hash map.
static struct GNUNET_CONTAINER_MultiPeerMap * validation_map
Map of PeerIdentities to &#39;struct ValidationEntry*&#39;s (addresses of the given peer that we are currentl...
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
struct GNUNET_TRANSPORT_PluginFunctions * GST_plugins_find(const char *name)
Obtain the plugin API based on a plugin name.
struct GNUNET_MQ_Envelope * GNUNET_PEERINFO_add_peer(struct GNUNET_PEERINFO_Handle *h, const struct GNUNET_HELLO_Message *hello, GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
Add a host to the persistent list.
Definition: peerinfo_api.c:553
uint32_t challenge
Challenge code from PING (showing freshness).
static char * expiration
Credential TTL.
Definition: gnunet-abd.c:96
int GST_ats_is_known_no_session(const struct GNUNET_HELLO_Address *address)
Test if ATS knows about this address.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
struct GNUNET_CRYPTO_EddsaSignature pong_sig_cache
Cached PONG signature.
static void pong(struct GNUNET_CADET_Channel *channel, const struct CadetPingMessage *ping)
Reply with a pong to origin.
size_t GNUNET_HELLO_add_address(const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration, char *target, size_t max)
Copy the given address information into the given buffer using the format of HELLOs.
Definition: hello.c:109
static struct GNUNET_TIME_Relative validation_delay
Minimum delay between to validations.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:272
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
GST_NeighbourIterator cb
Function to call on each connected neighbour.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:67
int GNUNET_HELLO_is_friend_only(const struct GNUNET_HELLO_Message *h)
Return HELLO type.
Definition: hello.c:89
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN to confirm that this is a plausible address for the signi...
void GST_blacklist_test_cancel(struct GST_BlacklistCheck *bc)
Cancel a blacklist check.
#define VALIDATED_PING_FREQUENCY
How often do we PING an address that we have successfully validated in the past but are not actively ...
struct GNUNET_PeerIdentity peer
For which peer is this an address?
#define PONG_SIGNATURE_LIFETIME
How long is a PONG signature valid? We&#39;ll recycle a signature until 1/4 of this time is remaining...
an ECC signature using EdDSA.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
static int validate_address_iterator(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
Iterator callback to go over all addresses and try to validate them (unless blocked or already valida...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_PONG
Transport PONG message.
enum GNUNET_NetworkType scope
Which network scope does the respective address belong to? This property does not change...
Allow multiple values with the same key.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don&#39;t receive messages from the peer...
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
static struct GNUNET_CRYPTO_EddsaPrivateKey * GST_my_private_key
Our private key.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition: time.c:579
enum GNUNET_TRANSPORT_ValidationState state
Current state of this validation entry.
const struct GNUNET_MessageHeader * GST_hello_get()
Obtain this peers HELLO message.
#define HELLO_ADDRESS_EXPIRATION
After how long do we expire an address in a HELLO that we just validated? This value is also used for...
The identity of the host (wraps the signing key of the peer).
No additional information.
struct GNUNET_TIME_Absolute next_validation
At what time do we send the next validation request (PING)?
#define PING_PRIORITY
Priority to use for PINGs.
struct GST_BlacklistCheck * bc
Handle to the blacklist check (if we&#39;re currently in it).
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to &#39;struct&#39;s...
#define GNUNET_PACKED
gcc-ism to get packed structs.
struct GNUNET_PEERINFO_Handle * GST_peerinfo
Handle to peerinfo service.
struct ValidationEntry * ve
Where to store the result?
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:375
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN
Signature for confirming that this peer uses a particular address.
static struct GNUNET_PEERINFO_NotifyContext * pnc
Context for peerinfo iteration.
An address for communicating with a peer.
void GST_ats_update_delay(const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Relative delay)
Notify ATS about delay changes to properties of an address.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:109
Automatic transport selection and outbound bandwidth determination.
struct GNUNET_TIME_Absolute pong_sig_valid_until
Until when is the cached PONG signature valid? ZERO if it is not currently considered valid...
GNUNET_TRANSPORT_ValidationState
Current state of a validation process.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
enum GNUNET_NetworkType network
Which network type does our address belong to?
Header for all communications.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:527
Time for absolute times used by GNUnet, in microseconds.
static void revalidate_address(void *cls)
Do address validation again to keep address valid.
#define GNUNET_YES
Definition: gnunet_common.h:77
static const struct GNUNET_CONFIGURATION_Handle * GST_cfg
Configuration handle.
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PING.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
static void transmit_ping_if_allowed(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_HELLO_Address *address_null, struct GNUNET_ATS_Session *session_null, int result)
Function called with the result from blacklisting.
GNUNET_TRANSPORT_CheckAddress check_address
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
uint32_t challenge
Challenge code (to ensure fresh reply).
static unsigned int validations_fast_start_threshold
Validition fast start threshold.
struct GNUNET_TIME_Absolute send_time
At what time did we send the latest validation request (PING)?
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:657
static char * address
GNS address for this phone.
#define GNUNET_TIME_UNIT_MICROSECONDS
One microsecond, our basic time unit.
struct GNUNET_PeerIdentity target
Who is the intended recipient?
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_HELLO_address_free(addr)
Free an address.
void GST_validation_handle_address(const struct GNUNET_HELLO_Address *address)
Validate an individual address.
static char * plugin_name
Name of our plugin.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_malloc(size)
Wrapper around malloc.
void GST_ats_new_session(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
Notify ATS about a new session now existing for the given address.
struct GNUNET_TIME_AbsoluteNBO expiration
When does this signature expire?
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_HELLO_Address * address
The address.
Time for relative time used by GNUnet, in microseconds.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
#define gettext_noop(String)
Definition: gettext.h:69
Category of last resort.
Definition: gnunet_nt_lib.h:40
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966