more fixes of misalignment

pull/129/head
orignal 10 years ago
parent fa4009821e
commit 29d1aa0146

@ -190,18 +190,17 @@ namespace client
void ClientDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, i2p::tunnel::InboundTunnel * from) 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 uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET];
I2NPHeader * header = (I2NPHeader *)buf; switch (typeID)
switch (header->typeID)
{ {
case eI2NPData: case eI2NPData:
HandleDataMessage (buf + sizeof (I2NPHeader), be16toh (header->size)); HandleDataMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
break; break;
case eI2NPDatabaseStore: case eI2NPDatabaseStore:
HandleDatabaseStoreMessage (buf + sizeof (I2NPHeader), be16toh (header->size)); HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
break; break;
case eI2NPDatabaseSearchReply: case eI2NPDatabaseSearchReply:
HandleDatabaseSearchReplyMessage (buf + sizeof (I2NPHeader), be16toh (header->size)); HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
break; break;
default: default:
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from));

@ -545,19 +545,18 @@ namespace i2p
size_t GetI2NPMessageLength (const uint8_t * msg) size_t GetI2NPMessageLength (const uint8_t * msg)
{ {
I2NPHeader * header = (I2NPHeader *)msg; return bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE;
return be16toh (header->size) + sizeof (I2NPHeader);
} }
void HandleI2NPMessage (uint8_t * msg, size_t len) void HandleI2NPMessage (uint8_t * msg, size_t len)
{ {
I2NPHeader * header = (I2NPHeader *)msg; uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
uint32_t msgID = be32toh (header->msgID); uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
LogPrint ("I2NP msg received len=", len,", type=", (int)header->typeID, ", msgID=", (unsigned int)msgID); LogPrint ("I2NP msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
uint8_t * buf = msg + sizeof (I2NPHeader); uint8_t * buf = msg + I2NP_HEADER_SIZE;
int size = be16toh (header->size); int size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
switch (header->typeID) switch (typeID)
{ {
case eI2NPVariableTunnelBuild: case eI2NPVariableTunnelBuild:
LogPrint ("VariableTunnelBuild"); LogPrint ("VariableTunnelBuild");
@ -576,7 +575,7 @@ namespace i2p
// TODO: // TODO:
break; break;
default: default:
LogPrint ("Unexpected message ", (int)header->typeID); LogPrint ("Unexpected message ", (int)typeID);
} }
} }

@ -19,6 +19,11 @@ namespace i2p
const size_t I2NP_HEADER_SIZE_OFFSET = I2NP_HEADER_EXPIRATION_OFFSET + 8; 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_CHKS_OFFSET = I2NP_HEADER_SIZE_OFFSET + 2;
const size_t I2NP_HEADER_SIZE = I2NP_HEADER_CHKS_OFFSET + 1; 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 // Tunnel Gateway header
const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0; const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0;
@ -27,21 +32,6 @@ namespace i2p
#pragma pack (1) #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 struct I2NPDatabaseStoreMsg
{ {
uint8_t key[32]; uint8_t key[32];
@ -118,10 +108,10 @@ namespace tunnel
size_t len, offset, maxLen; size_t len, offset, maxLen;
i2p::tunnel::InboundTunnel * from; 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) {}; offset(2), maxLen (0), from (nullptr) {};
// reserve 2 bytes for NTCP header // reserve 2 bytes for NTCP header
I2NPHeader * GetHeader () { return (I2NPHeader *)GetBuffer (); }; // depricated // I2NPHeader * GetHeader () { return (I2NPHeader *)GetBuffer (); }; // depricated
// header accessors // header accessors
uint8_t * GetHeaderBuffer () { return GetBuffer (); }; uint8_t * GetHeaderBuffer () { return GetBuffer (); };
const uint8_t * GetHeaderBuffer () const { 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); }; uint32_t GetMsgID () const { return bufbe32toh (GetHeaderBuffer () + I2NP_HEADER_MSGID_OFFSET); };
void SetExpiration (uint64_t expiration) { htobe64buf (GetHeaderBuffer () + I2NP_HEADER_EXPIRATION_OFFSET, expiration); }; void SetExpiration (uint64_t expiration) { htobe64buf (GetHeaderBuffer () + I2NP_HEADER_EXPIRATION_OFFSET, expiration); };
uint64_t GetExpiration () const { return bufbe64toh (GetHeaderBuffer () + I2NP_HEADER_EXPIRATION_OFFSET); }; 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); }; 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 () void UpdateChks ()
{ {
uint8_t hash[32]; uint8_t hash[32];
@ -141,11 +133,11 @@ namespace tunnel
} }
// payload // payload
uint8_t * GetPayload () { return GetBuffer () + sizeof(I2NPHeader); }; uint8_t * GetPayload () { return GetBuffer () + I2NP_HEADER_SIZE; };
uint8_t * GetBuffer () { return buf + offset; }; uint8_t * GetBuffer () { return buf + offset; };
const uint8_t * GetBuffer () const { return buf + offset; }; const uint8_t * GetBuffer () const { return buf + offset; };
size_t GetLength () const { return len - 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) void Align (size_t alignment)
{ {
@ -166,25 +158,25 @@ namespace tunnel
} }
// for SSU only // 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 void FromSSU (uint32_t msgID) // we have received SSU message and convert it to regular
{ {
I2NPHeaderShort ssu = *(I2NPHeaderShort *)GetSSUHeader (); const uint8_t * ssu = GetSSUHeader ();
I2NPHeader * header = GetHeader (); GetHeaderBuffer ()[I2NP_HEADER_TYPEID_OFFSET] = ssu[I2NP_SHORT_HEADER_TYPEID_OFFSET]; // typeid
header->typeID = ssu.typeID; SetMsgID (msgID);
header->msgID = htobe32 (msgID); SetExpiration (bufbe32toh (ssu + I2NP_SHORT_HEADER_EXPIRATION_OFFSET)*1000LL);
header->expiration = htobe64 (be32toh (ssu.shortExpiration)*1000LL); SetSize (len - offset - I2NP_HEADER_SIZE);
header->size = htobe16 (len - offset - sizeof (I2NPHeader)); SetChks (0);
header->chks = 0;
} }
uint32_t ToSSU () // return msgID uint32_t ToSSU () // return msgID
{ {
I2NPHeader header = *GetHeader (); uint8_t header[I2NP_HEADER_SIZE];
I2NPHeaderShort * ssu = (I2NPHeaderShort *)GetSSUHeader (); memcpy (header, GetHeaderBuffer (), I2NP_HEADER_SIZE);
ssu->typeID = header.typeID; uint8_t * ssu = GetSSUHeader ();
ssu->shortExpiration = htobe32 (be64toh (header.expiration)/1000LL); ssu[I2NP_SHORT_HEADER_TYPEID_OFFSET] = header[I2NP_HEADER_TYPEID_OFFSET]; // typeid
len = offset + sizeof (I2NPHeaderShort) + be16toh (header.size); htobe32buf (ssu + I2NP_SHORT_HEADER_EXPIRATION_OFFSET, bufbe64toh (header + I2NP_HEADER_EXPIRATION_OFFSET)/1000LL);
return be32toh (header.msgID); len = offset + I2NP_SHORT_HEADER_SIZE + bufbe16toh (header + I2NP_HEADER_SIZE_OFFSET);
return bufbe32toh (header + I2NP_HEADER_MSGID_OFFSET);
} }
}; };

