From 49f3c71e21b3b4f09905bf967b84e909fa24cd2b Mon Sep 17 00:00:00 2001 From: Hugo Santos Date: Fri, 13 Apr 2007 21:33:13 +0000 Subject: [PATCH] respect SO_BROADCAST for received and sent datagrams. - check if the destination address is specified in IPv4's SendData() - minor cleanups to IPv4's TRACE()s. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20681 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/net/ProtocolUtilities.h | 20 +++-- .../kernel/network/protocols/ipv4/ipv4.cpp | 84 ++++++++++++------- .../kernel/network/protocols/udp/udp.cpp | 2 +- src/add-ons/kernel/network/stack/link.cpp | 2 +- 4 files changed, 68 insertions(+), 40 deletions(-) diff --git a/headers/private/net/ProtocolUtilities.h b/headers/private/net/ProtocolUtilities.h index 49051bfee0..7618f450d7 100644 --- a/headers/private/net/ProtocolUtilities.h +++ b/headers/private/net/ProtocolUtilities.h @@ -50,13 +50,14 @@ public: status_t InitCheck() const; status_t Enqueue(net_buffer *buffer); - status_t EnqueueClone(net_buffer *buffer); net_buffer *Dequeue(bool clone); status_t BlockingDequeue(bool clone, bigtime_t timeout, net_buffer **_buffer); - status_t SocketDequeue(uint32 flags, net_buffer **_buffer); void Clear(); + status_t SocketEnqueue(net_buffer *buffer); + status_t SocketDequeue(uint32 flags, net_buffer **_buffer); + size_t AvailableData() const; void WakeAll(); @@ -65,7 +66,7 @@ public: protected: status_t _Enqueue(net_buffer *buffer); - status_t _EnqueueClone(net_buffer *buffer); + status_t _SocketEnqueue(net_buffer *buffer); net_buffer *_Dequeue(bool clone); void _Clear(); @@ -141,15 +142,22 @@ DECL_DATAGRAM_SOCKET(inline status_t)::_Enqueue(net_buffer *buffer) } -DECL_DATAGRAM_SOCKET(inline status_t)::EnqueueClone(net_buffer *_buffer) +DECL_DATAGRAM_SOCKET(inline status_t)::SocketEnqueue(net_buffer *_buffer) { AutoLocker _(fLock); - return _EnqueueClone(_buffer); + return _SocketEnqueue(_buffer); } -DECL_DATAGRAM_SOCKET(inline status_t)::_EnqueueClone(net_buffer *_buffer) +DECL_DATAGRAM_SOCKET(inline status_t)::_SocketEnqueue(net_buffer *_buffer) { + if (_buffer->flags & MSG_BCAST) { + // only deliver datagrams sent to a broadcast address + // to sockets with SO_BROADCAST on. + if (!(fSocket->options & SO_BROADCAST)) + return B_OK; + } + net_buffer *buffer = ModuleBundle::Buffer()->clone(_buffer, false); if (buffer == NULL) return B_NO_MEMORY; diff --git a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp index 42766a7090..7979f679e0 100644 --- a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp +++ b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp @@ -31,9 +31,14 @@ //#define TRACE_IPV4 #ifdef TRACE_IPV4 -# define TRACE(x) dprintf x +# define TRACE(format, args...) \ + dprintf("IPv4 [%llu] " format "\n", system_time() , ##args) +# define TRACE_SK(protocol, format, args...) \ + dprintf("IPv4 [%llu] %p " format "\n", system_time(), \ + protocol , ##args) #else -# define TRACE(x) ; +# define TRACE(args...) do { } while (0) +# define TRACE_SK(args...) do { } while (0) #endif struct ipv4_header { @@ -211,17 +216,17 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer, return B_OK; } - TRACE((" previous: %p, next: %p\n", previous, next)); + TRACE(" previous: %p, next: %p", previous, next); // If we have parts of the data already, truncate as needed if (previous != NULL && previous->fragment.end > start) { - TRACE((" remove header %d bytes\n", previous->fragment.end - start)); + TRACE(" remove header %d bytes", previous->fragment.end - start); gBufferModule->remove_header(buffer, previous->fragment.end - start); start = previous->fragment.end; } if (next != NULL && next->fragment.start < end) { - TRACE((" remove trailer %d bytes\n", next->fragment.start - end)); + TRACE(" remove trailer %d bytes", next->fragment.start - end); gBufferModule->remove_trailer(buffer, next->fragment.start - end); end = next->fragment.start; } @@ -238,7 +243,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer, buffer->fragment.end = end; status_t status = gBufferModule->merge(buffer, previous, false); - TRACE((" merge previous: %s\n", strerror(status))); + TRACE(" merge previous: %s", strerror(status)); if (status < B_OK) { fFragments.Insert(next, previous); return status; @@ -254,7 +259,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer, fBytesLeft -= IP_MAXPACKET - end; } - TRACE((" hole length: %d\n", (int)fBytesLeft)); + TRACE(" hole length: %d", (int)fBytesLeft); return B_OK; } else if (next != NULL && next->fragment.start == end) { @@ -264,7 +269,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer, buffer->fragment.end = next->fragment.end; status_t status = gBufferModule->merge(buffer, next, true); - TRACE((" merge next: %s\n", strerror(status))); + TRACE(" merge next: %s", strerror(status)); if (status < B_OK) { fFragments.Insert((net_buffer *)previous->link.next, next); return status; @@ -280,14 +285,14 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer, fBytesLeft -= IP_MAXPACKET - end; } - TRACE((" hole length: %d\n", (int)fBytesLeft)); + TRACE(" hole length: %d", (int)fBytesLeft); return B_OK; } // We couldn't merge the fragments, so we need to add it as is - TRACE((" new fragment: %p, bytes %d-%d\n", buffer, start, end)); + TRACE(" new fragment: %p, bytes %d-%d", buffer, start, end); buffer->fragment.start = start; buffer->fragment.end = end; @@ -301,7 +306,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer, fBytesLeft -= IP_MAXPACKET - end; } - TRACE((" hole length: %d\n", (int)fBytesLeft)); + TRACE(" hole length: %d", (int)fBytesLeft); return B_OK; } @@ -373,7 +378,7 @@ FragmentPacket::Hash(void *_packet, const void *_key, uint32 range) FragmentPacket::StaleTimer(struct net_timer *timer, void *data) { FragmentPacket *packet = (FragmentPacket *)data; - TRACE(("Assembling FragmentPacket %p timed out!\n", packet)); + TRACE("Assembling FragmentPacket %p timed out!", packet); BenaphoreLocker locker(&sFragmentLock); @@ -464,8 +469,8 @@ reassemble_fragments(const ipv4_header &header, net_buffer **_buffer) uint16 end = start + header.TotalLength() - header.HeaderLength(); bool lastFragment = (fragmentOffset & IP_MORE_FRAGMENTS) == 0; - TRACE((" Received IPv4 %sfragment of size %d, offset %d.\n", - lastFragment ? "last ": "", end - start, start)); + TRACE(" Received IPv4 %sfragment of size %d, offset %d.", + lastFragment ? "last ": "", end - start, start); // Remove header unless this is the first fragment if (start != 0) @@ -500,8 +505,7 @@ static status_t send_fragments(ipv4_protocol *protocol, struct net_route *route, net_buffer *buffer, uint32 mtu) { - TRACE(("ipv4 needs to fragment (size %lu, MTU %lu)...\n", - buffer->size, mtu)); + TRACE_SK(protocol, "SendFragments(%lu bytes, mtu %lu)", buffer->size, mtu); NetBufferHeaderReader originalHeader(buffer); if (originalHeader.Status() < B_OK) @@ -581,7 +585,7 @@ raw_receive_data(net_buffer *buffer) { BenaphoreLocker locker(sRawSocketsLock); - TRACE(("ipv4:raw_receive_data(): protocol %i\n", buffer->protocol)); + TRACE("RawReceiveData(%i)", buffer->protocol); RawSocketList::Iterator iterator = sRawSockets.GetIterator(); @@ -589,7 +593,7 @@ raw_receive_data(net_buffer *buffer) RawSocket *raw = iterator.Next(); if (raw->Socket()->protocol == buffer->protocol) - raw->EnqueueClone(buffer); + raw->SocketEnqueue(buffer); } } @@ -662,6 +666,8 @@ ipv4_open(net_protocol *_protocol) return status; } + TRACE_SK(protocol, "Open()"); + protocol->raw = raw; BenaphoreLocker locker(sRawSocketsLock); @@ -678,6 +684,8 @@ ipv4_close(net_protocol *_protocol) if (raw == NULL) return B_ERROR; + TRACE_SK(protocol, "Close()"); + BenaphoreLocker locker(sRawSocketsLock); sRawSockets.Remove(raw); delete raw; @@ -859,7 +867,8 @@ ipv4_send_routed_data(net_protocol *_protocol, struct net_route *route, ipv4_protocol *protocol = (ipv4_protocol *)_protocol; net_interface *interface = route->interface; - TRACE(("someone tries to send some actual routed data!\n")); + TRACE_SK(protocol, "SendRoutedData(%p, %p [%ld bytes])", route, buffer, + buffer->size); sockaddr_in &source = *(sockaddr_in *)&buffer->source; sockaddr_in &destination = *(sockaddr_in *)&buffer->destination; @@ -908,12 +917,12 @@ ipv4_send_routed_data(net_protocol *_protocol, struct net_route *route, *IPChecksumField(buffer) = gBufferModule->checksum(buffer, 0, sizeof(ipv4_header), true); - TRACE(("header chksum: %ld, buffer checksum: %ld\n", + TRACE_SK(protocol, " SendRoutedData(): header chksum: %ld, buffer checksum: %ld", gBufferModule->checksum(buffer, 0, sizeof(ipv4_header), true), - gBufferModule->checksum(buffer, 0, buffer->size, true))); + gBufferModule->checksum(buffer, 0, buffer->size, true)); - TRACE(("destination-IP: buffer=%p addr=%p %08lx\n", buffer, &buffer->destination, - ntohl(destination.sin_addr.s_addr))); + TRACE_SK(protocol, " SendRoutedData(): destination: %08lx", + ntohl(destination.sin_addr.s_addr)); uint32 mtu = route->mtu ? route->mtu : interface->mtu; if (buffer->size > mtu) { @@ -928,7 +937,17 @@ ipv4_send_routed_data(net_protocol *_protocol, struct net_route *route, status_t ipv4_send_data(net_protocol *protocol, net_buffer *buffer) { - TRACE(("someone tries to send some actual data!\n")); + TRACE_SK(protocol, "SendData(%p [%ld bytes])", buffer, buffer->size); + + sockaddr_in &destination = *(sockaddr_in *)&buffer->destination; + + if (destination.sin_len == 0 || destination.sin_addr.s_addr == INADDR_ANY) + return EDESTADDRREQ; + else if (destination.sin_addr.s_addr == INADDR_BROADCAST) { + // TODO check for local broadcast addresses as well? + if (protocol && !(protocol->socket->options & SO_BROADCAST)) + return B_BAD_VALUE; + } net_route *route = NULL; status_t status = sDatalinkModule->get_buffer_route(sDomain, buffer, @@ -958,7 +977,8 @@ ipv4_read_data(net_protocol *_protocol, size_t numBytes, uint32 flags, if (raw == NULL) return B_ERROR; - TRACE(("read is waiting for data...\n")); + TRACE_SK(protocol, "ReadData(%lu, 0x%lx)", numBytes, flags); + return raw->SocketDequeue(flags, _buffer); } @@ -1003,7 +1023,7 @@ ipv4_get_mtu(net_protocol *protocol, const struct sockaddr *address) status_t ipv4_receive_data(net_buffer *buffer) { - TRACE(("IPv4 received a packet (%p) of %ld size!\n", buffer, buffer->size)); + TRACE("ReceiveData(%p [%ld bytes])", buffer, buffer->size); NetBufferHeaderReader bufferHeader(buffer); if (bufferHeader.Status() < B_OK) @@ -1038,10 +1058,10 @@ ipv4_receive_data(net_buffer *buffer) // test if the packet is really for us uint32 matchedAddressType; - if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination, + if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination, &buffer->interface, &matchedAddressType)) { - TRACE(("this packet was not for us %lx -> %lx\n", - ntohl(header.source), ntohl(header.destination))); + TRACE(" ReceiveData(): packet was not for us %lx -> %lx", + ntohl(header.source), ntohl(header.destination)); return B_ERROR; } if (matchedAddressType != 0) { @@ -1061,15 +1081,15 @@ ipv4_receive_data(net_buffer *buffer) if ((fragmentOffset & IP_MORE_FRAGMENTS) != 0 || (fragmentOffset & IP_FRAGMENT_OFFSET_MASK) != 0) { // this is a fragment - TRACE((" Found a Fragment!\n")); + TRACE(" ReceiveData(): Found a Fragment!"); status = reassemble_fragments(header, &buffer); - TRACE((" -> %s!\n", strerror(status))); + TRACE(" ReceiveData(): -> %s", strerror(status)); if (status != B_OK) return status; if (buffer == NULL) { // buffer was put into fragment packet - TRACE((" Not yet assembled...\n")); + TRACE(" ReceiveData(): Not yet assembled."); return B_OK; } } diff --git a/src/add-ons/kernel/network/protocols/udp/udp.cpp b/src/add-ons/kernel/network/protocols/udp/udp.cpp index 159ef15f20..c665e8f01e 100644 --- a/src/add-ons/kernel/network/protocols/udp/udp.cpp +++ b/src/add-ons/kernel/network/protocols/udp/udp.cpp @@ -938,7 +938,7 @@ UdpEndpoint::StoreData(net_buffer *buffer) { TRACE_EP("StoreData(%p [%ld bytes])", buffer, buffer->size); - return EnqueueClone(buffer); + return SocketEnqueue(buffer); } diff --git a/src/add-ons/kernel/network/stack/link.cpp b/src/add-ons/kernel/network/stack/link.cpp index 0e5a316eaf..43bb2f2469 100644 --- a/src/add-ons/kernel/network/stack/link.cpp +++ b/src/add-ons/kernel/network/stack/link.cpp @@ -169,7 +169,7 @@ LinkProtocol::_Unregister() status_t LinkProtocol::_MonitorData(net_device_monitor *monitor, net_buffer *packet) { - return ((LinkProtocol *)monitor->cookie)->EnqueueClone(packet); + return ((LinkProtocol *)monitor->cookie)->SocketEnqueue(packet); }