ifc_utils.c revision b6b48ae47a44cb231d0a16ca618ac28b0024c11c
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright 2008, The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/select.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <netinet/in.h>
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <arpa/inet.h>
287d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt#include <net/if.h>
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/if.h>
31c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak#include <linux/if_ether.h>
32c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak#include <linux/if_arp.h>
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/sockios.h>
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/route.h>
358984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik#include <linux/ipv6_route.h>
368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik#include <netdb.h>
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/wireless.h>
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef ANDROID
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_TAG "NetUtils"
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/log.h>
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/properties.h>
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOGD printf
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOGW printf
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int ifc_ctl_sock = -1;
518984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikstatic int ifc_ctl_sock6 = -1;
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid printerr(char *fmt, ...);
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
54b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt#define DBG 0
55b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
5609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltin_addr_t prefixLengthToIpv4Netmask(int prefix_length)
5709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt{
5809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    in_addr_t mask = 0;
5909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt
6009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    // C99 (6.5.7): shifts of 32 bits have undefined results
6109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    if (prefix_length <= 0 || prefix_length > 32) {
6209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt        return 0;
6309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    }
6409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt
6509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    mask = ~mask << (32 - prefix_length);
6609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    mask = htonl(mask);
6709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt
6809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    return mask;
6909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt}
7009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt
7109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ipv4NetmaskToPrefixLength(in_addr_t mask)
7209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt{
7309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    mask = ntohl(mask);
7409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    int prefixLength = 0;
7509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    uint32_t m = (uint32_t)mask;
7609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    while (m & 0x80000000) {
7709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt        prefixLength++;
7809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt        m = m << 1;
7909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    }
8009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    return prefixLength;
8109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt}
8209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt
83c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczakstatic const char *ipaddr_to_string(in_addr_t addr)
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct in_addr in_addr;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    in_addr.s_addr = addr;
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return inet_ntoa(in_addr);
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_init(void)
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
93b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int ret;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ifc_ctl_sock == -1) {
95b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt        ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ifc_ctl_sock < 0) {
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            printerr("socket() failed: %s\n", strerror(errno));
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
100b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
101b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    ret = ifc_ctl_sock < 0 ? -1 : 0;
102b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    if (DBG) printerr("ifc_init_returning %d", ret);
103b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return ret;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1068984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikint ifc_init6(void)
1078984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{
1088984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (ifc_ctl_sock6 == -1) {
1098984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
1108984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        if (ifc_ctl_sock6 < 0) {
1118984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik            printerr("socket() failed: %s\n", strerror(errno));
1128984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        }
1138984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
1148984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    return ifc_ctl_sock6 < 0 ? -1 : 0;
1158984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik}
1168984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid ifc_close(void)
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
119b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    if (DBG) printerr("ifc_close");
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ifc_ctl_sock != -1) {
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (void)close(ifc_ctl_sock);
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ifc_ctl_sock = -1;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1268984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikvoid ifc_close6(void)
1278984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{
1288984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (ifc_ctl_sock6 != -1) {
1298984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        (void)close(ifc_ctl_sock6);
1308984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        ifc_ctl_sock6 = -1;
1318984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
1328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik}
1338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void ifc_init_ifr(const char *name, struct ifreq *ifr)
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(ifr, 0, sizeof(struct ifreq));
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strncpy(ifr->ifr_name, name, IFNAMSIZ);
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifr->ifr_name[IFNAMSIZ - 1] = 0;
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_get_hwaddr(const char *name, void *ptr)
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int r;
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct ifreq ifr;
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init_ifr(name, &ifr);
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr);
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(r < 0) return -1;
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
150c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak    memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
151b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return 0;
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_get_ifindex(const char *name, int *if_indexp)
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int r;
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct ifreq ifr;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init_ifr(name, &ifr);
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    r = ioctl(ifc_ctl_sock, SIOCGIFINDEX, &ifr);
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(r < 0) return -1;
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *if_indexp = ifr.ifr_ifindex;
1647d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt    return 0;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int ifc_set_flags(const char *name, unsigned set, unsigned clr)
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct ifreq ifr;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init_ifr(name, &ifr);
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) return -1;
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set;
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ioctl(ifc_ctl_sock, SIOCSIFFLAGS, &ifr);
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_up(const char *name)
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
179b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int ret = ifc_set_flags(name, IFF_UP, 0);
180b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    if (DBG) printerr("ifc_up(%s) = %d", name, ret);
181b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return ret;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_down(const char *name)
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
186b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int ret = ifc_set_flags(name, 0, IFF_UP);
187b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    if (DBG) printerr("ifc_down(%s) = %d", name, ret);
188b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return ret;
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr)
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct sockaddr_in *sin = (struct sockaddr_in *) sa;
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sin->sin_family = AF_INET;
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sin->sin_port = 0;
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sin->sin_addr.s_addr = addr;
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_set_addr(const char *name, in_addr_t addr)
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct ifreq ifr;
202b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int ret;
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init_ifr(name, &ifr);
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    init_sockaddr_in(&ifr.ifr_addr, addr);
2067d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt
207b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    ret = ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr);
208b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    if (DBG) printerr("ifc_set_addr(%s, xx) = %d", name, ret);
209b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return ret;
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
212c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczakint ifc_set_hwaddr(const char *name, const void *ptr)
213c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak{
214c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak    int r;
215c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak    struct ifreq ifr;
216c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak    ifc_init_ifr(name, &ifr);
217c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak
218c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak    ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
219c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak    memcpy(&ifr.ifr_hwaddr.sa_data, ptr, ETH_ALEN);
220c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak    return ioctl(ifc_ctl_sock, SIOCSIFHWADDR, &ifr);
221c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak}
222c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak
2236f49d5f266dffee103a3af07a7f6266f405d2924Jake Hambyint ifc_set_mask(const char *name, in_addr_t mask)
2246f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby{
2256f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby    struct ifreq ifr;
226b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int ret;
2276f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby
2286f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby    ifc_init_ifr(name, &ifr);
2296f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby    init_sockaddr_in(&ifr.ifr_addr, mask);
2306f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby
231b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    ret = ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr);
232b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    if (DBG) printerr("ifc_set_mask(%s, xx) = %d", name, ret);
233b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return ret;
2346f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby}
2356f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby
23609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ifc_set_prefixLength(const char *name, int prefixLength)
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct ifreq ifr;
23909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    // TODO - support ipv6
24009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    if (prefixLength > 32 || prefixLength < 0) return -1;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
24209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    in_addr_t mask = prefixLengthToIpv4Netmask(prefixLength);
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init_ifr(name, &ifr);
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    init_sockaddr_in(&ifr.ifr_addr, mask);
2457d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr);
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2499092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidtint ifc_get_addr(const char *name, in_addr_t *addr)
2509092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt{
2519092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt    struct ifreq ifr;
2529092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt    int ret = 0;
2539092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt
2549092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt    ifc_init_ifr(name, &ifr);
2559092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt    if (addr != NULL) {
2569092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt        ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr);
2579092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt        if (ret < 0) {
2589092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt            *addr = 0;
2599092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt        } else {
2609092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt            *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
2619092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt        }
2629092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt    }
2639092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt    return ret;
2649092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt}
2659092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt
26609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags)
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct ifreq ifr;
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init_ifr(name, &ifr);
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (addr != NULL) {
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr) < 0) {
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *addr = 0;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
2787d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt
27909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    if (prefixLength != NULL) {
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) {
28109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt            *prefixLength = 0;
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
28309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt            *prefixLength = ipv4NetmaskToPrefixLength((int)
28409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt                    ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr);
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (flags != NULL) {
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) {
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *flags = 0;
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *flags = ifr.ifr_flags;
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
299021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_ipv4_route(int action, const char *ifname, struct in_addr dst, int prefix_length,
3008984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik      struct in_addr gw)
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct rtentry rt;
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int result;
3048984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    in_addr_t netmask;
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&rt, 0, sizeof(rt));
3078984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    rt.rt_dst.sa_family = AF_INET;
3098984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    rt.rt_dev = (void*) ifname;
3108984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
31109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    netmask = prefixLengthToIpv4Netmask(prefix_length);
3128984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    init_sockaddr_in(&rt.rt_genmask, netmask);
3138984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    init_sockaddr_in(&rt.rt_dst, dst.s_addr);
3148984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    rt.rt_flags = RTF_UP;
3158984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
3168984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (prefix_length == 32) {
3178984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        rt.rt_flags |= RTF_HOST;
3188984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
3198984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
3208984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (gw.s_addr != 0) {
3218984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        rt.rt_flags |= RTF_GATEWAY;
3228984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        init_sockaddr_in(&rt.rt_gateway, gw.s_addr);
3238984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
3248984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init();
3268984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
3278984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (ifc_ctl_sock < 0) {
3288984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        return -errno;
3298984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
3308984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
331021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt    result = ioctl(ifc_ctl_sock, action, &rt);
3328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (result < 0) {
3338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        if (errno == EEXIST) {
3348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik            result = 0;
3358984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        } else {
3368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik            result = -errno;
3378984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        }
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_close();
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
343b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* deprecated - v4 only */
3448984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikint ifc_create_default_route(const char *name, in_addr_t gw)
3458984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{
3468984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    struct in_addr in_dst, in_gw;
3478984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
3488984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    in_dst.s_addr = 0;
3498984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    in_gw.s_addr = gw;
3508984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
351b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int ret = ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 0, in_gw);
352b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    if (DBG) printerr("ifc_create_default_route(%s, %d) = %d", name, gw, ret);
353b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return ret;
354b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt}
355b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
356b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* deprecated v4-only */
357b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_add_host_route(const char *name, in_addr_t dst)
358b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{
359b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    struct in_addr in_dst, in_gw;
360b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
361b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    in_dst.s_addr = dst;
362b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    in_gw.s_addr = 0;
363b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
364b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 32, in_gw);
3658984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik}
3668984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
367feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwoodint ifc_enable(const char *ifname)
368feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood{
369feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood    int result;
370feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood
371feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood    ifc_init();
372feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood    result = ifc_up(ifname);
373feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood    ifc_close();
374feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood    return result;
375feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood}
376feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_disable(const char *ifname)
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
3799092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt    unsigned addr, count;
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int result;
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init();
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    result = ifc_down(ifname);
3849092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_set_addr(ifname, 0);
3869092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt    for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
3879092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt       if (ifc_get_addr(ifname, &addr) < 0)
3889092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt            break;
3899092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt       if (addr)
3909092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt          ifc_set_addr(ifname, 0);
3919092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt    }
3929092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_close();
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_reset_connections(const char *ifname)
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_ANDROID_OS
4006cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    int result, success;
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    in_addr_t myaddr;
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct ifreq ifr;
4036cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    struct in6_ifreq ifr6;
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4056cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    /* IPv4. Clear connections on the IP address. */
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init();
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_get_info(ifname, &myaddr, NULL, NULL);
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init_ifr(ifname, &ifr);
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    init_sockaddr_in(&ifr.ifr_addr, myaddr);
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    result = ioctl(ifc_ctl_sock, SIOCKILLADDR,  &ifr);
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_close();
4127d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt
4136cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    /*
4146cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti     * IPv6. On Linux, when an interface goes down it loses all its IPv6
4156cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti     * addresses, so we don't know which connections belonged to that interface
4166cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti     * So we clear all unused IPv6 connections on the device by specifying an
4176cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti     * empty IPv6 address.
4186cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti     */
4196cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    ifc_init6();
4206cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets.
4216cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    memset(&ifr6, 0, sizeof(ifr6));
4226cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    success = ioctl(ifc_ctl_sock6, SIOCKILLADDR,  &ifr6);
4236cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    if (result == 0) {
4246cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti        result = success;
4256cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    }
4266cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti    ifc_close6();
4276cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Remove the routes associated with the named interface.
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_remove_host_routes(const char *name)
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char ifname[64];
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    in_addr_t dest, gway, mask;
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int flags, refcnt, use, metric, mtu, win, irtt;
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct rtentry rt;
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FILE *fp;
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct in_addr addr;
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fp = fopen("/proc/net/route", "r");
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fp == NULL)
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* Skip the header line */
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fscanf(fp, "%*[^\n]\n") < 0) {
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fclose(fp);
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init();
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (;;) {
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n",
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                           ifname, &dest, &gway, &flags, &refcnt, &use, &metric, &mask,
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                           &mtu, &win, &irtt);
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (nread != 11) {
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST)
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                || strcmp(ifname, name) != 0) {
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        memset(&rt, 0, sizeof(rt));
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        rt.rt_dev = (void *)name;
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        init_sockaddr_in(&rt.rt_dst, dest);
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        init_sockaddr_in(&rt.rt_gateway, gway);
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        init_sockaddr_in(&rt.rt_genmask, mask);
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        addr.s_addr = dest;
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ioctl(ifc_ctl_sock, SIOCDELRT, &rt) < 0) {
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            LOGD("failed to remove route for %s to %s: %s",
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                 ifname, inet_ntoa(addr), strerror(errno));
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fclose(fp);
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_close();
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
483b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * Return the address of the default gateway
484b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt *
485b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * TODO: factor out common code from this and remove_host_routes()
486b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * so that we only scan /proc/net/route in one place.
487b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt *
488b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED
489b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */
490b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_get_default_route(const char *ifname)
491b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{
492b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    char name[64];
493b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    in_addr_t dest, gway, mask;
494b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int flags, refcnt, use, metric, mtu, win, irtt;
495b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int result;
496b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    FILE *fp;
497b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
498b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    fp = fopen("/proc/net/route", "r");
499b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    if (fp == NULL)
500b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt        return 0;
501b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    /* Skip the header line */
502b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    if (fscanf(fp, "%*[^\n]\n") < 0) {
503b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt        fclose(fp);
504b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt        return 0;
505b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    }
506b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    ifc_init();
507b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    result = 0;
508b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    for (;;) {
509b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt        int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n",
510b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt                           name, &dest, &gway, &flags, &refcnt, &use, &metric, &mask,
511b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt                           &mtu, &win, &irtt);
512b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt        if (nread != 11) {
513b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt            break;
514b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt        }
515b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt        if ((flags & (RTF_UP|RTF_GATEWAY)) == (RTF_UP|RTF_GATEWAY)
516b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt                && dest == 0
517b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt                && strcmp(ifname, name) == 0) {
518b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt            result = gway;
519b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt            break;
520b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt        }
521b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    }
522b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    fclose(fp);
523b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    ifc_close();
524b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return result;
525b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt}
526b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
527b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/*
528b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * Sets the specified gateway as the default route for the named interface.
529b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED
530b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */
531b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_set_default_route(const char *ifname, in_addr_t gateway)
532b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{
533b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    struct in_addr addr;
534b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int result;
535b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
536b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    ifc_init();
537b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    addr.s_addr = gateway;
538b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    if ((result = ifc_create_default_route(ifname, gateway)) < 0) {
539b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt        LOGD("failed to add %s as default route for %s: %s",
540b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt             inet_ntoa(addr), ifname, strerror(errno));
541b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    }
542b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    ifc_close();
543b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return result;
544b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt}
545b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
546b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/*
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Removes the default route for the named interface.
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_remove_default_route(const char *ifname)
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct rtentry rt;
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int result;
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init();
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&rt, 0, sizeof(rt));
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    rt.rt_dev = (void *)ifname;
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    rt.rt_flags = RTF_UP|RTF_GATEWAY;
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    init_sockaddr_in(&rt.rt_dst, 0);
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ((result = ioctl(ifc_ctl_sock, SIOCDELRT, &rt)) < 0) {
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        LOGD("failed to remove default route for %s: %s", ifname, strerror(errno));
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_close();
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectifc_configure(const char *ifname,
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        in_addr_t address,
56909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt        uint32_t prefixLength,
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        in_addr_t gateway,
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        in_addr_t dns1,
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        in_addr_t dns2) {
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char dns_prop_name[PROPERTY_KEY_MAX];
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_init();
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ifc_up(ifname)) {
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printerr("failed to turn on interface %s: %s\n", ifname, strerror(errno));
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ifc_close();
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ifc_set_addr(ifname, address)) {
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printerr("failed to set ipaddr %s: %s\n", ipaddr_to_string(address), strerror(errno));
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ifc_close();
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
58809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt    if (ifc_set_prefixLength(ifname, prefixLength)) {
58909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt        printerr("failed to set prefixLength %d: %s\n", prefixLength, strerror(errno));
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ifc_close();
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ifc_create_default_route(ifname, gateway)) {
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printerr("failed to set default route %s: %s\n", ipaddr_to_string(gateway), strerror(errno));
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ifc_close();
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifc_close();
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
601c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak    snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", ifname);
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : "");
603c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak    snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname);
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : "");
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
6088984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
609021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_ipv6_route(int action, const char *ifname, struct in6_addr dst, int prefix_length,
6108984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik      struct in6_addr gw)
6118984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{
6128984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    struct in6_rtmsg rtmsg;
6138984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    int result;
6148984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    int ifindex;
6158984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6168984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    memset(&rtmsg, 0, sizeof(rtmsg));
6178984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6188984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    ifindex = if_nametoindex(ifname);
6198984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (ifindex == 0) {
6208984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        printerr("if_nametoindex() failed: interface %s\n", ifname);
6218984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        return -ENXIO;
6228984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
6238984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6248984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    rtmsg.rtmsg_ifindex = ifindex;
6258984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    rtmsg.rtmsg_dst = dst;
6268984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    rtmsg.rtmsg_dst_len = prefix_length;
6278984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    rtmsg.rtmsg_flags = RTF_UP;
6288984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6298984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (prefix_length == 128) {
6308984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        rtmsg.rtmsg_flags |= RTF_HOST;
6318984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
6328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (memcmp(&gw, &in6addr_any, sizeof(in6addr_any))) {
6348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        rtmsg.rtmsg_flags |= RTF_GATEWAY;
6358984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        rtmsg.rtmsg_gateway = gw;
6368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
6378984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    ifc_init6();
6398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6408984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (ifc_ctl_sock6 < 0) {
6418984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        return -errno;
6428984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
6438984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
644021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt    result = ioctl(ifc_ctl_sock6, action, &rtmsg);
6458984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (result < 0) {
6468984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        if (errno == EEXIST) {
6478984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik            result = 0;
6488984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        } else {
6498984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik            result = -errno;
6508984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        }
6518984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
6528984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    ifc_close6();
6538984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    return result;
6548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik}
6558984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
656021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_route(int action, const char *ifname, const char *dst, int prefix_length,
657021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt        const char *gw)
6588984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{
6598984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    int ret = 0;
6608984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    struct sockaddr_in ipv4_dst, ipv4_gw;
6618984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    struct sockaddr_in6 ipv6_dst, ipv6_gw;
6628984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    struct addrinfo hints, *addr_ai, *gw_ai;
6638984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6648984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    memset(&hints, 0, sizeof(hints));
6658984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    hints.ai_family = AF_UNSPEC;  /* Allow IPv4 or IPv6 */
6668984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    hints.ai_flags = AI_NUMERICHOST;
6678984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6688984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    ret = getaddrinfo(dst, NULL, &hints, &addr_ai);
6698984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6708984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (ret != 0) {
6718984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        printerr("getaddrinfo failed: invalid address %s\n", dst);
6728984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        return -EINVAL;
6738984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
6748984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
675021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt    if (gw == NULL || (strlen(gw) == 0)) {
6768984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        if (addr_ai->ai_family == AF_INET6) {
6778984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik            gw = "::";
6788984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        } else if (addr_ai->ai_family == AF_INET) {
6798984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik            gw = "0.0.0.0";
6808984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        }
6818984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
6828984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
683021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt    if (((addr_ai->ai_family == AF_INET6) && (prefix_length < 0 || prefix_length > 128)) ||
684021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt            ((addr_ai->ai_family == AF_INET) && (prefix_length < 0 || prefix_length > 32))) {
685021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt        printerr("ifc_add_route: invalid prefix length");
686021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt        freeaddrinfo(addr_ai);
687021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt        return -EINVAL;
688021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt    }
689021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt
6908984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    ret = getaddrinfo(gw, NULL, &hints, &gw_ai);
6918984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (ret != 0) {
6928984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        printerr("getaddrinfo failed: invalid gateway %s\n", gw);
6938984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        freeaddrinfo(addr_ai);
6948984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        return -EINVAL;
6958984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
6968984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
6978984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (addr_ai->ai_family != gw_ai->ai_family) {
6988984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        printerr("ifc_add_route: different address families: %s and %s\n", dst, gw);
6998984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        freeaddrinfo(addr_ai);
7008984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        freeaddrinfo(gw_ai);
7018984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        return -EINVAL;
7028984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
7038984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
7048984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    if (addr_ai->ai_family == AF_INET6) {
7058984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        memcpy(&ipv6_dst, addr_ai->ai_addr, sizeof(struct sockaddr_in6));
7068984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        memcpy(&ipv6_gw, gw_ai->ai_addr, sizeof(struct sockaddr_in6));
707021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt        ret = ifc_act_on_ipv6_route(action, ifname, ipv6_dst.sin6_addr,
708021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt                prefix_length, ipv6_gw.sin6_addr);
7098984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    } else if (addr_ai->ai_family == AF_INET) {
7108984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        memcpy(&ipv4_dst, addr_ai->ai_addr, sizeof(struct sockaddr_in));
7118984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        memcpy(&ipv4_gw, gw_ai->ai_addr, sizeof(struct sockaddr_in));
712021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt        ret = ifc_act_on_ipv4_route(action, ifname, ipv4_dst.sin_addr,
713021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt                prefix_length, ipv4_gw.sin_addr);
7148984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    } else {
7158984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        printerr("ifc_add_route: getaddrinfo returned un supported address family %d\n",
7168984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik                  addr_ai->ai_family);
7178984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik        ret = -EAFNOSUPPORT;
7188984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    }
7198984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik
7208984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    freeaddrinfo(addr_ai);
7218984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    freeaddrinfo(gw_ai);
7228984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik    return ret;
7238984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik}
724021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt
725b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/*
726b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED
727b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */
728b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_add_ipv4_route(const char *ifname, struct in_addr dst, int prefix_length,
729b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt      struct in_addr gw)
730b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{
731b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int i =ifc_act_on_ipv4_route(SIOCADDRT, ifname, dst, prefix_length, gw);
732b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    printerr("ifc_add_ipv4_route(%s, xx, %d, xx) = %d", ifname, prefix_length, i);
733b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return i;
734b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt}
735b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
736b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/*
737b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED
738b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */
739b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_add_ipv6_route(const char *ifname, struct in6_addr dst, int prefix_length,
740b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt      struct in6_addr gw)
741b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{
742b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return ifc_act_on_ipv6_route(SIOCADDRT, ifname, dst, prefix_length, gw);
743b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt}
744b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt
745021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_add_route(const char *ifname, const char *dst, int prefix_length, const char *gw)
746021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt{
747b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    int i = ifc_act_on_route(SIOCADDRT, ifname, dst, prefix_length, gw);
748b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    printerr("ifc_add_route(%s, %s, %d, %s) = %d", ifname, dst, prefix_length, gw, i);
749b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt    return i;
750021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt}
751021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt
752021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_remove_route(const char *ifname, const char*dst, int prefix_length, const char *gw)
753021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt{
754021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt    return ifc_act_on_route(SIOCDELRT, ifname, dst, prefix_length, gw);
755021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt}
756