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> 2947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#include <netdb.h> 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/if.h> 32c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak#include <linux/if_ether.h> 33c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak#include <linux/if_arp.h> 3447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#include <linux/netlink.h> 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/route.h> 368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik#include <linux/ipv6_route.h> 3747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#include <linux/rtnetlink.h> 3847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#include <linux/sockios.h> 3947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 4047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#include "netutils/ifc.h" 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef ANDROID 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_TAG "NetUtils" 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/log.h> 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/properties.h> 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 498d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block#define ALOGD printf 50ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block#define ALOGW printf 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int ifc_ctl_sock = -1; 548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikstatic int ifc_ctl_sock6 = -1; 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid printerr(char *fmt, ...); 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 57b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt#define DBG 0 5847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#define INET_ADDRLEN 4 5947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#define INET6_ADDRLEN 16 60b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 6109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltin_addr_t prefixLengthToIpv4Netmask(int prefix_length) 6209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt{ 6309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt in_addr_t mask = 0; 6409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 6509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt // C99 (6.5.7): shifts of 32 bits have undefined results 6609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefix_length <= 0 || prefix_length > 32) { 6709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return 0; 6809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt } 6909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt mask = ~mask << (32 - prefix_length); 7109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt mask = htonl(mask); 7209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return mask; 7409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt} 7509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ipv4NetmaskToPrefixLength(in_addr_t mask) 7709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt{ 7809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt int prefixLength = 0; 796ee3ecc03a7cf9118e6a0b2577f15c76244bc408Chris Dearman uint32_t m = (uint32_t)ntohl(mask); 8009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt while (m & 0x80000000) { 8109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt prefixLength++; 8209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt m = m << 1; 8309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt } 8409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return prefixLength; 8509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt} 8609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 87c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczakstatic const char *ipaddr_to_string(in_addr_t addr) 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct in_addr in_addr; 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr.s_addr = addr; 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return inet_ntoa(in_addr); 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 9547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint string_to_ip(const char *string, struct sockaddr_storage *ss) { 9647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct addrinfo hints, *ai; 9747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int ret; 9847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 9947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ss == NULL) { 10047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EFAULT; 10147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 10247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 10347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memset(&hints, 0, sizeof(hints)); 10447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_family = AF_UNSPEC; 10547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_flags = AI_NUMERICHOST; 10647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_socktype = SOCK_DGRAM; 10747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 10847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = getaddrinfo(string, NULL, &hints, &ai); 10947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret == 0) { 11047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memcpy(ss, ai->ai_addr, ai->ai_addrlen); 11147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti freeaddrinfo(ai); 11247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 11347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 11447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ret; 11547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 11647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_init(void) 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 119b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock == -1) { 121b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock < 0) { 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("socket() failed: %s\n", strerror(errno)); 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 126b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 127b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ifc_ctl_sock < 0 ? -1 : 0; 128b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_init_returning %d", ret); 129b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikint ifc_init6(void) 1338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 1348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 == -1) { 1358984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM, 0); 1368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 < 0) { 1378984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("socket() failed: %s\n", strerror(errno)); 1388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1408984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return ifc_ctl_sock6 < 0 ? -1 : 0; 1418984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 1428984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid ifc_close(void) 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 145b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_close"); 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock != -1) { 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project (void)close(ifc_ctl_sock); 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_ctl_sock = -1; 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1528984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikvoid ifc_close6(void) 1538984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 1548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 != -1) { 1558984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik (void)close(ifc_ctl_sock6); 1568984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_ctl_sock6 = -1; 1578984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1588984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 1598984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void ifc_init_ifr(const char *name, struct ifreq *ifr) 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(ifr, 0, sizeof(struct ifreq)); 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strncpy(ifr->ifr_name, name, IFNAMSIZ); 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifr->ifr_name[IFNAMSIZ - 1] = 0; 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_get_hwaddr(const char *name, void *ptr) 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int r; 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr); 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(r < 0) return -1; 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 176c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); 177b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return 0; 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_get_ifindex(const char *name, int *if_indexp) 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int r; 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = ioctl(ifc_ctl_sock, SIOCGIFINDEX, &ifr); 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(r < 0) return -1; 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *if_indexp = ifr.ifr_ifindex; 1907d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt return 0; 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int ifc_set_flags(const char *name, unsigned set, unsigned clr) 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) return -1; 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set; 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ioctl(ifc_ctl_sock, SIOCSIFFLAGS, &ifr); 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_up(const char *name) 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 205b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_set_flags(name, IFF_UP, 0); 206b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_up(%s) = %d", name, ret); 207b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_down(const char *name) 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 212b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_set_flags(name, 0, IFF_UP); 213b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_down(%s) = %d", name, ret); 214b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr) 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_in *sin = (struct sockaddr_in *) sa; 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_family = AF_INET; 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_port = 0; 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_addr.s_addr = addr; 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_set_addr(const char *name, in_addr_t addr) 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 228b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&ifr.ifr_addr, addr); 2327d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 233b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr); 234b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_set_addr(%s, xx) = %d", name, ret); 235b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 23847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 23947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Adds or deletes an IP address on an interface. 24047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * 24147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Action is one of: 24247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * - RTM_NEWADDR (to add a new address) 24347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * - RTM_DELADDR (to delete an existing address) 24447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * 24547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Returns zero on success and negative errno on failure. 24647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 24747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_act_on_address(int action, const char *name, const char *address, 24847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int prefixlen) { 24947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int ifindex, s, len, ret; 25047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_storage ss; 25147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti void *addr; 25247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti size_t addrlen; 25347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct { 25447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsghdr n; 25547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct ifaddrmsg r; 25647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Allow for IPv6 address, headers, and padding. 25747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char attrbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 25847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct rtattr)) + 25947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(INET6_ADDRLEN)]; 26047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } req; 26147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct rtattr *rta; 26247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsghdr *nh; 26347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsgerr *err; 26447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 26547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct nlmsgerr)) + 26647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct nlmsghdr))]; 26747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 26847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Get interface ID. 26947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifindex = if_nametoindex(name); 27047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ifindex == 0) { 27147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 27247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 27347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 27447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Convert string representation to sockaddr_storage. 27547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = string_to_ip(address, &ss); 27647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret) { 27747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ret; 27847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 27947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 28047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Determine address type and length. 28147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ss.ss_family == AF_INET) { 28247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_in *sin = (struct sockaddr_in *) &ss; 28347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addr = &sin->sin_addr; 28447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrlen = INET_ADDRLEN; 28547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } else if (ss.ss_family == AF_INET6) { 28647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss; 28747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addr = &sin6->sin6_addr; 28847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrlen = INET6_ADDRLEN; 28947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } else { 29047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EAFNOSUPPORT; 29147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 29247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 29347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Fill in netlink structures. 29447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memset(&req, 0, sizeof(req)); 29547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 29647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Netlink message header. 29747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r)); 29847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_type = action; 29947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 30047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_pid = getpid(); 30147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 30247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Interface address message header. 30347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_family = ss.ss_family; 30447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_prefixlen = prefixlen; 30547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_index = ifindex; 30647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 30747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Routing attribute. Contains the actual IP address. 30847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len)); 30947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta->rta_type = IFA_LOCAL; 31047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta->rta_len = RTA_LENGTH(addrlen); 31147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen); 31247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memcpy(RTA_DATA(rta), addr, addrlen); 31347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 31447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 31547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (send(s, &req, req.n.nlmsg_len, 0) < 0) { 31647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti close(s); 31747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 31847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 31947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 32047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti len = recv(s, buf, sizeof(buf), 0); 32147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti close(s); 32247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (len < 0) { 32347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 32447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 32547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 32647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Parse the acknowledgement to find the return code. 32747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti nh = (struct nlmsghdr *) buf; 32847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (!NLMSG_OK(nh, (unsigned) len) || nh->nlmsg_type != NLMSG_ERROR) { 32947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EINVAL; 33047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 33147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti err = NLMSG_DATA(nh); 33247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 33347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Return code is negative errno. 33447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return err->error; 33547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 33647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 33747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_add_address(const char *name, const char *address, int prefixlen) { 33847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen); 33947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 34047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 34147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_del_address(const char *name, const char * address, int prefixlen) { 34247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen); 34347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 34447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 34547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 34647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears IPv6 addresses on the specified interface. 34747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 34847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_clear_ipv6_addresses(const char *name) { 34947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char rawaddrstr[INET6_ADDRSTRLEN], addrstr[INET6_ADDRSTRLEN]; 35047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti unsigned int prefixlen; 35147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int lasterror = 0, i, j, ret; 35247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char ifname[64]; // Currently, IFNAMSIZ = 16. 35347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti FILE *f = fopen("/proc/net/if_inet6", "r"); 35447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (!f) { 35547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 35647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 35747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 35847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Format: 35947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // 20010db8000a0001fc446aa4b5b347ed 03 40 00 01 wlan0 36047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti while (fscanf(f, "%32s %*02x %02x %*02x %*02x %63s\n", 36147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rawaddrstr, &prefixlen, ifname) == 3) { 36247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Is this the interface we're looking for? 36347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (strcmp(name, ifname)) { 36447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti continue; 36547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 36647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 36747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Put the colons back into the address. 36847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti for (i = 0, j = 0; i < 32; i++, j++) { 36947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[j] = rawaddrstr[i]; 37047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (i % 4 == 3) { 37147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[++j] = ':'; 37247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 37347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 37447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[j - 1] = '\0'; 37547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 37647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Don't delete the link-local address as well, or it will disable IPv6 37747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // on the interface. 37847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (strncmp(addrstr, "fe80:", 5) == 0) { 37947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti continue; 38047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 38147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 38247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = ifc_del_address(ifname, addrstr, prefixlen); 38347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret) { 38401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Deleting address %s/%d on %s: %s", addrstr, prefixlen, ifname, 38547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti strerror(-ret)); 38647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti lasterror = ret; 38747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 38847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 38947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 39047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti fclose(f); 39147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return lasterror; 39247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 39347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 39447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 39547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears IPv4 addresses on the specified interface. 39647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 39747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittivoid ifc_clear_ipv4_addresses(const char *name) { 39847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti unsigned count, addr; 39947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_init(); 40047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { 40147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ifc_get_addr(name, &addr) < 0) 40247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti break; 40347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (addr) 40447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_set_addr(name, 0); 40547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 40647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_close(); 40747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 40847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 40947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 41047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears all IP addresses on the specified interface. 41147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 41247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_clear_addresses(const char *name) { 41347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_clear_ipv4_addresses(name); 41447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_clear_ipv6_addresses(name); 41547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 41647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 417c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczakint ifc_set_hwaddr(const char *name, const void *ptr) 418c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak{ 419c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak int r; 420c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak struct ifreq ifr; 421c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak ifc_init_ifr(name, &ifr); 422c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak 423c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; 424c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak memcpy(&ifr.ifr_hwaddr.sa_data, ptr, ETH_ALEN); 425c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak return ioctl(ifc_ctl_sock, SIOCSIFHWADDR, &ifr); 426c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak} 427c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak 4286f49d5f266dffee103a3af07a7f6266f405d2924Jake Hambyint ifc_set_mask(const char *name, in_addr_t mask) 4296f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby{ 4306f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby struct ifreq ifr; 431b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 4326f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 4336f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby ifc_init_ifr(name, &ifr); 4346f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby init_sockaddr_in(&ifr.ifr_addr, mask); 4356f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 436b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); 437b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_set_mask(%s, xx) = %d", name, ret); 438b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 4396f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby} 4406f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 44109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ifc_set_prefixLength(const char *name, int prefixLength) 442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 44409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt // TODO - support ipv6 44509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefixLength > 32 || prefixLength < 0) return -1; 446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 44709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt in_addr_t mask = prefixLengthToIpv4Netmask(prefixLength); 448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&ifr.ifr_addr, mask); 4507d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); 452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4549092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidtint ifc_get_addr(const char *name, in_addr_t *addr) 4559092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt{ 4569092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt struct ifreq ifr; 4579092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt int ret = 0; 4589092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 4599092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ifc_init_ifr(name, &ifr); 4609092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (addr != NULL) { 4619092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr); 4629092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (ret < 0) { 4639092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt *addr = 0; 4649092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } else { 4659092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; 4669092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 4679092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 4689092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt return ret; 4699092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt} 4709092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 47109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags) 472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (addr != NULL) { 477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr) < 0) { 478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *addr = 0; 479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; 481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 4837d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 48409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefixLength != NULL) { 485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) { 48609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt *prefixLength = 0; 487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 4886ee3ecc03a7cf9118e6a0b2577f15c76244bc408Chris Dearman *prefixLength = ipv4NetmaskToPrefixLength( 48909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr); 490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (flags != NULL) { 494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) { 495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *flags = 0; 496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *flags = ifr.ifr_flags; 498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 504021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_ipv4_route(int action, const char *ifname, struct in_addr dst, int prefix_length, 5058984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in_addr gw) 506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct rtentry rt; 508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result; 5098984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_addr_t netmask; 510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&rt, 0, sizeof(rt)); 5128984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_dst.sa_family = AF_INET; 5148984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_dev = (void*) ifname; 5158984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 51609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt netmask = prefixLengthToIpv4Netmask(prefix_length); 5178984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_genmask, netmask); 5188984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_dst, dst.s_addr); 5198984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags = RTF_UP; 5208984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5218984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (prefix_length == 32) { 5228984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags |= RTF_HOST; 5238984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5248984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5258984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (gw.s_addr != 0) { 5268984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags |= RTF_GATEWAY; 5278984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_gateway, gw.s_addr); 5288984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5298984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 5318984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock < 0) { 5338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -errno; 5348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5358984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 536021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt result = ioctl(ifc_ctl_sock, action, &rt); 5378984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (result < 0) { 5388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (errno == EEXIST) { 5398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = 0; 5408984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else { 5418984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = -errno; 5428984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 548b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* deprecated - v4 only */ 5498984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikint ifc_create_default_route(const char *name, in_addr_t gw) 5508984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 5518984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in_addr in_dst, in_gw; 5528984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5538984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_dst.s_addr = 0; 5548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_gw.s_addr = gw; 5558984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 556b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 0, in_gw); 557b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_create_default_route(%s, %d) = %d", name, gw, ret); 558b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 559b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 560b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 561b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* deprecated v4-only */ 562b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_add_host_route(const char *name, in_addr_t dst) 563b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 564b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt struct in_addr in_dst, in_gw; 565b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 566b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt in_dst.s_addr = dst; 567b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt in_gw.s_addr = 0; 568b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 569b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 32, in_gw); 5708984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 5718984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 572feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwoodint ifc_enable(const char *ifname) 573feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood{ 574feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood int result; 575feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood 576feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood ifc_init(); 577feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood result = ifc_up(ifname); 578feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood ifc_close(); 579feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood return result; 580feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood} 581feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood 582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_disable(const char *ifname) 583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 5849092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt unsigned addr, count; 585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result; 586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project result = ifc_down(ifname); 5899092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_set_addr(ifname, 0); 5919092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { 5929092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (ifc_get_addr(ifname, &addr) < 0) 5939092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt break; 5949092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (addr) 5959092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ifc_set_addr(ifname, 0); 5969092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 5979092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 602979203ee34084327bf4f20ad1f878450de94826eWink Savilleint ifc_reset_connections(const char *ifname, const int reset_mask) 603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_ANDROID_OS 6056cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti int result, success; 606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t myaddr; 607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 6086cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti struct in6_ifreq ifr6; 609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 610979203ee34084327bf4f20ad1f878450de94826eWink Saville if (reset_mask & RESET_IPV4_ADDRESSES) { 611979203ee34084327bf4f20ad1f878450de94826eWink Saville /* IPv4. Clear connections on the IP address. */ 612979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init(); 613979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_get_info(ifname, &myaddr, NULL, NULL); 614979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init_ifr(ifname, &ifr); 615979203ee34084327bf4f20ad1f878450de94826eWink Saville init_sockaddr_in(&ifr.ifr_addr, myaddr); 616979203ee34084327bf4f20ad1f878450de94826eWink Saville result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); 617979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_close(); 618979203ee34084327bf4f20ad1f878450de94826eWink Saville } else { 619979203ee34084327bf4f20ad1f878450de94826eWink Saville result = 0; 620979203ee34084327bf4f20ad1f878450de94826eWink Saville } 6217d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 622979203ee34084327bf4f20ad1f878450de94826eWink Saville if (reset_mask & RESET_IPV6_ADDRESSES) { 623979203ee34084327bf4f20ad1f878450de94826eWink Saville /* 624979203ee34084327bf4f20ad1f878450de94826eWink Saville * IPv6. On Linux, when an interface goes down it loses all its IPv6 625979203ee34084327bf4f20ad1f878450de94826eWink Saville * addresses, so we don't know which connections belonged to that interface 626979203ee34084327bf4f20ad1f878450de94826eWink Saville * So we clear all unused IPv6 connections on the device by specifying an 627979203ee34084327bf4f20ad1f878450de94826eWink Saville * empty IPv6 address. 628979203ee34084327bf4f20ad1f878450de94826eWink Saville */ 629979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init6(); 630979203ee34084327bf4f20ad1f878450de94826eWink Saville // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets. 631979203ee34084327bf4f20ad1f878450de94826eWink Saville memset(&ifr6, 0, sizeof(ifr6)); 632979203ee34084327bf4f20ad1f878450de94826eWink Saville success = ioctl(ifc_ctl_sock6, SIOCKILLADDR, &ifr6); 633979203ee34084327bf4f20ad1f878450de94826eWink Saville if (result == 0) { 634979203ee34084327bf4f20ad1f878450de94826eWink Saville result = success; 635979203ee34084327bf4f20ad1f878450de94826eWink Saville } 636979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_close6(); 6376cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti } 6386cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti 639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Remove the routes associated with the named interface. 647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_remove_host_routes(const char *name) 649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char ifname[64]; 651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t dest, gway, mask; 652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int flags, refcnt, use, metric, mtu, win, irtt; 653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct rtentry rt; 654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FILE *fp; 655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct in_addr addr; 656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fp = fopen("/proc/net/route", "r"); 658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fp == NULL) 659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Skip the header line */ 661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fscanf(fp, "%*[^\n]\n") < 0) { 662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fclose(fp); 663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (;;) { 667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n", 668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifname, &dest, &gway, &flags, &refcnt, &use, &metric, &mask, 669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project &mtu, &win, &irtt); 670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (nread != 11) { 671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if ((flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST) 674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project || strcmp(ifname, name) != 0) { 675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&rt, 0, sizeof(rt)); 678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_dev = (void *)name; 679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&rt.rt_dst, dest); 680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&rt.rt_gateway, gway); 681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&rt.rt_genmask, mask); 682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project addr.s_addr = dest; 683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ioctl(ifc_ctl_sock, SIOCDELRT, &rt) < 0) { 6848d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("failed to remove route for %s to %s: %s", 685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifname, inet_ntoa(addr), strerror(errno)); 686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fclose(fp); 689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 694b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * Return the address of the default gateway 695b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * 696b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * TODO: factor out common code from this and remove_host_routes() 697b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * so that we only scan /proc/net/route in one place. 698b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * 699b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED 700b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */ 701b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_get_default_route(const char *ifname) 702b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 703b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt char name[64]; 704b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt in_addr_t dest, gway, mask; 705b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int flags, refcnt, use, metric, mtu, win, irtt; 706b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int result; 707b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt FILE *fp; 708b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 709b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt fp = fopen("/proc/net/route", "r"); 710b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (fp == NULL) 711b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return 0; 712b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt /* Skip the header line */ 713b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (fscanf(fp, "%*[^\n]\n") < 0) { 714b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt fclose(fp); 715b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return 0; 716b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt } 717b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_init(); 718b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt result = 0; 719b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt for (;;) { 720b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n", 721b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt name, &dest, &gway, &flags, &refcnt, &use, &metric, &mask, 722b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt &mtu, &win, &irtt); 723b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (nread != 11) { 724b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt break; 725b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt } 726b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if ((flags & (RTF_UP|RTF_GATEWAY)) == (RTF_UP|RTF_GATEWAY) 727b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt && dest == 0 728b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt && strcmp(ifname, name) == 0) { 729b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt result = gway; 730b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt break; 731b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt } 732b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt } 733b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt fclose(fp); 734b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_close(); 735b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return result; 736b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 737b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 738b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* 739b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * Sets the specified gateway as the default route for the named interface. 740b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED 741b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */ 742b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_set_default_route(const char *ifname, in_addr_t gateway) 743b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 744b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt struct in_addr addr; 745b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int result; 746b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 747b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_init(); 748b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt addr.s_addr = gateway; 749b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if ((result = ifc_create_default_route(ifname, gateway)) < 0) { 7508d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("failed to add %s as default route for %s: %s", 751b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt inet_ntoa(addr), ifname, strerror(errno)); 752b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt } 753b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_close(); 754b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return result; 755b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 756b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 757b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* 758dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Removes the default route for the named interface. 759dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_remove_default_route(const char *ifname) 761dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 762dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct rtentry rt; 763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result; 764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 765dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 766dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&rt, 0, sizeof(rt)); 767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_dev = (void *)ifname; 768dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_flags = RTF_UP|RTF_GATEWAY; 769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&rt.rt_dst, 0); 770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if ((result = ioctl(ifc_ctl_sock, SIOCDELRT, &rt)) < 0) { 7718d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("failed to remove default route for %s: %s", ifname, strerror(errno)); 772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint 778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectifc_configure(const char *ifname, 779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t address, 78009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt uint32_t prefixLength, 781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t gateway, 782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t dns1, 783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t dns2) { 784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char dns_prop_name[PROPERTY_KEY_MAX]; 786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_up(ifname)) { 790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to turn on interface %s: %s\n", ifname, strerror(errno)); 791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_set_addr(ifname, address)) { 795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to set ipaddr %s: %s\n", ipaddr_to_string(address), strerror(errno)); 796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 79909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (ifc_set_prefixLength(ifname, prefixLength)) { 80009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt printerr("failed to set prefixLength %d: %s\n", prefixLength, strerror(errno)); 801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_create_default_route(ifname, gateway)) { 805dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to set default route %s: %s\n", ipaddr_to_string(gateway), strerror(errno)); 806dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 811dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 812c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", ifname); 813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : ""); 814c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname); 815dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : ""); 816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 817dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 8198984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 820021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_ipv6_route(int action, const char *ifname, struct in6_addr dst, int prefix_length, 8218984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in6_addr gw) 8228984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 8238984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in6_rtmsg rtmsg; 8248984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik int result; 8258984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik int ifindex; 8268984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8278984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memset(&rtmsg, 0, sizeof(rtmsg)); 8288984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8298984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifindex = if_nametoindex(ifname); 8308984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifindex == 0) { 8318984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("if_nametoindex() failed: interface %s\n", ifname); 8328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -ENXIO; 8338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8358984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_ifindex = ifindex; 8368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_dst = dst; 8378984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_dst_len = prefix_length; 8388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_flags = RTF_UP; 8398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8408984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (prefix_length == 128) { 8418984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_flags |= RTF_HOST; 8428984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8438984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8448984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (memcmp(&gw, &in6addr_any, sizeof(in6addr_any))) { 8458984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_flags |= RTF_GATEWAY; 8468984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_gateway = gw; 8478984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8488984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8498984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_init6(); 8508984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8518984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 < 0) { 8528984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -errno; 8538984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 855021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt result = ioctl(ifc_ctl_sock6, action, &rtmsg); 8568984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (result < 0) { 8578984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (errno == EEXIST) { 8588984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = 0; 8598984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else { 8608984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = -errno; 8618984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8628984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8638984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_close6(); 8648984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return result; 8658984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 8668984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 867021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_route(int action, const char *ifname, const char *dst, int prefix_length, 868021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt const char *gw) 8698984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 8708984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik int ret = 0; 8718984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct sockaddr_in ipv4_dst, ipv4_gw; 8728984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct sockaddr_in6 ipv6_dst, ipv6_gw; 8738984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct addrinfo hints, *addr_ai, *gw_ai; 8748984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8758984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memset(&hints, 0, sizeof(hints)); 8768984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 8778984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik hints.ai_flags = AI_NUMERICHOST; 8788984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8798984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ret = getaddrinfo(dst, NULL, &hints, &addr_ai); 8808984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8818984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ret != 0) { 8828984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("getaddrinfo failed: invalid address %s\n", dst); 8838984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -EINVAL; 8848984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8858984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 886021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt if (gw == NULL || (strlen(gw) == 0)) { 8878984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (addr_ai->ai_family == AF_INET6) { 8888984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik gw = "::"; 8898984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else if (addr_ai->ai_family == AF_INET) { 8908984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik gw = "0.0.0.0"; 8918984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8928984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8938984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 894021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt if (((addr_ai->ai_family == AF_INET6) && (prefix_length < 0 || prefix_length > 128)) || 895021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt ((addr_ai->ai_family == AF_INET) && (prefix_length < 0 || prefix_length > 32))) { 896021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt printerr("ifc_add_route: invalid prefix length"); 897021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt freeaddrinfo(addr_ai); 898021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt return -EINVAL; 899021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt } 900021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt 9018984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ret = getaddrinfo(gw, NULL, &hints, &gw_ai); 9028984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ret != 0) { 9038984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("getaddrinfo failed: invalid gateway %s\n", gw); 9048984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik freeaddrinfo(addr_ai); 9058984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -EINVAL; 9068984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 9078984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 9088984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (addr_ai->ai_family != gw_ai->ai_family) { 9098984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("ifc_add_route: different address families: %s and %s\n", dst, gw); 9108984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik freeaddrinfo(addr_ai); 9118984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik freeaddrinfo(gw_ai); 9128984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -EINVAL; 9138984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 9148984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 9158984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (addr_ai->ai_family == AF_INET6) { 9168984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memcpy(&ipv6_dst, addr_ai->ai_addr, sizeof(struct sockaddr_in6)); 9178984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memcpy(&ipv6_gw, gw_ai->ai_addr, sizeof(struct sockaddr_in6)); 918021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt ret = ifc_act_on_ipv6_route(action, ifname, ipv6_dst.sin6_addr, 919021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt prefix_length, ipv6_gw.sin6_addr); 9208984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else if (addr_ai->ai_family == AF_INET) { 9218984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memcpy(&ipv4_dst, addr_ai->ai_addr, sizeof(struct sockaddr_in)); 9228984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memcpy(&ipv4_gw, gw_ai->ai_addr, sizeof(struct sockaddr_in)); 923021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt ret = ifc_act_on_ipv4_route(action, ifname, ipv4_dst.sin_addr, 924021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt prefix_length, ipv4_gw.sin_addr); 9258984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else { 9268984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("ifc_add_route: getaddrinfo returned un supported address family %d\n", 9278984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik addr_ai->ai_family); 9288984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ret = -EAFNOSUPPORT; 9298984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 9308984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 9318984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik freeaddrinfo(addr_ai); 9328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik freeaddrinfo(gw_ai); 9338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return ret; 9348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 935021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt 936b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* 937b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED 938b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */ 939b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_add_ipv4_route(const char *ifname, struct in_addr dst, int prefix_length, 940b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt struct in_addr gw) 941b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 942b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int i =ifc_act_on_ipv4_route(SIOCADDRT, ifname, dst, prefix_length, gw); 9430c613613d757c544d6ec7e5678f49a631a99d72aWink Saville if (DBG) printerr("ifc_add_ipv4_route(%s, xx, %d, xx) = %d", ifname, prefix_length, i); 944b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return i; 945b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 946b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 947b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* 948b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED 949b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */ 950b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_add_ipv6_route(const char *ifname, struct in6_addr dst, int prefix_length, 951b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt struct in6_addr gw) 952b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 953b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ifc_act_on_ipv6_route(SIOCADDRT, ifname, dst, prefix_length, gw); 954b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 955b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 956021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_add_route(const char *ifname, const char *dst, int prefix_length, const char *gw) 957021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt{ 958b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int i = ifc_act_on_route(SIOCADDRT, ifname, dst, prefix_length, gw); 9590c613613d757c544d6ec7e5678f49a631a99d72aWink Saville if (DBG) printerr("ifc_add_route(%s, %s, %d, %s) = %d", ifname, dst, prefix_length, gw, i); 960b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return i; 961021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt} 962021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt 963021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_remove_route(const char *ifname, const char*dst, int prefix_length, const char *gw) 964021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt{ 965021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt return ifc_act_on_route(SIOCDELRT, ifname, dst, prefix_length, gw); 966021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt} 967