Browse Source

fetched sources from android source. tested, they seem to work okay

master
hypnosis-i2p 8 years ago
parent
commit
6289f998c7
  1. 43
      ErrnoRestorer.h
  2. 49
      bionic_macros.h
  3. 106
      bionic_netlink.cpp
  4. 59
      bionic_netlink.h
  5. 260
      ifaddrs.cpp
  6. 75
      ifaddrs.h
  7. 137
      ifaddrs.old.cpp.txt
  8. 54
      ifaddrs.old.h.txt

43
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 <errno.h>
#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

49
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<unsigned long>(value)))) \
: (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value)))))
#endif // _BIONIC_MACROS_H_

106
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 <errno.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#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<nlmsghdr*>(data_);
for (; NLMSG_OK(hdr, static_cast<size_t>(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<nlmsgerr*>(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;
}

59
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 <sys/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
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

260
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 <ifaddrs.h>
#include <errno.h>
#include <linux/if_packet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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<ifaddrs*>(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<sockaddr*>(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<sockaddr*>(&netmask);
}
void SetPacketAttributes(int ifindex, unsigned short hatype, unsigned char halen) {
sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(&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<sockaddr_in6*>(ss)->sin6_scope_id = interface_index;
}
return reinterpret_cast<sockaddr*>(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<sockaddr_in*>(ss);
return reinterpret_cast<uint8_t*>(&ss4->sin_addr);
} else if (family == AF_INET6) {
sockaddr_in6* ss6 = reinterpret_cast<sockaddr_in6*>(ss);
return reinterpret_cast<uint8_t*>(&ss6->sin6_addr);
} else if (family == AF_PACKET) {
sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ss);
return reinterpret_cast<uint8_t*>(&sll->sll_addr);
}
return nullptr;
}
};
static void __getifaddrs_callback(void* context, nlmsghdr* hdr) {
ifaddrs** out = reinterpret_cast<ifaddrs**>(context);
if (hdr->nlmsg_type == RTM_NEWLINK) {
ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(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<ifaddrmsg*>(NLMSG_DATA(hdr));
// We should already know about this from an RTM_NEWLINK message.
const ifaddrs_storage* addr = reinterpret_cast<const ifaddrs_storage*>(*out);
while (addr != nullptr && addr->interface_index != static_cast<int>(msg->ifa_index)) {
addr = reinterpret_cast<const ifaddrs_storage*>(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);
}
}

75
ifaddrs.h

@ -1,54 +1,59 @@
/* /*
* Copyright (c) 1995, 1999 * Copyright (C) 2015 The Android Open Source Project
* Berkeley Software Design, Inc. All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * 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. * 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 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * 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. * SUCH DAMAGE.
*
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
*/ */
#ifndef _IFADDRS_H_ #ifndef _IFADDRS_H_
#define _IFADDRS_H_ #define _IFADDRS_H_
#include <sys/cdefs.h>
#include <netinet/in.h>
#include <sys/socket.h>
__BEGIN_DECLS
struct ifaddrs { struct ifaddrs {
struct ifaddrs *ifa_next; struct ifaddrs* ifa_next;
char *ifa_name; char* ifa_name;
unsigned int ifa_flags; unsigned int ifa_flags;
struct sockaddr *ifa_addr; struct sockaddr* ifa_addr;
struct sockaddr *ifa_netmask; struct sockaddr* ifa_netmask;
struct sockaddr *ifa_dstaddr; union {
void *ifa_data; struct sockaddr* ifu_broadaddr;
struct sockaddr* ifu_dstaddr;
} ifa_ifu;
void* ifa_data;
}; };
/* #define ifa_broadaddr ifa_ifu.ifu_broadaddr
* This may have been defined in <net/if.h>. Note that if <net/if.h> is #define ifa_dstaddr ifa_ifu.ifu_dstaddr
* to be included it must be included before this header file.
*/
#ifndef ifa_broadaddr
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
#endif
#include <sys/cdefs.h> void freeifaddrs(struct ifaddrs*);
int getifaddrs(struct ifaddrs**);
__BEGIN_DECLS
extern int getifaddrs(struct ifaddrs **ifap);
extern void freeifaddrs(struct ifaddrs *ifa);
__END_DECLS __END_DECLS
#endif #endif

137
ifaddrs.c → 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. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#define TRACE_DEBUG_IFADDRS 1
#ifdef TRACE_DEBUG_IFADDRS
#include <QDebug>
#endif
#include "ifaddrs.h" #include "ifaddrs.h"
#include <string.h> #include <string.h>
@ -33,6 +38,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <netinet/in.h> #include <netinet/in.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#ifdef TRACE_DEBUG_IFADDRS
#define trace(a) qDebug() << a;
#else
#define trace(a)
#endif
typedef struct NetlinkList 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) static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
{ {
size_t l_size = 4096; size_t l_size = 4096;
void *l_buffer = NULL; struct nlmsghdr * l_buffer = NULL;
for(;;) for(;;)
{ {
free(l_buffer); if(l_buffer) free(l_buffer);
l_buffer = malloc(l_size); l_buffer = (struct nlmsghdr *)malloc(l_size);
int l_read = netlink_recv(p_socket, l_buffer, l_size); int l_read = netlink_recv(p_socket, l_buffer, l_size);
*p_size = l_read; *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(); pid_t l_pid = getpid();
struct nlmsghdr *l_hdr; 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) 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) 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_next = NULL;
l_item->m_data = p_data; l_item->m_data = p_data;
l_item->m_size = p_size; 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) 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)); memset(l_entry, 0, sizeof(struct ifaddrs));
l_entry->ifa_name = ""; 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)); 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)) 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); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
switch(l_rta->rta_type) 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) 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); struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
trace("interpretAddr.trace2")
size_t l_nameSize = 0; size_t l_nameSize = 0;
size_t l_addrSize = 0; size_t l_addrSize = 0;
trace("interpretAddr.trace3")
int l_addedNetmask = 0; int l_addedNetmask = 0;
trace("interpretAddr.trace4")
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
struct rtattr *l_rta; 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)) 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); void *l_rtaData = RTA_DATA(l_rta);
trace("interpretAddr.trace7")
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
trace("interpretAddr.trace8")
if(l_info->ifa_family == AF_PACKET) if(l_info->ifa_family == AF_PACKET)
{ {
trace("interpretAddr.trace9")
continue; continue;
} }
trace("interpretAddr.traceA")
switch(l_rta->rta_type) switch(l_rta->rta_type)
{ {
case IFA_ADDRESS: case IFA_ADDRESS:
case IFA_LOCAL: case IFA_LOCAL:
trace("interpretAddr.traceB")
if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
{ // make room for netmask { // make room for netmask
trace("interpretAddr.traceC")
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
trace("interpretAddr.traceD")
l_addedNetmask = 1; l_addedNetmask = 1;
trace("interpretAddr.traceE")
} }
//TEST HYPN'S HYPOTHESIS
break;
//END OF TEST
case IFA_BROADCAST: case IFA_BROADCAST:
trace("interpretAddr.traceF")
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
trace("interpretAddr.trace10")
break; break;
case IFA_LABEL: case IFA_LABEL:
trace("interpretAddr.trace11")
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
trace("interpretAddr.trace12")
break; break;
default: default:
trace("interpretAddr.trace13")
break; 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)); memset(l_entry, 0, sizeof(struct ifaddrs));
trace("interpretAddr.trace17")
l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name; 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); char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
trace("interpretAddr.trace19")
char *l_addr = l_name + l_nameSize; 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; 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)); 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)) 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); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
trace("interpretAddr.trace1E")
switch(l_rta->rta_type) switch(l_rta->rta_type)
{ {
case IFA_ADDRESS: case IFA_ADDRESS:
case IFA_BROADCAST: case IFA_BROADCAST:
case IFA_LOCAL: case IFA_LOCAL:
{ {
trace("interpretAddr.trace1F")
size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, 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) 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)) 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; ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
} }
} }
trace("interpretAddr.trace23")
if(l_rta->rta_type == IFA_ADDRESS) 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 { // 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) if(l_entry->ifa_addr)
{ {
trace("interpretAddr.trace25")
l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
} }
else else
{ {
trace("interpretAddr.trace26")
l_entry->ifa_addr = (struct sockaddr *)l_addr; l_entry->ifa_addr = (struct sockaddr *)l_addr;
} }
} }
else if(l_rta->rta_type == IFA_LOCAL) else if(l_rta->rta_type == IFA_LOCAL)
{ {
trace("interpretAddr.trace27")
if(l_entry->ifa_addr) if(l_entry->ifa_addr)
{ {
trace("interpretAddr.trace28")
l_entry->ifa_dstaddr = l_entry->ifa_addr; l_entry->ifa_dstaddr = l_entry->ifa_addr;
} }
trace("interpretAddr.trace29")
l_entry->ifa_addr = (struct sockaddr *)l_addr; l_entry->ifa_addr = (struct sockaddr *)l_addr;
} }
else else
{ {
trace("interpretAddr.trace2A")
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
} }
trace("interpretAddr.trace2B")
l_addr += NLMSG_ALIGN(l_addrLen); l_addr += NLMSG_ALIGN(l_addrLen);
trace("interpretAddr.trace2C")
break; break;
} }
case IFA_LABEL: case IFA_LABEL:
trace("interpretAddr.trace2D")
strncpy(l_name, l_rtaData, l_rtaDataSize); strncpy(l_name, l_rtaData, l_rtaDataSize);
trace("interpretAddr.trace2E")
l_name[l_rtaDataSize] = '\0'; l_name[l_rtaDataSize] = '\0';
trace("interpretAddr.trace2F")
l_entry->ifa_name = l_name; l_entry->ifa_name = l_name;
trace("interpretAddr.trace30")
break; break;
default: default:
trace("interpretAddr.trace31")
break; 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)) 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_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); unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
char l_mask[16] = {0}; char l_mask[16] = {0};
unsigned i; unsigned i;
trace("interpretAddr.trace35")
for(i=0; i<(l_prefix/8); ++i) for(i=0; i<(l_prefix/8); ++i)
{ {
l_mask[i] = 0xff; l_mask[i] = 0xff;
} }
l_mask[i] = 0xff << (8 - (l_prefix % 8)); 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); makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
l_entry->ifa_netmask = (struct sockaddr *)l_addr; l_entry->ifa_netmask = (struct sockaddr *)l_addr;
trace("interpretAddr.trace37")
} }
trace("interpretAddr.trace38")
addToEnd(p_resultList, l_entry); 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) 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(); pid_t l_pid = getpid();
trace("ifaddrs.interpret: after getpid");
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
{ {
trace("ifaddrs.interpret: trace1");
unsigned int l_nlsize = p_netlinkList->m_size; unsigned int l_nlsize = p_netlinkList->m_size;
trace("ifaddrs.interpret: trace2");
struct nlmsghdr *l_hdr; 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)) 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) if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
{ {
trace("ifaddrs.interpret: trace5");
continue; continue;
} }
trace("ifaddrs.interpret: trace6");
if(l_hdr->nlmsg_type == NLMSG_DONE) if(l_hdr->nlmsg_type == NLMSG_DONE)
{ {
trace("ifaddrs.interpret: trace7");
break; break;
} }
trace("ifaddrs.interpret: trace8");
if(l_hdr->nlmsg_type == RTM_NEWLINK) if(l_hdr->nlmsg_type == RTM_NEWLINK)
{ {
trace("ifaddrs.interpret: trace9");
interpretLink(l_hdr, p_links, p_resultList); interpretLink(l_hdr, p_links, p_resultList);
trace("ifaddrs.interpret: traceA");
} }
else if(l_hdr->nlmsg_type == RTM_NEWADDR) else if(l_hdr->nlmsg_type == RTM_NEWADDR)
{ {
trace("ifaddrs.interpret: traceB");
interpretAddr(l_hdr, p_links, p_resultList); 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) 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) int getifaddrs(struct ifaddrs **ifap)
{ {
qDebug() << "entered getifaddrs";
if(!ifap) if(!ifap)
{ {
trace("leaving getifaddrs: !ifap\n");
return -1; return -1;
} }
trace("getifaddrs: before *ifap = NULL\n");
*ifap = NULL; *ifap = NULL;
trace("getifaddrs: before netlink_socket()\n");
int l_socket = netlink_socket(); int l_socket = netlink_socket();
if(l_socket < 0) if(l_socket < 0)
{ {
trace("getifaddrs: leave, l_socket < 0\n");
return -1; return -1;
} }
trace("getifaddrs: before getResultList(l_socket, RTM_GETLINK)\n");
NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK); NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
if(!l_linkResults) if(!l_linkResults)
{ {
trace("getifaddrs: before close(l_socket)\n");
close(l_socket); close(l_socket);
trace("getifaddrs: before return -1\n");
return -1; return -1;
} }
trace("getifaddrs: before getResultList(l_socket, RTM_GETADDR)\n");
NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR); NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
if(!l_addrResults) if(!l_addrResults)
{ {
trace("getifaddrs: before close(l_socket)\n");
close(l_socket); close(l_socket);
trace("getifaddrs: before freeResultList\n");
freeResultList(l_linkResults); freeResultList(l_linkResults);
trace("getifaddrs: before return -1\n");
return -1; return -1;
} }
trace("getifaddrs: before countLinks\n");
unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults); 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]; struct ifaddrs *l_links[l_numLinks];
trace("getifaddrs: before memset l_links\n");
memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *)); memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *));
trace("getifaddrs: before interpret 1\n");
interpret(l_socket, l_linkResults, l_links, ifap); interpret(l_socket, l_linkResults, l_links, ifap);
trace("getifaddrs: before interpret 2\n");
interpret(l_socket, l_addrResults, l_links, ifap); interpret(l_socket, l_addrResults, l_links, ifap);
trace("getifaddrs: before freeResultList(l_linkResults)\n");
freeResultList(l_linkResults); freeResultList(l_linkResults);
trace("getifaddrs: before freeResultList(l_addrResults)\n");
freeResultList(l_addrResults); freeResultList(l_addrResults);
trace("getifaddrs: before close(l_socket)\n");
close(l_socket); close(l_socket);
trace("getifaddrs: leaving, return 0\n");
return 0; return 0;
} }

54
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 <net/if.h>. Note that if <net/if.h> 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 <sys/cdefs.h>
__BEGIN_DECLS
extern int getifaddrs(struct ifaddrs **ifap);
extern void freeifaddrs(struct ifaddrs *ifa);
__END_DECLS
#endif
Loading…
Cancel
Save