gnunet-service-transport_validation.c 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file transport/gnunet-service-transport_validation.c
  19. * @brief address validation subsystem
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet-service-transport_ats.h"
  24. #include "gnunet-service-transport_blacklist.h"
  25. #include "gnunet-service-transport_clients.h"
  26. #include "gnunet-service-transport_hello.h"
  27. #include "gnunet-service-transport_neighbours.h"
  28. #include "gnunet-service-transport_plugins.h"
  29. #include "gnunet-service-transport_validation.h"
  30. #include "gnunet-service-transport.h"
  31. #include "gnunet_hello_lib.h"
  32. #include "gnunet_ats_service.h"
  33. #include "gnunet_peerinfo_service.h"
  34. #include "gnunet_signatures.h"
  35. /**
  36. * How long is a PONG signature valid? We'll recycle a signature until
  37. * 1/4 of this time is remaining. PONGs should expire so that if our
  38. * external addresses change an adversary cannot replay them indefinitely.
  39. * OTOH, we don't want to spend too much time generating PONG signatures,
  40. * so they must have some lifetime to reduce our CPU usage.
  41. */
  42. #define PONG_SIGNATURE_LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
  43. /**
  44. * After how long do we expire an address in a HELLO that we just
  45. * validated? This value is also used for our own addresses when we
  46. * create a HELLO.
  47. */
  48. #define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
  49. /**
  50. * How often do we allow PINGing an address that we have not yet
  51. * validated? This also determines how long we track an address that
  52. * we cannot validate (because after this time we can destroy the
  53. * validation record).
  54. */
  55. #define UNVALIDATED_PING_KEEPALIVE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
  56. /**
  57. * How often do we PING an address that we have successfully validated
  58. * in the past but are not actively using? Should be (significantly)
  59. * smaller than HELLO_ADDRESS_EXPIRATION.
  60. */
  61. #define VALIDATED_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
  62. /**
  63. * How often do we PING an address that we are currently using?
  64. */
  65. #define CONNECTED_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
  66. /**
  67. * How much delay is acceptable for sending the PING or PONG?
  68. */
  69. #define ACCEPTABLE_PING_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
  70. /**
  71. * Size of the validation map hashmap.
  72. */
  73. #define VALIDATION_MAP_SIZE 256
  74. /**
  75. * Priority to use for PINGs
  76. */
  77. #define PING_PRIORITY 2
  78. /**
  79. * Priority to use for PONGs
  80. */
  81. #define PONG_PRIORITY 4
  82. GNUNET_NETWORK_STRUCT_BEGIN
  83. /**
  84. * Message used to ask a peer to validate receipt (to check an address
  85. * from a HELLO). Followed by the address we are trying to validate,
  86. * or an empty address if we are just sending a PING to confirm that a
  87. * connection which the receiver (of the PING) initiated is still valid.
  88. */
  89. struct TransportPingMessage
  90. {
  91. /**
  92. * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_PING
  93. */
  94. struct GNUNET_MessageHeader header;
  95. /**
  96. * Challenge code (to ensure fresh reply).
  97. */
  98. uint32_t challenge GNUNET_PACKED;
  99. /**
  100. * Who is the intended recipient?
  101. */
  102. struct GNUNET_PeerIdentity target;
  103. };
  104. /**
  105. * Message used to validate a HELLO. The challenge is included in the
  106. * confirmation to make matching of replies to requests possible. The
  107. * signature signs our public key, an expiration time and our address.<p>
  108. *
  109. * This message is followed by our transport address that the PING tried
  110. * to confirm (if we liked it). The address can be empty (zero bytes)
  111. * if the PING had not address either (and we received the request via
  112. * a connection that we initiated).
  113. */
  114. struct TransportPongMessage
  115. {
  116. /**
  117. * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_PONG
  118. */
  119. struct GNUNET_MessageHeader header;
  120. /**
  121. * Challenge code from PING (showing freshness). Not part of what
  122. * is signed so that we can re-use signatures.
  123. */
  124. uint32_t challenge GNUNET_PACKED;
  125. /**
  126. * Signature.
  127. */
  128. struct GNUNET_CRYPTO_EddsaSignature signature;
  129. /**
  130. * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN to confirm that this is a
  131. * plausible address for the signing peer.
  132. */
  133. struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
  134. /**
  135. * When does this signature expire?
  136. */
  137. struct GNUNET_TIME_AbsoluteNBO expiration;
  138. /**
  139. * Size of address appended to this message (part of what is
  140. * being signed, hence not redundant).
  141. */
  142. uint32_t addrlen GNUNET_PACKED;
  143. };
  144. GNUNET_NETWORK_STRUCT_END
  145. /**
  146. * Information about an address under validation
  147. */
  148. struct ValidationEntry
  149. {
  150. /**
  151. * The address.
  152. */
  153. struct GNUNET_HELLO_Address *address;
  154. /**
  155. * Handle to the blacklist check (if we're currently in it).
  156. */
  157. struct GST_BlacklistCheck *bc;
  158. /**
  159. * Cached PONG signature
  160. */
  161. struct GNUNET_CRYPTO_EddsaSignature pong_sig_cache;
  162. /**
  163. * ID of task that will clean up this entry if nothing happens.
  164. */
  165. struct GNUNET_SCHEDULER_Task *timeout_task;
  166. /**
  167. * ID of task that will trigger address revalidation.
  168. */
  169. struct GNUNET_SCHEDULER_Task *revalidation_task;
  170. /**
  171. * At what time did we send the latest validation request (PING)?
  172. */
  173. struct GNUNET_TIME_Absolute send_time;
  174. /**
  175. * At what time do we send the next validation request (PING)?
  176. */
  177. struct GNUNET_TIME_Absolute next_validation;
  178. /**
  179. * Until when is this address valid?
  180. * ZERO if it is not currently considered valid.
  181. */
  182. struct GNUNET_TIME_Absolute valid_until;
  183. /**
  184. * Until when is the cached PONG signature valid?
  185. * ZERO if it is not currently considered valid.
  186. */
  187. struct GNUNET_TIME_Absolute pong_sig_valid_until;
  188. /**
  189. * How long until we can try to validate this address again?
  190. * FOREVER if the address is for an unsupported plugin (from PEERINFO)
  191. * ZERO if the address is considered valid (no validation needed)
  192. * otherwise a time in the future if we're currently denying re-validation
  193. */
  194. struct GNUNET_TIME_Absolute revalidation_block;
  195. /**
  196. * Last observed latency for this address (round-trip), delay between
  197. * last PING sent and PONG received; FOREVER if we never got a PONG.
  198. */
  199. struct GNUNET_TIME_Relative latency;
  200. /**
  201. * Current state of this validation entry
  202. */
  203. enum GNUNET_TRANSPORT_ValidationState state;
  204. /**
  205. * Challenge number we used.
  206. */
  207. uint32_t challenge;
  208. /**
  209. * When passing the address in #add_valid_peer_address(), did we
  210. * copy the address to the HELLO yet?
  211. */
  212. int copied;
  213. /**
  214. * Are we currently using this address for a connection?
  215. */
  216. int in_use;
  217. /**
  218. * Are we expecting a PONG message for this validation entry?
  219. */
  220. int expecting_pong;
  221. /**
  222. * Is this address known to ATS as valid right now?
  223. */
  224. int known_to_ats;
  225. /**
  226. * Which network type does our address belong to?
  227. */
  228. enum GNUNET_ATS_Network_Type network;
  229. };
  230. /**
  231. * Map of PeerIdentities to 'struct ValidationEntry*'s (addresses
  232. * of the given peer that we are currently validating, have validated
  233. * or are blocked from re-validation for a while).
  234. */
  235. static struct GNUNET_CONTAINER_MultiPeerMap *validation_map;
  236. /**
  237. * Context for peerinfo iteration.
  238. */
  239. static struct GNUNET_PEERINFO_NotifyContext *pnc;
  240. /**
  241. * Minimum delay between to validations
  242. */
  243. static struct GNUNET_TIME_Relative validation_delay;
  244. /**
  245. * Number of validations running; any PING that was not yet
  246. * matched by a PONG and for which we have not yet hit the
  247. * timeout is considered a running 'validation'.
  248. */
  249. static unsigned int validations_running;
  250. /**
  251. * Validition fast start threshold
  252. */
  253. static unsigned int validations_fast_start_threshold;
  254. /**
  255. * When is next validation allowed
  256. */
  257. static struct GNUNET_TIME_Absolute validation_next;
  258. /**
  259. * Context for the validation entry match function.
  260. */
  261. struct ValidationEntryMatchContext
  262. {
  263. /**
  264. * Where to store the result?
  265. */
  266. struct ValidationEntry *ve;
  267. /**
  268. * Address we're interested in.
  269. */
  270. const struct GNUNET_HELLO_Address *address;
  271. };
  272. /**
  273. * Provide an update on the `validation_map` map size to statistics.
  274. * This function should be called whenever the `validation_map`
  275. * is changed.
  276. */
  277. static void
  278. publish_ve_stat_update ()
  279. {
  280. GNUNET_STATISTICS_set (GST_stats,
  281. gettext_noop ("# Addresses in validation map"),
  282. GNUNET_CONTAINER_multipeermap_size (validation_map),
  283. GNUNET_NO);
  284. }
  285. /**
  286. * Iterate over validation entries until a matching one is found.
  287. *
  288. * @param cls the `struct ValidationEntryMatchContext *`
  289. * @param key peer identity (unused)
  290. * @param value a `struct ValidationEntry *` to match
  291. * @return #GNUNET_YES if the entry does not match,
  292. * #GNUNET_NO if the entry does match
  293. */
  294. static int
  295. validation_entry_match (void *cls,
  296. const struct GNUNET_PeerIdentity *key,
  297. void *value)
  298. {
  299. struct ValidationEntryMatchContext *vemc = cls;
  300. struct ValidationEntry *ve = value;
  301. if (0 == GNUNET_HELLO_address_cmp (ve->address,
  302. vemc->address))
  303. {
  304. vemc->ve = ve;
  305. return GNUNET_NO;
  306. }
  307. return GNUNET_YES;
  308. }
  309. /**
  310. * A validation entry changed. Update the state and notify
  311. * monitors.
  312. *
  313. * @param ve validation entry that changed
  314. * @param state new state
  315. */
  316. static void
  317. validation_entry_changed (struct ValidationEntry *ve,
  318. enum GNUNET_TRANSPORT_ValidationState state)
  319. {
  320. ve->state = state;
  321. GST_clients_broadcast_validation_notification (&ve->address->peer,
  322. ve->address,
  323. ve->send_time,
  324. ve->valid_until,
  325. ve->next_validation,
  326. state);
  327. }
  328. /**
  329. * Iterate over validation entries and free them.
  330. *
  331. * @param cls (unused)
  332. * @param key peer identity (unused)
  333. * @param value a `struct ValidationEntry *` to clean up
  334. * @return #GNUNET_YES (continue to iterate)
  335. */
  336. static int
  337. cleanup_validation_entry (void *cls,
  338. const struct GNUNET_PeerIdentity *key,
  339. void *value)
  340. {
  341. struct ValidationEntry *ve = value;
  342. ve->next_validation = GNUNET_TIME_UNIT_ZERO_ABS;
  343. ve->valid_until = GNUNET_TIME_UNIT_ZERO_ABS;
  344. /* Notify about deleted entry */
  345. validation_entry_changed (ve, GNUNET_TRANSPORT_VS_REMOVE);
  346. if (NULL != ve->bc)
  347. {
  348. GST_blacklist_test_cancel (ve->bc);
  349. ve->bc = NULL;
  350. }
  351. GNUNET_break (GNUNET_OK ==
  352. GNUNET_CONTAINER_multipeermap_remove (validation_map,
  353. &ve->address->peer,
  354. ve));
  355. publish_ve_stat_update ();
  356. if (GNUNET_YES == ve->known_to_ats)
  357. {
  358. GST_ats_expire_address (ve->address);
  359. ve->known_to_ats = GNUNET_NO;
  360. }
  361. GNUNET_HELLO_address_free (ve->address);
  362. if (NULL != ve->timeout_task)
  363. {
  364. GNUNET_SCHEDULER_cancel (ve->timeout_task);
  365. ve->timeout_task = NULL;
  366. }
  367. if (NULL != ve->revalidation_task)
  368. {
  369. GNUNET_SCHEDULER_cancel (ve->revalidation_task);
  370. ve->revalidation_task = NULL;
  371. }
  372. if ( (GNUNET_YES == ve->expecting_pong) &&
  373. (validations_running > 0) )
  374. {
  375. validations_running--;
  376. GNUNET_STATISTICS_set (GST_stats,
  377. gettext_noop ("# validations running"),
  378. validations_running,
  379. GNUNET_NO);
  380. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  381. "Validation aborted, %u validation processes running\n",
  382. validations_running);
  383. }
  384. GNUNET_free (ve);
  385. return GNUNET_OK;
  386. }
  387. /**
  388. * Address validation cleanup task. Assesses if the record is no
  389. * longer valid and then possibly triggers its removal.
  390. *
  391. * @param cls the `struct ValidationEntry`
  392. * @param tc scheduler context (unused)
  393. */
  394. static void
  395. timeout_hello_validation (void *cls,
  396. const struct GNUNET_SCHEDULER_TaskContext *tc)
  397. {
  398. struct ValidationEntry *ve = cls;
  399. struct GNUNET_TIME_Absolute max;
  400. struct GNUNET_TIME_Relative left;
  401. ve->timeout_task = NULL;
  402. max = GNUNET_TIME_absolute_max (ve->valid_until,
  403. ve->revalidation_block);
  404. left = GNUNET_TIME_absolute_get_remaining (max);
  405. if (left.rel_value_us > 0)
  406. {
  407. /* should wait a bit longer */
  408. ve->timeout_task =
  409. GNUNET_SCHEDULER_add_delayed (left, &timeout_hello_validation, ve);
  410. return;
  411. }
  412. GNUNET_STATISTICS_update (GST_stats,
  413. gettext_noop ("# address records discarded"), 1,
  414. GNUNET_NO);
  415. cleanup_validation_entry (NULL, &ve->address->peer, ve);
  416. }
  417. /**
  418. * Function called with the result from blacklisting.
  419. * Send a PING to the other peer if a communication is allowed.
  420. *
  421. * @param cls our `struct ValidationEntry`
  422. * @param pid identity of the other peer
  423. * @param result #GNUNET_OK if the connection is allowed, #GNUNET_NO if not
  424. */
  425. static void
  426. transmit_ping_if_allowed (void *cls,
  427. const struct GNUNET_PeerIdentity *pid,
  428. int result)
  429. {
  430. struct ValidationEntry *ve = cls;
  431. struct TransportPingMessage ping;
  432. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  433. struct GNUNET_TIME_Absolute next;
  434. const struct GNUNET_MessageHeader *hello;
  435. enum GNUNET_ATS_Network_Type network;
  436. ssize_t ret;
  437. size_t tsize;
  438. size_t slen;
  439. uint16_t hsize;
  440. ve->bc = NULL;
  441. if (GNUNET_NO == result)
  442. {
  443. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  444. "Blacklist denies to send PING to `%s' `%s' `%s'\n",
  445. GNUNET_i2s (pid),
  446. GST_plugins_a2s (ve->address),
  447. ve->address->transport_name);
  448. cleanup_validation_entry (NULL, pid, ve);
  449. return;
  450. }
  451. hello = GST_hello_get ();
  452. if (NULL == hello)
  453. {
  454. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  455. "Not PINGing peer `%s' as our HELLO is not yet ready\n",
  456. GNUNET_i2s (pid));
  457. return;
  458. }
  459. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  460. "Transmitting plain PING to `%s' `%s' `%s'\n",
  461. GNUNET_i2s (pid),
  462. GST_plugins_a2s (ve->address),
  463. ve->address->transport_name);
  464. slen = strlen (ve->address->transport_name) + 1;
  465. hsize = ntohs (hello->size);
  466. tsize =
  467. sizeof (struct TransportPingMessage) + ve->address->address_length +
  468. slen + hsize;
  469. ping.header.size =
  470. htons (sizeof (struct TransportPingMessage) +
  471. ve->address->address_length + slen);
  472. ping.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
  473. ping.challenge = htonl (ve->challenge);
  474. ping.target = *pid;
  475. if (tsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
  476. {
  477. GNUNET_break (0);
  478. hsize = 0;
  479. tsize =
  480. sizeof (struct TransportPingMessage) + ve->address->address_length +
  481. slen + hsize;
  482. }
  483. {
  484. char message_buf[tsize];
  485. /* build message with structure:
  486. * [HELLO][TransportPingMessage][Transport name][Address] */
  487. memcpy (message_buf, hello, hsize);
  488. memcpy (&message_buf[hsize],
  489. &ping,
  490. sizeof (struct TransportPingMessage));
  491. memcpy (&message_buf[sizeof (struct TransportPingMessage) + hsize],
  492. ve->address->transport_name,
  493. slen);
  494. memcpy (&message_buf[sizeof (struct TransportPingMessage) + slen + hsize],
  495. ve->address->address,
  496. ve->address->address_length);
  497. papi = GST_plugins_find (ve->address->transport_name);
  498. GNUNET_assert (NULL != papi);
  499. GNUNET_assert (NULL != papi->send);
  500. struct Session *session = papi->get_session (papi->cls,
  501. ve->address);
  502. if (NULL != session)
  503. {
  504. ret = papi->send (papi->cls, session,
  505. message_buf, tsize,
  506. PING_PRIORITY,
  507. ACCEPTABLE_PING_DELAY,
  508. NULL, NULL);
  509. network = papi->get_network (papi->cls, session);
  510. if (GNUNET_ATS_NET_UNSPECIFIED == network)
  511. {
  512. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  513. "Could not obtain a valid network for `%s' `%s'\n",
  514. GNUNET_i2s (pid),
  515. GST_plugins_a2s (ve->address));
  516. GNUNET_break(0);
  517. }
  518. GST_neighbours_notify_data_sent (ve->address, session, tsize);
  519. }
  520. else
  521. {
  522. /* Could not get a valid session */
  523. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  524. "Could not get a valid session for `%s' `%s'\n",
  525. GNUNET_i2s (pid),
  526. GST_plugins_a2s (ve->address));
  527. ret = -1;
  528. }
  529. }
  530. if (-1 != ret)
  531. {
  532. next = GNUNET_TIME_relative_to_absolute (validation_delay);
  533. validation_next = GNUNET_TIME_absolute_max (next,
  534. validation_next);
  535. ve->send_time = GNUNET_TIME_absolute_get ();
  536. GNUNET_STATISTICS_update (GST_stats,
  537. gettext_noop ("# PINGs for address validation sent"),
  538. 1,
  539. GNUNET_NO);
  540. ve->network = network;
  541. ve->expecting_pong = GNUNET_YES;
  542. validations_running++;
  543. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  544. "Validation started, %u validation processes running\n",
  545. validations_running);
  546. GNUNET_STATISTICS_set (GST_stats,
  547. gettext_noop ("# validations running"),
  548. validations_running,
  549. GNUNET_NO);
  550. /* Notify about PING sent */
  551. validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE);
  552. }
  553. }
  554. /**
  555. * Do address validation again to keep address valid.
  556. *
  557. * @param cls the `struct ValidationEntry`
  558. * @param tc scheduler context (unused)
  559. */
  560. static void
  561. revalidate_address (void *cls,
  562. const struct GNUNET_SCHEDULER_TaskContext *tc)
  563. {
  564. struct ValidationEntry *ve = cls;
  565. struct GNUNET_TIME_Relative canonical_delay;
  566. struct GNUNET_TIME_Relative delay;
  567. struct GNUNET_TIME_Relative blocked_for;
  568. struct GST_BlacklistCheck *bc;
  569. uint32_t rdelay;
  570. ve->revalidation_task = NULL;
  571. delay = GNUNET_TIME_absolute_get_remaining (ve->revalidation_block);
  572. /* Considering current connectivity situation, what is the maximum
  573. block period permitted? */
  574. if (GNUNET_YES == ve->in_use)
  575. canonical_delay = CONNECTED_PING_FREQUENCY;
  576. else if (GNUNET_TIME_absolute_get_remaining (ve->valid_until).rel_value_us > 0)
  577. canonical_delay = VALIDATED_PING_FREQUENCY;
  578. else
  579. canonical_delay = UNVALIDATED_PING_KEEPALIVE;
  580. /* Use delay that is MIN of original delay and possibly adjusted
  581. new maximum delay (which may be lower); the real delay
  582. is originally randomized between "canonical_delay" and "2 * canonical_delay",
  583. so continue to permit that window for the operation. */
  584. delay = GNUNET_TIME_relative_min (delay,
  585. GNUNET_TIME_relative_multiply (canonical_delay,
  586. 2));
  587. ve->revalidation_block = GNUNET_TIME_relative_to_absolute (delay);
  588. if (delay.rel_value_us > 0)
  589. {
  590. /* should wait a bit longer */
  591. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  592. "Waiting for %s longer before validating address `%s'\n",
  593. GNUNET_STRINGS_relative_time_to_string (delay,
  594. GNUNET_YES),
  595. GST_plugins_a2s (ve->address));
  596. ve->revalidation_task =
  597. GNUNET_SCHEDULER_add_delayed (delay,
  598. &revalidate_address, ve);
  599. ve->next_validation = GNUNET_TIME_relative_to_absolute (delay);
  600. return;
  601. }
  602. /* check if globally we have too many active validations at a
  603. too high rate, if so, delay ours */
  604. blocked_for = GNUNET_TIME_absolute_get_remaining (validation_next);
  605. if ( (validations_running > validations_fast_start_threshold) &&
  606. (blocked_for.rel_value_us > 0) )
  607. {
  608. /* Validations are blocked, have to wait for blocked_for time */
  609. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  610. "Validations blocked for another %s, delaying validating address `%s'\n",
  611. GNUNET_STRINGS_relative_time_to_string (blocked_for,
  612. GNUNET_YES),
  613. GST_plugins_a2s (ve->address));
  614. GNUNET_STATISTICS_update (GST_stats,
  615. gettext_noop ("# validations delayed by global throttle"),
  616. 1,
  617. GNUNET_NO);
  618. ve->revalidation_task =
  619. GNUNET_SCHEDULER_add_delayed (blocked_for,
  620. &revalidate_address,
  621. ve);
  622. ve->next_validation = GNUNET_TIME_relative_to_absolute (blocked_for);
  623. return;
  624. }
  625. /* We are good to go; remember to not go again for `canonical_delay` time;
  626. add up to `canonical_delay` to randomize start time */
  627. ve->revalidation_block = GNUNET_TIME_relative_to_absolute (canonical_delay);
  628. /* schedule next PINGing with some extra random delay to avoid synchronous re-validations */
  629. rdelay =
  630. GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
  631. canonical_delay.rel_value_us);
  632. delay = GNUNET_TIME_relative_add (canonical_delay,
  633. GNUNET_TIME_relative_multiply
  634. (GNUNET_TIME_UNIT_MICROSECONDS, rdelay));
  635. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  636. "Validating now, next scheduled for %s, now validating address `%s'\n",
  637. GNUNET_STRINGS_relative_time_to_string (blocked_for,
  638. GNUNET_YES),
  639. GST_plugins_a2s (ve->address));
  640. ve->revalidation_task =
  641. GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve);
  642. ve->next_validation = GNUNET_TIME_relative_to_absolute (delay);
  643. /* start PINGing by checking blacklist */
  644. GNUNET_STATISTICS_update (GST_stats,
  645. gettext_noop ("# address revalidations started"), 1,
  646. GNUNET_NO);
  647. bc = GST_blacklist_test_allowed (&ve->address->peer,
  648. ve->address->transport_name,
  649. &transmit_ping_if_allowed, ve);
  650. if (NULL != bc)
  651. ve->bc = bc; /* only set 'bc' if 'transmit_ping_if_allowed' was not already
  652. * called... */
  653. }
  654. /**
  655. * Find a ValidationEntry entry for the given neighbour that matches
  656. * the given address and transport. If none exists, create one (but
  657. * without starting any validation).
  658. *
  659. * @param address address to find
  660. * @return validation entry matching the given specifications, NULL
  661. * if we don't have an existing entry and no public key was given
  662. */
  663. static struct ValidationEntry *
  664. find_validation_entry (const struct GNUNET_HELLO_Address *address)
  665. {
  666. struct ValidationEntryMatchContext vemc;
  667. struct ValidationEntry *ve;
  668. vemc.ve = NULL;
  669. vemc.address = address;
  670. GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
  671. &address->peer,
  672. &validation_entry_match, &vemc);
  673. if (NULL != (ve = vemc.ve))
  674. return ve;
  675. ve = GNUNET_new (struct ValidationEntry);
  676. ve->in_use = GNUNET_SYSERR; /* not defined */
  677. ve->address = GNUNET_HELLO_address_copy (address);
  678. ve->pong_sig_valid_until = GNUNET_TIME_UNIT_ZERO_ABS;
  679. memset (&ve->pong_sig_cache, '\0', sizeof (struct GNUNET_CRYPTO_EddsaSignature));
  680. ve->latency = GNUNET_TIME_UNIT_FOREVER_REL;
  681. ve->challenge =
  682. GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
  683. ve->timeout_task =
  684. GNUNET_SCHEDULER_add_delayed (UNVALIDATED_PING_KEEPALIVE,
  685. &timeout_hello_validation, ve);
  686. GNUNET_CONTAINER_multipeermap_put (validation_map, &address->peer,
  687. ve,
  688. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  689. publish_ve_stat_update ();
  690. validation_entry_changed (ve, GNUNET_TRANSPORT_VS_NEW);
  691. return ve;
  692. }
  693. /**
  694. * Iterator which adds the given address to the set of validated
  695. * addresses.
  696. *
  697. * @param cls original HELLO message
  698. * @param address the address
  699. * @param expiration expiration time
  700. * @return #GNUNET_OK (keep the address), could return
  701. * #GNUNET_NO (delete address, but this is ignored);
  702. * #GNUNET_SYSERR would abort iteration (but we always iterate all)
  703. */
  704. static int
  705. add_valid_address (void *cls,
  706. const struct GNUNET_HELLO_Address *address,
  707. struct GNUNET_TIME_Absolute expiration)
  708. {
  709. const struct GNUNET_HELLO_Message *hello = cls;
  710. struct ValidationEntry *ve;
  711. struct GNUNET_PeerIdentity pid;
  712. struct GNUNET_ATS_Properties prop;
  713. if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
  714. return GNUNET_OK; /* expired */
  715. if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
  716. {
  717. GNUNET_break (0);
  718. return GNUNET_OK; /* invalid HELLO !? */
  719. }
  720. if (NULL == GST_plugins_find (address->transport_name))
  721. {
  722. /* might have been valid in the past, but we don't have that
  723. plugin loaded right now */
  724. return GNUNET_OK;
  725. }
  726. ve = find_validation_entry (address);
  727. ve->valid_until = GNUNET_TIME_absolute_max (ve->valid_until,
  728. expiration);
  729. if (NULL == ve->revalidation_task)
  730. {
  731. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  732. "Starting revalidations for valid address `%s'\n",
  733. GST_plugins_a2s (ve->address));
  734. ve->next_validation = GNUNET_TIME_absolute_get();
  735. ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve);
  736. }
  737. validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE);
  738. memset (&prop, 0, sizeof (prop));
  739. prop.scope = ve->network;
  740. prop.delay = GNUNET_TIME_relative_divide (ve->latency, 2);
  741. if (GNUNET_YES != ve->known_to_ats)
  742. {
  743. ve->known_to_ats = GNUNET_YES;
  744. GST_ats_add_address (address, &prop);
  745. }
  746. return GNUNET_OK;
  747. }
  748. /**
  749. * Function called for any HELLO known to PEERINFO.
  750. *
  751. * @param cls unused (NULL)
  752. * @param peer id of the peer, NULL for last call (during iteration,
  753. * as we are monitoring, this should never happen)
  754. * @param hello hello message for the peer (can be NULL)
  755. * @param err_msg error message
  756. */
  757. static void
  758. process_peerinfo_hello (void *cls,
  759. const struct GNUNET_PeerIdentity *peer,
  760. const struct GNUNET_HELLO_Message *hello,
  761. const char *err_msg)
  762. {
  763. GNUNET_assert (NULL != peer);
  764. if (NULL == hello)
  765. return;
  766. if (0 == memcmp (&GST_my_identity,
  767. peer,
  768. sizeof (struct GNUNET_PeerIdentity)))
  769. {
  770. /* Peerinfo returned own identity, skip validation */
  771. return;
  772. }
  773. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  774. "Handling HELLO for peer `%s'\n",
  775. GNUNET_i2s (peer));
  776. GNUNET_assert (NULL ==
  777. GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO,
  778. &add_valid_address,
  779. (void *) hello));
  780. }
  781. /**
  782. * Start the validation subsystem.
  783. *
  784. * @param max_fds maximum number of fds to use
  785. */
  786. void
  787. GST_validation_start (unsigned int max_fds)
  788. {
  789. /**
  790. * Initialization for validation throttling
  791. *
  792. * We have a maximum number max_fds of connections we can use for validation
  793. * We monitor the number of validations in parallel and start to throttle it
  794. * when doing to many validations in parallel:
  795. * if (running validations < (max_fds / 2))
  796. * - "fast start": run validation immediately
  797. * - have delay of (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2)
  798. * (300 sec / ~150 == ~2 sec.) between two validations
  799. */
  800. validation_next = GNUNET_TIME_absolute_get();
  801. validation_delay.rel_value_us = (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2);
  802. validations_fast_start_threshold = (max_fds / 2);
  803. validations_running = 0;
  804. GNUNET_STATISTICS_set (GST_stats,
  805. gettext_noop ("# validations running"),
  806. validations_running,
  807. GNUNET_NO);
  808. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  809. "Validation uses a fast start threshold of %u connections and a delay of %s\n",
  810. validations_fast_start_threshold,
  811. GNUNET_STRINGS_relative_time_to_string (validation_delay,
  812. GNUNET_YES));
  813. validation_map = GNUNET_CONTAINER_multipeermap_create (VALIDATION_MAP_SIZE,
  814. GNUNET_NO);
  815. pnc = GNUNET_PEERINFO_notify (GST_cfg, GNUNET_YES,
  816. &process_peerinfo_hello, NULL);
  817. }
  818. /**
  819. * Stop the validation subsystem.
  820. */
  821. void
  822. GST_validation_stop ()
  823. {
  824. GNUNET_CONTAINER_multipeermap_iterate (validation_map,
  825. &cleanup_validation_entry,
  826. NULL);
  827. GNUNET_CONTAINER_multipeermap_destroy (validation_map);
  828. validation_map = NULL;
  829. GNUNET_PEERINFO_notify_cancel (pnc);
  830. }
  831. /**
  832. * Send the given PONG to the given address.
  833. *
  834. * @param cls the PONG message
  835. * @param valid_until is ZERO if we never validated the address,
  836. * otherwise a time up to when we consider it (or was) valid
  837. * @param validation_block is FOREVER if the address is for an unsupported plugin (from PEERINFO)
  838. * is ZERO if the address is considered valid (no validation needed)
  839. * otherwise a time in the future if we're currently denying re-validation
  840. * @param address target address
  841. */
  842. static void
  843. multicast_pong (void *cls,
  844. struct GNUNET_TIME_Absolute valid_until,
  845. struct GNUNET_TIME_Absolute validation_block,
  846. const struct GNUNET_HELLO_Address *address)
  847. {
  848. struct TransportPongMessage *pong = cls;
  849. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  850. struct Session *session;
  851. papi = GST_plugins_find (address->transport_name);
  852. if (NULL == papi)
  853. {
  854. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  855. "Plugin %s not supported, cannot send PONG\n",
  856. address->transport_name);
  857. return;
  858. }
  859. GNUNET_assert (NULL != papi->send);
  860. GNUNET_assert (NULL != papi->get_session);
  861. session = papi->get_session(papi->cls, address);
  862. if (NULL == session)
  863. {
  864. GNUNET_break (0);
  865. return;
  866. }
  867. GST_ats_new_session (address, session);
  868. papi->send (papi->cls, session,
  869. (const char *) pong,
  870. ntohs (pong->header.size),
  871. PONG_PRIORITY,
  872. ACCEPTABLE_PING_DELAY,
  873. NULL, NULL);
  874. GST_neighbours_notify_data_sent (address,
  875. session,
  876. pong->header.size);
  877. }
  878. /**
  879. * We've received a PING. If appropriate, generate a PONG.
  880. *
  881. * @param sender peer sending the PING
  882. * @param hdr the PING
  883. * @param sender_address the sender address as we got it
  884. * @param session session we got the PING from
  885. * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error
  886. */
  887. int
  888. GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender,
  889. const struct GNUNET_MessageHeader *hdr,
  890. const struct GNUNET_HELLO_Address *sender_address,
  891. struct Session *session)
  892. {
  893. const struct TransportPingMessage *ping;
  894. struct TransportPongMessage *pong;
  895. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  896. struct GNUNET_CRYPTO_EddsaSignature *sig_cache;
  897. struct GNUNET_TIME_Absolute *sig_cache_exp;
  898. const char *addr;
  899. const char *addrend;
  900. char *plugin_name;
  901. char *pos;
  902. size_t len_address;
  903. size_t len_plugin;
  904. ssize_t ret;
  905. struct GNUNET_HELLO_Address address;
  906. if (ntohs (hdr->size) < sizeof (struct TransportPingMessage))
  907. {
  908. GNUNET_break_op (0);
  909. return GNUNET_SYSERR;
  910. }
  911. ping = (const struct TransportPingMessage *) hdr;
  912. if (0 !=
  913. memcmp (&ping->target, &GST_my_identity,
  914. sizeof (struct GNUNET_PeerIdentity)))
  915. {
  916. GNUNET_STATISTICS_update (GST_stats,
  917. gettext_noop
  918. ("# PING message for different peer received"), 1,
  919. GNUNET_NO);
  920. return GNUNET_SYSERR;
  921. }
  922. GNUNET_STATISTICS_update (GST_stats,
  923. gettext_noop ("# PING messages received"), 1,
  924. GNUNET_NO);
  925. addr = (const char *) &ping[1];
  926. len_address = ntohs (hdr->size) - sizeof (struct TransportPingMessage);
  927. /* peer wants to confirm that this is one of our addresses, this is what is
  928. * used for address validation */
  929. sig_cache = NULL;
  930. sig_cache_exp = NULL;
  931. papi = NULL;
  932. if (len_address > 0)
  933. {
  934. addrend = memchr (addr, '\0', len_address);
  935. if (NULL == addrend)
  936. {
  937. GNUNET_break_op (0);
  938. return GNUNET_SYSERR;
  939. }
  940. addrend++;
  941. len_plugin = strlen (addr) + 1;
  942. len_address -= len_plugin;
  943. address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE;
  944. address.address = addrend;
  945. address.address_length = len_address;
  946. address.transport_name = addr;
  947. address.peer = GST_my_identity;
  948. if (NULL == address.transport_name)
  949. {
  950. GNUNET_break (0);
  951. }
  952. if (0 != strstr (address.transport_name, "_client"))
  953. {
  954. plugin_name = GNUNET_strdup (address.transport_name);
  955. pos = strstr (plugin_name, "_client");
  956. GNUNET_assert (NULL != pos);
  957. GNUNET_snprintf (pos, strlen ("_server") + 1, "%s", "_server");
  958. }
  959. else
  960. plugin_name = GNUNET_strdup (address.transport_name);
  961. if (NULL == (papi = GST_plugins_find (plugin_name)))
  962. {
  963. /* we don't have the plugin for this address */
  964. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  965. _("Plugin `%s' not available, cannot confirm having this address\n"),
  966. plugin_name);
  967. GNUNET_free (plugin_name);
  968. return GNUNET_SYSERR;
  969. }
  970. GNUNET_free (plugin_name);
  971. if (GNUNET_OK !=
  972. papi->check_address (papi->cls,
  973. addrend,
  974. len_address))
  975. {
  976. GNUNET_STATISTICS_update (GST_stats,
  977. gettext_noop
  978. ("# failed address checks during validation"), 1,
  979. GNUNET_NO);
  980. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  981. _("Address `%s' is not one of my addresses, not confirming PING\n"),
  982. GST_plugins_a2s (&address));
  983. return GNUNET_SYSERR;
  984. }
  985. else
  986. {
  987. GNUNET_STATISTICS_update (GST_stats,
  988. gettext_noop
  989. ("# successful address checks during validation"), 1,
  990. GNUNET_NO);
  991. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  992. "Address `%s' is one of my addresses, confirming PING\n",
  993. GST_plugins_a2s (&address));
  994. }
  995. if (GNUNET_YES !=
  996. GST_hello_test_address (&address,
  997. &sig_cache,
  998. &sig_cache_exp))
  999. {
  1000. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1001. _("Not confirming PING from peer `%s' with address `%s' since I cannot confirm having this address.\n"),
  1002. GNUNET_i2s (sender),
  1003. GST_plugins_a2s (&address));
  1004. return GNUNET_SYSERR;
  1005. }
  1006. }
  1007. else
  1008. {
  1009. addrend = NULL; /* make gcc happy */
  1010. len_plugin = 0;
  1011. static struct GNUNET_CRYPTO_EddsaSignature no_address_signature;
  1012. static struct GNUNET_TIME_Absolute no_address_signature_expiration;
  1013. sig_cache = &no_address_signature;
  1014. sig_cache_exp = &no_address_signature_expiration;
  1015. }
  1016. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1017. "I am `%s', sending PONG to peer `%s'\n",
  1018. GNUNET_i2s_full (&GST_my_identity),
  1019. GNUNET_i2s (sender));
  1020. /* message with structure:
  1021. * [TransportPongMessage][Transport name][Address] */
  1022. pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + len_address + len_plugin);
  1023. pong->header.size =
  1024. htons (sizeof (struct TransportPongMessage) + len_address + len_plugin);
  1025. pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
  1026. pong->purpose.size =
  1027. htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
  1028. sizeof (uint32_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) +
  1029. len_address + len_plugin);
  1030. pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN);
  1031. memcpy (&pong->challenge, &ping->challenge, sizeof (ping->challenge));
  1032. pong->addrlen = htonl (len_address + len_plugin);
  1033. memcpy (&pong[1], addr, len_plugin); /* Copy transport plugin */
  1034. if (len_address > 0)
  1035. {
  1036. GNUNET_assert (NULL != addrend);
  1037. memcpy (&((char *) &pong[1])[len_plugin], addrend, len_address);
  1038. }
  1039. if (GNUNET_TIME_absolute_get_remaining (*sig_cache_exp).rel_value_us <
  1040. PONG_SIGNATURE_LIFETIME.rel_value_us / 4)
  1041. {
  1042. /* create / update cached sig */
  1043. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1044. "Creating PONG signature to indicate ownership.\n");
  1045. *sig_cache_exp = GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
  1046. pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
  1047. if (GNUNET_OK !=
  1048. GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, &pong->purpose,
  1049. sig_cache))
  1050. {
  1051. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1052. _("Failed to create PONG signature for peer `%s'\n"), GNUNET_i2s (sender));
  1053. }
  1054. }
  1055. else
  1056. {
  1057. pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
  1058. }
  1059. pong->signature = *sig_cache;
  1060. GNUNET_assert (NULL != sender_address);
  1061. /* first see if the session we got this PING from can be used to transmit
  1062. * a response reliably */
  1063. if (NULL == papi)
  1064. {
  1065. ret = -1;
  1066. }
  1067. else
  1068. {
  1069. GNUNET_assert (NULL != papi->send);
  1070. GNUNET_assert (NULL != papi->get_session);
  1071. if (NULL == session)
  1072. {
  1073. session = papi->get_session (papi->cls, sender_address);
  1074. }
  1075. if (NULL == session)
  1076. {
  1077. GNUNET_break (0);
  1078. ret = -1;
  1079. }
  1080. else
  1081. {
  1082. ret = papi->send (papi->cls, session,
  1083. (const char *) pong,
  1084. ntohs (pong->header.size),
  1085. PONG_PRIORITY, ACCEPTABLE_PING_DELAY,
  1086. NULL, NULL);
  1087. if (-1 != ret)
  1088. GST_neighbours_notify_data_sent (sender_address,
  1089. session,
  1090. pong->header.size);
  1091. }
  1092. }
  1093. if (-1 != ret)
  1094. {
  1095. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1096. "Transmitted PONG to `%s' via reliable mechanism\n",
  1097. GNUNET_i2s (sender));
  1098. /* done! */
  1099. GNUNET_STATISTICS_update (GST_stats,
  1100. gettext_noop
  1101. ("# PONGs unicast via reliable transport"), 1,
  1102. GNUNET_NO);
  1103. GNUNET_free (pong);
  1104. return GNUNET_OK;
  1105. }
  1106. /* no reliable method found, try transmission via all known addresses */
  1107. GNUNET_STATISTICS_update (GST_stats,
  1108. gettext_noop
  1109. ("# PONGs multicast to all available addresses"), 1,
  1110. GNUNET_NO);
  1111. GST_validation_get_addresses (sender,
  1112. &multicast_pong, pong);
  1113. GNUNET_free (pong);
  1114. return GNUNET_OK;
  1115. }
  1116. /**
  1117. * Validate an individual address.
  1118. *
  1119. * @param address address we should try to validate
  1120. */
  1121. void
  1122. GST_validation_handle_address (const struct GNUNET_HELLO_Address *address)
  1123. {
  1124. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  1125. struct ValidationEntry *ve;
  1126. papi = GST_plugins_find (address->transport_name);
  1127. if (NULL == papi)
  1128. {
  1129. /* This plugin is currently unvailable ... ignore */
  1130. return;
  1131. }
  1132. ve = find_validation_entry (address);
  1133. if (NULL == ve->revalidation_task)
  1134. {
  1135. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1136. "Validation process started for fresh address `%s' of %s\n",
  1137. GST_plugins_a2s (ve->address),
  1138. GNUNET_i2s (&ve->address->peer));
  1139. ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve);
  1140. }
  1141. }
  1142. /**
  1143. * Iterator callback to go over all addresses and try to validate them
  1144. * (unless blocked or already validated).
  1145. *
  1146. * @param cls NULL
  1147. * @param address the address
  1148. * @param expiration expiration time
  1149. * @return #GNUNET_OK (keep the address)
  1150. */
  1151. static int
  1152. validate_address_iterator (void *cls,
  1153. const struct GNUNET_HELLO_Address *address,
  1154. struct GNUNET_TIME_Absolute expiration)
  1155. {
  1156. if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
  1157. {
  1158. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1159. "Skipping expired address from HELLO\n");
  1160. return GNUNET_OK; /* expired */
  1161. }
  1162. GST_validation_handle_address (address);
  1163. return GNUNET_OK;
  1164. }
  1165. /**
  1166. * Add the validated peer address to the HELLO.
  1167. *
  1168. * @param cls the `struct ValidationEntry *` with the validated address
  1169. * @param max space in @a buf
  1170. * @param buf where to add the address
  1171. * @return number of bytes written, #GNUNET_SYSERR to signal the
  1172. * end of the iteration.
  1173. */
  1174. static ssize_t
  1175. add_valid_peer_address (void *cls,
  1176. size_t max,
  1177. void *buf)
  1178. {
  1179. struct ValidationEntry *ve = cls;
  1180. if (GNUNET_YES == ve->copied)
  1181. return GNUNET_SYSERR; /* Done */
  1182. ve->copied = GNUNET_YES;
  1183. return GNUNET_HELLO_add_address (ve->address,
  1184. ve->valid_until,
  1185. buf,
  1186. max);
  1187. }
  1188. /**
  1189. * We've received a PONG. Check if it matches a pending PING and
  1190. * mark the respective address as confirmed.
  1191. *
  1192. * @param sender peer sending the PONG
  1193. * @param hdr the PONG
  1194. * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error
  1195. */
  1196. int
  1197. GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender,
  1198. const struct GNUNET_MessageHeader *hdr)
  1199. {
  1200. const struct TransportPongMessage *pong;
  1201. struct ValidationEntry *ve;
  1202. const char *tname;
  1203. const char *addr;
  1204. size_t addrlen;
  1205. size_t slen;
  1206. size_t size;
  1207. struct GNUNET_HELLO_Message *hello;
  1208. struct GNUNET_HELLO_Address address;
  1209. int sig_res;
  1210. int do_verify;
  1211. if (ntohs (hdr->size) < sizeof (struct TransportPongMessage))
  1212. {
  1213. GNUNET_break_op (0);
  1214. return GNUNET_SYSERR;
  1215. }
  1216. GNUNET_STATISTICS_update (GST_stats,
  1217. gettext_noop ("# PONG messages received"), 1,
  1218. GNUNET_NO);
  1219. /* message with structure:
  1220. * [TransportPongMessage][Transport name][Address] */
  1221. pong = (const struct TransportPongMessage *) hdr;
  1222. tname = (const char *) &pong[1];
  1223. size = ntohs (hdr->size) - sizeof (struct TransportPongMessage);
  1224. addr = memchr (tname, '\0', size);
  1225. if (NULL == addr)
  1226. {
  1227. GNUNET_break_op (0);
  1228. return GNUNET_SYSERR;
  1229. }
  1230. addr++;
  1231. slen = strlen (tname) + 1;
  1232. addrlen = size - slen;
  1233. if (NULL == GST_plugins_find (tname))
  1234. {
  1235. /* we got the PONG, but the transport plugin specified in it
  1236. is not supported by this peer, so this cannot be a good
  1237. PONG for us. */
  1238. GNUNET_break_op (0);
  1239. return GNUNET_OK;
  1240. }
  1241. address.peer = *sender;
  1242. address.address = addr;
  1243. address.address_length = addrlen;
  1244. address.transport_name = tname;
  1245. address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE;
  1246. ve = find_validation_entry (&address);
  1247. if ((NULL == ve) || (GNUNET_NO == ve->expecting_pong))
  1248. {
  1249. GNUNET_STATISTICS_update (GST_stats,
  1250. gettext_noop
  1251. ("# PONGs dropped, no matching pending validation"),
  1252. 1, GNUNET_NO);
  1253. return GNUNET_OK;
  1254. }
  1255. /* now check that PONG is well-formed */
  1256. if (0 != memcmp (&ve->address->peer,
  1257. sender,
  1258. sizeof (struct GNUNET_PeerIdentity)))
  1259. {
  1260. GNUNET_break_op (0);
  1261. return GNUNET_SYSERR;
  1262. }
  1263. if (0 ==
  1264. GNUNET_TIME_absolute_get_remaining
  1265. (GNUNET_TIME_absolute_ntoh (pong->expiration)).rel_value_us)
  1266. {
  1267. GNUNET_STATISTICS_update (GST_stats,
  1268. gettext_noop
  1269. ("# PONGs dropped, signature expired"), 1,
  1270. GNUNET_NO);
  1271. return GNUNET_SYSERR;
  1272. }
  1273. sig_res = GNUNET_SYSERR;
  1274. do_verify = GNUNET_YES;
  1275. if (0 != GNUNET_TIME_absolute_get_remaining (ve->pong_sig_valid_until).rel_value_us)
  1276. {
  1277. /* We have a cached and valid signature for this peer,
  1278. * try to compare instead of verify */
  1279. if (0 == memcmp (&ve->pong_sig_cache, &pong->signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature)))
  1280. {
  1281. /* signatures are identical, we can skip verification */
  1282. sig_res = GNUNET_OK;
  1283. do_verify = GNUNET_NO;
  1284. }
  1285. else
  1286. {
  1287. sig_res = GNUNET_SYSERR;
  1288. /* signatures do not match, we have to verify */
  1289. }
  1290. }
  1291. if (GNUNET_YES == do_verify)
  1292. {
  1293. /* Do expensive verification */
  1294. sig_res = GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
  1295. &pong->purpose, &pong->signature,
  1296. &ve->address->peer.public_key);
  1297. if (sig_res == GNUNET_SYSERR)
  1298. {
  1299. GNUNET_break_op (0);
  1300. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1301. "Failed to verify: invalid signature on address `%s':%s from peer `%s'\n",
  1302. tname,
  1303. GST_plugins_a2s (ve->address),
  1304. GNUNET_i2s (sender));
  1305. }
  1306. }
  1307. if (sig_res == GNUNET_SYSERR)
  1308. {
  1309. GNUNET_break_op (0);
  1310. return GNUNET_SYSERR;
  1311. }
  1312. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1313. "Validation process successful for peer `%s' with plugin `%s' address `%s'\n",
  1314. GNUNET_i2s (sender),
  1315. tname,
  1316. GST_plugins_a2s (ve->address));
  1317. GNUNET_STATISTICS_update (GST_stats,
  1318. gettext_noop ("# validations succeeded"),
  1319. 1,
  1320. GNUNET_NO);
  1321. /* validity achieved, remember it! */
  1322. ve->expecting_pong = GNUNET_NO;
  1323. ve->valid_until = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
  1324. ve->pong_sig_cache = pong->signature;
  1325. ve->pong_sig_valid_until = GNUNET_TIME_absolute_ntoh (pong->expiration);
  1326. ve->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
  1327. {
  1328. if (GNUNET_YES == ve->known_to_ats)
  1329. {
  1330. GST_ats_update_delay (ve->address,
  1331. GNUNET_TIME_relative_divide (ve->latency, 2));
  1332. }
  1333. else
  1334. {
  1335. struct GNUNET_ATS_Properties prop;
  1336. memset (&prop, 0, sizeof (prop));
  1337. prop.scope = ve->network;
  1338. prop.delay = GNUNET_TIME_relative_divide (ve->latency, 2);
  1339. ve->known_to_ats = GNUNET_YES;
  1340. GST_ats_add_address (ve->address, &prop);
  1341. }
  1342. }
  1343. if (validations_running > 0)
  1344. {
  1345. validations_running--;
  1346. GNUNET_STATISTICS_set (GST_stats,
  1347. gettext_noop ("# validations running"),
  1348. validations_running,
  1349. GNUNET_NO);
  1350. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1351. "Validation finished, %u validation processes running\n",
  1352. validations_running);
  1353. }
  1354. else
  1355. {
  1356. GNUNET_break (0);
  1357. }
  1358. /* Notify about new validity */
  1359. validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE);
  1360. /* build HELLO to store in PEERINFO */
  1361. ve->copied = GNUNET_NO;
  1362. hello = GNUNET_HELLO_create (&ve->address->peer.public_key,
  1363. &add_valid_peer_address, ve,
  1364. GNUNET_NO);
  1365. GNUNET_PEERINFO_add_peer (GST_peerinfo, hello, NULL, NULL);
  1366. GNUNET_free (hello);
  1367. return GNUNET_OK;
  1368. }
  1369. /**
  1370. * We've received a HELLO, check which addresses are new and trigger
  1371. * validation.
  1372. *
  1373. * @param hello the HELLO we received
  1374. * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error
  1375. */
  1376. int
  1377. GST_validation_handle_hello (const struct GNUNET_MessageHeader *hello)
  1378. {
  1379. const struct GNUNET_HELLO_Message *hm =
  1380. (const struct GNUNET_HELLO_Message *) hello;
  1381. struct GNUNET_PeerIdentity pid;
  1382. struct GNUNET_HELLO_Message *h;
  1383. int friend;
  1384. friend = GNUNET_HELLO_is_friend_only (hm);
  1385. if ( ( (GNUNET_YES != friend) &&
  1386. (GNUNET_NO != friend) ) ||
  1387. (GNUNET_OK != GNUNET_HELLO_get_id (hm, &pid)) )
  1388. {
  1389. /* malformed HELLO */
  1390. GNUNET_break_op (0);
  1391. return GNUNET_SYSERR;
  1392. }
  1393. if (0 ==
  1394. memcmp (&GST_my_identity,
  1395. &pid,
  1396. sizeof (struct GNUNET_PeerIdentity)))
  1397. {
  1398. /* got our own HELLO, how boring */
  1399. return GNUNET_OK;
  1400. }
  1401. if (GNUNET_NO ==
  1402. GNUNET_CONTAINER_multipeermap_contains (validation_map,
  1403. &pid))
  1404. {
  1405. /* Add peer identity without addresses to peerinfo service */
  1406. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1407. "Adding HELLO without addresses for peer `%s'\n",
  1408. GNUNET_i2s (&pid));
  1409. h = GNUNET_HELLO_create (&pid.public_key, NULL, NULL, friend);
  1410. GNUNET_PEERINFO_add_peer (GST_peerinfo, h, NULL, NULL);
  1411. GNUNET_free (h);
  1412. }
  1413. else
  1414. {
  1415. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1416. "Validation received HELLO message for peer `%s' with size %u, checking for new addresses\n",
  1417. GNUNET_i2s (&pid),
  1418. ntohs (hello->size));
  1419. }
  1420. GNUNET_assert (NULL ==
  1421. GNUNET_HELLO_iterate_addresses (hm,
  1422. GNUNET_NO,
  1423. &validate_address_iterator,
  1424. NULL));
  1425. return GNUNET_OK;
  1426. }
  1427. /**
  1428. * Closure for #iterate_addresses().
  1429. */
  1430. struct IteratorContext
  1431. {
  1432. /**
  1433. * Function to call on each address.
  1434. */
  1435. GST_ValidationAddressCallback cb;
  1436. /**
  1437. * Closure for @e cb.
  1438. */
  1439. void *cb_cls;
  1440. };
  1441. /**
  1442. * Call the callback in the closure for each validation entry.
  1443. *
  1444. * @param cls the `struct IteratorContext`
  1445. * @param key the peer's identity
  1446. * @param value the `struct ValidationEntry`
  1447. * @return #GNUNET_OK (continue to iterate)
  1448. */
  1449. static int
  1450. iterate_addresses (void *cls,
  1451. const struct GNUNET_PeerIdentity *key,
  1452. void *value)
  1453. {
  1454. struct IteratorContext *ic = cls;
  1455. struct ValidationEntry *ve = value;
  1456. ic->cb (ic->cb_cls,
  1457. ve->valid_until,
  1458. ve->revalidation_block,
  1459. ve->address);
  1460. return GNUNET_OK;
  1461. }
  1462. /**
  1463. * Call the given function for each address for the given target.
  1464. * Can either give a snapshot (synchronous API) or be continuous.
  1465. *
  1466. * @param target peer information is requested for
  1467. * @param cb function to call; will not be called after this function returns
  1468. * @param cb_cls closure for @a cb
  1469. */
  1470. void
  1471. GST_validation_get_addresses (const struct GNUNET_PeerIdentity *target,
  1472. GST_ValidationAddressCallback cb,
  1473. void *cb_cls)
  1474. {
  1475. struct IteratorContext ic;
  1476. ic.cb = cb;
  1477. ic.cb_cls = cb_cls;
  1478. GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
  1479. target,
  1480. &iterate_addresses, &ic);
  1481. }
  1482. /**
  1483. * Update if we are using an address for a connection actively right now.
  1484. * Based on this, the validation module will measure latency for the
  1485. * address more or less often.
  1486. *
  1487. * @param address the address that we are now using (or not)
  1488. * @param in_use #GNUNET_YES if we are now using the address for a connection,
  1489. * #GNUNET_NO if we are no longer using the address for a connection
  1490. */
  1491. void
  1492. GST_validation_set_address_use (const struct GNUNET_HELLO_Address *address,
  1493. int in_use)
  1494. {
  1495. struct ValidationEntry *ve;
  1496. if (GNUNET_HELLO_address_check_option (address,
  1497. GNUNET_HELLO_ADDRESS_INFO_INBOUND))
  1498. return; /* ignore inbound for validation */
  1499. if (NULL == GST_plugins_find (address->transport_name))
  1500. {
  1501. /* How can we use an address for which we don't have the plugin? */
  1502. GNUNET_break (0);
  1503. return;
  1504. }
  1505. ve = find_validation_entry (address);
  1506. if (NULL == ve)
  1507. {
  1508. GNUNET_break (0);
  1509. return;
  1510. }
  1511. if (in_use == ve->in_use)
  1512. return;
  1513. ve->in_use = in_use;
  1514. if (GNUNET_YES == in_use)
  1515. {
  1516. /* from now on, higher frequeny, so reschedule now */
  1517. if (NULL != ve->revalidation_task)
  1518. GNUNET_SCHEDULER_cancel (ve->revalidation_task);
  1519. ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address,
  1520. ve);
  1521. }
  1522. }
  1523. /**
  1524. * Closure for the validation_entries_iterate function.
  1525. */
  1526. struct ValidationIteratorContext
  1527. {
  1528. /**
  1529. * Function to call on each validation entry
  1530. */
  1531. GST_ValidationChangedCallback cb;
  1532. /**
  1533. * Closure for @e cb.
  1534. */
  1535. void *cb_cls;
  1536. };
  1537. /**
  1538. * Function called on each entry in the validation map.
  1539. * Passes the information from the validation entry to
  1540. * the callback given in the closure.
  1541. *
  1542. * @param cls the `struct ValidationIteratorContext`
  1543. * @param key peer this is about
  1544. * @param value the `struct ValidationEntry`
  1545. * @return #GNUNET_OK (continue to iterate)
  1546. */
  1547. static int
  1548. validation_entries_iterate (void *cls,
  1549. const struct GNUNET_PeerIdentity *key,
  1550. void *value)
  1551. {
  1552. struct ValidationIteratorContext *ic = cls;
  1553. struct ValidationEntry *ve = value;
  1554. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1555. "Notifying about validation entry for peer `%s' address `%s' \n",
  1556. GNUNET_i2s (&ve->address->peer),
  1557. GST_plugins_a2s (ve->address));
  1558. ic->cb (ic->cb_cls,
  1559. ve->address,
  1560. ve->send_time,
  1561. ve->valid_until,
  1562. ve->next_validation,
  1563. ve->state);
  1564. return GNUNET_OK;
  1565. }
  1566. /**
  1567. * Iterate over all iteration entries
  1568. *
  1569. * @param cb function to call
  1570. * @param cb_cls closure for @a cb
  1571. */
  1572. void
  1573. GST_validation_iterate (GST_ValidationChangedCallback cb,
  1574. void *cb_cls)
  1575. {
  1576. struct ValidationIteratorContext ic;
  1577. if (NULL == validation_map)
  1578. return; /* can happen during shutdown */
  1579. ic.cb = cb;
  1580. ic.cb_cls = cb_cls;
  1581. GNUNET_CONTAINER_multipeermap_iterate (validation_map,
  1582. &validation_entries_iterate,
  1583. &ic);
  1584. }
  1585. /* end of file gnunet-service-transport_validation.c */