blob: 1a27d8f34572a167e87b8cf012734bf5906cf626 [file] [log] [blame]
Samuel Tan71df7772015-08-20 11:04:41 -07001/* 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
35struct 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; */
Samuel Tanc9637df2015-08-26 14:53:50 -070087 ifc_get_ifindex(ifa->ifa_name, &hwaddr->sll_ifindex);
Samuel Tan71df7772015-08-20 11:04:41 -070088 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
99int 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
136void 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}