* Now we should also support link layer and INADDR_BROADCAST broadcasts again
correctly. * This should finally fix ticket #6454, but I keep it open until it's confirmed. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38365 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1581,6 +1581,7 @@ ipv4_receive_data(net_buffer* buffer)
|
|||||||
// lower layers notion of broadcast or multicast have no relevance to us
|
// lower layers notion of broadcast or multicast have no relevance to us
|
||||||
// other than deciding whether to send an ICMP error
|
// other than deciding whether to send an ICMP error
|
||||||
bool wasMulticast = (buffer->flags & (MSG_BCAST | MSG_MCAST)) != 0;
|
bool wasMulticast = (buffer->flags & (MSG_BCAST | MSG_MCAST)) != 0;
|
||||||
|
bool notForUs = false;
|
||||||
buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
|
buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
|
||||||
|
|
||||||
sockaddr_in destination;
|
sockaddr_in destination;
|
||||||
@@ -1590,29 +1591,33 @@ ipv4_receive_data(net_buffer* buffer)
|
|||||||
buffer->flags |= MSG_BCAST;
|
buffer->flags |= MSG_BCAST;
|
||||||
|
|
||||||
// Find first interface with a matching family
|
// Find first interface with a matching family
|
||||||
// TODO: support for ethernet broadcasts!
|
if (!sDatalinkModule->is_local_link_address(sDomain, true,
|
||||||
// TODO: we might need to send it to all interfaces if it's an ethernet
|
buffer->destination, &buffer->interface_address))
|
||||||
// broadcast as well!
|
notForUs = wasMulticast;
|
||||||
sDatalinkModule->is_local_link_address(sDomain, true,
|
|
||||||
buffer->destination, &buffer->interface_address);
|
|
||||||
} else if (IN_MULTICAST(ntohl(header.destination))) {
|
} else if (IN_MULTICAST(ntohl(header.destination))) {
|
||||||
buffer->flags |= MSG_MCAST;
|
buffer->flags |= MSG_MCAST;
|
||||||
// TODO: must set buffer->interface_address!
|
|
||||||
} else {
|
} else {
|
||||||
uint32 matchedAddressType = 0;
|
uint32 matchedAddressType = 0;
|
||||||
|
|
||||||
// test if the packet is really for us
|
// test if the packet is really for us
|
||||||
if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
|
if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
|
||||||
&buffer->interface_address, &matchedAddressType)) {
|
&buffer->interface_address, &matchedAddressType)
|
||||||
sDatalinkModule->is_local_link_address(sDomain, true,
|
&& !sDatalinkModule->is_local_link_address(sDomain, true,
|
||||||
buffer->destination, &buffer->interface_address);
|
buffer->destination, &buffer->interface_address)) {
|
||||||
|
notForUs = true;
|
||||||
} else {
|
} else {
|
||||||
// copy over special address types (MSG_BCAST or MSG_MCAST):
|
// copy over special address types (MSG_BCAST or MSG_MCAST):
|
||||||
buffer->flags |= matchedAddressType;
|
buffer->flags |= matchedAddressType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer->interface_address == NULL) {
|
// set net_buffer's source/destination address
|
||||||
|
fill_sockaddr_in((struct sockaddr_in*)buffer->source, header.source);
|
||||||
|
memcpy(buffer->destination, &destination, sizeof(sockaddr_in));
|
||||||
|
|
||||||
|
buffer->protocol = header.protocol;
|
||||||
|
|
||||||
|
if (notForUs) {
|
||||||
TRACE(" ipv4_receive_data(): packet was not for us %x -> %x",
|
TRACE(" ipv4_receive_data(): packet was not for us %x -> %x",
|
||||||
ntohl(header.source), ntohl(header.destination));
|
ntohl(header.source), ntohl(header.destination));
|
||||||
|
|
||||||
@@ -1625,12 +1630,6 @@ ipv4_receive_data(net_buffer* buffer)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set net_buffer's source/destination address
|
|
||||||
fill_sockaddr_in((struct sockaddr_in*)buffer->source, header.source);
|
|
||||||
memcpy(buffer->destination, &destination, sizeof(sockaddr_in));
|
|
||||||
|
|
||||||
buffer->protocol = header.protocol;
|
|
||||||
|
|
||||||
// remove any trailing/padding data
|
// remove any trailing/padding data
|
||||||
status_t status = gBufferModule->trim(buffer, packetLength);
|
status_t status = gBufferModule->trim(buffer, packetLength);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
|
|||||||
@@ -234,8 +234,10 @@ public:
|
|||||||
static int DumpEndpoints(int argc, char *argv[]);
|
static int DumpEndpoints(int argc, char *argv[]);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UdpDomainSupport* _GetDomain(net_domain *domain, bool create);
|
inline net_domain* _GetDomain(net_buffer* buffer);
|
||||||
UdpDomainSupport* _GetDomain(net_buffer* buffer);
|
UdpDomainSupport* _GetDomainSupport(net_domain* domain,
|
||||||
|
bool create);
|
||||||
|
UdpDomainSupport* _GetDomainSupport(net_buffer* buffer);
|
||||||
|
|
||||||
mutex fLock;
|
mutex fLock;
|
||||||
status_t fStatus;
|
status_t fStatus;
|
||||||
@@ -504,23 +506,21 @@ UdpDomainSupport::_FindActiveEndpoint(const sockaddr *ourAddress,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
UdpDomainSupport::_DemuxBroadcast(net_buffer *buffer)
|
UdpDomainSupport::_DemuxBroadcast(net_buffer* buffer)
|
||||||
{
|
{
|
||||||
sockaddr *peerAddr = buffer->source;
|
sockaddr* peerAddr = buffer->source;
|
||||||
sockaddr *broadcastAddr = buffer->destination;
|
sockaddr* broadcastAddr = buffer->destination;
|
||||||
sockaddr *mask = NULL;
|
|
||||||
if (buffer->interface_address != NULL)
|
|
||||||
mask = (sockaddr *)buffer->interface_address->mask;
|
|
||||||
|
|
||||||
TRACE_DOMAIN("_DemuxBroadcast(%p)", buffer);
|
|
||||||
|
|
||||||
uint16 incomingPort = AddressModule()->get_port(broadcastAddr);
|
uint16 incomingPort = AddressModule()->get_port(broadcastAddr);
|
||||||
|
|
||||||
EndpointTable::Iterator it = fActiveEndpoints.GetIterator();
|
sockaddr* mask = NULL;
|
||||||
|
if (buffer->interface_address != NULL)
|
||||||
|
mask = (sockaddr*)buffer->interface_address->mask;
|
||||||
|
|
||||||
while (it.HasNext()) {
|
TRACE_DOMAIN("_DemuxBroadcast(%p): mask %p\n", buffer, mask);
|
||||||
UdpEndpoint *endpoint = it.Next();
|
|
||||||
|
|
||||||
|
EndpointTable::Iterator iterator = fActiveEndpoints.GetIterator();
|
||||||
|
|
||||||
|
while (UdpEndpoint* endpoint = iterator.Next()) {
|
||||||
TRACE_DOMAIN(" _DemuxBroadcast(): checking endpoint %s...",
|
TRACE_DOMAIN(" _DemuxBroadcast(): checking endpoint %s...",
|
||||||
AddressString(fDomain, *endpoint->LocalAddress(), true).Data());
|
AddressString(fDomain, *endpoint->LocalAddress(), true).Data());
|
||||||
|
|
||||||
@@ -540,7 +540,7 @@ UdpDomainSupport::_DemuxBroadcast(net_buffer *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (endpoint->LocalAddress().MatchMasked(broadcastAddr, mask)
|
if (endpoint->LocalAddress().MatchMasked(broadcastAddr, mask)
|
||||||
|| endpoint->LocalAddress().IsEmpty(false)) {
|
|| mask == NULL || endpoint->LocalAddress().IsEmpty(false)) {
|
||||||
// address matches, dispatch to this endpoint:
|
// address matches, dispatch to this endpoint:
|
||||||
endpoint->StoreData(buffer);
|
endpoint->StoreData(buffer);
|
||||||
}
|
}
|
||||||
@@ -675,7 +675,7 @@ UdpEndpointManager::ReceiveData(net_buffer *buffer)
|
|||||||
{
|
{
|
||||||
TRACE_EPM("ReceiveData(%p [%" B_PRIu32 " bytes])", buffer, buffer->size);
|
TRACE_EPM("ReceiveData(%p [%" B_PRIu32 " bytes])", buffer, buffer->size);
|
||||||
|
|
||||||
UdpDomainSupport* domainSupport = _GetDomain(buffer);
|
UdpDomainSupport* domainSupport = _GetDomainSupport(buffer);
|
||||||
if (domainSupport == NULL) {
|
if (domainSupport == NULL) {
|
||||||
// we don't instantiate domain supports in the receiving path, as
|
// we don't instantiate domain supports in the receiving path, as
|
||||||
// we are only interested in delivering data to existing sockets.
|
// we are only interested in delivering data to existing sockets.
|
||||||
@@ -710,7 +710,7 @@ UdpEndpointManager::ReceiveError(status_t error, net_buffer* buffer)
|
|||||||
if (buffer->size < 4)
|
if (buffer->size < 4)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
UdpDomainSupport* domainSupport = _GetDomain(buffer);
|
UdpDomainSupport* domainSupport = _GetDomainSupport(buffer);
|
||||||
if (domainSupport == NULL) {
|
if (domainSupport == NULL) {
|
||||||
// we don't instantiate domain supports in the receiving path, as
|
// we don't instantiate domain supports in the receiving path, as
|
||||||
// we are only interested in delivering data to existing sockets.
|
// we are only interested in delivering data to existing sockets.
|
||||||
@@ -738,25 +738,23 @@ UdpEndpointManager::ReceiveError(status_t error, net_buffer* buffer)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
UdpEndpointManager::Deframe(net_buffer *buffer)
|
UdpEndpointManager::Deframe(net_buffer* buffer)
|
||||||
{
|
{
|
||||||
TRACE_EPM("Deframe(%p [%ld bytes])", buffer, buffer->size);
|
TRACE_EPM("Deframe(%p [%ld bytes])", buffer, buffer->size);
|
||||||
|
|
||||||
NetBufferHeaderReader<udp_header> bufferHeader(buffer);
|
NetBufferHeaderReader<udp_header> bufferHeader(buffer);
|
||||||
if (bufferHeader.Status() < B_OK)
|
if (bufferHeader.Status() != B_OK)
|
||||||
return bufferHeader.Status();
|
return bufferHeader.Status();
|
||||||
|
|
||||||
udp_header &header = bufferHeader.Data();
|
udp_header& header = bufferHeader.Data();
|
||||||
|
|
||||||
if (buffer->interface_address == NULL
|
net_domain* domain = _GetDomain(buffer);
|
||||||
|| buffer->interface_address->domain == NULL) {
|
if (domain == NULL) {
|
||||||
TRACE_EPM(" Deframe(): UDP packed dropped as there was no domain "
|
TRACE_EPM(" Deframe(): UDP packed dropped as there was no domain "
|
||||||
"specified (interface address %p).", buffer->interface_address);
|
"specified (interface address %p).", buffer->interface_address);
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
net_address_module_info* addressModule = domain->address_module;
|
||||||
net_domain *domain = buffer->interface_address->domain;
|
|
||||||
net_address_module_info *addressModule = domain->address_module;
|
|
||||||
|
|
||||||
SocketAddress source(addressModule, buffer->source);
|
SocketAddress source(addressModule, buffer->source);
|
||||||
SocketAddress destination(addressModule, buffer->destination);
|
SocketAddress destination(addressModule, buffer->destination);
|
||||||
@@ -799,7 +797,7 @@ UdpEndpointManager::OpenEndpoint(UdpEndpoint *endpoint)
|
|||||||
{
|
{
|
||||||
MutexLocker _(fLock);
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
UdpDomainSupport *domain = _GetDomain(endpoint->Domain(), true);
|
UdpDomainSupport* domain = _GetDomainSupport(endpoint->Domain(), true);
|
||||||
if (domain)
|
if (domain)
|
||||||
domain->Ref();
|
domain->Ref();
|
||||||
return domain;
|
return domain;
|
||||||
@@ -823,10 +821,23 @@ UdpEndpointManager::FreeEndpoint(UdpDomainSupport *domain)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
UdpDomainSupport *
|
inline net_domain*
|
||||||
UdpEndpointManager::_GetDomain(net_domain *domain, bool create)
|
UdpEndpointManager::_GetDomain(net_buffer* buffer)
|
||||||
{
|
{
|
||||||
UdpDomainList::Iterator it = fDomains.GetIterator();
|
if (buffer->interface_address != NULL)
|
||||||
|
return buffer->interface_address->domain;
|
||||||
|
|
||||||
|
return gStackModule->get_domain(buffer->destination->sa_family);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UdpDomainSupport*
|
||||||
|
UdpEndpointManager::_GetDomainSupport(net_domain* domain, bool create)
|
||||||
|
{
|
||||||
|
ASSERT_LOCKED_MUTEX(&fLock);
|
||||||
|
|
||||||
|
if (domain == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// TODO convert this into a Hashtable or install per-domain
|
// TODO convert this into a Hashtable or install per-domain
|
||||||
// receiver handlers that forward the requests to the
|
// receiver handlers that forward the requests to the
|
||||||
@@ -834,8 +845,8 @@ UdpEndpointManager::_GetDomain(net_domain *domain, bool create)
|
|||||||
// being constructed UdpDomainSupport could call
|
// being constructed UdpDomainSupport could call
|
||||||
// register_domain_receiving_protocol() with the right
|
// register_domain_receiving_protocol() with the right
|
||||||
// family.
|
// family.
|
||||||
while (it.HasNext()) {
|
UdpDomainList::Iterator iterator = fDomains.GetIterator();
|
||||||
UdpDomainSupport *domainSupport = it.Next();
|
while (UdpDomainSupport* domainSupport = iterator.Next()) {
|
||||||
if (domainSupport->Domain() == domain)
|
if (domainSupport->Domain() == domain)
|
||||||
return domainSupport;
|
return domainSupport;
|
||||||
}
|
}
|
||||||
@@ -843,8 +854,8 @@ UdpEndpointManager::_GetDomain(net_domain *domain, bool create)
|
|||||||
if (!create)
|
if (!create)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
UdpDomainSupport *domainSupport =
|
UdpDomainSupport* domainSupport
|
||||||
new (std::nothrow) UdpDomainSupport(domain);
|
= new (std::nothrow) UdpDomainSupport(domain);
|
||||||
if (domainSupport == NULL || domainSupport->Init() < B_OK) {
|
if (domainSupport == NULL || domainSupport->Init() < B_OK) {
|
||||||
delete domainSupport;
|
delete domainSupport;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -855,14 +866,16 @@ UdpEndpointManager::_GetDomain(net_domain *domain, bool create)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Retrieves the UdpDomainSupport object responsible for this buffer, if the
|
||||||
|
domain can be determined. This is only successful if the domain support is
|
||||||
|
already existing, ie. there must already be an endpoint for the domain.
|
||||||
|
*/
|
||||||
UdpDomainSupport*
|
UdpDomainSupport*
|
||||||
UdpEndpointManager::_GetDomain(net_buffer* buffer)
|
UdpEndpointManager::_GetDomainSupport(net_buffer* buffer)
|
||||||
{
|
{
|
||||||
if (buffer->interface_address == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
MutexLocker _(fLock);
|
MutexLocker _(fLock);
|
||||||
return _GetDomain(buffer->interface_address->domain, false);
|
|
||||||
|
return _GetDomainSupport(_GetDomain(buffer), false);
|
||||||
// TODO: we don't want to hold to the manager's lock during the
|
// TODO: we don't want to hold to the manager's lock during the
|
||||||
// whole RX path, we may not hold an endpoint's lock with the
|
// whole RX path, we may not hold an endpoint's lock with the
|
||||||
// manager lock held.
|
// manager lock held.
|
||||||
|
|||||||
Reference in New Issue
Block a user