aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-08-15 20:53:55 +0000
committerChristian Grothoff <christian@grothoff.org>2013-08-15 20:53:55 +0000
commita67f39e2f07320d19f3f03d6ca22ae5ee53ea230 (patch)
tree9ff2002c68732a4529049172e5975773960c975e /src
parent1e40e081305fef24bb83e6fbaabce5e83950d246 (diff)
downloadgnunet-a67f39e2f07320d19f3f03d6ca22ae5ee53ea230.tar.gz
gnunet-a67f39e2f07320d19f3f03d6ca22ae5ee53ea230.zip
-more work on GNS resolver
Diffstat (limited to 'src')
-rw-r--r--src/gns/gnunet-service-gns.c4
-rw-r--r--src/gns/gnunet-service-gns_resolver.c1561
2 files changed, 220 insertions, 1345 deletions
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c
index 24e0668a9..2de67020d 100644
--- a/src/gns/gnunet-service-gns.c
+++ b/src/gns/gnunet-service-gns.c
@@ -22,6 +22,10 @@
22 * @brief GNUnet GNS service 22 * @brief GNUnet GNS service
23 * @author Martin Schanzenbach 23 * @author Martin Schanzenbach
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - perform conversion of relative expiration times to absolute time
28 * when going to DHT!
25 */ 29 */
26#include "platform.h" 30#include "platform.h"
27#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c
index d357a1312..6d77997e7 100644
--- a/src/gns/gnunet-service-gns_resolver.c
+++ b/src/gns/gnunet-service-gns_resolver.c
@@ -25,10 +25,31 @@
25 * @author Christian Grothoff 25 * @author Christian Grothoff
26 * 26 *
27 * TODO: 27 * TODO:
28 * - recurive GNS resulution 28 * - GNS: handle CNAME records (idea: manipulate rh->name)
29 * - GNS: handle VPN records (easy)
30 * - GNS: handle special SRV names --- no delegation, direct lookup;
31 * can likely be done in 'resolver_lookup_get_next_label'.
29 * - recursive DNS resolution 32 * - recursive DNS resolution
30 * - shortening triggers 33 * - shortening triggers
31 * - revocation checks (privacy!?) 34 * - revocation checks (make optional: privacy!)
35 *
36 * Issues:
37 * - We currently go to the DHT simply if we find no local reply; this
38 * is incorrect; the correct rules for going to DHT are:
39 *
40 * 1. The entry in the DHT is RSL_RECORD_EXPIRED OR
41 * 2. No entry in the NS existed AND
42 * 3. The zone queried is not the local resolver's zone AND
43 * 4. The name that was looked up is '+'
44 * because if it was any other canonical name we either already queried
45 * the DHT for the authority in the authority lookup phase (and thus
46 * would already have an entry in the NS for the record)
47 * 5. We are not in cache only mode
48 *
49 * - We currently never look "into" the records; for example,
50 * MX, SRV and SOA records may include ".+" that need to be
51 * handled
52 *
32 */ 53 */
33#include "platform.h" 54#include "platform.h"
34#include "gnunet_util_lib.h" 55#include "gnunet_util_lib.h"
@@ -116,7 +137,7 @@ struct AuthorityChain
116 * (appended to construct the DNS name to resolve; 137 * (appended to construct the DNS name to resolve;
117 * this is NOT the DNS name of the DNS server!). 138 * this is NOT the DNS name of the DNS server!).
118 */ 139 */
119 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; 140 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1];
120 141
121 /** 142 /**
122 * IP address of the DNS resolver that is authoritative. 143 * IP address of the DNS resolver that is authoritative.
@@ -943,112 +964,6 @@ start_shorten (const char *original_label,
943 964
944 965
945/** 966/**
946 * Namestore calls this function if we have record for this name.
947 * (or with rd_count=0 to indicate no matches)
948 *
949 * @param cls the pending query
950 * @param key the key of the zone we did the lookup
951 * @param expiration expiration date of the namestore entry
952 * @param name the name for which we need an authority
953 * @param rd_count the number of records with 'name'
954 * @param rd the record data
955 * @param signature the signature of the authority for the record data
956 */
957static void
958process_record_result_ns (void* cls,
959 const struct GNUNET_CRYPTO_EccPublicKey *key,
960 struct GNUNET_TIME_Absolute expiration,
961 const char *name, unsigned int rd_count,
962 const struct GNUNET_NAMESTORE_RecordData *rd,
963 const struct GNUNET_CRYPTO_EccSignature *signature)
964{
965 struct ResolverHandle *rh = cls;
966 struct RecordLookupHandle *rlh = rh->proc_cls;
967 struct GNUNET_TIME_Relative remaining_time;
968 struct GNUNET_CRYPTO_ShortHashCode zone;
969 struct GNUNET_TIME_Absolute et;
970 unsigned int i;
971
972 rh->namestore_task = NULL;
973 GNUNET_CRYPTO_short_hash (key,
974 sizeof (struct GNUNET_CRYPTO_EccPublicKey),
975 &zone);
976 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
977 rh->status = 0;
978 if (NULL != name)
979 {
980 rh->status |= RSL_RECORD_EXISTS;
981 if (remaining_time.rel_value_us == 0)
982 rh->status |= RSL_RECORD_EXPIRED;
983 }
984 if (0 == rd_count)
985 {
986 /**
987 * Lookup terminated and no results
988 */
989 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
990 "GNS_PHASE_REC-%llu: Namestore lookup for %s terminated without results\n",
991 rh->id, name);
992
993 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
994 "GNS_PHASE_REC-%llu: Record %s unknown in namestore\n",
995 rh->id, rh->name);
996 /**
997 * Our zone and no result? Cannot resolve TT
998 */
999 rh->proc(rh->proc_cls, rh, 0, NULL);
1000 return;
1001
1002 }
1003 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1004 "GNS_PHASE_REC-%llu: Processing additional result %s from namestore\n",
1005 rh->id, name);
1006 for (i = 0; i < rd_count;i++)
1007 {
1008 if (rd[i].record_type != rlh->record_type)
1009 continue;
1010
1011 if (ignore_pending_records &&
1012 (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
1013 {
1014 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1015 "GNS_PHASE_REC-%llu: Record %s is awaiting user confirmation. Skipping\n",
1016 rh->id, name);
1017 continue;
1018 }
1019
1020 //FIXME: eh? do I have to handle this here?
1021 GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
1022 et.abs_value_us = rd[i].expiration_time;
1023 if (0 == (GNUNET_TIME_absolute_get_remaining (et)).rel_value_us)
1024 {
1025 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1026 "GNS_PHASE_REC-%llu: This record is expired. Skipping\n",
1027 rh->id);
1028 continue;
1029 }
1030 rh->answered++;
1031 }
1032
1033 /**
1034 * no answers found
1035 */
1036 if (0 == rh->answered)
1037 {
1038 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1039 "GNS_PHASE_REC-%llu: No answers found. This is odd!\n", rh->id);
1040 rh->proc(rh->proc_cls, rh, 0, NULL);
1041 return;
1042 }
1043
1044 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1045 "GNS_PHASE_REC-%llu: Found %d answer(s) to query in %d records!\n",
1046 rh->id, rh->answered, rd_count);
1047 rh->proc(rh->proc_cls, rh, rd_count, rd);
1048}
1049
1050
1051/**
1052 * VPN redirect result callback 967 * VPN redirect result callback
1053 * 968 *
1054 * @param cls the resolver handle 969 * @param cls the resolver handle
@@ -1115,165 +1030,7 @@ process_record_result_vpn (void* cls, int af, const void *address)
1115} 1030}
1116 1031
1117 1032
1118/**
1119 * Process VPN lookup result for record
1120 *
1121 * @param cls the record lookup handle
1122 * @param rh resolver handle
1123 * @param rd_count number of results (1)
1124 * @param rd record data containing the result
1125 */
1126static void
1127handle_record_vpn (void* cls, struct ResolverHandle *rh,
1128 unsigned int rd_count,
1129 const struct GNUNET_NAMESTORE_RecordData *rd)
1130{
1131 struct RecordLookupHandle* rlh = cls;
1132
1133 if (0 == rd_count)
1134 {
1135 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1136 "GNS_PHASE_REC_VPN-%llu: VPN returned no records. (status: %d)!\n",
1137 rh->id,
1138 rh->status);
1139 /* give up, cannot resolve */
1140 finish_lookup(rh, rlh, 0, NULL);
1141 return;
1142 }
1143
1144 /* results found yay */
1145 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1146 "GNS_PHASE_REC_VPN-%llu: Record resolved from VPN!\n",
1147 rh->id);
1148
1149 finish_lookup(rh, rlh, rd_count, rd);
1150}
1151
1152
1153/**
1154 * The final phase of resoution.
1155 * We found a NS RR and want to resolve via DNS
1156 *
1157 * @param rh the pending lookup handle
1158 * @param rd_count length of record data
1159 * @param rd record data containing VPN RR
1160 */
1161static void
1162resolve_record_dns (struct ResolverHandle *rh,
1163 unsigned int rd_count,
1164 const struct GNUNET_NAMESTORE_RecordData *rd)
1165{
1166 struct RecordLookupHandle *rlh = rh->proc_cls;
1167 struct GNUNET_DNSPARSER_Query query;
1168 struct GNUNET_DNSPARSER_Packet packet;
1169 struct GNUNET_TUN_DnsFlags flags;
1170 struct in_addr dnsip;
1171 struct sockaddr_in addr;
1172 struct sockaddr *sa;
1173 unsigned int i;
1174
1175 memset (&packet, 0, sizeof (struct GNUNET_DNSPARSER_Packet));
1176 memset (rh->dns_name, 0, sizeof (rh->dns_name));
1177
1178 /* We cancel here as to not include the ns lookup in the timeout */
1179 if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task)
1180 {
1181 GNUNET_SCHEDULER_cancel(rh->timeout_task);
1182 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1183 }
1184 /* Start shortening */
1185 if ((NULL != rh->priv_key) &&
1186 (GNUNET_YES == is_canonical (rh->name)))
1187 {
1188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1189 "GNS_PHASE_REC_DNS-%llu: Trying to shorten authority chain\n",
1190 rh->id);
1191 start_shorten (rh->authority_chain_head,
1192 rh->priv_key);
1193 }
1194
1195 for (i = 0; i < rd_count; i++)
1196 {
1197 /* Synthesize dns name */
1198 if (GNUNET_DNSPARSER_TYPE_NS == rd[i].record_type)
1199 {
1200 strcpy (rh->dns_zone, (char*)rd[i].data);
1201 if (0 == strcmp (rh->name, ""))
1202 strcpy (rh->dns_name, (char*)rd[i].data);
1203 else
1204 sprintf (rh->dns_name, "%s.%s", rh->name, (char*)rd[i].data);
1205 }
1206 /* The glue */
1207 if (GNUNET_DNSPARSER_TYPE_A == rd[i].record_type)
1208 /* need to use memcpy as .data may be unaligned */
1209 memcpy (&dnsip, rd[i].data, sizeof (dnsip));
1210 }
1211
1212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1213 "GNS_PHASE_REC_DNS-%llu: Looking up `%s' from `%s'\n",
1214 rh->id,
1215 rh->dns_name,
1216 inet_ntoa (dnsip));
1217 rh->dns_sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0);
1218 if (NULL == rh->dns_sock)
1219 {
1220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1221 "GNS_PHASE_REC_DNS-%llu: Error creating udp socket for dns!\n",
1222 rh->id);
1223 finish_lookup (rh, rlh, 0, NULL);
1224 return;
1225 }
1226
1227 memset (&addr, 0, sizeof (struct sockaddr_in));
1228 sa = (struct sockaddr *) &addr;
1229 sa->sa_family = AF_INET;
1230 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (rh->dns_sock,
1231 sa,
1232 sizeof (struct sockaddr_in),
1233 0))
1234 {
1235 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1236 "GNS_PHASE_REC_DNS-%llu: Error binding UDP socket for DNS lookup!\n",
1237 rh->id);
1238 finish_lookup (rh, rlh, 0, NULL);
1239 return;
1240 }
1241 query.name = rh->dns_name;
1242 query.type = rlh->record_type;
1243 query.class = GNUNET_TUN_DNS_CLASS_INTERNET;
1244 memset (&flags, 0, sizeof (flags));
1245 flags.recursion_desired = 1;
1246 flags.checking_disabled = 1;
1247 packet.queries = &query;
1248 packet.answers = NULL;
1249 packet.authority_records = NULL;
1250 packet.num_queries = 1;
1251 packet.num_answers = 0;
1252 packet.num_authority_records = 0;
1253 packet.num_additional_records = 0;
1254 packet.flags = flags;
1255 packet.id = rh->id;
1256 if (GNUNET_OK != GNUNET_DNSPARSER_pack (&packet,
1257 UINT16_MAX,
1258 &rh->dns_raw_packet,
1259 &rh->dns_raw_packet_size))
1260 {
1261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1262 "GNS_PHASE_REC_DNS-%llu: Creating raw dns packet!\n",
1263 rh->id);
1264 GNUNET_NETWORK_socket_close (rh->dns_sock);
1265 finish_lookup (rh, rlh, 0, NULL);
1266 return;
1267 }
1268 1033
1269 rh->dns_addr.sin_family = AF_INET;
1270 rh->dns_addr.sin_port = htons (53); //domain
1271 rh->dns_addr.sin_addr = dnsip;
1272#if HAVE_SOCKADDR_IN_SIN_LEN
1273 rh->dns_addr.sin_len = (u_char) sizeof (struct sockaddr_in);
1274#endif
1275 send_dns_packet (rh);
1276}
1277 1034
1278 1035
1279/** 1036/**
@@ -1360,362 +1117,6 @@ resolve_record_vpn (struct ResolverHandle *rh,
1360} 1117}
1361 1118
1362 1119
1363/**
1364 * The final phase of resolution.
1365 * rh->name is a name that is canonical and we do not have a delegation.
1366 * Query namestore for this record
1367 *
1368 * @param rh the pending lookup handle
1369 */
1370static void
1371resolve_record_ns(struct ResolverHandle *rh)
1372{
1373 struct RecordLookupHandle *rlh = rh->proc_cls;
1374
1375 /* We cancel here as to not include the ns lookup in the timeout */
1376 if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task)
1377 {
1378 GNUNET_SCHEDULER_cancel(rh->timeout_task);
1379 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1380 }
1381 /* Start shortening */
1382 if ((NULL != rh->priv_key) &&
1383 (GNUNET_YES == is_canonical (rh->name)))
1384 {
1385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1386 "GNS_PHASE_REC-%llu: Trying to shorten authority chain\n",
1387 rh->id);
1388 start_shorten (rh->authority_chain_head,
1389 rh->priv_key);
1390 }
1391
1392 /**
1393 * Try to resolve this record in our namestore.
1394 * The name to resolve is now in rh->authority_name
1395 * since we tried to resolve it to an authority
1396 * and failed.
1397 **/
1398 rh->namestore_task = GNUNET_NAMESTORE_lookup_record(namestore_handle,
1399 &rh->authority,
1400 rh->name,
1401 rlh->record_type,
1402 &process_record_result_ns,
1403 rh);
1404}
1405
1406
1407/**
1408 * This is a callback function that checks for key revocation
1409 *
1410 * @param cls the pending query
1411 * @param key the key of the zone we did the lookup
1412 * @param expiration expiration date of the record data set in the namestore
1413 * @param name the name for which we need an authority
1414 * @param rd_count the number of records with 'name'
1415 * @param rd the record data
1416 * @param signature the signature of the authority for the record data
1417 */
1418static void
1419process_pkey_revocation_result_ns (void *cls,
1420 const struct GNUNET_CRYPTO_EccPublicKey *key,
1421 struct GNUNET_TIME_Absolute expiration,
1422 const char *name,
1423 unsigned int rd_count,
1424 const struct GNUNET_NAMESTORE_RecordData *rd,
1425 const struct GNUNET_CRYPTO_EccSignature *signature)
1426{
1427 struct ResolverHandle *rh = cls;
1428 struct GNUNET_TIME_Relative remaining_time;
1429 int i;
1430
1431 rh->namestore_task = NULL;
1432 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
1433
1434 for (i = 0; i < rd_count; i++)
1435 {
1436 if (GNUNET_NAMESTORE_TYPE_REV == rd[i].record_type)
1437 {
1438 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1439 "GNS_PHASE_DELEGATE_REV-%llu: Zone has been revoked.\n",
1440 rh->id);
1441 rh->status |= RSL_PKEY_REVOKED;
1442 rh->proc (rh->proc_cls, rh, 0, NULL);
1443 return;
1444 }
1445 }
1446
1447 if ((NULL == name) ||
1448 (0 == remaining_time.rel_value_us))
1449 {
1450 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1451 "GNS_PHASE_DELEGATE_REV-%llu: + Records don't exist or are expired.\n",
1452 rh->id, name);
1453
1454 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != rh->timeout.rel_value_us)
1455 {
1456 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1457 "GNS_PHASE_DELEGATE_REV-%llu: Starting background lookup for %s type %d\n",
1458 rh->id, "+.gnu", GNUNET_NAMESTORE_TYPE_REV);
1459
1460 gns_resolver_lookup_record(rh->authority,
1461 rh->private_local_zone,
1462 GNUNET_NAMESTORE_TYPE_REV,
1463 GNUNET_GNS_TLD,
1464 NULL,
1465 GNUNET_TIME_UNIT_FOREVER_REL,
1466 GNUNET_NO,
1467 &background_lookup_result_processor,
1468 NULL);
1469 }
1470 }
1471 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1472 "GNS_PHASE_DELEGATE_REV-%llu: Revocation check passed\n",
1473 rh->id);
1474 /**
1475 * We are done with PKEY resolution if name is empty
1476 * else resolve again with new authority
1477 */
1478 if (strcmp (rh->name, "") == 0)
1479 rh->proc (rh->proc_cls, rh, rh->rd_count, &rh->rd);
1480 else
1481 resolve_delegation_ns (rh);
1482}
1483
1484
1485/**
1486 * Function called when we get a result from the dht
1487 * for our query. Recursively tries to resolve authorities
1488 * for name in DHT.
1489 *
1490 * @param cls the request handle
1491 * @param exp lifetime
1492 * @param key the key the record was stored under
1493 * @param get_path get path
1494 * @param get_path_length get path length
1495 * @param put_path put path
1496 * @param put_path_length put path length
1497 * @param type the block type
1498 * @param size the size of the record
1499 * @param data the record data
1500 */
1501static void
1502process_delegation_result_dht (void* cls,
1503 struct GNUNET_TIME_Absolute exp,
1504 const struct GNUNET_HashCode * key,
1505 const struct GNUNET_PeerIdentity *get_path,
1506 unsigned int get_path_length,
1507 const struct GNUNET_PeerIdentity *put_path,
1508 unsigned int put_path_length,
1509 enum GNUNET_BLOCK_Type type,
1510 size_t size, const void *data)
1511{
1512 struct ResolverHandle *rh = cls;
1513 const struct GNSNameRecordBlock *nrb = data;
1514 const char* rd_data;
1515 uint32_t num_records;
1516 const char* name;
1517 uint32_t i;
1518 int rd_size;
1519 struct GNUNET_CRYPTO_ShortHashCode zone;
1520
1521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1522 "GNS_PHASE_DELEGATE_DHT-%llu: Got DHT result\n",
1523 rh->id);
1524 if (data == NULL)
1525 return;
1526 /* stop dht lookup and timeout task */
1527 GNUNET_DHT_get_stop (rh->get_handle);
1528 rh->get_handle = NULL;
1529 if (rh->dht_heap_node != NULL)
1530 {
1531 GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node);
1532 rh->dht_heap_node = NULL;
1533 }
1534
1535 num_records = ntohl(nrb->rd_count);
1536 name = (const char*) &nrb[1];
1537 {
1538 struct GNUNET_NAMESTORE_RecordData rd[num_records];
1539 struct NamestoreBGTask *ns_heap_root;
1540 struct NamestoreBGTask *namestore_bg_task;
1541
1542 rd_data = name + strlen(name) + 1;
1543 rd_size = size - strlen(name) - 1 - sizeof (struct GNSNameRecordBlock);
1544 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
1545 rd_data,
1546 num_records,
1547 rd))
1548 {
1549 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1550 "GNS_PHASE_DELEGATE_DHT-%llu: Error deserializing data!\n",
1551 rh->id);
1552 return;
1553 }
1554
1555 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1556 "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n",
1557 rh->id, name, rh->authority_name);
1558 for (i=0; i<num_records; i++)
1559 {
1560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1561 "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n",
1562 rh->id, name, rh->authority_name);
1563 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1564 "GNS_PHASE_DELEGATE_DHT-%llu: Got type: %d (wanted %d)\n",
1565 rh->id, rd[i].record_type, GNUNET_NAMESTORE_TYPE_PKEY);
1566 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1567 "GNS_PHASE_DELEGATE_DHT-%llu: Got data length: %d\n",
1568 rh->id, rd[i].data_size);
1569 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1570 "GNS_PHASE_DELEGATE_DHT-%llu: Got flag %d\n",
1571 rh->id, rd[i].flags);
1572
1573 if ((GNUNET_NAMESTORE_TYPE_VPN == rd[i].record_type) ||
1574 (GNUNET_DNSPARSER_TYPE_NS == rd[i].record_type) ||
1575 (GNUNET_DNSPARSER_TYPE_CNAME == rd[i].record_type))
1576 {
1577 /**
1578 * This is a VPN,NS,CNAME entry. Let namestore handle this after caching
1579 */
1580 if (0 == strcmp(rh->name, ""))
1581 strcpy(rh->name, rh->authority_name);
1582 else
1583 GNUNET_snprintf(rh->name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s",
1584 rh->name, rh->authority_name); //FIXME ret
1585 rh->answered = 1;
1586 break;
1587 }
1588
1589 if ((0 == strcmp(name, rh->authority_name)) &&
1590 (GNUNET_NAMESTORE_TYPE_PKEY == rd[i].record_type))
1591 {
1592 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1593 "GNS_PHASE_DELEGATE_DHT-%llu: Authority found in DHT\n",
1594 rh->id);
1595 rh->answered = 1;
1596 memcpy(&rh->authority, rd[i].data, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
1597 struct AuthorityChain *auth =
1598 GNUNET_malloc(sizeof(struct AuthorityChain));
1599 auth->zone = rh->authority;
1600 memset(auth->name, 0, strlen(rh->authority_name)+1);
1601 strcpy(auth->name, rh->authority_name);
1602 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
1603 rh->authority_chain_tail,
1604 auth);
1605
1606 if (NULL != rh->rd.data)
1607 GNUNET_free ((void*)rh->rd.data);
1608
1609 memcpy (&rh->rd, &rd[i], sizeof (struct GNUNET_NAMESTORE_RecordData));
1610 rh->rd.data = GNUNET_malloc (rd[i].data_size);
1611 memcpy ((void*)(rh->rd.data), rd[i].data, rd[i].data_size);
1612 rh->rd_count = 1;
1613
1614 /** try to import pkey if private key available */
1615 //if (rh->priv_key && is_canonical (rh->name))
1616 // process_discovered_authority(name, auth->zone,
1617 // rh->authority_chain_tail->zone,
1618 // rh->priv_key);
1619 }
1620
1621 }
1622 GNUNET_GNS_get_zone_from_key (name, key, &zone);
1623
1624
1625 /* Save to namestore
1626 if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
1627 &zone))
1628 {*/
1629 if (max_allowed_ns_tasks <=
1630 GNUNET_CONTAINER_heap_get_size (ns_task_heap))
1631 {
1632 ns_heap_root = GNUNET_CONTAINER_heap_remove_root (ns_task_heap);
1633 GNUNET_NAMESTORE_cancel (ns_heap_root->qe);
1634
1635 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1636 "GNS_PHASE_DELEGATE_DHT-%llu: Replacing oldest background ns task\n",
1637 rh->id);
1638 }
1639 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1640 "GNS_PHASE_DELEGATE_DHT-%llu: Caching record for %s\n",
1641 rh->id, name);
1642 namestore_bg_task = GNUNET_malloc (sizeof (struct NamestoreBGTask));
1643
1644 namestore_bg_task->node = GNUNET_CONTAINER_heap_insert (ns_task_heap,
1645 namestore_bg_task,
1646 GNUNET_TIME_absolute_get().abs_value_us);
1647 namestore_bg_task->qe = GNUNET_NAMESTORE_record_put (namestore_handle,
1648 &nrb->public_key,
1649 name,
1650 exp,
1651 num_records,
1652 rd,
1653 &nrb->signature,
1654 &on_namestore_delegation_put_result, //cont
1655 namestore_bg_task); //cls
1656 }
1657 //}
1658
1659 if (0 != rh->answered)
1660 {
1661 rh->answered = 0;
1662 /**
1663 * delegate
1664 * FIXME in this case. should we ask namestore again?
1665 */
1666 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1667 "GNS_PHASE_DELEGATE_DHT-%llu: Answer from DHT for %s. Yet to resolve: %s\n",
1668 rh->id, rh->authority_name, rh->name);
1669
1670 if (0 == strcmp(rh->name, ""))
1671 {
1672 /* Start shortening */
1673 if ((NULL != rh->priv_key) &&
1674 (GNUNET_YES == is_canonical (rh->name)))
1675 {
1676 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1677 "GNS_PHASE_DELEGATE_DHT-%llu: Trying to shorten authority chain\n",
1678 rh->id);
1679 start_shorten (rh->authority_chain_head,
1680 rh->priv_key);
1681 }
1682 }
1683 else
1684 rh->proc = &handle_delegation_ns;
1685
1686
1687 /* Check for key revocation and delegate */
1688 rh->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle,
1689 &rh->authority,
1690 GNUNET_GNS_MASTERZONE_STR,
1691 GNUNET_NAMESTORE_TYPE_REV,
1692 &process_pkey_revocation_result_ns,
1693 rh);
1694
1695 return;
1696 }
1697
1698 /**
1699 * No pkey but name exists
1700 * promote back
1701 */
1702 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1703 "GNS_PHASE_DELEGATE_DHT-%llu: Adding %s back to %s\n",
1704 rh->id, rh->authority_name, rh->name);
1705 if (0 == strcmp(rh->name, ""))
1706 strcpy(rh->name, rh->authority_name);
1707 else
1708 GNUNET_snprintf(rh->name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s",
1709 rh->name, rh->authority_name); //FIXME ret
1710
1711 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1712 "GNS_PHASE_DELEGATE_DHT-%llu: %s restored\n", rh->id, rh->name);
1713 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1714 "GNS_PHASE_DELEGATE_DHT-%llu: DHT authority lookup found no match!\n",
1715 rh->id);
1716 rh->proc(rh->proc_cls, rh, 0, NULL);
1717}
1718
1719//FIXME maybe define somewhere else? 1120//FIXME maybe define somewhere else?
1720#define MAX_SOA_LENGTH sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)\ 1121#define MAX_SOA_LENGTH sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)\
1721 +(GNUNET_DNSPARSER_MAX_NAME_LENGTH*2) 1122 +(GNUNET_DNSPARSER_MAX_NAME_LENGTH*2)
@@ -1897,718 +1298,6 @@ finish_lookup (struct ResolverHandle *rh,
1897} 1298}
1898 1299
1899 1300
1900/**
1901 * Process DHT lookup result for record.
1902 *
1903 * @param cls the closure
1904 * @param rh resolver handle
1905 * @param rd_count number of results
1906 * @param rd record data
1907 */
1908static void
1909handle_record_dht (void* cls, struct ResolverHandle *rh,
1910 unsigned int rd_count,
1911 const struct GNUNET_NAMESTORE_RecordData *rd)
1912{
1913 struct RecordLookupHandle* rlh = cls;
1914
1915 if (0 == rd_count)
1916 {
1917 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1918 "GNS_PHASE_REC-%llu: No records for %s found in DHT. Aborting\n",
1919 rh->id, rh->name);
1920 /* give up, cannot resolve */
1921 finish_lookup (rh, rlh, 0, NULL);
1922 return;
1923 }
1924 /* results found yay */
1925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1926 "GNS_PHASE_REC-%llu: Record resolved from DHT!", rh->id);
1927 finish_lookup (rh, rlh, rd_count, rd);
1928}
1929
1930
1931/**
1932 * Process namestore lookup result for record.
1933 *
1934 * @param cls the closure
1935 * @param rh resolver handle
1936 * @param rd_count number of results
1937 * @param rd record data
1938 */
1939static void
1940handle_record_ns (void* cls, struct ResolverHandle *rh,
1941 unsigned int rd_count,
1942 const struct GNUNET_NAMESTORE_RecordData *rd)
1943{
1944 struct RecordLookupHandle* rlh = cls;
1945 int check_dht = GNUNET_YES;
1946
1947 if (0 != rd_count)
1948 {
1949 /* results found yay */
1950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1951 "GNS_PHASE_REC-%llu: Record resolved from namestore!\n", rh->id);
1952 finish_lookup (rh, rlh, rd_count, rd);
1953 return;
1954 }
1955
1956 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1957 "GNS_PHASE_REC-%llu: NS returned no records. (status: %d)!\n",
1958 rh->id,
1959 rh->status);
1960 /**
1961 * There are 5 conditions that have to met for us to consult the DHT:
1962 * 1. The entry in the DHT is RSL_RECORD_EXPIRED OR
1963 * 2. No entry in the NS existed AND
1964 * 3. The zone queried is not the local resolver's zone AND
1965 * 4. The name that was looked up is '+'
1966 * because if it was any other canonical name we either already queried
1967 * the DHT for the authority in the authority lookup phase (and thus
1968 * would already have an entry in the NS for the record)
1969 * 5. We are not in cache only mode
1970 */
1971 if ((0 != (rh->status & RSL_RECORD_EXPIRED)) &&
1972 (0 == (rh->status & RSL_RECORD_EXISTS)) )
1973 {
1974
1975 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1976 "GNS_PHASE_REC-%llu: Not expired and exists!\n",
1977 rh->id);
1978 check_dht = GNUNET_NO;
1979 }
1980
1981 if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
1982 &rh->private_local_zone))
1983 {
1984
1985 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1986 "GNS_PHASE_REC-%llu: Our zone!\n",
1987 rh->id);
1988 check_dht = GNUNET_NO;
1989 }
1990
1991 if ((0 != strcmp (rh->name, GNUNET_GNS_MASTERZONE_STR)) && (GNUNET_YES == is_srv (rh->name)))
1992 check_dht = GNUNET_NO;
1993
1994 if (GNUNET_YES == rh->only_cached)
1995 check_dht = GNUNET_NO;
1996
1997 if (GNUNET_YES == check_dht)
1998 {
1999 rh->proc = &handle_record_dht;
2000 resolve_record_dht(rh);
2001 return;
2002 }
2003 /* give up, cannot resolve */
2004 finish_lookup (rh, rlh, 0, NULL);
2005}
2006
2007
2008/**
2009 * Move one level up in the domain hierarchy and return the
2010 * passed top level domain.
2011 *
2012 * FIXME: funky API: not only 'dest' is updated, so is 'name'!
2013 *
2014 * @param name the domain
2015 * @param dest the destination where the tld will be put
2016 */
2017static void
2018pop_tld (char* name, char* dest)
2019{
2020 uint32_t len;
2021
2022 if (GNUNET_YES == is_canonical (name))
2023 {
2024 strcpy (dest, name);
2025 strcpy (name, "");
2026 return;
2027 }
2028
2029 for (len = strlen(name); 0 < len; len--)
2030 {
2031 if (*(name+len) == '.')
2032 break;
2033 }
2034
2035 //Was canonical?
2036 if (0 == len)
2037 return;
2038 name[len] = '\0';
2039 strcpy (dest, (name+len+1));
2040}
2041
2042
2043/**
2044 * DHT resolution for delegation finished. Processing result.
2045 *
2046 * @param cls the closure
2047 * @param rh resolver handle
2048 * @param rd_count number of results (always 0)
2049 * @param rd record data (always NULL)
2050 */
2051static void
2052handle_delegation_dht(void* cls, struct ResolverHandle *rh,
2053 unsigned int rd_count,
2054 const struct GNUNET_NAMESTORE_RecordData *rd)
2055{
2056 struct RecordLookupHandle* rlh = cls;
2057
2058 if (0 == strcmp(rh->name, ""))
2059 {
2060 if (GNUNET_NAMESTORE_TYPE_PKEY == rlh->record_type)
2061 {
2062 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2063 "GNS_PHASE_DELEGATE_DHT-%llu: Resolved queried PKEY via DHT.\n",
2064 rh->id);
2065 finish_lookup(rh, rlh, rd_count, rd);
2066 return;
2067 }
2068 /* We resolved full name for delegation. resolving record */
2069 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2070 "GNS_PHASE_DELEGATE_DHT-%llu: Resolved full name for delegation via DHT.\n",
2071 rh->id);
2072 strcpy(rh->name, "+\0");
2073 rh->proc = &handle_record_ns;
2074 resolve_record_ns(rh);
2075 return;
2076 }
2077
2078 /**
2079 * we still have some left
2080 **/
2081 if (GNUNET_YES == is_canonical (rh->name))
2082 {
2083 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2084 "GNS_PHASE_DELEGATE_DHT-%llu: Resolving canonical record %s in ns\n",
2085 rh->id,
2086 rh->name);
2087 rh->proc = &handle_record_ns;
2088 resolve_record_ns(rh);
2089 return;
2090 }
2091 /* give up, cannot resolve */
2092 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2093 "GNS_PHASE_DELEGATE_DHT-%llu: Cannot fully resolve delegation for %s via DHT!\n",
2094 rh->id, rh->name);
2095 finish_lookup(rh, rlh, 0, NULL);
2096}
2097
2098
2099/**
2100 * Start DHT lookup for a name -> PKEY (compare NS) record in
2101 * rh->authority's zone
2102 *
2103 * @param rh the pending gns query
2104 */
2105static void
2106resolve_delegation_dht (struct ResolverHandle *rh)
2107{
2108 uint32_t xquery;
2109 struct GNUNET_HashCode lookup_key;
2110 struct ResolverHandle *rh_heap_root;
2111
2112 pop_tld (rh->name, rh->authority_name);
2113 GNUNET_GNS_get_key_for_record (rh->authority_name,
2114 &rh->authority,
2115 &lookup_key);
2116 rh->dht_heap_node = NULL;
2117 if (rh->timeout.rel_value_us != GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
2118 {
2119 rh->timeout_cont = &dht_authority_lookup_timeout;
2120 rh->timeout_cont_cls = rh;
2121 }
2122 else
2123 {
2124 if (max_allowed_background_queries <=
2125 GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
2126 {
2127 /* terminate oldest lookup */
2128 rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
2129 GNUNET_DHT_get_stop (rh_heap_root->get_handle);
2130 rh_heap_root->get_handle = NULL;
2131 rh_heap_root->dht_heap_node = NULL;
2132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2133 "GNS_PHASE_DELEGATE_DHT-%llu: Replacing oldest background query for %s\n",
2134 rh->id,
2135 rh_heap_root->authority_name);
2136 rh_heap_root->proc (rh_heap_root->proc_cls,
2137 rh_heap_root,
2138 0,
2139 NULL);
2140 }
2141 rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
2142 rh,
2143 GNUNET_TIME_absolute_get().abs_value_us);
2144 }
2145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2146 "Beginning DHT lookup for %s in zone %s for request %llu\n",
2147 rh->authority_name,
2148 GNUNET_short_h2s (&rh->authority),
2149 rh->id);
2150 xquery = htonl (GNUNET_NAMESTORE_TYPE_PKEY);
2151 GNUNET_assert (rh->get_handle == NULL);
2152 rh->get_handle = GNUNET_DHT_get_start (dht_handle,
2153 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
2154 &lookup_key,
2155 DHT_GNS_REPLICATION_LEVEL,
2156 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
2157 &xquery,
2158 sizeof(xquery),
2159 &process_delegation_result_dht,
2160 rh);
2161}
2162
2163
2164/**
2165 * Namestore resolution for delegation finished. Processing result.
2166 *
2167 * @param cls the closure
2168 * @param rh resolver handle
2169 * @param rd_count number of results (always 0)
2170 * @param rd record data (always NULL)
2171 */
2172static void
2173handle_delegation_ns (void* cls, struct ResolverHandle *rh,
2174 unsigned int rd_count,
2175 const struct GNUNET_NAMESTORE_RecordData *rd)
2176{
2177 struct RecordLookupHandle* rlh = cls;
2178 int check_dht;
2179 size_t s_len;
2180
2181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2182 "GNS_PHASE_DELEGATE_NS-%llu: Resolution status: %d.\n",
2183 rh->id, rh->status);
2184
2185 if (rh->status & RSL_PKEY_REVOKED)
2186 {
2187 finish_lookup (rh, rlh, 0, NULL);
2188 return;
2189 }
2190
2191 if (0 == strcmp(rh->name, ""))
2192 {
2193
2194 /* We resolved full name for delegation. resolving record */
2195 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2196 "GNS_PHASE_DELEGATE_NS-%llu: Resolved full name for delegation.\n",
2197 rh->id);
2198 if (rh->status & RSL_CNAME_FOUND)
2199 {
2200 if (GNUNET_DNSPARSER_TYPE_CNAME == rlh->record_type)
2201 {
2202 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2203 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried CNAME in NS.\n",
2204 rh->id);
2205 strcpy (rh->name, rh->authority_name);
2206 finish_lookup (rh, rlh, rd_count, rd);
2207 return;
2208 }
2209
2210 /* A .+ CNAME */
2211 if (GNUNET_YES == is_tld ((char*)rd->data, GNUNET_GNS_TLD_PLUS))
2212 {
2213 s_len = strlen (rd->data) - 2;
2214 memcpy (rh->name, rd->data, s_len);
2215 rh->name[s_len] = '\0';
2216 resolve_delegation_ns (rh);
2217 return;
2218 }
2219 else if (GNUNET_YES == is_tld ((char*)rd->data, GNUNET_GNS_TLD_ZKEY))
2220 {
2221 gns_resolver_lookup_record (rh->authority,
2222 rh->private_local_zone,
2223 rlh->record_type,
2224 (char*)rd->data,
2225 rh->priv_key,
2226 rh->timeout,
2227 rh->only_cached,
2228 rlh->proc,
2229 rlh->proc_cls);
2230 GNUNET_free (rlh);
2231 GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh);
2232 free_resolver_handle (rh);
2233 return;
2234 }
2235 else
2236 {
2237 //Try DNS resolver
2238 strcpy (rh->dns_name, (char*)rd->data);
2239 resolve_dns_name (rh);
2240 return;
2241 }
2242
2243 }
2244 else if (rh->status & RSL_DELEGATE_VPN)
2245 {
2246 if (GNUNET_NAMESTORE_TYPE_VPN == rlh->record_type)
2247 {
2248 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2249 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried VPNRR in NS.\n",
2250 rh->id);
2251 finish_lookup(rh, rlh, rd_count, rd);
2252 return;
2253 }
2254 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2255 "GNS_PHASE_DELEGATE_NS-%llu: VPN delegation starting.\n",
2256 rh->id);
2257 GNUNET_assert (NULL != rd);
2258 rh->proc = &handle_record_vpn;
2259 resolve_record_vpn (rh, rd_count, rd);
2260 return;
2261 }
2262 else if (rh->status & RSL_DELEGATE_NS)
2263 {
2264 if (GNUNET_DNSPARSER_TYPE_NS == rlh->record_type)
2265 {
2266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2267 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n",
2268 rh->id);
2269 finish_lookup (rh, rlh, rd_count, rd);
2270 return;
2271 }
2272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2273 "GNS_PHASE_DELEGATE_NS-%llu: NS delegation starting.\n",
2274 rh->id);
2275 GNUNET_assert (NULL != rd);
2276 rh->proc = &handle_record_ns;
2277 resolve_record_dns (rh, rd_count, rd);
2278 return;
2279 }
2280 else if (rh->status & RSL_DELEGATE_PKEY)
2281 {
2282 if (rh->status & RSL_PKEY_REVOKED)
2283 {
2284 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2285 "GNS_PHASE_DELEGATE_NS-%llu: Resolved PKEY is revoked.\n",
2286 rh->id);
2287 finish_lookup (rh, rlh, 0, NULL);
2288 return;
2289 }
2290 else if (GNUNET_NAMESTORE_TYPE_PKEY == rlh->record_type)
2291 {
2292 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2293 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried PKEY in NS.\n",
2294 rh->id);
2295 finish_lookup(rh, rlh, rd_count, rd);
2296 return;
2297 }
2298 }
2299 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2300 "GNS_PHASE_DELEGATE_NS-%llu: Resolving record +\n",
2301 rh->id);
2302 strcpy(rh->name, "+\0");
2303 rh->proc = &handle_record_ns;
2304 resolve_record_ns(rh);
2305 return;
2306 }
2307
2308 if (rh->status & RSL_DELEGATE_NS)
2309 {
2310 if (GNUNET_DNSPARSER_TYPE_NS == rlh->record_type)
2311 {
2312 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2313 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n",
2314 rh->id);
2315 finish_lookup(rh, rlh, rd_count, rd);
2316 return;
2317 }
2318
2319 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2320 "GNS_PHASE_DELEGATE_NS-%llu: NS delegation starting.\n",
2321 rh->id);
2322 GNUNET_assert (NULL != rd);
2323 rh->proc = &handle_record_ns;
2324 resolve_record_dns (rh, rd_count, rd);
2325 return;
2326 }
2327
2328 /**
2329 * we still have some left
2330 * check if authority in ns is fresh
2331 * and exists
2332 * or we are authority
2333 **/
2334
2335 check_dht = GNUNET_YES;
2336 if ((rh->status & RSL_RECORD_EXISTS) &&
2337 !(rh->status & RSL_RECORD_EXPIRED))
2338 check_dht = GNUNET_NO;
2339
2340 if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2341 &rh->private_local_zone))
2342 check_dht = GNUNET_NO;
2343
2344 if (GNUNET_YES == rh->only_cached)
2345 check_dht = GNUNET_NO;
2346
2347 if (GNUNET_YES == check_dht)
2348 {
2349
2350 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2351 "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n",
2352 rh->id, rh->name);
2353 rh->proc = &handle_delegation_dht;
2354 resolve_delegation_dht(rh);
2355 return;
2356 }
2357
2358 if (GNUNET_NO == is_canonical (rh->name))
2359 {
2360 /* give up, cannot resolve */
2361 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2362 "GNS_PHASE_DELEGATE_NS-%llu: Cannot fully resolve delegation for %s!\n",
2363 rh->id,
2364 rh->name);
2365 finish_lookup(rh, rlh, rd_count, rd);
2366 return;
2367 }
2368 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2369 "GNS_PHASE_DELEGATE_NS-%llu: Resolving canonical record %s\n",
2370 rh->id,
2371 rh->name);
2372 rh->proc = &handle_record_ns;
2373 resolve_record_ns(rh);
2374}
2375
2376
2377/**
2378 * This is a callback function that should give us only PKEY
2379 * records. Used to query the namestore for the authority (PKEY)
2380 * for 'name'. It will recursively try to resolve the
2381 * authority for a given name from the namestore.
2382 *
2383 * @param cls the pending query
2384 * @param key the key of the zone we did the lookup
2385 * @param expiration expiration date of the record data set in the namestore
2386 * @param name the name for which we need an authority
2387 * @param rd_count the number of records with 'name'
2388 * @param rd the record data
2389 * @param signature the signature of the authority for the record data
2390 */
2391static void
2392process_delegation_result_ns (void* cls,
2393 const struct GNUNET_CRYPTO_EccPublicKey *key,
2394 struct GNUNET_TIME_Absolute expiration,
2395 const char *name,
2396 unsigned int rd_count,
2397 const struct GNUNET_NAMESTORE_RecordData *rd,
2398 const struct GNUNET_CRYPTO_EccSignature *signature)
2399{
2400 struct ResolverHandle *rh = cls;
2401 struct GNUNET_TIME_Relative remaining_time;
2402 struct GNUNET_CRYPTO_ShortHashCode zone;
2403 char new_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
2404 unsigned int i;
2405 struct GNUNET_TIME_Absolute et;
2406 struct AuthorityChain *auth;
2407
2408 rh->namestore_task = NULL;
2409 GNUNET_CRYPTO_short_hash (key,
2410 sizeof (struct GNUNET_CRYPTO_EccPublicKey),
2411 &zone);
2412 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2413 "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup for `%s' in zone %s\n",
2414 rh->id, rd_count,
2415 name,
2416 GNUNET_short_h2s (&zone));
2417
2418 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
2419
2420 rh->status = 0;
2421
2422 if (NULL != name)
2423 {
2424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2425 "GNS_PHASE_DELEGATE_NS-%llu: Records with name `%s' exist in zone %s.\n",
2426 rh->id, name,
2427 GNUNET_short_h2s (&zone));
2428 rh->status |= RSL_RECORD_EXISTS;
2429
2430 if (0 == remaining_time.rel_value_us)
2431 {
2432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2433 "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n",
2434 rh->id, name);
2435 rh->status |= RSL_RECORD_EXPIRED;
2436 }
2437 }
2438
2439 /**
2440 * No authority found in namestore.
2441 */
2442 if (0 == rd_count)
2443 {
2444 /**
2445 * We did not find an authority in the namestore
2446 */
2447
2448 /**
2449 * No PKEY in zone.
2450 * Promote this authority back to a name maybe it is
2451 * our record.
2452 */
2453 if (strcmp (rh->name, "") == 0)
2454 {
2455 /* simply promote back */
2456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2457 "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
2458 rh->id, rh->authority_name);
2459 strcpy (rh->name, rh->authority_name);
2460 }
2461 else
2462 {
2463 /* add back to existing name */
2464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2465 "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n",
2466 rh->id, rh->authority_name, rh->name);
2467 GNUNET_snprintf (new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s",
2468 rh->name, rh->authority_name);
2469 strcpy (rh->name, new_name);
2470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2471 "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n",
2472 rh->id, rh->name);
2473 }
2474
2475 rh->proc (rh->proc_cls, rh, 0, NULL);
2476 return;
2477 }
2478
2479 /**
2480 * We found an authority that may be able to help us
2481 * move on with query
2482 * Note only 1 pkey should have been returned.. anything else would be strange
2483 */
2484 for (i=0; i < rd_count;i++)
2485 {
2486 switch (rd[i].record_type)
2487 {
2488 case GNUNET_DNSPARSER_TYPE_CNAME:
2489 /* Like in regular DNS this should mean that there is no other
2490 * record for this name. */
2491
2492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2493 "GNS_PHASE_DELEGATE_NS-%llu: CNAME `%.*s' found.\n",
2494 rh->id,
2495 (int) rd[i].data_size,
2496 rd[i].data);
2497 rh->status |= RSL_CNAME_FOUND;
2498 rh->proc (rh->proc_cls, rh, rd_count, rd);
2499 return;
2500 case GNUNET_NAMESTORE_TYPE_VPN:
2501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2502 "GNS_PHASE_DELEGATE_NS-%llu: VPN found.\n",
2503 rh->id);
2504 rh->status |= RSL_DELEGATE_VPN;
2505 rh->proc (rh->proc_cls, rh, rd_count, rd);
2506 return;
2507 case GNUNET_DNSPARSER_TYPE_NS:
2508 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2509 "GNS_PHASE_DELEGATE_NS-%llu: NS `%.*s' found.\n",
2510 rh->id,
2511 (int) rd[i].data_size,
2512 rd[i].data);
2513 rh->status |= RSL_DELEGATE_NS;
2514 rh->proc (rh->proc_cls, rh, rd_count, rd);
2515 return;
2516 case GNUNET_NAMESTORE_TYPE_PKEY:
2517 rh->status |= RSL_DELEGATE_PKEY;
2518 if ((ignore_pending_records != 0) &&
2519 (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
2520 {
2521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2522 "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n",
2523 rh->id,
2524 name);
2525 continue;
2526 }
2527 GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
2528 et.abs_value_us = rd[i].expiration_time;
2529 if (0 == (GNUNET_TIME_absolute_get_remaining (et)).rel_value_us)
2530 {
2531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2532 "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n",
2533 rh->id);
2534 if (remaining_time.rel_value_us == 0)
2535 {
2536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2537 "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n",
2538 rh->id);
2539 rh->authority_chain_head->fresh = 0;
2540 rh->proc (rh->proc_cls, rh, 0, NULL);
2541 return;
2542 }
2543 continue;
2544 }
2545 /* Resolve rest of query with new authority */
2546 memcpy (&rh->authority, rd[i].data,
2547 sizeof (struct GNUNET_CRYPTO_ShortHashCode));
2548 auth = GNUNET_malloc(sizeof (struct AuthorityChain));
2549 auth->zone = rh->authority;
2550 memset (auth->name, 0, strlen (rh->authority_name)+1);
2551 strcpy (auth->name, rh->authority_name);
2552 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
2553 rh->authority_chain_tail,
2554 auth);
2555 if (NULL != rh->rd.data)
2556 GNUNET_free ((void*)(rh->rd.data));
2557 memcpy (&rh->rd, &rd[i], sizeof (struct GNUNET_NAMESTORE_RecordData));
2558 rh->rd.data = GNUNET_malloc (rd[i].data_size);
2559 memcpy ((void*)rh->rd.data, rd[i].data, rd[i].data_size);
2560 rh->rd_count = 1;
2561 /* Check for key revocation and delegate */
2562 rh->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle,
2563 &rh->authority,
2564 GNUNET_GNS_MASTERZONE_STR,
2565 GNUNET_NAMESTORE_TYPE_REV,
2566 &process_pkey_revocation_result_ns,
2567 rh);
2568 return;
2569 default:
2570 /* ignore, move to next result */
2571 break;
2572 }
2573 }
2574
2575 /* no answers that would cause delegation were found */
2576 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2577 "GNS_PHASE_DELEGATE_NS-%llu: Authority lookup failed (no PKEY record)\n",
2578 rh->id);
2579 /**
2580 * If we have found some records for the LAST label
2581 * we return the results. Else NULL.
2582 */
2583 if (0 == strcmp (rh->name, ""))
2584 {
2585 /* Start shortening */
2586 if ((rh->priv_key != NULL) &&
2587 (is_canonical (rh->name) == GNUNET_YES))
2588 {
2589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2590 "GNS_PHASE_DELEGATE_NS-%llu: Trying to shorten authority chain\n",
2591 rh->id);
2592 start_shorten (rh->authority_chain_head,
2593 rh->priv_key);
2594 }
2595 /* simply promote back */
2596 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2597 "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
2598 rh->id, rh->authority_name);
2599 strcpy (rh->name, rh->authority_name);
2600 rh->proc (rh->proc_cls, rh, rd_count, rd);
2601 }
2602 else
2603 {
2604 GNUNET_snprintf (new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH,
2605 "%s.%s", rh->name, rh->authority_name);
2606 strcpy (rh->name, new_name);
2607 rh->proc (rh->proc_cls, rh, 0, NULL);
2608 }
2609}
2610
2611
2612#endif 1301#endif
2613 1302
2614/////////////////////////////////////////////////////////////////////////////////////////////////// 1303///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2921,6 +1610,25 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh)
2921 1610
2922 1611
2923/** 1612/**
1613 * We encountered a CNAME record during our resolution.
1614 * Merge it into our chain.
1615 *
1616 * @param rh resolution we are performing
1617 * @param cname value of the cname record we got for the current
1618 * authority chain tail
1619 */
1620static void
1621handle_gns_cname_result (struct GNS_ResolverHandle *rh,
1622 const char *cname)
1623{
1624 // FIXME: not implemented
1625 GNUNET_break (0);
1626 rh->proc (rh->proc_cls, 0, NULL);
1627 GNS_resolver_lookup_cancel (rh);
1628}
1629
1630
1631/**
2924 * Process a records that were decrypted from a block. 1632 * Process a records that were decrypted from a block.
2925 * 1633 *
2926 * @param cls closure with the 'struct GNS_ResolverHandle' 1634 * @param cls closure with the 'struct GNS_ResolverHandle'
@@ -2933,14 +1641,179 @@ handle_gns_resolution_result (void *cls,
2933 const struct GNUNET_NAMESTORE_RecordData *rd) 1641 const struct GNUNET_NAMESTORE_RecordData *rd)
2934{ 1642{
2935 struct GNS_ResolverHandle *rh = cls; 1643 struct GNS_ResolverHandle *rh = cls;
1644 struct AuthorityChain *ac;
1645 unsigned int i;
1646 unsigned int j;
1647 struct sockaddr *sa;
1648 struct sockaddr_in v4;
1649 struct sockaddr_in6 v6;
1650 size_t sa_len;
1651 char *cname;
2936 1652
2937 // FIXME: not implemented 1653 if (0 == rh->name_resolution_pos)
2938 // if this was the last label, return 'rd' to application 1654 {
2939 // (possibly first checking about converting records 1655 /* top-level match, are we done yet? */
2940 // to requested type, if possible). 1656 if ( (rd_count > 0) &&
2941 // if not, look for PKEY, CNAME, DNAME or NS to extend 1657 (GNUNET_DNSPARSER_TYPE_CNAME == rd[0].record_type) &&
2942 // auth chain and continue with recursion 1658 (GNUNET_DNSPARSER_TYPE_CNAME != rh->record_type) )
2943 GNUNET_break (0); 1659 {
1660 cname = GNUNET_strndup (rd[0].data,
1661 rd[0].data_size);
1662 handle_gns_cname_result (rh,
1663 cname);
1664 GNUNET_free (cname);
1665 return;
1666 }
1667 /* FIXME: if A/AAAA was requested, but we got a VPN
1668 record, we should interact with GNUnet VPN here */
1669
1670 /* yes, we are done, return result */
1671 rh->proc (rh->proc_cls, rd_count, rd);
1672 GNS_resolver_lookup_cancel (rh);
1673 return;
1674 }
1675 /* need to recurse, check if we can */
1676 for (i=0;i<rd_count;i++)
1677 {
1678 switch (rd[i].record_type)
1679 {
1680 case GNUNET_NAMESTORE_TYPE_PKEY:
1681 /* delegation to another zone */
1682 if (sizeof (struct GNUNET_CRYPTO_EccPublicKey) !=
1683 rd[i].data_size)
1684 {
1685 GNUNET_break_op (0);
1686 rh->proc (rh->proc_cls, 0, NULL);
1687 GNS_resolver_lookup_cancel (rh);
1688 return;
1689 }
1690 /* expand authority chain */
1691 ac = GNUNET_new (struct AuthorityChain);
1692 ac->rh = rh;
1693 ac->gns_authority = GNUNET_YES;
1694 memcpy (&ac->authority_info.gns_authority,
1695 rd[i].data,
1696 sizeof (struct GNUNET_CRYPTO_EccPublicKey));
1697 ac->label = resolver_lookup_get_next_label (rh);
1698 GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1699 rh->ac_tail,
1700 ac);
1701 /* recurse */
1702 rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1703 rh);
1704 break;
1705 case GNUNET_DNSPARSER_TYPE_NS:
1706 /* resolution continues within DNS */
1707 if (GNUNET_DNSPARSER_MAX_NAME_LENGTH < rd[i].data_size)
1708 {
1709 GNUNET_break_op (0);
1710 rh->proc (rh->proc_cls, 0, NULL);
1711 GNS_resolver_lookup_cancel (rh);
1712 return;
1713 }
1714 /* find associated A/AAAA record */
1715 sa = NULL;
1716 for (j=0;j<rd_count;j++)
1717 {
1718 switch (rd[j].record_type)
1719 {
1720 case GNUNET_DNSPARSER_TYPE_A:
1721 if (sizeof (struct in_addr) != rd[i].data_size)
1722 {
1723 GNUNET_break_op (0);
1724 rh->proc (rh->proc_cls, 0, NULL);
1725 GNS_resolver_lookup_cancel (rh);
1726 return;
1727 }
1728 /* FIXME: might want to check if we support IPv4 here,
1729 and otherwise skip this one and hope we find another */
1730 memset (&v4, 0, sizeof (v4));
1731 sa_len = sizeof (v4);
1732 v4.sin_family = AF_INET;
1733 v4.sin_port = htons (53);
1734#if HAVE_SOCKADDR_IN_SIN_LEN
1735 v4.sin_len = (u_char) sa_len;
1736#endif
1737 memcpy (&v4.sin_addr,
1738 rd[j].data,
1739 sizeof (struct in_addr));
1740 sa = (struct sockaddr *) &v4;
1741 break;
1742 case GNUNET_DNSPARSER_TYPE_AAAA:
1743 if (sizeof (struct in6_addr) != rd[i].data_size)
1744 {
1745 GNUNET_break_op (0);
1746 rh->proc (rh->proc_cls, 0, NULL);
1747 GNS_resolver_lookup_cancel (rh);
1748 return;
1749 }
1750 /* FIXME: might want to check if we support IPv6 here,
1751 and otherwise skip this one and hope we find another */
1752 memset (&v6, 0, sizeof (v6));
1753 sa_len = sizeof (v6);
1754 v6.sin6_family = AF_INET6;
1755 v6.sin6_port = htons (53);
1756#if HAVE_SOCKADDR_IN_SIN_LEN
1757 v6.sin6_len = (u_char) sa_len;
1758#endif
1759 memcpy (&v6.sin6_addr,
1760 rd[j].data,
1761 sizeof (struct in6_addr));
1762 sa = (struct sockaddr *) &v6;
1763 break;
1764 }
1765 if (NULL != sa)
1766 break;
1767 }
1768 /* expand authority chain */
1769 ac = GNUNET_new (struct AuthorityChain);
1770 ac->rh = rh;
1771 strncpy (ac->authority_info.dns_authority.name,
1772 rd[i].data,
1773 rd[i].data_size);
1774 ac->authority_info.dns_authority.name[rd[i].data_size] = '\0';
1775 memcpy (&ac->authority_info.dns_authority.dns_ip,
1776 sa,
1777 sa_len);
1778 /* for DNS recursion, the label is the full DNS name,
1779 created from the remainder of the GNS name and the
1780 name in the NS record */
1781 GNUNET_asprintf (&ac->label,
1782 "%.*s%s",
1783 (int) rh->name_resolution_pos,
1784 rh->name,
1785 ac->authority_info.dns_authority.name);
1786 GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1787 rh->ac_tail,
1788 ac);
1789 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1790 {
1791 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1792 _("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1793 ac->label);
1794 rh->proc (rh->proc_cls, 0, NULL);
1795 GNS_resolver_lookup_cancel (rh);
1796 return;
1797 }
1798 /* recurse */
1799 rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1800 rh);
1801 return;
1802 case GNUNET_DNSPARSER_TYPE_CNAME:
1803 cname = GNUNET_strndup (rd[i].data,
1804 rd[i].data_size);
1805 handle_gns_cname_result (rh,
1806 cname);
1807 GNUNET_free (cname);
1808 return;
1809 /* FIXME: handle DNAME */
1810 default:
1811 /* skip */
1812 break;
1813 }
1814 }
1815 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1816 _("GNS lookup recursion failed (no delegation record found)\n"));
2944 rh->proc (rh->proc_cls, 0, NULL); 1817 rh->proc (rh->proc_cls, 0, NULL);
2945 GNS_resolver_lookup_cancel (rh); 1818 GNS_resolver_lookup_cancel (rh);
2946} 1819}
@@ -3132,7 +2005,7 @@ recursive_gns_resolution_namestore (struct GNS_ResolverHandle *rh)
3132 */ 2005 */
3133static void 2006static void
3134recursive_resolution (void *cls, 2007recursive_resolution (void *cls,
3135 const struct GNUNET_SCHEDULER_TaskContext *tc) 2008 const struct GNUNET_SCHEDULER_TaskContext *tc)
3136{ 2009{
3137 struct GNS_ResolverHandle *rh = cls; 2010 struct GNS_ResolverHandle *rh = cls;
3138 2011
@@ -3423,6 +2296,4 @@ is_tld (const char* name, const char* tld)
3423} 2296}
3424 2297
3425 2298
3426
3427
3428/* end of gnunet-service-gns_resolver.c */ 2299/* end of gnunet-service-gns_resolver.c */