Esempio n. 1
0
void RouterContext::HandleI2NPMessage(
    const uint8_t* buf,
    size_t,
    std::shared_ptr<i2p::tunnel::InboundTunnel> from) {
  i2p::HandleI2NPMessage(
      CreateI2NPMessage(
        buf,
        GetI2NPMessageLength(buf),
        from));
}
Esempio n. 2
0
	I2NPMessage * CreateDeliveryStatusMsg (uint32_t msgID)
	{
		I2NPDeliveryStatusMsg msg;
		if (msgID)
		{
			msg.msgID = htobe32 (msgID);
			msg.timestamp = htobe64 (i2p::util::GetMillisecondsSinceEpoch ());
		}
		else // for SSU establishment
		{
			msg.msgID = htobe32 (i2p::context.GetRandomNumberGenerator ().GenerateWord32 ());
			msg.timestamp = htobe64 (2); // netID = 2
 		}
		return CreateI2NPMessage (eI2NPDeliveryStatus, (uint8_t *)&msg, sizeof (msg));
	}
Esempio n. 3
0
	void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len)
	{	
		int num = buf[0];
		LogPrint (eLogDebug, "I2NP: VariableTunnelBuild ", num, " records");
		if (len < num*BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 1)
		{
			LogPrint (eLogError, "VaribleTunnelBuild message of ", num, " records is too short ", len);
			return;
		}	

		auto tunnel =  i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID);
		if (tunnel)
		{
			// endpoint of inbound tunnel
			LogPrint (eLogDebug, "I2NP: VariableTunnelBuild reply for tunnel ", tunnel->GetTunnelID ());
			if (tunnel->HandleTunnelBuildResponse (buf, len))
			{
				LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been created");
				tunnel->SetState (i2p::tunnel::eTunnelStateEstablished);	
				i2p::tunnel::tunnels.AddInboundTunnel (tunnel);
			}
			else
			{
				LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been declined");
				tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed);	
			}
		}
		else
		{
			uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE];	
			if (HandleBuildRequestRecords (num, buf + 1, clearText))
			{
				if (clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40) // we are endpoint of outboud tunnel
				{
					// so we send it to reply tunnel 
					transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 
						CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
							eI2NPVariableTunnelBuildReply, buf, len, 
						    bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));                         
				}	
				else	
					transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 
						CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, 
							bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
			}	
		}	
	}
Esempio n. 4
0
	void HandleTunnelBuildMsg (uint8_t * buf, size_t len)
	{
		I2NPBuildRequestRecordClearText clearText;	
		if (HandleBuildRequestRecords (NUM_TUNNEL_BUILD_RECORDS, (I2NPBuildRequestRecordElGamalEncrypted *)buf, clearText))
		{
			if (clearText.flag & 0x40) // we are endpoint of outbound tunnel
			{
				// so we send it to reply tunnel 
				transports.SendMessage (clearText.nextIdent, 
					CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel),
						eI2NPTunnelBuildReply, buf, len, 
					    be32toh (clearText.nextMessageID)));                         
			}	
			else	
				transports.SendMessage (clearText.nextIdent, 
					CreateI2NPMessage (eI2NPTunnelBuild, buf, len, be32toh (clearText.nextMessageID)));
		} 
	}