@ -122,7 +122,7 @@ namespace data
{ {
while (msg) while (msg)
{ {
switch (msg->GetHeader ()->typeID) switch (msg->GetTypeID ())
{ {
case eI2NPDatabaseStore: case eI2NPDatabaseStore:
LogPrint ("DatabaseStore"); LogPrint ("DatabaseStore");
@ -137,7 +137,7 @@ namespace data
HandleDatabaseLookupMsg (msg); HandleDatabaseLookupMsg (msg);
break; break;
default: // WTF? default: // WTF?
LogPrint ("NetDb: unexpected message type ", msg->GetHeader ()->typeID); LogPrint ("NetDb: unexpected message type ", msg->GetTypeID ());
i2p::HandleI2NPMessage (msg); i2p::HandleI2NPMessage (msg);
} }
msg = m_Queue.Get (); msg = m_Queue.Get ();
@ -424,7 +424,7 @@ namespace data
void NetDb::HandleDatabaseStoreMsg (I2NPMessage * m) void NetDb::HandleDatabaseStoreMsg (I2NPMessage * m)
{ {
const uint8_t * buf = m->GetPayload (); const uint8_t * buf = m->GetPayload ();
size_t len = be16toh (m->GetHeader ()->size); size_t len = m->GetSize ();
I2NPDatabaseStoreMsg msg; I2NPDatabaseStoreMsg msg;
memcpy (&msg, buf, sizeof (I2NPDatabaseStoreMsg)); memcpy (&msg, buf, sizeof (I2NPDatabaseStoreMsg));
size_t offset = sizeof (I2NPDatabaseStoreMsg); size_t offset = sizeof (I2NPDatabaseStoreMsg);

@ -168,7 +168,7 @@ namespace transport
{ {
// create new message // create new message
msg = NewI2NPMessage (); msg = NewI2NPMessage ();
msg->len -= sizeof (I2NPHeaderShort); msg->len -= I2NP_SHORT_HEADER_SIZE;
incompleteMessage = new IncompleteMessage (msg); incompleteMessage = new IncompleteMessage (msg);
m_IncomleteMessages[msgID] = incompleteMessage; m_IncomleteMessages[msgID] = incompleteMessage;
} }
@ -246,13 +246,13 @@ namespace transport
else else
{ {
// we expect DeliveryStatus // we expect DeliveryStatus
if (msg->GetHeader ()->typeID == eI2NPDeliveryStatus) if (msg->GetTypeID () == eI2NPDeliveryStatus)
{ {
LogPrint ("SSU session established"); LogPrint ("SSU session established");
m_Session.Established (); m_Session.Established ();
} }
else else
LogPrint (eLogError, "SSU unexpected message ", (int)msg->GetHeader ()->typeID); LogPrint (eLogError, "SSU unexpected message ", (int)msg->GetTypeID ());
DeleteI2NPMessage (msg); DeleteI2NPMessage (msg);
} }
} }
@ -316,7 +316,7 @@ namespace transport
payload++; payload++;
*payload = 1; // always 1 message fragment per message *payload = 1; // always 1 message fragment per message
payload++; payload++;
htobuf32(payload, msgID); *(uint32_t *)payload = msgID;
payload += 4; payload += 4;
bool isLast = (len <= payloadSize); bool isLast = (len <= payloadSize);
size_t size = isLast ? len : payloadSize; size_t size = isLast ? len : payloadSize;
@ -359,7 +359,7 @@ namespace transport
payload++; payload++;
*payload = 1; // number of ACKs *payload = 1; // number of ACKs
payload++; payload++;
htobe32buf (payload, msgID); // msgID *(uint32_t *)(payload) = htobe32 (msgID); // msgID
payload += 4; payload += 4;
*payload = 0; // number of fragments *payload = 0; // number of fragments
@ -382,7 +382,7 @@ namespace transport
*payload = 1; // number of ACK bitfields *payload = 1; // number of ACK bitfields
payload++; payload++;
// one ack // one ack
htobe32buf (payload, msgID); // msgID *(uint32_t *)(payload) = htobe32 (msgID); // msgID
payload += 4; payload += 4;
div_t d = div (fragmentNum, 7); div_t d = div (fragmentNum, 7);
memset (payload, 0x80, d.quot); // 0x80 means non-last memset (payload, 0x80, d.quot); // 0x80 means non-last

@ -228,7 +228,7 @@ namespace tunnel
void TunnelEndpoint::HandleNextMessage (const TunnelMessageBlock& msg) 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) switch (msg.deliveryType)
{ {
case eDeliveryTypeLocal: case eDeliveryTypeLocal:
@ -245,8 +245,8 @@ namespace tunnel
// to somebody else // to somebody else
if (!m_IsInbound) // outbound transit tunnel if (!m_IsInbound) // outbound transit tunnel
{ {
if (msg.data->GetHeader()->typeID == eI2NPDatabaseStore || auto typeID = msg.data->GetTypeID ();
msg.data->GetHeader()->typeID == eI2NPDatabaseSearchReply ) if (typeID == eI2NPDatabaseStore || typeID == eI2NPDatabaseSearchReply )
{ {
// catch RI or reply with new list of routers // catch RI or reply with new list of routers
auto ds = NewI2NPMessage (); auto ds = NewI2NPMessage ();

@ -68,7 +68,8 @@ namespace tunnel
if (diLen + 6 <= m_RemainingSize) if (diLen + 6 <= m_RemainingSize)
{ {
// delivery instructions fit // 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) size_t size = m_RemainingSize - diLen - 6; // 6 = 4 (msgID) + 2 (size)
// first fragment // first fragment
@ -134,7 +135,7 @@ namespace tunnel
m_CurrentTunnelDataMsg = NewI2NPMessage (); m_CurrentTunnelDataMsg = NewI2NPMessage ();
m_CurrentTunnelDataMsg->Align (12); m_CurrentTunnelDataMsg->Align (12);
// we reserve space for padding // 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_CurrentTunnelDataMsg->len = m_CurrentTunnelDataMsg->offset;
m_RemainingSize = TUNNEL_DATA_MAX_PAYLOAD_SIZE; m_RemainingSize = TUNNEL_DATA_MAX_PAYLOAD_SIZE;
} }
@ -145,7 +146,7 @@ namespace tunnel
uint8_t * payload = m_CurrentTunnelDataMsg->GetBuffer (); uint8_t * payload = m_CurrentTunnelDataMsg->GetBuffer ();
size_t size = m_CurrentTunnelDataMsg->len - m_CurrentTunnelDataMsg->offset; 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 (); uint8_t * buf = m_CurrentTunnelDataMsg->GetPayload ();
htobe32buf (buf, m_TunnelID); htobe32buf (buf, m_TunnelID);
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();

Loading…
Cancel
Save