diff --git a/src/add-ons/kernel/network/stack/device_interfaces.cpp b/src/add-ons/kernel/network/stack/device_interfaces.cpp index 174e703ecf..061328ba95 100644 --- a/src/add-ons/kernel/network/stack/device_interfaces.cpp +++ b/src/add-ons/kernel/network/stack/device_interfaces.cpp @@ -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; } diff --git a/src/add-ons/kernel/network/stack/interfaces.cpp b/src/add-ons/kernel/network/stack/interfaces.cpp index edd43f3c36..0a5d22caa2 100644 --- a/src/add-ons/kernel/network/stack/interfaces.cpp +++ b/src/add-ons/kernel/network/stack/interfaces.cpp @@ -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; } diff --git a/src/add-ons/kernel/network/stack/routes.cpp b/src/add-ons/kernel/network/stack/routes.cpp index 5df3d52681..e2b8777b4a 100644 --- a/src/add-ons/kernel/network/stack/routes.cpp +++ b/src/add-ons/kernel/network/stack/routes.cpp @@ -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); } diff --git a/src/add-ons/kernel/network/stack/utility.cpp b/src/add-ons/kernel/network/stack/utility.cpp index 00589a3bd4..99b83dead8 100644 --- a/src/add-ons/kernel/network/stack/utility.cpp +++ b/src/add-ons/kernel/network/stack/utility.cpp @@ -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) { diff --git a/src/add-ons/kernel/network/stack/utility.h b/src/add-ons/kernel/network/stack/utility.h index 242a84ac28..302ed809b1 100644 --- a/src/add-ons/kernel/network/stack/utility.h +++ b/src/add-ons/kernel/network/stack/utility.h @@ -14,16 +14,22 @@ class UserBuffer { public: - UserBuffer(void* buffer, size_t size); + 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; - status_t fStatus; + uint8* fBuffer; + 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);