Esempio n. 5
0
	void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len)
	{	
		int num = buf[0];
		LogPrint ("VariableTunnelBuild ", num, " records");

		i2p::tunnel::Tunnel * tunnel =  i2p::tunnel::tunnels.GetPendingTunnel (replyMsgID);
		if (tunnel)
		{
			// endpoint of inbound tunnel
			LogPrint ("VariableTunnelBuild reply for tunnel ", tunnel->GetTunnelID ());
			if (tunnel->HandleTunnelBuildResponse (buf, len))
			{
				LogPrint ("Inbound tunnel ", tunnel->GetTunnelID (), " has been created");
				tunnel->SetState (i2p::tunnel::eTunnelStateEstablished);	
				i2p::tunnel::tunnels.AddInboundTunnel (static_cast<i2p::tunnel::InboundTunnel *>(tunnel));
			}
			else
			{
				LogPrint ("Inbound tunnel ", tunnel->GetTunnelID (), " has been declined");
				tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed);	
			}
		}
		else
		{
			I2NPBuildRequestRecordElGamalEncrypted * records = (I2NPBuildRequestRecordElGamalEncrypted *)(buf+1); 
			I2NPBuildRequestRecordClearText clearText;	
			if (HandleBuildRequestRecords (num, records, clearText))
			{
				if (clearText.flag & 0x40) // we are endpoint of outboud tunnel
				{
					// so we send it to reply tunnel 
					transports.SendMessage (clearText.nextIdent, 
						CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel),
							eI2NPVariableTunnelBuildReply, buf, len, 
						    be32toh (clearText.nextMessageID)));                         
				}	
				else	
					transports.SendMessage (clearText.nextIdent, 
						CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, be32toh (clearText.nextMessageID)));
			}	
		}	
	}
Esempio n. 6
0
	void HandleTunnelBuildMsg (uint8_t * buf, size_t len)
	{
		if (len < NUM_TUNNEL_BUILD_RECORDS*BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE)
		{
			LogPrint (eLogError, "TunnelBuild message is too short ", len);
			return;
		}	
		uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE];	
		if (HandleBuildRequestRecords (NUM_TUNNEL_BUILD_RECORDS, buf, clearText))
		{
			if (clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40) // we are endpoint of outbound tunnel
			{
				// so we send it to reply tunnel 
				transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 
					CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
						eI2NPTunnelBuildReply, buf, len, 
					    bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));                         
			}	
			else	
				transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 
					CreateI2NPMessage (eI2NPTunnelBuild, buf, len, 
						bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
		} 
	}
Esempio n. 7
0
	void GarlicDestination::HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
	{
		if (len < 1)
		{
			LogPrint (eLogError, "Garlic: payload is too short");
			return;
		}
		int numCloves = buf[0];
		LogPrint (eLogDebug, "Garlic: ", numCloves," cloves");
		buf++; len--;
		for (int i = 0; i < numCloves; i++)
		{
			const uint8_t * buf1 = buf;
			// delivery instructions
			uint8_t flag = buf[0];
			buf++; // flag
			if (flag & 0x80) // encrypted?
			{
				// TODO: implement
				LogPrint (eLogWarning, "Garlic: clove encrypted");
				buf += 32;
			}
			ptrdiff_t offset = buf - buf1;
			GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03);
			switch (deliveryType)
			{
				case eGarlicDeliveryTypeLocal:
					LogPrint (eLogDebug, "Garlic: type local");
					if (offset > (int)len)
					{
						LogPrint (eLogError, "Garlic: message is too short");
						break;
					}
					HandleI2NPMessage (buf, len - offset, from);
				break;
				case eGarlicDeliveryTypeDestination:
					LogPrint (eLogDebug, "Garlic: type destination");
					buf += 32; // destination. check it later or for multiple destinations
					offset = buf - buf1;
					if (offset > (int)len)
					{
						LogPrint (eLogError, "Garlic: message is too short");
						break;
					}
					HandleI2NPMessage (buf, len - offset, from);
				break;
				case eGarlicDeliveryTypeTunnel:
				{
					LogPrint (eLogDebug, "Garlic: type tunnel");
					// gwHash and gwTunnel sequence is reverted
					uint8_t * gwHash = buf;
					buf += 32;
					offset = buf - buf1;
					if (offset + 4 > (int)len)
					{
						LogPrint (eLogError, "Garlic: message is too short");
						break;
					}
					uint32_t gwTunnel = bufbe32toh (buf);
					buf += 4; offset += 4;
					auto msg = CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len - offset), from);
					if (from) // received through an inbound tunnel
					{
						std::shared_ptr<i2p::tunnel::OutboundTunnel> tunnel;
						if (from->GetTunnelPool ())
							tunnel = from->GetTunnelPool ()->GetNextOutboundTunnel ();
						else
							LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel");
						if (tunnel) // we have send it through an outbound tunnel
							tunnel->SendTunnelDataMsg (gwHash, gwTunnel, msg);
						else
							LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
					}
					else // received directly
						i2p::transport::transports.SendMessage (gwHash, i2p::CreateTunnelGatewayMsg (gwTunnel, msg)); // send directly
					break;
				}
				case eGarlicDeliveryTypeRouter:
				{
					uint8_t * ident = buf;
					buf += 32;
					offset = buf - buf1;
					if (!from) // received directly
					{
						if (offset > (int)len)
						{
							LogPrint (eLogError, "Garlic: message is too short");
							break;
						}
						i2p::transport::transports.SendMessage (ident,
							CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len - offset)));
					}
					else
						LogPrint (eLogWarning, "Garlic: type router for inbound tunnels not supported");
					break;
				}
				default:
					LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType);
			}
			if (offset > (int)len)
			{
				LogPrint (eLogError, "Garlic: message is too short");
				break;
			}
			buf += GetI2NPMessageLength (buf, len - offset); //  I2NP
			buf += 4; // CloveID
			buf += 8; // Date
			buf += 3; // Certificate
			offset = buf - buf1;
			if (offset > (int)len)
			{
				LogPrint (eLogError, "Garlic: clove is too long");
				break;
			}
			len -= offset;
		}
	}
