* Fragmenting IP packets is now working as expected (there were several bugs

in the code before).
* Added a SetTo() method to NetBufferHeader.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19069 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-10-15 09:52:54 +00:00
parent 2e95d2f425
commit 81435928fb
2 changed files with 29 additions and 17 deletions
+8 -4
View File
@@ -36,6 +36,13 @@ template<typename Type, typename Module = NetBufferModuleGetter > class NetBuffe
return fBuffer->size < sizeof(Type) ? B_BAD_VALUE : B_OK; return fBuffer->size < sizeof(Type) ? B_BAD_VALUE : B_OK;
} }
status_t
SetTo(net_buffer *buffer)
{
fBuffer = buffer;
return Status();
}
Type & Type &
Data() Data()
{ {
@@ -51,10 +58,7 @@ template<typename Type, typename Module = NetBufferModuleGetter > class NetBuffe
void void
Remove() Remove()
{ {
if (fBuffer != NULL) { Remove(sizeof(Type));
Module::Get()->remove_header(fBuffer, sizeof(Type));
fBuffer = NULL;
}
} }
void void
@@ -568,18 +568,14 @@ send_fragments(ipv4_protocol *protocol, struct net_route *route,
dprintf("ipv4 needs to fragment (size %lu, MTU %lu), but that's not yet tested...\n", dprintf("ipv4 needs to fragment (size %lu, MTU %lu), but that's not yet tested...\n",
buffer->size, mtu); buffer->size, mtu);
// adapt MTU to be a multiple of 8 (fragment offsets can only be specified this way)
mtu &= ~7;
dprintf(" adjusted MTU to %ld\n", mtu);
NetBufferHeader<ipv4_header> bufferHeader(buffer); NetBufferHeader<ipv4_header> bufferHeader(buffer);
if (bufferHeader.Status() < B_OK) if (bufferHeader.Status() < B_OK)
return bufferHeader.Status(); return bufferHeader.Status();
ipv4_header &header = bufferHeader.Data(); ipv4_header *header = &bufferHeader.Data();
bufferHeader.Detach(); bufferHeader.Detach();
uint16 headerLength = header.HeaderLength(); uint16 headerLength = header->HeaderLength();
uint32 bytesLeft = buffer->size - headerLength; uint32 bytesLeft = buffer->size - headerLength;
uint32 fragmentOffset = 0; uint32 fragmentOffset = 0;
status_t status = B_OK; status_t status = B_OK;
@@ -588,16 +584,28 @@ send_fragments(ipv4_protocol *protocol, struct net_route *route,
if (headerBuffer == NULL) if (headerBuffer == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
bufferHeader.SetTo(headerBuffer);
header = &bufferHeader.Data();
bufferHeader.Detach();
// adapt MTU to be a multiple of 8 (fragment offsets can only be specified this way)
mtu -= headerLength;
mtu &= ~7;
dprintf(" adjusted MTU to %ld\n", mtu);
dprintf(" bytesLeft = %ld\n", bytesLeft);
while (bytesLeft > 0) { while (bytesLeft > 0) {
uint32 fragmentLength = max_c(bytesLeft, mtu); uint32 fragmentLength = min_c(bytesLeft, mtu);
bytesLeft -= fragmentLength; bytesLeft -= fragmentLength;
bool lastFragment = bytesLeft == 0; bool lastFragment = bytesLeft == 0;
header.total_length = htons(fragmentLength); header->total_length = htons(fragmentLength + headerLength);
header.fragment_offset = htons((lastFragment ? 0 : IP_MORE_FRAGMENTS) header->fragment_offset = htons((lastFragment ? 0 : IP_MORE_FRAGMENTS)
| (fragmentOffset >> 3)); | (fragmentOffset >> 3));
header.checksum = sBufferModule->checksum(buffer, 0, sizeof(ipv4_header), true); header->checksum = 0;
header->checksum = sStackModule->checksum((uint8 *)header, headerLength);
// TODO: compute the checksum only for those parts that changed? // TODO: compute the checksum only for those parts that changed?
dprintf(" send fragment of %ld bytes (%ld bytes left)\n", fragmentLength, bytesLeft); dprintf(" send fragment of %ld bytes (%ld bytes left)\n", fragmentLength, bytesLeft);
net_buffer *fragmentBuffer; net_buffer *fragmentBuffer;
@@ -613,7 +621,7 @@ send_fragments(ipv4_protocol *protocol, struct net_route *route,
} }
// copy header to fragment // copy header to fragment
status = sBufferModule->prepend(fragmentBuffer, &header, headerLength); status = sBufferModule->prepend(fragmentBuffer, header, headerLength);
// send fragment // send fragment
if (status == B_OK) if (status == B_OK)
@@ -979,7 +987,7 @@ ipv4_get_mtu(net_protocol *protocol, const struct sockaddr *address)
status_t status_t
ipv4_receive_data(net_buffer *buffer) ipv4_receive_data(net_buffer *buffer)
{ {
TRACE(("IPv4 received a packet of %ld size!\n", buffer->size)); TRACE(("IPv4 received a packet (%p) of %ld size!\n", buffer, buffer->size));
NetBufferHeader<ipv4_header> bufferHeader(buffer); NetBufferHeader<ipv4_header> bufferHeader(buffer);
if (bufferHeader.Status() < B_OK) if (bufferHeader.Status() < B_OK)