From aea00dc3bcf831cc364f4f2d41bd39028375dfef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 21 Jul 2010 13:11:58 +0000 Subject: [PATCH] * deliver_multicast() now returns whether or not it delivered the buffer, instead of always returning B_OK. * deliver_multicast() now takes the protocol restriction of a raw socket into account. * raw_receive_data() now correctly returns whether a buffer was delivered (due to the protocol restriction, this wasn't the case before). * ipv4_receive_data() leaked all multicast buffers. * Some minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37648 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/network/protocols/ipv4/ipv4.cpp | 118 ++++++++++-------- 1 file changed, 68 insertions(+), 50 deletions(-) diff --git a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp index 9b7bbbb33e..88963875e3 100644 --- a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp +++ b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp @@ -69,37 +69,38 @@ struct ipv4_packet_key { class FragmentPacket { public: - FragmentPacket(const ipv4_packet_key &key); - ~FragmentPacket(); + FragmentPacket(const ipv4_packet_key& key); + ~FragmentPacket(); - status_t AddFragment(uint16 start, uint16 end, - net_buffer* buffer, bool lastFragment); - status_t Reassemble(net_buffer* to); + status_t AddFragment(uint16 start, uint16 end, + net_buffer* buffer, bool lastFragment); + status_t Reassemble(net_buffer* to); - bool IsComplete() const - { return fReceivedLastFragment - && fBytesLeft == 0; } + bool IsComplete() const + { return fReceivedLastFragment + && fBytesLeft == 0; } - static uint32 Hash(void* _packet, const void* _key, uint32 range); - static int Compare(void* _packet, const void* _key); - static int32 NextOffset() - { return offsetof(FragmentPacket, fNext); } - static void StaleTimer(struct net_timer* timer, void* data); + static uint32 Hash(void* _packet, const void* _key, + uint32 range); + static int Compare(void* _packet, const void* _key); + static int32 NextOffset() + { return offsetof(FragmentPacket, fNext); } + static void StaleTimer(struct net_timer* timer, void* data); private: - FragmentPacket* fNext; + FragmentPacket* fNext; struct ipv4_packet_key fKey; - bool fReceivedLastFragment; - int32 fBytesLeft; - FragmentList fFragments; - net_timer fTimer; + bool fReceivedLastFragment; + int32 fBytesLeft; + FragmentList fFragments; + net_timer fTimer; }; class RawSocket : public DoublyLinkedListLinkImpl, public DatagramSocket<> { public: - RawSocket(net_socket* socket); + RawSocket(net_socket* socket); }; typedef DoublyLinkedList RawSocketList; @@ -133,14 +134,14 @@ struct ipv4_protocol : net_protocol { { } - RawSocket *raw; - uint8 service_type; - uint8 time_to_live; - uint8 multicast_time_to_live; - uint32 flags; - struct sockaddr* interface_address; // for IP_MULTICAST_IF + RawSocket* raw; + uint8 service_type; + uint8 time_to_live; + uint8 multicast_time_to_live; + uint32 flags; + struct sockaddr* interface_address; // for IP_MULTICAST_IF - IPv4MulticastFilter multicast_filter; + IPv4MulticastFilter multicast_filter; }; // protocol flags @@ -660,12 +661,15 @@ send_fragments(ipv4_protocol* protocol, struct net_route* route, } -static status_t +/*! Delivers the provided \a buffer to all listeners of this multicast group. + Does not take over ownership of the buffer. +*/ +static bool deliver_multicast(net_protocol_module_info* module, net_buffer* buffer, bool deliverToRaw) { if (module->deliver_data == NULL) - return B_OK; + return false; MutexLocker _(sMulticastGroupsLock); @@ -674,32 +678,41 @@ deliver_multicast(net_protocol_module_info* module, net_buffer* buffer, MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair( &multicastAddr->sin_addr, buffer->interface->index)); + size_t count = 0; + while (it.HasNext()) { IPv4GroupInterface* state = it.Next(); - if (deliverToRaw && state->Parent()->Socket()->raw == NULL) + ipv4_protocol* ipProtocol = state->Parent()->Socket(); + if (deliverToRaw && (ipProtocol->raw == NULL + || ipProtocol->socket->protocol != buffer->protocol)) continue; if (state->FilterAccepts(buffer)) { - // as Multicast filters are installed with an IPv4 protocol - // reference, we need to go and find the appropriate instance - // related to the 'receiving protocol' with module 'module'. - net_protocol* protocol - = state->Parent()->Socket()->socket->first_protocol; + net_protocol* protocol = ipProtocol; + if (protocol->module != module) { + // as multicast filters are installed with an IPv4 protocol + // reference, we need to go and find the appropriate instance + // related to the 'receiving protocol' with module 'module'. + net_protocol* protocol = ipProtocol->socket->first_protocol; - while (protocol != NULL && protocol->module != module) - protocol = protocol->next; + while (protocol != NULL && protocol->module != module) + protocol = protocol->next; + } - if (protocol != NULL) + if (protocol != NULL) { module->deliver_data(protocol, buffer); + count++; + } } } - return B_OK; + return count > 0; } -/*! Delivers the buffer to all listening raw sockets. +/*! Delivers the buffer to all listening raw sockets without taking ownership of + the provided \a buffer. Returns \c true if there was any receiver, \c false if not. */ static bool @@ -712,25 +725,28 @@ raw_receive_data(net_buffer* buffer) TRACE("RawReceiveData(%i)", buffer->protocol); - if (buffer->flags & MSG_MCAST) { + if ((buffer->flags & MSG_MCAST) != 0) { // we need to call deliver_multicast here separately as // buffer still has the IP header, and it won't in the // next call. This isn't very optimized but works for now. // A better solution would be to hold separate hash tables // and lists for RAW and non-RAW sockets. - deliver_multicast(&gIPv4Module, buffer, true); - } else { - RawSocketList::Iterator iterator = sRawSockets.GetIterator(); + return deliver_multicast(&gIPv4Module, buffer, true); + } + + RawSocketList::Iterator iterator = sRawSockets.GetIterator(); + size_t count = 0; - while (iterator.HasNext()) { - RawSocket* raw = iterator.Next(); + while (iterator.HasNext()) { + RawSocket* raw = iterator.Next(); - if (raw->Socket()->protocol == buffer->protocol) - raw->SocketEnqueue(buffer); + if (raw->Socket()->protocol == buffer->protocol) { + raw->SocketEnqueue(buffer); + count++; } } - return true; + return count > 0; } @@ -1637,11 +1653,13 @@ ipv4_receive_data(net_buffer* buffer) } if ((buffer->flags & MSG_MCAST) != 0) { - // Unfortunely historical reasons dictate that the IP multicast + // Unfortunately historical reasons dictate that the IP multicast // model be a little different from the unicast one. We deliver // this frame directly to all sockets registered with interest // for this multicast group. - return deliver_multicast(module, buffer, false); + deliver_multicast(module, buffer, false); + gBufferModule->free(buffer); + return B_OK; } return module->receive_data(buffer);