fixed the reception of multicast frames by RAW sockets.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20696 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos
2007-04-15 07:46:30 +00:00
parent 6a60618094
commit 342824b6da
@@ -121,7 +121,8 @@ public:
MulticastGroup(const in_addr &address); MulticastGroup(const in_addr &address);
status_t Deliver(net_protocol_module_info *module, net_buffer *buffer); status_t Deliver(net_protocol_module_info *module, net_buffer *buffer,
bool raw);
void Add(Link *link); void Add(Link *link);
void Remove(Link *link); void Remove(Link *link);
@@ -436,7 +437,8 @@ MulticastGroup::MulticastGroup(const in_addr &address)
status_t status_t
MulticastGroup::Deliver(net_protocol_module_info *module, net_buffer *buffer) MulticastGroup::Deliver(net_protocol_module_info *module, net_buffer *buffer,
bool deliverToRaw)
{ {
if (module->deliver_data == NULL) if (module->deliver_data == NULL)
return B_OK; return B_OK;
@@ -446,8 +448,25 @@ MulticastGroup::Deliver(net_protocol_module_info *module, net_buffer *buffer)
while (iterator.HasNext()) { while (iterator.HasNext()) {
Link *link = iterator.Next(); Link *link = iterator.Next();
if (link->group->FilterAccepts(buffer)) // we are pretty sure of this cast since multicast filters
module->deliver_data(link->group->Socket(), buffer); // are installed with the IPv4 protocol reference
ipv4_protocol *protocol = (ipv4_protocol *)link->group->Socket();
if (deliverToRaw && protocol->raw == NULL)
continue;
if (link->group->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 *proto = link->group->Socket();
while (proto && proto->module != module)
proto = proto->next;
if (proto)
module->deliver_data(proto, buffer);
}
} }
return B_OK; return B_OK;
@@ -688,13 +707,39 @@ send_fragments(ipv4_protocol *protocol, struct net_route *route,
} }
static status_t
deliver_multicast(net_protocol_module_info *module, net_buffer *buffer,
bool deliverToRaw)
{
BenaphoreLocker _(sMulticastGroupsLock);
MulticastGroup *group = (MulticastGroup *)hash_lookup(sMulticastGroups,
&buffer->destination);
if (group == NULL)
return B_OK;
return group->Deliver(module, buffer, deliverToRaw);
}
static void static void
raw_receive_data(net_buffer *buffer) raw_receive_data(net_buffer *buffer)
{ {
BenaphoreLocker locker(sRawSocketsLock); BenaphoreLocker locker(sRawSocketsLock);
if (sRawSockets.IsEmpty())
return;
TRACE("RawReceiveData(%i)", buffer->protocol); TRACE("RawReceiveData(%i)", buffer->protocol);
if (buffer->flags & MSG_MCAST) {
// 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(); RawSocketList::Iterator iterator = sRawSockets.GetIterator();
while (iterator.HasNext()) { while (iterator.HasNext()) {
@@ -704,22 +749,6 @@ raw_receive_data(net_buffer *buffer)
raw->SocketEnqueue(buffer); raw->SocketEnqueue(buffer);
} }
} }
static status_t
deliver_multicast(net_protocol_module_info *module, net_buffer *buffer)
{
BenaphoreLocker _(sMulticastGroupsLock);
MulticastGroup *group = (MulticastGroup *)hash_lookup(sMulticastGroups,
&buffer->destination);
if (group == NULL)
return B_OK;
// TODO fix sending multicast to RAW sockets, right now
// they are receiving the frames without the IP header
return group->Deliver(module, buffer);
} }
@@ -1499,7 +1528,6 @@ ipv4_receive_data(net_buffer *buffer)
// we must no longer access bufferHeader or header anymore after // we must no longer access bufferHeader or header anymore after
// this point // this point
if (!(buffer->flags & MSG_MCAST))
raw_receive_data(buffer); raw_receive_data(buffer);
gBufferModule->remove_header(buffer, headerLength); gBufferModule->remove_header(buffer, headerLength);
@@ -1517,7 +1545,7 @@ ipv4_receive_data(net_buffer *buffer)
// 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); return deliver_multicast(module, buffer, false);
} }
return module->receive_data(buffer); return module->receive_data(buffer);