/*====================================================================* * * Copyright (c) 2013 Qualcomm Atheros, Inc. * * All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted (subject to the limitations * in the disclaimer below) 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. * * * Neither the name of Qualcomm Atheros nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE * GRANTED BY THIS LICENSE. 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. * *--------------------------------------------------------------------*/ /*====================================================================* * * unsigned hostnics (struct nic list [], unsigned size); * * ether.h * * encode an external memory region with a packed list of available * nost network interfaces; return the number of interfaces found; * each interface has an index, ethernet address, internet address, * name and description; * * this function is implemented for Linux and MacOSX; * * * Contributor(s): * Charles Maier <cmaier@qca.qualcomm.com> * *--------------------------------------------------------------------*/ #ifndef HOSTNICS_SOURCE #define HOSTNICS_SOURCE #if defined (__linux__) # include <net/if.h> # include <net/ethernet.h> # include <sys/ioctl.h> #elif defined (__linux__) # include <net/if.h> # include <netpacket/packet.h> # include <ifaddrs.h> #elif defined (__APPLE__) || defined (__OpenBSD__) # include <sys/types.h> # include <sys/socket.h> # include <net/if.h> # include <net/if_dl.h> # include <net/if_types.h> # include <ifaddrs.h> #elif defined (WIN32) #error "Not implemented for Windows" #else #error "Unknown environment" #endif #include <unistd.h> #include <memory.h> #include <errno.h> #include "../ether/ether.h" #include "../tools/error.h" unsigned hostnics (struct nic nics [], unsigned size) { #if defined (__linux__) /* * native method on Linux systems; */ char buffer [1024]; struct ifconf ifconf; struct ifreq * ifreq; unsigned next; signed fd; memset (nics, 0, size * sizeof (struct nic)); ifconf.ifc_len = sizeof (buffer); ifconf.ifc_buf = buffer; if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { error (1, errno, "Can't open socket"); } if (ioctl (fd, SIOCGIFCONF, &ifconf) < 0) { error (1, errno, "Can't read socket configuration"); } ifreq = ifconf.ifc_req; next = ifconf.ifc_len / sizeof (struct ifreq); if (next > size) { next = size; } if (next < size) { size = next; } for (next = 0; next < size; next++) { struct nic * nic = &nics [next]; struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)(&ifreq->ifr_addr); memcpy (nic->ifname, ifreq->ifr_name, sizeof (nic->ifname)); memcpy (nic->ifdesc, ifreq->ifr_name, sizeof (nic->ifdesc)); memcpy (nic->internet, &sockaddr_in->sin_addr, sizeof (nic->internet)); if (ioctl (fd, SIOCGIFHWADDR, ifreq) == -1) { error (0, errno, "Can't read hardware address: %s", ifreq->ifr_name); } memcpy (nic->ethernet, ifreq->ifr_hwaddr.sa_data, sizeof (nic->ethernet)); if (ioctl (fd, SIOCGIFINDEX, ifreq) == -1) { error (0, errno, "Can't read interface index: %s", ifreq->ifr_name); } nic->ifindex = ifreq->ifr_ifindex; ifreq++; } close (fd); #elif defined (__linux__) || defined (__APPLE__) || defined (__OpenBSD__) /* * generic (POSIX) method for unix-like systems; */ struct ifaddrs * ifaddrs; memset (nics, 0, size * sizeof (struct nic)); unsigned next = 0; if (getifaddrs (&ifaddrs) != -1) { struct ifaddrs * ifaddr; for (ifaddr = ifaddrs; ifaddr && size; ifaddr = ifaddr->ifa_next) { struct nic * nic = &nics [next]; struct nic * tmp = nics; if (!ifaddr->ifa_addr) { continue; } nic->ifindex = if_nametoindex (ifaddr->ifa_name); for (tmp = nics; tmp->ifindex != nic->ifindex; tmp++); if (tmp == nic) { next++; size--; } else { nic = tmp; } memcpy (nic->ifname, ifaddr->ifa_name, sizeof (nic->ifname)); memcpy (nic->ifdesc, ifaddr->ifa_name, sizeof (nic->ifdesc)); if (ifaddr->ifa_addr->sa_family == AF_INET) { struct sockaddr_in * sockaddr_in = (struct sockaddr_in *) (ifaddr->ifa_addr); struct in_addr * in_addr = (struct in_addr *)(&sockaddr_in->sin_addr); memcpy (nic->internet, &in_addr->s_addr, sizeof (nic->internet)); } #if defined (__linux__) #define LLADDR(socket) &(socket)->sll_addr if (ifaddr->ifa_addr->sa_family == AF_PACKET) { struct sockaddr_ll * sockaddr_ll = (struct sockaddr_ll *) (ifaddr->ifa_addr); memcpy (nic->ethernet, LLADDR (sockaddr_ll), sizeof (nic->ethernet)); } #elif defined (__APPLE__) || defined (__OpenBSD__) if (ifaddr->ifa_addr->sa_family == AF_LINK) { struct sockaddr_dl * sockaddr_dl = (struct sockaddr_dl *) (ifaddr->ifa_addr); if (sockaddr_dl->sdl_type == IFT_ETHER) { #if 1 memcpy (nic->ethernet, LLADDR (sockaddr_dl), sizeof (nic->ethernet)); #else memcpy (nic->ethernet, LLADDR (sockaddr_dl), sockaddr_dl->sdl_alen); #endif } } #else #error "Abandon all hope!" #endif } freeifaddrs (ifaddrs); } #else #error "Unknown environment" #endif return (next); } #endif