From af56b5b233a200d83b427d967bac7453f4043f6f Mon Sep 17 00:00:00 2001 From: Hugo Santos Date: Tue, 10 Apr 2007 19:04:13 +0000 Subject: [PATCH] fixed add_tcp_header() as it wasn't considering the possibility that prepending data would not result in a contiguous buffer. This would result in wrong checksums for apparent no reason. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20643 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/net/NetBufferUtilities.h | 45 +++++++++++++------ .../kernel/network/protocols/tcp/tcp.cpp | 9 +++- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/headers/private/net/NetBufferUtilities.h b/headers/private/net/NetBufferUtilities.h index 3045cff7e9..290d496c95 100644 --- a/headers/private/net/NetBufferUtilities.h +++ b/headers/private/net/NetBufferUtilities.h @@ -81,21 +81,24 @@ template class NetBuffe Type fDataBuffer; }; -//! A class to add a header to a buffer -template class NetBufferPrepend { +//! A class to access a header safely across data node boundaries +template +class NetBufferSafeHeader { public: - NetBufferPrepend(net_buffer *buffer, size_t size = 0) + NetBufferSafeHeader(net_buffer *buffer) : - fBuffer(buffer), - fData(NULL) + fBuffer(buffer) { - if (size == 0) - size = sizeof(Type); - - fStatus = Module::Get()->prepend_size(buffer, size, (void **)&fData); + fStatus = Module::Get()->direct_access(fBuffer, 0, + sizeof(Type), (void **)&fData); + if (fStatus != B_OK) { + fData = NULL; + fStatus = Module::Get()->read(fBuffer, 0, &fDataBuffer, + sizeof(Type)); + } } - ~NetBufferPrepend() + ~NetBufferSafeHeader() { if (fBuffer != NULL) Detach(); @@ -116,8 +119,6 @@ template class NetBuffe return fDataBuffer; } - // TODO: I'm not sure it's a good idea to have Detach() routines - // in NetBufferHeader and here with such a different outcome... void Detach() { @@ -126,11 +127,29 @@ template class NetBuffe fBuffer = NULL; } - private: + protected: + NetBufferSafeHeader() {} + net_buffer *fBuffer; status_t fStatus; Type *fData; Type fDataBuffer; }; +//! A class to add a header to a buffer +template +class NetBufferPrepend : public NetBufferSafeHeader { + public: + NetBufferPrepend(net_buffer *buffer, size_t size = 0) + { + fBuffer = buffer; + fData = NULL; + + if (size == 0) + size = sizeof(Type); + + fStatus = Module::Get()->prepend_size(buffer, size, (void **)&fData); + } +}; + #endif // NET_BUFFER_UTILITIES_H diff --git a/src/add-ons/kernel/network/protocols/tcp/tcp.cpp b/src/add-ons/kernel/network/protocols/tcp/tcp.cpp index b22e2e45bc..e9fb65f8b0 100644 --- a/src/add-ons/kernel/network/protocols/tcp/tcp.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/tcp.cpp @@ -148,6 +148,10 @@ add_tcp_header(tcp_segment_header &segment, net_buffer *buffer) header.urgent_offset = 0; // TODO: urgent pointer not yet supported + // we must detach before calculating the checksum as we may + // not have a contiguous buffer. + bufferHeader.Detach(); + if (optionsLength > 0) gBufferModule->write(buffer, sizeof(tcp_header), optionsBuffer, optionsLength); @@ -162,7 +166,10 @@ add_tcp_header(tcp_segment_header &segment, net_buffer *buffer) << (uint16)htons(IPPROTO_TCP) << (uint16)htons(buffer->size) << Checksum::BufferHelper(buffer, gBufferModule); - header.checksum = checksum; + + // we are pretty sure the header is there. + NetBufferSafeHeader headerRef(buffer); + headerRef.Data().checksum = checksum; return B_OK; }