gnunet-namestore.c 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012, 2013, 2014, 2019 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 gnunet-namestore.c
  18. * @brief command line tool to manipulate the local zone
  19. * @author Christian Grothoff
  20. *
  21. * TODO:
  22. * - test
  23. */
  24. #include "platform.h"
  25. #include <gnunet_util_lib.h>
  26. #include <gnunet_dnsparser_lib.h>
  27. #include <gnunet_identity_service.h>
  28. #include <gnunet_gnsrecord_lib.h>
  29. #include <gnunet_gns_service.h>
  30. #include <gnunet_namestore_service.h>
  31. /**
  32. * Entry in record set for bulk processing.
  33. */
  34. struct RecordSetEntry
  35. {
  36. /**
  37. * Kept in a linked list.
  38. */
  39. struct RecordSetEntry *next;
  40. /**
  41. * The record to add/remove.
  42. */
  43. struct GNUNET_GNSRECORD_Data record;
  44. };
  45. /**
  46. * Handle to the namestore.
  47. */
  48. static struct GNUNET_NAMESTORE_Handle *ns;
  49. /**
  50. * Private key for the our zone.
  51. */
  52. static struct GNUNET_IDENTITY_PrivateKey zone_pkey;
  53. /**
  54. * Handle to identity lookup.
  55. */
  56. static struct GNUNET_IDENTITY_EgoLookup *el;
  57. /**
  58. * Identity service handle
  59. */
  60. static struct GNUNET_IDENTITY_Handle *idh;
  61. /**
  62. * Obtain default ego
  63. */
  64. struct GNUNET_IDENTITY_Operation *get_default;
  65. /**
  66. * Name of the ego controlling the zone.
  67. */
  68. static char *ego_name;
  69. /**
  70. * Desired action is to add a record.
  71. */
  72. static int add;
  73. /**
  74. * Queue entry for the 'add-uri' operation.
  75. */
  76. static struct GNUNET_NAMESTORE_QueueEntry *add_qe_uri;
  77. /**
  78. * Queue entry for the 'add' operation.
  79. */
  80. static struct GNUNET_NAMESTORE_QueueEntry *add_qe;
  81. /**
  82. * Queue entry for the 'lookup' operation.
  83. */
  84. static struct GNUNET_NAMESTORE_QueueEntry *get_qe;
  85. /**
  86. * Queue entry for the 'reverse lookup' operation (in combination with a name).
  87. */
  88. static struct GNUNET_NAMESTORE_QueueEntry *reverse_qe;
  89. /**
  90. * Desired action is to list records.
  91. */
  92. static int list;
  93. /**
  94. * List iterator for the 'list' operation.
  95. */
  96. static struct GNUNET_NAMESTORE_ZoneIterator *list_it;
  97. /**
  98. * Desired action is to remove a record.
  99. */
  100. static int del;
  101. /**
  102. * Is record public (opposite of #GNUNET_GNSRECORD_RF_PRIVATE)
  103. */
  104. static int is_public;
  105. /**
  106. * Is record a shadow record (#GNUNET_GNSRECORD_RF_SHADOW_RECORD)
  107. */
  108. static int is_shadow;
  109. /**
  110. * Queue entry for the 'del' operation.
  111. */
  112. static struct GNUNET_NAMESTORE_QueueEntry *del_qe;
  113. /**
  114. * Queue entry for the 'set/replace' operation.
  115. */
  116. static struct GNUNET_NAMESTORE_QueueEntry *set_qe;
  117. /**
  118. * Name of the records to add/list/remove.
  119. */
  120. static char *name;
  121. /**
  122. * Value of the record to add/remove.
  123. */
  124. static char *value;
  125. /**
  126. * URI to import.
  127. */
  128. static char *uri;
  129. /**
  130. * Reverse lookup to perform.
  131. */
  132. static char *reverse_pkey;
  133. /**
  134. * Type of the record to add/remove, NULL to remove all.
  135. */
  136. static char *typestring;
  137. /**
  138. * Desired expiration time.
  139. */
  140. static char *expirationstring;
  141. /**
  142. * Desired nick name.
  143. */
  144. static char *nickstring;
  145. /**
  146. * Global return value
  147. */
  148. static int ret;
  149. /**
  150. * Type string converted to DNS type value.
  151. */
  152. static uint32_t type;
  153. /**
  154. * Value in binary format.
  155. */
  156. static void *data;
  157. /**
  158. * Number of bytes in #data.
  159. */
  160. static size_t data_size;
  161. /**
  162. * Expiration string converted to numeric value.
  163. */
  164. static uint64_t etime;
  165. /**
  166. * Is expiration time relative or absolute time?
  167. */
  168. static int etime_is_rel = GNUNET_SYSERR;
  169. /**
  170. * Monitor handle.
  171. */
  172. static struct GNUNET_NAMESTORE_ZoneMonitor *zm;
  173. /**
  174. * Enables monitor mode.
  175. */
  176. static int monitor;
  177. /**
  178. * Entry in record set for processing records in bulk.
  179. */
  180. static struct RecordSetEntry *recordset;
  181. /**
  182. * Task run on shutdown. Cleans up everything.
  183. *
  184. * @param cls unused
  185. */
  186. static void
  187. do_shutdown (void *cls)
  188. {
  189. (void) cls;
  190. if (NULL != get_default)
  191. {
  192. GNUNET_IDENTITY_cancel (get_default);
  193. get_default = NULL;
  194. }
  195. if (NULL != idh)
  196. {
  197. GNUNET_IDENTITY_disconnect (idh);
  198. idh = NULL;
  199. }
  200. if (NULL != el)
  201. {
  202. GNUNET_IDENTITY_ego_lookup_cancel (el);
  203. el = NULL;
  204. }
  205. if (NULL != list_it)
  206. {
  207. GNUNET_NAMESTORE_zone_iteration_stop (list_it);
  208. list_it = NULL;
  209. }
  210. if (NULL != add_qe)
  211. {
  212. GNUNET_NAMESTORE_cancel (add_qe);
  213. add_qe = NULL;
  214. }
  215. if (NULL != set_qe)
  216. {
  217. GNUNET_NAMESTORE_cancel (set_qe);
  218. set_qe = NULL;
  219. }
  220. if (NULL != add_qe_uri)
  221. {
  222. GNUNET_NAMESTORE_cancel (add_qe_uri);
  223. add_qe_uri = NULL;
  224. }
  225. if (NULL != get_qe)
  226. {
  227. GNUNET_NAMESTORE_cancel (get_qe);
  228. get_qe = NULL;
  229. }
  230. if (NULL != del_qe)
  231. {
  232. GNUNET_NAMESTORE_cancel (del_qe);
  233. del_qe = NULL;
  234. }
  235. if (NULL != ns)
  236. {
  237. GNUNET_NAMESTORE_disconnect (ns);
  238. ns = NULL;
  239. }
  240. memset (&zone_pkey, 0, sizeof(zone_pkey));
  241. if (NULL != uri)
  242. {
  243. GNUNET_free (uri);
  244. uri = NULL;
  245. }
  246. if (NULL != zm)
  247. {
  248. GNUNET_NAMESTORE_zone_monitor_stop (zm);
  249. zm = NULL;
  250. }
  251. if (NULL != data)
  252. {
  253. GNUNET_free (data);
  254. data = NULL;
  255. }
  256. }
  257. /**
  258. * Check if we are finished, and if so, perform shutdown.
  259. */
  260. static void
  261. test_finished ()
  262. {
  263. if ((NULL == add_qe) && (NULL == add_qe_uri) && (NULL == get_qe) &&
  264. (NULL == del_qe) && (NULL == reverse_qe) && (NULL == list_it))
  265. GNUNET_SCHEDULER_shutdown ();
  266. }
  267. /**
  268. * Continuation called to notify client about result of the
  269. * operation.
  270. *
  271. * @param cls closure, location of the QueueEntry pointer to NULL out
  272. * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
  273. * #GNUNET_NO if content was already there
  274. * #GNUNET_YES (or other positive value) on success
  275. * @param emsg NULL on success, otherwise an error message
  276. */
  277. static void
  278. add_continuation (void *cls, int32_t success, const char *emsg)
  279. {
  280. struct GNUNET_NAMESTORE_QueueEntry **qe = cls;
  281. *qe = NULL;
  282. if (GNUNET_YES != success)
  283. {
  284. fprintf (stderr,
  285. _ ("Adding record failed: %s\n"),
  286. (GNUNET_NO == success) ? "record exists" : emsg);
  287. if (GNUNET_NO != success)
  288. ret = 1;
  289. }
  290. ret = 0;
  291. test_finished ();
  292. }
  293. /**
  294. * Continuation called to notify client about result of the
  295. * operation.
  296. *
  297. * @param cls closure, unused
  298. * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
  299. * #GNUNET_NO if content was already there
  300. * #GNUNET_YES (or other positive value) on success
  301. * @param emsg NULL on success, otherwise an error message
  302. */
  303. static void
  304. del_continuation (void *cls, int32_t success, const char *emsg)
  305. {
  306. (void) cls;
  307. del_qe = NULL;
  308. if (GNUNET_NO == success)
  309. {
  310. fprintf (stderr,
  311. _ ("Deleting record failed, record does not exist%s%s\n"),
  312. (NULL != emsg) ? ": " : "",
  313. (NULL != emsg) ? emsg : "");
  314. }
  315. if (GNUNET_SYSERR == success)
  316. {
  317. fprintf (stderr,
  318. _ ("Deleting record failed%s%s\n"),
  319. (NULL != emsg) ? ": " : "",
  320. (NULL != emsg) ? emsg : "");
  321. }
  322. test_finished ();
  323. }
  324. /**
  325. * Function called when we are done with a zone iteration.
  326. */
  327. static void
  328. zone_iteration_finished (void *cls)
  329. {
  330. (void) cls;
  331. list_it = NULL;
  332. test_finished ();
  333. }
  334. /**
  335. * Function called when we encountered an error in a zone iteration.
  336. */
  337. static void
  338. zone_iteration_error_cb (void *cls)
  339. {
  340. (void) cls;
  341. list_it = NULL;
  342. fprintf (stderr, "Error iterating over zone\n");
  343. ret = 1;
  344. test_finished ();
  345. }
  346. /**
  347. * Process a record that was stored in the namestore.
  348. *
  349. * @param rname name that is being mapped (at most 255 characters long)
  350. * @param rd_len number of entries in @a rd array
  351. * @param rd array of records with data to store
  352. */
  353. static void
  354. display_record (const char *rname,
  355. unsigned int rd_len,
  356. const struct GNUNET_GNSRECORD_Data *rd)
  357. {
  358. const char *typestr;
  359. char *s;
  360. const char *ets;
  361. struct GNUNET_TIME_Absolute at;
  362. struct GNUNET_TIME_Relative rt;
  363. int have_record;
  364. if ((NULL != name) && (0 != strcmp (name, rname)))
  365. {
  366. GNUNET_NAMESTORE_zone_iterator_next (list_it, 1);
  367. return;
  368. }
  369. have_record = GNUNET_NO;
  370. for (unsigned int i = 0; i < rd_len; i++)
  371. {
  372. if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
  373. (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)))
  374. continue;
  375. if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type))
  376. continue;
  377. have_record = GNUNET_YES;
  378. break;
  379. }
  380. if (GNUNET_NO == have_record)
  381. return;
  382. fprintf (stdout, "%s:\n", rname);
  383. if (NULL != typestring)
  384. type = GNUNET_GNSRECORD_typename_to_number (typestring);
  385. else
  386. type = GNUNET_GNSRECORD_TYPE_ANY;
  387. for (unsigned int i = 0; i < rd_len; i++)
  388. {
  389. if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
  390. (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)))
  391. continue;
  392. if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type))
  393. continue;
  394. typestr = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
  395. s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
  396. rd[i].data,
  397. rd[i].data_size);
  398. if (NULL == s)
  399. {
  400. fprintf (stdout,
  401. _ ("\tCorrupt or unsupported record of type %u\n"),
  402. (unsigned int) rd[i].record_type);
  403. continue;
  404. }
  405. if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
  406. {
  407. rt.rel_value_us = rd[i].expiration_time;
  408. ets = GNUNET_STRINGS_relative_time_to_string (rt, GNUNET_YES);
  409. }
  410. else
  411. {
  412. at.abs_value_us = rd[i].expiration_time;
  413. ets = GNUNET_STRINGS_absolute_time_to_string (at);
  414. }
  415. fprintf (stdout,
  416. "\t%s: %s (%s)\t%s\t%s\n",
  417. typestr,
  418. s,
  419. ets,
  420. (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) ? "PRIVATE"
  421. : "PUBLIC",
  422. (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)) ? "SHADOW"
  423. : "");
  424. GNUNET_free (s);
  425. }
  426. fprintf (stdout, "%s", "\n");
  427. }
  428. /**
  429. * Process a record that was stored in the namestore.
  430. *
  431. * @param cls closure
  432. * @param zone_key private key of the zone
  433. * @param rname name that is being mapped (at most 255 characters long)
  434. * @param rd_len number of entries in @a rd array
  435. * @param rd array of records with data to store
  436. */
  437. static void
  438. display_record_iterator (void *cls,
  439. const struct GNUNET_IDENTITY_PrivateKey *zone_key,
  440. const char *rname,
  441. unsigned int rd_len,
  442. const struct GNUNET_GNSRECORD_Data *rd)
  443. {
  444. (void) cls;
  445. (void) zone_key;
  446. display_record (rname, rd_len, rd);
  447. GNUNET_NAMESTORE_zone_iterator_next (list_it, 1);
  448. }
  449. /**
  450. * Process a record that was stored in the namestore.
  451. *
  452. * @param cls closure
  453. * @param zone_key private key of the zone
  454. * @param rname name that is being mapped (at most 255 characters long)
  455. * @param rd_len number of entries in @a rd array
  456. * @param rd array of records with data to store
  457. */
  458. static void
  459. display_record_monitor (void *cls,
  460. const struct GNUNET_IDENTITY_PrivateKey *zone_key,
  461. const char *rname,
  462. unsigned int rd_len,
  463. const struct GNUNET_GNSRECORD_Data *rd)
  464. {
  465. (void) cls;
  466. (void) zone_key;
  467. display_record (rname, rd_len, rd);
  468. GNUNET_NAMESTORE_zone_monitor_next (zm, 1);
  469. }
  470. /**
  471. * Process a record that was stored in the namestore.
  472. *
  473. * @param cls closure
  474. * @param zone_key private key of the zone
  475. * @param rname name that is being mapped (at most 255 characters long)
  476. * @param rd_len number of entries in @a rd array
  477. * @param rd array of records with data to store
  478. */
  479. static void
  480. display_record_lookup (void *cls,
  481. const struct GNUNET_IDENTITY_PrivateKey *zone_key,
  482. const char *rname,
  483. unsigned int rd_len,
  484. const struct GNUNET_GNSRECORD_Data *rd)
  485. {
  486. (void) cls;
  487. (void) zone_key;
  488. get_qe = NULL;
  489. display_record (rname, rd_len, rd);
  490. test_finished ();
  491. }
  492. /**
  493. * Function called once we are in sync in monitor mode.
  494. *
  495. * @param cls NULL
  496. */
  497. static void
  498. sync_cb (void *cls)
  499. {
  500. (void) cls;
  501. fprintf (stdout, "%s", "Monitor is now in sync.\n");
  502. }
  503. /**
  504. * Function called on errors while monitoring.
  505. *
  506. * @param cls NULL
  507. */
  508. static void
  509. monitor_error_cb (void *cls)
  510. {
  511. (void) cls;
  512. fprintf (stderr, "%s", "Monitor disconnected and out of sync.\n");
  513. }
  514. /**
  515. * Function called on errors while monitoring.
  516. *
  517. * @param cls NULL
  518. */
  519. static void
  520. lookup_error_cb (void *cls)
  521. {
  522. (void) cls;
  523. get_qe = NULL;
  524. fprintf (stderr, "%s", "Failed to lookup record.\n");
  525. test_finished ();
  526. }
  527. /**
  528. * Function called if lookup fails.
  529. */
  530. static void
  531. add_error_cb (void *cls)
  532. {
  533. (void) cls;
  534. add_qe = NULL;
  535. GNUNET_break (0);
  536. ret = 1;
  537. test_finished ();
  538. }
  539. /**
  540. * We're storing a record; this function is given the existing record
  541. * so that we can merge the information.
  542. *
  543. * @param cls closure, unused
  544. * @param zone_key private key of the zone
  545. * @param rec_name name that is being mapped (at most 255 characters long)
  546. * @param rd_count number of entries in @a rd array
  547. * @param rd array of records with data to store
  548. */
  549. static void
  550. get_existing_record (void *cls,
  551. const struct GNUNET_IDENTITY_PrivateKey *zone_key,
  552. const char *rec_name,
  553. unsigned int rd_count,
  554. const struct GNUNET_GNSRECORD_Data *rd)
  555. {
  556. struct GNUNET_GNSRECORD_Data rdn[rd_count + 1];
  557. struct GNUNET_GNSRECORD_Data *rde;
  558. (void) cls;
  559. (void) zone_key;
  560. add_qe = NULL;
  561. if (0 != strcmp (rec_name, name))
  562. {
  563. GNUNET_break (0);
  564. ret = 1;
  565. test_finished ();
  566. return;
  567. }
  568. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  569. "Received %u records for name `%s'\n",
  570. rd_count,
  571. rec_name);
  572. for (unsigned int i = 0; i < rd_count; i++)
  573. {
  574. switch (rd[i].record_type)
  575. {
  576. case GNUNET_DNSPARSER_TYPE_CNAME:
  577. fprintf (
  578. stderr,
  579. _ (
  580. "A %s record exists already under `%s', no other records can be added.\n"),
  581. "CNAME",
  582. rec_name);
  583. ret = 1;
  584. test_finished ();
  585. return;
  586. case GNUNET_GNSRECORD_TYPE_PKEY:
  587. case GNUNET_GNSRECORD_TYPE_EDKEY:
  588. fprintf (
  589. stderr,
  590. _ (
  591. "A zone key record exists already under `%s', no other records can be added.\n"),
  592. rec_name);
  593. ret = 1;
  594. test_finished ();
  595. return;
  596. case GNUNET_DNSPARSER_TYPE_SOA:
  597. if (GNUNET_DNSPARSER_TYPE_SOA == type)
  598. {
  599. fprintf (
  600. stderr,
  601. _ (
  602. "A SOA record exists already under `%s', cannot add a second SOA to the same zone.\n"),
  603. rec_name);
  604. ret = 1;
  605. test_finished ();
  606. return;
  607. }
  608. break;
  609. }
  610. }
  611. switch (type)
  612. {
  613. case GNUNET_DNSPARSER_TYPE_CNAME:
  614. if (0 != rd_count)
  615. {
  616. fprintf (stderr,
  617. _ (
  618. "Records already exist under `%s', cannot add `%s' record.\n"),
  619. rec_name,
  620. "CNAME");
  621. ret = 1;
  622. test_finished ();
  623. return;
  624. }
  625. break;
  626. case GNUNET_GNSRECORD_TYPE_PKEY:
  627. case GNUNET_GNSRECORD_TYPE_EDKEY:
  628. if (0 != rd_count)
  629. {
  630. fprintf (stderr,
  631. _ (
  632. "Records already exist under `%s', cannot add record.\n"),
  633. rec_name);
  634. ret = 1;
  635. test_finished ();
  636. return;
  637. }
  638. break;
  639. case GNUNET_GNSRECORD_TYPE_GNS2DNS:
  640. for (unsigned int i = 0; i < rd_count; i++)
  641. if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
  642. {
  643. fprintf (
  644. stderr,
  645. _ (
  646. "Non-GNS2DNS records already exist under `%s', cannot add GNS2DNS record.\n"),
  647. rec_name);
  648. ret = 1;
  649. test_finished ();
  650. return;
  651. }
  652. break;
  653. }
  654. memset (rdn, 0, sizeof(struct GNUNET_GNSRECORD_Data));
  655. GNUNET_memcpy (&rdn[1], rd, rd_count * sizeof(struct GNUNET_GNSRECORD_Data));
  656. rde = &rdn[0];
  657. rde->data = data;
  658. rde->data_size = data_size;
  659. rde->record_type = type;
  660. if (1 == is_shadow)
  661. rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
  662. if (1 != is_public)
  663. rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
  664. rde->expiration_time = etime;
  665. if (GNUNET_YES == etime_is_rel)
  666. rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
  667. else if (GNUNET_NO != etime_is_rel)
  668. rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
  669. GNUNET_assert (NULL != name);
  670. add_qe = GNUNET_NAMESTORE_records_store (ns,
  671. &zone_pkey,
  672. name,
  673. rd_count + 1,
  674. rde,
  675. &add_continuation,
  676. &add_qe);
  677. }
  678. /**
  679. * Function called if we encountered an error in zone-to-name.
  680. */
  681. static void
  682. reverse_error_cb (void *cls)
  683. {
  684. (void) cls;
  685. reverse_qe = NULL;
  686. fprintf (stdout, "%s.zkey\n", reverse_pkey);
  687. }
  688. /**
  689. * Function called with the result of our attempt to obtain a name for a given
  690. * public key.
  691. *
  692. * @param cls NULL
  693. * @param zone private key of the zone; NULL on disconnect
  694. * @param label label of the records; NULL on disconnect
  695. * @param rd_count number of entries in @a rd array, 0 if label was deleted
  696. * @param rd array of records with data to store
  697. */
  698. static void
  699. handle_reverse_lookup (void *cls,
  700. const struct GNUNET_IDENTITY_PrivateKey *zone,
  701. const char *label,
  702. unsigned int rd_count,
  703. const struct GNUNET_GNSRECORD_Data *rd)
  704. {
  705. (void) cls;
  706. (void) zone;
  707. (void) rd_count;
  708. (void) rd;
  709. reverse_qe = NULL;
  710. if (NULL == label)
  711. fprintf (stdout, "%s\n", reverse_pkey);
  712. else
  713. fprintf (stdout, "%s.%s\n", label, ego_name);
  714. test_finished ();
  715. }
  716. /**
  717. * Function called if lookup for deletion fails.
  718. */
  719. static void
  720. del_lookup_error_cb (void *cls)
  721. {
  722. (void) cls;
  723. del_qe = NULL;
  724. GNUNET_break (0);
  725. ret = 1;
  726. test_finished ();
  727. }
  728. /**
  729. * We were asked to delete something; this function is called with
  730. * the existing records. Now we should determine what should be
  731. * deleted and then issue the deletion operation.
  732. *
  733. * @param cls NULL
  734. * @param zone private key of the zone we are deleting from
  735. * @param label name of the records we are editing
  736. * @param rd_count size of the @a rd array
  737. * @param rd existing records
  738. */
  739. static void
  740. del_monitor (void *cls,
  741. const struct GNUNET_IDENTITY_PrivateKey *zone,
  742. const char *label,
  743. unsigned int rd_count,
  744. const struct GNUNET_GNSRECORD_Data *rd)
  745. {
  746. struct GNUNET_GNSRECORD_Data rdx[rd_count];
  747. unsigned int rd_left;
  748. uint32_t type;
  749. char *vs;
  750. (void) cls;
  751. (void) zone;
  752. del_qe = NULL;
  753. if (0 == rd_count)
  754. {
  755. fprintf (stderr,
  756. _ (
  757. "There are no records under label `%s' that could be deleted.\n"),
  758. label);
  759. ret = 1;
  760. test_finished ();
  761. return;
  762. }
  763. if ((NULL == value) && (NULL == typestring))
  764. {
  765. /* delete everything */
  766. del_qe = GNUNET_NAMESTORE_records_store (ns,
  767. &zone_pkey,
  768. name,
  769. 0,
  770. NULL,
  771. &del_continuation,
  772. NULL);
  773. return;
  774. }
  775. rd_left = 0;
  776. if (NULL != typestring)
  777. type = GNUNET_GNSRECORD_typename_to_number (typestring);
  778. else
  779. type = GNUNET_GNSRECORD_TYPE_ANY;
  780. for (unsigned int i = 0; i < rd_count; i++)
  781. {
  782. vs = NULL;
  783. if (! (((GNUNET_GNSRECORD_TYPE_ANY == type) ||
  784. (rd[i].record_type == type)) &&
  785. ((NULL == value) ||
  786. (NULL ==
  787. (vs = (GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
  788. rd[i].data,
  789. rd[i].data_size)))) ||
  790. (0 == strcmp (vs, value)))))
  791. rdx[rd_left++] = rd[i];
  792. GNUNET_free (vs);
  793. }
  794. if (rd_count == rd_left)
  795. {
  796. /* nothing got deleted */
  797. fprintf (
  798. stderr,
  799. _ (
  800. "There are no records under label `%s' that match the request for deletion.\n"),
  801. label);
  802. test_finished ();
  803. return;
  804. }
  805. /* delete everything but what we copied to 'rdx' */
  806. del_qe = GNUNET_NAMESTORE_records_store (ns,
  807. &zone_pkey,
  808. name,
  809. rd_left,
  810. rdx,
  811. &del_continuation,
  812. NULL);
  813. }
  814. /**
  815. * Parse expiration time.
  816. *
  817. * @param expirationstring text to parse
  818. * @param etime_is_rel[out] set to #GNUNET_YES if time is relative
  819. * @param etime[out] set to expiration time (abs or rel)
  820. * @return #GNUNET_OK on success
  821. */
  822. static int
  823. parse_expiration (const char *expirationstring,
  824. int *etime_is_rel,
  825. uint64_t *etime)
  826. {
  827. struct GNUNET_TIME_Relative etime_rel;
  828. struct GNUNET_TIME_Absolute etime_abs;
  829. if (0 == strcmp (expirationstring, "never"))
  830. {
  831. *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
  832. *etime_is_rel = GNUNET_NO;
  833. return GNUNET_OK;
  834. }
  835. if (GNUNET_OK ==
  836. GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel))
  837. {
  838. *etime_is_rel = GNUNET_YES;
  839. *etime = etime_rel.rel_value_us;
  840. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  841. "Storing record with relative expiration time of %s\n",
  842. GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO));
  843. return GNUNET_OK;
  844. }
  845. if (GNUNET_OK ==
  846. GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs))
  847. {
  848. *etime_is_rel = GNUNET_NO;
  849. *etime = etime_abs.abs_value_us;
  850. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  851. "Storing record with absolute expiration time of %s\n",
  852. GNUNET_STRINGS_absolute_time_to_string (etime_abs));
  853. return GNUNET_OK;
  854. }
  855. return GNUNET_SYSERR;
  856. }
  857. /**
  858. * Function called when namestore is done with the replace
  859. * operation.
  860. *
  861. * @param cls NULL
  862. * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
  863. * #GNUNET_NO if content was already there or not found
  864. * #GNUNET_YES (or other positive value) on success
  865. * @param emsg NULL on success, otherwise an error message
  866. */
  867. static void
  868. replace_cont (void *cls, int success, const char *emsg)
  869. {
  870. (void) cls;
  871. set_qe = NULL;
  872. if (GNUNET_OK != success)
  873. {
  874. GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
  875. _ ("Failed to replace records: %s\n"),
  876. emsg);
  877. ret = 1; /* fail from 'main' */
  878. }
  879. GNUNET_SCHEDULER_shutdown ();
  880. }
  881. /**
  882. * We have obtained the zone's private key, so now process
  883. * the main commands using it.
  884. *
  885. * @param cfg configuration to use
  886. */
  887. static void
  888. run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
  889. {
  890. struct GNUNET_GNSRECORD_Data rd;
  891. if (! (add | del | list | (NULL != nickstring) | (NULL != uri)
  892. | (NULL != reverse_pkey) | (NULL != recordset)))
  893. {
  894. /* nothing more to be done */
  895. fprintf (stderr, _ ("No options given\n"));
  896. GNUNET_SCHEDULER_shutdown ();
  897. return;
  898. }
  899. ns = GNUNET_NAMESTORE_connect (cfg);
  900. if (NULL == ns)
  901. {
  902. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  903. _ ("Failed to connect to namestore\n"));
  904. return;
  905. }
  906. if (NULL != recordset)
  907. {
  908. /* replace entire record set */
  909. unsigned int rd_count;
  910. struct GNUNET_GNSRECORD_Data *rd;
  911. if (NULL == name)
  912. {
  913. fprintf (stderr,
  914. _ ("Missing option `%s' for operation `%s'\n"),
  915. "-R",
  916. _ ("replace"));
  917. GNUNET_SCHEDULER_shutdown ();
  918. ret = 1;
  919. return;
  920. }
  921. rd_count = 0;
  922. for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next)
  923. rd_count++;
  924. rd = GNUNET_new_array (rd_count, struct GNUNET_GNSRECORD_Data);
  925. rd_count = 0;
  926. for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next)
  927. {
  928. rd[rd_count] = e->record;
  929. rd_count++;
  930. }
  931. set_qe = GNUNET_NAMESTORE_records_store (ns,
  932. &zone_pkey,
  933. name,
  934. rd_count,
  935. rd,
  936. &replace_cont,
  937. NULL);
  938. GNUNET_free (rd);
  939. return;
  940. }
  941. if (NULL != nickstring)
  942. {
  943. if (0 == strlen (nickstring))
  944. {
  945. fprintf (stderr, _ ("Invalid nick `%s'\n"), nickstring);
  946. GNUNET_SCHEDULER_shutdown ();
  947. ret = 1;
  948. return;
  949. }
  950. add = 1;
  951. typestring = GNUNET_strdup (GNUNET_GNSRECORD_number_to_typename (
  952. GNUNET_GNSRECORD_TYPE_NICK));
  953. name = GNUNET_strdup (GNUNET_GNS_EMPTY_LABEL_AT);
  954. value = GNUNET_strdup (nickstring);
  955. is_public = 0;
  956. expirationstring = GNUNET_strdup ("never");
  957. GNUNET_free (nickstring);
  958. nickstring = NULL;
  959. }
  960. if (add)
  961. {
  962. if (NULL == name)
  963. {
  964. fprintf (stderr,
  965. _ ("Missing option `%s' for operation `%s'\n"),
  966. "-n",
  967. _ ("add"));
  968. GNUNET_SCHEDULER_shutdown ();
  969. ret = 1;
  970. return;
  971. }
  972. if (NULL == typestring)
  973. {
  974. fprintf (stderr,
  975. _ ("Missing option `%s' for operation `%s'\n"),
  976. "-t",
  977. _ ("add"));
  978. GNUNET_SCHEDULER_shutdown ();
  979. ret = 1;
  980. return;
  981. }
  982. type = GNUNET_GNSRECORD_typename_to_number (typestring);
  983. if (UINT32_MAX == type)
  984. {
  985. fprintf (stderr, _ ("Unsupported type `%s'\n"), typestring);
  986. GNUNET_SCHEDULER_shutdown ();
  987. ret = 1;
  988. return;
  989. }
  990. if ((GNUNET_DNSPARSER_TYPE_SRV == type) ||
  991. (GNUNET_DNSPARSER_TYPE_TLSA == type) ||
  992. (GNUNET_DNSPARSER_TYPE_OPENPGPKEY == type))
  993. {
  994. fprintf (stderr,
  995. _ ("For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"));
  996. fprintf (stderr, ", please use a `BOX' record instead\n");
  997. GNUNET_SCHEDULER_shutdown ();
  998. ret = 1;
  999. return;
  1000. }
  1001. if (NULL == value)
  1002. {
  1003. fprintf (stderr,
  1004. _ ("Missing option `%s' for operation `%s'\n"),
  1005. "-V",
  1006. _ ("add"));
  1007. ret = 1;
  1008. GNUNET_SCHEDULER_shutdown ();
  1009. return;
  1010. }
  1011. if (GNUNET_OK !=
  1012. GNUNET_GNSRECORD_string_to_value (type, value, &data, &data_size))
  1013. {
  1014. fprintf (stderr,
  1015. _ ("Value `%s' invalid for record type `%s'\n"),
  1016. value,
  1017. typestring);
  1018. GNUNET_SCHEDULER_shutdown ();
  1019. ret = 1;
  1020. return;
  1021. }
  1022. if (NULL == expirationstring)
  1023. {
  1024. fprintf (stderr,
  1025. _ ("Missing option `%s' for operation `%s'\n"),
  1026. "-e",
  1027. _ ("add"));
  1028. GNUNET_SCHEDULER_shutdown ();
  1029. ret = 1;
  1030. return;
  1031. }
  1032. if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime))
  1033. {
  1034. fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring);
  1035. GNUNET_SCHEDULER_shutdown ();
  1036. ret = 1;
  1037. return;
  1038. }
  1039. add_qe = GNUNET_NAMESTORE_records_lookup (ns,
  1040. &zone_pkey,
  1041. name,
  1042. &add_error_cb,
  1043. NULL,
  1044. &get_existing_record,
  1045. NULL);
  1046. }
  1047. if (del)
  1048. {
  1049. if (NULL == name)
  1050. {
  1051. fprintf (stderr,
  1052. _ ("Missing option `%s' for operation `%s'\n"),
  1053. "-n",
  1054. _ ("del"));
  1055. GNUNET_SCHEDULER_shutdown ();
  1056. ret = 1;
  1057. return;
  1058. }
  1059. del_qe = GNUNET_NAMESTORE_records_lookup (ns,
  1060. &zone_pkey,
  1061. name,
  1062. &del_lookup_error_cb,
  1063. NULL,
  1064. &del_monitor,
  1065. NULL);
  1066. }
  1067. if (list)
  1068. {
  1069. if (NULL != name)
  1070. get_qe = GNUNET_NAMESTORE_records_lookup (ns,
  1071. &zone_pkey,
  1072. name,
  1073. &lookup_error_cb,
  1074. NULL,
  1075. &display_record_lookup,
  1076. NULL);
  1077. else
  1078. list_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
  1079. &zone_pkey,
  1080. &zone_iteration_error_cb,
  1081. NULL,
  1082. &display_record_iterator,
  1083. NULL,
  1084. &zone_iteration_finished,
  1085. NULL);
  1086. }
  1087. if (NULL != reverse_pkey)
  1088. {
  1089. struct GNUNET_IDENTITY_PublicKey pubkey;
  1090. if (GNUNET_OK !=
  1091. GNUNET_IDENTITY_public_key_from_string (reverse_pkey,
  1092. &pubkey))
  1093. {
  1094. fprintf (stderr,
  1095. _ ("Invalid public key for reverse lookup `%s'\n"),
  1096. reverse_pkey);
  1097. GNUNET_SCHEDULER_shutdown ();
  1098. }
  1099. reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns,
  1100. &zone_pkey,
  1101. &pubkey,
  1102. &reverse_error_cb,
  1103. NULL,
  1104. &handle_reverse_lookup,
  1105. NULL);
  1106. }
  1107. if (NULL != uri)
  1108. {
  1109. char sh[105];
  1110. char sname[64];
  1111. struct GNUNET_IDENTITY_PublicKey pkey;
  1112. GNUNET_STRINGS_utf8_tolower (uri, uri);
  1113. if ((2 != (sscanf (uri, "gnunet://gns/%52s/%63s", sh, sname))) ||
  1114. (GNUNET_OK !=
  1115. GNUNET_IDENTITY_public_key_from_string (sh, &pkey)))
  1116. {
  1117. fprintf (stderr, _ ("Invalid URI `%s'\n"), uri);
  1118. GNUNET_SCHEDULER_shutdown ();
  1119. ret = 1;
  1120. return;
  1121. }
  1122. if (NULL == expirationstring)
  1123. {
  1124. fprintf (stderr,
  1125. _ ("Missing option `%s' for operation `%s'\n"),
  1126. "-e",
  1127. _ ("add"));
  1128. GNUNET_SCHEDULER_shutdown ();
  1129. ret = 1;
  1130. return;
  1131. }
  1132. if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime))
  1133. {
  1134. fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring);
  1135. GNUNET_SCHEDULER_shutdown ();
  1136. ret = 1;
  1137. return;
  1138. }
  1139. memset (&rd, 0, sizeof(rd));
  1140. rd.data = &pkey;
  1141. rd.data_size = GNUNET_IDENTITY_key_get_length (&pkey);
  1142. rd.record_type = ntohl (pkey.type);
  1143. rd.expiration_time = etime;
  1144. if (GNUNET_YES == etime_is_rel)
  1145. rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
  1146. if (1 == is_shadow)
  1147. rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
  1148. add_qe_uri = GNUNET_NAMESTORE_records_store (ns,
  1149. &zone_pkey,
  1150. sname,
  1151. 1,
  1152. &rd,
  1153. &add_continuation,
  1154. &add_qe_uri);
  1155. }
  1156. if (monitor)
  1157. {
  1158. zm = GNUNET_NAMESTORE_zone_monitor_start (cfg,
  1159. &zone_pkey,
  1160. GNUNET_YES,
  1161. &monitor_error_cb,
  1162. NULL,
  1163. &display_record_monitor,
  1164. NULL,
  1165. &sync_cb,
  1166. NULL);
  1167. }
  1168. }
  1169. /**
  1170. * Callback invoked from identity service with ego information.
  1171. * An @a ego of NULL means the ego was not found.
  1172. *
  1173. * @param cls closure with the configuration
  1174. * @param ego an ego known to identity service, or NULL
  1175. */
  1176. static void
  1177. identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
  1178. {
  1179. const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
  1180. el = NULL;
  1181. if ((NULL != name) && (0 != strchr (name, '.')))
  1182. {
  1183. fprintf (stderr,
  1184. _ ("Label `%s' contains `.' which is not allowed\n"),
  1185. name);
  1186. GNUNET_SCHEDULER_shutdown ();
  1187. ret = -1;
  1188. return;
  1189. }
  1190. if (NULL == ego)
  1191. {
  1192. if (NULL != ego_name)
  1193. {
  1194. fprintf (stderr,
  1195. _ ("Ego `%s' not known to identity service\n"),
  1196. ego_name);
  1197. }
  1198. GNUNET_SCHEDULER_shutdown ();
  1199. ret = -1;
  1200. return;
  1201. }
  1202. zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
  1203. GNUNET_free (ego_name);
  1204. ego_name = NULL;
  1205. run_with_zone_pkey (cfg);
  1206. }
  1207. /**
  1208. * Function called with the default ego to be used for GNS
  1209. * operations. Used if the user did not specify a zone via
  1210. * command-line or environment variables.
  1211. *
  1212. * @param cls NULL
  1213. * @param ego default ego, NULL for none
  1214. * @param ctx NULL
  1215. * @param name unused
  1216. */
  1217. static void
  1218. default_ego_cb (void *cls,
  1219. struct GNUNET_IDENTITY_Ego *ego,
  1220. void **ctx,
  1221. const char *name)
  1222. {
  1223. const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
  1224. (void) ctx;
  1225. (void) name;
  1226. get_default = NULL;
  1227. if (NULL == ego)
  1228. {
  1229. fprintf (stderr,
  1230. _ ("No default identity configured for `namestore' subsystem\n"
  1231. "Run gnunet-identity -s namestore -e $NAME to set the default to $NAME\n"
  1232. "Run gnunet-identity -d to get a list of choices for $NAME\n"));
  1233. GNUNET_SCHEDULER_shutdown ();
  1234. ret = -1;
  1235. return;
  1236. }
  1237. else
  1238. {
  1239. identity_cb ((void *) cfg, ego);
  1240. }
  1241. }
  1242. /**
  1243. * Function called with ALL of the egos known to the
  1244. * identity service, used on startup if the user did
  1245. * not specify a zone on the command-line.
  1246. * Once the iteration is done (@a ego is NULL), we
  1247. * ask for the default ego for "namestore".
  1248. *
  1249. * @param cls a `struct GNUNET_CONFIGURATION_Handle`
  1250. * @param ego an ego, NULL for end of iteration
  1251. * @param ctx NULL
  1252. * @param name name associated with @a ego
  1253. */
  1254. static void
  1255. id_connect_cb (void *cls,
  1256. struct GNUNET_IDENTITY_Ego *ego,
  1257. void **ctx,
  1258. const char *name)
  1259. {
  1260. const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
  1261. (void) ctx;
  1262. (void) name;
  1263. if (NULL != ego)
  1264. return;
  1265. get_default =
  1266. GNUNET_IDENTITY_get (idh, "namestore", &default_ego_cb, (void *) cfg);
  1267. }
  1268. /**
  1269. * Main function that will be run.
  1270. *
  1271. * @param cls closure
  1272. * @param args remaining command-line arguments
  1273. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  1274. * @param cfg configuration
  1275. */
  1276. static void
  1277. run (void *cls,
  1278. char *const *args,
  1279. const char *cfgfile,
  1280. const struct GNUNET_CONFIGURATION_Handle *cfg)
  1281. {
  1282. const char *pkey_str;
  1283. (void) cls;
  1284. (void) args;
  1285. (void) cfgfile;
  1286. if (NULL != args[0])
  1287. GNUNET_log (
  1288. GNUNET_ERROR_TYPE_WARNING,
  1289. _ ("Superfluous command line arguments (starting with `%s') ignored\n"),
  1290. args[0]);
  1291. if ((NULL != args[0]) && (NULL == uri))
  1292. uri = GNUNET_strdup (args[0]);
  1293. GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg);
  1294. pkey_str = getenv ("GNUNET_NAMESTORE_EGO_PRIVATE_KEY");
  1295. if (NULL != pkey_str)
  1296. {
  1297. if (GNUNET_OK != GNUNET_STRINGS_string_to_data (pkey_str,
  1298. strlen (pkey_str),
  1299. &zone_pkey,
  1300. sizeof(zone_pkey)))
  1301. {
  1302. fprintf (stderr,
  1303. "Malformed private key `%s' in $%s\n",
  1304. pkey_str,
  1305. "GNUNET_NAMESTORE_EGO_PRIVATE_KEY");
  1306. ret = 1;
  1307. GNUNET_SCHEDULER_shutdown ();
  1308. return;
  1309. }
  1310. run_with_zone_pkey (cfg);
  1311. return;
  1312. }
  1313. if (NULL == ego_name)
  1314. {
  1315. idh = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, (void *) cfg);
  1316. if (NULL == idh)
  1317. fprintf (stderr, _ ("Cannot connect to identity service\n"));
  1318. ret = -1;
  1319. return;
  1320. }
  1321. el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &identity_cb, (void *) cfg);
  1322. }
  1323. /**
  1324. * Command-line option parser function that allows the user to specify
  1325. * a complete record as one argument for adding/removing. A pointer
  1326. * to the head of the list of record sets must be passed as the "scls"
  1327. * argument.
  1328. *
  1329. * @param ctx command line processor context
  1330. * @param scls must be of type "struct GNUNET_FS_Uri **"
  1331. * @param option name of the option (typically 'R')
  1332. * @param value command line argument given; format is
  1333. * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs),
  1334. * always given in seconds (without the unit),
  1335. * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or
  1336. * a combination of 's' (shadow) and 'p' (public) and VALUE is the
  1337. * value (in human-readable format)
  1338. * @return #GNUNET_OK on success
  1339. */
  1340. static int
  1341. multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  1342. void *scls,
  1343. const char *option,
  1344. const char *value)
  1345. {
  1346. struct RecordSetEntry **head = scls;
  1347. struct RecordSetEntry *r;
  1348. struct GNUNET_GNSRECORD_Data record;
  1349. char *cp;
  1350. char *tok;
  1351. char *saveptr;
  1352. int etime_is_rel;
  1353. void *raw_data;
  1354. (void) ctx;
  1355. (void) option;
  1356. cp = GNUNET_strdup (value);
  1357. tok = strtok_r (cp, " ", &saveptr);
  1358. if (NULL == tok)
  1359. {
  1360. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1361. _ ("Empty record line argument is not allowed.\n"));
  1362. GNUNET_free (cp);
  1363. return GNUNET_SYSERR;
  1364. }
  1365. {
  1366. char *etime_in_s;
  1367. GNUNET_asprintf (&etime_in_s, "%s s", tok);
  1368. if (GNUNET_OK !=
  1369. parse_expiration (etime_in_s, &etime_is_rel, &record.expiration_time))
  1370. {
  1371. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1372. _ ("Invalid expiration time `%s' (must be without unit)\n"),
  1373. tok);
  1374. GNUNET_free (cp);
  1375. GNUNET_free (etime_in_s);
  1376. return GNUNET_SYSERR;
  1377. }
  1378. GNUNET_free (etime_in_s);
  1379. }
  1380. tok = strtok_r (NULL, " ", &saveptr);
  1381. if (NULL == tok)
  1382. {
  1383. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1384. _ ("Missing entries in record line `%s'.\n"),
  1385. value);
  1386. GNUNET_free (cp);
  1387. return GNUNET_SYSERR;
  1388. }
  1389. record.record_type = GNUNET_GNSRECORD_typename_to_number (tok);
  1390. if (UINT32_MAX == record.record_type)
  1391. {
  1392. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Unknown record type `%s'\n"), tok);
  1393. GNUNET_free (cp);
  1394. return GNUNET_SYSERR;
  1395. }
  1396. tok = strtok_r (NULL, " ", &saveptr);
  1397. if (NULL == tok)
  1398. {
  1399. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1400. _ ("Missing entries in record line `%s'.\n"),
  1401. value);
  1402. GNUNET_free (cp);
  1403. return GNUNET_SYSERR;
  1404. }
  1405. record.flags = GNUNET_GNSRECORD_RF_NONE;
  1406. if (etime_is_rel)
  1407. record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
  1408. if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */
  1409. record.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
  1410. if (NULL != strchr (tok, (unsigned char) 's'))
  1411. record.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
  1412. /* find beginning of record value */
  1413. tok = strchr (&value[tok - cp], (unsigned char) ' ');
  1414. if (NULL == tok)
  1415. {
  1416. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1417. _ ("Missing entries in record line `%s'.\n"),
  1418. value);
  1419. GNUNET_free (cp);
  1420. return GNUNET_SYSERR;
  1421. }
  1422. GNUNET_free (cp);
  1423. tok++; /* skip space */
  1424. if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record.record_type,
  1425. tok,
  1426. &raw_data,
  1427. &record.data_size))
  1428. {
  1429. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1430. _ ("Invalid record data for type %s: `%s'.\n"),
  1431. GNUNET_GNSRECORD_number_to_typename (record.record_type),
  1432. tok);
  1433. return GNUNET_SYSERR;
  1434. }
  1435. r = GNUNET_malloc (sizeof(struct RecordSetEntry) + record.data_size);
  1436. r->next = *head;
  1437. record.data = &r[1];
  1438. memcpy (&r[1], raw_data, record.data_size);
  1439. GNUNET_free (raw_data);
  1440. r->record = record;
  1441. *head = r;
  1442. return GNUNET_OK;
  1443. }
  1444. /**
  1445. * Allow user to specify keywords.
  1446. *
  1447. * @param shortName short name of the option
  1448. * @param name long name of the option
  1449. * @param argumentHelp help text for the option argument
  1450. * @param description long help text for the option
  1451. * @param[out] topKeywords set to the desired value
  1452. */
  1453. struct GNUNET_GETOPT_CommandLineOption
  1454. multirecord_option (char shortName,
  1455. const char *name,
  1456. const char *argumentHelp,
  1457. const char *description,
  1458. struct RecordSetEntry **rs)
  1459. {
  1460. struct GNUNET_GETOPT_CommandLineOption clo = { .shortName = shortName,
  1461. .name = name,
  1462. .argumentHelp = argumentHelp,
  1463. .description = description,
  1464. .require_argument = 1,
  1465. .processor =
  1466. &multirecord_process,
  1467. .scls = (void *) rs };
  1468. return clo;
  1469. }
  1470. /**
  1471. * The main function for gnunet-namestore.
  1472. *
  1473. * @param argc number of arguments from the command line
  1474. * @param argv command line arguments
  1475. * @return 0 ok, 1 on error
  1476. */
  1477. int
  1478. main (int argc, char *const *argv)
  1479. {
  1480. struct GNUNET_GETOPT_CommandLineOption options[] =
  1481. { GNUNET_GETOPT_option_flag ('a', "add", gettext_noop ("add record"), &add),
  1482. GNUNET_GETOPT_option_flag ('d',
  1483. "delete",
  1484. gettext_noop ("delete record"),
  1485. &del),
  1486. GNUNET_GETOPT_option_flag ('D',
  1487. "display",
  1488. gettext_noop ("display records"),
  1489. &list),
  1490. GNUNET_GETOPT_option_string (
  1491. 'e',
  1492. "expiration",
  1493. "TIME",
  1494. gettext_noop (
  1495. "expiration time for record to use (for adding only), \"never\" is possible"),
  1496. &expirationstring),
  1497. GNUNET_GETOPT_option_string ('i',
  1498. "nick",
  1499. "NICKNAME",
  1500. gettext_noop (
  1501. "set the desired nick name for the zone"),
  1502. &nickstring),
  1503. GNUNET_GETOPT_option_flag ('m',
  1504. "monitor",
  1505. gettext_noop (
  1506. "monitor changes in the namestore"),
  1507. &monitor),
  1508. GNUNET_GETOPT_option_string ('n',
  1509. "name",
  1510. "NAME",
  1511. gettext_noop (
  1512. "name of the record to add/delete/display"),
  1513. &name),
  1514. GNUNET_GETOPT_option_string ('r',
  1515. "reverse",
  1516. "PKEY",
  1517. gettext_noop (
  1518. "determine our name for the given PKEY"),
  1519. &reverse_pkey),
  1520. multirecord_option (
  1521. 'R',
  1522. "replace",
  1523. "RECORDLINE",
  1524. gettext_noop (
  1525. "set record set to values given by (possibly multiple) RECORDLINES; can be specified multiple times"),
  1526. &recordset),
  1527. GNUNET_GETOPT_option_string ('t',
  1528. "type",
  1529. "TYPE",
  1530. gettext_noop (
  1531. "type of the record to add/delete/display"),
  1532. &typestring),
  1533. GNUNET_GETOPT_option_string ('u',
  1534. "uri",
  1535. "URI",
  1536. gettext_noop ("URI to import into our zone"),
  1537. &uri),
  1538. GNUNET_GETOPT_option_string ('V',
  1539. "value",
  1540. "VALUE",
  1541. gettext_noop (
  1542. "value of the record to add/delete"),
  1543. &value),
  1544. GNUNET_GETOPT_option_flag ('p',
  1545. "public",
  1546. gettext_noop ("create or list public record"),
  1547. &is_public),
  1548. GNUNET_GETOPT_option_flag (
  1549. 's',
  1550. "shadow",
  1551. gettext_noop (
  1552. "create shadow record (only valid if all other records of the same type have expired"),
  1553. &is_shadow),
  1554. GNUNET_GETOPT_option_string ('z',
  1555. "zone",
  1556. "EGO",
  1557. gettext_noop (
  1558. "name of the ego controlling the zone"),
  1559. &ego_name),
  1560. GNUNET_GETOPT_OPTION_END };
  1561. int lret;
  1562. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  1563. return 2;
  1564. is_public = -1;
  1565. is_shadow = -1;
  1566. GNUNET_log_setup ("gnunet-namestore", "WARNING", NULL);
  1567. if (GNUNET_OK !=
  1568. (lret = GNUNET_PROGRAM_run (argc,
  1569. argv,
  1570. "gnunet-namestore",
  1571. _ ("GNUnet zone manipulation tool"),
  1572. options,
  1573. &run,
  1574. NULL)))
  1575. {
  1576. GNUNET_free_nz ((void *) argv);
  1577. //FIXME
  1578. //GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey);
  1579. return lret;
  1580. }
  1581. GNUNET_free_nz ((void *) argv);
  1582. //FIXME
  1583. //GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey);
  1584. return ret;
  1585. }
  1586. /* end of gnunet-namestore.c */