GNUnet  0.10.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 
52 
59 
66 
73 
80 };
81 
82 
83 
84 
92 #define PONG_SIGNATURE_LIFETIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_HOURS, 1)
93 
99 #define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_HOURS, 12)
100 
107 #define UNVALIDATED_PING_KEEPALIVE GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
108 
114 #define VALIDATED_PING_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 15)
115 
119 #define CONNECTED_PING_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
120 
124 #define ACCEPTABLE_PING_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 1)
125 
129 #define VALIDATION_MAP_SIZE 256
130 
134 #define PING_PRIORITY 2
135 
139 #define PONG_PRIORITY 4
140 
141 
143 
155 
160 
165 };
166 
167 
183 
189 
194 
200 
205 
210  uint32_t addrlen GNUNET_PACKED;
211 };
213 
222 
227 
231  struct GNUNET_CRYPTO_EddsaSignature pong_sig_cache;
232 
237 
242 
246  struct GNUNET_TIME_Absolute send_time;
247 
251  struct GNUNET_TIME_Absolute next_validation;
252 
257  struct GNUNET_TIME_Absolute valid_until;
258 
263  struct GNUNET_TIME_Absolute pong_sig_valid_until;
264 
271  struct GNUNET_TIME_Absolute revalidation_block;
272 
277  struct GNUNET_TIME_Relative latency;
278 
283 
287  uint32_t challenge;
288 
293  int copied;
294 
298  int in_use;
299 
304 
309 
313  enum GNUNET_NetworkType network;
314 };
315 
316 
323 
328 
333 
339 static unsigned int validations_running;
340 
345 
350 
351 
360 
365 };
366 
367 
373 static void
375 {
377  gettext_noop("# Addresses in validation map"),
378  GNUNET_CONTAINER_multipeermap_size(validation_map),
379  GNUNET_NO);
380 }
381 
382 
392 static int
394  const struct GNUNET_PeerIdentity *key,
395  void *value)
396 {
397  struct ValidationEntryMatchContext *vemc = cls;
398  struct ValidationEntry *ve = value;
399 
400  if (0 == GNUNET_HELLO_address_cmp(ve->address,
401  vemc->address))
402  {
403  vemc->ve = ve;
404  return GNUNET_NO;
405  }
406  return GNUNET_YES;
407 }
408 
409 
417 static void
420 {
421  ve->state = state;
422 }
423 
424 
433 static int
435  const struct GNUNET_PeerIdentity *key,
436  void *value)
437 {
438  struct ValidationEntry *ve = value;
439 
442 
443  /* Notify about deleted entry */
446 
447  if (NULL != ve->bc)
448  {
450  ve->bc = NULL;
451  }
454  &ve->address->peer,
455  ve));
457  if (GNUNET_YES == ve->known_to_ats)
458  {
462  ve->known_to_ats = GNUNET_NO;
463  }
465  if (NULL != ve->timeout_task)
466  {
468  ve->timeout_task = NULL;
469  }
470  if (NULL != ve->revalidation_task)
471  {
473  ve->revalidation_task = NULL;
474  }
475  if ((GNUNET_YES == ve->expecting_pong) &&
476  (validations_running > 0))
477  {
480  gettext_noop("# validations running"),
482  GNUNET_NO);
483  }
484  GNUNET_free(ve);
485  return GNUNET_OK;
486 }
487 
488 
495 static void
497 {
498  struct ValidationEntry *ve = cls;
499  struct GNUNET_TIME_Absolute max;
500  struct GNUNET_TIME_Relative left;
501 
502  ve->timeout_task = NULL;
503  /* For valid addresses, we want to wait until the expire;
504  for addresses under PING validation, we want to wait
505  until we give up on the PING */
507  ve->revalidation_block);
509  if (left.rel_value_us > 0)
510  {
511  /* We should wait a bit longer. This happens when
512  address lifetimes are extended due to successful
513  validations. */
514  ve->timeout_task =
517  ve);
518  return;
519  }
521  gettext_noop("# address records discarded (timeout)"),
522  1,
523  GNUNET_NO);
525  &ve->address->peer,
526  ve);
527 }
528 
529 
542 static void
544  const struct GNUNET_PeerIdentity *pid,
545  const struct GNUNET_HELLO_Address *address_null,
546  struct GNUNET_ATS_Session *session_null,
547  int result)
548 {
549  struct ValidationEntry *ve = cls;
550  struct TransportPingMessage ping;
552  struct GNUNET_TIME_Absolute next;
553  const struct GNUNET_MessageHeader *hello;
554  ssize_t ret;
555  size_t tsize;
556  size_t slen;
557  uint16_t hsize;
558  struct GNUNET_ATS_Session *session;
559 
560  ve->bc = NULL;
561  if (GNUNET_OK != result)
562  {
564  "Blacklist denies sending PING to `%s' `%s' `%s'\n",
565  GNUNET_i2s(pid),
567  ve->address->transport_name);
569  gettext_noop("# address records discarded (blacklist)"),
570  1,
571  GNUNET_NO);
573  pid,
574  ve);
575  return;
576  }
577  hello = GST_hello_get();
578  GNUNET_assert(NULL != hello);
579  slen = strlen(ve->address->transport_name) + 1;
580  hsize = ntohs(hello->size);
581  tsize = sizeof(struct TransportPingMessage) +
582  ve->address->address_length + slen + hsize;
583 
584  ping.header.size =
585  htons(sizeof(struct TransportPingMessage) +
586  ve->address->address_length + slen);
588  ping.challenge = htonl(ve->challenge);
589  ping.target = *pid;
590 
591  if (tsize >= GNUNET_MAX_MESSAGE_SIZE)
592  {
593  GNUNET_break(0);
594  hsize = 0;
595  tsize =
596  sizeof(struct TransportPingMessage) + ve->address->address_length +
597  slen + hsize;
598  }
599  {
600  char message_buf[tsize] GNUNET_ALIGN;
601 
602  GNUNET_memcpy(message_buf,
603  hello,
604  hsize);
605  GNUNET_memcpy(&message_buf[hsize],
606  &ping,
607  sizeof(struct TransportPingMessage));
608  GNUNET_memcpy(&message_buf[sizeof(struct TransportPingMessage) + hsize],
609  ve->address->transport_name,
610  slen);
611  GNUNET_memcpy(&message_buf[sizeof(struct TransportPingMessage) + slen + hsize],
612  ve->address->address,
613  ve->address->address_length);
614  papi = GST_plugins_find(ve->address->transport_name);
615  GNUNET_assert(NULL != papi);
616  session = papi->get_session(papi->cls,
617  ve->address);
618  if (NULL == session)
619  {
620  /* Could not get a valid session */
622  "Failed to get session to send PING to `%s' at `%s'\n",
623  GNUNET_i2s(pid),
624  GST_plugins_a2s(ve->address));
625  return;
626  }
627 
628  ret = papi->send(papi->cls, session,
629  message_buf, tsize,
632  NULL, NULL);
633  if (-1 == ret)
634  {
636  "Failed to send PING to `%s' at `%s'\n",
637  GNUNET_i2s(pid),
638  GST_plugins_a2s(ve->address));
639  return;
640  }
642  "Transmitted plain PING to `%s' `%s' `%s'\n",
643  GNUNET_i2s(pid),
644  GST_plugins_a2s(ve->address),
645  ve->address->transport_name);
646  ve->network = papi->get_network(papi->cls,
647  session);
648  GNUNET_break(GNUNET_NT_UNSPECIFIED != ve->network);
650  session,
651  tsize);
655  ve->send_time = GNUNET_TIME_absolute_get();
657  gettext_noop("# PINGs for address validation sent"),
658  1,
659  GNUNET_NO);
660  ve->expecting_pong = GNUNET_YES;
663  "Validation started, %u validation processes running\n",
666  gettext_noop("# validations running"),
668  GNUNET_NO);
669  /* Notify about PING sent */
672  }
673 }
674 
675 
681 static void
683 {
684  struct ValidationEntry *ve = cls;
685  struct GNUNET_TIME_Relative canonical_delay;
686  struct GNUNET_TIME_Relative delay;
687  struct GNUNET_TIME_Relative blocked_for;
688  struct GST_BlacklistCheck *bc;
689  uint32_t rdelay;
690 
691  ve->revalidation_task = NULL;
693  /* Considering current connectivity situation, what is the maximum
694  block period permitted? */
695  if (GNUNET_YES == ve->in_use)
696  canonical_delay = CONNECTED_PING_FREQUENCY;
698  canonical_delay = VALIDATED_PING_FREQUENCY;
699  else
700  canonical_delay = UNVALIDATED_PING_KEEPALIVE;
701  /* Use delay that is MIN of original delay and possibly adjusted
702  new maximum delay (which may be lower); the real delay
703  is originally randomized between "canonical_delay" and "2 * canonical_delay",
704  so continue to permit that window for the operation. */
705  delay = GNUNET_TIME_relative_min(delay,
706  GNUNET_TIME_relative_multiply(canonical_delay,
707  2));
709  if (delay.rel_value_us > 0)
710  {
711  /* should wait a bit longer */
713  "Waiting for %s longer before (re)validating address `%s'\n",
715  GNUNET_YES),
716  GST_plugins_a2s(ve->address));
717  ve->revalidation_task =
719  &revalidate_address, ve);
721  return;
722  }
723  /* check if globally we have too many active validations at a
724  too high rate, if so, delay ours */
727  (blocked_for.rel_value_us > 0))
728  {
729  /* Validations are blocked, have to wait for blocked_for time */
731  "Validations blocked for another %s, delaying validating address `%s'\n",
733  GNUNET_YES),
734  GST_plugins_a2s(ve->address));
736  gettext_noop("# validations delayed by global throttle"),
737  1,
738  GNUNET_NO);
739  ve->revalidation_task =
740  GNUNET_SCHEDULER_add_delayed(blocked_for,
742  ve);
744  return;
745  }
746 
747  /* We are good to go; remember to not go again for `canonical_delay` time;
748  add up to `canonical_delay` to randomize start time */
750  /* schedule next PINGing with some extra random delay to avoid synchronous re-validations */
751  rdelay =
753  canonical_delay.rel_value_us);
754 
755  delay = GNUNET_TIME_relative_add(canonical_delay,
758  rdelay));
759 
761  "Validating now, next scheduled for %s, now validating address `%s'\n",
763  GNUNET_YES),
764  GST_plugins_a2s(ve->address));
765  ve->revalidation_task =
768  ve);
770 
771  /* start PINGing by checking blacklist */
773  gettext_noop("# address revalidations started"), 1,
774  GNUNET_NO);
775  if (NULL != ve->bc)
776  {
778  ve->bc = NULL;
779  }
781  ve->address->transport_name,
783  ve,
784  NULL,
785  NULL);
786  if (NULL != bc)
787  {
788  /* If transmit_ping_if_allowed was already called it may have freed ve,
789  * so only set ve->bc if it has not been called.
790  */
791  ve->bc = bc;
792  }
793 }
794 
795 
805 static struct ValidationEntry *
807 {
808  struct ValidationEntryMatchContext vemc;
809  struct ValidationEntry *ve;
810 
811  vemc.ve = NULL;
812  vemc.address = address;
814  &address->peer,
815  &validation_entry_match, &vemc);
816  if (NULL != (ve = vemc.ve))
817  return ve;
819  GST_ats_is_known_no_session(address));
820  ve = GNUNET_new(struct ValidationEntry);
821  ve->in_use = GNUNET_SYSERR; /* not defined */
822  ve->address = GNUNET_HELLO_address_copy(address);
824  memset(&ve->pong_sig_cache,
825  '\0',
826  sizeof(struct GNUNET_CRYPTO_EddsaSignature));
828  ve->challenge =
830  ve->timeout_task =
833  ve);
834  GNUNET_CONTAINER_multipeermap_put(validation_map,
835  &address->peer,
836  ve,
841  return ve;
842 }
843 
844 
856 static int
858  const struct GNUNET_HELLO_Address *address,
860 {
861  const struct GNUNET_HELLO_Message *hello = cls;
862  struct ValidationEntry *ve;
863  struct GNUNET_PeerIdentity pid;
864  struct GNUNET_ATS_Properties prop;
866 
867  if (0 == GNUNET_TIME_absolute_get_remaining(expiration).rel_value_us)
868  return GNUNET_OK; /* expired */
869  if (GNUNET_OK != GNUNET_HELLO_get_id(hello, &pid))
870  {
871  GNUNET_break(0);
872  return GNUNET_OK; /* invalid HELLO !? */
873  }
874  if (NULL == (papi = GST_plugins_find(address->transport_name)))
875  {
876  /* might have been valid in the past, but we don't have that
877  plugin loaded right now */
878  return GNUNET_OK;
879  }
880  if (NULL ==
881  papi->address_to_string(papi->cls,
882  address->address,
883  address->address_length))
884  {
885  /* Why do we try to add an ill-formed address? */
886  GNUNET_break(0);
888  "Address with %u bytes for plugin %s and peer %s is malformed\n",
889  (unsigned int)address->address_length,
890  address->transport_name,
891  GNUNET_i2s(&pid));
892  return GNUNET_OK;
893  }
894 
895  ve = find_validation_entry(address);
896  ve->network = papi->get_network_for_address(papi->cls,
897  address);
900  expiration);
901  if (NULL == ve->revalidation_task)
902  {
904  "Starting revalidations for valid address `%s'\n",
905  GST_plugins_a2s(ve->address));
908  }
911  memset(&prop, 0, sizeof(prop));
912  prop.scope = ve->network;
914  if (GNUNET_YES != ve->known_to_ats)
915  {
916  ve->known_to_ats = GNUNET_YES;
917  GST_ats_add_address(address, &prop);
920  }
921  return GNUNET_OK;
922 }
923 
924 
934 static void
936  const struct GNUNET_PeerIdentity *peer,
937  const struct GNUNET_HELLO_Message *hello,
938  const char *err_msg)
939 {
940  GNUNET_assert(NULL != peer);
941  if (NULL == hello)
942  return;
943  if (0 == memcmp(&GST_my_identity,
944  peer,
945  sizeof(struct GNUNET_PeerIdentity)))
946  {
947  /* Peerinfo returned own identity, skip validation */
948  return;
949  }
951  "Handling HELLO for peer `%s'\n",
952  GNUNET_i2s(peer));
953  GNUNET_assert(NULL ==
956  (void *)hello));
957 }
958 
959 
965 void
966 GST_validation_start(unsigned int max_fds)
967 {
982  validations_fast_start_threshold = (max_fds / 2);
985  gettext_noop("# validations running"),
987  GNUNET_NO);
989  "Validation uses a fast start threshold of %u connections and a delay of %s\n",
992  GNUNET_YES));
994  GNUNET_NO);
996  &process_peerinfo_hello, NULL);
997 }
998 
999 
1003 void
1005 {
1008  NULL);
1009  GNUNET_CONTAINER_multipeermap_destroy(validation_map);
1010  validation_map = NULL;
1012 }
1013 
1014 
1026 static void
1028  struct GNUNET_TIME_Absolute valid_until,
1029  struct GNUNET_TIME_Absolute validation_block,
1030  const struct GNUNET_HELLO_Address *address)
1031 {
1032  struct TransportPongMessage *pong = cls;
1033  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1034  struct GNUNET_ATS_Session *session;
1035 
1036  papi = GST_plugins_find(address->transport_name);
1037  if (NULL == papi)
1038  {
1040  "Plugin %s not supported, cannot send PONG\n",
1041  address->transport_name);
1042  return;
1043  }
1044  GNUNET_assert(NULL != papi->send);
1045  GNUNET_assert(NULL != papi->get_session);
1046  session = papi->get_session(papi->cls, address);
1047  if (NULL == session)
1048  {
1049  GNUNET_break(0);
1050  return;
1051  }
1052  GST_ats_new_session(address, session);
1053  papi->send(papi->cls, session,
1054  (const char *)pong,
1055  ntohs(pong->header.size),
1056  PONG_PRIORITY,
1058  NULL, NULL);
1060  session,
1061  pong->header.size);
1062 }
1063 
1064 
1074 int
1076  const struct GNUNET_MessageHeader *hdr,
1077  const struct GNUNET_HELLO_Address *sender_address,
1078  struct GNUNET_ATS_Session *session)
1079 {
1080  const struct TransportPingMessage *ping;
1081  struct TransportPongMessage *pong;
1082  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1083  struct GNUNET_CRYPTO_EddsaSignature *sig_cache;
1084  struct GNUNET_TIME_Absolute *sig_cache_exp;
1085  const char *addr;
1086  const char *addrend;
1087  char *plugin_name;
1088  char *pos;
1089  size_t len_address;
1090  size_t len_plugin;
1091  ssize_t ret;
1092  struct GNUNET_HELLO_Address address;
1093 
1094  if (0 ==
1095  memcmp(&GST_my_identity,
1096  sender,
1097  sizeof(struct GNUNET_PeerIdentity)))
1098  return GNUNET_OK; /* our own, ignore! */
1099  if (ntohs(hdr->size) < sizeof(struct TransportPingMessage))
1100  {
1101  GNUNET_break_op(0);
1102  return GNUNET_SYSERR;
1103  }
1104  ping = (const struct TransportPingMessage *)hdr;
1105  if (0 !=
1106  memcmp(&ping->target,
1107  &GST_my_identity,
1108  sizeof(struct GNUNET_PeerIdentity)))
1109  {
1111  gettext_noop
1112  ("# PING message for different peer received"), 1,
1113  GNUNET_NO);
1114  return GNUNET_SYSERR;
1115  }
1117  gettext_noop("# PING messages received"), 1,
1118  GNUNET_NO);
1119  addr = (const char *)&ping[1];
1120  len_address = ntohs(hdr->size) - sizeof(struct TransportPingMessage);
1121  /* peer wants to confirm that this is one of our addresses, this is what is
1122  * used for address validation */
1123 
1124  sig_cache = NULL;
1125  sig_cache_exp = NULL;
1126  papi = NULL;
1127  if (len_address > 0)
1128  {
1129  addrend = memchr(addr, '\0', len_address);
1130  if (NULL == addrend)
1131  {
1132  GNUNET_break_op(0);
1133  return GNUNET_SYSERR;
1134  }
1135  addrend++;
1136  len_plugin = strlen(addr) + 1;
1137  len_address -= len_plugin;
1139  address.address = addrend;
1140  address.address_length = len_address;
1141  address.transport_name = addr;
1142  address.peer = GST_my_identity;
1143 
1144  if (NULL == address.transport_name)
1145  {
1146  GNUNET_break(0);
1147  }
1148 
1149  if (0 != strstr(address.transport_name, "_client"))
1150  {
1151  plugin_name = GNUNET_strdup(address.transport_name);
1152  pos = strstr(plugin_name, "_client");
1153  GNUNET_assert(NULL != pos);
1154  GNUNET_snprintf(pos, strlen("_server") + 1, "%s", "_server");
1155  }
1156  else
1157  plugin_name = GNUNET_strdup(address.transport_name);
1158 
1159  if (NULL == (papi = GST_plugins_find(plugin_name)))
1160  {
1161  /* we don't have the plugin for this address */
1163  _("Plugin `%s' not available, cannot confirm having this address\n"),
1164  plugin_name);
1165  GNUNET_free(plugin_name);
1166  return GNUNET_SYSERR;
1167  }
1168  GNUNET_free(plugin_name);
1169  if (GNUNET_OK !=
1170  papi->check_address(papi->cls,
1171  addrend,
1172  len_address))
1173  {
1175  gettext_noop
1176  ("# failed address checks during validation"), 1,
1177  GNUNET_NO);
1179  _("Address `%s' is not one of my addresses, not confirming PING\n"),
1180  GST_plugins_a2s(&address));
1181  return GNUNET_SYSERR;
1182  }
1183  else
1184  {
1186  gettext_noop
1187  ("# successful address checks during validation"), 1,
1188  GNUNET_NO);
1190  "Address `%s' is one of my addresses, confirming PING\n",
1191  GST_plugins_a2s(&address));
1192  }
1193 
1194  if (GNUNET_YES !=
1195  GST_hello_test_address(&address,
1196  &sig_cache,
1197  &sig_cache_exp))
1198  {
1200  _("Not confirming PING from peer `%s' with address `%s' since I cannot confirm having this address.\n"),
1201  GNUNET_i2s(sender),
1202  GST_plugins_a2s(&address));
1203  return GNUNET_SYSERR;
1204  }
1205  }
1206  else
1207  {
1208  addrend = NULL; /* make gcc happy */
1209  len_plugin = 0;
1210  static struct GNUNET_CRYPTO_EddsaSignature no_address_signature;
1211  static struct GNUNET_TIME_Absolute no_address_signature_expiration;
1212 
1213  sig_cache = &no_address_signature;
1214  sig_cache_exp = &no_address_signature_expiration;
1215  }
1216 
1218  "I am `%s', sending PONG to peer `%s'\n",
1220  GNUNET_i2s(sender));
1221 
1222  /* message with structure:
1223  * [TransportPongMessage][Transport name][Address] */
1224 
1225  pong = GNUNET_malloc(sizeof(struct TransportPongMessage) + len_address + len_plugin);
1226  pong->header.size =
1227  htons(sizeof(struct TransportPongMessage) + len_address + len_plugin);
1229  pong->purpose.size =
1230  htonl(sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) +
1231  sizeof(uint32_t) + sizeof(struct GNUNET_TIME_AbsoluteNBO) +
1232  len_address + len_plugin);
1234  GNUNET_memcpy(&pong->challenge, &ping->challenge, sizeof(ping->challenge));
1235  pong->addrlen = htonl(len_address + len_plugin);
1236  GNUNET_memcpy(&pong[1], addr, len_plugin); /* Copy transport plugin */
1237  if (len_address > 0)
1238  {
1239  GNUNET_assert(NULL != addrend);
1240  GNUNET_memcpy(&((char *)&pong[1])[len_plugin], addrend, len_address);
1241  }
1242  if (GNUNET_TIME_absolute_get_remaining(*sig_cache_exp).rel_value_us <
1243  PONG_SIGNATURE_LIFETIME.rel_value_us / 4)
1244  {
1245  /* create / update cached sig */
1247  "Creating PONG signature to indicate ownership.\n");
1249  pong->expiration = GNUNET_TIME_absolute_hton(*sig_cache_exp);
1250  if (GNUNET_OK !=
1252  sig_cache))
1253  {
1255  _("Failed to create PONG signature for peer `%s'\n"), GNUNET_i2s(sender));
1256  }
1257  }
1258  else
1259  {
1260  pong->expiration = GNUNET_TIME_absolute_hton(*sig_cache_exp);
1261  }
1262  pong->signature = *sig_cache;
1263 
1264  GNUNET_assert(NULL != sender_address);
1265 
1266  /* first see if the session we got this PING from can be used to transmit
1267  * a response reliably */
1268  if (NULL == papi)
1269  {
1270  ret = -1;
1271  }
1272  else
1273  {
1274  GNUNET_assert(NULL != papi->send);
1275  GNUNET_assert(NULL != papi->get_session);
1276  if (NULL == session)
1277  {
1278  session = papi->get_session(papi->cls, sender_address);
1279  }
1280  if (NULL == session)
1281  {
1282  GNUNET_break(0);
1283  ret = -1;
1284  }
1285  else
1286  {
1287  ret = papi->send(papi->cls, session,
1288  (const char *)pong,
1289  ntohs(pong->header.size),
1291  NULL, NULL);
1292  if (-1 != ret)
1293  GST_neighbours_notify_data_sent(sender_address,
1294  session,
1295  pong->header.size);
1296  }
1297  }
1298  if (-1 != ret)
1299  {
1301  "Transmitted PONG to `%s' via reliable mechanism\n",
1302  GNUNET_i2s(sender));
1303  /* done! */
1305  gettext_noop
1306  ("# PONGs unicast via reliable transport"), 1,
1307  GNUNET_NO);
1308  GNUNET_free(pong);
1309  return GNUNET_OK;
1310  }
1311 
1312  /* no reliable method found, try transmission via all known addresses */
1314  gettext_noop
1315  ("# PONGs multicast to all available addresses"), 1,
1316  GNUNET_NO);
1318  &multicast_pong, pong);
1319  GNUNET_free(pong);
1320  return GNUNET_OK;
1321 }
1322 
1323 
1329 void
1331 {
1332  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1333  struct ValidationEntry *ve;
1334 
1335  papi = GST_plugins_find(address->transport_name);
1336  if (NULL == papi)
1337  {
1338  /* This plugin is currently unvailable ... ignore */
1340  "No plugin available for %s\n",
1341  address->transport_name);
1342  return;
1343  }
1344  ve = find_validation_entry(address);
1345  if (NULL == ve->revalidation_task)
1346  {
1348  "Validation process started for fresh address `%s' of %s\n",
1349  GST_plugins_a2s(ve->address),
1350  GNUNET_i2s(&ve->address->peer));
1352  }
1353  else
1354  {
1356  "Validation already running for address `%s' of %s\n",
1357  GST_plugins_a2s(ve->address),
1358  GNUNET_i2s(&ve->address->peer));
1359  }
1360 }
1361 
1362 
1372 static int
1374  const struct GNUNET_HELLO_Address *address,
1376 {
1377  if (0 == GNUNET_TIME_absolute_get_remaining(expiration).rel_value_us)
1378  {
1380  "Skipping expired address from HELLO\n");
1381  return GNUNET_OK; /* expired */
1382  }
1384  return GNUNET_OK;
1385 }
1386 
1387 
1397 static ssize_t
1399  size_t max,
1400  void *buf)
1401 {
1402  struct ValidationEntry *ve = cls;
1403 
1404  if (GNUNET_YES == ve->copied)
1405  return GNUNET_SYSERR; /* Done */
1406  ve->copied = GNUNET_YES;
1407  return GNUNET_HELLO_add_address(ve->address,
1408  ve->valid_until,
1409  buf,
1410  max);
1411 }
1412 
1413 
1422 int
1424  const struct GNUNET_MessageHeader *hdr)
1425 {
1426  const struct TransportPongMessage *pong;
1427  struct ValidationEntry *ve;
1428  const char *tname;
1429  const char *addr;
1430  size_t addrlen;
1431  size_t slen;
1432  size_t size;
1433  struct GNUNET_HELLO_Message *hello;
1434  struct GNUNET_HELLO_Address address;
1435  int sig_res;
1436  int do_verify;
1437 
1438  if (0 ==
1439  memcmp(&GST_my_identity,
1440  sender,
1441  sizeof(struct GNUNET_PeerIdentity)))
1442  return GNUNET_OK; /* our own, ignore! */
1443 
1444  if (ntohs(hdr->size) < sizeof(struct TransportPongMessage))
1445  {
1446  GNUNET_break_op(0);
1447  return GNUNET_SYSERR;
1448  }
1450  gettext_noop("# PONG messages received"), 1,
1451  GNUNET_NO);
1452 
1453  /* message with structure:
1454  * [TransportPongMessage][Transport name][Address] */
1455 
1456  pong = (const struct TransportPongMessage *)hdr;
1457  tname = (const char *)&pong[1];
1458  size = ntohs(hdr->size) - sizeof(struct TransportPongMessage);
1459  addr = memchr(tname, '\0', size);
1460  if (NULL == addr)
1461  {
1462  GNUNET_break_op(0);
1463  return GNUNET_SYSERR;
1464  }
1465  addr++;
1466  slen = strlen(tname) + 1;
1467  addrlen = size - slen;
1468 
1469  if (NULL == GST_plugins_find(tname))
1470  {
1471  /* we got the PONG, but the transport plugin specified in it
1472  is not supported by this peer, so this cannot be a good
1473  PONG for us. */
1474  GNUNET_break_op(0);
1475  return GNUNET_OK;
1476  }
1477 
1478  address.peer = *sender;
1479  address.address = addr;
1480  address.address_length = addrlen;
1481  address.transport_name = tname;
1483  ve = find_validation_entry(&address);
1484  if ((NULL == ve) || (GNUNET_NO == ve->expecting_pong))
1485  {
1487  gettext_noop
1488  ("# PONGs dropped, no matching pending validation"),
1489  1, GNUNET_NO);
1490  return GNUNET_OK;
1491  }
1492  /* now check that PONG is well-formed */
1493  if (0 != memcmp(&ve->address->peer,
1494  sender,
1495  sizeof(struct GNUNET_PeerIdentity)))
1496  {
1497  GNUNET_break_op(0);
1498  return GNUNET_SYSERR;
1499  }
1500  if (0 ==
1503  {
1505  gettext_noop
1506  ("# PONGs dropped, signature expired"), 1,
1507  GNUNET_NO);
1508  return GNUNET_SYSERR;
1509  }
1510 
1511  sig_res = GNUNET_SYSERR;
1512  do_verify = GNUNET_YES;
1514  {
1515  /* We have a cached and valid signature for this peer,
1516  * try to compare instead of verify */
1517  if (0 == memcmp(&ve->pong_sig_cache,
1518  &pong->signature,
1519  sizeof(struct GNUNET_CRYPTO_EddsaSignature)))
1520  {
1521  /* signatures are identical, we can skip verification */
1522  sig_res = GNUNET_OK;
1523  do_verify = GNUNET_NO;
1524  }
1525  else
1526  {
1527  sig_res = GNUNET_SYSERR;
1528  /* signatures do not match, we have to verify */
1529  }
1530  }
1531 
1532  if (GNUNET_YES == do_verify)
1533  {
1534  /* Do expensive verification */
1536  &pong->purpose,
1537  &pong->signature,
1538  &ve->address->peer.public_key);
1539  if (sig_res == GNUNET_SYSERR)
1540  {
1541  GNUNET_break_op(0);
1543  "Failed to verify: invalid signature on address `%s':%s from peer `%s'\n",
1544  tname,
1545  GST_plugins_a2s(ve->address),
1546  GNUNET_i2s(sender));
1547  }
1548  }
1549  if (sig_res == GNUNET_SYSERR)
1550  {
1551  GNUNET_break_op(0);
1552  return GNUNET_SYSERR;
1553  }
1554 
1556  "Validation process successful for peer `%s' with plugin `%s' address `%s'\n",
1557  GNUNET_i2s(sender),
1558  tname,
1559  GST_plugins_a2s(ve->address));
1561  gettext_noop("# validations succeeded"),
1562  1,
1563  GNUNET_NO);
1564  /* validity achieved, remember it! */
1565  ve->expecting_pong = GNUNET_NO;
1567  ve->pong_sig_cache = pong->signature;
1570  {
1571  if (GNUNET_YES == ve->known_to_ats)
1572  {
1577  }
1578  else
1579  {
1580  struct GNUNET_ATS_Properties prop;
1581 
1582  memset(&prop, 0, sizeof(prop));
1584  prop.scope = ve->network;
1585  prop.delay = GNUNET_TIME_relative_divide(ve->latency, 2);
1588  ve->known_to_ats = GNUNET_YES;
1589  GST_ats_add_address(ve->address, &prop);
1592  }
1593  }
1594  if (validations_running > 0)
1595  {
1598  gettext_noop("# validations running"),
1600  GNUNET_NO);
1602  "Validation finished, %u validation processes running\n",
1604  }
1605  else
1606  {
1607  GNUNET_break(0);
1608  }
1609 
1610  /* Notify about new validity */
1613 
1614  /* build HELLO to store in PEERINFO */
1616  gettext_noop("# HELLOs given to peerinfo"),
1617  1,
1618  GNUNET_NO);
1619  ve->copied = GNUNET_NO;
1622  ve,
1623  GNUNET_NO);
1624  GNUNET_break(NULL !=
1626  hello,
1627  NULL,
1628  NULL));
1629  GNUNET_free(hello);
1630  return GNUNET_OK;
1631 }
1632 
1633 
1641 int
1643 {
1644  const struct GNUNET_HELLO_Message *hm =
1645  (const struct GNUNET_HELLO_Message *)hello;
1646  struct GNUNET_PeerIdentity pid;
1647  int friend;
1648 
1649  friend = GNUNET_HELLO_is_friend_only(hm);
1650  if (((GNUNET_YES != friend) &&
1651  (GNUNET_NO != friend)) ||
1652  (GNUNET_OK != GNUNET_HELLO_get_id(hm, &pid)))
1653  {
1654  /* malformed HELLO */
1655  GNUNET_break_op(0);
1656  return GNUNET_SYSERR;
1657  }
1658  if (0 ==
1659  memcmp(&GST_my_identity,
1660  &pid,
1661  sizeof(struct GNUNET_PeerIdentity)))
1662  {
1663  /* got our own HELLO, how boring */
1665  "Validation received our own HELLO (%s), ignoring\n",
1666  GNUNET_i2s(&pid));
1667  return GNUNET_OK;
1668  }
1670  "Validation received HELLO message for peer `%s' with size %u, checking for new addresses\n",
1671  GNUNET_i2s(&pid),
1672  ntohs(hello->size));
1673  GNUNET_assert(NULL ==
1675  GNUNET_NO,
1677  NULL));
1678  return GNUNET_OK;
1679 }
1680 
1681 
1685 struct IteratorContext {
1690 
1694  void *cb_cls;
1695 };
1696 
1697 
1706 static int
1708  const struct GNUNET_PeerIdentity *key,
1709  void *value)
1710 {
1711  struct IteratorContext *ic = cls;
1712  struct ValidationEntry *ve = value;
1713 
1714  ic->cb(ic->cb_cls,
1715  ve->valid_until,
1716  ve->revalidation_block,
1717  ve->address);
1718  return GNUNET_OK;
1719 }
1720 
1721 
1730 void
1733  void *cb_cls)
1734 {
1735  struct IteratorContext ic;
1736 
1737  ic.cb = cb;
1738  ic.cb_cls = cb_cls;
1740  target,
1741  &iterate_addresses, &ic);
1742 }
1743 
1744 
1754 void
1756  int in_use)
1757 {
1758  struct ValidationEntry *ve;
1759 
1762  return; /* ignore inbound for validation */
1763  if (NULL == GST_plugins_find(address->transport_name))
1764  {
1765  /* How can we use an address for which we don't have the plugin? */
1766  GNUNET_break(0);
1767  return;
1768  }
1769  ve = find_validation_entry(address);
1770  if (NULL == ve)
1771  {
1772  GNUNET_break(0);
1773  return;
1774  }
1775  if (in_use == ve->in_use)
1776  return;
1777  ve->in_use = in_use;
1778  if (GNUNET_YES == in_use)
1779  {
1780  /* from now on, higher frequeny, so reschedule now */
1781  if (NULL != ve->revalidation_task)
1784  ve);
1785  }
1786 }
1787 
1788 
1789 /* 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:662
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.
static char * expiration
Credential TTL.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:671
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:202
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:989
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.
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).
static int ret
Final status code.
Definition: gnunet-arm.c:89
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:1237
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:1116
#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:252
Information about ongoing sessions of the transport client.
#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:1264
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:686
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:440
#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.
static char * plugin_name
Solver plugin name as string.
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:552
uint32_t challenge
Challenge code from PING (showing freshness).
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:107
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:66
int GNUNET_HELLO_is_friend_only(const struct GNUNET_HELLO_Message *h)
Return HELLO type.
Definition: hello.c:87
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:577
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:373
#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:131
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:525
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:655
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.
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:39
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956