gnunet-service-transport_validation.c 57 KB

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