diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/namestore/gnunet-namestore.c | 273 |
1 files changed, 238 insertions, 35 deletions
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c index c5f48848e..0f0660edc 100644 --- a/src/namestore/gnunet-namestore.c +++ b/src/namestore/gnunet-namestore.c | |||
@@ -33,6 +33,24 @@ | |||
33 | 33 | ||
34 | 34 | ||
35 | /** | 35 | /** |
36 | * Entry in record set for bulk processing. | ||
37 | */ | ||
38 | struct RecordSetEntry | ||
39 | { | ||
40 | /** | ||
41 | * Kept in a linked list. | ||
42 | */ | ||
43 | struct RecordSetEntry *next; | ||
44 | |||
45 | /** | ||
46 | * The record to add/remove. | ||
47 | */ | ||
48 | struct GNUNET_GNSRECORD_Data record; | ||
49 | |||
50 | }; | ||
51 | |||
52 | |||
53 | /** | ||
36 | * Handle to the namestore. | 54 | * Handle to the namestore. |
37 | */ | 55 | */ |
38 | static struct GNUNET_NAMESTORE_Handle *ns; | 56 | static struct GNUNET_NAMESTORE_Handle *ns; |
@@ -197,6 +215,11 @@ static struct GNUNET_NAMESTORE_ZoneMonitor *zm; | |||
197 | */ | 215 | */ |
198 | static int monitor; | 216 | static int monitor; |
199 | 217 | ||
218 | /** | ||
219 | * Entry in record set for processing records in bulk. | ||
220 | */ | ||
221 | static struct RecordSetEntry *recordset; | ||
222 | |||
200 | 223 | ||
201 | /** | 224 | /** |
202 | * Task run on shutdown. Cleans up everything. | 225 | * Task run on shutdown. Cleans up everything. |
@@ -864,6 +887,56 @@ del_monitor (void *cls, | |||
864 | 887 | ||
865 | 888 | ||
866 | /** | 889 | /** |
890 | * Parse expiration time. | ||
891 | * | ||
892 | * @param expirationstring text to parse | ||
893 | * @param etime_is_rel[out] set to #GNUNET_YES if time is relative | ||
894 | * @param etime[out] set to expiration time (abs or rel) | ||
895 | * @return #GNUNET_OK on success | ||
896 | */ | ||
897 | static int | ||
898 | parse_expiration (const char *expirationstring, | ||
899 | int *etime_is_rel, | ||
900 | uint64_t *etime) | ||
901 | { | ||
902 | struct GNUNET_TIME_Relative etime_rel; | ||
903 | struct GNUNET_TIME_Absolute etime_abs; | ||
904 | |||
905 | if (0 == strcmp (expirationstring, | ||
906 | "never")) | ||
907 | { | ||
908 | *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
909 | *etime_is_rel = GNUNET_NO; | ||
910 | return GNUNET_OK; | ||
911 | } | ||
912 | if (GNUNET_OK == | ||
913 | GNUNET_STRINGS_fancy_time_to_relative (expirationstring, | ||
914 | &etime_rel)) | ||
915 | { | ||
916 | *etime_is_rel = GNUNET_YES; | ||
917 | *etime = etime_rel.rel_value_us; | ||
918 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
919 | "Storing record with relative expiration time of %s\n", | ||
920 | GNUNET_STRINGS_relative_time_to_string (etime_rel, | ||
921 | GNUNET_NO)); | ||
922 | return GNUNET_OK; | ||
923 | } | ||
924 | if (GNUNET_OK == | ||
925 | GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, | ||
926 | &etime_abs)) | ||
927 | { | ||
928 | *etime_is_rel = GNUNET_NO; | ||
929 | *etime = etime_abs.abs_value_us; | ||
930 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
931 | "Storing record with absolute expiration time of %s\n", | ||
932 | GNUNET_STRINGS_absolute_time_to_string (etime_abs)); | ||
933 | return GNUNET_OK; | ||
934 | } | ||
935 | return GNUNET_SYSERR; | ||
936 | } | ||
937 | |||
938 | |||
939 | /** | ||
867 | * Callback invoked from identity service with ego information. | 940 | * Callback invoked from identity service with ego information. |
868 | * An @a ego of NULL means the ego was not found. | 941 | * An @a ego of NULL means the ego was not found. |
869 | * | 942 | * |
@@ -877,6 +950,7 @@ identity_cb (void *cls, | |||
877 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | 950 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; |
878 | struct GNUNET_CRYPTO_EcdsaPublicKey pub; | 951 | struct GNUNET_CRYPTO_EcdsaPublicKey pub; |
879 | struct GNUNET_GNSRECORD_Data rd; | 952 | struct GNUNET_GNSRECORD_Data rd; |
953 | uint64_t etime; | ||
880 | 954 | ||
881 | el = NULL; | 955 | el = NULL; |
882 | if (NULL == ego) | 956 | if (NULL == ego) |
@@ -976,32 +1050,10 @@ identity_cb (void *cls, | |||
976 | ret = 1; | 1050 | ret = 1; |
977 | return; | 1051 | return; |
978 | } | 1052 | } |
979 | if (0 == strcmp (expirationstring, | 1053 | if (GNUNET_OK != |
980 | "never")) | 1054 | parse_expiration (expirationstring, |
981 | { | 1055 | &etime_is_rel, |
982 | etime_abs = GNUNET_TIME_UNIT_FOREVER_ABS; | 1056 | &etime)) |
983 | etime_is_rel = GNUNET_NO; | ||
984 | } | ||
985 | else if (GNUNET_OK == | ||
986 | GNUNET_STRINGS_fancy_time_to_relative (expirationstring, | ||
987 | &etime_rel)) | ||
988 | { | ||
989 | etime_is_rel = GNUNET_YES; | ||
990 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
991 | "Storing record with relative expiration time of %s\n", | ||
992 | GNUNET_STRINGS_relative_time_to_string (etime_rel, | ||
993 | GNUNET_NO)); | ||
994 | } | ||
995 | else if (GNUNET_OK == | ||
996 | GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, | ||
997 | &etime_abs)) | ||
998 | { | ||
999 | etime_is_rel = GNUNET_NO; | ||
1000 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1001 | "Storing record with absolute expiration time of %s\n", | ||
1002 | GNUNET_STRINGS_absolute_time_to_string (etime_abs)); | ||
1003 | } | ||
1004 | else | ||
1005 | { | 1057 | { |
1006 | fprintf (stderr, | 1058 | fprintf (stderr, |
1007 | _("Invalid time format `%s'\n"), | 1059 | _("Invalid time format `%s'\n"), |
@@ -1106,16 +1158,9 @@ identity_cb (void *cls, | |||
1106 | rd.data = &pkey; | 1158 | rd.data = &pkey; |
1107 | rd.data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); | 1159 | rd.data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); |
1108 | rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; | 1160 | rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; |
1109 | if (GNUNET_YES == etime_is_rel) | 1161 | rd.expiration_time = etime; |
1110 | { | 1162 | if (GNUNET_YES == etime_is_rel) |
1111 | rd.expiration_time = etime_rel.rel_value_us; | ||
1112 | rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | 1163 | rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; |
1113 | } | ||
1114 | else if (GNUNET_NO == etime_is_rel) | ||
1115 | rd.expiration_time = etime_abs.abs_value_us; | ||
1116 | else | ||
1117 | rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
1118 | |||
1119 | if (1 == is_shadow) | 1164 | if (1 == is_shadow) |
1120 | rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; | 1165 | rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; |
1121 | add_qe_uri = GNUNET_NAMESTORE_records_store (ns, | 1166 | add_qe_uri = GNUNET_NAMESTORE_records_store (ns, |
@@ -1247,6 +1292,159 @@ run (void *cls, | |||
1247 | 1292 | ||
1248 | 1293 | ||
1249 | /** | 1294 | /** |
1295 | * Command-line option parser function that allows the user to specify | ||
1296 | * a complete record as one argument for adding/removing. A pointer | ||
1297 | * to the head of the list of record sets must be passed as the "scls" | ||
1298 | * argument. | ||
1299 | * | ||
1300 | * @param ctx command line processor context | ||
1301 | * @param scls must be of type "struct GNUNET_FS_Uri **" | ||
1302 | * @param option name of the option (typically 'R') | ||
1303 | * @param value command line argument given; format is | ||
1304 | * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs), | ||
1305 | * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or | ||
1306 | * a combination of 's' (shadow) and 'p' (public) and VALUE is the | ||
1307 | * value (in human-readable format) | ||
1308 | * @return #GNUNET_OK on success | ||
1309 | */ | ||
1310 | static int | ||
1311 | multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | ||
1312 | void *scls, | ||
1313 | const char *option, | ||
1314 | const char *value) | ||
1315 | { | ||
1316 | struct RecordSetEntry **head = scls; | ||
1317 | struct RecordSetEntry *r; | ||
1318 | struct GNUNET_GNSRECORD_Data record; | ||
1319 | char *cp; | ||
1320 | char *tok; | ||
1321 | int etime_is_rel; | ||
1322 | void *raw_data; | ||
1323 | |||
1324 | cp = GNUNET_strdup (value); | ||
1325 | tok = strtok (cp, " "); | ||
1326 | if (NULL == tok) | ||
1327 | { | ||
1328 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
1329 | _("Empty record line argument is not allowed.\n")); | ||
1330 | GNUNET_free (cp); | ||
1331 | return GNUNET_SYSERR; | ||
1332 | } | ||
1333 | if (GNUNET_OK != | ||
1334 | parse_expiration (tok, | ||
1335 | &etime_is_rel, | ||
1336 | &record.expiration_time)) | ||
1337 | { | ||
1338 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
1339 | _("Invalid expiration time `%s'\n"), | ||
1340 | tok); | ||
1341 | GNUNET_free (cp); | ||
1342 | return GNUNET_SYSERR; | ||
1343 | } | ||
1344 | tok = strtok (NULL, " "); | ||
1345 | if (NULL == tok) | ||
1346 | { | ||
1347 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
1348 | _("Missing entries in record line `%s'.\n"), | ||
1349 | value); | ||
1350 | GNUNET_free (cp); | ||
1351 | return GNUNET_SYSERR; | ||
1352 | } | ||
1353 | record.record_type = GNUNET_GNSRECORD_typename_to_number (tok); | ||
1354 | if (UINT32_MAX == record.record_type) | ||
1355 | { | ||
1356 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
1357 | _("Unknown record type `%s'\n"), | ||
1358 | tok); | ||
1359 | GNUNET_free (cp); | ||
1360 | return GNUNET_SYSERR; | ||
1361 | } | ||
1362 | tok = strtok (NULL, " "); | ||
1363 | if (NULL == tok) | ||
1364 | { | ||
1365 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
1366 | _("Missing entries in record line `%s'.\n"), | ||
1367 | value); | ||
1368 | GNUNET_free (cp); | ||
1369 | return GNUNET_SYSERR; | ||
1370 | } | ||
1371 | record.flags = GNUNET_GNSRECORD_RF_NONE; | ||
1372 | if (etime_is_rel) | ||
1373 | record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1374 | if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */ | ||
1375 | record.flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
1376 | if (NULL != strchr (tok, (unsigned char) 's')) | ||
1377 | record.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; | ||
1378 | /* find beginning of record value */ | ||
1379 | tok = strchr (&value[tok - cp], (unsigned char) ' '); | ||
1380 | if (NULL == tok) | ||
1381 | { | ||
1382 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
1383 | _("Missing entries in record line `%s'.\n"), | ||
1384 | value); | ||
1385 | GNUNET_free (cp); | ||
1386 | return GNUNET_SYSERR; | ||
1387 | } | ||
1388 | GNUNET_free (cp); | ||
1389 | tok++; /* skip space */ | ||
1390 | if (GNUNET_OK != | ||
1391 | GNUNET_GNSRECORD_string_to_value (record.record_type, | ||
1392 | tok, | ||
1393 | &raw_data, | ||
1394 | &record.data_size)) | ||
1395 | { | ||
1396 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
1397 | _("Invalid record data for type %s: `%s'.\n"), | ||
1398 | GNUNET_GNSRECORD_number_to_typename (record.record_type), | ||
1399 | tok); | ||
1400 | return GNUNET_SYSERR; | ||
1401 | } | ||
1402 | |||
1403 | r = GNUNET_malloc (sizeof (struct RecordSetEntry) + record.data_size); | ||
1404 | r->next = *head; | ||
1405 | record.data = &r[1]; | ||
1406 | memcpy (&r[1], | ||
1407 | raw_data, | ||
1408 | record.data_size); | ||
1409 | GNUNET_free (raw_data); | ||
1410 | r->record = record; | ||
1411 | *head = r; | ||
1412 | return GNUNET_OK; | ||
1413 | } | ||
1414 | |||
1415 | |||
1416 | /** | ||
1417 | * Allow user to specify keywords. | ||
1418 | * | ||
1419 | * @param shortName short name of the option | ||
1420 | * @param name long name of the option | ||
1421 | * @param argumentHelp help text for the option argument | ||
1422 | * @param description long help text for the option | ||
1423 | * @param[out] topKeywords set to the desired value | ||
1424 | */ | ||
1425 | struct GNUNET_GETOPT_CommandLineOption | ||
1426 | multirecord_option (char shortName, | ||
1427 | const char *name, | ||
1428 | const char *argumentHelp, | ||
1429 | const char *description, | ||
1430 | struct RecordSetEntry **rs) | ||
1431 | { | ||
1432 | struct GNUNET_GETOPT_CommandLineOption clo = { | ||
1433 | .shortName = shortName, | ||
1434 | .name = name, | ||
1435 | .argumentHelp = argumentHelp, | ||
1436 | .description = description, | ||
1437 | .require_argument = 1, | ||
1438 | .processor = &multirecord_process, | ||
1439 | .scls = (void *) rs | ||
1440 | }; | ||
1441 | |||
1442 | return clo; | ||
1443 | } | ||
1444 | |||
1445 | |||
1446 | |||
1447 | /** | ||
1250 | * The main function for gnunet-namestore. | 1448 | * The main function for gnunet-namestore. |
1251 | * | 1449 | * |
1252 | * @param argc number of arguments from the command line | 1450 | * @param argc number of arguments from the command line |
@@ -1294,6 +1492,11 @@ main (int argc, | |||
1294 | "PKEY", | 1492 | "PKEY", |
1295 | gettext_noop ("determine our name for the given PKEY"), | 1493 | gettext_noop ("determine our name for the given PKEY"), |
1296 | &reverse_pkey), | 1494 | &reverse_pkey), |
1495 | multirecord_option ('R', | ||
1496 | "record", | ||
1497 | "RECORDLINE", | ||
1498 | gettext_noop ("complete record on one line to add/delete/display; can be specified multiple times"), | ||
1499 | &recordset), | ||
1297 | GNUNET_GETOPT_option_string ('t', | 1500 | GNUNET_GETOPT_option_string ('t', |
1298 | "type", | 1501 | "type", |
1299 | "TYPE", | 1502 | "TYPE", |