diff --git a/Destination.cpp b/Destination.cpp index 5e1dd2c8..148d9429 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -190,18 +190,17 @@ namespace client void ClientDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, i2p::tunnel::InboundTunnel * from) { - //TODO: since we are accessing a uint8_t this is unlikely to crash due to alignment but should be improved - I2NPHeader * header = (I2NPHeader *)buf; - switch (header->typeID) + uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET]; + switch (typeID) { case eI2NPData: - HandleDataMessage (buf + sizeof (I2NPHeader), be16toh (header->size)); + HandleDataMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); break; case eI2NPDatabaseStore: - HandleDatabaseStoreMessage (buf + sizeof (I2NPHeader), be16toh (header->size)); + HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); break; case eI2NPDatabaseSearchReply: - HandleDatabaseSearchReplyMessage (buf + sizeof (I2NPHeader), be16toh (header->size)); + HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); break; default: i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index 3ad54ff5..423ee047 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -545,19 +545,18 @@ namespace i2p size_t GetI2NPMessageLength (const uint8_t * msg) { - I2NPHeader * header = (I2NPHeader *)msg; - return be16toh (header->size) + sizeof (I2NPHeader); + return bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE; } void HandleI2NPMessage (uint8_t * msg, size_t len) { - I2NPHeader * header = (I2NPHeader *)msg; - uint32_t msgID = be32toh (header->msgID); - LogPrint ("I2NP msg received len=", len,", type=", (int)header->typeID, ", msgID=", (unsigned int)msgID); + uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET]; + uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET); + LogPrint ("I2NP msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID); - uint8_t * buf = msg + sizeof (I2NPHeader); - int size = be16toh (header->size); - switch (header->typeID) + uint8_t * buf = msg + I2NP_HEADER_SIZE; + int size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET); + switch (typeID) { case eI2NPVariableTunnelBuild: LogPrint ("VariableTunnelBuild"); @@ -576,7 +575,7 @@ namespace i2p // TODO: break; default: - LogPrint ("Unexpected message ", (int)header->typeID); + LogPrint ("Unexpected message ", (int)typeID); } } diff --git a/I2NPProtocol.h b/I2NPProtocol.h index 348632aa..1f93b0a1 100644 --- a/I2NPProtocol.h +++ b/I2NPProtocol.h @@ -19,6 +19,11 @@ namespace i2p const size_t I2NP_HEADER_SIZE_OFFSET = I2NP_HEADER_EXPIRATION_OFFSET + 8; const size_t I2NP_HEADER_CHKS_OFFSET = I2NP_HEADER_SIZE_OFFSET + 2; const size_t I2NP_HEADER_SIZE = I2NP_HEADER_CHKS_OFFSET + 1; + + // I2NP short header + const size_t I2NP_SHORT_HEADER_TYPEID_OFFSET = 0; + const size_t I2NP_SHORT_HEADER_EXPIRATION_OFFSET = I2NP_SHORT_HEADER_TYPEID_OFFSET + 1; + const size_t I2NP_SHORT_HEADER_SIZE = I2NP_SHORT_HEADER_EXPIRATION_OFFSET + 4; // Tunnel Gateway header const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0; @@ -27,21 +32,6 @@ namespace i2p #pragma pack (1) - struct I2NPHeader - { - uint8_t typeID; - uint32_t msgID; - uint64_t expiration; - uint16_t size; - uint8_t chks; - }; - - struct I2NPHeaderShort - { - uint8_t typeID; - uint32_t shortExpiration; - }; - struct I2NPDatabaseStoreMsg { uint8_t key[32]; @@ -118,10 +108,10 @@ namespace tunnel size_t len, offset, maxLen; i2p::tunnel::InboundTunnel * from; - I2NPMessage (): buf (nullptr),len (sizeof (I2NPHeader) + 2), + I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2), offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header - I2NPHeader * GetHeader () { return (I2NPHeader *)GetBuffer (); }; // depricated + // I2NPHeader * GetHeader () { return (I2NPHeader *)GetBuffer (); }; // depricated // header accessors uint8_t * GetHeaderBuffer () { return GetBuffer (); }; const uint8_t * GetHeaderBuffer () const { return GetBuffer (); }; @@ -131,8 +121,10 @@ namespace tunnel uint32_t GetMsgID () const { return bufbe32toh (GetHeaderBuffer () + I2NP_HEADER_MSGID_OFFSET); }; void SetExpiration (uint64_t expiration) { htobe64buf (GetHeaderBuffer () + I2NP_HEADER_EXPIRATION_OFFSET, expiration); }; uint64_t GetExpiration () const { return bufbe64toh (GetHeaderBuffer () + I2NP_HEADER_EXPIRATION_OFFSET); }; + void SetSize (uint16_t size) { htobe16buf (GetHeaderBuffer () + I2NP_HEADER_SIZE_OFFSET, size); }; uint16_t GetSize () const { return bufbe16toh (GetHeaderBuffer () + I2NP_HEADER_SIZE_OFFSET); }; - void UpdateSize () { htobe16buf (GetHeaderBuffer () + I2NP_HEADER_SIZE_OFFSET, GetPayloadLength ()); }; + void UpdateSize () { SetSize (GetPayloadLength ()); }; + void SetChks (uint8_t chks) { GetHeaderBuffer ()[I2NP_HEADER_CHKS_OFFSET] = chks; }; void UpdateChks () { uint8_t hash[32]; @@ -141,11 +133,11 @@ namespace tunnel } // payload - uint8_t * GetPayload () { return GetBuffer () + sizeof(I2NPHeader); }; + uint8_t * GetPayload () { return GetBuffer () + I2NP_HEADER_SIZE; }; uint8_t * GetBuffer () { return buf + offset; }; const uint8_t * GetBuffer () const { return buf + offset; }; size_t GetLength () const { return len - offset; }; - size_t GetPayloadLength () const { return GetLength () - sizeof(I2NPHeader); }; + size_t GetPayloadLength () const { return GetLength () - I2NP_HEADER_SIZE; }; void Align (size_t alignment) { @@ -166,25 +158,25 @@ namespace tunnel } // for SSU only - uint8_t * GetSSUHeader () { return buf + offset + sizeof(I2NPHeader) - sizeof(I2NPHeaderShort); }; + uint8_t * GetSSUHeader () { return buf + offset + I2NP_HEADER_SIZE - I2NP_SHORT_HEADER_SIZE; }; void FromSSU (uint32_t msgID) // we have received SSU message and convert it to regular { - I2NPHeaderShort ssu = *(I2NPHeaderShort *)GetSSUHeader (); - I2NPHeader * header = GetHeader (); - header->typeID = ssu.typeID; - header->msgID = htobe32 (msgID); - header->expiration = htobe64 (be32toh (ssu.shortExpiration)*1000LL); - header->size = htobe16 (len - offset - sizeof (I2NPHeader)); - header->chks = 0; + const uint8_t * ssu = GetSSUHeader (); + GetHeaderBuffer ()[I2NP_HEADER_TYPEID_OFFSET] = ssu[I2NP_SHORT_HEADER_TYPEID_OFFSET]; // typeid + SetMsgID (msgID); + SetExpiration (bufbe32toh (ssu + I2NP_SHORT_HEADER_EXPIRATION_OFFSET)*1000LL); + SetSize (len - offset - I2NP_HEADER_SIZE); + SetChks (0); } uint32_t ToSSU () // return msgID { - I2NPHeader header = *GetHeader (); - I2NPHeaderShort * ssu = (I2NPHeaderShort *)GetSSUHeader (); - ssu->typeID = header.typeID; - ssu->shortExpiration = htobe32 (be64toh (header.expiration)/1000LL); - len = offset + sizeof (I2NPHeaderShort) + be16toh (header.size); - return be32toh (header.msgID); + uint8_t header[I2NP_HEADER_SIZE]; + memcpy (header, GetHeaderBuffer (), I2NP_HEADER_SIZE); + uint8_t * ssu = GetSSUHeader (); + ssu[I2NP_SHORT_HEADER_TYPEID_OFFSET] = header[I2NP_HEADER_TYPEID_OFFSET]; // typeid + htobe32buf (ssu + I2NP_SHORT_HEADER_EXPIRATION_OFFSET, bufbe64toh (header + I2NP_HEADER_EXPIRATION_OFFSET)/1000LL); + len = offset + I2NP_SHORT_HEADER_SIZE + bufbe16toh (header + I2NP_HEADER_SIZE_OFFSET); + return bufbe32toh (header + I2NP_HEADER_MSGID_OFFSET); } }; diff --git a/NetDb.cpp b/NetDb.cpp index b4d63631..e9a2f0c1 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -122,7 +122,7 @@ namespace data { while (msg) { - switch (msg->GetHeader ()->typeID) + switch (msg->GetTypeID ()) { case eI2NPDatabaseStore: LogPrint ("DatabaseStore"); @@ -137,7 +137,7 @@ namespace data HandleDatabaseLookupMsg (msg); break; default: // WTF? - LogPrint ("NetDb: unexpected message type ", msg->GetHeader ()->typeID); + LogPrint ("NetDb: unexpected message type ", msg->GetTypeID ()); i2p::HandleI2NPMessage (msg); } msg = m_Queue.Get (); @@ -424,7 +424,7 @@ namespace data void NetDb::HandleDatabaseStoreMsg (I2NPMessage * m) { const uint8_t * buf = m->GetPayload (); - size_t len = be16toh (m->GetHeader ()->size); + size_t len = m->GetSize (); I2NPDatabaseStoreMsg msg; memcpy (&msg, buf, sizeof (I2NPDatabaseStoreMsg)); size_t offset = sizeof (I2NPDatabaseStoreMsg); diff --git a/SSUData.cpp b/SSUData.cpp index c6f0b5e5..a4c47559 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -168,7 +168,7 @@ namespace transport { // create new message msg = NewI2NPMessage (); - msg->len -= sizeof (I2NPHeaderShort); + msg->len -= I2NP_SHORT_HEADER_SIZE; incompleteMessage = new IncompleteMessage (msg); m_IncomleteMessages[msgID] = incompleteMessage; } @@ -246,13 +246,13 @@ namespace transport else { // we expect DeliveryStatus - if (msg->GetHeader ()->typeID == eI2NPDeliveryStatus) + if (msg->GetTypeID () == eI2NPDeliveryStatus) { LogPrint ("SSU session established"); m_Session.Established (); } else - LogPrint (eLogError, "SSU unexpected message ", (int)msg->GetHeader ()->typeID); + LogPrint (eLogError, "SSU unexpected message ", (int)msg->GetTypeID ()); DeleteI2NPMessage (msg); } } @@ -316,7 +316,7 @@ namespace transport payload++; *payload = 1; // always 1 message fragment per message payload++; - htobuf32(payload, msgID); + *(uint32_t *)payload = msgID; payload += 4; bool isLast = (len <= payloadSize); size_t size = isLast ? len : payloadSize; @@ -359,7 +359,7 @@ namespace transport payload++; *payload = 1; // number of ACKs payload++; - htobe32buf (payload, msgID); // msgID + *(uint32_t *)(payload) = htobe32 (msgID); // msgID payload += 4; *payload = 0; // number of fragments @@ -382,7 +382,7 @@ namespace transport *payload = 1; // number of ACK bitfields payload++; // one ack - htobe32buf (payload, msgID); // msgID + *(uint32_t *)(payload) = htobe32 (msgID); // msgID payload += 4; div_t d = div (fragmentNum, 7); memset (payload, 0x80, d.quot); // 0x80 means non-last diff --git a/TunnelEndpoint.cpp b/TunnelEndpoint.cpp index 74fd0262..d7fa821b 100644 --- a/TunnelEndpoint.cpp +++ b/TunnelEndpoint.cpp @@ -228,7 +228,7 @@ namespace tunnel void TunnelEndpoint::HandleNextMessage (const TunnelMessageBlock& msg) { - LogPrint ("TunnelMessage: handle fragment of ", msg.data->GetLength ()," bytes. Msg type ", (int)msg.data->GetHeader()->typeID); + LogPrint ("TunnelMessage: handle fragment of ", msg.data->GetLength ()," bytes. Msg type ", (int)msg.data->GetTypeID ()); switch (msg.deliveryType) { case eDeliveryTypeLocal: @@ -245,8 +245,8 @@ namespace tunnel // to somebody else if (!m_IsInbound) // outbound transit tunnel { - if (msg.data->GetHeader()->typeID == eI2NPDatabaseStore || - msg.data->GetHeader()->typeID == eI2NPDatabaseSearchReply ) + auto typeID = msg.data->GetTypeID (); + if (typeID == eI2NPDatabaseStore || typeID == eI2NPDatabaseSearchReply ) { // catch RI or reply with new list of routers auto ds = NewI2NPMessage (); diff --git a/TunnelGateway.cpp b/TunnelGateway.cpp index 3b3980e0..62311912 100644 --- a/TunnelGateway.cpp +++ b/TunnelGateway.cpp @@ -68,7 +68,8 @@ namespace tunnel if (diLen + 6 <= m_RemainingSize) { // delivery instructions fit - uint32_t msgID = msg->GetHeader ()->msgID; // in network bytes order + uint32_t msgID; + memcpy (&msgID, msg->GetHeaderBuffer () + I2NP_HEADER_MSGID_OFFSET, 4); // in network bytes order size_t size = m_RemainingSize - diLen - 6; // 6 = 4 (msgID) + 2 (size) // first fragment @@ -134,7 +135,7 @@ namespace tunnel m_CurrentTunnelDataMsg = NewI2NPMessage (); m_CurrentTunnelDataMsg->Align (12); // we reserve space for padding - m_CurrentTunnelDataMsg->offset += TUNNEL_DATA_MSG_SIZE + sizeof (I2NPHeader); + m_CurrentTunnelDataMsg->offset += TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE; m_CurrentTunnelDataMsg->len = m_CurrentTunnelDataMsg->offset; m_RemainingSize = TUNNEL_DATA_MAX_PAYLOAD_SIZE; } @@ -145,7 +146,7 @@ namespace tunnel uint8_t * payload = m_CurrentTunnelDataMsg->GetBuffer (); size_t size = m_CurrentTunnelDataMsg->len - m_CurrentTunnelDataMsg->offset; - m_CurrentTunnelDataMsg->offset = m_CurrentTunnelDataMsg->len - TUNNEL_DATA_MSG_SIZE - sizeof (I2NPHeader); + m_CurrentTunnelDataMsg->offset = m_CurrentTunnelDataMsg->len - TUNNEL_DATA_MSG_SIZE - I2NP_HEADER_SIZE; uint8_t * buf = m_CurrentTunnelDataMsg->GetPayload (); htobe32buf (buf, m_TunnelID); CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();