Home | History | Annotate | Download | only in dhcpcd-6.8.2
      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