* Removed the interface fallback from the datalink module's is_local_address().
* Instead, added a new function is_local_link_address() which returns the interface with the matching link level address, and can additionally test for unconfigured interfaces. * Merged the two versions of fill_sockaddr_in() together in ipv4.cpp. * ipv4 now uses the new is_local_link_address() function to figure out whether the received packet should be processed or not. This should fix a few DHCP issues with multiple and configured interfaces as recently explained on the mailing list. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34466 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -70,9 +70,11 @@ struct net_datalink_module_info {
|
|||||||
struct net_domain *domain, struct net_buffer *buffer);
|
struct net_domain *domain, struct net_buffer *buffer);
|
||||||
|
|
||||||
bool (*is_local_address)(struct net_domain *domain,
|
bool (*is_local_address)(struct net_domain *domain,
|
||||||
const struct sockaddr *address,
|
const struct sockaddr *address, net_interface **_interface,
|
||||||
net_interface **_interface,
|
|
||||||
uint32 *_matchedType);
|
uint32 *_matchedType);
|
||||||
|
bool (*is_local_link_address)(struct net_domain *domain, bool unconfigured,
|
||||||
|
const struct sockaddr *address, net_interface **_interface);
|
||||||
|
|
||||||
net_interface *(*get_interface)(struct net_domain *domain, uint32 index);
|
net_interface *(*get_interface)(struct net_domain *domain, uint32 index);
|
||||||
net_interface *(*get_interface_with_address)(struct net_domain *domain,
|
net_interface *(*get_interface_with_address)(struct net_domain *domain,
|
||||||
const struct sockaddr *address);
|
const struct sockaddr *address);
|
||||||
|
|||||||
@@ -750,13 +750,14 @@ raw_receive_data(net_buffer* buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static sockaddr*
|
static inline sockaddr*
|
||||||
fill_sockaddr_in(sockaddr_in* destination, const in_addr &source)
|
fill_sockaddr_in(sockaddr_in* target, in_addr_t address)
|
||||||
{
|
{
|
||||||
memset(destination, 0, sizeof(sockaddr_in));
|
target->sin_family = AF_INET;
|
||||||
destination->sin_family = AF_INET;
|
target->sin_len = sizeof(sockaddr_in);
|
||||||
destination->sin_addr = source;
|
target->sin_port = 0;
|
||||||
return (sockaddr*)destination;
|
target->sin_addr.s_addr = address;
|
||||||
|
return (sockaddr*)target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -770,7 +771,7 @@ IPv4Multicast::JoinGroup(IPv4GroupInterface* state)
|
|||||||
|
|
||||||
status_t status = interface->first_info->join_multicast(
|
status_t status = interface->first_info->join_multicast(
|
||||||
interface->first_protocol,
|
interface->first_protocol,
|
||||||
fill_sockaddr_in(&groupAddr, state->Address()));
|
fill_sockaddr_in(&groupAddr, state->Address().s_addr));
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -791,7 +792,7 @@ IPv4Multicast::LeaveGroup(IPv4GroupInterface* state)
|
|||||||
|
|
||||||
return interface->first_protocol->module->join_multicast(
|
return interface->first_protocol->module->join_multicast(
|
||||||
interface->first_protocol,
|
interface->first_protocol,
|
||||||
fill_sockaddr_in(&groupAddr, state->Address()));
|
fill_sockaddr_in(&groupAddr, state->Address().s_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -816,17 +817,6 @@ receiving_protocol(uint8 protocol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline sockaddr*
|
|
||||||
fill_sockaddr_in(sockaddr_in* target, in_addr_t address)
|
|
||||||
{
|
|
||||||
memset(target, 0, sizeof(sockaddr_in));
|
|
||||||
target->sin_family = AF_INET;
|
|
||||||
target->sin_len = sizeof(sockaddr_in);
|
|
||||||
target->sin_addr.s_addr = address;
|
|
||||||
return (sockaddr*)target;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
ipv4_delta_group(IPv4GroupInterface* group, int option,
|
ipv4_delta_group(IPv4GroupInterface* group, int option,
|
||||||
net_interface* interface, const in_addr* sourceAddr)
|
net_interface* interface, const in_addr* sourceAddr)
|
||||||
@@ -1572,24 +1562,24 @@ ipv4_receive_data(net_buffer* buffer)
|
|||||||
if (gBufferModule->checksum(buffer, 0, headerLength, true) != 0)
|
if (gBufferModule->checksum(buffer, 0, headerLength, true) != 0)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
struct sockaddr_in& source = *(struct sockaddr_in*)buffer->source;
|
|
||||||
struct sockaddr_in& destination = *(struct sockaddr_in*)buffer->destination;
|
|
||||||
|
|
||||||
fill_sockaddr_in(&source, header.source);
|
|
||||||
fill_sockaddr_in(&destination, header.destination);
|
|
||||||
|
|
||||||
// lower layers notion of Broadcast or Multicast have no relevance to us
|
// lower layers notion of Broadcast or Multicast have no relevance to us
|
||||||
buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
|
buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
|
||||||
|
|
||||||
|
sockaddr_in destination;
|
||||||
|
fill_sockaddr_in(&destination, header.destination);
|
||||||
|
|
||||||
if (header.destination == INADDR_BROADCAST) {
|
if (header.destination == INADDR_BROADCAST) {
|
||||||
buffer->flags |= MSG_BCAST;
|
buffer->flags |= MSG_BCAST;
|
||||||
} else if (IN_MULTICAST(ntohl(header.destination))) {
|
} else if (IN_MULTICAST(ntohl(header.destination))) {
|
||||||
buffer->flags |= MSG_MCAST;
|
buffer->flags |= MSG_MCAST;
|
||||||
} 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, &matchedAddressType)) {
|
&buffer->interface, &matchedAddressType)
|
||||||
|
&& !sDatalinkModule->is_local_link_address(sDomain, true,
|
||||||
|
buffer->destination, &buffer->interface)) {
|
||||||
TRACE(" ReceiveData(): packet was not for us %lx -> %lx",
|
TRACE(" ReceiveData(): packet was not for us %lx -> %lx",
|
||||||
ntohl(header.source), ntohl(header.destination));
|
ntohl(header.source), ntohl(header.destination));
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -1599,6 +1589,10 @@ ipv4_receive_data(net_buffer* buffer)
|
|||||||
buffer->flags |= matchedAddressType;
|
buffer->flags |= matchedAddressType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set net_buffer's source/destination address
|
||||||
|
fill_sockaddr_in((struct sockaddr_in*)buffer->source, header.source);
|
||||||
|
memcpy(buffer->destination, &destination, sizeof(sockaddr_in));
|
||||||
|
|
||||||
uint8 protocol = buffer->protocol = header.protocol;
|
uint8 protocol = buffer->protocol = header.protocol;
|
||||||
|
|
||||||
// remove any trailing/padding data
|
// remove any trailing/padding data
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <util/AutoLock.h>
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
#include <net/if_dl.h>
|
||||||
#include <net/if_media.h>
|
#include <net/if_media.h>
|
||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
#include <sys/sockio.h>
|
#include <sys/sockio.h>
|
||||||
@@ -399,8 +400,8 @@ datalink_send_datagram(net_protocol* protocol, net_domain* domain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Tests if \a address is a local address in the domain.
|
||||||
Tests if \a address is a local address in the domain.
|
|
||||||
\param _interface will be set to the interface belonging to that address
|
\param _interface will be set to the interface belonging to that address
|
||||||
if non-NULL.
|
if non-NULL.
|
||||||
\param _matchedType will be set to either zero or MSG_BCAST if non-NULL.
|
\param _matchedType will be set to either zero or MSG_BCAST if non-NULL.
|
||||||
@@ -416,7 +417,6 @@ datalink_is_local_address(net_domain* _domain, const struct sockaddr* address,
|
|||||||
RecursiveLocker locker(domain->lock);
|
RecursiveLocker locker(domain->lock);
|
||||||
|
|
||||||
net_interface* interface = NULL;
|
net_interface* interface = NULL;
|
||||||
net_interface* fallback = NULL;
|
|
||||||
uint32 matchedType = 0;
|
uint32 matchedType = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -424,10 +424,8 @@ datalink_is_local_address(net_domain* _domain, const struct sockaddr* address,
|
|||||||
&domain->interfaces, interface);
|
&domain->interfaces, interface);
|
||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
break;
|
break;
|
||||||
if (interface->address == NULL) {
|
if (interface->address == NULL)
|
||||||
fallback = interface;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// check for matching unicast address first
|
// check for matching unicast address first
|
||||||
if (domain->address_module->equal_addresses(interface->address, address))
|
if (domain->address_module->equal_addresses(interface->address, address))
|
||||||
@@ -436,7 +434,7 @@ datalink_is_local_address(net_domain* _domain, const struct sockaddr* address,
|
|||||||
// check for matching broadcast address if interface supports
|
// check for matching broadcast address if interface supports
|
||||||
// broadcasting (IFF_BROADCAST is a link-level flag, so it is
|
// broadcasting (IFF_BROADCAST is a link-level flag, so it is
|
||||||
// a property of the device)
|
// a property of the device)
|
||||||
if ((interface->device->flags & IFF_BROADCAST)
|
if ((interface->device->flags & IFF_BROADCAST) != 0
|
||||||
&& domain->address_module->equal_addresses(interface->destination,
|
&& domain->address_module->equal_addresses(interface->destination,
|
||||||
address)) {
|
address)) {
|
||||||
matchedType = MSG_BCAST;
|
matchedType = MSG_BCAST;
|
||||||
@@ -444,11 +442,8 @@ datalink_is_local_address(net_domain* _domain, const struct sockaddr* address,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interface == NULL) {
|
if (interface == NULL)
|
||||||
interface = fallback;
|
return false;
|
||||||
if (interface == NULL)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_interface != NULL)
|
if (_interface != NULL)
|
||||||
*_interface = interface;
|
*_interface = interface;
|
||||||
@@ -458,6 +453,49 @@ datalink_is_local_address(net_domain* _domain, const struct sockaddr* address,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Tests if \a address is a local link address in the domain.
|
||||||
|
|
||||||
|
\param unconfigured only unconfigured interfaces are taken into account.
|
||||||
|
\param _interface will be set to the interface belonging to that address
|
||||||
|
if non-NULL.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
datalink_is_local_link_address(net_domain* _domain, bool unconfigured,
|
||||||
|
const struct sockaddr* address, net_interface** _interface)
|
||||||
|
{
|
||||||
|
net_domain_private* domain = (net_domain_private*)_domain;
|
||||||
|
if (domain == NULL || address == NULL || address->sa_family != AF_LINK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RecursiveLocker locker(domain->lock);
|
||||||
|
|
||||||
|
sockaddr_dl& linkAddress = *(sockaddr_dl*)address;
|
||||||
|
net_interface* interface = NULL;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
interface = (net_interface*)list_get_next_item(
|
||||||
|
&domain->interfaces, interface);
|
||||||
|
if (interface == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (unconfigured && interface->address != NULL
|
||||||
|
&& (interface->flags & IFF_CONFIGURING) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (linkAddress.sdl_alen == interface->device->address.length
|
||||||
|
&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
|
||||||
|
linkAddress.sdl_alen) == 0) {
|
||||||
|
// link address matches
|
||||||
|
if (_interface != NULL)
|
||||||
|
*_interface = interface;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
net_interface*
|
net_interface*
|
||||||
datalink_get_interface_with_address(net_domain* _domain,
|
datalink_get_interface_with_address(net_domain* _domain,
|
||||||
const sockaddr* address)
|
const sockaddr* address)
|
||||||
@@ -859,6 +897,7 @@ net_datalink_module_info gNetDatalinkModule = {
|
|||||||
datalink_send_data,
|
datalink_send_data,
|
||||||
datalink_send_datagram,
|
datalink_send_datagram,
|
||||||
datalink_is_local_address,
|
datalink_is_local_address,
|
||||||
|
datalink_is_local_link_address,
|
||||||
datalink_get_interface,
|
datalink_get_interface,
|
||||||
datalink_get_interface_with_address,
|
datalink_get_interface_with_address,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user