Esempio n. 8
0
	void GarlicDestination::HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
	{
		const uint8_t * buf1 = buf;
		int numCloves = buf[0];
		LogPrint (eLogDebug, "Garlic: ", numCloves," cloves");
		buf++;
		for (int i = 0; i < numCloves; i++)
		{
			// delivery instructions
			uint8_t flag = buf[0];
			buf++; // flag
			if (flag & 0x80) // encrypted?
			{
				// TODO: implement
				LogPrint (eLogWarning, "Garlic: clove encrypted");
				buf += 32; 
			}	
			GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03);
			switch (deliveryType)
			{
				case eGarlicDeliveryTypeLocal:
					LogPrint (eLogDebug, "Garlic: type local");
					HandleI2NPMessage (buf, len, from);
				break;	
				case eGarlicDeliveryTypeDestination:	
					LogPrint (eLogDebug, "Garlic: type destination");
					buf += 32; // destination. check it later or for multiple destinations
					HandleI2NPMessage (buf, len, from);
				break;
				case eGarlicDeliveryTypeTunnel:
				{	
					LogPrint (eLogDebug, "Garlic: type tunnel");
					// gwHash and gwTunnel sequence is reverted
					uint8_t * gwHash = buf;
					buf += 32;
					uint32_t gwTunnel = bufbe32toh (buf);
					buf += 4;
					std::shared_ptr<i2p::tunnel::OutboundTunnel> tunnel;
					if (from && from->GetTunnelPool ())
						tunnel = from->GetTunnelPool ()->GetNextOutboundTunnel ();
					if (tunnel) // we have send it through an outbound tunnel
					{	
						auto msg = CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from);
						tunnel->SendTunnelDataMsg (gwHash, gwTunnel, msg);
					}	
					else
						LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
					break;
				}
				case eGarlicDeliveryTypeRouter:
					LogPrint (eLogWarning, "Garlic: type router not supported");
					buf += 32;
				break;	
				default:
					LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType);
			}
			buf += GetI2NPMessageLength (buf); //  I2NP
			buf += 4; // CloveID
			buf += 8; // Date
			buf += 3; // Certificate
			if (buf - buf1  > (int)len)
			{
				LogPrint (eLogError, "Garlic: clove is too long");
				break;
			}	
		}	
	}