* Changed the _SIZEOF_ADDR_IFREQ() macro such that it can be used how we are

using it - hopefully, that is actually correct (it's adopted from FreeBSD).
* Fixed bug that cut off the sockaddr_dl reported by the system, so that DHCP
  wouldn't work anymore (and ifconfig wouldn't show the actual MAC address
  anymore).
* Changed the listing code to actually pad to ifreq size, and leave the length
  of the sockaddr untouched.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37941 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2010-08-06 12:58:02 +00:00
parent 8b6048a285
commit 1f9c8c4576
4 changed files with 28 additions and 20 deletions

View File

@ -94,8 +94,11 @@ struct ifconf {
};
};
/* Macro that returns the size of a single address within a SIOCGIFCONF buffer;
it looks like this because of compatibility with other platforms. */
#define _SIZEOF_ADDR_IFREQ(request) \
(sizeof((request).ifr_name) + (request).ifr_addr.sa_len)
(IF_NAMESIZE + (request).ifr_addr.sa_len > (int)sizeof(ifreq) \
? IF_NAMESIZE + (request).ifr_addr.sa_len : sizeof(ifreq))
/* POSIX definitions follow */

View File

@ -307,7 +307,8 @@ get_device_interface_address(net_device_interface* interface,
address.sdl_alen = interface->device->address.length;
memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen);
address.sdl_len = sizeof(sockaddr_dl);
address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data)
+ address.sdl_nlen + address.sdl_alen;
}
@ -343,10 +344,14 @@ list_device_interfaces(void* _buffer, size_t* bufferSize)
while (net_device_interface* interface = iterator.Next()) {
buffer.Push(interface->device->name, IF_NAMESIZE);
sockaddr address;
get_device_interface_address(interface, &address);
sockaddr_storage address;
get_device_interface_address(interface, (sockaddr*)&address);
if (buffer.Push(&address, address.sa_len) == NULL)
buffer.Push(&address, address.ss_len);
if (IF_NAMESIZE + address.ss_len < (int)sizeof(ifreq))
buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - address.ss_len);
if (buffer.Status() != B_OK)
return buffer.Status();
}

View File

@ -1415,29 +1415,29 @@ list_interfaces(int family, void* _buffer, size_t* bufferSize)
// Copy address
InterfaceAddress* address = interface->FirstForFamily(family);
sockaddr_storage storage;
size_t length = 0;
if (address != NULL && address->local != NULL) {
// Actual address
memcpy(&storage, address->local, address->local->sa_len);
buffer.Push(address->local, length = address->local->sa_len);
} else {
// Empty address
storage.ss_len = 2;
storage.ss_family = AF_UNSPEC;
}
if (storage.ss_len < sizeof(sockaddr)) {
// Make sure at least sizeof(sockaddr) bytes are written for
// compatibility with other platforms
memset((uint8*)&storage + storage.ss_len, 0,
sizeof(sockaddr) - storage.ss_len);
storage.ss_len = sizeof(sockaddr);
sockaddr empty;
empty.sa_len = 2;
empty.sa_family = AF_UNSPEC;
buffer.Push(&empty, length = empty.sa_len);
}
if (address != NULL)
address->ReleaseReference();
if (buffer.Push(&storage, storage.ss_len) == NULL)
if (IF_NAMESIZE + length < sizeof(ifreq)) {
// Make sure at least sizeof(ifreq) bytes are written for each
// interface for compatibility with other platforms
buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length);
}
if (buffer.Status() != B_OK)
return buffer.Status();
}

View File

@ -530,8 +530,8 @@ NetworkStatusView::_Update(bool force)
fStatus = status;
}
interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
+ interface->ifr_addr.sa_len);
interface = (ifreq *)((addr_t)interface
+ _SIZEOF_ADDR_IFREQ(interface[0]));
}
free(buffer);