* 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:
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user