| /* 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; */ |
| ifc_get_ifindex(ifa->ifa_name, &hwaddr->sll_ifindex); |
| 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); |
| } |
| } |