1 /* external/dhcpcd-6.8.2/ifaddrs.c 2 ** Copied from external/dhcpcd/ifaddrs.c. 3 ** 4 ** Copyright 2011, The Android Open Source Project 5 ** 6 ** Licensed under the Apache License, Version 2.0 (the "License");. 7 ** you may not use this file except in compliance with the License.. 8 ** You may obtain a copy of the License at. 9 ** 10 ** http://www.apache.org/licenses/LICENSE-2.0. 11 ** 12 ** Unless required by applicable law or agreed to in writing, software. 13 ** distributed under the License is distributed on an "AS IS" BASIS,. 14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.. 15 ** See the License for the specific language governing permissions and. 16 ** limitations under the License. 17 */ 18 19 #include <arpa/inet.h> 20 #include <sys/socket.h> 21 #include "ifaddrs.h" 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 #include <sys/types.h> 27 #include <dirent.h> 28 #include <netinet/ether.h> 29 #include <netdb.h> 30 #include <linux/if_packet.h> 31 #include <netinet/if_ether.h> 32 #include <linux/if_arp.h> 33 #include <netutils/ifc.h> 34 35 struct ifaddrs *get_interface(const char *name, sa_family_t family) 36 { 37 unsigned addr, flags; 38 int masklen; 39 struct ifaddrs *ifa; 40 struct sockaddr_in *saddr = NULL; 41 struct sockaddr_in *smask = NULL; 42 struct sockaddr_ll *hwaddr = NULL; 43 unsigned char hwbuf[ETH_ALEN]; 44 45 if (ifc_get_info(name, &addr, &masklen, &flags)) 46 return NULL; 47 48 if ((family == AF_INET) && (addr == 0)) 49 return NULL; 50 51 ifa = malloc(sizeof(struct ifaddrs)); 52 if (!ifa) 53 return NULL; 54 memset(ifa, 0, sizeof(struct ifaddrs)); 55 56 ifa->ifa_name = malloc(strlen(name)+1); 57 if (!ifa->ifa_name) { 58 free(ifa); 59 return NULL; 60 } 61 strcpy(ifa->ifa_name, name); 62 ifa->ifa_flags = flags; 63 64 if (family == AF_INET) { 65 saddr = malloc(sizeof(struct sockaddr_in)); 66 if (saddr) { 67 saddr->sin_addr.s_addr = addr; 68 saddr->sin_family = family; 69 } 70 ifa->ifa_addr = (struct sockaddr *)saddr; 71 72 if (masklen != 0) { 73 smask = malloc(sizeof(struct sockaddr_in)); 74 if (smask) { 75 smask->sin_addr.s_addr = prefixLengthToIpv4Netmask(masklen); 76 smask->sin_family = family; 77 } 78 } 79 ifa->ifa_netmask = (struct sockaddr *)smask; 80 } else if (family == AF_PACKET) { 81 if (!ifc_get_hwaddr(name, hwbuf)) { 82 hwaddr = malloc(sizeof(struct sockaddr_ll)); 83 if (hwaddr) { 84 memset(hwaddr, 0, sizeof(struct sockaddr_ll)); 85 hwaddr->sll_family = family; 86 /* hwaddr->sll_protocol = ETHERTYPE_IP; */ 87 ifc_get_ifindex(ifa->ifa_name, &hwaddr->sll_ifindex); 88 hwaddr->sll_hatype = ARPHRD_ETHER; 89 hwaddr->sll_halen = ETH_ALEN; 90 memcpy(hwaddr->sll_addr, hwbuf, ETH_ALEN); 91 } 92 } 93 ifa->ifa_addr = (struct sockaddr *)hwaddr; 94 ifa->ifa_netmask = (struct sockaddr *)smask; 95 } 96 return ifa; 97 } 98 99 int getifaddrs(struct ifaddrs **ifap) 100 { 101 DIR *d; 102 struct dirent *de; 103 struct ifaddrs *ifa; 104 struct ifaddrs *ifah = NULL; 105 106 if (!ifap) 107 return -1; 108 *ifap = NULL; 109 110 if (ifc_init()) 111 return -1; 112 113 d = opendir("/sys/class/net"); 114 if (d == 0) 115 return -1; 116 while ((de = readdir(d))) { 117 if (de->d_name[0] == '.') 118 continue; 119 ifa = get_interface(de->d_name, AF_INET); 120 if (ifa != NULL) { 121 ifa->ifa_next = ifah; 122 ifah = ifa; 123 } 124 ifa = get_interface(de->d_name, AF_PACKET); 125 if (ifa != NULL) { 126 ifa->ifa_next = ifah; 127 ifah = ifa; 128 } 129 } 130 *ifap = ifah; 131 closedir(d); 132 ifc_close(); 133 return 0; 134 } 135 136 void freeifaddrs(struct ifaddrs *ifa) 137 { 138 struct ifaddrs *ifp; 139 140 while (ifa) { 141 ifp = ifa; 142 free(ifp->ifa_name); 143 if (ifp->ifa_addr) 144 free(ifp->ifa_addr); 145 if (ifp->ifa_netmask) 146 free(ifp->ifa_netmask); 147 ifa = ifa->ifa_next; 148 free(ifp); 149 } 150 } 151