* 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
This commit is contained in:
Axel Dörfler 2010-07-21 13:11:58 +00:00
parent 1978fb81ee
commit aea00dc3bc
1 changed files with 68 additions and 50 deletions

View File

@ -69,7 +69,7 @@ struct ipv4_packet_key {
class FragmentPacket { class FragmentPacket {
public: public:
FragmentPacket(const ipv4_packet_key &key); FragmentPacket(const ipv4_packet_key& key);
~FragmentPacket(); ~FragmentPacket();
status_t AddFragment(uint16 start, uint16 end, status_t AddFragment(uint16 start, uint16 end,
@ -80,7 +80,8 @@ public:
{ return fReceivedLastFragment { return fReceivedLastFragment
&& fBytesLeft == 0; } && fBytesLeft == 0; }
static uint32 Hash(void* _packet, const void* _key, uint32 range); static uint32 Hash(void* _packet, const void* _key,
uint32 range);
static int Compare(void* _packet, const void* _key); static int Compare(void* _packet, const void* _key);
static int32 NextOffset() static int32 NextOffset()
{ return offsetof(FragmentPacket, fNext); } { return offsetof(FragmentPacket, fNext); }
@ -133,7 +134,7 @@ struct ipv4_protocol : net_protocol {
{ {
} }
RawSocket *raw; RawSocket* raw;
uint8 service_type; uint8 service_type;
uint8 time_to_live; uint8 time_to_live;
uint8 multicast_time_to_live; uint8 multicast_time_to_live;
@ -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, deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
bool deliverToRaw) bool deliverToRaw)
{ {
if (module->deliver_data == NULL) if (module->deliver_data == NULL)
return B_OK; return false;
MutexLocker _(sMulticastGroupsLock); MutexLocker _(sMulticastGroupsLock);
@ -674,32 +678,41 @@ deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair( MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair(
&multicastAddr->sin_addr, buffer->interface->index)); &multicastAddr->sin_addr, buffer->interface->index));
size_t count = 0;
while (it.HasNext()) { while (it.HasNext()) {
IPv4GroupInterface* state = it.Next(); 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; continue;
if (state->FilterAccepts(buffer)) { if (state->FilterAccepts(buffer)) {
// as Multicast filters are installed with an IPv4 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 // reference, we need to go and find the appropriate instance
// related to the 'receiving protocol' with module 'module'. // related to the 'receiving protocol' with module 'module'.
net_protocol* protocol net_protocol* protocol = ipProtocol->socket->first_protocol;
= state->Parent()->Socket()->socket->first_protocol;
while (protocol != NULL && protocol->module != module) while (protocol != NULL && protocol->module != module)
protocol = protocol->next; protocol = protocol->next;
}
if (protocol != NULL) if (protocol != NULL) {
module->deliver_data(protocol, buffer); 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. Returns \c true if there was any receiver, \c false if not.
*/ */
static bool static bool
@ -712,25 +725,28 @@ raw_receive_data(net_buffer* buffer)
TRACE("RawReceiveData(%i)", buffer->protocol); 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 // we need to call deliver_multicast here separately as
// buffer still has the IP header, and it won't in the // buffer still has the IP header, and it won't in the
// next call. This isn't very optimized but works for now. // next call. This isn't very optimized but works for now.
// A better solution would be to hold separate hash tables // A better solution would be to hold separate hash tables
// and lists for RAW and non-RAW sockets. // and lists for RAW and non-RAW sockets.
deliver_multicast(&gIPv4Module, buffer, true); return deliver_multicast(&gIPv4Module, buffer, true);
} else { }
RawSocketList::Iterator iterator = sRawSockets.GetIterator(); RawSocketList::Iterator iterator = sRawSockets.GetIterator();
size_t count = 0;
while (iterator.HasNext()) { while (iterator.HasNext()) {
RawSocket* raw = iterator.Next(); RawSocket* raw = iterator.Next();
if (raw->Socket()->protocol == buffer->protocol) if (raw->Socket()->protocol == buffer->protocol) {
raw->SocketEnqueue(buffer); 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) { 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 // model be a little different from the unicast one. We deliver
// this frame directly to all sockets registered with interest // this frame directly to all sockets registered with interest
// for this multicast group. // 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); return module->receive_data(buffer);