diff options
Diffstat (limited to 'src/gns')
-rw-r--r-- | src/gns/gnunet-service-gns.c | 4 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns_resolver.c | 1561 |
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 | */ | ||
957 | static void | ||
958 | process_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 | */ | ||
1126 | static void | ||
1127 | handle_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 | */ | ||
1161 | static void | ||
1162 | resolve_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 | */ | ||
1370 | static void | ||
1371 | resolve_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 | */ | ||
1418 | static void | ||
1419 | process_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 | */ | ||
1501 | static void | ||
1502 | process_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 | */ | ||
1908 | static void | ||
1909 | handle_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 | */ | ||
1939 | static void | ||
1940 | handle_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 | */ | ||
2017 | static void | ||
2018 | pop_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 | */ | ||
2051 | static void | ||
2052 | handle_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 | */ | ||
2105 | static void | ||
2106 | resolve_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 | */ | ||
2172 | static void | ||
2173 | handle_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 | */ | ||
2391 | static void | ||
2392 | process_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 | */ | ||
1620 | static void | ||
1621 | handle_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 | */ |
3133 | static void | 2006 | static void |
3134 | recursive_resolution (void *cls, | 2007 | recursive_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 */ |