| 464 | } |
| 465 | |
| 466 | bool TransitTunnels::HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText) |
| 467 | { |
| 468 | for (int i = 0; i < num; i++) |
| 469 | { |
| 470 | uint8_t * record = records + i*TUNNEL_BUILD_RECORD_SIZE; |
| 471 | if (!memcmp (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16)) |
| 472 | { |
| 473 | LogPrint (eLogDebug, "TransitTunnel: Build request record ", i, " is ours"); |
| 474 | if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) |
| 475 | { |
| 476 | LogPrint (eLogWarning, "TransitTunnel: Failed to decrypt tunnel build record"); |
| 477 | return false; |
| 478 | } |
| 479 | if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32) && // if next ident is now ours |
| 480 | !(clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG)) // and not endpoint |
| 481 | { |
| 482 | LogPrint (eLogWarning, "TransitTunnel: Next ident is ours in tunnel build record"); |
| 483 | return false; |
| 484 | } |
| 485 | uint8_t retCode = 0; |
| 486 | // decide if we should accept tunnel |
| 487 | bool accept = i2p::context.AcceptsTunnels () && !i2p::context.IsLimitedConnectivity (); |
| 488 | if (accept) |
| 489 | { |
| 490 | auto congestionLevel = i2p::context.GetCongestionLevel (false); |
| 491 | if (congestionLevel >= CONGESTION_LEVEL_MEDIUM) |
| 492 | { |
| 493 | if (congestionLevel < CONGESTION_LEVEL_FULL) |
| 494 | { |
| 495 | // random reject depending on congestion level |
| 496 | int level = m_Rng () % (CONGESTION_LEVEL_FULL - CONGESTION_LEVEL_MEDIUM) + CONGESTION_LEVEL_MEDIUM; |
| 497 | if (congestionLevel > level) |
| 498 | accept = false; |
| 499 | } |
| 500 | else |
| 501 | accept = false; |
| 502 | } |
| 503 | } |
| 504 | |
| 505 | if (accept) |
| 506 | { |
| 507 | i2p::data::IdentHash nextIdent(clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET); |
| 508 | bool isEndpoint = clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG; |
| 509 | if (isEndpoint || !i2p::data::IsRouterDuplicated (nextIdent)) |
| 510 | { |
| 511 | auto transitTunnel = CreateTransitTunnel ( |
| 512 | bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), |
| 513 | nextIdent, |
| 514 | bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), |
| 515 | clearText + ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, |
| 516 | clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET, |
| 517 | clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG, |
| 518 | isEndpoint); |
| 519 | if (!AddTransitTunnel (transitTunnel)) |
| 520 | retCode = 30; |
| 521 | } |
| 522 | else |
| 523 | // decline tunnel going to duplicated router |
nothing calls this directly
no test coverage detected