* Make sure the SIOCGIFCONF never returns an address with an address length

smaller than sizeof(sockaddr). This fixes a compatibility issue with other
  platforms - portable software often assumes that the amount of bytes to
  add to an ifreq structure is the larger amount between sizeof(ifreq), and
  basically what the _SIZEOF_ADDR_IFREQ() macro returns, instead of always
  relying on that macro.
* Renamed UserBuffer::Copy() to Push, ConsumedAmount() to BytesConsumed(),
  added Pad() method.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37927 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2010-08-05 13:17:12 +00:00
parent 40061f8fd5
commit 715fed4479
5 changed files with 77 additions and 43 deletions

View File

@ -292,7 +292,8 @@ acquire_device_interface(net_device_interface* interface)
void
get_device_interface_address(net_device_interface* interface, sockaddr* _address)
get_device_interface_address(net_device_interface* interface,
sockaddr* _address)
{
sockaddr_dl &address = *(sockaddr_dl*)_address;
@ -306,8 +307,7 @@ get_device_interface_address(net_device_interface* interface, sockaddr* _address
address.sdl_alen = interface->device->address.length;
memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen);
address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data)
+ address.sdl_nlen + address.sdl_alen;
address.sdl_len = sizeof(sockaddr_dl);
}
@ -341,15 +341,16 @@ list_device_interfaces(void* _buffer, size_t* bufferSize)
UserBuffer buffer(_buffer, *bufferSize);
while (net_device_interface* interface = iterator.Next()) {
ifreq request;
strlcpy(request.ifr_name, interface->device->name, IF_NAMESIZE);
get_device_interface_address(interface, &request.ifr_addr);
buffer.Push(interface->device->name, IF_NAMESIZE);
if (buffer.Copy(&request, IF_NAMESIZE + request.ifr_addr.sa_len) == NULL)
sockaddr address;
get_device_interface_address(interface, &address);
if (buffer.Push(&address, address.sa_len) == NULL)
return buffer.Status();
}
*bufferSize = buffer.ConsumedAmount();
*bufferSize = buffer.BytesConsumed();
return B_OK;
}

View File

@ -1385,27 +1385,38 @@ list_interfaces(int family, void* _buffer, size_t* bufferSize)
InterfaceList::Iterator iterator = sInterfaces.GetIterator();
while (Interface* interface = iterator.Next()) {
ifreq request;
strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
// Copy name
buffer.Push(interface->name, IF_NAMESIZE);
// Copy address
InterfaceAddress* address = interface->FirstForFamily(family);
sockaddr_storage storage;
if (address != NULL && address->local != NULL) {
// copy actual address
memcpy(&request.ifr_addr, address->local, address->local->sa_len);
// Actual address
memcpy(&storage, address->local, address->local->sa_len);
} else {
// empty address
request.ifr_addr.sa_len = 2;
request.ifr_addr.sa_family = AF_UNSPEC;
// 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);
}
if (address != NULL)
address->ReleaseReference();
if (buffer.Copy(&request, IF_NAMESIZE
+ request.ifr_addr.sa_len) == NULL)
if (buffer.Push(&storage, storage.ss_len) == NULL)
return buffer.Status();
}
*bufferSize = buffer.ConsumedAmount();
*bufferSize = buffer.BytesConsumed();
return B_OK;
}

View File

@ -282,7 +282,7 @@ copy_address(UserBuffer& buffer, sockaddr* address)
if (address == NULL)
return NULL;
return (sockaddr*)buffer.Copy(address, address->sa_len);
return (sockaddr*)buffer.Push(address, address->sa_len);
}

View File

@ -123,11 +123,11 @@ base_fifo_clear(FifoType* fifo)
}
// #pragma mark -
// #pragma mark - UserBuffer
void*
UserBuffer::Copy(void* source, size_t length)
UserBuffer::Push(void* source, size_t length)
{
if (fStatus != B_OK)
return NULL;
@ -139,7 +139,7 @@ UserBuffer::Copy(void* source, size_t length)
#ifdef _KERNEL_MODE
fStatus = user_memcpy(fBuffer, source, length);
if (fStatus < B_OK)
if (fStatus != B_OK)
return NULL;
#else
memcpy(fBuffer, source, length);
@ -154,6 +154,36 @@ UserBuffer::Copy(void* source, size_t length)
}
status_t
UserBuffer::Pad(size_t length)
{
if (fStatus != B_OK)
return fStatus;
if (fAvailable < length)
return fStatus = ENOBUFS;
fStatus = user_memset(fBuffer, 0, length);
if (fStatus != B_OK)
return fStatus;
fAvailable -= length;
fBuffer += length;
return B_OK;
}
status_t
UserBuffer::PadToNext(size_t length)
{
return Pad((BytesConsumed() + length - 1) / length - BytesConsumed());
}
// #pragma mark -
uint16
compute_checksum(uint8* _buffer, size_t length)
{

View File

@ -16,13 +16,19 @@ class UserBuffer {
public:
UserBuffer(void* buffer, size_t size);
void* Copy(void* source, size_t size);
status_t Status() const;
size_t ConsumedAmount() const;
void* Push(void* source, size_t size);
status_t Pad(size_t length);
status_t PadToNext(size_t length);
status_t Status() const
{ return fStatus; }
size_t BytesConsumed() const
{ return fBufferSize - fAvailable; }
private:
uint8* fBuffer;
size_t fBufferSize, fAvailable;
size_t fBufferSize;
size_t fAvailable;
status_t fStatus;
};
@ -38,20 +44,6 @@ UserBuffer::UserBuffer(void* buffer, size_t size)
}
inline status_t
UserBuffer::Status() const
{
return fStatus;
}
inline size_t
UserBuffer::ConsumedAmount() const
{
return fBufferSize - fAvailable;
}
// checksums
uint16 compute_checksum(uint8* _buffer, size_t length);
uint16 checksum(uint8* buffer, size_t length);