From 6289f998c737e70bf47bc2838559e2b043137429 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sun, 7 May 2017 19:25:34 +0800 Subject: [PATCH] fetched sources from android source. tested, they seem to work okay --- ErrnoRestorer.h | 43 +++++ bionic_macros.h | 49 ++++++ bionic_netlink.cpp | 106 +++++++++++++ bionic_netlink.h | 59 +++++++ ifaddrs.cpp | 260 +++++++++++++++++++++++++++++++ ifaddrs.h | 75 ++++----- ifaddrs.c => ifaddrs.old.cpp.txt | 137 ++++++++++++++-- ifaddrs.old.h.txt | 54 +++++++ 8 files changed, 735 insertions(+), 48 deletions(-) create mode 100644 ErrnoRestorer.h create mode 100644 bionic_macros.h create mode 100644 bionic_netlink.cpp create mode 100644 bionic_netlink.h create mode 100644 ifaddrs.cpp rename ifaddrs.c => ifaddrs.old.cpp.txt (76%) create mode 100644 ifaddrs.old.h.txt diff --git a/ErrnoRestorer.h b/ErrnoRestorer.h new file mode 100644 index 0000000..f467393 --- /dev/null +++ b/ErrnoRestorer.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ERRNO_RESTORER_H +#define ERRNO_RESTORER_H + +#include + +#include "bionic_macros.h" + +class ErrnoRestorer { + public: + explicit ErrnoRestorer() : saved_errno_(errno) { + } + + ~ErrnoRestorer() { + errno = saved_errno_; + } + + void override(int new_errno) { + saved_errno_ = new_errno; + } + + private: + int saved_errno_; + + DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer); +}; + +#endif // ERRNO_RESTORER_H diff --git a/bionic_macros.h b/bionic_macros.h new file mode 100644 index 0000000..4969bd9 --- /dev/null +++ b/bionic_macros.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _BIONIC_MACROS_H_ +#define _BIONIC_MACROS_H_ + +// Frameworks OpenGL code currently leaks this header and allows +// collisions with other declarations, e.g., from libnativehelper. +// TODO: Remove once cleaned up. b/18334516 +#if !defined(DISALLOW_COPY_AND_ASSIGN) +// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions. +// It goes in the private: declarations in a class. +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete +#endif // !defined(DISALLOW_COPY_AND_ASSIGN) + +// A macro to disallow all the implicit constructors, namely the +// default constructor, copy constructor and operator= functions. +// +// This should be used in the private: declarations for a class +// that wants to prevent anyone from instantiating it. This is +// especially useful for classes containing only static methods. +#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName() = delete; \ + DISALLOW_COPY_AND_ASSIGN(TypeName) + +#define BIONIC_ALIGN(value, alignment) \ + (((value) + (alignment) - 1) & ~((alignment) - 1)) + +#define BIONIC_ROUND_UP_POWER_OF_2(value) \ + ((sizeof(value) == 8) \ + ? (1UL << (64 - __builtin_clzl(static_cast(value)))) \ + : (1UL << (32 - __builtin_clz(static_cast(value))))) + +#endif // _BIONIC_MACROS_H_ diff --git a/bionic_netlink.cpp b/bionic_netlink.cpp new file mode 100644 index 0000000..436fdaa --- /dev/null +++ b/bionic_netlink.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "bionic_netlink.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ErrnoRestorer.h" + +NetlinkConnection::NetlinkConnection() { + fd_ = -1; + + // The kernel keeps packets under 8KiB (NLMSG_GOODSIZE), + // but that's a bit too large to go on the stack. + size_ = 8192; + data_ = new char[size_]; +} + +NetlinkConnection::~NetlinkConnection() { + ErrnoRestorer errno_restorer; + if (fd_ != -1) close(fd_); + delete[] data_; +} + +bool NetlinkConnection::SendRequest(int type) { + // Rather than force all callers to check for the unlikely event of being + // unable to allocate 8KiB, check here. + if (data_ == nullptr) return false; + + // Did we open a netlink socket yet? + if (fd_ == -1) { + +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC O_CLOEXEC +#endif + + fd_ = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); + if (fd_ == -1) return false; + } + + // Construct and send the message. + struct NetlinkMessage { + nlmsghdr hdr; + rtgenmsg msg; + } request; + memset(&request, 0, sizeof(request)); + request.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; + request.hdr.nlmsg_type = type; + request.hdr.nlmsg_len = sizeof(request); + request.msg.rtgen_family = AF_UNSPEC; // All families. + return (TEMP_FAILURE_RETRY(send(fd_, &request, sizeof(request), 0)) == sizeof(request)); +} + +bool NetlinkConnection::ReadResponses(void callback(void*, nlmsghdr*), void* context) { + // Read through all the responses, handing interesting ones to the callback. + ssize_t bytes_read; + while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd_, data_, size_, 0))) > 0) { + nlmsghdr* hdr = reinterpret_cast(data_); + for (; NLMSG_OK(hdr, static_cast(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) { + if (hdr->nlmsg_type == NLMSG_DONE) return true; + if (hdr->nlmsg_type == NLMSG_ERROR) { + nlmsgerr* err = reinterpret_cast(NLMSG_DATA(hdr)); + errno = (hdr->nlmsg_len >= NLMSG_LENGTH(sizeof(nlmsgerr))) ? -err->error : EIO; + return false; + } + callback(context, hdr); + } + } + + // We only get here if recv fails before we see a NLMSG_DONE. + return false; +} diff --git a/bionic_netlink.h b/bionic_netlink.h new file mode 100644 index 0000000..4b103f3 --- /dev/null +++ b/bionic_netlink.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef BIONIC_NETLINK_H +#define BIONIC_NETLINK_H + +#include + +#include +#include + +struct nlmsghdr; + +class NetlinkConnection { + public: + NetlinkConnection(); + ~NetlinkConnection(); + + bool SendRequest(int type); + bool ReadResponses(void callback(void*, nlmsghdr*), void* context); + + private: + int fd_; + char* data_; + size_t size_; +}; + +#if !defined(__clang__) +// GCC gets confused by NLMSG_DATA and doesn't realize that the old-style +// cast is from a system header and should be ignored. +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + +#endif diff --git a/ifaddrs.cpp b/ifaddrs.cpp new file mode 100644 index 0000000..7ddd46b --- /dev/null +++ b/ifaddrs.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ErrnoRestorer.h" + +#include "bionic_netlink.h" + +// The public ifaddrs struct is full of pointers. Rather than track several +// different allocations, we use a maximally-sized structure with the public +// part at offset 0, and pointers into its hidden tail. +struct ifaddrs_storage { + // Must come first, so that `ifaddrs_storage` is-a `ifaddrs`. + ifaddrs ifa; + + // The interface index, so we can match RTM_NEWADDR messages with + // earlier RTM_NEWLINK messages (to copy the interface flags). + int interface_index; + + // Storage for the pointers in `ifa`. + sockaddr_storage addr; + sockaddr_storage netmask; + sockaddr_storage ifa_ifu; + char name[IFNAMSIZ + 1]; + + explicit ifaddrs_storage(ifaddrs** list) { + memset(this, 0, sizeof(*this)); + + // push_front onto `list`. + ifa.ifa_next = *list; + *list = reinterpret_cast(this); + } + + void SetAddress(int family, const void* data, size_t byteCount) { + // The kernel currently uses the order IFA_ADDRESS, IFA_LOCAL, IFA_BROADCAST + // in inet_fill_ifaddr, but let's not assume that will always be true... + if (ifa.ifa_addr == nullptr) { + // This is an IFA_ADDRESS and haven't seen an IFA_LOCAL yet, so assume this is the + // local address. SetLocalAddress will fix things if we later see an IFA_LOCAL. + ifa.ifa_addr = CopyAddress(family, data, byteCount, &addr); + } else { + // We already saw an IFA_LOCAL, which implies this is a destination address. + ifa.ifa_dstaddr = CopyAddress(family, data, byteCount, &ifa_ifu); + } + } + + void SetBroadcastAddress(int family, const void* data, size_t byteCount) { + // ifa_broadaddr and ifa_dstaddr overlap in a union. Unfortunately, it's possible + // to have an interface with both. Keeping the last thing the kernel gives us seems + // to be glibc 2.19's behavior too, so our choice is being source compatible with + // badly-written code that assumes ifa_broadaddr and ifa_dstaddr are interchangeable + // or supporting interfaces with both addresses configured. My assumption is that + // bad code is more common than weird network interfaces... + ifa.ifa_broadaddr = CopyAddress(family, data, byteCount, &ifa_ifu); + } + + void SetLocalAddress(int family, const void* data, size_t byteCount) { + // The kernel source says "for point-to-point IFA_ADDRESS is DESTINATION address, + // local address is supplied in IFA_LOCAL attribute". + // -- http://lxr.free-electrons.com/source/include/uapi/linux/if_addr.h#L17 + + // So copy any existing IFA_ADDRESS into ifa_dstaddr... + if (ifa.ifa_addr != nullptr) { + ifa.ifa_dstaddr = reinterpret_cast(memcpy(&ifa_ifu, &addr, sizeof(addr))); + } + // ...and then put this IFA_LOCAL into ifa_addr. + ifa.ifa_addr = CopyAddress(family, data, byteCount, &addr); + } + + // Netlink gives us the prefix length as a bit count. We need to turn + // that into a BSD-compatible netmask represented by a sockaddr*. + void SetNetmask(int family, size_t prefix_length) { + // ...and work out the netmask from the prefix length. + netmask.ss_family = family; + uint8_t* dst = SockaddrBytes(family, &netmask); + memset(dst, 0xff, prefix_length / 8); + if ((prefix_length % 8) != 0) { + dst[prefix_length/8] = (0xff << (8 - (prefix_length % 8))); + } + ifa.ifa_netmask = reinterpret_cast(&netmask); + } + + void SetPacketAttributes(int ifindex, unsigned short hatype, unsigned char halen) { + sockaddr_ll* sll = reinterpret_cast(&addr); + sll->sll_ifindex = ifindex; + sll->sll_hatype = hatype; + sll->sll_halen = halen; + } + + private: + sockaddr* CopyAddress(int family, const void* data, size_t byteCount, sockaddr_storage* ss) { + // Netlink gives us the address family in the header, and the + // sockaddr_in or sockaddr_in6 bytes as the payload. We need to + // stitch the two bits together into the sockaddr that's part of + // our portable interface. + ss->ss_family = family; + memcpy(SockaddrBytes(family, ss), data, byteCount); + + // For IPv6 we might also have to set the scope id. + if (family == AF_INET6 && (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)data) || IN6_IS_ADDR_MC_LINKLOCAL((const struct in6_addr *)data))) { + reinterpret_cast(ss)->sin6_scope_id = interface_index; + } + + return reinterpret_cast(ss); + } + + // Returns a pointer to the first byte in the address data (which is + // stored in network byte order). + uint8_t* SockaddrBytes(int family, sockaddr_storage* ss) { + if (family == AF_INET) { + sockaddr_in* ss4 = reinterpret_cast(ss); + return reinterpret_cast(&ss4->sin_addr); + } else if (family == AF_INET6) { + sockaddr_in6* ss6 = reinterpret_cast(ss); + return reinterpret_cast(&ss6->sin6_addr); + } else if (family == AF_PACKET) { + sockaddr_ll* sll = reinterpret_cast(ss); + return reinterpret_cast(&sll->sll_addr); + } + return nullptr; + } +}; + +static void __getifaddrs_callback(void* context, nlmsghdr* hdr) { + ifaddrs** out = reinterpret_cast(context); + + if (hdr->nlmsg_type == RTM_NEWLINK) { + ifinfomsg* ifi = reinterpret_cast(NLMSG_DATA(hdr)); + + // Create a new ifaddr entry, and set the interface index and flags. + ifaddrs_storage* new_addr = new ifaddrs_storage(out); + new_addr->interface_index = ifi->ifi_index; + new_addr->ifa.ifa_flags = ifi->ifi_flags; + + // Go through the various bits of information and find the name. + rtattr* rta = IFLA_RTA(ifi); + size_t rta_len = IFLA_PAYLOAD(hdr); + while (RTA_OK(rta, rta_len)) { + if (rta->rta_type == IFLA_ADDRESS) { + if (RTA_PAYLOAD(rta) < sizeof(new_addr->addr)) { + new_addr->SetAddress(AF_PACKET, RTA_DATA(rta), RTA_PAYLOAD(rta)); + new_addr->SetPacketAttributes(ifi->ifi_index, ifi->ifi_type, RTA_PAYLOAD(rta)); + } + } else if (rta->rta_type == IFLA_BROADCAST) { + if (RTA_PAYLOAD(rta) < sizeof(new_addr->ifa_ifu)) { + new_addr->SetBroadcastAddress(AF_PACKET, RTA_DATA(rta), RTA_PAYLOAD(rta)); + new_addr->SetPacketAttributes(ifi->ifi_index, ifi->ifi_type, RTA_PAYLOAD(rta)); + } + } else if (rta->rta_type == IFLA_IFNAME) { + if (RTA_PAYLOAD(rta) < sizeof(new_addr->name)) { + memcpy(new_addr->name, RTA_DATA(rta), RTA_PAYLOAD(rta)); + new_addr->ifa.ifa_name = new_addr->name; + } + } + rta = RTA_NEXT(rta, rta_len); + } + } else if (hdr->nlmsg_type == RTM_NEWADDR) { + ifaddrmsg* msg = reinterpret_cast(NLMSG_DATA(hdr)); + + // We should already know about this from an RTM_NEWLINK message. + const ifaddrs_storage* addr = reinterpret_cast(*out); + while (addr != nullptr && addr->interface_index != static_cast(msg->ifa_index)) { + addr = reinterpret_cast(addr->ifa.ifa_next); + } + // If this is an unknown interface, ignore whatever we're being told about it. + if (addr == nullptr) return; + + // Create a new ifaddr entry and copy what we already know. + ifaddrs_storage* new_addr = new ifaddrs_storage(out); + // We can just copy the name rather than look for IFA_LABEL. + strcpy(new_addr->name, addr->name); + new_addr->ifa.ifa_name = new_addr->name; + new_addr->ifa.ifa_flags = addr->ifa.ifa_flags; + new_addr->interface_index = addr->interface_index; + + // Go through the various bits of information and find the address + // and any broadcast/destination address. + rtattr* rta = IFA_RTA(msg); + size_t rta_len = IFA_PAYLOAD(hdr); + while (RTA_OK(rta, rta_len)) { + if (rta->rta_type == IFA_ADDRESS) { + if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) { + new_addr->SetAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta)); + new_addr->SetNetmask(msg->ifa_family, msg->ifa_prefixlen); + } + } else if (rta->rta_type == IFA_BROADCAST) { + if (msg->ifa_family == AF_INET) { + new_addr->SetBroadcastAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta)); + } + } else if (rta->rta_type == IFA_LOCAL) { + if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) { + new_addr->SetLocalAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta)); + } + } + rta = RTA_NEXT(rta, rta_len); + } + } +} + +int getifaddrs(ifaddrs** out) { + // We construct the result directly into `out`, so terminate the list. + *out = nullptr; + + // Open the netlink socket and ask for all the links and addresses. + NetlinkConnection nc; + bool okay = nc.SendRequest(RTM_GETLINK) && nc.ReadResponses(__getifaddrs_callback, out) && + nc.SendRequest(RTM_GETADDR) && nc.ReadResponses(__getifaddrs_callback, out); + if (!okay) { + freeifaddrs(*out); + // Ensure that callers crash if they forget to check for success. + *out = nullptr; + return -1; + } + + return 0; +} + +void freeifaddrs(ifaddrs* list) { + while (list != nullptr) { + ifaddrs* current = list; + list = list->ifa_next; + free(current); + } +} diff --git a/ifaddrs.h b/ifaddrs.h index 9cd19fe..54a5a2c 100644 --- a/ifaddrs.h +++ b/ifaddrs.h @@ -1,54 +1,59 @@ /* - * Copyright (c) 1995, 1999 - * Berkeley Software Design, Inc. All rights reserved. + * Copyright (C) 2015 The Android Open Source Project + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * 1. Redistributions of source code must retain the above copyright + * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. * - * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp */ -#ifndef _IFADDRS_H_ -#define _IFADDRS_H_ +#ifndef _IFADDRS_H_ +#define _IFADDRS_H_ + +#include +#include +#include + +__BEGIN_DECLS struct ifaddrs { - struct ifaddrs *ifa_next; - char *ifa_name; - unsigned int ifa_flags; - struct sockaddr *ifa_addr; - struct sockaddr *ifa_netmask; - struct sockaddr *ifa_dstaddr; - void *ifa_data; + struct ifaddrs* ifa_next; + char* ifa_name; + unsigned int ifa_flags; + struct sockaddr* ifa_addr; + struct sockaddr* ifa_netmask; + union { + struct sockaddr* ifu_broadaddr; + struct sockaddr* ifu_dstaddr; + } ifa_ifu; + void* ifa_data; }; -/* - * This may have been defined in . Note that if is - * to be included it must be included before this header file. - */ -#ifndef ifa_broadaddr -#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ -#endif +#define ifa_broadaddr ifa_ifu.ifu_broadaddr +#define ifa_dstaddr ifa_ifu.ifu_dstaddr -#include +void freeifaddrs(struct ifaddrs*); +int getifaddrs(struct ifaddrs**); -__BEGIN_DECLS -extern int getifaddrs(struct ifaddrs **ifap); -extern void freeifaddrs(struct ifaddrs *ifa); __END_DECLS #endif diff --git a/ifaddrs.c b/ifaddrs.old.cpp.txt similarity index 76% rename from ifaddrs.c rename to ifaddrs.old.cpp.txt index 338fff8..1184ba2 100644 --- a/ifaddrs.c +++ b/ifaddrs.old.cpp.txt @@ -22,6 +22,11 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define TRACE_DEBUG_IFADDRS 1 +#ifdef TRACE_DEBUG_IFADDRS +#include +#endif + #include "ifaddrs.h" #include @@ -33,6 +38,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#ifdef TRACE_DEBUG_IFADDRS +#define trace(a) qDebug() << a; +#else +#define trace(a) +#endif typedef struct NetlinkList { @@ -119,12 +129,12 @@ static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done) { size_t l_size = 4096; - void *l_buffer = NULL; + struct nlmsghdr * l_buffer = NULL; for(;;) { - free(l_buffer); - l_buffer = malloc(l_size); + if(l_buffer) free(l_buffer); + l_buffer = (struct nlmsghdr *)malloc(l_size); int l_read = netlink_recv(p_socket, l_buffer, l_size); *p_size = l_read; @@ -137,7 +147,7 @@ static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_don { pid_t l_pid = getpid(); struct nlmsghdr *l_hdr; - for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) + for(l_hdr = l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) { if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) { @@ -165,7 +175,7 @@ static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_don static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size) { - NetlinkList *l_item = malloc(sizeof(NetlinkList)); + NetlinkList *l_item = (NetlinkList *)malloc(sizeof(NetlinkList)); l_item->m_next = NULL; l_item->m_data = p_data; l_item->m_size = p_size; @@ -238,7 +248,7 @@ static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) } } -static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size) +static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, const char *p_data, size_t p_size) { switch(p_family) { @@ -307,7 +317,10 @@ static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, stru } } - struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize + l_dataSize); + struct ifaddrs *l_entry = (struct ifaddrs *)malloc(sizeof(struct ifaddrs) + + l_nameSize + + l_addrSize + + l_dataSize); memset(l_entry, 0, sizeof(struct ifaddrs)); l_entry->ifa_name = ""; @@ -320,7 +333,7 @@ static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, stru l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { - void *l_rtaData = RTA_DATA(l_rta); + const char *l_rtaData = (const char *)RTA_DATA(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); switch(l_rta->rta_type) { @@ -362,158 +375,235 @@ static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, stru static void interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList) { + trace("interpretAddr.trace1") struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); + trace("interpretAddr.trace2") size_t l_nameSize = 0; size_t l_addrSize = 0; - + trace("interpretAddr.trace3") + int l_addedNetmask = 0; + trace("interpretAddr.trace4") size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); struct rtattr *l_rta; + trace("interpretAddr.trace5") for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { + trace("interpretAddr.trace6") void *l_rtaData = RTA_DATA(l_rta); + trace("interpretAddr.trace7") size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); + trace("interpretAddr.trace8") if(l_info->ifa_family == AF_PACKET) { + trace("interpretAddr.trace9") continue; } + trace("interpretAddr.traceA") switch(l_rta->rta_type) { case IFA_ADDRESS: case IFA_LOCAL: + trace("interpretAddr.traceB") if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) { // make room for netmask + trace("interpretAddr.traceC") l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); + trace("interpretAddr.traceD") l_addedNetmask = 1; + trace("interpretAddr.traceE") } + //TEST HYPN'S HYPOTHESIS + break; + //END OF TEST case IFA_BROADCAST: + trace("interpretAddr.traceF") l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); + trace("interpretAddr.trace10") break; case IFA_LABEL: + trace("interpretAddr.trace11") l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); + trace("interpretAddr.trace12") break; default: + trace("interpretAddr.trace13") break; } + trace("interpretAddr.trace14") } - struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); + trace("interpretAddr.trace15") + struct ifaddrs *l_entry = (struct ifaddrs *) malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); + trace("interpretAddr.trace16") memset(l_entry, 0, sizeof(struct ifaddrs)); + trace("interpretAddr.trace17") l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name; + trace("interpretAddr.trace18") char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs); + trace("interpretAddr.trace19") char *l_addr = l_name + l_nameSize; + trace("interpretAddr.trace1A") l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - 1]->ifa_flags; + trace("interpretAddr.trace1B") l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); + trace("interpretAddr.trace1C") for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { - void *l_rtaData = RTA_DATA(l_rta); + trace("interpretAddr.trace1D") + const char *l_rtaData = (const char *)RTA_DATA(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); + trace("interpretAddr.trace1E") switch(l_rta->rta_type) { case IFA_ADDRESS: case IFA_BROADCAST: case IFA_LOCAL: { + trace("interpretAddr.trace1F") size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); + trace("interpretAddr.trace20") if(l_info->ifa_family == AF_INET6) { + trace("interpretAddr.trace21") if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) { + trace("interpretAddr.trace22") ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index; } } - + trace("interpretAddr.trace23") + if(l_rta->rta_type == IFA_ADDRESS) { // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address + trace("interpretAddr.trace24") if(l_entry->ifa_addr) { + trace("interpretAddr.trace25") l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; } else { + trace("interpretAddr.trace26") l_entry->ifa_addr = (struct sockaddr *)l_addr; } } else if(l_rta->rta_type == IFA_LOCAL) { + trace("interpretAddr.trace27") if(l_entry->ifa_addr) { + trace("interpretAddr.trace28") l_entry->ifa_dstaddr = l_entry->ifa_addr; } + trace("interpretAddr.trace29") l_entry->ifa_addr = (struct sockaddr *)l_addr; } else { + trace("interpretAddr.trace2A") l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; } + trace("interpretAddr.trace2B") l_addr += NLMSG_ALIGN(l_addrLen); + trace("interpretAddr.trace2C") break; } case IFA_LABEL: + trace("interpretAddr.trace2D") strncpy(l_name, l_rtaData, l_rtaDataSize); + trace("interpretAddr.trace2E") l_name[l_rtaDataSize] = '\0'; + trace("interpretAddr.trace2F") l_entry->ifa_name = l_name; + trace("interpretAddr.trace30") break; default: + trace("interpretAddr.trace31") break; } + trace("interpretAddr.trace32") } + trace("interpretAddr.trace33") if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) { + trace("interpretAddr.trace34") unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128); unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen); char l_mask[16] = {0}; unsigned i; + trace("interpretAddr.trace35") for(i=0; i<(l_prefix/8); ++i) { l_mask[i] = 0xff; } l_mask[i] = 0xff << (8 - (l_prefix % 8)); + trace("interpretAddr.trace36") makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8); l_entry->ifa_netmask = (struct sockaddr *)l_addr; + trace("interpretAddr.trace37") } + trace("interpretAddr.trace38") addToEnd(p_resultList, l_entry); + trace("interpretAddr.trace39") } static void interpret(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_links, struct ifaddrs **p_resultList) { + trace("ifaddrs.interpret: entered"); pid_t l_pid = getpid(); + trace("ifaddrs.interpret: after getpid"); for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) { + trace("ifaddrs.interpret: trace1"); unsigned int l_nlsize = p_netlinkList->m_size; + trace("ifaddrs.interpret: trace2"); struct nlmsghdr *l_hdr; + trace("ifaddrs.interpret: trace3"); for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) { + trace("ifaddrs.interpret: trace4"); if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) { + trace("ifaddrs.interpret: trace5"); continue; } - + trace("ifaddrs.interpret: trace6"); + if(l_hdr->nlmsg_type == NLMSG_DONE) { + trace("ifaddrs.interpret: trace7"); break; } + trace("ifaddrs.interpret: trace8"); if(l_hdr->nlmsg_type == RTM_NEWLINK) { + trace("ifaddrs.interpret: trace9"); interpretLink(l_hdr, p_links, p_resultList); + trace("ifaddrs.interpret: traceA"); } else if(l_hdr->nlmsg_type == RTM_NEWADDR) { + trace("ifaddrs.interpret: traceB"); interpretAddr(l_hdr, p_links, p_resultList); + trace("ifaddrs.interpret: traceC"); } + trace("ifaddrs.interpret: traceD"); } + trace("ifaddrs.interpret: traceE"); } + trace("ifaddrs.interpret: leaving"); } static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList) @@ -548,43 +638,64 @@ static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList) int getifaddrs(struct ifaddrs **ifap) { + qDebug() << "entered getifaddrs"; if(!ifap) { + trace("leaving getifaddrs: !ifap\n"); return -1; } + trace("getifaddrs: before *ifap = NULL\n"); *ifap = NULL; + trace("getifaddrs: before netlink_socket()\n"); int l_socket = netlink_socket(); if(l_socket < 0) { + trace("getifaddrs: leave, l_socket < 0\n"); return -1; } + trace("getifaddrs: before getResultList(l_socket, RTM_GETLINK)\n"); NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK); if(!l_linkResults) { + trace("getifaddrs: before close(l_socket)\n"); close(l_socket); + trace("getifaddrs: before return -1\n"); return -1; } + trace("getifaddrs: before getResultList(l_socket, RTM_GETADDR)\n"); NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR); if(!l_addrResults) { + trace("getifaddrs: before close(l_socket)\n"); close(l_socket); + trace("getifaddrs: before freeResultList\n"); freeResultList(l_linkResults); + trace("getifaddrs: before return -1\n"); return -1; } + trace("getifaddrs: before countLinks\n"); unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults); + trace("getifaddrs: before struct ifaddrs *l_links\n"); struct ifaddrs *l_links[l_numLinks]; + trace("getifaddrs: before memset l_links\n"); memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *)); + trace("getifaddrs: before interpret 1\n"); interpret(l_socket, l_linkResults, l_links, ifap); + trace("getifaddrs: before interpret 2\n"); interpret(l_socket, l_addrResults, l_links, ifap); + trace("getifaddrs: before freeResultList(l_linkResults)\n"); freeResultList(l_linkResults); + trace("getifaddrs: before freeResultList(l_addrResults)\n"); freeResultList(l_addrResults); + trace("getifaddrs: before close(l_socket)\n"); close(l_socket); + trace("getifaddrs: leaving, return 0\n"); return 0; } diff --git a/ifaddrs.old.h.txt b/ifaddrs.old.h.txt new file mode 100644 index 0000000..9cd19fe --- /dev/null +++ b/ifaddrs.old.h.txt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1995, 1999 + * Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp + */ + +#ifndef _IFADDRS_H_ +#define _IFADDRS_H_ + +struct ifaddrs { + struct ifaddrs *ifa_next; + char *ifa_name; + unsigned int ifa_flags; + struct sockaddr *ifa_addr; + struct sockaddr *ifa_netmask; + struct sockaddr *ifa_dstaddr; + void *ifa_data; +}; + +/* + * This may have been defined in . Note that if is + * to be included it must be included before this header file. + */ +#ifndef ifa_broadaddr +#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ +#endif + +#include + +__BEGIN_DECLS +extern int getifaddrs(struct ifaddrs **ifap); +extern void freeifaddrs(struct ifaddrs *ifa); +__END_DECLS + +#endif