diff options
author | Samuel Tan <samueltan@google.com> | 2015-08-20 11:04:41 -0700 |
---|---|---|
committer | Samuel Tan <samueltan@google.com> | 2015-08-20 11:10:32 -0700 |
commit | 71df777a3ab1a98a30e32ef482e8b28409a3989e (patch) | |
tree | d758626ca6e84d1f517321aae4b2d99f45c30a24 | |
parent | 68df7cfd9156424667636ad3544d0fa9f337647d (diff) | |
download | dhcpcd-6.8.2-71df777a3ab1a98a30e32ef482e8b28409a3989e.tar.gz |
dhcpcd-6.8.2: add ifaddrs.c and ifaddrs.h
Add an Android implementation of ifaddrs to the
dhcpcd-6.8.2 repo, which this daemon depends on.
ifaddr.c cherry-picked from
https://googleplex-android.git.corp.google.com/platform/external/dhcpcd/+/master
at 31db56e5b40726fed587656ac1730705c79741b9.
ifaddr.h cherry-picked from
https://googleplex-android.git.corp.google.com/platform/external/dhcpcd/+/master
at e86eee143ed21592f88a46623a81f71002430459.
BUG: 22956197
Change-Id: Id19c9ee8e7c0c32b36742052f9ee63dc197aa218
-rw-r--r-- | ifaddrs.c | 149 | ||||
-rw-r--r-- | ifaddrs.h | 34 |
2 files changed, 183 insertions, 0 deletions
diff --git a/ifaddrs.c b/ifaddrs.c new file mode 100644 index 0000000..a88bcc1 --- /dev/null +++ b/ifaddrs.c @@ -0,0 +1,149 @@ +/* external/dhcpcd-6.8.2/ifaddrs.c +** Copied from external/dhcpcd/ifaddrs.c. +** +** Copyright 2011, 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. +*/ + +#include <arpa/inet.h> +#include <sys/socket.h> +#include "ifaddrs.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <dirent.h> +#include <netinet/ether.h> +#include <netdb.h> +#include <linux/if_packet.h> +#include <netinet/if_ether.h> +#include <linux/if_arp.h> +#include <netutils/ifc.h> + +struct ifaddrs *get_interface(const char *name, sa_family_t family) +{ + unsigned addr, flags; + int masklen; + struct ifaddrs *ifa; + struct sockaddr_in *saddr = NULL; + struct sockaddr_in *smask = NULL; + struct sockaddr_ll *hwaddr = NULL; + unsigned char hwbuf[ETH_ALEN]; + + if (ifc_get_info(name, &addr, &masklen, &flags)) + return NULL; + + if ((family == AF_INET) && (addr == 0)) + return NULL; + + ifa = malloc(sizeof(struct ifaddrs)); + if (!ifa) + return NULL; + memset(ifa, 0, sizeof(struct ifaddrs)); + + ifa->ifa_name = malloc(strlen(name)+1); + if (!ifa->ifa_name) { + free(ifa); + return NULL; + } + strcpy(ifa->ifa_name, name); + ifa->ifa_flags = flags; + + if (family == AF_INET) { + saddr = malloc(sizeof(struct sockaddr_in)); + if (saddr) { + saddr->sin_addr.s_addr = addr; + saddr->sin_family = family; + } + ifa->ifa_addr = (struct sockaddr *)saddr; + + if (masklen != 0) { + smask = malloc(sizeof(struct sockaddr_in)); + if (smask) { + smask->sin_addr.s_addr = prefixLengthToIpv4Netmask(masklen); + smask->sin_family = family; + } + } + ifa->ifa_netmask = (struct sockaddr *)smask; + } else if (family == AF_PACKET) { + if (!ifc_get_hwaddr(name, hwbuf)) { + hwaddr = malloc(sizeof(struct sockaddr_ll)); + if (hwaddr) { + memset(hwaddr, 0, sizeof(struct sockaddr_ll)); + hwaddr->sll_family = family; + /* hwaddr->sll_protocol = ETHERTYPE_IP; */ + hwaddr->sll_hatype = ARPHRD_ETHER; + hwaddr->sll_halen = ETH_ALEN; + memcpy(hwaddr->sll_addr, hwbuf, ETH_ALEN); + } + } + ifa->ifa_addr = (struct sockaddr *)hwaddr; + ifa->ifa_netmask = (struct sockaddr *)smask; + } + return ifa; +} + +int getifaddrs(struct ifaddrs **ifap) +{ + DIR *d; + struct dirent *de; + struct ifaddrs *ifa; + struct ifaddrs *ifah = NULL; + + if (!ifap) + return -1; + *ifap = NULL; + + if (ifc_init()) + return -1; + + d = opendir("/sys/class/net"); + if (d == 0) + return -1; + while ((de = readdir(d))) { + if (de->d_name[0] == '.') + continue; + ifa = get_interface(de->d_name, AF_INET); + if (ifa != NULL) { + ifa->ifa_next = ifah; + ifah = ifa; + } + ifa = get_interface(de->d_name, AF_PACKET); + if (ifa != NULL) { + ifa->ifa_next = ifah; + ifah = ifa; + } + } + *ifap = ifah; + closedir(d); + ifc_close(); + return 0; +} + +void freeifaddrs(struct ifaddrs *ifa) +{ + struct ifaddrs *ifp; + + while (ifa) { + ifp = ifa; + free(ifp->ifa_name); + if (ifp->ifa_addr) + free(ifp->ifa_addr); + if (ifp->ifa_netmask) + free(ifp->ifa_netmask); + ifa = ifa->ifa_next; + free(ifp); + } +} diff --git a/ifaddrs.h b/ifaddrs.h new file mode 100644 index 0000000..6356653 --- /dev/null +++ b/ifaddrs.h @@ -0,0 +1,34 @@ +/**************************************************************************** + **************************************************************************** + *** + *** This header was generated from a glibc header of the same name. + *** It contains only constants, structures, and macros generated from + *** the original header, and thus, contains no copyrightable information. + *** + **************************************************************************** + ****************************************************************************/ +#ifndef _IFADDRS_H +#define _IFADDRS_H + +#include <sys/socket.h> + +struct ifaddrs { + 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; +#define ifa_broadaddr ifa_ifu.ifu_broadaddr +#define ifa_dstaddr ifa_ifu.ifu_dstaddr + void *ifa_data; +}; + +extern int getifaddrs(struct ifaddrs **ifap); + +extern void freeifaddrs(struct ifaddrs *ifa); + +#endif |