diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-07-07 20:29:24 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-07-07 20:29:24 +0200 |
commit | 3abeb45550e1cbf4939583c9b6ff48335fe6f1a9 (patch) | |
tree | a653991a417cc0a683a95d3b61c67e26fb341486 /src/dht/gnunet-service-dht_neighbours.c | |
parent | 2906241b6a21d6009a0d195199f3a08e8f4d4e2a (diff) | |
download | gnunet-3abeb45550e1cbf4939583c9b6ff48335fe6f1a9.tar.gz gnunet-3abeb45550e1cbf4939583c9b6ff48335fe6f1a9.zip |
implemented new DHT path signing with origin authentication
Diffstat (limited to 'src/dht/gnunet-service-dht_neighbours.c')
-rw-r--r-- | src/dht/gnunet-service-dht_neighbours.c | 566 |
1 files changed, 415 insertions, 151 deletions
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c index 2a54f715a..cc7333a9c 100644 --- a/src/dht/gnunet-service-dht_neighbours.c +++ b/src/dht/gnunet-service-dht_neighbours.c | |||
@@ -150,8 +150,12 @@ struct PeerPutMessage | |||
150 | */ | 150 | */ |
151 | struct GNUNET_HashCode key; | 151 | struct GNUNET_HashCode key; |
152 | 152 | ||
153 | /* trunc_peer (if truncated) */ | ||
154 | |||
153 | /* put path (if tracked) */ | 155 | /* put path (if tracked) */ |
154 | 156 | ||
157 | /* sender_sig (if path tracking is on) */ | ||
158 | |||
155 | /* Payload */ | 159 | /* Payload */ |
156 | }; | 160 | }; |
157 | 161 | ||
@@ -172,9 +176,9 @@ struct PeerResultMessage | |||
172 | uint32_t type GNUNET_PACKED; | 176 | uint32_t type GNUNET_PACKED; |
173 | 177 | ||
174 | /** | 178 | /** |
175 | * Reserved. | 179 | * Message options, actually an 'enum GNUNET_DHT_RouteOption' value in NBO. |
176 | */ | 180 | */ |
177 | uint32_t reserved GNUNET_PACKED; | 181 | uint32_t options GNUNET_PACKED; |
178 | 182 | ||
179 | /** | 183 | /** |
180 | * Length of the PUT path that follows (if tracked). | 184 | * Length of the PUT path that follows (if tracked). |
@@ -196,10 +200,14 @@ struct PeerResultMessage | |||
196 | */ | 200 | */ |
197 | struct GNUNET_HashCode key; | 201 | struct GNUNET_HashCode key; |
198 | 202 | ||
203 | /* trunc_peer (if truncated) */ | ||
204 | |||
199 | /* put path (if tracked) */ | 205 | /* put path (if tracked) */ |
200 | 206 | ||
201 | /* get path (if tracked) */ | 207 | /* get path (if tracked) */ |
202 | 208 | ||
209 | /* sender_sig (if path tracking is on) */ | ||
210 | |||
203 | /* Payload */ | 211 | /* Payload */ |
204 | }; | 212 | }; |
205 | 213 | ||
@@ -537,10 +545,11 @@ sign_path (const void *data, | |||
537 | .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DHT_HOP), | 545 | .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DHT_HOP), |
538 | .purpose.size = htonl (sizeof (hs)), | 546 | .purpose.size = htonl (sizeof (hs)), |
539 | .expiration_time = GNUNET_TIME_absolute_hton (exp_time), | 547 | .expiration_time = GNUNET_TIME_absolute_hton (exp_time), |
540 | .pred = *pred, | ||
541 | .succ = *succ | 548 | .succ = *succ |
542 | }; | 549 | }; |
543 | 550 | ||
551 | if (NULL != pred) | ||
552 | hs.pred = *pred; | ||
544 | GNUNET_CRYPTO_hash (data, | 553 | GNUNET_CRYPTO_hash (data, |
545 | data_size, | 554 | data_size, |
546 | &hs.h_data); | 555 | &hs.h_data); |
@@ -1314,21 +1323,36 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd, | |||
1314 | struct PeerInfo **targets; | 1323 | struct PeerInfo **targets; |
1315 | size_t msize; | 1324 | size_t msize; |
1316 | unsigned int skip_count; | 1325 | unsigned int skip_count; |
1326 | enum GNUNET_DHT_RouteOption ro = bd->ro; | ||
1317 | unsigned int put_path_length = bd->put_path_length; | 1327 | unsigned int put_path_length = bd->put_path_length; |
1328 | const struct GNUNET_DHT_PathElement *put_path = bd->put_path; | ||
1329 | bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED)); | ||
1330 | bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE)); | ||
1331 | const struct GNUNET_PeerIdentity *trunc_peer | ||
1332 | = truncated | ||
1333 | ? &bd->trunc_peer | ||
1334 | : NULL; | ||
1318 | 1335 | ||
1319 | GNUNET_assert (NULL != bf); | ||
1320 | #if SANITY_CHECKS > 1 | 1336 | #if SANITY_CHECKS > 1 |
1321 | if (0 != | 1337 | unsigned int failure_offset; |
1322 | GNUNET_DHT_verify_path (bd->data, | 1338 | |
1339 | failure_offset | ||
1340 | = GNUNET_DHT_verify_path (bd->data, | ||
1323 | bd->data_size, | 1341 | bd->data_size, |
1324 | bd->expiration_time, | 1342 | bd->expiration_time, |
1325 | bd->put_path, | 1343 | trunc_peer, |
1326 | bd->put_path_length, | 1344 | put_path, |
1327 | NULL, 0, /* get_path */ | 1345 | put_path_length, |
1328 | &GDS_my_identity)) | 1346 | NULL, 0, /* get_path */ |
1347 | &GDS_my_identity); | ||
1348 | if (0 != failure_offset) | ||
1329 | { | 1349 | { |
1330 | GNUNET_break_op (0); | 1350 | GNUNET_break_op (0); |
1331 | put_path_length = 0; | 1351 | truncated = true; |
1352 | trunc_peer = &put_path[failure_offset - 1].pred; | ||
1353 | put_path = &put_path[failure_offset]; | ||
1354 | put_path_length = put_path_length - failure_offset; | ||
1355 | ro |= GNUNET_DHT_RO_TRUNCATED; | ||
1332 | } | 1356 | } |
1333 | #endif | 1357 | #endif |
1334 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1358 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1340,12 +1364,70 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd, | |||
1340 | 1364 | ||
1341 | /* if we got a HELLO, consider it for our own routing table */ | 1365 | /* if we got a HELLO, consider it for our own routing table */ |
1342 | hello_check (bd); | 1366 | hello_check (bd); |
1367 | GNUNET_assert (NULL != bf); | ||
1343 | GNUNET_CONTAINER_bloomfilter_add (bf, | 1368 | GNUNET_CONTAINER_bloomfilter_add (bf, |
1344 | &GDS_my_identity_hash); | 1369 | &GDS_my_identity_hash); |
1345 | GNUNET_STATISTICS_update (GDS_stats, | 1370 | GNUNET_STATISTICS_update (GDS_stats, |
1346 | "# PUT requests routed", | 1371 | "# PUT requests routed", |
1347 | 1, | 1372 | 1, |
1348 | GNUNET_NO); | 1373 | GNUNET_NO); |
1374 | if (bd->data_size | ||
1375 | > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE | ||
1376 | - sizeof(struct PeerPutMessage)) | ||
1377 | { | ||
1378 | GNUNET_break (0); | ||
1379 | return GNUNET_SYSERR; | ||
1380 | } | ||
1381 | msize = bd->data_size + sizeof(struct PeerPutMessage); | ||
1382 | if (tracking) | ||
1383 | { | ||
1384 | if (msize + sizeof (struct GNUNET_CRYPTO_EddsaSignature) | ||
1385 | > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) | ||
1386 | { | ||
1387 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1388 | "Discarding message that is too large due to tracking\n"); | ||
1389 | return GNUNET_NO; | ||
1390 | } | ||
1391 | msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature); | ||
1392 | } | ||
1393 | else | ||
1394 | { | ||
1395 | /* If tracking is disabled, also discard any path we might have | ||
1396 | gotten from some broken peer */ | ||
1397 | GNUNET_break_op (0 == put_path_length); | ||
1398 | put_path_length = 0; | ||
1399 | } | ||
1400 | if (truncated) | ||
1401 | msize += sizeof (struct GNUNET_PeerIdentity); | ||
1402 | if (msize + put_path_length * sizeof(struct GNUNET_DHT_PathElement) | ||
1403 | > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) | ||
1404 | { | ||
1405 | unsigned int mlen; | ||
1406 | unsigned int ppl; | ||
1407 | |||
1408 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1409 | "Truncating path that is too large due\n"); | ||
1410 | mlen = GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE - msize; | ||
1411 | if (! truncated) | ||
1412 | { | ||
1413 | /* We need extra space for the truncation, consider that, | ||
1414 | too! */ | ||
1415 | truncated = true; | ||
1416 | mlen -= sizeof (struct GNUNET_PeerIdentity); | ||
1417 | msize += sizeof (struct GNUNET_PeerIdentity); | ||
1418 | } | ||
1419 | /* compute maximum length of path we can keep */ | ||
1420 | ppl = mlen / sizeof (struct GNUNET_DHT_PathElement); | ||
1421 | GNUNET_assert (put_path_length - ppl > 0); | ||
1422 | trunc_peer = &put_path[put_path_length - ppl - 1].pred; | ||
1423 | put_path = &put_path[put_path_length - ppl]; | ||
1424 | put_path_length = ppl; | ||
1425 | ro |= GNUNET_DHT_RO_TRUNCATED; | ||
1426 | } | ||
1427 | else | ||
1428 | { | ||
1429 | msize += bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement); | ||
1430 | } | ||
1349 | target_count | 1431 | target_count |
1350 | = get_target_peers (&bd->key, | 1432 | = get_target_peers (&bd->key, |
1351 | bf, | 1433 | bf, |
@@ -1361,28 +1443,14 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd, | |||
1361 | GNUNET_i2s (&GDS_my_identity)); | 1443 | GNUNET_i2s (&GDS_my_identity)); |
1362 | return GNUNET_NO; | 1444 | return GNUNET_NO; |
1363 | } | 1445 | } |
1364 | msize = bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement) | ||
1365 | + bd->data_size; | ||
1366 | if (msize + sizeof(struct PeerPutMessage) | ||
1367 | >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) | ||
1368 | { | ||
1369 | put_path_length = 0; | ||
1370 | msize = bd->data_size; | ||
1371 | } | ||
1372 | if (msize + sizeof(struct PeerPutMessage) | ||
1373 | >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) | ||
1374 | { | ||
1375 | GNUNET_break (0); | ||
1376 | GNUNET_free (targets); | ||
1377 | return GNUNET_NO; | ||
1378 | } | ||
1379 | skip_count = 0; | 1446 | skip_count = 0; |
1380 | for (unsigned int i = 0; i < target_count; i++) | 1447 | for (unsigned int i = 0; i < target_count; i++) |
1381 | { | 1448 | { |
1382 | struct PeerInfo *target = targets[i]; | 1449 | struct PeerInfo *target = targets[i]; |
1383 | struct PeerPutMessage *ppm; | 1450 | struct PeerPutMessage *ppm; |
1384 | char buf[sizeof (*ppm) + msize] GNUNET_ALIGN; | 1451 | char buf[msize] GNUNET_ALIGN; |
1385 | struct GNUNET_DHT_PathElement *pp; | 1452 | struct GNUNET_DHT_PathElement *pp; |
1453 | void *data; | ||
1386 | 1454 | ||
1387 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1455 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1388 | "Routing PUT for %s after %u hops to %s\n", | 1456 | "Routing PUT for %s after %u hops to %s\n", |
@@ -1393,7 +1461,7 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd, | |||
1393 | ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT); | 1461 | ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT); |
1394 | ppm->header.size = htons (sizeof (buf)); | 1462 | ppm->header.size = htons (sizeof (buf)); |
1395 | ppm->type = htonl (bd->type); | 1463 | ppm->type = htonl (bd->type); |
1396 | ppm->options = htons (bd->ro); | 1464 | ppm->options = htons (ro); |
1397 | ppm->hop_count = htons (hop_count + 1); | 1465 | ppm->hop_count = htons (hop_count + 1); |
1398 | ppm->desired_replication_level = htons (desired_replication_level); | 1466 | ppm->desired_replication_level = htons (desired_replication_level); |
1399 | ppm->put_path_length = htons (put_path_length); | 1467 | ppm->put_path_length = htons (put_path_length); |
@@ -1406,28 +1474,62 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd, | |||
1406 | ppm->bloomfilter, | 1474 | ppm->bloomfilter, |
1407 | DHT_BLOOM_SIZE)); | 1475 | DHT_BLOOM_SIZE)); |
1408 | ppm->key = bd->key; | 1476 | ppm->key = bd->key; |
1409 | pp = (struct GNUNET_DHT_PathElement *) &ppm[1]; | 1477 | if (truncated) |
1478 | { | ||
1479 | void *tgt = &ppm[1]; | ||
1480 | |||
1481 | GNUNET_memcpy (tgt, | ||
1482 | trunc_peer, | ||
1483 | sizeof (struct GNUNET_PeerIdentity)); | ||
1484 | pp = (struct GNUNET_DHT_PathElement *) | ||
1485 | (tgt + sizeof (struct GNUNET_PeerIdentity)); | ||
1486 | } | ||
1487 | else | ||
1488 | { | ||
1489 | pp = (struct GNUNET_DHT_PathElement *) &ppm[1]; | ||
1490 | } | ||
1410 | GNUNET_memcpy (pp, | 1491 | GNUNET_memcpy (pp, |
1411 | bd->put_path, | 1492 | put_path, |
1412 | sizeof (struct GNUNET_DHT_PathElement) * put_path_length); | 1493 | sizeof (struct GNUNET_DHT_PathElement) * put_path_length); |
1413 | /* 0 == put_path_length means path is not being tracked */ | 1494 | if (tracking) |
1414 | if (0 != put_path_length) | ||
1415 | { | 1495 | { |
1416 | /* Note that the signature in 'put_path' was not initialized before, | 1496 | void *tgt = &pp[put_path_length]; |
1417 | so this is crucial to avoid sending garbage. */ | 1497 | struct GNUNET_CRYPTO_EddsaSignature last_sig; |
1418 | sign_path (bd->data, | 1498 | |
1419 | bd->data_size, | 1499 | if (0 == put_path_length) |
1420 | bd->expiration_time, | 1500 | { |
1421 | &pp[put_path_length - 1].pred, | 1501 | /* Note that the signature in 'put_path' was not initialized before, |
1422 | &target->id, | 1502 | so this is crucial to avoid sending garbage. */ |
1423 | &pp[put_path_length - 1].sig); | 1503 | sign_path (bd->data, |
1504 | bd->data_size, | ||
1505 | bd->expiration_time, | ||
1506 | trunc_peer, | ||
1507 | &target->id, | ||
1508 | &last_sig); | ||
1509 | } | ||
1510 | else | ||
1511 | { | ||
1512 | sign_path (bd->data, | ||
1513 | bd->data_size, | ||
1514 | bd->expiration_time, | ||
1515 | &pp[put_path_length - 1].pred, | ||
1516 | &target->id, | ||
1517 | &last_sig); | ||
1518 | } | ||
1424 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1519 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1425 | "Signing PUT PATH %u => %s\n", | 1520 | "Signing PUT PATH %u => %s\n", |
1426 | put_path_length, | 1521 | put_path_length, |
1427 | GNUNET_B2S (&pp[put_path_length - 1].sig)); | 1522 | GNUNET_B2S (&last_sig)); |
1523 | memcpy (tgt, | ||
1524 | &last_sig, | ||
1525 | sizeof (last_sig)); | ||
1526 | data = tgt + sizeof (last_sig); | ||
1428 | } | 1527 | } |
1429 | 1528 | else /* ! tracking */ | |
1430 | GNUNET_memcpy (&pp[put_path_length], | 1529 | { |
1530 | data = &ppm[1]; | ||
1531 | } | ||
1532 | GNUNET_memcpy (data, | ||
1431 | bd->data, | 1533 | bd->data, |
1432 | bd->data_size); | 1534 | bd->data_size); |
1433 | do_send (target, | 1535 | do_send (target, |
@@ -1572,46 +1674,86 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi, | |||
1572 | struct GNUNET_DHT_PathElement *paths; | 1674 | struct GNUNET_DHT_PathElement *paths; |
1573 | size_t msize; | 1675 | size_t msize; |
1574 | unsigned int ppl = bd->put_path_length; | 1676 | unsigned int ppl = bd->put_path_length; |
1575 | 1677 | const struct GNUNET_DHT_PathElement *put_path = bd->put_path; | |
1678 | enum GNUNET_DHT_RouteOption ro = bd->ro; | ||
1679 | bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED)); | ||
1680 | const struct GNUNET_PeerIdentity *trunc_peer | ||
1681 | = truncated | ||
1682 | ? &bd->trunc_peer | ||
1683 | : NULL; | ||
1684 | bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE)); | ||
1576 | #if SANITY_CHECKS > 1 | 1685 | #if SANITY_CHECKS > 1 |
1577 | if (0 != | 1686 | unsigned int failure_offset; |
1578 | GNUNET_DHT_verify_path (bd->data, | 1687 | |
1688 | failure_offset | ||
1689 | = GNUNET_DHT_verify_path (bd->data, | ||
1579 | bd->data_size, | 1690 | bd->data_size, |
1580 | bd->expiration_time, | 1691 | bd->expiration_time, |
1581 | bd->put_path, | 1692 | trunc_peer, |
1582 | bd->put_path_length, | 1693 | put_path, |
1694 | ppl, | ||
1583 | get_path, | 1695 | get_path, |
1584 | get_path_length, | 1696 | get_path_length, |
1585 | &GDS_my_identity)) | 1697 | &GDS_my_identity); |
1698 | if (0 != failure_offset) | ||
1586 | { | 1699 | { |
1700 | GNUNET_assert (failure_offset <= ppl + get_path_length); | ||
1587 | GNUNET_break_op (0); | 1701 | GNUNET_break_op (0); |
1588 | return false; | 1702 | if (failure_offset < ppl) |
1703 | { | ||
1704 | trunc_peer = &put_path[failure_offset - 1].pred; | ||
1705 | put_path += failure_offset; | ||
1706 | ppl -= failure_offset; | ||
1707 | truncated = true; | ||
1708 | ro |= GNUNET_DHT_RO_TRUNCATED; | ||
1709 | } | ||
1710 | else | ||
1711 | { | ||
1712 | failure_offset -= ppl; | ||
1713 | if (0 == failure_offset) | ||
1714 | trunc_peer = &put_path[ppl - 1].pred; | ||
1715 | else | ||
1716 | trunc_peer = &get_path[failure_offset - 1].pred; | ||
1717 | ppl = 0; | ||
1718 | put_path = NULL; | ||
1719 | truncated = true; | ||
1720 | ro |= GNUNET_DHT_RO_TRUNCATED; | ||
1721 | get_path += failure_offset; | ||
1722 | get_path_length -= failure_offset; | ||
1723 | } | ||
1589 | } | 1724 | } |
1590 | #endif | 1725 | #endif |
1591 | msize = bd->data_size + (get_path_length + ppl) | 1726 | msize = bd->data_size + sizeof (struct PeerResultMessage); |
1592 | * sizeof(struct GNUNET_DHT_PathElement); | 1727 | if (msize > GNUNET_MAX_MESSAGE_SIZE) |
1593 | if ( (msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) || | 1728 | { |
1594 | (get_path_length > | 1729 | GNUNET_break_op (0); |
1595 | GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) || | 1730 | return false; |
1596 | (ppl > | 1731 | } |
1597 | GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) || | 1732 | if (truncated) |
1598 | (bd->data_size > GNUNET_MAX_MESSAGE_SIZE)) | 1733 | msize += sizeof (struct GNUNET_PeerIdentity); |
1734 | if (tracking) | ||
1735 | msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature); | ||
1736 | if (msize < bd->data_size) | ||
1737 | { | ||
1738 | GNUNET_break_op (0); | ||
1739 | return false; | ||
1740 | } | ||
1741 | if ( (GNUNET_MAX_MESSAGE_SIZE - msize) | ||
1742 | / sizeof(struct GNUNET_DHT_PathElement) | ||
1743 | < (get_path_length + ppl) ) | ||
1599 | { | 1744 | { |
1600 | ppl = 0; | ||
1601 | get_path_length = 0; | 1745 | get_path_length = 0; |
1602 | msize = bd->data_size + (get_path_length + ppl) | 1746 | ppl = 0; |
1603 | * sizeof(struct GNUNET_DHT_PathElement); | ||
1604 | } | 1747 | } |
1605 | if ( (msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) || | 1748 | if ( (get_path_length > UINT16_MAX) || |
1606 | (get_path_length > | 1749 | (ppl > UINT16_MAX) ) |
1607 | GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) || | ||
1608 | (ppl > | ||
1609 | GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) || | ||
1610 | (bd->data_size > GNUNET_MAX_MESSAGE_SIZE)) | ||
1611 | { | 1750 | { |
1612 | GNUNET_break (0); | 1751 | GNUNET_break (0); |
1613 | return false; | 1752 | get_path_length = 0; |
1753 | ppl = 0; | ||
1614 | } | 1754 | } |
1755 | msize += (get_path_length + ppl) | ||
1756 | * sizeof(struct GNUNET_DHT_PathElement); | ||
1615 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1757 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1616 | "Forwarding reply for key %s to peer %s\n", | 1758 | "Forwarding reply for key %s to peer %s\n", |
1617 | GNUNET_h2s (query_hash), | 1759 | GNUNET_h2s (query_hash), |
@@ -1622,22 +1764,36 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi, | |||
1622 | GNUNET_NO); | 1764 | GNUNET_NO); |
1623 | { | 1765 | { |
1624 | struct PeerResultMessage *prm; | 1766 | struct PeerResultMessage *prm; |
1625 | char buf[sizeof (*prm) + msize] GNUNET_ALIGN; | 1767 | char buf[msize] GNUNET_ALIGN; |
1768 | void *data; | ||
1626 | 1769 | ||
1627 | prm = (struct PeerResultMessage *) buf; | 1770 | prm = (struct PeerResultMessage *) buf; |
1628 | prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT); | 1771 | prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT); |
1629 | prm->header.size = htons (sizeof (buf)); | 1772 | prm->header.size = htons (sizeof (buf)); |
1630 | prm->type = htonl (bd->type); | 1773 | prm->type = htonl ((uint32_t) bd->type); |
1631 | prm->reserved = htonl (0); | 1774 | prm->options = htonl ((uint32_t) ro); |
1632 | prm->put_path_length = htons (ppl); | 1775 | prm->put_path_length = htons ((uint16_t) ppl); |
1633 | prm->get_path_length = htons (get_path_length); | 1776 | prm->get_path_length = htons ((uint16_t) get_path_length); |
1634 | prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time); | 1777 | prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time); |
1635 | prm->key = *query_hash; | 1778 | prm->key = *query_hash; |
1636 | paths = (struct GNUNET_DHT_PathElement *) &prm[1]; | 1779 | if (truncated) |
1637 | if (NULL != bd->put_path) | 1780 | { |
1781 | void *tgt = &prm[1]; | ||
1782 | |||
1783 | GNUNET_memcpy (tgt, | ||
1784 | trunc_peer, | ||
1785 | sizeof (struct GNUNET_PeerIdentity)); | ||
1786 | paths = (struct GNUNET_DHT_PathElement *) | ||
1787 | (tgt + sizeof (struct GNUNET_PeerIdentity)); | ||
1788 | } | ||
1789 | else | ||
1790 | { | ||
1791 | paths = (struct GNUNET_DHT_PathElement *) &prm[1]; | ||
1792 | } | ||
1793 | if (NULL != put_path) | ||
1638 | { | 1794 | { |
1639 | GNUNET_memcpy (paths, | 1795 | GNUNET_memcpy (paths, |
1640 | bd->put_path, | 1796 | put_path, |
1641 | ppl * sizeof(struct GNUNET_DHT_PathElement)); | 1797 | ppl * sizeof(struct GNUNET_DHT_PathElement)); |
1642 | } | 1798 | } |
1643 | else | 1799 | else |
@@ -1654,51 +1810,69 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi, | |||
1654 | { | 1810 | { |
1655 | GNUNET_assert (0 == get_path_length); | 1811 | GNUNET_assert (0 == get_path_length); |
1656 | } | 1812 | } |
1657 | /* 0 == get_path_length+ppl means path is not being tracked */ | 1813 | if (tracking) |
1658 | if (0 != (get_path_length + ppl)) | ||
1659 | { | 1814 | { |
1815 | struct GNUNET_CRYPTO_EddsaSignature sig; | ||
1816 | void *tgt = &paths[get_path_length + ppl]; | ||
1817 | const struct GNUNET_PeerIdentity *pred; | ||
1818 | |||
1819 | if (ppl + get_path_length > 0) | ||
1820 | pred = &paths[ppl + get_path_length - 1].pred; | ||
1821 | else if (truncated) | ||
1822 | pred = trunc_peer; | ||
1823 | else | ||
1824 | pred = NULL; /* we are first! */ | ||
1660 | /* Note that the last signature in 'paths' was not initialized before, | 1825 | /* Note that the last signature in 'paths' was not initialized before, |
1661 | so this is crucial to avoid sending garbage. */ | 1826 | so this is crucial to avoid sending garbage. */ |
1662 | sign_path (bd->data, | 1827 | sign_path (bd->data, |
1663 | bd->data_size, | 1828 | bd->data_size, |
1664 | bd->expiration_time, | 1829 | bd->expiration_time, |
1665 | &paths[ppl + get_path_length - 1].pred, | 1830 | pred, |
1666 | &pi->id, | 1831 | &pi->id, |
1667 | &paths[ppl + get_path_length - 1].sig); | 1832 | &sig); |
1833 | memcpy (tgt, | ||
1834 | &sig, | ||
1835 | sizeof (sig)); | ||
1836 | data = tgt + sizeof (sig); | ||
1668 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1837 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1669 | "Signing GET PATH %u/%u of %s => %s\n", | 1838 | "Signing GET PATH %u/%u of %s => %s\n", |
1670 | ppl, | 1839 | ppl, |
1671 | get_path_length, | 1840 | get_path_length, |
1672 | GNUNET_h2s (query_hash), | 1841 | GNUNET_h2s (query_hash), |
1673 | GNUNET_B2S (&paths[ppl + get_path_length - 1].sig)); | 1842 | GNUNET_B2S (&sig)); |
1674 | } | ||
1675 | GNUNET_memcpy (&paths[ppl + get_path_length], | ||
1676 | bd->data, | ||
1677 | bd->data_size); | ||
1678 | |||
1679 | #if SANITY_CHECKS > 1 | 1843 | #if SANITY_CHECKS > 1 |
1680 | { | ||
1681 | struct GNUNET_DHT_PathElement xpaths[get_path_length + 1]; | ||
1682 | |||
1683 | memcpy (xpaths, | ||
1684 | &paths[ppl], | ||
1685 | get_path_length * sizeof (struct GNUNET_DHT_PathElement)); | ||
1686 | xpaths[get_path_length].pred = GDS_my_identity; | ||
1687 | if (0 != | ||
1688 | GNUNET_DHT_verify_path (bd->data, | ||
1689 | bd->data_size, | ||
1690 | bd->expiration_time, | ||
1691 | paths, | ||
1692 | ppl, | ||
1693 | xpaths, | ||
1694 | get_path_length + 1, | ||
1695 | &pi->id)) | ||
1696 | { | 1844 | { |
1697 | GNUNET_break (0); | 1845 | struct GNUNET_DHT_PathElement xpaths[get_path_length + 1]; |
1698 | return false; | 1846 | |
1847 | memcpy (xpaths, | ||
1848 | &paths[ppl], | ||
1849 | get_path_length * sizeof (struct GNUNET_DHT_PathElement)); | ||
1850 | xpaths[get_path_length].sig = sig; | ||
1851 | xpaths[get_path_length].pred = GDS_my_identity; | ||
1852 | if (0 != | ||
1853 | GNUNET_DHT_verify_path (bd->data, | ||
1854 | bd->data_size, | ||
1855 | bd->expiration_time, | ||
1856 | trunc_peer, | ||
1857 | paths, | ||
1858 | ppl, | ||
1859 | xpaths, | ||
1860 | get_path_length + 1, | ||
1861 | &pi->id)) | ||
1862 | { | ||
1863 | GNUNET_break (0); | ||
1864 | return false; | ||
1865 | } | ||
1699 | } | 1866 | } |
1700 | } | ||
1701 | #endif | 1867 | #endif |
1868 | } | ||
1869 | else | ||
1870 | { | ||
1871 | data = &prm[1]; | ||
1872 | } | ||
1873 | GNUNET_memcpy (data, | ||
1874 | bd->data, | ||
1875 | bd->data_size); | ||
1702 | do_send (pi, | 1876 | do_send (pi, |
1703 | &prm->header); | 1877 | &prm->header); |
1704 | } | 1878 | } |
@@ -1717,15 +1891,30 @@ static enum GNUNET_GenericReturnValue | |||
1717 | check_dht_p2p_put (void *cls, | 1891 | check_dht_p2p_put (void *cls, |
1718 | const struct PeerPutMessage *put) | 1892 | const struct PeerPutMessage *put) |
1719 | { | 1893 | { |
1894 | enum GNUNET_DHT_RouteOption ro | ||
1895 | = (enum GNUNET_DHT_RouteOption) ntohs (put->options); | ||
1896 | bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED)); | ||
1897 | bool has_path = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE)); | ||
1720 | uint16_t msize = ntohs (put->header.size); | 1898 | uint16_t msize = ntohs (put->header.size); |
1721 | uint16_t putlen = ntohs (put->put_path_length); | 1899 | uint16_t putlen = ntohs (put->put_path_length); |
1900 | size_t xsize = (has_path | ||
1901 | ? sizeof (struct GNUNET_CRYPTO_EddsaSignature) | ||
1902 | : 0) | ||
1903 | + (truncated | ||
1904 | ? sizeof (struct GNUNET_PeerIdentity) | ||
1905 | : 0); | ||
1906 | size_t var_meta_size | ||
1907 | = putlen * sizeof(struct GNUNET_DHT_PathElement) | ||
1908 | + xsize; | ||
1722 | 1909 | ||
1723 | (void) cls; | 1910 | (void) cls; |
1724 | if ( (msize < | 1911 | if ( (msize < |
1725 | sizeof(struct PeerPutMessage) | 1912 | sizeof (struct PeerPutMessage) + var_meta_size) || |
1726 | + putlen * sizeof(struct GNUNET_DHT_PathElement)) || | ||
1727 | (putlen > | 1913 | (putlen > |
1728 | GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) ) | 1914 | (GNUNET_MAX_MESSAGE_SIZE |
1915 | - sizeof (struct PeerPutMessage) | ||
1916 | - xsize) | ||
1917 | / sizeof(struct GNUNET_DHT_PathElement)) ) | ||
1729 | { | 1918 | { |
1730 | GNUNET_break_op (0); | 1919 | GNUNET_break_op (0); |
1731 | return GNUNET_SYSERR; | 1920 | return GNUNET_SYSERR; |
@@ -1746,27 +1935,49 @@ handle_dht_p2p_put (void *cls, | |||
1746 | { | 1935 | { |
1747 | struct Target *t = cls; | 1936 | struct Target *t = cls; |
1748 | struct PeerInfo *peer = t->pi; | 1937 | struct PeerInfo *peer = t->pi; |
1938 | enum GNUNET_DHT_RouteOption ro | ||
1939 | = (enum GNUNET_DHT_RouteOption) ntohs (put->options); | ||
1940 | bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED)); | ||
1941 | bool has_path = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE)); | ||
1749 | uint16_t msize = ntohs (put->header.size); | 1942 | uint16_t msize = ntohs (put->header.size); |
1943 | uint16_t putlen = ntohs (put->put_path_length); | ||
1944 | const struct GNUNET_PeerIdentity *trunc_peer | ||
1945 | = truncated | ||
1946 | ? (const struct GNUNET_PeerIdentity *) &put[1] | ||
1947 | : NULL; | ||
1750 | const struct GNUNET_DHT_PathElement *put_path | 1948 | const struct GNUNET_DHT_PathElement *put_path |
1751 | = (const struct GNUNET_DHT_PathElement *) &put[1]; | 1949 | = truncated |
1752 | uint16_t putlen | 1950 | ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1] |
1753 | = ntohs (put->put_path_length); | 1951 | : (const struct GNUNET_DHT_PathElement *) &put[1]; |
1952 | const struct GNUNET_CRYPTO_EddsaSignature *last_sig | ||
1953 | = has_path | ||
1954 | ? (const struct GNUNET_CRYPTO_EddsaSignature *) &put_path[putlen] | ||
1955 | : NULL; | ||
1956 | const char *data | ||
1957 | = has_path | ||
1958 | ? (const char *) &last_sig[1] | ||
1959 | : (const char *) &put_path[putlen]; | ||
1960 | size_t var_meta_size | ||
1961 | = putlen * sizeof(struct GNUNET_DHT_PathElement) | ||
1962 | + has_path ? sizeof (*last_sig) : 0 | ||
1963 | + truncated ? sizeof (*trunc_peer) : 0; | ||
1754 | struct GNUNET_DATACACHE_Block bd = { | 1964 | struct GNUNET_DATACACHE_Block bd = { |
1755 | .key = put->key, | 1965 | .key = put->key, |
1756 | .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time), | 1966 | .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time), |
1757 | .type = ntohl (put->type), | 1967 | .type = ntohl (put->type), |
1758 | .ro = (enum GNUNET_DHT_RouteOption) ntohs (put->options), | 1968 | .ro = ro, |
1759 | .data_size = msize - (sizeof(*put) | 1969 | .data_size = msize - sizeof(*put) - var_meta_size, |
1760 | + putlen * sizeof(struct GNUNET_DHT_PathElement)), | 1970 | .data = data |
1761 | .data = &put_path[putlen] | ||
1762 | }; | 1971 | }; |
1763 | 1972 | ||
1973 | if (NULL != trunc_peer) | ||
1974 | bd.trunc_peer = *trunc_peer; | ||
1764 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1975 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1765 | "PUT for `%s' from %s with RO (%s/%s)\n", | 1976 | "PUT for `%s' from %s with RO (%s/%s)\n", |
1766 | GNUNET_h2s (&put->key), | 1977 | GNUNET_h2s (&put->key), |
1767 | GNUNET_i2s (&peer->id), | 1978 | GNUNET_i2s (&peer->id), |
1768 | (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-", | 1979 | (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-", |
1769 | (bd.ro & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-"); | 1980 | has_path ? "R" : "-"); |
1770 | if (GNUNET_TIME_absolute_is_past (bd.expiration_time)) | 1981 | if (GNUNET_TIME_absolute_is_past (bd.expiration_time)) |
1771 | { | 1982 | { |
1772 | GNUNET_STATISTICS_update (GDS_stats, | 1983 | GNUNET_STATISTICS_update (GDS_stats, |
@@ -1784,7 +1995,7 @@ handle_dht_p2p_put (void *cls, | |||
1784 | GNUNET_break_op (0); | 1995 | GNUNET_break_op (0); |
1785 | return; | 1996 | return; |
1786 | } | 1997 | } |
1787 | if (0 == (bd.ro & GNUNET_DHT_RO_RECORD_ROUTE)) | 1998 | if (! has_path) |
1788 | putlen = 0; | 1999 | putlen = 0; |
1789 | GNUNET_STATISTICS_update (GDS_stats, | 2000 | GNUNET_STATISTICS_update (GDS_stats, |
1790 | "# P2P PUT requests received", | 2001 | "# P2P PUT requests received", |
@@ -1835,7 +2046,7 @@ handle_dht_p2p_put (void *cls, | |||
1835 | /* extend 'put path' by sender */ | 2046 | /* extend 'put path' by sender */ |
1836 | bd.put_path = (const struct GNUNET_DHT_PathElement *) pp; | 2047 | bd.put_path = (const struct GNUNET_DHT_PathElement *) pp; |
1837 | bd.put_path_length = putlen + 1; | 2048 | bd.put_path_length = putlen + 1; |
1838 | if (0 != (bd.ro & GNUNET_DHT_RO_RECORD_ROUTE)) | 2049 | if (has_path) |
1839 | { | 2050 | { |
1840 | unsigned int failure_offset; | 2051 | unsigned int failure_offset; |
1841 | 2052 | ||
@@ -1843,10 +2054,7 @@ handle_dht_p2p_put (void *cls, | |||
1843 | put_path, | 2054 | put_path, |
1844 | putlen * sizeof(struct GNUNET_DHT_PathElement)); | 2055 | putlen * sizeof(struct GNUNET_DHT_PathElement)); |
1845 | pp[putlen].pred = peer->id; | 2056 | pp[putlen].pred = peer->id; |
1846 | /* zero-out signature, not valid until we actually do forward! */ | 2057 | pp[putlen].sig = *last_sig; |
1847 | memset (&pp[putlen].sig, | ||
1848 | 0, | ||
1849 | sizeof (pp[putlen].sig)); | ||
1850 | #if SANITY_CHECKS | 2058 | #if SANITY_CHECKS |
1851 | /* TODO: might want to eventually implement probabilistic | 2059 | /* TODO: might want to eventually implement probabilistic |
1852 | load-based path verification, but for now it is all or nothing */ | 2060 | load-based path verification, but for now it is all or nothing */ |
@@ -1854,6 +2062,7 @@ handle_dht_p2p_put (void *cls, | |||
1854 | = GNUNET_DHT_verify_path (bd.data, | 2062 | = GNUNET_DHT_verify_path (bd.data, |
1855 | bd.data_size, | 2063 | bd.data_size, |
1856 | bd.expiration_time, | 2064 | bd.expiration_time, |
2065 | trunc_peer, | ||
1857 | pp, | 2066 | pp, |
1858 | putlen + 1, | 2067 | putlen + 1, |
1859 | NULL, 0, /* get_path */ | 2068 | NULL, 0, /* get_path */ |
@@ -1863,12 +2072,15 @@ handle_dht_p2p_put (void *cls, | |||
1863 | #endif | 2072 | #endif |
1864 | if (0 != failure_offset) | 2073 | if (0 != failure_offset) |
1865 | { | 2074 | { |
2075 | GNUNET_break_op (0); | ||
1866 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 2076 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
1867 | "Recorded put path invalid at offset %u, truncating\n", | 2077 | "Recorded put path invalid at offset %u, truncating\n", |
1868 | failure_offset); | 2078 | failure_offset); |
1869 | GNUNET_assert (failure_offset <= putlen); | 2079 | GNUNET_assert (failure_offset <= putlen + 1); |
1870 | bd.put_path = &pp[failure_offset]; | 2080 | bd.put_path = &pp[failure_offset]; |
1871 | bd.put_path_length = putlen - failure_offset; | 2081 | bd.put_path_length = putlen - failure_offset; |
2082 | bd.ro |= GNUNET_DHT_RO_TRUNCATED; | ||
2083 | bd.trunc_peer = pp[failure_offset - 1].pred; | ||
1872 | } | 2084 | } |
1873 | } | 2085 | } |
1874 | else | 2086 | else |
@@ -2218,8 +2430,6 @@ handle_dht_p2p_get (void *cls, | |||
2218 | type, | 2430 | type, |
2219 | hop_count, | 2431 | hop_count, |
2220 | desired_replication_level, | 2432 | desired_replication_level, |
2221 | 0, | ||
2222 | NULL, | ||
2223 | &get->key); | 2433 | &get->key); |
2224 | } | 2434 | } |
2225 | /* clean up; note that 'bg' is owned by routing now! */ | 2435 | /* clean up; note that 'bg' is owned by routing now! */ |
@@ -2326,17 +2536,44 @@ handle_dht_p2p_result (void *cls, | |||
2326 | { | 2536 | { |
2327 | struct Target *t = cls; | 2537 | struct Target *t = cls; |
2328 | struct PeerInfo *peer = t->pi; | 2538 | struct PeerInfo *peer = t->pi; |
2329 | uint16_t msize = ntohs (prm->header.size); | 2539 | uint16_t msize = ntohs (prm->header.size) - sizeof (*prm); |
2540 | enum GNUNET_DHT_RouteOption ro | ||
2541 | = (enum GNUNET_DHT_RouteOption) ntohl (prm->options); | ||
2542 | bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED)); | ||
2543 | bool tracked = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE)); | ||
2330 | uint16_t get_path_length = ntohs (prm->get_path_length); | 2544 | uint16_t get_path_length = ntohs (prm->get_path_length); |
2545 | uint16_t put_path_length = ntohs (prm->put_path_length); | ||
2546 | const struct GNUNET_PeerIdentity *trunc_peer | ||
2547 | = truncated | ||
2548 | ? (const struct GNUNET_PeerIdentity *) &prm[1] | ||
2549 | : NULL; | ||
2550 | const struct GNUNET_DHT_PathElement *put_path | ||
2551 | = truncated | ||
2552 | ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1] | ||
2553 | : (const struct GNUNET_DHT_PathElement *) &prm[1]; | ||
2554 | const struct GNUNET_DHT_PathElement *get_path | ||
2555 | = &put_path[put_path_length]; | ||
2556 | const struct GNUNET_CRYPTO_EddsaSignature *last_sig | ||
2557 | = tracked | ||
2558 | ? (const struct GNUNET_CRYPTO_EddsaSignature *) &get_path[get_path_length] | ||
2559 | : NULL; | ||
2560 | const void *data | ||
2561 | = tracked | ||
2562 | ? (const void *) &last_sig[1] | ||
2563 | : (const void *) &get_path[get_path_length]; | ||
2564 | size_t vsize = (truncated ? sizeof (struct GNUNET_PeerIdentity) : 0) | ||
2565 | + (tracked ? sizeof (struct GNUNET_CRYPTO_EddsaSignature) : 0); | ||
2331 | struct GNUNET_DATACACHE_Block bd = { | 2566 | struct GNUNET_DATACACHE_Block bd = { |
2332 | .expiration_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time), | 2567 | .expiration_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time), |
2333 | .put_path = (const struct GNUNET_DHT_PathElement *) &prm[1], | 2568 | .put_path = put_path, |
2334 | .put_path_length = ntohs (prm->put_path_length), | 2569 | .put_path_length = put_path_length, |
2335 | .key = prm->key, | 2570 | .key = prm->key, |
2336 | .type = ntohl (prm->type) | 2571 | .type = ntohl (prm->type), |
2572 | .ro = ro, | ||
2573 | .data = data, | ||
2574 | .data_size = msize - vsize - (get_path_length + put_path_length) | ||
2575 | * sizeof(struct GNUNET_DHT_PathElement) | ||
2337 | }; | 2576 | }; |
2338 | const struct GNUNET_DHT_PathElement *get_path | ||
2339 | = &bd.put_path[bd.put_path_length]; | ||
2340 | 2577 | ||
2341 | /* parse and validate message */ | 2578 | /* parse and validate message */ |
2342 | if (GNUNET_TIME_absolute_is_past (bd.expiration_time)) | 2579 | if (GNUNET_TIME_absolute_is_past (bd.expiration_time)) |
@@ -2347,11 +2584,6 @@ handle_dht_p2p_result (void *cls, | |||
2347 | GNUNET_NO); | 2584 | GNUNET_NO); |
2348 | return; | 2585 | return; |
2349 | } | 2586 | } |
2350 | get_path = &bd.put_path[bd.put_path_length]; | ||
2351 | bd.data = (const void *) &get_path[get_path_length]; | ||
2352 | bd.data_size = msize - (sizeof(struct PeerResultMessage) | ||
2353 | + (get_path_length + bd.put_path_length) | ||
2354 | * sizeof(struct GNUNET_DHT_PathElement)); | ||
2355 | if (GNUNET_OK != | 2587 | if (GNUNET_OK != |
2356 | GNUNET_BLOCK_check_block (GDS_block_context, | 2588 | GNUNET_BLOCK_check_block (GDS_block_context, |
2357 | bd.type, | 2589 | bd.type, |
@@ -2385,6 +2617,7 @@ handle_dht_p2p_result (void *cls, | |||
2385 | hello_check (&bd); | 2617 | hello_check (&bd); |
2386 | 2618 | ||
2387 | /* Need to append 'peer' to 'get_path' */ | 2619 | /* Need to append 'peer' to 'get_path' */ |
2620 | if (tracked) | ||
2388 | { | 2621 | { |
2389 | struct GNUNET_DHT_PathElement xget_path[get_path_length + 1]; | 2622 | struct GNUNET_DHT_PathElement xget_path[get_path_length + 1]; |
2390 | struct GNUNET_DHT_PathElement *gp = xget_path; | 2623 | struct GNUNET_DHT_PathElement *gp = xget_path; |
@@ -2394,9 +2627,10 @@ handle_dht_p2p_result (void *cls, | |||
2394 | get_path, | 2627 | get_path, |
2395 | get_path_length * sizeof(struct GNUNET_DHT_PathElement)); | 2628 | get_path_length * sizeof(struct GNUNET_DHT_PathElement)); |
2396 | xget_path[get_path_length].pred = peer->id; | 2629 | xget_path[get_path_length].pred = peer->id; |
2397 | memset (&xget_path[get_path_length].sig, | 2630 | /* use memcpy(), as last_sig may not be aligned */ |
2398 | 0, | 2631 | memcpy (&xget_path[get_path_length].sig, |
2399 | sizeof (xget_path[get_path_length].sig)); | 2632 | last_sig, |
2633 | sizeof (*last_sig)); | ||
2400 | #if SANITY_CHECKS | 2634 | #if SANITY_CHECKS |
2401 | /* TODO: might want to eventually implement probabilistic | 2635 | /* TODO: might want to eventually implement probabilistic |
2402 | load-based path verification, but for now it is all or nothing */ | 2636 | load-based path verification, but for now it is all or nothing */ |
@@ -2404,9 +2638,10 @@ handle_dht_p2p_result (void *cls, | |||
2404 | = GNUNET_DHT_verify_path (bd.data, | 2638 | = GNUNET_DHT_verify_path (bd.data, |
2405 | bd.data_size, | 2639 | bd.data_size, |
2406 | bd.expiration_time, | 2640 | bd.expiration_time, |
2407 | bd.put_path, | 2641 | trunc_peer, |
2408 | bd.put_path_length, | 2642 | put_path, |
2409 | xget_path, | 2643 | put_path_length, |
2644 | gp, | ||
2410 | get_path_length + 1, | 2645 | get_path_length + 1, |
2411 | &GDS_my_identity); | 2646 | &GDS_my_identity); |
2412 | #else | 2647 | #else |
@@ -2417,30 +2652,59 @@ handle_dht_p2p_result (void *cls, | |||
2417 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 2652 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
2418 | "Recorded path invalid at offset %u, truncating\n", | 2653 | "Recorded path invalid at offset %u, truncating\n", |
2419 | failure_offset); | 2654 | failure_offset); |
2420 | GNUNET_assert (failure_offset <= bd.put_path_length + get_path_length); | 2655 | GNUNET_assert (failure_offset <= bd.put_path_length + get_path_length |
2421 | if (failure_offset >= bd.put_path_length) | 2656 | + 1); |
2422 | { | 2657 | if (failure_offset < bd.put_path_length) |
2423 | /* failure on get path */ | ||
2424 | get_path_length -= (failure_offset - bd.put_path_length); | ||
2425 | gp = &xget_path[failure_offset - bd.put_path_length]; | ||
2426 | bd.put_path_length = 0; | ||
2427 | } | ||
2428 | else | ||
2429 | { | 2658 | { |
2430 | /* failure on put path */ | 2659 | /* failure on put path */ |
2660 | trunc_peer = &bd.put_path[failure_offset - 1].pred; | ||
2661 | bd.ro |= GNUNET_DHT_RO_TRUNCATED; | ||
2431 | bd.put_path = &bd.put_path[failure_offset]; | 2662 | bd.put_path = &bd.put_path[failure_offset]; |
2432 | bd.put_path_length -= failure_offset; | 2663 | bd.put_path_length -= failure_offset; |
2664 | truncated = true; | ||
2665 | } | ||
2666 | else | ||
2667 | { | ||
2668 | /* failure on get path */ | ||
2669 | failure_offset -= bd.put_path_length; | ||
2670 | if (0 == failure_offset) | ||
2671 | trunc_peer = &bd.put_path[bd.put_path_length - 1].pred; | ||
2672 | else | ||
2673 | trunc_peer = &gp[failure_offset - 1].pred; | ||
2674 | get_path_length -= failure_offset; | ||
2675 | gp = &gp[failure_offset]; | ||
2676 | bd.put_path_length = 0; | ||
2677 | bd.put_path = NULL; | ||
2678 | bd.ro |= GNUNET_DHT_RO_TRUNCATED; | ||
2679 | truncated = true; | ||
2433 | } | 2680 | } |
2434 | } | 2681 | } |
2435 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2682 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2436 | "Extending GET path of length %u with %s\n", | 2683 | "Extending GET path of length %u with %s\n", |
2437 | get_path_length, | 2684 | get_path_length, |
2438 | GNUNET_i2s (&peer->id)); | 2685 | GNUNET_i2s (&peer->id)); |
2686 | if (truncated) | ||
2687 | { | ||
2688 | GNUNET_assert (NULL != trunc_peer); | ||
2689 | bd.trunc_peer = *trunc_peer; | ||
2690 | } | ||
2439 | GNUNET_break (process_reply_with_path (&bd, | 2691 | GNUNET_break (process_reply_with_path (&bd, |
2440 | &prm->key, | 2692 | &prm->key, |
2441 | get_path_length + 1, | 2693 | get_path_length + 1, |
2442 | gp)); | 2694 | gp)); |
2443 | } | 2695 | } |
2696 | else | ||
2697 | { | ||
2698 | if (truncated) | ||
2699 | { | ||
2700 | GNUNET_assert (NULL != trunc_peer); | ||
2701 | bd.trunc_peer = *trunc_peer; | ||
2702 | } | ||
2703 | GNUNET_break (process_reply_with_path (&bd, | ||
2704 | &prm->key, | ||
2705 | 0, | ||
2706 | NULL)); | ||
2707 | } | ||
2444 | } | 2708 | } |
2445 | 2709 | ||
2446 | 2710 | ||