* We need to call arp_remove_local_entry() from arp_change_address() even if the

old address is NULL for anything but SIOCAIFADDR. Hopefully, this fixes the
  problem Rene is seeing.
* Make sure that arp_entry::protocol is not NULL before using it. This is
  necessary because of the possibility to manually set ARP entries.
* Further improved debug output.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37916 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-08-05 07:56:23 +00:00
parent 84f7450097
commit 07ad8bb60e
@@ -127,6 +127,35 @@ static mutex sCacheLock;
static bool sIgnoreReplies; static bool sIgnoreReplies;
#ifdef TRACE_ARP
const char*
mac_to_string(uint8* address)
{
static char buffer[20];
snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
address[0], address[1], address[2], address[3], address[4], address[5]);
return buffer;
}
const char*
inet_to_string(in_addr_t address)
{
static char buffer[20];
unsigned int hostAddress = ntohl(address);
snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d",
hostAddress >> 24, (hostAddress >> 16) & 0xff,
(hostAddress >> 8) & 0xff, hostAddress & 0xff);
return buffer;
}
#endif // TRACE_ARP
static net_buffer* static net_buffer*
get_request_buffer(arp_entry* entry) get_request_buffer(arp_entry* entry)
{ {
@@ -165,6 +194,33 @@ delete_request_buffer(arp_entry* entry)
} }
static void
ipv4_to_ether_multicast(sockaddr_dl *destination, const sockaddr_in *source)
{
// RFC 1112 - Host extensions for IP multicasting
//
// ``An IP host group address is mapped to an Ethernet multicast
// address by placing the low-order 23-bits of the IP address into
// the low-order 23 bits of the Ethernet multicast address
// 01-00-5E-00-00-00 (hex).''
destination->sdl_len = sizeof(sockaddr_dl);
destination->sdl_family = AF_LINK;
destination->sdl_index = 0;
destination->sdl_type = IFT_ETHER;
destination->sdl_e_type = ETHER_TYPE_IP;
destination->sdl_nlen = destination->sdl_slen = 0;
destination->sdl_alen = ETHER_ADDRESS_LENGTH;
memcpy(LLADDR(destination) + 2, &source->sin_addr, sizeof(in_addr));
uint32 *data = (uint32 *)LLADDR(destination);
data[0] = (data[0] & htonl(0x7f)) | htonl(0x01005e00);
}
// #pragma mark -
/*static*/ int /*static*/ int
arp_entry::Compare(void *_entry, const void *_key) arp_entry::Compare(void *_entry, const void *_key)
{ {
@@ -316,33 +372,6 @@ arp_entry::ScheduleRemoval()
// #pragma mark - // #pragma mark -
static void
ipv4_to_ether_multicast(sockaddr_dl *destination, const sockaddr_in *source)
{
// RFC 1112 - Host extensions for IP multicasting
//
// ``An IP host group address is mapped to an Ethernet multicast
// address by placing the low-order 23-bits of the IP address into
// the low-order 23 bits of the Ethernet multicast address
// 01-00-5E-00-00-00 (hex).''
destination->sdl_len = sizeof(sockaddr_dl);
destination->sdl_family = AF_LINK;
destination->sdl_index = 0;
destination->sdl_type = IFT_ETHER;
destination->sdl_e_type = ETHER_TYPE_IP;
destination->sdl_nlen = destination->sdl_slen = 0;
destination->sdl_alen = ETHER_ADDRESS_LENGTH;
memcpy(LLADDR(destination) + 2, &source->sin_addr, sizeof(in_addr));
uint32 *data = (uint32 *)LLADDR(destination);
data[0] = (data[0] & htonl(0x7f)) | htonl(0x01005e00);
}
// #pragma mark -
/*! Updates the entry determined by \a protocolAddress with the specified /*! Updates the entry determined by \a protocolAddress with the specified
\a hardwareAddress. \a hardwareAddress.
If such an entry does not exist yet, a new entry is added. If you try If such an entry does not exist yet, a new entry is added. If you try
@@ -379,6 +408,7 @@ arp_update_entry(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
entry->hardware_address = *hardwareAddress; entry->hardware_address = *hardwareAddress;
entry->timestamp = system_time(); entry->timestamp = system_time();
entry->protocol = NULL;
} else { } else {
entry = arp_entry::Add(protocolAddress, hardwareAddress, flags); entry = arp_entry::Add(protocolAddress, hardwareAddress, flags);
if (entry == NULL) if (entry == NULL)
@@ -393,7 +423,7 @@ arp_update_entry(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
sStackModule->set_timer(&entry->timer, ARP_STALE_TIMEOUT); sStackModule->set_timer(&entry->timer, ARP_STALE_TIMEOUT);
} }
if (entry->flags & ARP_FLAG_REJECT) if ((entry->flags & ARP_FLAG_REJECT) != 0)
entry->MarkFailed(); entry->MarkFailed();
else else
entry->MarkValid(); entry->MarkValid();
@@ -409,9 +439,15 @@ static void
arp_remove_local_entry(arp_protocol* protocol, const sockaddr* local, arp_remove_local_entry(arp_protocol* protocol, const sockaddr* local,
bool updateLocalAddress) bool updateLocalAddress)
{ {
in_addr_t inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr; in_addr_t inetAddress;
TRACE(("%s(): address %x\n", __FUNCTION__, inetAddress)); if (local == NULL) {
// interface has not yet been set
inetAddress = INADDR_ANY;
} else
inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr;
TRACE(("%s(): address %s\n", __FUNCTION__, inet_to_string(inetAddress)));
MutexLocker locker(sCacheLock); MutexLocker locker(sCacheLock);
@@ -472,7 +508,7 @@ arp_set_local_entry(arp_protocol* protocol, const sockaddr* local)
} else } else
inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr; inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr;
TRACE(("%s(): address %x\n", __FUNCTION__, inetAddress)); TRACE(("%s(): address %s\n", __FUNCTION__, inet_to_string(inetAddress)));
if (protocol->local_address == 0) if (protocol->local_address == 0)
protocol->local_address = inetAddress; protocol->local_address = inetAddress;
@@ -545,7 +581,7 @@ handle_arp_request(net_buffer *buffer, arp_header &header)
// check if this request is for us // check if this request is for us
arp_entry *entry = arp_entry::Lookup(header.protocol_target); arp_entry *entry = arp_entry::Lookup(header.protocol_target);
if (entry == NULL if (entry == NULL || entry->protocol == NULL
|| (entry->flags & (ARP_FLAG_LOCAL | ARP_FLAG_PUBLISH)) == 0) { || (entry->flags & (ARP_FLAG_LOCAL | ARP_FLAG_PUBLISH)) == 0) {
// We're not the one to answer this request // We're not the one to answer this request
// TODO: instead of letting the other's request time-out, can we reply // TODO: instead of letting the other's request time-out, can we reply
@@ -603,21 +639,11 @@ arp_receive(void *cookie, net_device *device, net_buffer *buffer)
uint16 opcode = ntohs(header.opcode); uint16 opcode = ntohs(header.opcode);
#ifdef TRACE_ARP #ifdef TRACE_ARP
dprintf(" hw sender: %02x:%02x:%02x:%02x:%02x:%02x\n", dprintf(" hw sender: %s\n", mac_to_string(header.hardware_sender));
header.hardware_sender[0], header.hardware_sender[1], dprintf(" proto sender: %s\n", inet_to_string(header.protocol_sender));
header.hardware_sender[2], header.hardware_sender[3], dprintf(" hw target: %s\n", mac_to_string(header.hardware_target));;
header.hardware_sender[4], header.hardware_sender[5]); dprintf(" proto target: %s\n", inet_to_string(header.protocol_target));
unsigned int addr = ntohl(header.protocol_sender); #endif // TRACE_ARP
dprintf(" proto sender: %d.%d.%d.%d\n", addr >> 24, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff);
dprintf(" hw target: %02x:%02x:%02x:%02x:%02x:%02x\n",
header.hardware_target[0], header.hardware_target[1],
header.hardware_target[2], header.hardware_target[3],
header.hardware_target[4], header.hardware_target[5]);
addr = ntohl(header.protocol_target);
dprintf(" proto target: %d.%d.%d.%d\n", addr >> 24, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff);
#endif
if (ntohs(header.protocol_type) != ETHER_TYPE_IP if (ntohs(header.protocol_type) != ETHER_TYPE_IP
|| ntohs(header.hardware_type) != ARP_HARDWARE_TYPE_ETHER) || ntohs(header.hardware_type) != ARP_HARDWARE_TYPE_ETHER)
@@ -698,7 +724,8 @@ arp_timer(struct net_timer *timer, void *data)
default: default:
{ {
if (entry->timer_state > ARP_STATE_LAST_REQUEST) if (entry->timer_state > ARP_STATE_LAST_REQUEST
|| entry->protocol == NULL)
break; break;
TRACE((" send request for ARP entry %p!\n", entry)); TRACE((" send request for ARP entry %p!\n", entry));
@@ -946,7 +973,7 @@ arp_uninit()
} }
// #pragma mark - // #pragma mark - net_datalink_protocol
status_t status_t
@@ -1093,7 +1120,8 @@ arp_change_address(net_datalink_protocol* _protocol,
return status; return status;
} }
if (oldAddress != NULL && oldAddress->sa_family == AF_INET) if (option != SIOCAIFADDR
&& (oldAddress == NULL || oldAddress->sa_family == AF_INET))
arp_remove_local_entry(protocol, oldAddress, true); arp_remove_local_entry(protocol, oldAddress, true);
} }
break; break;