* 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
|
||||
// other than deciding whether to send an ICMP error
|
||||
bool wasMulticast = (buffer->flags & (MSG_BCAST | MSG_MCAST)) != 0;
|
||||
bool notForUs = false;
|
||||
buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
|
||||
|
||||
sockaddr_in destination;
|
||||
@@ -1590,29 +1591,33 @@ ipv4_receive_data(net_buffer* buffer)
|
||||
buffer->flags |= MSG_BCAST;
|
||||
|
||||
// Find first interface with a matching family
|
||||
// TODO: support for ethernet broadcasts!
|
||||
// TODO: we might need to send it to all interfaces if it's an ethernet
|
||||
// broadcast as well!
|
||||
sDatalinkModule->is_local_link_address(sDomain, true,
|
||||
buffer->destination, &buffer->interface_address);
|
||||
if (!sDatalinkModule->is_local_link_address(sDomain, true,
|
||||
buffer->destination, &buffer->interface_address))
|
||||
notForUs = wasMulticast;
|
||||
} else if (IN_MULTICAST(ntohl(header.destination))) {
|
||||
buffer->flags |= MSG_MCAST;
|
||||
// TODO: must set buffer->interface_address!
|
||||
} else {
|
||||
uint32 matchedAddressType = 0;
|
||||
|
||||
// test if the packet is really for us
|
||||
if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
|
||||
&buffer->interface_address, &matchedAddressType)) {
|
||||
sDatalinkModule->is_local_link_address(sDomain, true,
|
||||
buffer->destination, &buffer->interface_address);
|
||||
&buffer->interface_address, &matchedAddressType)
|
||||
&& !sDatalinkModule->is_local_link_address(sDomain, true,
|
||||
buffer->destination, &buffer->interface_address)) {
|
||||
notForUs = true;
|
||||
} else {
|
||||
// copy over special address types (MSG_BCAST or MSG_MCAST):
|
||||
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",
|
||||
ntohl(header.source), ntohl(header.destination));
|
||||
|
||||
@@ -1625,12 +1630,6 @@ ipv4_receive_data(net_buffer* buffer)
|
||||
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
|
||||
status_t status = gBufferModule->trim(buffer, packetLength);
|
||||
if (status != B_OK)
|
||||
|
||||
@@ -234,8 +234,10 @@ public:
|
||||
static int DumpEndpoints(int argc, char *argv[]);
|
||||
|
||||
private:
|
||||
UdpDomainSupport* _GetDomain(net_domain *domain, bool create);
|
||||
UdpDomainSupport* _GetDomain(net_buffer* buffer);
|
||||
inline net_domain* _GetDomain(net_buffer* buffer);
|
||||
UdpDomainSupport* _GetDomainSupport(net_domain* domain,
|
||||
bool create);
|
||||
UdpDomainSupport* _GetDomainSupport(net_buffer* buffer);
|
||||
|
||||
mutex fLock;
|
||||
status_t fStatus;
|
||||
@@ -504,23 +506,21 @@ UdpDomainSupport::_FindActiveEndpoint(const sockaddr *ourAddress,
|
||||
|
||||
|
||||
status_t
|
||||
UdpDomainSupport::_DemuxBroadcast(net_buffer *buffer)
|
||||
UdpDomainSupport::_DemuxBroadcast(net_buffer* buffer)
|
||||
{
|
||||
sockaddr *peerAddr = buffer->source;
|
||||
sockaddr *broadcastAddr = buffer->destination;
|
||||
sockaddr *mask = NULL;
|
||||
if (buffer->interface_address != NULL)
|
||||
mask = (sockaddr *)buffer->interface_address->mask;
|
||||
|
||||
TRACE_DOMAIN("_DemuxBroadcast(%p)", buffer);
|
||||
|
||||
sockaddr* peerAddr = buffer->source;
|
||||
sockaddr* broadcastAddr = buffer->destination;
|
||||
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()) {
|
||||
UdpEndpoint *endpoint = it.Next();
|
||||
TRACE_DOMAIN("_DemuxBroadcast(%p): mask %p\n", buffer, mask);
|
||||
|
||||
EndpointTable::Iterator iterator = fActiveEndpoints.GetIterator();
|
||||
|
||||
while (UdpEndpoint* endpoint = iterator.Next()) {
|
||||
TRACE_DOMAIN(" _DemuxBroadcast(): checking endpoint %s...",
|
||||
AddressString(fDomain, *endpoint->LocalAddress(), true).Data());
|
||||
|
||||
@@ -540,7 +540,7 @@ UdpDomainSupport::_DemuxBroadcast(net_buffer *buffer)
|
||||
}
|
||||
|
||||
if (endpoint->LocalAddress().MatchMasked(broadcastAddr, mask)
|
||||
|| endpoint->LocalAddress().IsEmpty(false)) {
|
||||
|| mask == NULL || endpoint->LocalAddress().IsEmpty(false)) {
|
||||
// address matches, dispatch to this endpoint:
|
||||
endpoint->StoreData(buffer);
|
||||
}
|
||||
@@ -675,7 +675,7 @@ UdpEndpointManager::ReceiveData(net_buffer *buffer)
|
||||
{
|
||||
TRACE_EPM("ReceiveData(%p [%" B_PRIu32 " bytes])", buffer, buffer->size);
|
||||
|
||||
UdpDomainSupport* domainSupport = _GetDomain(buffer);
|
||||
UdpDomainSupport* domainSupport = _GetDomainSupport(buffer);
|
||||
if (domainSupport == NULL) {
|
||||
// we don't instantiate domain supports in the receiving path, as
|
||||
// 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)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
UdpDomainSupport* domainSupport = _GetDomain(buffer);
|
||||
UdpDomainSupport* domainSupport = _GetDomainSupport(buffer);
|
||||
if (domainSupport == NULL) {
|
||||
// we don't instantiate domain supports in the receiving path, as
|
||||
// we are only interested in delivering data to existing sockets.
|
||||
@@ -738,25 +738,23 @@ UdpEndpointManager::ReceiveError(status_t error, net_buffer* buffer)
|
||||
|
||||
|
||||
status_t
|
||||
UdpEndpointManager::Deframe(net_buffer *buffer)
|
||||
UdpEndpointManager::Deframe(net_buffer* buffer)
|
||||
{
|
||||
TRACE_EPM("Deframe(%p [%ld bytes])", buffer, buffer->size);
|
||||
|
||||
NetBufferHeaderReader<udp_header> bufferHeader(buffer);
|
||||
if (bufferHeader.Status() < B_OK)
|
||||
if (bufferHeader.Status() != B_OK)
|
||||
return bufferHeader.Status();
|
||||
|
||||
udp_header &header = bufferHeader.Data();
|
||||
udp_header& header = bufferHeader.Data();
|
||||
|
||||
if (buffer->interface_address == NULL
|
||||
|| buffer->interface_address->domain == NULL) {
|
||||
net_domain* domain = _GetDomain(buffer);
|
||||
if (domain == NULL) {
|
||||
TRACE_EPM(" Deframe(): UDP packed dropped as there was no domain "
|
||||
"specified (interface address %p).", buffer->interface_address);
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
net_domain *domain = buffer->interface_address->domain;
|
||||
net_address_module_info *addressModule = domain->address_module;
|
||||
net_address_module_info* addressModule = domain->address_module;
|
||||
|
||||
SocketAddress source(addressModule, buffer->source);
|
||||
SocketAddress destination(addressModule, buffer->destination);
|
||||
@@ -799,7 +797,7 @@ UdpEndpointManager::OpenEndpoint(UdpEndpoint *endpoint)
|
||||
{
|
||||
MutexLocker _(fLock);
|
||||
|
||||
UdpDomainSupport *domain = _GetDomain(endpoint->Domain(), true);
|
||||
UdpDomainSupport* domain = _GetDomainSupport(endpoint->Domain(), true);
|
||||
if (domain)
|
||||
domain->Ref();
|
||||
return domain;
|
||||
@@ -823,10 +821,23 @@ UdpEndpointManager::FreeEndpoint(UdpDomainSupport *domain)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
UdpDomainSupport *
|
||||
UdpEndpointManager::_GetDomain(net_domain *domain, bool create)
|
||||
inline net_domain*
|
||||
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
|
||||
// receiver handlers that forward the requests to the
|
||||
@@ -834,8 +845,8 @@ UdpEndpointManager::_GetDomain(net_domain *domain, bool create)
|
||||
// being constructed UdpDomainSupport could call
|
||||
// register_domain_receiving_protocol() with the right
|
||||
// family.
|
||||
while (it.HasNext()) {
|
||||
UdpDomainSupport *domainSupport = it.Next();
|
||||
UdpDomainList::Iterator iterator = fDomains.GetIterator();
|
||||
while (UdpDomainSupport* domainSupport = iterator.Next()) {
|
||||
if (domainSupport->Domain() == domain)
|
||||
return domainSupport;
|
||||
}
|
||||
@@ -843,8 +854,8 @@ UdpEndpointManager::_GetDomain(net_domain *domain, bool create)
|
||||
if (!create)
|
||||
return NULL;
|
||||
|
||||
UdpDomainSupport *domainSupport =
|
||||
new (std::nothrow) UdpDomainSupport(domain);
|
||||
UdpDomainSupport* domainSupport
|
||||
= new (std::nothrow) UdpDomainSupport(domain);
|
||||
if (domainSupport == NULL || domainSupport->Init() < B_OK) {
|
||||
delete domainSupport;
|
||||
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*
|
||||
UdpEndpointManager::_GetDomain(net_buffer* buffer)
|
||||
UdpEndpointManager::_GetDomainSupport(net_buffer* buffer)
|
||||
{
|
||||
if (buffer->interface_address == NULL)
|
||||
return NULL;
|
||||
|
||||
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
|
||||
// whole RX path, we may not hold an endpoint's lock with the
|
||||
// manager lock held.
|
||||
|
||||
Reference in New Issue
Block a user