From 9c4477d3bf7ba915564c31106c177cde3998ed26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 1 Apr 2007 11:48:07 +0000 Subject: [PATCH] SIOCGIFCONF will now also report the size of the written buffer in ifconf.ifc_len to cover the case the list of interfaces changed since SIOCGIFCOUNT was called. Patch by Hugo Santos. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20491 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/network/stack/datalink.cpp | 7 ++++++- src/add-ons/kernel/network/stack/domains.cpp | 17 +++++++++-------- src/add-ons/kernel/network/stack/domains.h | 4 ++-- src/add-ons/kernel/network/stack/interfaces.cpp | 15 ++++++++------- src/add-ons/kernel/network/stack/interfaces.h | 2 +- src/add-ons/kernel/network/stack/link.cpp | 11 ++++++++--- 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/add-ons/kernel/network/stack/datalink.cpp b/src/add-ons/kernel/network/stack/datalink.cpp index e2670390c9..6688a3d4a9 100644 --- a/src/add-ons/kernel/network/stack/datalink.cpp +++ b/src/add-ons/kernel/network/stack/datalink.cpp @@ -280,7 +280,12 @@ datalink_control(net_domain *_domain, int32 option, void *value, if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK) return B_BAD_ADDRESS; - return list_domain_interfaces(config.ifc_buf, config.ifc_len); + status_t result = list_domain_interfaces(config.ifc_buf, + (size_t *)&config.ifc_len); + if (result != B_OK) + return result; + + return user_memcpy(value, &config, sizeof(struct ifconf)); } case SIOCGRTSIZE: diff --git a/src/add-ons/kernel/network/stack/domains.cpp b/src/add-ons/kernel/network/stack/domains.cpp index 078e7160fb..3085078257 100644 --- a/src/add-ons/kernel/network/stack/domains.cpp +++ b/src/add-ons/kernel/network/stack/domains.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -99,12 +99,13 @@ count_domain_interfaces() returned. */ status_t -list_domain_interfaces(void *buffer, size_t size) +list_domain_interfaces(void *buffer, size_t *_bufferSize) { BenaphoreLocker locker(sDomainLock); + uint8 *current = (uint8 *)buffer; + const uint8 *bufferEnd = current + (*_bufferSize); net_domain_private *domain = NULL; - size_t spaceLeft = size; while (true) { domain = (net_domain_private *)list_get_next_item(&sDomains, domain); @@ -118,8 +119,8 @@ list_domain_interfaces(void *buffer, size_t size) if (interface == NULL) break; - size = IF_NAMESIZE + (interface->address ? interface->address->sa_len : 2); - if (spaceLeft < size) + size_t size = IF_NAMESIZE + (interface->address ? interface->address->sa_len : 2); + if ((current + size) > bufferEnd) return ENOBUFS; ifreq request; @@ -132,14 +133,14 @@ list_domain_interfaces(void *buffer, size_t size) request.ifr_addr.sa_family = AF_UNSPEC; } - if (user_memcpy(buffer, &request, size) < B_OK) + if (user_memcpy(current, &request, size) < B_OK) return B_BAD_ADDRESS; - buffer = (void *)((addr_t)buffer + size); - spaceLeft -= size; + current += size; } } + *_bufferSize = current - (uint8 *)buffer; return B_OK; } diff --git a/src/add-ons/kernel/network/stack/domains.h b/src/add-ons/kernel/network/stack/domains.h index 7750fcb53f..6b9d43d751 100644 --- a/src/add-ons/kernel/network/stack/domains.h +++ b/src/add-ons/kernel/network/stack/domains.h @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -30,7 +30,7 @@ status_t init_domains(); status_t uninit_domains(); uint32 count_domain_interfaces(); -status_t list_domain_interfaces(void *buffer, size_t size); +status_t list_domain_interfaces(void *buffer, size_t *_bufferSize); status_t add_interface_to_domain(net_domain *domain, struct ifreq& request); status_t remove_interface_from_domain(net_interface *interface); diff --git a/src/add-ons/kernel/network/stack/interfaces.cpp b/src/add-ons/kernel/network/stack/interfaces.cpp index 11537a9f20..da28a327f1 100644 --- a/src/add-ons/kernel/network/stack/interfaces.cpp +++ b/src/add-ons/kernel/network/stack/interfaces.cpp @@ -258,12 +258,13 @@ count_device_interfaces() returned. */ status_t -list_device_interfaces(void *buffer, size_t size) +list_device_interfaces(void *buffer, size_t *_bufferSize) { BenaphoreLocker locker(sInterfaceLock); + uint8 *current = (uint8 *)buffer; + const uint8 *bufferEnd = current + (*_bufferSize); net_device_interface *interface = NULL; - size_t spaceLeft = size; while (true) { interface = (net_device_interface *)list_get_next_item(&sInterfaces, @@ -275,17 +276,17 @@ list_device_interfaces(void *buffer, size_t size) strlcpy(request.ifr_name, interface->name, IF_NAMESIZE); get_device_interface_address(interface, &request.ifr_addr); - size = IF_NAMESIZE + request.ifr_addr.sa_len; - if (spaceLeft < size) + size_t size = IF_NAMESIZE + request.ifr_addr.sa_len; + if ((current + size) > bufferEnd) return ENOBUFS; - if (user_memcpy(buffer, &request, size) < B_OK) + if (user_memcpy(current, &request, size) < B_OK) return B_BAD_ADDRESS; - buffer = (void *)((addr_t)buffer + size); - spaceLeft -= size; + current += size; } + *_bufferSize = current - (uint8 *)buffer;; return B_OK; } diff --git a/src/add-ons/kernel/network/stack/interfaces.h b/src/add-ons/kernel/network/stack/interfaces.h index d780549357..e801ded8a9 100644 --- a/src/add-ons/kernel/network/stack/interfaces.h +++ b/src/add-ons/kernel/network/stack/interfaces.h @@ -72,7 +72,7 @@ void delete_interface(net_interface_private *interface); void get_device_interface_address(net_device_interface *interface, sockaddr *address); uint32 count_device_interfaces(); -status_t list_device_interfaces(void *buffer, size_t size); +status_t list_device_interfaces(void *buffer, size_t *_bufferSize); void put_device_interface(struct net_device_interface *interface); struct net_device_interface *get_device_interface(uint32 index); struct net_device_interface *get_device_interface(const char *name); diff --git a/src/add-ons/kernel/network/stack/link.cpp b/src/add-ons/kernel/network/stack/link.cpp index 7f127c8463..a6bc89aeb8 100644 --- a/src/add-ons/kernel/network/stack/link.cpp +++ b/src/add-ons/kernel/network/stack/link.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -174,12 +174,17 @@ link_control(net_protocol *_protocol, int level, int option, void *value, case SIOCGIFCONF: { - // count number of interfaces + // retrieve available interfaces struct ifconf config; if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK) return B_BAD_ADDRESS; - return list_device_interfaces(config.ifc_buf, config.ifc_len); + status_t result = list_device_interfaces(config.ifc_buf, + (size_t *)&config.ifc_len); + if (result != B_OK) + return result; + + return user_memcpy(value, &config, sizeof(struct ifconf)); } case SIOCGIFADDR: